From 33a7b314e633424aa3402441f457f2ddb08fb5c3 Mon Sep 17 00:00:00 2001 From: lixulun Date: Thu, 16 Jul 2026 15:16:26 +0800 Subject: [PATCH] update --- .gitignore | 6 +- custom-file.el | 7 +- init.el | 70 +++++++- vendor/odin-mode/odin-mode.el | 311 ++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+), 7 deletions(-) create mode 100644 vendor/odin-mode/odin-mode.el diff --git a/.gitignore b/.gitignore index 24a1b63..2ad1ea1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,11 @@ *~ \#*\# .#* +.cache /elpa /eshell -/tree-sitter \ No newline at end of file +/tree-sitter +/projects +/projectile-bookmarks.eld +/bookmarks diff --git a/custom-file.el b/custom-file.el index 98c6e14..5e52744 100644 --- a/custom-file.el +++ b/custom-file.el @@ -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. diff --git a/init.el b/init.el index b04c251..9106a5c 100644 --- a/init.el +++ b/init.el @@ -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) diff --git a/vendor/odin-mode/odin-mode.el b/vendor/odin-mode/odin-mode.el new file mode 100644 index 0000000..8a769aa --- /dev/null +++ b/vendor/odin-mode/odin-mode.el @@ -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 *\\_")) + +(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