Last active
August 18, 2024 17:12
-
-
Save include-yy/e70dcbfc1a80403814d0b7a7357971d9 to your computer and use it in GitHub Desktop.
include-yy's emacs config file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; init.el --- include-yy's emacs config -*- lexical-binding:t;no-byte-compile:t; -*- | |
;; Copyright (C) 2023 include-yy <yy@egh0bww1.com> | |
;; Author: include-yy <yy@egh0bww1.com> | |
;; Created: 17 Jun 2023 | |
;; Version: 0.1 | |
;; Keywords: config | |
;; URL: https://gist.github.com/include-yy/e70dcbfc1a80403814d0b7a7357971d9 | |
;; Everyone is permitted to copy and distribute verbatim or modified | |
;; copies of this license document, and changing it is allowed as long | |
;; as the name is changed. | |
;; DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
;; TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
;; 0. You just DO WHAT THE FUCK YOU WANT TO. | |
;;; Commentary: | |
;; 建议创建 early-init.el 并添加如下代码: | |
;; ;; -*- lexical-binding: t; -*- | |
;; (setopt package-user-dir | |
;; (expand-file-name | |
;; (format "elpa-%s" | |
;; emacs-major-version) | |
;; user-emacs-directory)) | |
;; 请将本文件放在 ~/.emacs.d 目录,并删除可能存在的 ~/.emacs 文件 | |
;; ;;@1 基础设置, ;;@2 内置包的设置, ;;@3 外部包的设置 | |
;; ;;@4 一些零散的配置, ;;@5 详细的语言特定配置 | |
;; ;;@@NAME 某包的配置, ;;@@ 一些无名配置, ;;te 需要手动配置的项 | |
;; 一些可供参考的配置 | |
;; https://github.com/purcell/emacs.d | |
;; https://github.com/manateelazycat/lazycat-emacs | |
;; https://github.com/redguardtoo/emacs.d | |
;; https://github.com/seagle0128/.emacs.d | |
;; https://github.com/lynnux/.emacs.d | |
;;; Code: | |
;;@1 基础配置 | |
;;@@ emacs 版本必须大于等于 29.1 | |
(when (version< emacs-version "29.1") | |
(error "init.el: emacs version must >= 29.1")) | |
;;@@ 调整 emacs 的默认 GC 大小 | |
;; https://github.com/purcell/emacs.d/blob/master/init.el#L27 | |
(let ((normal-gc-cons-threshold (* 20 1024 1024)) | |
(init-gc-cons-threshold (* 128 1024 1024))) | |
(setq gc-cons-threshold init-gc-cons-threshold) | |
(add-hook 'emacs-startup-hook | |
(lambda () (setq gc-cons-threshold normal-gc-cons-threshold)))) | |
;;@@ 定义用户的自定义 group,可以保存一些特定于机器的选项 | |
;; 或者其他的一些选项。配置文件中出现的 option 默认属于该组,无需指定 `:group' | |
(defgroup yy nil | |
"配置文件中的选项,可用来保存一些特定于机器的路径或选项" | |
:group 'emacs) | |
(defmacro yy/defcustom (symbol value doc &rest args) | |
"保证使用 `yy/defcustom' 定义的 option 位于 `yy' 组内" | |
(declare (doc-string 3) (debug (name body)) | |
(indent defun)) | |
(let ((args (if (plist-get args :group) args | |
(cons :group (cons ''yy args))))) | |
`(defcustom ,symbol ,value ,doc ,@args))) | |
(defun yy/add-to-group (sym) | |
"添加某一 option 到 yy group 中,方便显示" | |
(custom-add-to-group 'yy sym 'custom-variable)) | |
(defun yy/customize () | |
(interactive) | |
(customize-group 'yy)) | |
;;@@ 额外的配置文件 `yy-local.el' | |
(when (file-exists-p "~/.emacs.d/yy-local.el") | |
(load "~/.emacs.d/yy-local.el")) | |
;;@@ 设置 custom.el 的位置 | |
(setopt custom-file "~/.emacs.d/custom.el") | |
(load custom-file t) | |
;;@@ 查看配置中需要手动配置的部分 | |
(defun yy/occur-te () | |
"使用 `occur' 列出配置文件中需要手动配置的位置 ;;te" | |
(interactive) | |
(with-current-buffer (get-file-buffer "~/.emacs.d/init.el") | |
(occur "^ *;;te"))) | |
;;@@ 设置 changelog file 相关的一些选项 | |
(setopt add-log-full-name "include-yy") | |
(setopt add-log-mailing-address "yy@egh0bww1.com") | |
(setopt add-log-time-zone-rule t) ; 使用 UTC+0 时间 | |
;;@@ 启动时不显示 GNU Emacs startup 页面 | |
(setopt inhibit-startup-screen t) | |
(setopt initial-scratch-message (format ";;Emacs %s" emacs-version)) | |
;;@@ 关闭 C-g, 边界移动命令响铃 | |
(setopt ring-bell-function 'ignore) | |
;;@@ 不使用对话框 | |
(setopt use-dialog-box nil) | |
;;@@ 基础补全设置 | |
;; 按下 TAB 时进行补全,可设置为 'complete | |
;; 使用补全框架则不用设置 | |
;; (setopt tab-always-indent 'complete) | |
;; 让 C-h f, C-h v 在选词阶段提供更多信息,更好看 | |
(setopt completions-detailed t) | |
;; Emacs 29 提供了许多不错的补全改进 | |
;; 但是,我们现在有超级好用的 vectico 了,不过加上也不费事 | |
;; https://www.scss.tcd.ie/~sulimanm/posts/default-emacs-completion.html | |
;; https://robbmann.io/posts/emacs-29-completions/ | |
(setopt completions-format 'one-column) ; 在补全 buffer 中单列显示候选词 | |
(setopt completions-header-format nil) ; 补全 buffer 中不显示汇总信息 | |
(setopt completions-max-height 20) ; 补全 buffer 限高为 20 行 | |
(setopt completion-auto-select nil) ; 触发补全时不移动焦点到补全 buffer | |
;; 也许可以考虑试试 Protesilaos Stavrou 的时尚小垃圾 -- mct.el | |
;; https://protesilaos.com/emacs/mct | |
;;@@ 总是使用 y-or-n-p,可以少打字 | |
;; 也可以设置 `use-short-answers' 为非空值 | |
;; (defalias 'yes-or-no-p 'y-or-n-p) | |
(setopt use-short-answers t) | |
;;@@ 关闭一些窗口元素 | |
(tool-bar-mode -1) ; 关闭工具栏 | |
(scroll-bar-mode -1) ; 关闭滚动条 | |
(menu-bar-mode -1) ; 关闭菜单栏 | |
(blink-cursor-mode -1) ; 光标不闪烁 | |
;;@@ backup 与 auto-save 设置 | |
;; 不让 Emacs 生成 backup file,也就是 ~ 结尾的临时文件 | |
(setopt make-backup-files nil) | |
;; 不进行 auto-save | |
(setopt auto-save-default nil) | |
;; 不创建 lock files | |
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Locks.html | |
(setopt create-lockfiles nil) | |
;;@@ 设置默认的 major-mode 为 `text-mode' | |
(setq-default major-mode 'text-mode) | |
;;@@ 从子进程读取输出时的最大单次 thunk 读取字节数量,设置为 1MB | |
;; (setq process-adaptive-read-buffering nil) | |
(setq read-process-output-max (* 1024 1024)) | |
;;@@ 运行 `run-lisp' 时使用的 Lisp 程序名 | |
;; sbcl 官网:http://www.sbcl.org/index.html | |
(setopt inferior-lisp-program "sbcl") | |
;;@@ 单次滚动设置为 1 行 | |
(setopt scroll-step 1) | |
(setopt scroll-conservatively 10000) | |
;;@@ 中文智能换行 | |
(setopt word-wrap-by-category t) | |
;;@@ 时间格式设置为 "C" | |
(setq system-time-locale "C") | |
;;@@ 添加一些全局绑定 | |
(bind-keys | |
;; 正则向前和向后搜索的快捷键 | |
;; 使用 consult 爽一点 | |
;;("C-c s" . isearch-forward-regexp) | |
;;("C-c r" . isearch-backward-regexp) | |
;; 不询问直接杀死 buffer | |
("C-x k" . kill-current-buffer) | |
;; 互换 C-w 和 M-w | |
("M-w" . kill-region) | |
("C-w" . kill-ring-save) | |
;; 防止误触 | |
("C-c <f12>" . save-buffers-kill-emacs) | |
;; 中文输入法下的处理,不用切换输入法了 | |
("C-x 【" . backward-page) | |
("C-x 】" . forward-page) | |
;; 日文输入法下的处理 | |
("C-x 「" . backward-page) | |
("C-x 」" . forward-page) | |
("M-x" . execute-extended-command) | |
("C-x b" . switch-to-buffer) | |
("M-w" . kill-region)) | |
;;@@ 倾向使用 utf-8 作为 buffer 默认编码 | |
(prefer-coding-system 'utf-8) | |
;;@@ 在关闭关联进程的 buffer 时不提示是否关闭 | |
(setq kill-buffer-query-functions | |
(remq 'process-kill-buffer-query-function | |
kill-buffer-query-functions)) | |
;;@@ 长行优化,以及一些显示效果优化 | |
;; https://emacs.stackexchange.com/questions/598/how-do-i-prevent-extremely-long-lines-making-emacs-slow | |
(setq-default bidi-display-reordering 'left-to-right) | |
(setq-default bidi-paragraph-direction 'left-to-right) | |
(setq-default bidi-inhibit-bpa t) | |
(setq-default cursor-in-non-selected-windows nil) | |
(setopt fast-but-imprecise-scrolling t) | |
;;@@ kill 时若与 kill-ring 内最后内容重复则不添加入 kill-ring | |
(setopt kill-do-not-save-duplicates t) | |
;;@@ 将大文件警告提升至大约 100MB | |
(setopt large-file-warning-threshold (* 100 1024 1024)) | |
;;@@ 禁止光标移动到 minibuffer 的 prompt | |
(setopt minibuffer-prompt-properties | |
'(read-only t cursor-intangible t face minibuffer-prompt)) | |
;;@@ 默认 80 的 fill-column | |
(setopt fill-column 80) | |
;;@@ 解锁一些被禁用的命令 | |
(put 'list-timers 'disabled nil) | |
(put 'set-goal-column 'disabled nil) | |
(put 'erase-buffer 'disabled nil) | |
(put 'downcase-region 'disabled nil) | |
(put 'upcase-region 'disabled nil) | |
(put 'narrow-to-region 'disabled nil) | |
(put 'narrow-to-page 'disabled nil) | |
;;@@ Windows 相关配置 | |
(when (eq system-type 'windows-nt) | |
;; 为 Windows 添加 Super 和 Hyper 按键 | |
;;(setq w32-pass-lwindow-to-system nil) | |
;;(setq w32-lwindow-modifier 'hyper) | |
;;(setq w32-pass-rwindow-to-system nil) | |
;;(setq w32-rwindow-modifier 'super) | |
(setq w32-apps-modifier 'hyper) | |
;; 默认的 4KB 管道 buffer 太小了点,给到 64KB | |
(setq w32-pipe-buffer-size (* 64 1024)) | |
;; 在 Windows 下删除文件时默认移动到垃圾箱/回收站 | |
(setopt delete-by-moving-to-trash t) | |
;; 在 Windows 上没必要搜索两遍 auto-mode-alist, | |
;; 因为 Windows 文件系统忽略大小写 | |
(setopt auto-mode-case-fold nil) | |
;; tooltip-mode 在 Windows 下似乎有点卡 | |
(tooltip-mode -1)) | |
;;@@ 在 Windows 下的 `grep', `find' 和 `xargs' 等命令行工具的位置 | |
;;te 需要 msys2,指定 msys2 的根目录位置 | |
;; 设定后执行 `when' 处的代码即可 | |
(yy/defcustom yy/w32-msys-root-path nil | |
"Windows 系统下的 msys2 /usr/bin 路径" | |
:type '(choice (const nil) | |
(string :tag "path"))) | |
(when (and (eq system-type 'windows-nt) | |
yy/w32-msys-root-path) | |
(mapc (lambda (v) | |
(let ((sym (car v)) | |
(val (cdr v))) | |
(set sym (file-name-concat | |
yy/w32-msys-root-path "usr/bin" val)))) | |
'((grep-program . "grep.exe") | |
(find-program . "find.exe") | |
(xargs-program . "xargs.exe") | |
(diff-command . "diff.exe")))) | |
;; 启动 MSYS2 UCRT64 SHELL 的函数 | |
(defun yy/ucrt-shell () | |
(interactive) | |
(if (not yy/w32-msys-root-path) | |
(user-error "Path of MSYS2 root is unknown") | |
(let* ((env (if (not current-prefix-arg) ; 使用 C-u 选择不同的 MSYS2 环境 | |
"-ucrt64" | |
(completing-read | |
"Select a MSYS2 environment" | |
'("-msys" "-ucrt64" | |
"-clang64" "-mingw64")))) | |
(shell (file-name-concat yy/w32-msys-root-path "msys2_shell.cmd")) | |
(args (list "-defterm" "-here" "-no-start" env "-i"))) | |
(dlet ((explicit-shell-file-name shell) | |
(explicit-msys2_shell.cmd-args args)) | |
(shell "*msys2-shell*"))))) | |
;;@@ Windows 下的编码设定 | |
;; 建议使用代码页 65001 | |
;;te Windows 10: region setting -> Language -> Administrative language settings | |
;; -> Change systel locale -> Beta: Use Unicode UTF-8 for worldwide language support | |
(when (eq system-type 'windows-nt) | |
(let* ((codepage (w32-get-console-codepage)) | |
(coding (pcase codepage | |
(65001 'utf-8-dos) | |
(936 'gbk-dos) | |
(_ nil)))) | |
(when coding | |
(setq process-coding-system-alist | |
`(("[pP][lL][iI][nN][kK]" . #1=(,coding . ,coding)) | |
("[cC][mM][dD][pP][rR][oO][xX][yY]" . #1#))) | |
(setq default-process-coding-system | |
`(,coding . ,coding))))) | |
;;@@ LINUX 额外的执行路径,(如果没有添加到 $PATH 的话) | |
;; 添加 ~/.local/bin 到 exe-path | |
(when (eq system-type 'gnu/linux) | |
(add-to-list 'exec-path (expand-file-name "~/.local/bin"))) | |
;;@@ 豆腐块消除计划 | |
;;te 字体设置,使 C-h h 可全部正常显示 | |
;; https://qiita.com/styzo/items/28d5d994a293fa704476 | |
(yy/defcustom yy/all-font-available nil | |
"是否集齐了可以显示 C-h h 中所有语言的字体" | |
:type 'boolean) | |
(when yy/all-font-available | |
(add-hook 'after-init-hook | |
(lambda () | |
(run-with-idle-timer | |
1 nil | |
'yy/all-font-init)))) | |
(defun yy/all-font-init () | |
(set-fontset-font t 'adlam (font-spec :family "Noto Sans Adlam")) | |
(set-fontset-font t 'ethiopic (font-spec :family "Noto Serif Ethiopic")) ;; amharic | |
(set-fontset-font t 'arabic (font-spec :family "Noto Sans Arabic")) | |
(set-fontset-font t 'balinese (font-spec :family "Noto Serif Balinese")) | |
(set-fontset-font t 'batak (font-spec :family "Noto Sans Batak")) | |
(set-fontset-font t 'bengali (font-spec :family "Nirmala UI")) | |
(set-fontset-font t 'brahmi (font-spec :family "Noto Sans Brahmi")) | |
(set-fontset-font t 'braille "Symbola") | |
(set-fontset-font t 'buginese (font-spec :family "Noto Sans Buginese")) | |
(set-fontset-font t 'burmese (font-spec :family "Noto Sans Myanmar")) | |
(set-fontset-font t 'cham (font-spec :family "Noto Sans Cham")) | |
(set-fontset-font t 'cherokee (font-spec :family "Noto Sans Cherokee")) | |
(set-fontset-font t 'coptic (font-spec :family "Noto Sans coptic")) | |
(set-fontset-font t 'canadian-aboriginal | |
(font-spec :family "Noto Sans Canadian Aboriginal")) ;; cree | |
(set-fontset-font t 'devanagari (font-spec :family "Nirmala UI")) | |
(set-fontset-font t 'egyptian (font-spec :family "Noto Sans Egyptian Hieroglyphs")) | |
(set-fontset-font t 'emoji (font-spec :family "Symbola")) | |
(set-fontset-font t 'georgian (font-spec :family "Noto Serif Georgian")) | |
(set-fontset-font t 'gothic (font-spec :family "Noto Sans Gothic")) | |
(set-fontset-font t 'grantha (font-spec :family "Noto Serif Grantha")) | |
(set-fontset-font t 'gujarati (font-spec :family "Nirmala UI")) | |
(set-fontset-font t 'gurmukhi (font-spec :family "Nirmala UI")) | |
(set-fontset-font t 'hanifi-rohingya (font-spec :family "Noto Sans Hanifi Rohingya")) | |
(set-fontset-font t 'hanunoo (font-spec :family "Noto Sans Hanunoo")) | |
(set-fontset-font t 'hebrew "Noto Sans Hebrew") | |
(set-fontset-font t 'javanese (font-spec :family "Noto Sans Javanese")) | |
(set-fontset-font t 'kaithi (font-spec :family "Noto Sans Kaithi")) | |
(set-fontset-font t 'kannada (font-spec :family "Noto Serif Kannada")) | |
(set-fontset-font t 'kharoshthi (font-spec :family "Noto Sans Kharoshthi")) | |
(set-fontset-font t 'khmer (font-spec :family "Noto Sans Khmer")) | |
(set-fontset-font t 'lao (font-spec :family "Noto Sans Lao")) | |
(set-fontset-font t 'lepcha (font-spec :family "Noto Sans Lepcha")) | |
(set-fontset-font t 'limbu (font-spec :family "Noto Sans Limbu")) | |
(set-fontset-font t 'makasar (font-spec :family "Noto Serif Makasar")) | |
(set-fontset-font t 'malayalam (font-spec :family "Noto Sans Malayalam")) | |
(set-fontset-font t 'thaana (font-spec :family "Noto Sans Thaana")) ;; Maldivian | |
(set-fontset-font t 'meetei-mayek (font-spec :family "Noto Sans Meetei Mayek")) | |
(set-fontset-font t 'mende-kikakui (font-spec :family "Noto Sans Mende Kikakui")) | |
(set-fontset-font t 'modi (font-spec :family "Noto Sans Modi")) | |
(set-fontset-font t 'mongolian (font-spec :family "Noto Sans Mongolian")) | |
(set-fontset-font t 'tai-tham (font-spec :family "Noto Sans Tai Tham")) ; Northern Thai | |
(set-fontset-font t 'oriya (font-spec :family "Noto Sans Oriya")) ;; odia | |
(set-fontset-font t 'rejang (font-spec :family "Noto Sans Rejang")) | |
(set-fontset-font t 'sharada (font-spec :family "Noto Sans Sharada")) | |
(set-fontset-font t 'siddham (font-spec :family "Noto Sans Siddham")) | |
(set-fontset-font t 'sinhala (font-spec :family "Noto Sans Sinhala")) | |
(set-fontset-font t 'sundanese (font-spec :family "Noto Sans Sundanese")) | |
(set-fontset-font t 'syloti-nagri (font-spec :family "Noto Sans Syloti Nagri")) | |
(set-fontset-font t 'tamil (font-spec :family "Noto Sans Tamil")) | |
(set-fontset-font t 'telugu (font-spec :family "Noto Sans Telugu")) | |
(set-fontset-font t 'tagalog (font-spec :family "Noto Sans Tagalog")) | |
(set-fontset-font t 'tagbanwa (font-spec :family "Noto Sans Tagbanwa")) | |
(set-fontset-font t 'tai-viet (font-spec :family "Noto Sans Tai Viet")) | |
(set-fontset-font t 'thai (font-spec :family "Noto Sans Thai")) | |
(set-fontset-font t 'tibetan (font-spec :family "Noto Serif Tibetan")) | |
(set-fontset-font t 'tirhuta (font-spec :family "Noto Sans Tirhuta")) | |
(set-fontset-font t 'wancho (font-spec :family "Noto Sans Wancho")) | |
(set-fontset-font t 'hangul (font-spec :family "Noto Serif KR"))) | |
;;@2 内置的 emacs 包 | |
;;@@PACKAGE | |
(use-package package | |
:config | |
;; 添加 melpa 源和 yyelpa 源 | |
;; 使 yyelpa 具有最大优先级 | |
(setopt package-archives | |
'(("melpa" . "https://melpa.org/packages/") | |
("nongnu" . "https://elpa.nongnu.org/nongnu/") | |
("gnu" . "https://elpa.gnu.org/packages/") | |
("yyelpa" . "https://elpa.egh0bww1.com/packages/"))) | |
(add-to-list 'package-unsigned-archives "yyelpa") | |
(setopt package-check-signature nil) | |
(setopt package-archive-priorities | |
'(("melpa" . 1) ("nongnu" . 5) | |
("gnu" . 10) ("yyelpa" . 100))) | |
(when (version< emacs-version "27.1") | |
(package-initialize))) | |
;;@@DIMINISH 放在最前面 | |
;; 可以用来取消某些 minor-mode 字符在 modeline 的显示 | |
(use-package diminish :ensure t :pin "gnu") | |
;;@@DISPLAY-LINE-NUMBERS 显示行号 | |
(setopt line-number-display-limit | |
large-file-warning-threshold) | |
;;(setq line-number-display-limit-width 1000) | |
(add-hook 'prog-mode-hook 'display-line-numbers-mode) | |
;;@@HL-LINE-MODE 高亮当前行 | |
(add-hook 'prog-mode-hook 'hl-line-mode) | |
;;@@ELEC-PAIR 括号匹配高亮 | |
(add-hook 'prog-mode-hook 'electric-pair-mode) | |
;;@@DELETE-SELECTION-MODE 在选中区域时输入内容将删除区域 | |
(delete-selection-mode t) | |
;;@@UNIQUIFY 路径名显示唯一化 | |
(setopt uniquify-buffer-name-style 'reverse | |
uniquify-separator " ← " | |
uniquify-ignore-buffers-re "^\\*") | |
;;@@ISEARCH “智能搜索” | |
(setopt isearch-allow-scroll t) | |
;;@@IBUFFER 高级 buffer 列表 | |
(use-package ibuffer | |
:bind ("C-x C-b" . yy/ibuffer) | |
:config | |
(defun yy/ibuffer () | |
(interactive) | |
(if (string= (buffer-name) "*Ibuffer*") | |
(ibuffer-update nil t) | |
(ibuffer))) | |
;; 不显示临时 BUFFER | |
;; 还是显示吧 | |
;;(setopt ibuffer-never-show-predicates '("^\\*")) | |
;; 在其他窗口中显示 ibuffer | |
(setopt ibuffer-use-other-window t) | |
;; 不显示为空的分组 | |
(setopt ibuffer-show-empty-filter-groups nil) | |
;; 不显示汇总信息 | |
(setopt ibuffer-display-summary nil) | |
;; 默认的 filter-group | |
(setopt ibuffer-saved-filter-groups | |
'(("default" | |
("PROJECT" | |
(name . "\\*<p>.+\\*")) | |
("emacs-src-el" | |
(and (file-extension . "el") | |
(directory . "share/emacs/.*/lisp"))) | |
("emacs-lisp" | |
(or (file-extension . "el") | |
(mode . emacs-lisp-mode))) | |
("common-lisp" | |
(or (file-extension . "lisp") | |
(mode . lisp-mode))) | |
("scheme/racket" | |
(or (mode . scheme-mode) | |
(file-extension . "scm"))) | |
("C/C++" | |
(or (mode . c-mode) | |
(mode . c++-mode) | |
(filename . ".+\\.\\(c\\|cc\\|cpp\\|h\\|hpp\\)"))) | |
("Python" | |
(or (mode . python-mode) | |
(mode . python-ts-mode) | |
(file-extension . "py"))) | |
("js/css/html" | |
(or (mode . js-mode) | |
(mode . js-ts-mode) | |
(mode . json-ts-mode) | |
(filename . ".+\\.\\(cjs\\|mjs\\|js\\|json\\|ts\\)") | |
(mode . html-mode) | |
(mode . css-mode) | |
(filename . ".+\\.wgsl") | |
(filename . ".+\\.html?") | |
(filename . ".+\\.css"))) | |
("Rust" | |
(or (mode . rust-ts-mode) | |
(file-extension . "rs"))) | |
("rescript" | |
(or (mode . rescript-mode) | |
(filename . ".+\\.resi?"))) | |
("ORG" | |
(or (mode . org-mode) | |
(file-extension . "org"))) | |
("DIRED" | |
(mode . dired-mode)) | |
("IMAGES" | |
(or (mode . image-mode) | |
(filename . ".+\\.\\(jpe?g\\|png\\|gif\\|webp\\|ppm\\|pgm\\|pbm\\)"))) | |
("TEXT" | |
(or (mode . text-mode) | |
(filename . ".+\\.txt"))) | |
("CONFIG" | |
(or (mode . conf-mode) | |
(filename . ".+\\.toml") | |
(filename . ".+\\.yaml"))) | |
("LOG" | |
(or (filename . "[cC][hH][aA][nN][gG][eE][lL][oO][gG]") | |
(mode . change-log-mode))) | |
("PROCESS" | |
(process)) | |
("TEMP" | |
(name . "\\*.*\\*"))))) | |
(defun yy/ibuffer-use-default-group () | |
(and (not ibuffer-filter-groups) ;; not use group | |
(assoc "default" ibuffer-saved-filter-groups) | |
(ibuffer-switch-to-saved-filter-groups "default"))) | |
(add-hook 'ibuffer-hook 'yy/ibuffer-use-default-group)) | |
;;@@DESKTOP 保存当前 emacs 状态 | |
(use-package desktop | |
;; 在 Windows 上有点太慢了,还是用 recentf 算了 | |
:disabled | |
:config | |
(desktop-save-mode 1)) | |
;;@@RECENTF 保留最近文件打开记录 | |
(use-package recentf | |
:init | |
;; 可在 `recentf-open-files' 中显示的最大文件数量 | |
(setopt recentf-max-menu-items 50) | |
;; recentf 保存的文件数量 | |
(setopt recentf-max-saved-items 2000) | |
;; 不进行保存文件的自动清理 | |
;;(setopt recentf-auto-cleanup 'never) | |
:config | |
(recentf-mode 1) | |
;; 启动时显示 recentf buffer | |
;;(setopt initial-buffer-choice 'recentf-open-files) | |
;; 每三小时保存一次最近文件列表 | |
(defvar yy/recentf-save-timer nil) | |
(unless yy/recentf-save-timer | |
(setq yy/recentf-save-timer | |
(run-at-time nil (* 2 60 60) 'recentf-save-list))) | |
(bind-key "C-c r" 'recentf-open)) | |
;;@@SAVEPLACE 关闭 buffer 时保存光标位置 | |
;; 和 recentf-mode 联动一下,可以保存最近打开文件在关闭时的 point 位置 | |
(save-place-mode 1) | |
;;@@WINNER 保留窗口配置记录,可回退和前进 | |
(use-package winner | |
:config | |
(winner-mode 1) | |
;; 给快捷键添加 repeat-mode 支持 | |
(defvar yy/winner-repear-map | |
(let ((map (make-sparse-keymap))) | |
(define-key map (kbd "<up>") 'winner-undo) | |
(define-key map (kbd "<down>") 'winner-redo) | |
map)) | |
(dolist (cmd '(winner-undo winner-redo)) | |
(put cmd 'repeat-map 'yy/winner-repear-map)) | |
:bind (("C-x <up>" . winner-undo) | |
("C-x <down>" . winner-redo))) | |
;;@@ORG org-mode 基础配置 | |
(use-package org | |
:bind (("C-c l" . org-store-link) | |
("C-c a" . org-agenda) | |
("C-c c" . org-capture)) | |
:config | |
(setopt org-tags-column 0) | |
(setopt org-startup-truncated nil) | |
(setopt org-image-actual-width 400) | |
(setopt org-element-cache-persistent nil) | |
(setopt org-export-dispatch-use-expert-ui t) | |
(add-hook 'org-mode-hook 'visual-line-mode) | |
) | |
;;@@CC-MODE C 系语言基础配置 | |
(use-package cc-mode | |
:config | |
(setq-default c-default-style | |
'((java-mode . "java") | |
(awk-mode . "awk") | |
(other . "linux"))) | |
(setq-default c-recognize-knr-p nil) | |
;;(setq c-basic-offset 4) | |
(setopt c-electric-pound-behavior '(alignleft))) | |
;;@@HIPPIE 方便的路径补全 | |
(use-package hippie-exp | |
:bind ("C-c TAB" . hippie-expand)) | |
;;@@NATIVE-COMP | |
;; https://misohena.jp/blog/2023-07-31-setup-emacs-29-1-for-windows.html | |
;;te 在 bin/ 下添加必要库 | |
;; 注意 bin/ 中 libgccjit-0.dll 存在以下依赖项: | |
;; 可使用 https://github.com/lucasg/Dependencies 获取 DLL 的依赖项 | |
;; system32/{advapi32.dll, kernel32.dll, MSVCRT.dll} | |
;; libgcc_s_seh-1.dll, libgmp-10.dll | |
;; libisl-23.dll, libmpc-3.dll, libmpfr-6.dll ; 注意这三个 | |
;; libwinpthread-1.dll, zlib1.dll, libzstd.dll | |
;; 随后,在 /lib/gcc/ 下添加以下内容:(一共 18 个) | |
;; mingw64/bin/ 中的 as.exe 和 ld.exe,它们依赖同目录下的 libzstd.dll 和 zlib1.dll | |
;; mingw64/lib 下的以下文件: | |
;; crtbegin.o, crtend.o, dllcrt2.o | |
;; lib{ advapi32.a, gcc_s.a, kernel32.a, mingw32.a | |
;; mingwex.a, moldname.a, msvcrt.a, pthread.a | |
;; shell32.a, user32.a} | |
;; mingw64/lib/gcc/x86_64-w64-mingw32/13.1.0 中的 libgcc.a | |
;; 忽略 native-comp 过程中的 warning | |
;; (setopt native-comp-async-report-warnings-errors nil) | |
;; 添加编译的工具和库位置 | |
;; 似乎是不必要的 | |
;; (when (and (fboundp #'native-comp-available-p) | |
;; (native-comp-available-p) | |
;; (eq system-type 'windows-nt)) | |
;; (setopt native-comp-driver-options | |
;; (list "-B" (expand-file-name (file-name-concat | |
;; invocation-directory | |
;; "../lib/gcc"))))) | |
;;@@TREESIT 基于语法树的 PL 前端工具 | |
;;te 使用 `yy/treesit-install-all-languages' 安装 tree-sitter | |
;; https://www.nathanfurnal.xyz/posts/building-tree-sitter-langs-emacs/ | |
(use-package treesit | |
:when (treesit-available-p) | |
:init | |
(setq treesit-language-source-alist | |
'((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) | |
(c . ("https://github.com/tree-sitter/tree-sitter-c")) | |
(cmake . ("https://github.com/uyha/tree-sitter-cmake")) | |
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) | |
(css . ("https://github.com/tree-sitter/tree-sitter-css")) | |
(go . ("https://github.com/tree-sitter/tree-sitter-go")) | |
(html . ("https://github.com/tree-sitter/tree-sitter-html")) | |
(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) | |
(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" | |
nil "typescript/src")) | |
(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" | |
nil "tsx/src")) | |
(json . ("https://github.com/tree-sitter/tree-sitter-json")) | |
(lua . ("https://github.com/Azganoth/tree-sitter-lua")) | |
(make . ("https://github.com/alemuller/tree-sitter-make")) | |
(python . ("https://github.com/tree-sitter/tree-sitter-python")) | |
(php . ("https://github.com/tree-sitter/tree-sitter-php" nil "php/src")) | |
(ruby . ("https://github.com/tree-sitter/tree-sitter-ruby")) | |
(rust . ("https://github.com/tree-sitter/tree-sitter-rust")) | |
(sql . ("https://github.com/m-novikov/tree-sitter-sql")) | |
(toml . ("https://github.com/tree-sitter/tree-sitter-toml")) | |
(zig . ("https://github.com/GrayJack/tree-sitter-zig")))) | |
:config | |
(defun yy/treesit-install-all-languages () | |
"Install all languages specified by `treesit-language-source-alist'." | |
(interactive) | |
(let ((languages (mapcar 'car treesit-language-source-alist))) | |
(dolist (lang languages) | |
(if (treesit-language-available-p lang) | |
(progn (message "`%s' parser already exists" lang) | |
(sit-for 0.5)) | |
(treesit-install-language-grammar lang) | |
(message "`%s' parser was installed." lang) | |
(sit-for 0.75)))))) | |
;;@@PIXEL-SCROLL | |
;; https://emacs-china.org/t/topic/25114/4 | |
;;te 是否使用像素滚动翻页 | |
(yy/defcustom yy/use-pixel-scrool nil | |
"是否使用像素滚动" | |
:type 'boolean) | |
(when yy/use-pixel-scrool | |
(use-package pixel-scroll | |
:config | |
(pixel-scroll-precision-mode 1) | |
(setq pixel-scroll-precision-interpolate-page t) | |
(defun yy/pixel-scroll-interpolate-down (&optional lines) | |
(interactive) | |
(if lines | |
(pixel-scroll-precision-interpolate (* -1 lines (pixel-line-height))) | |
(pixel-scroll-interpolate-down))) | |
(defun yy/pixel-scroll-interpolate-up (&optional lines) | |
(interactive) | |
(if lines | |
(pixel-scroll-precision-interpolate (* lines (pixel-line-height)))) | |
(pixel-scroll-interpolate-up)) | |
(defalias 'scroll-up-command 'yy/pixel-scroll-interpolate-down) | |
(defalias 'scroll-down-command 'yy/pixel-scroll-interpolate-up))) | |
;;@@REPEAT-MODE 反复触发一组命令 | |
;; 重复按键可以使用某个键反复触发,比如 C-x o o o ... | |
;; 可通过 `describe-repeat-maps' 来了解哪些命令可用 | |
(repeat-mode 1) | |
;;@@ELDOC echo area 位置的短文档 | |
;; 让 eldoc 显示的快一点 | |
(setopt eldoc-idle-delay 0.3) | |
;;@@PROJECT 配置项目管理功能 | |
(use-package project | |
:bind ("C-x p C-b" . yy/project-list-buffers) | |
:config | |
;; 使用 ibuffer 显示属于当前项目的文件 | |
;; 可通过 `g' 键更新 ibuffer | |
(defun yy/project-list-buffers (&optional arg) | |
(interactive "P") | |
(let* ((pr (project-current t)) | |
(root (expand-file-name (project-root pr))) | |
(name (format "*<p>%s*" | |
(file-name-nondirectory | |
(directory-file-name root))))) | |
(ibuffer t name) | |
(ibuffer-filter-disable) | |
(ibuffer-filter-by-filename root)))) | |
;;@@WEBJUMP 通过 emacs 触发浏览器搜索 | |
;; 可通过 webjump 直接 google | |
(use-package webjump | |
:config | |
(add-to-list 'webjump-sites | |
'("Google" . | |
[simple-query "www.google.com" | |
"www.google.com/search?q=" ""]))) | |
(defun yy/google () | |
"谷歌一下" | |
(interactive) | |
(let ((str (if (region-active-p) | |
(prog1 | |
(buffer-substring (region-beginning) (region-end)) | |
(deactivate-mark)) | |
(read-string "Google: ")))) | |
(browse-url (concat "https://google.com/search?q=" str)))) | |
;;@@AUTO-REVERT-MODE 当文件在外部被修改时,自动更新对应的 buffer | |
(global-auto-revert-mode) | |
;;@@FILESETS 可用于保存一系列常用的文件,方便打开 | |
;;te 添加一组自己常用的文件来让 emacs 启动时自动打开 | |
;; 使用 `filesets-add-buffer' 添加 buffer 到 group 中 | |
;; 使用 `filesets-edit' 来编辑 filesets group | |
(use-package filesets | |
:config | |
;;(filesets-init) | |
;; 默认在启动时打开的一组 buffer,它们一般平时很有用 | |
(when (filesets-get-fileset-from-name "FREQ") | |
(with-eval-after-load 'init | |
(filesets-open nil "FREQ")))) | |
;;@@WINDMOVE 提供根据位置在 window 间移动 point 的方法 | |
(use-package windmove | |
:init | |
(setopt windmove-wrap-around t) | |
:config | |
(windmove-mode t) | |
;; 使用 Hyper + wasd 在窗口间移动光标 | |
;;(windmove-default-keybindings 'hyper) | |
:bind (("H-a" . windmove-left) | |
("H-d" . windmove-right) | |
("H-w" . windmove-up) | |
("H-s" . windmove-down))) | |
;;@@TAB-BAR 多个窗口配置空间 | |
(use-package tab-bar | |
:config | |
;; 不使用默认配色,根本区分不了,草 | |
;; 2024-05-02,modus 自带了 tab-bar 的 face,不用自己设置了 | |
;; (custom-set-faces | |
;; '(tab-bar-tab ((t (:box (:line-width (1 . 1) :style released-button) :background "pale green" :inherit tab-bar)))) | |
;; '(tab-bar-tab-inactive ((t (:background "gray75" :inherit tab-bar-tab))))) | |
;; 给 tab-bar 添加更大的加号和删除号 | |
;; https://www.reddit.com/r/emacs/comments/16yeb5x/comment/k39fyta/?utm_source=share&utm_medium=web2x&context=3 | |
(define-icon tab-bar-new nil | |
`((image "tabs/new.xpm" | |
:width 20 :height 20 | |
:margin ,tab-bar-button-margin | |
:ascent center) | |
;; (emoji "➕") | |
;; (symbol "+") | |
(text " + ")) | |
"Icon for creating a new tab." | |
:version "29.1" | |
:help-echo "New tab" | |
:group tab-bar) | |
(define-icon tab-bar-close nil | |
`((image "tabs/close.xpm" | |
:width 20 | |
:height 20 | |
:margin ,tab-bar-button-margin | |
:ascent center) | |
;; (emoji " ❌") | |
;; (symbol "✕") ;; "ⓧ" | |
(text " x")) | |
"Icon for closing the clicked tab." | |
:version "29.1" | |
:help-echo "Click to close tab" | |
:group tab-bar) | |
(define-icon tab-bar-menu-bar nil | |
'(;; (emoji "🍔") | |
(symbol "☰") | |
(text "Menu" :face tab-bar-tab-inactive)) | |
"Icon for the menu bar." | |
:version "29.1" | |
:help-echo "Menu bar" | |
:group tab-bar) | |
(tab-bar-mode 1)) | |
;;@@SAVEHIST-MODE 保存 minibuffer 的 s 表达式求值历史 | |
(savehist-mode t) | |
;;@@PRETTIFY-SYMBOLS-MODE 优化某些符号的显示 | |
;; 全局打开 | |
(global-prettify-symbols-mode) | |
;;@@EGLOT | |
;; 加载 eglot | |
(require 'eglot) | |
(setopt eglot-report-progress nil) | |
;; 关掉 flymake 的一些提示信息,太吵了 | |
(add-to-list 'eglot-stay-out-of 'flymake) | |
;; 取消 eglot 的 log 消息,我不是 LSP server 的开发者 | |
(setopt eglot-events-buffer-size 0) | |
;;@@DABBREV 根据 buffer 内容进行补全 | |
(require 'dabbrev) | |
(defun yy/dabbrev-capf () | |
"对 `dabbrev-capf' 的简单包装" | |
(dabbrev--reset-global-variables) | |
(setq dabbrev--check-other-buffers nil) | |
(setq dabbrev--check-all-buffers nil) | |
(let* ((abbrev (dabbrev--abbrev-at-point)) | |
(beg (progn (search-backward abbrev) (point))) | |
(end (progn (search-forward abbrev) (point))) | |
(ignore-case-p (dabbrev--ignore-case-p abbrev)) | |
(list 'uninitialized) | |
(table | |
(lambda (s p a) | |
(if (eq a 'metadata) | |
`(metadata (cycle-sort-function . ,#'identity) | |
(category . dabbrev)) | |
(when (eq list 'uninitialized) | |
(save-excursion | |
;;-------------------------------- | |
;; New abbreviation to expand. | |
;;-------------------------------- | |
(setq dabbrev--last-abbreviation abbrev) | |
;; Find all expansion | |
(with-temp-message (current-message) | |
(let* ((inhibit-message t) | |
(completion-list | |
(dabbrev--find-all-expansions abbrev ignore-case-p)) | |
(completion-ignore-case ignore-case-p)) | |
(setq list | |
(cond | |
((not (and ignore-case-p dabbrev-case-replace)) | |
completion-list) | |
((string= abbrev (upcase abbrev)) | |
(mapcar #'upcase completion-list)) | |
((string= (substring abbrev 0 1) | |
(upcase (substring abbrev 0 1))) | |
(mapcar #'capitalize completion-list)) | |
(t | |
(mapcar #'downcase completion-list)))))))) | |
(complete-with-action a list s p))))) | |
(list beg end table))) | |
;; 将 dabbrev-capf 作为默认的 capf 之一,提供最基础的补全功能 | |
;; (add-to-list 'completion-at-point-functions 'yy/dabbrev-capf) | |
;;@@ISPELL, 30 里面的某些设置 | |
(setopt text-mode-ispell-word-completion nil) | |
;;@@MODUS-THEME 试试 Emacs 内置的 modus 主题 | |
(dolist (c (copy-sequence custom-enabled-themes)) | |
(disable-theme c)) | |
(cond | |
((>= emacs-major-version 30) | |
(load-theme 'modus-operandi-tinted nil t) | |
(load-theme 'modus-vivendi-deuteranopia nil t) | |
(if (or (>= (nth 2 (decode-time (current-time))) 18) (<= (nth 2 (decode-time (current-time))) 6)) | |
(enable-theme 'modus-vivendi-deuteranopia) | |
(enable-theme 'modus-operandi-tinted))) | |
((>= emacs-major-version 29) | |
(load-theme 'modus-operandi nil t) | |
(enable-theme 'modus-operandi)) | |
(t nil)) | |
(when (>= emacs-major-version 30) | |
(defun yy/toggle-modus-theme () | |
"切换 modus 主题" | |
(interactive) | |
(let ((theme (car custom-enabled-themes))) | |
(cond | |
((eq theme 'modus-operandi-tinted) | |
(disable-theme theme) | |
(enable-theme 'modus-vivendi-deuteranopia)) | |
((eq theme 'modus-vivendi-deuteranopia) | |
(disable-theme theme) | |
(enable-theme 'modus-operandi-tinted)) | |
(t (message "Seems current theme is not modus's series")))))) | |
;;@@PAREN 配置 Emacs 内置的括号显示功能 | |
;; 让光标在紧贴括号内部时也显示高亮 | |
(setopt show-paren-when-point-inside-paren t) | |
;; 让光标在一行时,高亮显示该行的最外层括号 | |
(setopt show-paren-when-point-in-periphery t) | |
;; 使用 overlay 显示当前屏幕内不可见的括号上下文 | |
;; 可以使用 t(echo-area), 'overlay, 'child-frame | |
(setopt show-paren-context-when-offscreen 'overlay) | |
;;@3 外部安装的 elisp 包 | |
;;@@ 指定需要安装的包 | |
(setopt package-selected-packages | |
'(;; 安装的包列表 | |
markdown-mode ; 提供 emacs 中的 markdown 支持 | |
;;parrot ; modeline 上的沙雕鹦鹉,点击播放 gif | |
cnfonts ; 中英文字体对其,通过 `cnfonts-edit-profile' 进行设定 | |
find-file-in-project ; ffip,查找项目中的文件 | |
winum ; 快速的窗口间跳转 | |
pyim ; 拼音输入法 | |
pyim-basedict ; pyim 依赖项 | |
popup ; pyim 依赖项 | |
asmd ; yyelpa 上的第一个包 | |
;;moe-theme ; 萌主题 | |
vertico ; M-x 补全 | |
;;company ; company 补全 | |
;;company-posframe ; company 的 childframe 补全界面 | |
eldoc-box ; 提供悬浮的 eldoc 补全 | |
vundo ; 可视化 undo,undo-tree 的替代品 | |
magit ; 强大的 git UI | |
ibuffer-vc ; 为 ibuffer 添加基于项目的分组 | |
orderless ; 乱序补全后端 | |
consult ; 异步查询框架 | |
wgrep ; 基于 grep 的批量替换工具 | |
haskell-mode ; haskell 语言支持 | |
igist ; emacs 的一个 gist 客户端 | |
devdocs ; 提供来自 devdocs 的文档支持 | |
buffer-env ; 提供基于 direnv 的 buffer-local 环境 | |
expand-region ; 选中扩展 | |
which-key ; 按键辅助,提示按键对应的命令 | |
diminish ; 让某些 mode 标识不在 modeline 显示 | |
;;yasnippet ; 强大的代码模板工具 | |
breadcrumb ; 面包屑导航 | |
blacken ; python blacken 的 emacs 集成 | |
shrface ; 更美观的 HTML 渲染 | |
docker ; emacs 的 docker 集成 | |
;;benchmark-init ; 收集 emacs 的启动信息 | |
;;tabspaces ; 提供基于 tab-bar 的 session 管理 | |
;;popwin ; 快速关闭各种临时 buffer | |
;;hyperbole ; 远古插件,也许很强大 | |
embark ; DWIM 工具 | |
embark-consult | |
popper ; 类似 popwin 但更好用 | |
expreg ; 类似 expand-region,但更好 | |
corfu ; corfu 补全前端,company 的替代品 | |
tempel ; 代码模板引擎 | |
cape ; 为 corfu 提供一些后端 | |
envrc ; 类似 buffer-env | |
citre ; ctags 的 emacs 前端 | |
powershell ; 在 Emacs 中打开 powershell, windows 下可用 | |
zig-mode | |
typescript-mode | |
emacsql ; 统一的 SQL 前端 | |
f ; 稍微好用一点的文件 API | |
)) | |
(package-install-selected-packages) | |
;;@@ 安装来自 git 仓库的包 | |
(setopt package-vc-selected-packages | |
'( | |
(yyorg-bookmark :url "https://github.com/include-yy/yyorg-bookmark") | |
(chodf :url "https://github.com/include-yy/chodf") | |
(rescript-mode :url "https://github.com/include-yy/rescript-mode") | |
(ox-w3ctr :url "https://github.com/include-yy/ox-w3ctr") | |
(tetosave :url "https://github.com/yyelpa/tetosave") ; 自动保存 | |
;;(consult-everything :url "https://github.com/jthaman/consult-everything") | |
;;(wgsl-ts-mode :url "https://github.com/acowley/wgsl-ts-mode") | |
(yynt :url "https://github.com/include-yy/yynt") | |
)) | |
(package-vc-install-selected-packages) | |
;;@@ emacs 29 的 package-vc-upgrade 似乎有点问题... | |
;; https://emacs-china.org/t/package-vc-upgrade-error-file-is-not-under-version-control/27073 | |
;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2024-04/msg01407.html | |
(when (eq emacs-major-version 29) | |
(defun yy/package-vc-upgrade-advice (upfun pkg-desc) | |
(with-temp-buffer | |
(funcall upfun pkg-desc))) | |
(advice-add 'package-vc-upgrade :around 'yy/package-vc-upgrade-advice)) | |
;;@@MARKDOWN-MODE | |
(use-package markdown-mode | |
:mode "\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\|mdx\\)\\'") | |
;;@@PARROT 沙雕鹦鹉 | |
;; (parrot-mode 1) | |
;;@@CNFONTS 中英文字体对齐 | |
(cnfonts-mode 1) | |
;;@@FIND-FILE-IN-PROJECT 方便的项目内文件搜索 | |
;;te 设置 ffip 在 Windows 下的相关选项 | |
;; 在 Windows 上需要设定 `ffip-find-executable' 为 find | |
;; 也可考虑使用 rust 编写的 fd,设置 `ffip-use-rust-fd' 为 `t' | |
;; 并设定 `ffip-find-executable' 为 fd 路径 | |
;; 注意:使用 fd 必须设定 `ffip-use-rust-fd',fd 与 find 命令行参数不一致 | |
(use-package find-file-in-project | |
:bind ("C-c f" . find-file-in-project) | |
:config | |
(yy/add-to-group 'ffip-find-executable) | |
(yy/add-to-group 'ffip-use-rust-fd)) | |
;;@@WINUM 窗口间跳转 | |
(use-package winum | |
:config | |
(set-face-attribute 'winum-face nil | |
:foreground "DeepPink" | |
:underline "DeepPink" | |
:weight 'bold) | |
(winum-set-keymap-prefix (kbd "C-c")) | |
(winum-mode 1)) | |
;;@@PYIM elisp 实现的中文输入法 | |
(use-package pyim | |
:init (setopt default-input-method "pyim") | |
:defer t | |
:config | |
(use-package pyim-basedict) | |
(use-package popup) | |
(pyim-basedict-enable) | |
(pyim-default-scheme 'microsoft-shuangpin)) | |
;;@@MOE-THEME 萌主题 | |
(use-package moe-theme | |
:disabled | |
:config | |
(moe-light)) | |
;;@@VERTICO 更好的 icomplete 和 ido | |
;;(ido-mode 1) | |
;;(icomplete-mode 1) | |
;;(icomplete-vertical-mode 1) | |
(vertico-mode 1) | |
;;@@COMPANY company 补全前端 | |
(use-package company | |
:diminish company-mode | |
:disabled | |
:config | |
(global-company-mode 1) | |
(setq company-global-modes '(not shell-mode eshell-mode org-mode)) | |
;; front-end configure | |
(setq company-mininum-prefix-length 3) ; 3 char to pop up menu | |
(setq company-idle-delay 0) ; set pop-up delay to 0s | |
(setq company-echo-delay 0) ; remove annoying blink | |
(setq company-require-match nil) ; allow string don't match candidate words | |
(setq company-show-numbers t) ; show candidates order number 1 ~ 9 and 0 | |
(setq company-selection-wrap-around t) ; loop over candidates | |
(setq company-auto-commit nil) ; don't use auto-complete | |
;; Use the tab-and-go frontend | |
;; Allow TAB to select and complete at the same time | |
(company-tng-configure-default) | |
(setq company-frontends | |
'(company-tng-frontend | |
company-pseudo-tooltip-frontend | |
company-echo-metadata-frontend)) | |
;;Customize company backends | |
(setq company-backends (delete 'company-bbdb company-backends)) | |
(setq company-backends (delete 'company-oddmuse company-backends)) | |
;; Don't downcase the returned candidate | |
(setq company-dabbrev-downcase nil) | |
(setq company-dabbrev-ignore-case t)) | |
;;@@COMPANY-POSFRAME 为 company 提供浮动子窗口支持 | |
(use-package company-posframe | |
:diminish company-posframe-mode | |
:after company | |
:config | |
(company-posframe-mode 1) | |
;;dont display annoying quickhelper | |
(setq company-posframe-quickhelp-delay nil)) | |
;;@@CORFU 试试更加轻量和现代的 corfu | |
(use-package corfu | |
:init | |
;; 允许 cycle | |
(setopt corfu-cycle t) | |
;; 允许自动触发 corfu 补全 | |
(setopt corfu-auto t) | |
;; 在补全时若候选项小于 3 则不弹出选项 | |
(setopt completion-cycle-threshold 3) | |
;; 在输入字符 0.1 秒后触发 corfu | |
(setopt corfu-auto-delay 0.1) | |
;; 无候选项不显示 no match | |
(setopt corfu-quit-no-match t) | |
:config | |
(global-corfu-mode) | |
(defun corfu-enable-always-in-minibuffer () | |
"Enable Corfu in the minibuffer if Vertico/Mct are not active." | |
(unless (or (bound-and-true-p mct--active) | |
(bound-and-true-p vertico--input) | |
(eq (current-local-map) read-passwd-map)) | |
;; (setq-local corfu-auto nil) ;; Enable/disable auto completion | |
(setq-local corfu-echo-delay nil ;; Disable automatic echo and popup | |
corfu-popupinfo-delay nil) | |
(corfu-mode 1))) | |
(add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1) | |
(add-hook 'eshell-mode-hook | |
(lambda () | |
(setq-local corfu-auto nil) | |
(corfu-mode)))) | |
;;@@ELDOC-BOX 悬浮式 ELDOC | |
(add-hook 'eglot-managed-mode-hook | |
#'eldoc-box-hover-mode) | |
;;@@VUNDO 可视化 undo,比 undo-tree 更好 | |
(use-package vundo | |
:bind ("C-?" . vundo)) | |
;;@@ORDERLESS 好用的模糊搜索插件 | |
(use-package orderless | |
:config | |
(setopt completion-styles '(orderless basic)) | |
(setopt completion-category-overrides | |
'((file (styles basic partial-completion)))) | |
;; 让 company 使用 basic | |
;; We follow a suggestion by company maintainer u/hvis: | |
;; https://www.reddit.com/r/emacs/comments/nichkl/comment/gz1jr3s/ | |
(defun company-completion-styles (capf-fn &rest args) | |
(let ((completion-styles '(basic partial-completion))) | |
(apply capf-fn args))) | |
(advice-add 'company-capf :around #'company-completion-styles)) | |
;;@@CONSULT 异步搜索框架 | |
;;te 配置 consult 的 grep 和 ripgrep 位置 | |
;; 在 Windows 下,注意修改 consult-grep-args 中的 grep 为 msys2 路径 | |
;; 非常奇怪,在 customzie 中这个选项无法显示 | |
;; 只能打个补丁 `yy/consult-grep-args' | |
;; `consult-ripgrep-args' 可以正常显示,所以就不在这里改了 | |
;; 常用命令: | |
;; - `consult-grep', `consult-ripgrep',`consult-git-grep' grep 当前项目的内容 | |
;; - `consult-line', 可视化 buffer 搜索 | |
;; - `consult-buffer', 强化版切换 `switch-to-buffer' | |
;; - `consult-goto-line', 可视化切换行 | |
;; 似乎又能够正常显示了,暂时用不到这个 option 了 | |
(yy/defcustom yy/consult-grep-args nil | |
"用于 consult 的 grep 命令行参数" | |
:type 'boolean) | |
(use-package consult | |
:bind | |
(("C-c s" . consult-line) | |
("M-g g" . consult-goto-line)) | |
:config | |
(when yy/consult-grep-args | |
(setq consult-grep-args yy/consult-grep-args))) | |
;;@@WGREP 可对 grep 结果进行编辑 | |
;; C-c C-p 进入编辑模式, C-x C-s 应用编辑结果, C-x C-q 结束编辑 | |
;; C-c C-d 标记删除某行 | |
;; C-c C-k 撤销所有变化并退出 | |
(use-package wgrep) | |
;;@@TETOSAVE 自动保存 buffer,无需频繁使用 C-x C-s 了 | |
(use-package tetosave | |
:config | |
(setopt tetosave-idle 0.5) | |
(tetosave-enable)) | |
;;@@IGIST 好用的 gist 管理工具 | |
;;te 需要设置 `igist-auth-marker' 为 oauth token | |
;; token 的获取参考 https://github.com/KarimAziev/igist/tree/main#auth | |
(use-package igist | |
:after tetosave | |
:bind ("M-o" . igist-dispatch) | |
:config | |
(setopt igist-current-user-name "include-yy") | |
;; disable tetosave for igist-edit-mode | |
(add-to-list 'tetosave-disable-predicates | |
(defun igist/teto-pred () igist-edit-mode)) | |
;; disable tetosave for gpg file | |
(add-to-list 'tetosave-disable-predicates | |
(defun igist/teto-pred-authinfo () | |
(eq major-mode 'authinfo-mode)))) | |
;;@@EXPAND-REGION 方便的 region 扩展工具 | |
(use-package expand-region | |
;; 现在可以试试 Yuan fu 的 expreg | |
:when (not (treesit-available-p)) | |
:bind ("C-=" . er/expand-region)) | |
;;@@EXPREG 可以使用 tree sitter 的 expand-region | |
(use-package expreg | |
:when (treesit-available-p) | |
:bind ("C-=" . expreg-expand)) | |
;;@@WHICH-KEY 显示某个按键绑定的 keymap 中的命令 | |
(use-package which-key | |
:diminish which-key-mode | |
:init | |
;; 通过 C-h 或 ? 才显示 which-key buffer | |
;; 如果某些命令使用了 C-h 或 ? 可能会冲突 | |
(setopt which-key-show-early-on-C-h t) | |
;; 仅通过 C-h 触发 | |
(setopt which-key-idle-delay 10000.0) | |
;; 在随后的按键中迅速响应 | |
(setopt which-key-idle-secondary-delay 0.05) | |
:config | |
;; 启动全局 which-key-mode | |
(which-key-mode)) | |
;;@@BREADCRUMB 面包屑导航 | |
(breadcrumb-mode) | |
;;@@YASNIPPET 代码模板系统,提供好用的代码模板 | |
(use-package yasnippet | |
;; 试试 tempo 去 | |
:disabled) | |
;;@@SHRFACE,更好看的 html 渲染 | |
(use-package shrface | |
:config | |
:disabled | |
(shrface-basic) | |
(shrface-trial) | |
(shrface-default-keybindings) | |
(setopt shrface-href-versatile t)) | |
;;@@DOCKER 方便的 docker emacs 集成 | |
(use-package docker | |
:if (eq system-type 'gnu/linux) | |
:bind ("C-c d" . docker)) | |
;;@@TABSPACE 使用 tab-bar-mode 和 project.el 管理项目 | |
(use-package tabspaces | |
:disabled | |
:init | |
(setopt tabspaces-default-tab "Default") | |
(setopt tabspaces-initialize-project-with-todo nil) | |
;;(setopt tabspaces-use-filtered-buffers-as-default t) | |
;; sessions | |
(setopt tabspaces-session t) | |
(setopt tabspaces-session-auto-restore t) | |
:config | |
(tabspaces-mode)) | |
;;@@POPWIN 方便地从 *Help*, *Completions* 等临时 buffer 中通过 C-g 退出 | |
(use-package popwin | |
;; 感觉不如 popper | |
:disabled | |
:config | |
(popwin-mode)) | |
;;@@EMBARK 归一化的动作执行者 | |
(use-package embark | |
:bind | |
(("C-." . embark-act) | |
("C-;" . embark-dwim))) | |
;;@@EMBARK-CONSULT 联动 embark 与 consult | |
(use-package embark-consult | |
:hook | |
(embark-collect-mode . consult-preview-at-point-mode)) | |
;;@@HYPERBOLE 暂时不知道怎么用 | |
;; 它会占用 C-h h ,原本用于打开 Hello buffer | |
(use-package hyperbole | |
:disabled) | |
;;@@POPPER 管理弹出的各种临时 buffer | |
;; 这样就不会打破 Window 布局 | |
(use-package popper | |
:bind (("C-`" . popper-toggle) | |
("M-`" . popper-cycle) | |
("C-M-`" . popper-toggle-type)) | |
:init | |
(setopt popper-reference-buffers | |
'("\\*Messages\\*" "Output\\*$" | |
"\\*Async Shell Command\\*" | |
"\\*Completions\\*" | |
"\\*eshell.*\\*" eshell-mode | |
"\\*Occur\\*" | |
help-mode | |
compilation-mode | |
shell-mode "^\\*shell.*\\*" | |
"\\*xref\\*")) | |
:config | |
(popper-mode 1) | |
(popper-echo-mode 1)) | |
;;@@ENVRC Linux 上管理开发环境 | |
;; 可以执行 `envrc-allow' 和 `envrc-deny' 来开启和关闭某目录下的 .envrc | |
(use-package envrc | |
:when (eq system-type 'gnu/linux) | |
:config | |
(envrc-global-mode)) | |
;;@@TEMPEL 好用的代码模板工具 | |
(use-package templ | |
:bind (("M-+" . tempel-complete) | |
("M-*" . tempel-insert)) | |
:init | |
(defun tempel-setup-capf () | |
;; Add the Tempel Capf to `completion-at-point-functions'. | |
;; `tempel-expand' only triggers on exact matches. Alternatively use | |
;; `tempel-complete' if you want to see all matches, but then you | |
;; should also configure `tempel-trigger-prefix', such that Tempel | |
;; does not trigger too often when you don't expect it. NOTE: We add | |
;; `tempel-expand' *before* the main programming mode Capf, such | |
;; that it will be tried first. | |
(setq-local completion-at-point-functions | |
(cons #'tempel-expand | |
completion-at-point-functions))) | |
(add-hook 'prog-mode-hook 'tempel-setup-capf)) | |
;;@@CITRE 先进的 ctags 前端 | |
(use-package citre | |
:init | |
(use-package citre-config)) | |
;;@@OX-W3CTR 我写的 org 导出后端 | |
(require 'ox-w3ctr) | |
;;@4 一些零散的小函数和设定 | |
;;@@ 打开 init 文件 | |
(defun yy/open-init () | |
"Open my init file" | |
(interactive) | |
(find-file "~/.emacs.d/init.el")) | |
;;@@ 执行 yynt.el 的初始化 | |
(defun yy/open-yynt () | |
"eval yynt2.el whole buffer" | |
(interactive) | |
(if-let ((buf (get-buffer "yy.el"))) | |
(with-current-buffer buf | |
(eval-buffer)) | |
(message "yy.el not open"))) | |
;;@@ 增强 C-x <num> 系列的 Window 管理功能 | |
(defun yy/split-and-move-to-other-window (fun) | |
(lambda (&optional arg) | |
(interactive "P") | |
(funcall fun) | |
(let ((target-window (next-window))) | |
(set-window-buffer target-window (other-buffer)) | |
(unless arg | |
(select-window target-window))))) | |
(defalias 'yy/split-window-below (yy/split-and-move-to-other-window | |
'split-window-below)) | |
(defalias 'yy/split-window-right (yy/split-and-move-to-other-window | |
'split-window-right)) | |
(defun yy/delete-other-windows () | |
(interactive) | |
(if (and winner-mode | |
(equal (selected-window) (next-window))) | |
(winner-undo) | |
(delete-other-windows))) | |
(defun yy/split-change-place (fun) | |
"Kill any other windows and re-split current window in one way. | |
the current window is on the left/top half of the frame. | |
way-func can be | or _" | |
(lambda () | |
(interactive) | |
(let ((other-buf (and (next-window) (window-buffer (next-window))))) | |
(delete-other-windows) | |
(funcall fun) | |
(when other-buf | |
(set-window-buffer (next-window) other-buf))))) | |
(defalias 'yy/split-change-right (yy/split-change-place 'split-window-right)) | |
(defalias 'yy/split-change-below (yy/split-change-place 'split-window-below)) | |
(bind-key "C-x 1" 'yy/delete-other-windows) | |
(bind-key "C-x 2" 'yy/split-window-below) | |
(bind-key "C-x 3" 'yy/split-window-right) | |
(bind-key "C-x |" 'yy/split-change-right) | |
(bind-key "C-x _" 'yy/split-change-below) | |
;;@@ 显示修改过的按键绑定 | |
(defun yy/show-keys () | |
"显示所有通过 `use-package' 或 `bind-key' 修改的按键绑定" | |
(interactive) | |
(describe-personal-keybindings)) | |
;;@@ 文字计数,可以处理中文和英文 | |
;; Author: Andy Stewart <lazycat.manatee@gmail.com> | |
;; http://www.emacswiki.org/emacs/download/basic-toolkit.el | |
(defun count-ce-words (beg end) | |
"Count Chinese and English words in marked region." | |
(interactive "r") | |
(let ((cn-word 0) | |
(en-word 0) | |
(total-word 0) | |
(total-byte 0)) | |
(setq cn-word (count-matches "\\cc" beg end) | |
en-word (count-matches "\\w+\\W" beg end)) | |
(setq total-word (+ cn-word en-word) | |
total-byte (+ cn-word (abs (- beg end)))) | |
(message (format "Total: %d (CN: %d, EN: %d) words, %d bytes." | |
total-word cn-word en-word total-byte)))) | |
;;@@ 删除 *{name}* 的 buffer | |
(defun kill-unused-buffers () | |
(interactive) | |
(ignore-errors | |
(save-excursion | |
(dolist (buf (buffer-list)) | |
(set-buffer buf) | |
(if (and (string-prefix-p "*" (buffer-name)) | |
(string-suffix-p "*" (buffer-name))) | |
(kill-buffer buf)))))) | |
;;@@ 对整个 buffer 进行缩进 | |
(defun indent-buffer () | |
"Automatic format current buffer." | |
(interactive) | |
(save-excursion | |
(indent-region (point-min) (point-max) nil) | |
(delete-trailing-whitespace) | |
(untabify (point-min) (point-max)))) | |
;;@@IGIST 使用 igist 管理 init.el 配置文件 | |
(require 'igist) | |
(require 'transient) | |
(defun yy/upload-init-file () | |
"将 init.el 更新到对应 gist" | |
(interactive) | |
(when-let* ((initbuf (get-file-buffer (file-name-concat user-emacs-directory "init.el"))) | |
(gistbuf (current-buffer))) | |
(if (not (with-current-buffer gistbuf | |
(bound-and-true-p yy-init-file))) | |
(user-error "not in igist buffer init.el") | |
(let ((inhibit-read-only t)) | |
(with-current-buffer initbuf | |
(copy-to-buffer gistbuf (point-min) (point-max))) | |
(with-current-buffer gistbuf | |
(igist-save-current-gist-and-exit)))))) | |
(defun yy/update-init-file () | |
"将 igist init buffer 中的内容更新到本地的 init.el" | |
(interactive) | |
(when-let* ((initbuf (get-file-buffer (file-name-concat user-emacs-directory "init.el"))) | |
(gistbuf (current-buffer))) | |
(if (not (with-current-buffer gistbuf | |
(bound-and-true-p yy-init-file))) | |
(user-error "not in igist buffer init.el") | |
(let ((inhibit-read-only t)) | |
(with-current-buffer gistbuf | |
(copy-to-buffer initbuf (point-min) (point-max))) | |
(kill-buffer gistbuf))))) | |
(defun yy/diff-init-and-igist (&optional reverse) | |
"对 init.el 和 igist init buffer 调用 `diff-buffers'" | |
(interactive) | |
(when-let* ((initbuf (get-file-buffer (file-name-concat user-emacs-directory "init.el"))) | |
(gistbuf (current-buffer))) | |
(if (not (with-current-buffer gistbuf | |
(bound-and-true-p yy-init-file))) | |
(user-error "not in igist buffer init.el") | |
(if reverse | |
(diff-buffers initbuf gistbuf) | |
(diff-buffers gistbuf initbuf))))) | |
(defalias 'yy/diff-igist-and-init (lambda () (interactive) (yy/diff-init-and-igist t))) | |
(transient-define-prefix yy/init-file-transient () | |
"用于 igist init buffer 的 transient 按键,简单的界面" | |
["diff" | |
("f" "观察 init 相对 gist 的改动" yy/diff-init-and-igist) | |
("r" "观察 gist 相对 init 的区别" yy/diff-igist-and-init)] | |
["update" | |
("u" "将 init.el 更新到 gist" yy/upload-init-file) | |
("d" "将 gist 内容复制到本地 init" yy/update-init-file)]) | |
(defun yy/get-gist-init-file () | |
"获取来自 gist 的 init.el 文件,可直接复制其中内容,也可修改并 C-c C-c 提交 | |
建议在 init.el 文件中运行该命令,方便对比修改" | |
(interactive) | |
(yy/open-init) | |
(igist-list-load-gists | |
"include-yy" t | |
(lambda () | |
(with-current-buffer (igist-get-user-buffer-name | |
igist-current-user-name) | |
(goto-char (point-min)) | |
(search-forward "init.el") | |
(with-current-buffer (igist-list-edit-gist-at-point) | |
(setq-local yy-init-file t) | |
;;https://stackoverflow.com/questions/27321407/how-to-make-a-buffer-local-key-binding-in-emacs | |
(use-local-map (copy-keymap (current-local-map))) | |
(local-set-key (kbd "C-c c") 'yy/init-file-transient) | |
)) | |
(kill-buffer (igist-get-user-buffer-name | |
igist-current-user-name))))) | |
;;@@YYINIT-MODE 用于 init.el 浏览各配置节点的 minor-mode,使用了 outline-minor-mode | |
(defvar-keymap yyinit-mode-map | |
:doc "部分来自 outline-mode 的键绑定" | |
"C-c C-n" #'outline-next-visible-heading | |
"C-c C-p" #'outline-previous-visible-heading | |
"C-c C-u" #'outline-up-heading | |
"C-c C-a" #'outline-show-all | |
"C-c C-o" #'outline-hide-other | |
"C-c C-j" #'consult-outline | |
;; 把打开 gist 上配置的功能顺便放这里算了 | |
"C-c C-c" #'yy/get-gist-init-file) | |
(define-minor-mode yyinit-mode | |
"用于浏览配置文件各节点的 minor-mode,添加了部分 outline-mode 按键绑定" | |
:keymap yyinit-mode-map) | |
(defun yy/yyinit-setup () | |
(interactive) | |
(when (equal (expand-file-name "~/.emacs.d/init.el") | |
(buffer-file-name (current-buffer))) | |
(setq-local outline-regexp ";;; init.el ---\\|;;; Code\\|;;@+") | |
(setq-local outline-heading-alist '((";;; init.el ---" . 1) (";;; Code" . 1) | |
(";;@" . 2) (";;@@" . 3))) | |
(setq-local outline-minor-mode-use-buttons 'in-margins) | |
(setq-local outline-minor-mode-highlight 'override) | |
(setq-local outline-minor-mode-cycle t) | |
(setq-local outline-level 'outline-level) | |
(outline-minor-mode) | |
(yyinit-mode))) | |
;;@@EAF, lazycat 的 Emacs 应用框架 | |
;;te 从 eaf github 拉取仓库,在目录下创建名为 eaf-venv 的 python 虚拟环境 | |
;; 在虚拟环境下运行 install-eaf.py | |
(yy/defcustom yy/use-eaf nil "是否使用 eaf") | |
(when (and (eq system-type 'windows-nt) yy/use-eaf) | |
(let ((path (file-name-concat user-emacs-directory "emacs-application-framework"))) | |
(when (file-exists-p path) | |
(add-to-list 'load-path path) | |
(require 'eaf) | |
(require 'eaf-browser) | |
(setq eaf-python-command (file-name-concat path "eaf-venv" "Scripts" "python.exe"))))) | |
;;@5 专门的语言特定配置区域 | |
;;@@PYTHON 配置 | |
;; 默认使用 python-ts-mode,需要安装 python 的 treesitter | |
(add-to-list 'eglot-server-programs | |
'((python-mode python-ts-mode) . ("pyright-langserver" "--stdio"))) | |
;; 启用 treesit | |
(yy/defcustom yy-use-python-treesit nil | |
"是否使用 emacs 的 treesit python 支持 | |
当前,treesit 似乎还是不够稳定") | |
(when (and (treesit-available-p) | |
yy-use-python-treesit | |
(treesit-ready-p 'python)) | |
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))) | |
;; linux 下的 python 是 python3, Windows 还是用 python | |
(when (equal system-type 'windows-nt) | |
(setopt python-shell-interpreter "python")) | |
(use-package python | |
:init | |
(defun yy/python-devdocs-current-docs () | |
(setq-local devdocs-current-docs '("python~3.11"))) | |
:bind | |
;; 设置 C-c r 来使用 eglot-rename,提供简单的重构功能 | |
(:map python-base-mode-map | |
("C-c r" . eglot-rename) ;; 重命名 | |
("C-+" . hs-toggle-hiding) ;; 折叠代码 | |
("C-c d" . devdocs-lookup) ;; 查找文档 | |
("C-c f" . blacken-buffer) ;; black 格式化 | |
) | |
:hook | |
;; 使用 pyright 作为 lsp server | |
;;te 通过 pip/pipx install pyright 来安装 pyright,使用 npm 也行 | |
(python-base-mode . eglot-ensure) | |
;; 使用 prettify ,将 lambda -> λ, and -> ∧, or -> ∨ | |
(python-base-mode . prettify-symbols-mode) | |
;; 使用 hs-minor-mode 来折叠代码 | |
(python-base-mode . hs-minor-mode) | |
;; 默认使用 python3.11 的文档 | |
(python-base-mode . yy/python-devdocs-current-docs)) | |
;;@@JAVASCRIPT 配置 | |
;; 添加 treesit 支持,替换 js-mode 和 js-json-mode | |
;; 草,怎么感觉有时候还不如原始的 js-mode | |
(yy/defcustom yy/use-js-treesit nil | |
"是否使用 js 的 `js-ts-mode'" | |
:type 'boolean) | |
(if (and (treesit-available-p) | |
yy/use-js-treesit) | |
(progn | |
(when (treesit-language-available-p 'javascript) | |
(add-to-list 'major-mode-remap-alist '(javascript-mode . js-ts-mode))) | |
(when (treesit-language-available-p 'json) | |
(add-to-list 'major-mode-remap-alist '(js-json-mode . json-ts-mode))) | |
(when (treesit-language-available-p 'typescript) | |
(require 'typescript-ts-mode))) | |
(require 'typescript-mode)) | |
;; 默认开启 LSP: typescript-language-server | |
;;te 可通过 npm install -g typescript 安装 | |
(yy/defcustom yy/use-js-lsp nil | |
"是否使用 js 的 LSP" | |
:type 'boolean) | |
(when yy/use-js-lsp | |
(add-hook 'js-base-mode-hook 'eglot-ensure)) | |
;; 设置 M-. 使用 xref | |
(use-package js | |
:config | |
(keymap-set js-mode-map "M-." 'xref-find-definitions) | |
(when (treesit-available-p) | |
(keymap-set js-ts-mode-map "M-." 'xref-find-definitions))) | |
;; 将 cjs mjs 和 ts(根据是否有 tree-sitter-ts)添加到 `auto-mode-alist' | |
(add-to-list 'auto-mode-alist '("\\.\\(cjs\\|mjs\\)\\'" . javascript-mode)) | |
;;@@RESCRIPT 配置 | |
;;te 配置 rescript lsp | |
;; 从 https://github.com/rescript-lang/rescript-vscode/releases/tag/1.18.0 | |
;; 获取 lsp-server,然后解压缩将其中的 extension 文件夹放在 rescript-mode 目录下 | |
;; 也许可以考虑添加 tree-sitter 支持 | |
;; 项目在编译后才会有 LSP 提示 | |
;; 从 rescript 11 开始,提供了独立的 lsp 包,可通过以下方式安装 | |
;; npm install -g @rescript/language-server | |
;; npx rescript-language-server --stdio | |
(yy/defcustom yy/use-rescript-lsp nil | |
"是否使用 rescript 的 LSP" | |
:type '(choice (boolean) | |
(string :tag "Path"))) | |
(use-package rescript-mode | |
;;:disabled | |
) | |
(when yy/use-rescript-lsp | |
(let ((cmd (if (booleanp yy/use-js-lsp) | |
(list "rescript-language-server" "--stdio") | |
(list "node" yy/use-rescript-lsp "--stdio")))) | |
(add-to-list | |
'eglot-server-programs | |
`(rescript-mode . ,cmd))) | |
(add-hook 'rescript-mode-hook 'eglot-ensure)) | |
;;@@WGSL 配置 | |
;; 添加 treesit 支持 | |
;;te 需要从安装 libtree-sitter-wgsl 与 wgsl-ts-mode | |
;; 可自行从 https://github.com/szebniok/tree-sitter-wgsl 获取库并在 src 目录使用命令: | |
;; gcc -fPIC -c -I. parser.c && gcc -fPIC -c -I. scanner.c | |
;; gcc -fPIC -shared *.o -o libtree-sitter-wgsl.dll | |
;; 可使用 M-x package-vc-install https://github.com/acowley/wgsl-ts-mode 安装 ts mode | |
;;te 安装 wgsl lsp | |
;; cargo install --git https://github.com/wgsl-analyzer/wgsl-analyzer wgsl_analyzer | |
;; 当前似乎与 eglot 的配合存在一些问题 | |
(use-package wgsl-ts-mode | |
:disabled | |
:config | |
(add-hook 'wgsl-ts-mode-hook | |
(defun yy/set-dabbrev-capf () | |
(setq-local completion-at-point-functions | |
'(yy/dabbrev-capf t))))) | |
(yy/defcustom yy/use-wgsl-lsp nil | |
"是否使用 wgsl 的 LSP" | |
:type 'boolean) | |
(when (and (fboundp 'wgsl-ts-mode) | |
yy/use-wgsl-lsp) | |
(add-to-list 'eglot-server-programs | |
'(wgsl-ts-mode "wgsl_analyzer")) | |
(add-hook 'wgsl-ts-mode-hook 'eglot-ensure)) | |
;;@@RUST 配置 | |
(when (treesit-available-p) | |
(require 'rust-ts-mode)) | |
(yy/defcustom yy/use-rust-lsp nil | |
"是否使用 rust lsp" | |
:type 'boolean) | |
(when yy/use-rust-lsp | |
;; https://gist.github.com/casouri/0ad2c6e58965f6fd2498a91fc9c66501 | |
(add-to-list 'eglot-server-programs | |
`(rust-ts-mode . ("rust-analyzer" :initializationOptions | |
( :procMacro (:enable t) | |
:cargo ( :buildScripts (:enable t) | |
:features "all"))))) | |
(add-hook 'rust-ts-mode-hook 'eglot-ensure)) | |
;;@@C/C++ 配置 | |
;; 可以使用 cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=1 生成 LSP 可用的文件 | |
(yy/defcustom yy/use-msys2-ucrt-clangd nil | |
"是否使用 msys2 的 ucrt 中的 clangd LSP server" | |
:type 'boolean) | |
(when (and (treesit-available-p) | |
(treesit-ready-p 'c) | |
(treesit-ready-p 'cpp)) | |
(dolist (a '((c-mode . c-ts-mode) | |
(c++-mode . c++-ts-mode) | |
(c-or-c++-mode . c-or-c++-ts-mode))) | |
(add-to-list 'major-mode-remap-alist a)) | |
(setopt c-ts-mode-indent-style 'bsd) | |
(setopt c-ts-mode-indent-offset 4)) | |
(if yy/use-msys2-ucrt-clangd | |
(progn (add-to-list 'eglot-server-programs | |
`((c++-ts-mode c-ts-mode c-or-c++-mode) | |
;; https://stackoverflow.com/a/76077729 | |
,(file-name-concat yy/w32-msys-root-path | |
"msys2_shell.cmd") | |
"-defterm" "-no-start" "-ucrt64" "-here" | |
"-c" "\"clangd\"")) | |
(add-hook 'c-ts-mode-hook 'eglot-ensure) | |
(add-hook 'c++-ts-mode-hook 'eglot-ensure)) | |
(when (executable-find "clangd") | |
(add-to-list 'eglot-server-programs | |
'((c++-ts-mode c-ts-mode c-or-c++-mode) "clangd")) | |
(add-hook 'c-ts-mode-hook 'eglot-ensure) | |
(add-hook 'c++-ts-mode-hook 'eglot-ensure))) | |
;; 加载一下 cmake-ts-mode 里面的 `auto-mode-alist' 设定表达式 | |
(when (and | |
(treesit-available-p) | |
(treesit-language-available-p 'cmake)) | |
(require 'cmake-ts-mode)) | |
;;@@ 文件尾,file-local 变量 | |
(run-with-idle-timer | |
1.0 nil | |
(lambda () (message "hello world, emacs-init-time is %s" (emacs-init-time)))) | |
(provide 'init) | |
;; Local Variables: | |
;; eval: (when (fboundp 'yy/yyinit-setup) (yy/yyinit-setup)) | |
;; End: | |
;;; init.el ends here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; -*- mode: emacs-lisp; lexical-binding:t; -*- | |
fundamental-mode | |
org-mode | |
(quote "#+BEGIN_QUOTE" n r> n "#+END_QUOTE") | |
(q "{{{q(" p ")}}}") | |
(src "#+BEGIN_SRC " q n r n "#+END_SRC") | |
(isrc "src_" p "{" q "}") | |
(link "[[" p "]]") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment