This commit is contained in:
2026-07-16 15:16:26 +08:00
parent d01d150f36
commit 33a7b314e6
4 changed files with 387 additions and 7 deletions
+4
View File
@@ -2,7 +2,11 @@
*~
\#*\#
.#*
.cache
/elpa
/eshell
/tree-sitter
/projects
/projectile-bookmarks.eld
/bookmarks
+5 -2
View File
@@ -8,8 +8,11 @@
default))
'(inhibit-startup-screen t)
'(package-selected-packages
'(ace-window dimmer dune dune-format elixir-mode gruber-darker-theme
neocaml ocamlformat use-package-treesit)))
'(ace-window cargo cargo-mode crystal-mode dimmer dune dune-format
elixir-mode flycheck-rust gleam-ts-mode go-mode
gruber-darker-theme neocaml neotree ocamlformat
projectile rust-mode treemacs use-package-treesit
yaml-mode)))
(custom-set-faces
;; custom-set-faces was added by Custom.
+66 -4
View File
@@ -13,7 +13,7 @@
;; handy settings
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-display-line-numbers-mode 1)
(global-display-line-numbers-mode 0)
(global-auto-revert-mode t)
(setq mac-command-modifier 'meta)
@@ -25,6 +25,7 @@
(global-unset-key (kbd "C-SPC"))
(global-set-key (kbd "M-SPC") 'set-mark-command)
(global-set-key (kbd "C-x C-b") 'bs-show)
(global-set-key (kbd "C-,") 'compile)
(windmove-default-keybindings 'meta)
@@ -36,10 +37,25 @@
(load custom-file)
;; end handy settings
;; backup settings
(setq backup-directory-alist `(("." . "~/.emacs.d/backups/")))
(setq version-control t) ; 开启多版本备份
(setq kept-old-versions 2) ; 保留最早的2个版本
(setq kept-new-versions 6) ; 保留最新的6个版本
(setq delete-old-versions t) ; 自动删除中间的多余版本
;; treesit
(setq treesit-language-source-alist
'((c3 "https://github.com/c3lang/tree-sitter-c3")))
;; org
(global-set-key (kbd "C-c c") 'org-capture)
(setq org-capture-templates
'(("d" "draft" entry
(file+headline "~/org/draft.org" "草稿本")
"* %? \n TIME: %U\n %i" :empty-lines 1)))
;; packages
(use-package use-package-treesit
:ensure t)
@@ -52,7 +68,7 @@
(use-package dimmer
:ensure t
:init
(setq dimmer-fraction 0.3) ; 调整变暗的程度(0.0 到 1.0,越大越暗,0.3 刚刚好)
(setq dimmer-fraction 0.3) ; 调整变暗的程度(0.0 到y 1.0,越大越暗,0.3 刚刚好)
:config
(dimmer-mode 1))
@@ -60,10 +76,56 @@
:ensure t
:bind ("M-o" . ace-window))
(use-package treemacs
:ensure t
:defer t
:bind
("C-x t" . treemacs) ; 依然沿用你习惯的 C-x t 来开关
:config
(setq treemacs-position 'left ; 放在左边
treemacs-width 30 ; 宽度为 30
treemacs-is-never-other-window t ; 用 C-x o 切换分屏时,光标会自动跳过侧边栏,非常舒服
treemacs-file-follow-mode 'always)) ; 右边看什么代码,左边目录就自动高亮到哪里
(use-package projectile
:ensure t
:init
(projectile-mode +1)
:bind-keymap
("C-c p" . projectile-command-map) ; 统一把 C-c p 作为所有项目操作的前缀
:config
(setq projectile-sort-order 'recentf) ; 优先展示最近打开过的小伙伴
(setq projectile-project-search-path '("~/workspace/" "~/code/")))
(use-package go-mode
:ensure t
:hook (go-mode . eglot-ensure) ; 进入 go-mode 自动启动 eglot
:config
;; 配置 eglot 在保存时自动格式化和整理导包
(add-hook 'before-save-hook
(lambda ()
(when (derived-mode-p 'go-mode)
;; 相当于 goimports 的效果
(eglot-code-actions nil nil "source.organizeImports" t)
;; 相当于 gofmt 的效果
(eglot-format-buffer)))))
(use-package crystal-mode
:ensure t
:init
(autoload 'crystal-mode "crystal-mode" "Major mode for crystal files" t)
(add-to-list 'auto-mode-alist '("\\.cr$" . crystal-mode))
(add-to-list 'interpreter-mode-alist '("crystal" . crystal-mode))(autoload 'crystal-mode "crystal-mode" "Major mode for crystal files" t)
(add-to-list 'auto-mode-alist '("\\.cr$" . crystal-mode))
(add-to-list 'interpreter-mode-alist '("crystal" . crystal-mode)))
(use-package gleam-ts-mode
:ensure t
:mode (rx ".gleam" eos))
;; vendor
(add-to-list 'load-path (expand-file-name "vendor/c3-ts-mode" user-emacs-directory))
(require 'c3-ts-mode)
(add-to-list 'load-path (expand-file-name "vendor/odin-mode" user-emacs-directory))
(require 'odin-mode)
+311
View File
@@ -0,0 +1,311 @@
;;; odin-mode.el --- A minor mode for odin
;; Author: Ethan Morgan
;; Keywords: odin, language, languages, mode
;; Package-Requires: ((emacs "24.1"))
;; Homepage: https://github.com/glassofethanol/odin-mode
;; This file is NOT part of GNU Emacs.
;;; Code:
(require 'cl-lib)
(require 'rx)
(require 'js)
(defgroup odin nil
"Odin mode"
:group 'languages)
;; `compilation-mode' configuration
(eval-after-load 'compile
'(add-to-list 'compilation-error-regexp-alist '("^\\(.*?\\)(\\([0-9]+\\):\\([0-9]+\\).*" 1 2 3)))
(defconst odin-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?\\ "\\" table)
;; additional symbols
(modify-syntax-entry ?' "\"" table)
(modify-syntax-entry ?` "\"" table)
(modify-syntax-entry ?: "." table)
(modify-syntax-entry ?+ "." table)
(modify-syntax-entry ?- "." table)
(modify-syntax-entry ?% "." table)
(modify-syntax-entry ?& "." table)
(modify-syntax-entry ?| "." table)
(modify-syntax-entry ?^ "." table)
(modify-syntax-entry ?! "." table)
(modify-syntax-entry ?$ "." table)
(modify-syntax-entry ?= "." table)
(modify-syntax-entry ?< "." table)
(modify-syntax-entry ?> "." table)
(modify-syntax-entry ?? "." table)
;; Need this for #directive regexes to work correctly
(modify-syntax-entry ?# "_" table)
;; Modify some syntax entries to allow nested block comments
(modify-syntax-entry ?/ ". 124b" table)
(modify-syntax-entry ?* ". 23n" table)
(modify-syntax-entry ?\n "> b" table)
(modify-syntax-entry ?\^m "> b" table)
table))
(defconst odin-builtins
'("len" "cap"
"typeid_of" "type_info_of"
"swizzle" "complex" "real" "imag" "quaternion" "conj"
"jmag" "kmag"
"min" "max" "abs" "clamp"
"expand_to_tuple"
"init_global_temporary_allocator"
"copy" "pop" "unordered_remove" "ordered_remove" "clear" "reserve"
"resize" "new" "new_clone" "free" "free_all" "delete" "make"
"clear_map" "reserve_map" "delete_key" "append_elem" "append_elems"
"append" "append_string" "clear_dynamic_array" "reserve_dynamic_array"
"resize_dynamic_array" "incl_elem" "incl_elems" "incl_bit_set"
"excl_elem" "excl_elems" "excl_bit_set" "incl" "excl" "card"
"assert" "panic" "unimplemented" "unreachable"))
(defconst odin-keywords
'("import" "foreign" "package"
"where" "when" "if" "else" "for" "switch" "in" "not_in" "do" "case"
"break" "continue" "fallthrough" "defer" "return" "proc"
"struct" "union" "enum" "bit_field" "bit_set" "map" "dynamic"
"auto_cast" "cast" "transmute" "distinct" "opaque"
"using" "inline" "no_inline"
"size_of" "align_of" "offset_of" "type_of"
"or_return" "or_else" "or_continue" "or_break"
"context"
;; "_"
;; Reserved
"macro" "const"))
(defconst odin-constants
'("nil" "true" "false"
"ODIN_OS" "ODIN_ARCH" "ODIN_ENDIAN" "ODIN_VENDOR"
"ODIN_VERSION" "ODIN_ROOT" "ODIN_DEBUG"))
(defconst odin-typenames
'("bool" "b8" "b16" "b32" "b64"
"int" "i8" "i16" "i32" "i64"
"i16le" "i32le" "i64le"
"i16be" "i32be" "i64be"
"i128" "u128"
"i128le" "u128le"
"i128be" "u128be"
"uint" "u8" "u16" "u32" "u64"
"u16le" "u32le" "u64le"
"u16be" "u32be" "u64be"
"f32" "f64"
"complex64" "complex128"
"quaternion128" "quaternion256"
"rune"
"string" "cstring"
"uintptr" "rawptr"
"typeid" "any"
"byte"))
(defconst odin-attributes
'("builtin"
"export"
"static"
"deferred_in" "deferred_none" "deferred_out"
"require_results"
"default_calling_convention" "link_name" "link_prefix"
"deprecated" "private" "thread_local"))
(defconst odin-proc-directives
'("#force_inline"
"#force_no_inline"
"#type")
"Directives that can appear before a proc declaration")
(defconst odin-directives
(append '("#align" "#packed"
"#any_int"
"#raw_union"
"#no_nil"
"#complete"
"#no_alias"
"#c_vararg"
"#assert"
"#file" "#line" "#location" "#procedure" "#caller_location"
"#load"
"#defined"
"#bounds_check" "#no_bounds_check"
"#partial") odin-proc-directives))
(defun odin-wrap-word-rx (s)
(concat "\\<" s "\\>"))
(defun odin-wrap-keyword-rx (s)
(concat "\\(?:\\S.\\_<\\|\\`\\)" s "\\_>"))
(defun odin-wrap-directive-rx (s)
(concat "\\_<" s "\\>"))
(defun odin-wrap-attribute-rx (s)
(concat "[[:space:]\n]*@[[:space:]\n]*(?[[:space:]\n]*" s "\\>"))
(defun odin-keywords-rx (keywords)
"build keyword regexp"
(odin-wrap-keyword-rx (regexp-opt keywords t)))
(defun odin-directives-rx (directives)
(odin-wrap-directive-rx (regexp-opt directives t)))
(defun odin-attributes-rx (attributes)
(odin-wrap-attribute-rx (regexp-opt attributes t)))
(defconst odin-identifier-rx "[[:word:][:multibyte:]_]+")
(defconst odin-hat-type-rx (rx (group (and "^" (1+ (any word "." "_"))))))
(defconst odin-dollar-type-rx (rx (group "$" (or (1+ (any word "_")) (opt "$")))))
(defconst odin-number-rx
(rx (and
symbol-start
(or (and (+ digit) (opt (and (any "eE") (opt (any "-+")) (+ digit))))
(and "0" (any "xX") (+ hex-digit)))
(opt (and (any "_" "A-Z" "a-z") (* (any "_" "A-Z" "a-z" "0-9"))))
symbol-end)))
(defconst odin-proc-rx (concat "\\(\\_<" odin-identifier-rx "\\_>\\)\\s *::\\s *\\(" (odin-directives-rx odin-proc-directives) "\\)?\\s *\\_<proc\\_>"))
(defconst odin-type-rx (concat "\\_<\\(" odin-identifier-rx "\\)\\s *::\\s *\\(?:struct\\|enum\\|union\\|distinct\\)\\s *\\_>"))
(defconst odin-font-lock-defaults
`(
;; Types
(,odin-hat-type-rx 1 font-lock-type-face)
(,odin-dollar-type-rx 1 font-lock-type-face)
(,(odin-keywords-rx odin-typenames) 1 font-lock-type-face)
(,odin-type-rx 1 font-lock-type-face)
;; Hash directives
(,(odin-directives-rx odin-directives) 1 font-lock-preprocessor-face)
;; At directives
(,(odin-attributes-rx odin-attributes) 1 font-lock-preprocessor-face)
;; Keywords
(,(odin-keywords-rx odin-keywords) 1 font-lock-keyword-face)
;; single quote characters
("'\\(\\\\.\\|[^']\\)'" . font-lock-constant-face)
;; Variables
(,(odin-keywords-rx odin-builtins) 1 font-lock-builtin-face)
;; Constants
(,(odin-keywords-rx odin-constants) 1 font-lock-constant-face)
;; Strings
;; ("\\\".*\\\"" . font-lock-string-face)
;; Numbers
(,(odin-wrap-word-rx odin-number-rx) . font-lock-constant-face)
;; Procedures
(,odin-proc-rx 1 font-lock-function-name-face)
("---" . font-lock-constant-face)
("\\.\\.<" . font-lock-constant-face)
("\\.\\." . font-lock-constant-face)
))
;; add setq-local for older emacs versions
(unless (fboundp 'setq-local)
(defmacro setq-local (var val)
`(set (make-local-variable ',var) ,val)))
(defconst odin--defun-rx "\(.*\).*\{")
(defmacro odin-paren-level ()
`(car (syntax-ppss)))
(defun odin-line-is-defun ()
"return t if current line begins a procedure"
(interactive)
(save-excursion
(beginning-of-line)
(let (found)
(while (and (not (eolp)) (not found))
(if (looking-at odin--defun-rx)
(setq found t)
(forward-char 1)))
found)))
(defun odin-beginning-of-defun (&optional count)
"Go to line on which current function starts."
(interactive)
(let ((orig-level (odin-paren-level)))
(while (and
(not (odin-line-is-defun))
(not (bobp))
(> orig-level 0))
(setq orig-level (odin-paren-level))
(while (>= (odin-paren-level) orig-level)
(skip-chars-backward "^{")
(backward-char))))
(if (odin-line-is-defun)
(beginning-of-line)))
(defun odin-end-of-defun ()
"Go to line on which current function ends."
(interactive)
(let ((orig-level (odin-paren-level)))
(when (> orig-level 0)
(odin-beginning-of-defun)
(end-of-line)
(setq orig-level (odin-paren-level))
(skip-chars-forward "^}")
(while (>= (odin-paren-level) orig-level)
(skip-chars-forward "^}")
(forward-char)))))
(defalias 'odin-parent-mode
(if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
;;;###autoload
(define-derived-mode odin-mode odin-parent-mode "Odin"
:syntax-table odin-mode-syntax-table
:group 'odin
(setq bidi-paragraph-direction 'left-to-right)
(setq-local require-final-newline mode-require-final-newline)
(setq-local parse-sexp-ignore-comments t)
(setq-local comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
(setq-local comment-start "//")
(setq-local comment-end "")
(setq-local indent-line-function 'js-indent-line)
(setq-local font-lock-defaults '(odin-font-lock-defaults))
(setq-local beginning-of-defun-function 'odin-beginning-of-defun)
(setq-local end-of-defun-function 'odin-end-of-defun)
(setq-local electric-indent-chars
(append "{}():;," electric-indent-chars))
(setq imenu-generic-expression
`(("type" ,(concat "^" odin-type-rx) 1)
("proc" ,(concat "^" odin-proc-rx) 1)))
(font-lock-ensure))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.odin\\'" . odin-mode))
(provide 'odin-mode)
;;; odin-mode.el ends here