Reference

<doom/help-modules> 绑定到
<doom/delete-this-file> 绑定到
<doom/reload> 不用重启 emacs 就能刷新个人配置的更新
<doom/restart>
<doom/restart-and-restore>

<doom/open-scratch-buffer>

doom/help*

<doom/help-modules>
<doom/help-packages>

Keybinding Management

which-key

which-key 现已包含在 Emacs 的主分支中,并可能随 Emacs v30 发布。
which-key 的 Bug 报告和贡献现在将通过标准的 Emacs 渠道进行处理,此仓库将被存档。

目前 doom 貌似没有支持 官方的which-key

Session Management

<doom/quicksave-session>
<doom/quickload-session>
<doom/save-session>
<doom/load-session>

我有一个问题就是,这些 session 多久会被删除?

Projects Management

file
的依赖
projectile 将会被弃用

我想要知道它具体的判定规则!

search-project

<+default/search-project>

doom cli

doom bash脚本

它使用了 :; 技巧,把两种语言(shell 和 emacs lisp)的脚本放到一个文件里了

doom-cli.el

link

Others’ Doom Emacs Config

在这里放的是基于 doomemacs 的 emacs 配置
对于 vanilla emacs 的配置放在 Others’ Emacs Config

hlissner’s .doom.d

tecosaur’s Doom Emacs Configuration

这不只是一个配置!
我应该能学到很多东西

Emacs can be thought of as a platform within which various elements of your workflow may settle, with the potential for rich integrations between them — a life IDE if you will.

Official Modules

:emacs

vc

其实叫 git 更好,本质还是 git 的更优秀的集成

git-timemachine
<+vc/browse-at-remote>
<+vc/browse-at-remote-kill>
<+vc/browse-at-remote-homepage>
<+vc/browse-at-remote-kill-homepage>

undo

使用了 undo-fuvundo

还有一个 undo-fu-session 是和 undo-fu 配合的

:tools

magit

majutsu

这是我打算写的 majutsu 预设

tree-sitter

它有一个 treesit 分支,准备完全替代掉 elisp-tree-sitter
上次提交是在 5 月,作者还在努力中

[2025-09-04 Thu] 现在已经合并到主分支了!
Comparing b1826a0c6469f57b377b08ef7d54005504b12d59…26a5ad72e161f53151e78580…

biblio

<:tools biblio>

pass

  • pass.el

    • TODO 我打算做 org-roam 和 pass.el 的集成

      我想要实现的功能是
      自动收集所有有 pass 标签(非继承)的节点
      在下面查 pass_key 属性
      然后显示的时候可以显示节点的 olp,
      然后之后再用 pass_key 对应的条目下选一遍字段

      我觉得相当不错

debugger

用的是 dape

:ui

临时 window
非常好用的功能!

  • Chat: 和我解释一下我应该如何理解这个 doom module,如何使用它

    这个 Doom Emacs 模块是用来“驯服临时窗口”的:把各类不那么重要、短暂查看的缓冲区(Help、Completions、编译输出、Org capture 等)统一当作 popup,在侧边打开、按 ESC/C-g 一键关闭、需要时可恢复,并且能自动清理你标记为“短暂”的缓冲区。

    如何理解与启用

    • 在 init.el 的 doom! 中启用 :ui popup;可选加旗标:
      • +defaults:启用一组合理的默认规则(常见 Help/Completions 等)。
      • +all:兜底,把名称以空格或星号开头的“特殊缓冲区”都视为 popup。
    • 核心原理:通过 display-buffer-alist 定规则,拦截 display-buffer 的行为,把匹配的缓冲区以指定方式在侧窗显示。少数包若用 switch-to-buffer/switch-to-window 会绕过它(README 里提到 org 有额外兼容)。

    常用操作

    • C-x p:在普通窗口与 popup 窗口之间切换(+popup/other)。
    • 还有:+popup/toggle、+popup/close、+popup/close-all、+popup/restore、+popup/raise 等命令可用(可自行绑键)。
    • 在 popup 中按 ESC 或 C-g 通常会关闭它(受 :quit 规则影响)。

    如何写规则

    • 用 set-popup-rule! 或 set-popup-rules! 在 $DOOMDIR/config.el 定义匹配规则。按缓冲区名(正则)或谓词匹配。
    • 关键参数(简要):
      • :side ‘left/‘right/‘above/‘below:在哪一侧开窗。
      • :size/:width/:height:窗口大小(比例或像素/列行)。
      • :select t:打开后选中该窗口。
      • :quit t:允许用 ESC/C-g 关闭。
      • :ttl:控制自动销毁缓冲区的“存活时间”:
        • 0 立即杀掉(关闭时立刻 kill-buffer)。
        • 数字 N 表示在 N 秒后自动杀掉。
        • t 表示不自动杀(持久)。
      • :slot/:vslot:在侧窗口里的排序位置。
      • :modeline t/nil:是否显示模式行(默认隐藏,可覆盖)。
      • 其他 ACTIONS/PARAMETERS 会透传到 display-buffer 的动作与参数。
    • 示例(可直接粘到 config.el):
      • 基础多条规则:
            (set-popup-rules!
             '(("^ \\*" :slot -1)               ; 兜底:特殊缓冲区
               ("^\\*" :select t)
               ("^\\*Completions" :slot -1 :ttl 0)
               ("^\\*$?:scratch\\|Messages$" :ttl t)
               ("^\\*Help" :slot -1 :size 0.2 :select t)
               ("^\\*doom:" :size 0.35 :select t :modeline t :quit t :ttl t)))
      • 给 Help/compile 放在底部、可 ESC 关闭:
            (set-popup-rule! "^\\*Help" :side 'bottom :size 0.25 :select t :quit t)
            (set-popup-rule! "^\\*compilation\\*" :side 'bottom :size 0.25 :quit t :ttl 5)
      • 给 Org capture 做成右侧持久窗:
            (set-popup-rule! "^\\*Org Capture\\*" :side 'right :width 0.4 :select t :ttl t)

    配置细节

    • 默认 popup 隐藏 mode-line,如需显示:
      • 全局改默认: (plist-put +popup-defaults :modeline t)
      • 或完全禁用 mode-line 管理: (remove-hook ‘+popup-buffer-mode-hook #‘+popup-set-modeline-on-enable-h)
    • 宏与函数:
      • without-popups!:在一段代码里暂时禁用 popup 管理。
      • save-popups!:暂存并恢复当前 popup 状态。
      • +popup-window-p / +popup-buffer-p 等可在自定义逻辑里判断。

    注意与排错

    • 规则顺序很重要;越具体的规则应放在前面。
    • 有些包用 switch-to-buffer 绕过规则(尤其 org 的部分场景),README 已做了一些兼容;若仍无效,尝试为该包的命令写专门规则,或查其显示函数。
    • 用 M-: (pp display-buffer-alist) 查看当前规则是否已生效。
    • 若希望“所有特殊缓冲区都侧开”,启用 +all 作为兜底。

    总之:启用 :ui popup →(可选)+defaults/+all → 在 config.el 写 set-popup-rule!/set-popup-rules! → 用 C-x p 和相关命令管理 → 按需调大小、侧边、是否可一键关闭与是否自动清理。这样就能把临时窗口的体验统一、可控。

workspace

突然发现这东西很好用 使用的前缀是 详见

依赖的是 persp-mode 这个包

完全符合我的想象!
他们的 buffer 共享策略是这样的
不显示其他 workspace 的 buffer
则显示其他 workspace 的 buffer

和 doom 自带的 session 管理不能兼容…
也就是不能 save 和 load,那这有点难受了

smooth-scroll

使用的是 ultra-scrollgood-scroll.el

平滑滚动的逻辑和我习惯的不一样,所以我自己写了一个 neoscroll.el

现在已经弃用了,自适应了

treemacs

  • 突然发现可以直接跳到 org 文件的标题

    但是刚才出现了这个报错
    [Treemacs] Something went wrong when finding tag ‘long form’: (wrong-type-argument integer-or-marker-p nil)

    暂时没有发现什么特殊的触发条件

vc-gutter

实际的依赖是

有一个很好用的 <+vc-gutter/next-hunk>

:app

calendar

用的是


用的是 https://github.com/kiwanami/emacs-calfw

everywhere

这是 tecosaur 写的模块

理所当然地正在等待 wayland support
tecosaur/emacs-everywhere#50 Wayland support

IRC

使用的是 circe 这个包

我暂时还没搞懂 irc 到底是怎么连的

:editor

multiple-cursors

<:editor multiple-cursors>

  • gzz to toggle new (frozen) cursors at point.
  • gzt to toggle mirroring on and off (or switch to insert mode to activate
    them).
  • gzA to place cursors at the end of each selected line.
  • gzI will place them at the beginning.

我的评价就完全没法用,多选下的 x 然后 p 一下直接没了,只会粘贴一个

snippet

:lang

org

他终于把 org-roam v1 移除了
https://github.com/doomemacs/doomemacs/commit/d92883bff8ff5457faa09b41a1e8e404c3693594

:email mu4e

mu4e
<:email mu4e> 这里的文档应该算挺全的了

我应该使用 <set-email-account!> 吗?

:ui workspace 合作的有一个问题

退出的时候他会直接删除那个 workspace
需要注意在打开一个 window 的时候,不要退出

profiles管理

想要给 meow 开一个profile,结果出现了问题

󰄛 ❯  doom sync --profile meow
Error: Failed to load Doom from /home/_WD_/.config/emacs/early-init.el

搞不懂了

doom —doomdir ~/.config/doom-meow sync
这是有用的

最后放弃了

内置宏

map!

我已完全掌握!

在这里贴上文档

“A convenience macro for defining keybinds, powered by `general’.

If evil isn’t loaded, evil-specific bindings are ignored.

Properties
:leader […] an alias for (:prefix doom-leader-key …)
:localleader […] bind to localleader; requires a keymap
:mode [MODE(s)] […] inner keybinds are applied to major MODE(s)
:map [KEYMAP(s)] […] inner keybinds are applied to KEYMAP(S)
:prefix [PREFIX] […] set keybind prefix for following keys. PREFIX
can be a cons cell: (PREFIX . DESCRIPTION)
:prefix-map [PREFIX] […] same as :prefix, but defines a prefix keymap
where the following keys will be bound. DO NOT
USE THIS IN YOUR PRIVATE CONFIG.
:after [FEATURE] […] apply keybinds when [FEATURE] loads
:textobj KEY INNER-FN OUTER-FN define a text object keybind pair
:when [CONDITION] […]
:unless [CONDITION] […]

Any of the above properties may be nested, so that they only apply to a
certain group of keybinds.

States
:n normal
:v visual
:i insert
:e emacs
:o operator
:m motion
:r replace
:g global (binds the key without evil `current-global-map’)

These can be combined in any order, e.g. :nvi will apply to normal, visual and
insert mode. The state resets after the following key=>def pair. If states are
omitted the keybind will be global (no emacs state; this is different from
evil’s Emacs state and will work in the absence of `evil-mode’).

These must be placed right before the key string.

Do
(map! :leader :desc \“Description\” :n \“C-c\” #‘dosomething)
Don’t
(map! :n :leader :desc \“Description\” \“C-c\” #‘dosomething)
(map! :leader :n :desc \“Description\” \“C-c\” #‘dosomething)“

属性继承规则

(map! :leader               ; 设置 leader 属性
      "a" #'func-a          ; 继承 :leader
 
      :prefix "f"           ; 新增 prefix 属性
      "f" #'find-file       ; 继承 :leader + :prefix "f"
      "r" #'recent-files    ; 继承 :leader + :prefix "f"
 
      :map org-mode-map     ; 新增 map 属性
      "l" #'org-insert-link ; 继承 :leader + :prefix "f" + :map org-mode-map
 
      :prefix "b"           ; 覆盖之前的 prefix
      "b" #'switch-buffer)  ; 继承 :leader + :prefix "b" + :map org-mode-map
  • 状态的特殊性

    状态标记 (:n, :v, :i 等) 有特殊规则:

    (map! :leader
          :n "a" #'func-a      ; normal 模式
          :v "b" #'func-b      ; visual 模式
          "c" #'func-c         ; 全局 (状态重置)
          :nv "d" #'func-d)    ; normal + visual 模式

    关键点:

    • 状态在每个键绑定后 重置
    • 其他属性 持续继承 直到被新值覆盖
    • 嵌套块内的属性只在该块内有效

实际示例

(map! :leader               ; 全局设置
      (:prefix "f"          ; 嵌套块开始
       "f" #'find-file      ; :leader + :prefix "f"
       :n "n" #'new-file)   ; :leader + :prefix "f" + normal 模式
 
      "g" #'magit-status    ; 只继承 :leader,prefix "f" 已结束
 
      :map org-mode-map     ; 新增 map 属性
      "l" #'org-store-link) ; :leader + :map org-mode-map

use-package!

:custom 在有些时候可以替代
:init (setq xx xx)
要求这个变量是一个可以可自定义变量

setq!

<setq!>

setq! 是 Doom Emacs 提供的一个宏,用来“更聪明地”设置可自定义变量(即 Emacs 的 customizable variables)。

它的作用与 setq 类似:批量给变量赋值。但与 setq 和 setopt 有重要区别:

与 setq 不同:setq! 在设置变量时会触发该变量的自定义 setter(即通过 defcustom 定义时的 :set 函数等),因此能正确应用变量的副作用或验证逻辑。setq 只是简单赋值,不会调用这些机制。
与 setopt 不同:setq! 不会为了设置变量而加载相关的自定义库或包,避免不必要的依赖加载,更轻量。
简单理解:

如果你只是给普通变量赋值,用 setq 就行。
如果你要设置的是通过 defcustom 定义的“可自定义变量”,并希望它的 setter/副作用生效,但又不想像 setopt 那样引入额外依赖,建议用 setq!。
用法与 setq 一样: (setq! var1 val1 var2 val2 …)
示例:

(setq! tab-width 4) 会触发 tab-width 的 setter,确保相关行为正确更新。
(setq tab-width 4) 只改变量,不一定更新相关状态。
(setopt tab-width 4) 也会触发 setter,但可能会加载定制相关库;Doom 更推荐用 setq!。

Issues

doomemacs/doomemacs#8003 Failed `doom upgrade` - fatal: the requested upstrea…
我遇到过好多次这个问题了,我还以为是我的网络问题