虽然补全通常在小缓冲区中完成,但补全机制也可用于普通 Emacs 缓冲区中的文本。
在许多主模式中,缓冲区内补全由命令 C-M-i 或 M-TAB 执行,
该命令绑定到 completion-at-point。See Symbol Completion in The GNU Emacs Manual。
该命令使用异常钩子变量 completion-at-point-functions:
该异常钩子的值应为一个函数列表,用于计算补全表(see 基础补全函数), 以对光标处的文本进行补全。主模式可使用它提供特定于模式的补全表(see 主模式编码规范)。
当命令 completion-at-point 运行时,它会逐个调用列表中的函数,不带参数。
每个函数应返回 nil,除非它能够且希望负责光标处文本的补全数据。
否则应返回如下形式的列表:
(start end collection . props)
start 和 end 界定待补全的文本(必须包含光标)。
collection 是用于补全该文本的补全表,其形式适合作为 try-completion 的第二个参数传入(see 基础补全函数);
补全候选项将按照 completion-styles 中定义的补全风格以常规方式从该补全表生成(see 补全相关变量)。
props 是附加信息的属性列表;completion-extra-properties 中的所有属性均被识别(see 补全相关变量),
此外还支持以下属性:
:predicate值应为一个谓词,补全候选项必须满足该谓词。
:exclusive若值为 no,则当补全表无法匹配光标处文本时,
completion-at-point 会继续尝试 completion-at-point-functions 中的下一个函数,
而不是报告补全失败。
该钩子上的函数通常应快速返回,因为它们可能被频繁调用(例如从 post-command-hook)。
如果生成补全列表是开销较大的操作,强烈建议为 collection 提供一个函数。
Emacs 内部可能会多次调用 completion-at-point-functions 中的函数,
但仅在部分调用中关心 collection 的值。
通过为 collection 提供函数,Emacs 可以将补全生成推迟到必要时。
你可以使用 completion-table-dynamic 创建包装函数:
;; Avoid this pattern.
(let ((beg ...) (end ...) (my-completions (my-make-completions)))
(list beg end my-completions))
;; Use this instead.
(let ((beg ...) (end ...))
(list beg
end
(completion-table-dynamic
(lambda (_)
(my-make-completions)))))
此外,collection 通常不应基于 start 到 end 之间的当前文本进行预先过滤,
因为根据其决定使用的补全风格来执行过滤是 completion-at-point-functions 调用者的职责。
completion-at-point-functions 中的函数也可以返回一个函数,
而不是上面描述的列表。在这种情况下,会调用该返回的函数(无参数),
由它完全负责执行补全。我们不鼓励这种用法;
它仅用于帮助将旧代码迁移到使用 completion-at-point。
completion-at-point 会使用 completion-at-point-functions 中
第一个返回非 nil 值的函数,其余函数不会被调用。
上述 :exclusive 说明的情况除外。
下面的函数提供了一种便捷方式,对 Emacs 缓冲区中任意一段文本执行补全: