- 1 课程回顾
- 2 让Emacs的目录变得更加干净
- 3 让Emacs记住一些历史信息
- 3.1 让Emacs记住迷你缓冲区历史信息
- 3.2 让Emacs记住关闭文件时的位置
- 3.3 让Emacs记住最近打开的文件历史
- 4 撤销增强
- 5 自动保存
- 6 crux系统增强
- 7 结语
1 课程回顾 🔗
经过上一节课,我们学习了如何在Emacs里通过Avy快速跳转到屏幕上任何一个字符的位置,通过 multiple-cursors 进行多光标编辑,我们在Emacs里编辑文本的效率大大提升。
本节课,我们将学习如何通过配置,进一步提升Emacs的效率。
2 让Emacs的目录变得更加干净 🔗
我们通过 no-littering 插件将原本放在 .emacs.d
目录下的一些配置信息或动态信息,转移到 etc
或 var
子目录里,让配置目录更加简洁清爽。
(use-package no-littering
:ensure t)
当我们安装配置完这个插件后,我们别忘了,将 第7课:Emacs的补全强化 - Yasnippet模板补全章节 里的 snippets
文件夹移动到 .emacs.d/etc/yasnippet/
文件夹下:
mv ~/.emacs.d/snippets ~/.emacs.d/etc/yasnippet/
现在 .emacs.d
下的目录结构如下:
/Users/randolph/.emacs.d/
├── README.org
├── early-init.el
├── elpa
├── etc
│ ├── gnus
│ └── yasnippet
│ └── snippets
├── init.el
├── lisp
│ ├── init-base.el
│ ├── init-completion.el
│ ├── init-edit.el
│ ├── init-org.el
│ ├── init-tools.el
│ └── init-ui.el
└── var
├── auto-save
├── eww
├── gnus
├── org
├── recentf-save.el
├── save-place.el
└── savehist.el
...
3 让Emacs记住一些历史信息 🔗
我们打开一些文件,输入一些命令,这些命令的历史都是数据,而数据都是有价值的,一个最浅显的价值就是通过让Emacs记住一些历史信息,让我们直接从历史信息中再次执行。
3.1 让Emacs记住迷你缓冲区历史信息 🔗
我们通过Emacs自带的 savehist
插件,来记住迷你缓冲区的历史,如执行过的命令等。在设置这个插件之前,无论何时,我们按下 M-x
显示的命令都是一样的:
我们来配置一下 savehist
:
(use-package savehist
:ensure nil
:hook (after-init . savehist-mode)
:config
;; Allow commands in minibuffers, will affect `dired-do-dired-do-find-regexp-and-replace' command:
(setq enable-recursive-minibuffers t)
(setq history-length 1000)
(setq savehist-additional-variables '(mark-ring
global-mark-ring
search-ring
regexp-search-ring
extended-command-history))
(setq savehist-autosave-interval 300))
当我们配置完这个插件并开启了 savehist-mode
,我们先随便执行一些命令,然后我们再次按下 M-x
可以看到我们最新执行过的命令已经排在了最上面,如果我们短时间内还需要再执行一次该命令的话,只需要按下 C-n
或 C-p
来移动光标即可,非常方便:
3.2 让Emacs记住关闭文件时的位置 🔗
我们通过Emacs自带的 save-place
插件,来记住每个文件关闭时光标所在的位置,当我们再次打开这个文件时,自动跳转到记住的位置。
;; 自动记住每个文件的最后一次访问的光标位置
(use-package saveplace
:ensure nil
:hook (after-init . save-place-mode))
我们在设置这个插件之前,我们每次进入 emacs-config.org
文件时,都是下面这样的:
此时,如果我们打开了 save-place-mode
,并将光标移动到某一个标题行,然后关闭这个文件,我们再次打开这个文件时,光标会自动跳转到关闭时的位置,非常方便:
3.3 让Emacs记住最近打开的文件历史 🔗
我们通过Emacs自带的 recentf
插件,来记住Emacs最近打开的文件历史。
(use-package recentf
:ensure nil
:defines no-littering-etc-directory no-littering-var-directory
:hook (after-init . recentf-mode)
:custom
(recentf-max-saved-items 300)
(recentf-auto-cleanup 'never)
;; `recentf-add-file' will apply handlers first, then call `string-prefix-p'
;; to check if it can be pushed to recentf list.
(recentf-filename-handlers '(abbreviate-file-name))
(recentf-exclude `(,@(cl-loop for f in `(,package-user-dir
,no-littering-var-directory
,no-littering-etc-directory)
collect (abbreviate-file-name f))
;; Folders on MacOS start
"^/private/tmp/"
"^/var/folders/"
;; Folders on MacOS end
".cache"
".cask"
".elfeed"
"elfeed"
"bookmarks"
"cache"
"ido.*"
"persp-confs"
"recentf"
"undo-tree-hist"
"url"
"^/tmp/"
"/ssh\\(x\\)?:"
"/su\\(do\\)?:"
"^/usr/include/"
"/TAGS\\'"
"COMMIT_EDITMSG\\'")))
配置完这个插件,我们再次按下 C-x C-f
打开文件时,可以看到我们最近打开的目录和文件都排在了最上面,我们可以通过移动光标来快速选择,非常方便:
事实上,当我们按下 C-x b
键切换buffer时(对应的 consult-buffer
命令),我们也可以看到最近打开的文件历史也列了出来:
事实上,我们可以到 ~/.emacs.d/var/
目录下,看到 savehist.el
, save-place.el
, recentf-save.el
, 分别对应着上面三个插件的记录文件,里面记录着一些历史信息:
;;; Automatically generated by ‘recentf’ on Mon Jan 9 22:06:19 2023.
(setq recentf-list
'(
"~/.emacs.d.scratch/emacs-config.org"
))
(setq recentf-filter-changer-current 'nil)
;; Local Variables:
;; coding: utf-8-emacs
;; End:
4 撤销增强 🔗
我们在编辑文本时,常常会写错,需要撤销,Emacs自带撤销,你可以使用 C-/
或 C-x u
来撤销,使用 C-M-_
来重做。可以通过连续按这两个快捷键来达到持续撤销和持续重做的目的。
但是自带的撤销和重做不够直观,我们可以通过 undo-tree 插件,显示一个可视化的撤销、重做系统。
(use-package undo-tree
:ensure t
:hook (after-init . global-undo-tree-mode)
:config
;; don't save undo history to local files
(setq undo-tree-auto-save-history nil)
)
当我们安装完这个插件,并打开 undo-tree-mode
后,我们可以看到,当我们按下 C-x u
时,会出现一个可视化的树状结构,树上的每一个点都是一个编辑历史状态,我们可以通过 C-n
和 C-p
来选择历史状态,进而实现可视化的撤销和重做。这样不仅直观,而且可以防止多按出差错。
5 自动保存 🔗
很多时候,我们在编辑某个文档时,常常会忘记按下 C-x C-s
来保存,没有及时保存的后果我就不多说了。因此,也诞生出了很多自动保存的插件,Emacs自己也带着自动保存的机制,不过我们已经在 第6课:改变Emacs的一些编辑行为 - 备份设置章节 里禁用了Emacs自带的自动保存。
这里,我们通过 super-save 插件来实现自动保存,它的优点是可以根据一些行为来触发自动保存,如窗口切换:
(use-package super-save
:ensure t
:hook (after-init . super-save-mode)
:config
;; Emacs空闲是否自动保存,这里不设置
(setq super-save-auto-save-when-idle nil)
;; 切换窗口自动保存
(add-to-list 'super-save-triggers 'other-window)
;; 查找文件时自动保存
(add-to-list 'super-save-hook-triggers 'find-file-hook)
;; 远程文件编辑不自动保存
(setq super-save-remote-files nil)
;; 特定后缀名的文件不自动保存
(setq super-save-exclude '(".gpg"))
;; 自动保存时,保存所有缓冲区
(defun super-save/save-all-buffers ()
(save-excursion
(dolist (buf (buffer-list))
(set-buffer buf)
(when (and buffer-file-name
(buffer-modified-p (current-buffer))
(file-writable-p buffer-file-name)
(if (file-remote-p buffer-file-name) super-save-remote-files t))
(save-buffer)))))
(advice-add 'super-save-command :override 'super-save/save-all-buffers)
)
当我们安装配置完这个插件,并打开 super-save-mode
时,我们编辑完当前缓冲区,切换缓冲区,或者切换窗体时,Emacs会自动帮你保存,非常方便:
6 crux系统增强 🔗
在今天课程的最后,介绍一下 crux 插件,它提供了一系列的增强,如移动增强、删除增强等优化功能。
我们先来安装配置一下:
(use-package crux
:ensure t
:bind (("C-a" . crux-move-beginning-of-line)
("C-x 4 t" . crux-transpose-windows)
("C-x K" . crux-kill-other-buffers)
("C-k" . crux-smart-kill-line)
("C-c r" . crux-rename-file-and-buffer)
("C-x DEL" . crux-kill-line-backwards))
:config
(crux-with-region-or-buffer indent-region)
(crux-with-region-or-buffer untabify)
(crux-with-region-or-point-to-eol kill-ring-save)
(defalias 'rename-file-and-buffer #'crux-rename-file-and-buffer))
在安装这个增强插件前,当我们按下 C-k
删除行的快捷键时,Emacs只会将当前光标到行尾的字符都删除。而我们安装完这个插件,并使用 crux-smart-kill-line
来代替Emacs的 kill-line
时,我们可以看到,当当前光标到行尾没有字符时,它会智能地删除当前行(将当前光标到行首的内容删除),非常方便:
另外在安装该插件前,我们按下 C-a
移动到行首时,它不管行首有没有空格,直接移动到行首,当我们使用 crux-move-beginning-of-line
来代替Emacs自带的 move-beginning-of-line
后,我们按下 C-a
它会首先移动到第一个非空白字符的地方,再按下 C-a
它会再跳到行首位置,非常方便:
crux 增强插件还有很多有意思的系统增强,你可以按下 M-x crux
来查看和研究:
7 结语 🔗
经过今天的课程,我们通过让Emacs记住历史,让Emacs的撤销更加直观,让Emacs智能的自动保存,并通过 crux
增强Emacs的一些行为,让Emacs变得更加高效。
在Emacs的世界,远不止这些手段,还有非常多其他的插件或代码能让Emacs变的更高效。而且高效这个词是因人而异的,不同的人有不同的工作习惯,因为Emacs那伟大的自由,你可以根据自己的喜好和习惯来调教Emacs,这像不像一个养成游戏呢😄
配置文件的快照见:emacs-config-l11.org
你也可以在 这里 查看最新的配置文件。