Cover image for My Emacs Configuration

My Emacs Configuration

Words 6.6k
Views
Visitors

Timeline

Timeline

2025-01-12

init

2025-10-17

add clang-format

2025-12-03

modify indent style

2025-12-15

add desktop-save-mode, add ibuffer, add magit

This article describes the author's complete process of configuring Emacs in the Windows Terminal and WSL2 environment, including installing plugins such as clang-format, ibuffer, and magit, and enabling desktop-save-mode. The article details the Windows Terminal color scheme (GitHub-Dark-Default), font (FiraCode Nerd Font), background transparency and acrylic material settings, as well as installing win32yank.exe to support the clipboard. It also provides package installation and mirror source change suggestions for Arch Linux and Ubuntu 20.04. The article focuses on listing a rich set of keyboard shortcut configurations in table form, covering functions such as window size adjustment, tab switching, line movement, error navigation, LSP code fixes and jumps, file browsing, magit status, code formatting, etc., demonstrating a configuration approach for efficient code editing and navigation through LSP.

Environment

Using Windows Terminal + WSL2

WSL2 Arch Linux
WSL2 Arch Linux

Configuration

Windows Terminal

In Windows Terminal, open Settings, choose to open the JSON file, and add a color scheme in schemes.

123456789101112131415161718192021222324252627
"schemes":    [        {            "background": "#0D1117",            "black": "#484F58",            "blue": "#58A6FF",            "brightBlack": "#6E7681",            "brightBlue": "#79C0FF",            "brightCyan": "#56D4DD",            "brightGreen": "#56D364",            "brightPurple": "#D2A8FF",            "brightRed": "#FFA198",            "brightWhite": "#FFFFFF",            "brightYellow": "#E3B341",            "cursorColor": "#2F81F7",            "cyan": "#39C5CF",            "foreground": "#E6EDF3",            "green": "#3FB950",            "name": "GitHub-Dark-Default",            "purple": "#BC8CFF",            "red": "#FF7B72",            "selectionBackground": "#E6EDF3",            "white": "#B1BAC4",            "yellow": "#D29922"        }    ],
  • In the archlinux configuration, select the Appearance tab.
    • Select GitHub-Dark-Default as the color scheme.
    • Select FiraCode Nerd Font as the font.
    • Set background opacity to 86% and enable acrylic material.
  • In the archlinux configuration, select the Advanced tab.
    • For the bell notification style, uncheck Sound, and select Flash window and Flash taskbar.
  • Install win32yank.exe and add it to the environment variables so that it can be accessed directly from the command line.

If acrylic fails, turn off Windows power saving mode.

Arch Linux

Arch Linux needs to download some packages.

Download yay reference

Note: After downloading, it is best to change the source for pacman and yay, otherwise the speed will be extremely slow.

12345678910111213141516171819202122232425262728293031
# Set localesudo nano /etc/locale.gen# Find #en_US.UTF-8 UTF-8 and uncomment it.sudo locale-gensudo pacman -Sy emacs-noxsudo pacman -Sy clang nvm ripgrep bear pandoc# python/bash developmentsource /usr/share/nvm/init-nvm.shnvm list-remotenvm install v20.19.4nvm use v20.19.4npm i -g pyright bash-language-server devicetree-language-server prettier# rust developmentcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shrustup component add rust-analyzer# Replace the system ls command with the exa command.sudo pacman -S exa# If it is bash, write it to bashrc.echo 'alias ll="ls -alF"' >> ~/.bashrcecho 'alias ls="exa --icons"' >> ~/.bashrcsource ~/.bashrcmkdir -p ~/.emacs.d/data/backupmkdir -p ~/.emacs.d/data/autosavegit config --global core.editor "emacs"

Ubuntu20.04

Reference:

Emacs

Install

Arch Linux can be installed directly via pacman; if it is Ubuntu, consider compiling it yourself, refer to:

Configuration

.emacs(Click to expand)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
;;不显示menu-bar(menu-bar-mode -1);;显示行号(global-display-line-numbers-mode t);;在ModeLine显示列号(column-number-mode 1);;代码的折叠(add-hook 'prog-mode-hook 'hs-minor-mode);; 自动重载更改的文件(global-auto-revert-mode 1);;开启可视化换行,自动折行(global-visual-line-mode 1);; 括号匹配(electric-pair-mode 1);; 自动缩进(electric-indent-mode 1);; 鼠标模式(xterm-mouse-mode 1);; 中文显示(set-language-environment "utf-8")(set-buffer-file-coding-system 'utf-8)(set-terminal-coding-system 'utf-8)(set-keyboard-coding-system 'utf-8)(set-selection-coding-system 'utf-8)(set-default-coding-systems 'utf-8)(set-clipboard-coding-system 'utf-8)(modify-coding-system-alist 'process "*" 'utf-8)(prefer-coding-system 'utf-8)(setq-default pathname-coding-system 'utf-8)(setq default-process-coding-system '(utf-8 . utf-8)      locale-coding-system 'utf-8      file-name-coding-system 'utf-8      default-buffer-file-coding-system 'utf-8      slime-net-coding-system 'utf-8-unix      )(setq find-file-encoding 'auto)(setq-default coding-system-for-read 'utf-8)(setq-default coding-system-for-write 'utf-8);; 基本设置(setq-default window-combination-resize t                      ;; 新窗口平均其他左右窗口              x-stretch-cursor t                               ;; 将光标拉伸到字形宽度              indent-tabs-mode nil              tab-width 8              )(setq ring-bell-function 'ignore      initial-scratch-message nil      inhibit-startup-message t      auto-save-file-name-transforms '((".*" "~/.emacs.d/data/autosave/" t)) ;; Write auto-save files to a separate directory      backup-directory-alist '(("." . "~/.emacs.d/data/backup/"))          ;; Write backup files to a separate directory      create-lockfiles nil                                                 ;; Disable lockfiles      scroll-conservatively 10000 ;;防止页面滚动时跳动      scroll-step 1               ;; 当光标移动到边缘时,窗口每次只滚动一行      undo-limit 80000         ;; 提升撤销限制      display-time-default-load-average nil ;; 不显示系统负载      use-short-answers t      comp-deferred-compilation t ;; Emacs 28+      native-comp-async-report-warnings-errors nil      )(defun my/kill-unwanted-buffers ()  "在 Emacs 启动时关闭一些不想要的 buffer."  (dolist (buf-name '("*scratch*"                      ;;"*Async-native-compile-log*" ;; can't be killed                      ;;"*Messages*"                      ))    (when (get-buffer buf-name)      (kill-buffer buf-name))))(add-hook 'emacs-startup-hook #'my/kill-unwanted-buffers);; 启动速度统计(add-hook 'emacs-startup-hook          (lambda ()            (message "Emacs ready in %s with %d garbage collections."                     (format "%.2f seconds"                             (float-time                              (time-subtract after-init-time before-init-time)))                     gcs-done)));; 如果用emacs打开文件则只打开文件,如果直接打开emacs则开启上次退出的非空界面;; (add-hook 'after-init-hook;;           (defun if-desktop-read ();; 	    (setq desktop-dirname             "~/.emacs.d/desktop/";; 		  desktop-base-file-name      "emacs.desktop";; 		  desktop-base-lock-name      "lock";; 		  desktop-path                (list desktop-dirname);; 		  desktop-save                t;; 		  desktop-files-not-to-save   "^$" ;reload tramp paths;; 		  desktop-load-locked-desktop nil;; 		  desktop-auto-save-timeout   10);; 	    (desktop-save-mode 1);; 	    (if (< (length command-line-args) 2);; 		(desktop-read)));;           'if-desktop-read);; 使用 Fira Code Nerd Font 字体(when (display-graphic-p)  (set-face-attribute 'default nil                      :font "FiraCode Nerd Font"                      :height 120));; 剪贴板与系统共享:根据环境自动选择 WSL(Windows) 或 Ubuntu(Wayland/X11) 方案(cond ;; 1. WSL 与 Windows 共享剪贴板(win32yank.exe) ((executable-find "win32yank.exe")  (defun my/clipboard-to-windows (text &optional push)    (let ((process-connection-type nil))      (with-temp-buffer        (insert text)        (call-process-region (point-min) (point-max) "win32yank.exe" nil nil nil "-i"))))  (defun my/clipboard-from-windows ()    (string-trim-right     (with-output-to-string       (call-process "win32yank.exe" nil standard-output nil "-o"))))  (setq interprogram-cut-function 'my/clipboard-to-windows)  (setq interprogram-paste-function 'my/clipboard-from-windows)) ;; 2. Ubuntu (Wayland) 终端环境(必须同时满足有 wl-copy 且环境变量存在) ((and (getenv "WAYLAND_DISPLAY")       (executable-find "wl-copy")        (executable-find "wl-paste"))  (defun my/clipboard-to-wayland (text &optional push)    (let ((process-connection-type nil))      (with-temp-buffer        (insert text)        (call-process-region (point-min) (point-max) "wl-copy" nil nil nil))))  (defun my/clipboard-from-wayland ()    (string-trim-right     (with-output-to-string       (call-process "wl-paste" nil standard-output nil))))  (setq interprogram-cut-function 'my/clipboard-to-wayland)  (setq interprogram-paste-function 'my/clipboard-from-wayland)) ;; 3. Ubuntu (X11) 终端环境(备用方案,针对非 Wayland 环境) ((and (getenv "DISPLAY")       (executable-find "xclip"))  (defun my/clipboard-to-x11 (text &optional push)    (let ((process-connection-type nil))      (with-temp-buffer        (insert text)        (call-process-region (point-min) (point-max) "xclip" nil nil nil "-selection" "clipboard"))))  (defun my/clipboard-from-x11 ()    (string-trim-right     (with-output-to-string       (call-process "xclip" nil standard-output nil "-selection" "clipboard" "-o"))))  (setq interprogram-cut-function 'my/clipboard-to-x11)  (setq interprogram-paste-function 'my/clipboard-from-x11)));;设置镜像源;; (setq package-archives;;      '(("melpa" . "https://melpa.org/packages/");;        ("gnu"   . "https://elpa.gnu.org/packages/")))(setq package-archives '(("gnu"    . "https://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")                         ("nongnu" . "https://mirrors.tuna.tsinghua.edu.cn/elpa/nongnu/")                         ("melpa"  . "https://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")))(use-package package  :config  (unless (bound-and-true-p package--initialized)    (package-initialize)))(setq use-package-verbose t      use-package-always-ensure t      use-package-minimum-reported-time 0.01);;通过github下载包;; (unless (package-installed-p 'quelpa);;   (with-temp-buffer;;     (url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el");;     (eval-buffer);;     (quelpa-self-upgrade)));; ;; 关闭自动升级和 verbose(减少启动开销);; (setq quelpa-upgrade-p nil;;       quelpa-verbose nil;;       quelpa-checkout-melpa-p nil);; (quelpa;;  '(quelpa-use-package;;    :fetcher git;;    :url "https://github.com/quelpa/quelpa-use-package.git"));; (require 'quelpa-use-package);; 防止 GC 触发太频繁(use-package benchmark-init  :ensure t  :config  ;; To disable collection of benchmark data after init is done.  (add-hook 'after-init-hook 'benchmark-init/deactivate))(setq gc-cons-threshold (* 128 1024 1024 ))(add-hook 'after-init-hook (lambda () (setq gc-cons-threshold (* 5 1024 1024))));; 最近打开的文件(use-package recentf  :ensure t  ;; Loads after 2 second of idle time.  :defer 2)(use-package nerd-icons  :defer t  :custom  (nerd-icons-font-family "FiraCode Nerd Font")  );;doom主题(use-package doom-themes  :ensure t  :init  :config  (setq doom-themes-enable-bold t    ; if nil, bold is universally disabled        doom-themes-enable-italic nil  ; if nil, italics is universally disabled        )  ;; 加载主题(例如 doom-one)  (load-theme 'doom-tomorrow-night t)  (global-hl-line-mode 1)  (doom-themes-visual-bell-config) ;; 视觉提示“响铃”(visual bell)  );; dire 高亮(use-package diredfl  :ensure t  :defer t  :hook ((dired-mode . diredfl-mode)         (dirvish-directory-view-mode . diredfl-mode))  :config (set-face-attribute 'diredfl-dir-name nil :bold t))(setq dired-free-space nil)(setq dired-listing-switches      "-l --almost-all --human-readable --group-directories-first --no-group")(add-hook 'dired-mode-hook #'dired-hide-details-mode)(use-package dirvish  :ensure t  :config  (setq dirvish-default-layout '(main preview 0.75))  ; 移除 parent 面板  (setq dirvish-mode-line-bar-image-width 0) ; hide the leading bar image  (setq dirvish-mode-line-format        '(:left (sort symlink) :right (omit yank index)))  (setq dirvish-attributes           ; The order *MATTERS* for some attributes        '(vc-state subtree-state nerd-icons git-msg)        dirvish-side-attributes        '(vc-state nerd-icons))  ;; 修复:为 Dirvish 预览缓冲区开启行号  (defun my-dirvish-preview-enable-line-numbers ()    (unless (derived-mode-p 'dirvish-special-preview-mode)      (display-line-numbers-mode 1)))  ;; 将行号函数添加到预览缓冲区的钩子中  (add-hook 'dirvish-preview-setup-hook #'my-dirvish-preview-enable-line-numbers)  :hook (after-init . dirvish-override-dired-mode)  :bind ("C-x C-j" . dirvish));; (use-package nerd-icons-dired;;   :defer t;;   :quelpa (nerd-icons-dired :fetcher github :repo "rainstormstudio/nerd-icons-dired");;   :vc (:url "https://github.com/rainstormstudio/nerd-icons-dired" :rev :newest);;   :after nerd-icons;;   :hook (dired-mode . nerd-icons-dired-mode));;(add-hook 'dired-mode-hook 'nerd-icons-dired-mode);; Enable rich annotations using the Marginalia package(use-package marginalia  ;; Bind `marginalia-cycle' locally in the minibuffer.  To make the binding  ;; available in the *Completions* buffer, add it to the  ;; `completion-list-mode-map'.  :defer t  ;;:quelpa (marginalia :fetcher github :repo "")  :vc (:url "https://github.com/minad/marginalia" :rev :newest)  :bind (:map minibuffer-local-map              ("M-A" . marginalia-cycle))  ;; The :init section is always executed.  :init  ;; Marginalia must be activated in the :init section of use-package such that  ;; the mode gets enabled right away. Note that this forces loading the  ;; package.  (marginalia-mode))(use-package nerd-icons-completion  :after marginalia  :config  (nerd-icons-completion-mode)  (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))(use-package nerd-icons-ibuffer  :ensure t  :config  (setq  nerd-icons-ibuffer-human-readable-size t)  :hook (ibuffer-mode . nerd-icons-ibuffer-mode))(use-package ibuffer :ensure nil  :config  (setq ibuffer-expert t)  (setq ibuffer-display-summary nil)  (setq ibuffer-use-other-window nil)  (setq ibuffer-show-empty-filter-groups nil)  (setq ibuffer-default-sorting-mode 'filename/process)  (setq ibuffer-title-face 'font-lock-doc-face)  (setq ibuffer-use-header-line t)  (setq ibuffer-default-shrink-to-minimum-size nil)  (setq ibuffer-formats        '((mark modified read-only locked " "                (name 40 40 :left :elide) " "                (size 9 -1 :right) " "                (mode 16 16 :left :elide) " "                filename-and-process)          (mark " "                (name 16 -1) " "                filename)))  (setq ibuffer-saved-filter-groups        '(("Main"           ("Directories" (mode . dired-mode))           ("C/C++" (or                     (mode . c++-mode)                     (mode . c++-ts-mode)                     (mode . c-mode)                     (mode . c-ts-mode)                     (mode . c-or-c++-ts-mode)))           ("Devicetree" (or                          (mode . dts-mode)                          ))           ("Python" (or                      (mode . python-ts-mode)                      (mode . c-mode)                      (mode . python-mode)))           ("Build" (or                     (mode . make-mode)                     (mode . makefile-gmake-mode)                     (name . "^Makefile$")                     (mode . change-log-mode)))           ("Scripts" (or                       (mode . shell-script-mode)                       (mode . shell-mode)                       (mode . sh-mode)                       (mode . lua-mode)                       (mode . bat-mode)))           ("Config" (or                      (mode . conf-mode)                      (mode . conf-toml-mode)                      (mode . toml-ts-mode)                      (mode . conf-windows-mode)                      (name . "^\\.clangd$")                      (name . "^\\.gitignore$")                      (name . "^Doxyfile$")                      (name . "^config\\.toml$")                      (mode . yaml-mode)))           ("Web" (or                   (mode . mhtml-mode)                   (mode . html-mode)                   (mode . web-mode)                   (mode . nxml-mode)))           ("CSS" (or                   (mode . css-mode)                   (mode . sass-mode)))           ("JS" (or                  (mode . js-mode)                  (mode . rjsx-mode)))           ("Markup" (or                      (mode . markdown-mode)                      (mode . adoc-mode)))           ("Org" (mode . org-mode))           ("LaTeX" (name . "\.tex$"))           ("Magit" (or                     (mode . magit-blame-mode)                     (mode . magit-cherry-mode)                     (mode . magit-diff-mode)                     (mode . magit-log-mode)                     (mode . magit-process-mode)                     (mode . magit-status-mode)))           ("Apps" (or                    (mode . elfeed-search-mode)                    (mode . elfeed-show-mode)))           ("Claude Code" (and                           (mode . vterm-mode)                           (name . "^\\*claude\\*$")))           ("Fundamental" (or                           (mode . fundamental-mode)                           (mode . text-mode)))           ("Emacs" (or                     (mode . emacs-lisp-mode)                     (name . "^\\*Help\\*$")                     (name . "^\\*Custom.*")                     (name . "^\\*Org Agenda\\*$")                     (name . "^\\*info\\*$")                     (name . "^\\*scratch\\*$")                     (name . "^\\*Backtrace\\*$")                     (name . "^\\*Messages\\*$"))))))  :hook  (ibuffer-mode . (lambda ()                    (ibuffer-switch-to-saved-filter-groups "Main")))  );;tab栏显示buffer;; (use-package centaur-tabs;;   :ensure t;;   :demand;;   :init;;   :config;;   (defun centaur-tabs-hide-tab (x);;     "隐藏特殊 buffer,保留 GUD/GDB buffer.";;     (let ((name (format "%s" x)));;       (cond;;        ;; 保留所有 GDB/GUD 相关 buffer;;        ((string-match-p;;          "^\\*\\(gud\\|gdb\\)" name);;         nil);;        ;; 隐藏 *Messages*、*Async-native-compile-log* 等内部 buffer;;        ((string-prefix-p "*" name) t);;        ;; Magit buffer;;        ((and (string-prefix-p "magit" name);;              (not (file-name-extension name))) t);;        ;;非文件不显示;;        ((not (buffer-file-name x)) t);;        ;; 其他 buffer 显示;;        (t nil))));;   (defun centaur-tabs-buffer-groups ();;     "`centaur-tabs-buffer-groups' control buffers' group rules.";;     (list;;      (cond;;       ((or (string-equal "*" (substring (buffer-name) 0 1));;            (memq major-mode '(magit-process-mode;;                               magit-status-mode;;                               magit-diff-mode;;                               magit-log-mode;;                               magit-file-mode;;                               magit-blob-mode;;                               magit-blame-mode;;                               ))) "Emacs");;       ((memq major-mode '(helpful-mode;;                           help-mode)) "Help");;       (t;;        (centaur-tabs-get-group-name (current-buffer))))));;   (setq centaur-tabs-style "bar";;         centaur-tabs-set-bar 'over;;         centaur-tabs-enable-key-bindings nil;;         centaur-tabs-set-icons t;;         centaur-tabs-icon-type 'nerd-icons;;         centaur-tabs-set-close-button nil;;         centaur-tabs-show-new-tab-button nil;;         centaur-tabs-set-modified-marker t;;         centaur-tabs-modified-marker "M";;         centaur-tabs-cycle-scope 'tabs);;   (centaur-tabs-mode t);;   :bind;;   ("C-<left>" . centaur-tabs-backward);;   ("C-<right>" . centaur-tabs-forward);;   :hook;;   (dired-mode . centaur-tabs-local-mode);;   );; modeline主题(use-package doom-modeline  :ensure t  :custom  (doom-modeline-buffer-file-name-style 'truncate-except-project) ; 更智能的文件名截断  (doom-modeline-env-version t) ; 显示 Python/Rust 版本等  (doom-modeline-major-mode-icon t)  :init (doom-modeline-mode 1));;文件导航栏;; (use-package neotree;;   :defer t;;   :ensure t;;   :bind (("<f8>" . neotree-toggle));;   :config;;   (setq neo-theme 'nerd-icons);;   (setq neo-smart-open t)       ;;  打开时自动跳到当前文件路径;;   (setq neo-show-hidden-files t);;  显示隐藏文件;;   );; ;; neotree buffer 中强制截断长行;; (add-hook 'neo-after-create-hook;;           (lambda (_);;             ;; 不换行,禁用 visual-line(你全局开了的话);;             (visual-line-mode -1);;             (setq-local truncate-lines t);;             ;; 用 “…” 代替右侧的 $ 截断标记;;             (let ((tbl (or buffer-display-table (make-display-table))));;               (set-display-table-slot tbl 'truncation (make-glyph-code ?…));;               (setq-local buffer-display-table tbl))));; ;; 允许 neotree 窗口宽度可调整;; (with-eval-after-load 'neotree;;   (setq neo-window-fixed-size nil))(use-package undo-tree  :ensure t  :init (global-undo-tree-mode)  :config  ;;将undo-tree生成的文件,都写入到~/.emacs.d/.cache,方便管理.  (setq undo-tree-history-directory-alist `(("." . "~/.emacs.d/.cache")))  );; enhancement for amx;; 命令按历史排序(use-package amx  :ensure t  :defer t  :init (amx-mode))(use-package exec-path-from-shell  :ensure t  :init  :config  (when (memq window-system '(mac ns x))    (exec-path-from-shell-initialize)));; Git工具(use-package magit  :ensure t  :defer t  :bind (("C-x g" . magit-status))  )(use-package markdown-mode  :ensure t  :defer t  :mode ("\\.md\\'" . markdown-mode)  :init (setq markdown-command "pandoc")  ;; 额外添加 README/readme 等文件的关联  (add-to-list 'auto-mode-alist '("README\\'" . markdown-mode))  (add-to-list 'auto-mode-alist '("readme\\'" . markdown-mode))  ;; 可选:也支持 README.md, Readme.md 等大小写变体  (add-to-list 'auto-mode-alist '("[Rr]eadme\\(?:\\.md\\)?\\'" . markdown-mode)))(use-package dts-mode  :ensure t  :defer t  );; 语法解析(use-package tree-sitter  :ensure t  ;; :when (and (fboundp 'treesit-available-p)  ;;            (treesit-available-p))  :config  (setq treesit-font-lock-level 4)  ;;:init  (setq treesit-language-source-alist        '((bash       . ("https://github.com/tree-sitter/tree-sitter-bash" "v0.20.0"))          (c          . ("https://github.com/tree-sitter/tree-sitter-c" "v0.21.3"))          (cpp        . ("https://github.com/tree-sitter/tree-sitter-cpp"))          (python     . ("https://github.com/tree-sitter/tree-sitter-python"))          (rust       . ("https://github.com/tree-sitter/tree-sitter-rust"))          (toml       . ("https://github.com/tree-sitter/tree-sitter-toml"))          (elisp      . ("https://github.com/Wilfred/tree-sitter-elisp"))          (cmake      . ("https://github.com/uyha/tree-sitter-cmake"))          (dockerfile . ("https://github.com/camdencheek/tree-sitter-dockerfile"))          (make       . ("https://github.com/alemuller/tree-sitter-make"))          (yaml       . ("https://github.com/ikatyang/tree-sitter-yaml"))          (json       . ("https://github.com/tree-sitter/tree-sitter-json"))          (java       . ("https://github.com/tree-sitter/tree-sitter-java"))	  (html       . ("https://github.com/tree-sitter/tree-sitter-html"))	  (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript"))	  (css        . ("https://github.com/tree-sitter/tree-sitter-css"))	  (go         . ("https://github.com/tree-sitter/tree-sitter-go"))          ))  ;;没有内置<languate>-mode的需要添加  (add-to-list 'auto-mode-alist '("\\.c\\.[^/]*\\'" . c-ts-mode))  (add-to-list 'auto-mode-alist '("\\.include\\.[^/]*\\'" . c-ts-mode))  (add-to-list 'auto-mode-alist '("\\.y[a]?ml\\'" . yaml-ts-mode))  (add-to-list 'auto-mode-alist '("\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" . dockerfile-ts-mode))  (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-ts-mode))  (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))  (add-to-list 'auto-mode-alist '("\\.js\\'" . js-ts-mode))  );; 安装 tree-sitter 语法解析器(仅 Emacs 29+)(run-with-idle-timer 3 nil  ; 启动后3秒空闲时执行                     (lambda ()                       (dolist (lang '(bash c cpp python rust toml elisp cmake dockerfile make yaml json java html javascript css go))                         (unless (treesit-language-available-p lang)                           (treesit-install-language-grammar lang)))));; 优先使用 Tree-sitter mode(setq major-mode-remap-alist      '((bash-mode        . bash-ts-mode)        (c-mode           . c-ts-mode)        (c++-mode         . c++-ts-mode)        (python-mode      . python-ts-mode)        ;;(rust-mode        . rust-ts-mode)        (conf-toml-mode   . toml-ts-mode)        (elisp-mode       . elisp-ts-mode)        (cmake-mode       . cmake-ts-mode)        ;;(dockerfile-mode  . dockerfile-ts-mode)        (json-mode        . json-ts-mode)        (java-mode        . java-ts-mode)        ;;(yaml-mode        . yaml-ts-mode)        (makefile-mode    . makefile-ts-mode)        (mhtml-mode       . html-ts-mode)	(html-mode        . html-ts-mode)        ;;(js-mode          . js-ts-mode)        (css-mode         . css-ts-mode)        ;;(go-mode          . go-ts-mode)	));; 设置 C/C++ 模式的缩进为 8 个空格(defun my-c-cpp-indent-setup ()  "Customize C/C++ mode."  (setq c-ts-mode-indent-offset 8)        ;; 缩进单位为 8  (setq c-ts-mode-indent-style 'linux))(dolist (hook '(c-mode-hook                c++-mode-hook                c-ts-mode-hook                c++-ts-mode-hook))  (add-hook hook #'my-c-cpp-indent-setup));; lsp语言服务器配置(use-package eglot  :ensure t  :defer 1  :config  (setq eglot-server-programs        '(((c-mode-hook c++-mode-hook c++-ts-mode c-ts-mode)           . ("clangd"              ;; "-j=4"              "--enable-config"              "--background-index"              ;; "--background-index-priority=low"              "--clang-tidy"              "--completion-style=detailed"              "--ranking-model=decision_forest"              "--header-insertion=never"              ;; "--all-scopes-completion"              "--pretty"              ;; "--fallback-style=none"              ;;"--query-driver=aarch64-linux-gnu-*"              ;;"--query-driver=gcc,g++"              "--query-driver=/usr/bin/g++,/usr/bin/gcc"              ))          ((dts-mode)                                  . ("devicetree-language-server" "--stdio"))          ((rust-mode rust-ts-mode)                    . ("rust-analyzer" :initializationOptions                                                          (:cargo (:buildScripts (:enable t))                                                                  :procMacro (:enable t))))          ((python-mode python-ts-mode)                . ("pyright-langserver" "--stdio"))          ;; ((bash-mode bash-ts-mode sh-mode sh-ts-mode) . ("bash-language-server" "start"))          ;; ((toml-mode toml-ts-mode)                    . ("taplo" "lsp" "stdio"))          ;; ((yaml-mode yaml-ts-mode)                    . ("yaml-language-server" "--stdio"))          ;; ((markdown-mode markdown-ts-mode)            . ("marksman"))          ))  ;; 关闭lsp自动格式化  (setq eglot-ignored-server-capabilities '(:documentOnTypeFormattingProvider))  );;自动打开eglot(dolist (hook '(c-mode-hook c-ts-mode-hook c++-mode-hook c++-ts-mode-hook                            dts-mode-hook                            rust-mode-hook rust-ts-mode-hook                            python-mode-hook python-ts-mode-hook                            ;;bash-mode-hook bash-ts-mode-hook                            ;;sh-mode-hook sh-ts-mode-hook                            ;; markdown-mode-hook markdown-ts-mode-hook                            ;; toml-mode-hook toml-ts-mode-hook                            ;; yaml-mode-hook yaml-ts-mode-hook			    ))  (add-hook hook 'eglot-ensure));; eglot快捷键(global-set-key (kbd "M-,") 'xref-find-definitions)  ;; 跳转到定义(global-set-key (kbd "M-.") 'xref-pop-marker-stack)  ;; 跳回(global-set-key (kbd "M-?") 'xref-find-references)   ;; 查找引用;; comment(defun my-cpp-line-comments ()  "Use // comments instead of /* */ in C/C++."  (setq-local comment-start "// "              comment-end ""              comment-start-skip "//+\\s-*"))(dolist (hook '(c-mode-hook c++-mode-hook c-ts-mode-hook c++-ts-mode-hook                            rust-mode-hook rust-ts-mode-hook python-mode-hook python-ts-mode-hook java-mode-hook java-ts-mode-hook))  (add-hook hook #'my-cpp-line-comments))(use-package yasnippet  :ensure t  :hook (after-init . yas-global-mode)  :config  ;; 可选:设置 snippet 目录(默认已包含 ~/.emacs.d/snippets)  ;; (setq yas-snippet-dirs '("~/.emacs.d/snippets"))  );; 自动补全(use-package company  :defer 1  :ensure t  :hook (after-init . global-company-mode)  :config  ;; 光标停留 0 秒立即弹出补全  (setq company-idle-delay 0)  ;; 后端  (setq company-backends '((company-capf :with company-yasnippet)                           company-keywords                           company-files))  ;; 最少 1 个字符触发补全,0 表示空白处也可以触发  (setq company-minimum-prefix-length 1)  ;; 补全候选最多显示 30 个  (setq company-tooltip-limit 30)  (setq eldoc-idle-delay 0.3)  ;; GDB配置  (add-hook 'gud-mode-hook (lambda () (company-mode -1))) ;; gud模式下禁用 company  ;; 在 eshell 模式下禁用 company-mode  (add-hook 'eshell-mode-hook (lambda () (company-mode -1)))  );; 格式化(use-package format-all  :ensure t  :defer t  :commands format-all-mode  ;; :hook (prog-mode . format-all-mode) ;; 禁用自动保存格式化  :config  (setq-default format-all-formatters                '(("C" (clang-format))                  ("C++"     (clang-format))                  ;; ("Java" (clang-format))                  ("Rust" (rustfmt))                  ("JavaScript" (prettier))                  ("Markdown" (prettier))                  ("YAML" (prettier))                  ;;("TOML" (taplo-fmt))                  ;;("Devicetree" (dtsfmt))                  )))(global-set-key (kbd "C-x f") 'format-all-buffer);; claude code;; install required inheritenv dependency:(use-package inheritenv  :vc (:url "https://github.com/purcell/inheritenv" :rev :newest))(use-package monet  :vc (:url "https://github.com/stevemolitor/monet" :rev :newest));; for vterm terminal backend:(use-package vterm :ensure t);; install claude-code.el(use-package claude-code :ensure t  :vc (:url "https://github.com/stevemolitor/claude-code.el" :rev :newest)  :config  ;; optional IDE integration with Monet  (add-hook 'claude-code-process-environment-functions #'monet-start-server-function)  (monet-mode 1)  (setq claude-code-terminal-backend 'vterm)  (claude-code-mode)  :bind-keymap ("C-c c" . claude-code-command-map)  ;; Optionally define a repeat map so that "M" will cycle thru Claude auto-accept/plan/confirm modes after invoking claude-code-cycle-mode / C-c M.  :bind  (:repeat-map my-claude-code-map ("M" . claude-code-cycle-mode)));; which-key 显示键绑定提示(use-package which-key  :ensure t  :defer t  :config  (which-key-mode));; 窗格切换(use-package ace-window  :ensure t  :defer t  :bind (("M-o" . ace-window)));; 窗格移动(use-package buffer-move  :ensure t  :defer t  :bind (("C-c <up>"    . buf-move-up)         ("C-c <down>"  . buf-move-down)         ("C-c <left>"  . buf-move-left)         ("C-c <right>" . buf-move-right)));; 智能按键C-a C-c k(use-package crux  :ensure t  :defer t  :bind (("C-a" . 'crux-move-beginning-of-line)         ("C-c k" . 'crux-smart-kill-line)));; 预览要跳转的行(use-package goto-line-preview  :ensure t  :defer t  :bind (("M-g g" . goto-line-preview)));;代码整行上移下移(use-package move-dup  :ensure t  :defer t  :bind (("C-M-p"   . move-dup-move-lines-up)         ;;    ("C-M-p" . move-dup-duplicate-up)         ("C-M-n"   . move-dup-move-lines-down)         ;;    ("C-M-n" . move-dup-duplicate-down)         ));; 项目识别,通过创建.projectile文件识别为一个项目(setq project-find-functions nil)(use-package projectile  :ensure t  ;;:init  ;; :bind-keymap  ;; ("C-c p" . projectile-command-map)  :config  (projectile-mode +1)  (setq projectile-enable-caching t)  (setq projectile-project-search-path '("~/repository"))  (setq projectile-completion-system 'auto) ;; 或 ivy / helm / default  (use-package rg    :defer t    :ensure t))(use-package multiple-cursors  :ensure t  :config  (global-set-key (kbd "C-c m") 'mc/mark-all-dwim));; 快捷键定义必须放在后面否则容易被其他插件覆盖;; next error(global-set-key (kbd "M-n") #'flymake-goto-next-error)(global-set-key (kbd "M-p") #'flymake-goto-prev-error);; 快捷键绑定:使用调整窗口大小(global-set-key (kbd "M-<up>")    'enlarge-window)(global-set-key (kbd "M-<down>")  'shrink-window)(global-set-key (kbd "M-<left>")  'shrink-window-horizontally)(global-set-key (kbd "M-<right>") 'enlarge-window-horizontally);;撤销(global-set-key (kbd "C-/") 'undo-only);;全局搜索(global-set-key (kbd "C-c C-s") 'projectile-ripgrep)(defun k-insert-timestamp ()  (interactive)  (insert (format-time-string "%Y-%m-%d %H:%M")))(defun k-insert-date ()  (interactive)  (insert (format-time-string "%Y-%m-%d")))(global-set-key (kbd "C-c t") 'k-insert-timestamp)(global-set-key (kbd "C-c d") 'k-insert-date)(global-unset-key (kbd "C-x C-b"))(global-set-key (kbd "C-x C-b") 'ibuffer)(global-set-key (kbd "TAB") 'tab-to-tab-stop)(global-set-key (kbd "C-x k")                (lambda ()                  (interactive)                  (kill-this-buffer)))(add-hook 'prog-mode-hook          (lambda ()            (local-set-key (kbd "C-c p") #'flymake-show-buffer-diagnostics) ;; problem            (local-set-key (kbd "C-c f") #'eglot-code-actions))) ;; fix(custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(package-selected-packages nil) '(package-vc-selected-packages   '((claude-code :url "https://github.com/stevemolitor/claude-code.el"))))(custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. )

Keyboard shortcut configuration overview

“C” in Emacs meansCtrl

“M” in Emacs meansAlt

ShortcutFunction descriptionSource configuration
C-/Undo (undo-only)Manual binding
M-<up>Increase current window heightManual binding
M-<down>Decrease current window heightManual binding
M-<left>Decrease current window widthManual binding
M-<right>Increase current window widthManual binding
C-<left>Switch to previous tab (Centaur Tabs)centaur-tabs
C-<right>Switch to next tabcentaur-tabs
M-g gPreview jump to specified line (goto-line-preview)goto-line-preview
M-C-pMove current line upmove-dup
M-C-nMove current line downmove-dup
M-pNext errorflymake
M-nPrevious errorflymake
C-c pShow all errorsflymake
C-c fFix code using lsp (eglot-code-actions)eglot
C-x C-jOpen file browser (dirvish)dirvish
C-x C-fFind file and openBuilt-in
C-x C-bOpen buffer browserIbuffer
C-x gmagit statusmagit
C-x fFormat current buffer (clang-format / rustfmt)format-all
M-,Jump to definition (xref-find-definitions, requires LSP support)Manual binding
M-.Jump back to previous position (xref-pop-marker-stack)Manual binding
M-?Find references (xref-find-references, requires LSP support)Manual binding
M-oSwitch focus between windowsace-window
C-c <up>Move current buffer up to another windowbuffer-move
C-c <down>Move current buffer down to another windowbuffer-move
C-c <left>Move current buffer left to another windowbuffer-move
C-c <right>Move current buffer right to another windowbuffer-move
C-aSmart move cursor to beginning of line (press again to return to the start of the code)crux
C-c kSmart delete a line (preserves indentation)crux
C-x SPCRectangular selection mode, allows selecting specific columnsBuilt-in
M-<Move to beginning of bufferBuilt-in
M->Move to end of bufferBuilt-in
C-c tInsert timestampManual binding
C-c dInsert dateManual binding
C-x uOpen undo-treeundo-tree
  • M-X projectile-ripgrep Global search with ripgrep
  • C-c C-s Global search in the project
  • M-x recenter Center the current line in the window
  • M-x eglot-rename Rename symbol while programming
  • M-x man, then enter the function to search for, e.g.shmget(2), here 2 means search for syscall, then in*Man*In the buffer, use:
    • M-n → Next man page
    • M-p → Previous man page

buffer-menu

You can use the following keys:

KeyFunction
EnterorfSwitch to the buffer on the current line
oSwitch to that buffer and keep*Buffer List*
dMark this buffer as ‘to be deleted’ (not deleted immediately)
xActually deleteAll marked buffers
sSave this buffer (if modified)
uUnmark (if previously pressedd
qShutdown*Buffer List*Window
gRefresh list (reload latest status)

After pressing d to mark for deletion, press x to actually delete

magit

Magit’s design philosophy is:One key = one action

KeyFunction
sStage The file/region under the current cursor (equivalent togit add
uUnstage(Unstage)
cCommit(Commit) → then presscAcknowledge
PPush Push to remote
FFetch Pull updates from remote
pPull(Pull and merge)
bBranch operations (create/switch/merge)
lview log(Commit history)
LView the log with graph (likegit log --graph
dDiff View changes
=On a commit, press=View the diff of that commit
qQuit Close the current Magit buffer

⚠️ Note: These commands are only valid in the Magit status buffer (*magit: xxx*)!

After pressing a key, press Ctrl-g to cancel

Programming settings

For projects with a Makefile, you can use bear to generate compile_command.json for clangd to index.

123456
# Create in the project root directory to identify this as a project.touch .projectile# Generate compile_command.jsonmake cleanbear -- make

For Linux kernel-related settings, refer to

.clang-format configuration

Directly uses the Linux Kernel configuration, but uses spaces instead of TAB, and ColumnLimit is increased to 100.

.clang-format
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
# SPDX-License-Identifier: GPL-2.0## clang-format configuration file. Intended for clang-format >= 11.## For more information, see:##   Documentation/dev-tools/clang-format.rst#   https://clang.llvm.org/docs/ClangFormat.html#   https://clang.llvm.org/docs/ClangFormatStyleOptions.html#---AccessModifierOffset: -4AlignAfterOpenBracket: AlignAlignConsecutiveAssignments: falseAlignConsecutiveDeclarations: falseAlignEscapedNewlines: LeftAlignOperands: trueAlignTrailingComments: falseAllowAllParametersOfDeclarationOnNextLine: falseAllowShortBlocksOnASingleLine: falseAllowShortCaseLabelsOnASingleLine: falseAllowShortFunctionsOnASingleLine: NoneAllowShortIfStatementsOnASingleLine: falseAllowShortLoopsOnASingleLine: falseAlwaysBreakAfterDefinitionReturnType: NoneAlwaysBreakAfterReturnType: NoneAlwaysBreakBeforeMultilineStrings: falseAlwaysBreakTemplateDeclarations: falseBinPackArguments: trueBinPackParameters: trueBraceWrapping:  AfterClass: false  AfterControlStatement: false  AfterEnum: false  AfterFunction: true  AfterNamespace: true  AfterObjCDeclaration: false  AfterStruct: false  AfterUnion: false  AfterExternBlock: false  BeforeCatch: false  BeforeElse: false  IndentBraces: false  SplitEmptyFunction: true  SplitEmptyRecord: true  SplitEmptyNamespace: trueBreakBeforeBinaryOperators: NoneBreakBeforeBraces: CustomBreakBeforeInheritanceComma: falseBreakBeforeTernaryOperators: falseBreakConstructorInitializersBeforeComma: falseBreakConstructorInitializers: BeforeCommaBreakAfterJavaFieldAnnotations: falseBreakStringLiterals: falseColumnLimit: 100CommentPragmas: "^ IWYU pragma:"CompactNamespaces: falseConstructorInitializerAllOnOneLineOrOnePerLine: falseConstructorInitializerIndentWidth: 8ContinuationIndentWidth: 8Cpp11BracedListStyle: falseDerivePointerAlignment: falseDisableFormat: falseExperimentalAutoDetectBinPacking: falseFixNamespaceComments: falseIncludeBlocks: PreserveIncludeCategories:  - Regex: ".*"    Priority: 1IncludeIsMainRegex: "(Test)?$"IndentCaseLabels: falseIndentGotoLabels: falseIndentPPDirectives: NoneIndentWidth: 8IndentWrappedFunctionNames: falseJavaScriptQuotes: LeaveJavaScriptWrapImports: trueKeepEmptyLinesAtTheStartOfBlocks: falseMacroBlockBegin: ""MacroBlockEnd: ""MaxEmptyLinesToKeep: 1NamespaceIndentation: NoneObjCBinPackProtocolList: AutoObjCBlockIndentWidth: 8ObjCSpaceAfterProperty: trueObjCSpaceBeforeProtocolList: true# Taken from git's rulesPenaltyBreakAssignment: 10PenaltyBreakBeforeFirstCallParameter: 30PenaltyBreakComment: 10PenaltyBreakFirstLessLess: 0PenaltyBreakString: 10PenaltyExcessCharacter: 100PenaltyReturnTypeOnItsOwnLine: 60PointerAlignment: RightReflowComments: falseSortIncludes: falseSortUsingDeclarations: falseSpaceAfterCStyleCast: falseSpaceAfterTemplateKeyword: trueSpaceBeforeAssignmentOperators: trueSpaceBeforeCtorInitializerColon: trueSpaceBeforeInheritanceColon: trueSpaceBeforeParens: ControlStatementsExceptForEachMacrosSpaceBeforeRangeBasedForLoopColon: trueSpaceInEmptyParentheses: falseSpacesBeforeTrailingComments: 1SpacesInAngles: falseSpacesInContainerLiterals: falseSpacesInCStyleCastParentheses: falseSpacesInParentheses: falseSpacesInSquareBrackets: falseStandard: Cpp03TabWidth: 8UseTab: false

Run Emacs as a daemon

systemd

Requires systemd

12
systemctl --user enable --now emacsemacsclient file.txt

Shell

12
emacs --daemonemacsclient file.txt

After finishing editing, press Ctrl+x, then #Exit, Emacs will mark that buffer as completed, and then emacsclient will exit. If no other buffers are in use, the LSP (e.g., clangd) started by that buffer will also exit.

And if you pressCtrl+xquit, and then c, Emacs will think this buffer cannot be closed yet.

Loading comments…