我正在编写基于 comint-mode 的派生模式。该模式是命令行程序(GRASS gis)的接口,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
,但并没有真正理解“文档”,也没有取得任何进展。