Emacs: 如何学习Emacs和Elisp
- TAG: 编码
学会使用Emacs帮忙文档,多多练习Elisp
minibuffer增强vertico
vertico垂直展示内容更友好。
刷新包缓存 M-x package-refreesh-contents
, 安装包 M-x package-install
输入 vertico
(vertico-mode 1)
帮助系统是你最好的朋友
要成为一个称职的用户,你需要掌握帮助系统。
所有帮助命令都以 C-h
键开头。开始使用这些:
- C-h f
- 函数的帮助信息
- C-h v
- 变量的帮助信息
- C-h o
- 函数、变量、或的帮助信息
- C-h k
- 快捷键绑定的帮助信息
- C-h w
- 有关给定命令绑定到何处的帮助
- C-h m
- 当前模式(主要和次要模式)的帮助
当光标在函数或变量的符号(专有名称)上时, C-h f
、 C-h v
或 C-h o
将使用该选项作为默认选项。
因为 emacs 是自文档编辑器,里面的函数变量都能找到它的文档,后续在使用 emacs 过程中会非常有帮助。
请注意,当函数或变量的符号包含两个短划线时 --
那么这意味着它打算在文
件/包中使用。如果您计划将它们合并到您的设置中,请小心,因为它们可能会
在没有事先通知的情况下更改。
范例:
如查看C-x C-s,使用C-h k再输入C-x C-s 如save-buffer功能,使用C-h f再输入save-buffer
C-h 作为前缀和后缀
C-h
除了被用作前缀,还可以选择使用此键作为任何尚未结束的序列的后缀。
例如,Emacs 有很多以 C-x r
开头的命令。这些操作与寄存器、书签和矩形
操作有关。为了生成一个帮助缓冲区,向我们显示该序列的所有扩展,我们附加
C-h
到它,所以 C-x r C-h
。
您甚至可以使用 C-h
作为 C-h
的前缀的后缀作。这是一种奇特的说法,它
将 C-h C-h
提供有关可用帮助功能的特殊视图。
如果你使用的 embark
软件包,并且不想为 C-h
后缀生成帮助缓冲区,请
将以下内容添加到您的配置中:
(setq prefix-help-command #'embark-prefix-help-command)
如何阅读手册
Emacs 是一款功能强大的软件。只有在您熟悉它之后,它的潜力才会被释放出来。 这需要承诺、耐心和毅力。
换句话说:你一步一步地学习 Emacs。该过程的一部分涉及阅读通过内置信息阅
读器提供的大量文档。通过 C-h i
访问它,然后使用 C-h m
来了解有关
该模式的所有信息。
C-h i
内置很多文档。使用C-h m
查看可操作的快捷键C-h m
提供关于这个主模式下自信比如
m
指定菜单名、n
下一节点、p
上一节点、^
向上移动一个节点、d
到 Info 节点
范例:查看Elisp文档
C-h i
内置文档。m
Elisp : 搜索 Elisp 节点, 回车进入文档m
list : 搜索 Elisp 文档中 list 章节m
cons cells : 搜索 list 章节中 cons cells 小节…
对新手更好的文档是Emacs 手册,它是一个你经常访问的特殊文件,所以它有自己的键绑定:
C-h r
(将“r”视为“read”的助记符)。
与所有技术文档一样,您不会一次性阅读它们。它们不是故事。相反,你一次研 究一个片段。一旦你了解了它,你就会进入下一个,逐渐拓宽你的知识(或 完善你的设置)。
用 Emacs Lisp 思考
让我们从一个非常简单的场景开始。
- 假设您要编写一个将绑定到键的函数。
- 这些被称为“命令”,因为它们是交互式的。
- 此命令将在给定方向上一次将点(光标)移动 15 行。
- 键入
C-h k
并用C-n
orC-p
(移动到下一行/上一行的命令)跟踪它。你 将了解到它们分别称为next-line
和previous-line
。帮助缓冲区告诉 你,这些命令接受一个数值参数来一次移动 N 行。它还包括指向源代码的直 接链接。通过查看源代码,您最终会推断出函数是用defun
关键字(技术 上是 Lisp 宏)声明的。
考虑到这些,你可以切换到 *scratch*
缓冲区并开始试验:
(defun my-next-15-lines () "Move to the next 15 lines." (interactive) ; this turns a function into a command (next-line 15)) (defun my-previous-15-lines () "Move to the previous 15 lines." (interactive) (previous-line 15))
如果你仔细阅读上述帮助缓冲区,你将意识到你的代码可以改进,因为自定义代
码的正确命令是使用 forward-line
。因此,您可以相应地更新内容:
(defun my-next-15-lines () "Move to the next 15 lines." (interactive) (forward-line 15)) (defun my-previous-15-lines () "Move to the previous 15 lines." (interactive) (forward-line -15))
现在将它们绑定到 Ctrl+Shift,然后绑定到 n/p。要了解 Emacs 如何表示任何
键,请使用 C-h k
并键入它。你会得到 C-S-n
和 C-S-p
。
(define-key global-map (kbd "C-S-n") #'my-next-15-lines) (define-key global-map (kbd "C-S-p") #'my-previous-15-lines)
请注意,这 global-map
适用于所有主要模式。许多命令仅适用于特定模式,
因此有自己的键盘映射。 C-h k
缓冲区会相应地通知您。
试验 Elisp 条件
在前面的示例的基础上,让我们将一些变量和条件添加到组合中。下面是一个基 本变量:
(defvar my-first-toggle nil "If non-nil, do stuff.")
[ 通过移动到代码的末尾并键入代码 C-x C-e
,或者在 Elisp 缓冲区中键入
C-M-x
。也有 M-:
。]
让我们进入 scratch 并开始实验:
(if my-first-toggle (message "It is true") (message "It is not true"))
C-j
运行最近距离的代码
虽然这可能不切实际,但让我们添加第三个命令,它重用前两个命令:
(defun my-next-15-lines () "Move to the next 15 lines." (interactive) (forward-line 15)) (defun my-previous-15-lines () "Move to the previous 15 lines." (interactive) (forward-line -15)) (defun my-next-or-prev-15-lines () "Move to the next or previous 15 lines. The motion depends on the value of `my-first-toggle'." (interactive) (if my-first-toggle (my-next-15-lines) (my-previous-15-lines)))
在这种情况下,更现实的方案是让命令接受参数(即控制其行为的参数)。最简 单的是 C-u 前缀参数,您可以在命令的键之前键入该参数。
(defun my-next-or-prev-15-lines (&optional arg) "Move to the next or previous 15 lines. With optional prefix ARG, move to the next lines. Else to the previous ones." (interactive "P") ;;(if arg (if my-first-toggle (my-next-15-lines) (my-previous-15-lines)))
键入 C-h f
并搜索 interactive
。它会告诉你它接受的其他预设(你总是
可以编写自己的预设,但那是高级的东西)。
请注意该 &optional
类型的使用。如果没有它,如果该命令未使用 prefix
参数调用即arg,则该命令将返回错误。
练习并保持耐心
学习基础知识。永远有用的技能是使用帮助系统。
要有耐心。专业知识没有捷径可走。所有专家都是从菜鸟开始的。这也意味着你 通过反复试验的过程从错误中吸取教训:没关系。
通过尝试理解小模式来修补 Elisp。然后尝试将它们组合成更大的设计的方法。
用其他学习材料补充官方资源,例如博客文章、视频和其他人的代码。
永远——永远——阅读文档!
完整内容
;;;; C-h k find command of =C-n= or =C-p= ;;; 定义函数 (defun my-next-15-lines () "Move to the next 15 lines." (interactive) ; this turns a function into a command (next-line 15) ; instead of forward-line (forwad-line 15)) (defun my-previous-15-lines () "Move to the previous 15 lines." (interactive) (previous-line 15)) ;;; 绑定快捷键 (define-key global-map (kbd "C-S-n") #'my-next-15-lines) (define-key global-map (kbd "C-S-p") #'my-previous-15-lines) ;;; 调用 (defvar my-first-toggle nil "If non-ni, do stuff.") (if my-first-toggle (message "It is true") (message "It is no true")) (defun my-next-or-prev-15-lines () "Move to the next or previous 15 lines. The motion depends on the value of `my-first-toggle'." (interactive) (if my-first-toggle (my-next-15-lines) (my-previous-15-lines))) ;; 可选参数arg (defun my-next-or-prev-15-lines (&optional arg) "Move to the next or previous 15 lines. With optional prefix ARG, move to the next lines. Else to the previous ones." (interactive "P") (if my-first-toggle (if my-first-toggle (my-next-15-lines) (my-previous-15-lines)))
其它
中文的快速指南由水木的crazycool翻译,具体见本版1143, URL:http://www.newsmth.net/nForum/article/Emacs/34145?s=34145
- emacs 手册:
C-h r
。C-h m
查看帮助信息。n p ^
下上页,上一节- Online : Emacs manual