- 1 课程回顾
- 2 Emacs的矩形操作
- 3 Avy快速移动光标
- 3.1 avy的高阶用法
- 4 multiple-cursors多光标编辑
- 5 结语
1 课程回顾 🔗
通过上节课,我们对Emacs Lisp有了基础的认识,也了解了如何通过 C-h
系列按键,来查看变量或函数的定义。从这一节课后,我们就掌握了知其所以然的方法!遇到不明白的配置,直接 C-h
看一下文档,你会发现,随着时间的推移,你对Emacs的掌控力将越来越强!
那么,本节课,将进一步介绍通过Emacs来编辑文本时,有哪些高效的手段。
2 Emacs的矩形操作 🔗
Emacs无须安装任何插件就支持矩形操作,所谓矩形操作,就是选择一块矩形区域,对这块矩形区域进行编辑,如删除、替换、复制、粘贴等。
Emacs矩形操作的几个快捷键和命令如下:
快捷键 | 命令 | 含义 |
---|---|---|
C-x SPC | rectangle-mark-mode | 开始激活对一个矩形区域的标记 |
C-x r M-w | copy-rectangle-as-kill | 将标记的矩形区域拷贝 |
C-x r y | yank-rectangle | 将拷贝的矩形区域粘贴 |
C-x r t | string-rectangle | 将标记的矩形区域通过字符串来按行替换 |
C-x r k | kill-rectangle | 将标记的矩形区域删除 |
C-x r c | clear-rectangle | 将标记的矩形区域以空格清除 |
通过上面这些命令,我们就可以很方便的对矩形区域进行操作,在很多时候非常方便:
3 Avy快速移动光标 🔗
avy 是一个光标移动插件,能快速将光标移动到屏幕上的任意位置,非常强大!
我们先来安装配置 avy:
(use-package avy
:ensure t
:bind (("C-." . my/avy-goto-char-timer)
("C-。" . my/avy-goto-char-timer)
:map isearch-mode-map
("C-." . avy-isearch))
:config
;; Make `avy-goto-char-timer' support pinyin, refer to:
;; https://emacs-china.org/t/avy-avy-goto-char-timer/20900/2
(defun my/avy-goto-char-timer (&optional arg)
"Make avy-goto-char-timer support pinyin"
(interactive "P")
(let ((avy-all-windows (if arg
(not avy-all-windows)
avy-all-windows)))
(avy-with avy-goto-char-timer
(setq avy--old-cands (avy--read-candidates
'pinyinlib-build-regexp-string))
(avy-process avy--old-cands))))
(defun avy-action-kill-whole-line (pt)
"avy action: kill the whole line where avy selection is"
(save-excursion
(goto-char pt)
(kill-whole-line))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(defun avy-action-copy-whole-line (pt)
"avy action: copy the whole line where avy selection is"
(save-excursion
(goto-char pt)
(cl-destructuring-bind (start . end)
(bounds-of-thing-at-point 'line)
(copy-region-as-kill start end)))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(defun avy-action-yank-whole-line (pt)
"avy action: copy the line where avy selection is and paste to current point"
(avy-action-copy-whole-line pt)
(save-excursion (yank))
t)
(defun avy-action-teleport-whole-line (pt)
"avy action: kill the line where avy selection is and paste to current point"
(avy-action-kill-whole-line pt)
(save-excursion (yank)) t)
(defun avy-action-helpful (pt)
"avy action: get helpful information at point"
(save-excursion
(goto-char pt)
(helpful-at-point))
t)
(defun avy-action-mark-to-char (pt)
"avy action: mark from current point to avy selection"
(activate-mark)
(goto-char pt))
(defun avy-action-flyspell (pt)
"avy action: flyspell the word where avy selection is"
(save-excursion
(goto-char pt)
(when (require 'flyspell nil t)
(flyspell-correct-wrapper))))
(defun avy-action-define (pt)
"avy action: define the word in dictionary where avy selection is"
(save-excursion
(goto-char pt)
(fanyi-dwim2)))
(defun avy-action-embark (pt)
"avy action: embark where avy selection is"
(unwind-protect
(save-excursion
(goto-char pt)
(embark-act))
(select-window
(cdr (ring-ref avy-ring 0))))
t)
(defun avy-action-google (pt)
"avy action: google the avy selection when it is a word or browse it when it is a link"
(save-excursion
(goto-char pt)
(my/search-or-browse)))
(setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay
(alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line
(alist-get ?w avy-dispatch-alist) 'avy-action-copy
(alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line
(alist-get ?y avy-dispatch-alist) 'avy-action-yank
(alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line
(alist-get ?t avy-dispatch-alist) 'avy-action-teleport
(alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line
(alist-get ?H avy-dispatch-alist) 'avy-action-helpful
(alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char
(alist-get ?\; avy-dispatch-alist) 'avy-action-flyspell
(alist-get ?= avy-dispatch-alist) 'avy-action-define
(alist-get ?o avy-dispatch-alist) 'avy-action-embark
(alist-get ?G avy-dispatch-alist) 'avy-action-google
)
:custom
(avy-timeout-seconds 1.0)
(avy-all-windows t)
(avy-background t)
(avy-keys '(?a ?s ?d ?f ?g ?h ?j ?l ?q ?e ?r ?u ?i ?p ?n))
)
安装完 avy 插件后,我们就可以通过 C-.
快捷键来激活 avy,激活后,输入你想要跳转到的字符串,然后 avy 会自动将所有候选的位置高亮,并以字母提示,按照字母的提示选择,就会将光标移动到对应的位置,非常强大:
3.1 avy的高阶用法 🔗
avy 不仅仅能将光标快速跳转到屏幕的任何一个字符的位置,它还有更高阶的用法,详情可以参照这篇博客。
简而言之,avy 在快速跳转光标位置之前,可以设定一个 action,在设定完 action 后,在光标跳转到指定位置的同时,会执行这个 action 对应的指令。
下表是一个 avy action 的示例表,所有这些表格里的 action 都已经在上面的配置文件里配置好了,可以直接使用。
action指令 | Avy action 按键 | Emacs 相对应的按键 | 含义 |
---|---|---|---|
Kill | k (thing), K (line) | C-k | 删除目的光标处的字符 |
Copy | w (thing), W (line) | M-w | 拷贝目的光标处的字符 |
Yank | y (thing), Y (line) | C-y | 将目的光标处的字符粘贴到当前的光标位置 |
Transpose | t, T (line) | C-t, M-t etc. | 将目的光标处的字符剪切到当前的光标位置 |
Mark | m | m in special buffers | 选择目的光标处的字符 |
Activate region | SPC | C-SPC | 选择从当前光标到目的光标处的区域 |
Helpful | H | C-h | 展示目的光标处字符的定义 |
下面以 helpful
这个 action 为例:
- 按
C-.
激活 avy - 输入待选择的光标位置字符串
avy-action
- 输入 avy action,这里是
H
,即helpful
- 输入候选位置
j
- avy 会自动执行action,展示候选位置
j
处的字符定义,即avy-action-yank
的字符定义
4 multiple-cursors多光标编辑 🔗
multiple-cursors 插件能让Emacs实现多光标编辑和移动,非常强大!
我们先来安装和配置这个插件:
(use-package multiple-cursors
:ensure t
:bind-keymap ("C-c o" . multiple-cursors-map)
:bind (("C-`" . mc/mark-next-like-this)
("C-\\" . mc/unmark-next-like-this)
:map multiple-cursors-map
("SPC" . mc/edit-lines)
(">" . mc/mark-next-like-this)
("<" . mc/mark-previous-like-this)
("a" . mc/mark-all-like-this)
("n" . mc/mark-next-like-this-word)
("p" . mc/mark-previous-like-this-word)
("r" . set-rectangular-region-anchor)
)
:config
(defvar multiple-cursors-map nil "keymap for `multiple-cursors")
(setq multiple-cursors-map (make-sparse-keymap))
(setq mc/list-file (concat user-emacs-directory "/etc/mc-lists.el"))
(setq mc/always-run-for-all t)
)
当我们安装完这个插件后,我们可以通过 C-`
来激活多光标,激活后就可以直接编辑(输入字符、删除字符等),下面是三个典型的例子:
- 将指定的一些行前面加一些字符
- 将指定的一些行末尾加一些字符
- 将指定的一些字符替换成另外一些字符
当我们熟悉了多光标编辑后,我们就可以把Emacs自带的矩形操作给扔掉啦,所有的矩形操作,都可以通过多光标编辑来实现。我们真的应该感谢Emacs的自由,感谢有社区那么多厉害的大神,给我们开发出了如此高效的插件!
5 结语 🔗
经过今天的课程,我们在Emacs里编辑文本的效率进一步得到了提升,用魔兽里地精的一句名言作为本节课的结尾语“Time is money, my friend!”
配置文件的快照见:emacs-config-l10.org
你也可以在 这里 查看最新的配置文件。