命令循环首先必须读取按键序列,它是一组可转换为命令的输入事件。
这一过程通过调用函数 read-key-sequence 完成。
Lisp 程序也可以调用该函数(see 读取按键序列)。
它们还可以使用 read-key 或 read-event 在更低层级读取输入(see 读取单个事件),
或使用 discard-input 丢弃待处理输入(see 事件输入的杂项功能)。
按键序列通过当前生效的按键映射转换为命令。
关于转换方式的说明,参见 See 按键查找。
结果应为键盘宏或可交互式调用的函数。
如果按键是 M-x,则读取另一个命令的名称并执行。
这由命令 execute-extended-command 完成(see 交互式调用)。
在执行命令之前,Emacs 会运行 undo-boundary 以创建撤销边界。
参见 See Maintaining Undo Lists。
为执行命令,Emacs 首先通过调用 command-execute 读取其参数(see 交互式调用)。
对于用 Lisp 编写的命令,interactive 声明指明如何读取参数。
这可能会使用前缀参数(see 前缀命令参数),
或在小缓冲中通过提示读取(see 迷你缓冲区)。
例如,命令 find-file 的 interactive 声明指明使用小缓冲读取文件名。
find-file 的函数体本身不使用小缓冲,
因此如果你从 Lisp 代码中以函数形式调用 find-file,
必须将文件名字符串作为普通 Lisp 函数参数提供。
如果命令是键盘宏(即字符串或向量),
Emacs 使用 execute-kbd-macro 执行它(see 键盘宏)。
这个常规钩子由编辑器命令循环在执行每个命令之前运行。
此时,this-command 包含即将运行的命令,
last-command 描述上一个命令。
参见 See 来自命令循环的信息。
这个常规钩子由编辑器命令循环在执行每个命令之后运行(包括因退出或错误提前终止的命令)。
此时,this-command 指向刚刚运行的命令,
last-command 指向前一个命令。
当 Emacs 首次进入命令循环时也会运行该钩子
(此时 this-command 和 last-command 均为 nil)。
运行 pre-command-hook 和 post-command-hook 期间会禁止退出操作。
如果执行这些钩子时发生错误,不会终止钩子的执行;
相反,错误会被静默处理,发生错误的函数会从钩子中移除。
进入 Emacs 服务器的请求(see Emacs Server in The GNU Emacs Manual) 与键盘命令一样,会运行这两个钩子。
注意,当缓冲区文本包含极长行时,
这两个钩子的调用方式如同在 with-restriction 形式中(see Narrowing),
带有 long-line-optimizations-in-command-hooks 标签,
并且缓冲区被缩小到光标附近的一段区域。