M config/pkg-dev.el => config/pkg-dev.el +168 -1
@@ 1,6 1,9 @@
;;; pkg-dev.el --- Development tools and programming support -*- lexical-binding: t -*-
-;; Copyright (C) 2024 Cytrogen
+;; Copyright (C) 2026 Cytrogen
+
+;; Many package selections and configurations adapted from
+;; Steve Purcell's emacs.d: https://github.com/purcell/emacs.d
;; This file contains:
;; - Rainbow delimiters for code readability
@@ 31,8 34,172 @@
(setq show-paren-delay 0)
(setq show-paren-style 'parenthesis)
+;; JS/TS/JSON 缩进 2 格
+(setq js-indent-level 2)
+(setq typescript-ts-mode-indent-offset 2)
+
;; Development Utilities
;; Helper functions for programming
+;; Avy — 2-3 键跳转到屏幕任意位置
+(unless (package-installed-p 'avy)
+ (package-refresh-contents)
+ (package-install 'avy))
+(require 'avy)
+(setq avy-timeout-seconds 0.3)
+
+;; Multiple Cursors — 多光标编辑
+(unless (package-installed-p 'multiple-cursors)
+ (package-install 'multiple-cursors))
+(require 'multiple-cursors)
+
+;; Symbol Overlay — 高亮/跳转当前符号所有出现
+(unless (package-installed-p 'symbol-overlay)
+ (package-install 'symbol-overlay))
+(require 'symbol-overlay)
+(add-hook 'prog-mode-hook #'symbol-overlay-mode)
+
+;; Move-dup — 移动/复制行
+(unless (package-installed-p 'move-dup)
+ (package-install 'move-dup))
+(require 'move-dup)
+(global-move-dup-mode 1)
+(add-hook 'org-mode-hook (lambda () (move-dup-mode -1)))
+
+;; Whole-line-or-region — 无选区时 C-w/M-w 操作整行
+(unless (package-installed-p 'whole-line-or-region)
+ (package-install 'whole-line-or-region))
+(require 'whole-line-or-region)
+(whole-line-or-region-global-mode 1)
+
+;; Whitespace-cleanup-mode — 保存时只清理改过的行的空白
+(unless (package-installed-p 'whitespace-cleanup-mode)
+ (package-install 'whitespace-cleanup-mode))
+(require 'whitespace-cleanup-mode)
+(global-whitespace-cleanup-mode 1)
+
+;; Highlight-escape-sequences — 代码中转义序列高亮
+(unless (package-installed-p 'highlight-escape-sequences)
+ (package-install 'highlight-escape-sequences))
+(require 'highlight-escape-sequences)
+(add-hook 'prog-mode-hook 'hes-mode)
+
+;; Flymake(内置)— 实时语法检查
+(add-hook 'prog-mode-hook 'flymake-mode)
+
+;; 行号(仅编程模式)
+(add-hook 'prog-mode-hook 'display-line-numbers-mode)
+
+;; 代码中 URL 可点击
+(add-hook 'prog-mode-hook 'goto-address-prog-mode)
+
+;; 注释拼写检查(需系统安装 aspell 或 hunspell)
+(add-hook 'prog-mode-hook 'flyspell-prog-mode)
+
+;; Eat — 现代终端模拟器
+(unless (package-installed-p 'eat)
+ (package-install 'eat))
+
+(with-eval-after-load 'eat
+ ;; 关闭闪烁文本,减少视觉干扰
+ (setq eat-enable-blinking-text nil)
+ ;; 增大回滚缓冲区(默认 131072),方便查看长输出
+ (setq eat-term-scrollback-size (* 128 1024))
+
+ ;; Semi-char 模式下用 C-c 前缀滚动回看(不会被 zsh 拦截)
+ (define-key eat-semi-char-mode-map (kbd "C-c C-p") #'scroll-down-command)
+ (define-key eat-semi-char-mode-map (kbd "C-c C-n") #'scroll-up-command)
+
+ ;; ANSI 调色板适配 darcula 主题 (bg #2B2B2B)
+ (custom-set-faces
+ '(eat-term-color-0 ((t (:foreground "#1e1e1e" :background "#1e1e1e")))) ; black
+ '(eat-term-color-1 ((t (:foreground "#ff6b68" :background "#ff6b68")))) ; red
+ '(eat-term-color-2 ((t (:foreground "#a8c023" :background "#a8c023")))) ; green
+ '(eat-term-color-3 ((t (:foreground "#d6bf55" :background "#d6bf55")))) ; yellow
+ '(eat-term-color-4 ((t (:foreground "#6a76db" :background "#6a76db")))) ; blue
+ '(eat-term-color-5 ((t (:foreground "#b877db" :background "#b877db")))) ; magenta
+ '(eat-term-color-6 ((t (:foreground "#56b6c2" :background "#56b6c2")))) ; cyan
+ '(eat-term-color-7 ((t (:foreground "#a9b7c6" :background "#a9b7c6")))) ; white
+ '(eat-term-color-8 ((t (:foreground "#6c6c6c" :background "#6c6c6c")))) ; bright black
+ '(eat-term-color-9 ((t (:foreground "#ff8785" :background "#ff8785")))) ; bright red
+ '(eat-term-color-10 ((t (:foreground "#c0d868" :background "#c0d868")))) ; bright green
+ '(eat-term-color-11 ((t (:foreground "#ffe680" :background "#ffe680")))) ; bright yellow
+ '(eat-term-color-12 ((t (:foreground "#88aacc" :background "#88aacc")))) ; bright blue
+ '(eat-term-color-13 ((t (:foreground "#b89ad6" :background "#b89ad6")))) ; bright magenta
+ '(eat-term-color-14 ((t (:foreground "#6ed8c8" :background "#6ed8c8")))) ; bright cyan
+ '(eat-term-color-15 ((t (:foreground "#e8e8e8" :background "#e8e8e8")))))) ; bright white
+
+;; Restclient — 在 buffer 中测试 HTTP 请求
+(unless (package-installed-p 'restclient)
+ (package-install 'restclient))
+
+;; Rainbow-mode — CSS/Hex 颜色值直接显示对应颜色
+(unless (package-installed-p 'rainbow-mode)
+ (package-install 'rainbow-mode))
+(add-hook 'css-mode-hook 'rainbow-mode)
+(add-hook 'html-mode-hook 'rainbow-mode)
+(add-hook 'emacs-lisp-mode-hook 'rainbow-mode)
+
+;; Origami — 代码折叠
+(unless (package-installed-p 'origami)
+ (package-install 'origami))
+(add-hook 'prog-mode-hook 'origami-mode)
+
+;; Regex-tool — 交互式正则表达式测试
+(unless (package-installed-p 'regex-tool)
+ (package-install 'regex-tool))
+
+;; Eldoc — 函数签名/文档自动提示(minibuffer 多行显示)
+(setq eldoc-echo-area-use-multiline-p t)
+
+;; Eglot(内置)— LSP 支持(JS/TS/Python/CSS/HTML)
+;; 前置: pnpm add -g typescript-language-server typescript
+;; 前置: pnpm add -g vscode-langservers-extracted
+;; 前置: uv tool install python-lsp-server
+(with-eval-after-load 'eglot
+ (setq eglot-autoshutdown t))
+
+(defvar my/eglot-server-programs
+ '((js-mode . "typescript-language-server")
+ (js-ts-mode . "typescript-language-server")
+ (typescript-ts-mode . "typescript-language-server")
+ (tsx-ts-mode . "typescript-language-server")
+ (python-mode . "pylsp")
+ (python-ts-mode . "pylsp")
+ (css-mode . "vscode-css-language-server")
+ (css-ts-mode . "vscode-css-language-server")
+ (html-mode . "vscode-html-language-server")
+ (html-ts-mode . "vscode-html-language-server"))
+ "模式与对应 LSP 服务器可执行文件的映射.")
+
+(defun my/eglot-ensure-if-server ()
+ "只在对应 LSP 服务器存在时启用 eglot."
+ (when-let* ((server (alist-get major-mode my/eglot-server-programs)))
+ (when (executable-find server)
+ (eglot-ensure))))
+
+(dolist (entry my/eglot-server-programs)
+ (add-hook (intern (concat (symbol-name (car entry)) "-hook"))
+ #'my/eglot-ensure-if-server))
+
+(unless (package-installed-p 'consult-eglot)
+ (package-install 'consult-eglot))
+
+;; Tree-sitter(内置)— 语法树精确高亮
+;; 安装语法: M-x treesit-install-language-grammar RET javascript/typescript/python/...
+(setq treesit-font-lock-level 4)
+
+(defvar my/treesit-mode-remap
+ '((javascript-mode . (js-ts-mode . javascript))
+ (js-json-mode . (json-ts-mode . json))
+ (python-mode . (python-ts-mode . python))
+ (css-mode . (css-ts-mode . css)))
+ "Tree-sitter 模式映射: (旧模式 . (新模式 . 语言)).")
+
+(setq major-mode-remap-alist
+ (cl-loop for (old-mode . (new-mode . lang)) in my/treesit-mode-remap
+ when (treesit-language-available-p lang)
+ collect (cons old-mode new-mode)))
+
(provide 'pkg-dev)
;;; pkg-dev.el ends here=
\ No newline at end of file