gpt4 book ai didi

Emacs 完成点函数

转载 作者:行者123 更新时间:2023-12-05 00:00:25 25 4
gpt4 key购买 nike

我正在编写基于 comint-mode 的派生模式。该模式是命令行程序(GRASS gis)的接口(interface),comint 模式完成适用于这些程序。我正在尝试通过 completion-at-point-functions 添加对完成程序参数的支持.一个玩具示例是:

(setq my-commands 
'(("ls"
("my-completion-1")
("my-completion-2"))
("mv"
("my-completion-3")
("my-completion-4"))))


(defun my-completion-at-point ()
(interactive)
(let ((pt (point)) ;; collect point
start end)

(save-excursion ;; collect the program name
(comint-bol)
(re-search-forward "\\(\\S +\\)\\s ?"))
(if (and (>= pt (match-beginning 1))
(<= pt (match-end 1)))
() ;; if we're still entering the command, pass completion on to
;; comint-completion-at-point by returning nil

(let ((command (match-string-no-properties 1)))
(when (member* command my-commands :test 'string= :key 'car)
;; If the command is one of my-commands, use the associated completions
(goto-char pt)
(re-search-backward "\\S *")
(setq start (point))
(re-search-forward "\\S *")
(setq end (point))
(list start end (cdr (assoc command my-commands)) :exclusive 'no))))))

(push 'my-completion-at-point completion-at-point-functions)

这几乎可以工作。我得到程序名称的正常完成。但是,如果我输入了 ls在命令行,点击制表符插入 my-completion-并且不提供这两种选择。再次点击标签插入 my-completion-第二次,所以我现在有 ls my-completion-mycompletion- .

我的实际代码包括几行来检查多行命令,但对完成代码没有任何更改。使用此版本的代码,我在以 my-commands 中的一个程序名称开头的行上点击制表符。我看到了完成命令的可能参数列表,但缓冲区中没有插入任何内容,并且通过键入参数的前几个字母不会缩小列表的范围。

我已经阅读了手册,但我无法弄清楚编写 completion-at-point 的正确方法功能。有什么我想念的想法吗?

我简要地查看了 pcomplete ,但是并没有真正理解“文档”,也没有取得任何进展。

最佳答案

问题似乎出在您查找 start 的方式上。和 end返回参数在点的边界。我没有花足够长的时间调试它来确定细节,但我认为如果您以交互方式调用该函数,您会看到它为 start 返回相同的值。和 end ,这意味着完成 UI 不知道使用该参数从您传递给它的完成表中进行选择。

将函数的最后一部分更改为以下内容似乎是一种解决方法:

(when (member* command my-commands :test 'string= :key 'car)
;; If the command is one of my-commands, use the associated completions
(goto-char pt)
(let ((start
(save-excursion
(skip-syntax-backward "^ ")
(point))))

(list start pt (cdr (assoc command my-commands)) :exclusive 'no)))))))

当作为 completion-at-point-functions 的元素添加时,这给出了预期的结果。 .

这里我使用了 skip-syntax-backward而不是 regexp 搜索,我认为这对于这种事情来说更符合 Elisp 的习惯。它只是说将点向后移动到不在语法类“空白”中的任何内容。跳过语法函数返回移动的距离而不是点的值,因此我们必须添加对 point 的调用在保存游览结束时。

如果您确实在这样的函数中使用正则表达式搜索,通常最好传递 t对于第四个参数, noerror ,以便在匹配失败时不会将错误传递给用户。这确实意味着您必须自己检查返回值是否为 nil , 尽管。

最后,而不是 push添加你可能想要使用的补全函数 add-hook如下:
(add-hook 'completion-at-point-functions 'my-completion-at-point nil t)

这做了两件有用的事情:它在添加之前检查你的函数是否已经在钩子(Hook)中,并且(通过为第四个参数传递 t local )它只将函数添加到完成的缓冲区本地值点钩。这几乎肯定是您想要的,因为当您按下 TAB 键时,您不想在每个其他 Emacs 缓冲区中使用这些完成。

关于Emacs 完成点函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10274642/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com