2

我正在为旧的命令行工具编写一个 comint 模式。我想为其添加基本的自动完成功能。

假设我有以下工具使用的关键字列表:

(defconst my-keywords '("export" "extract" "display"))

如何根据此列表将自动完成添加到我的模式?


到目前为止我发现了什么: 我知道在 shell.el 或 comint.el 中有这样的例子,但我没有很好地理解代码来回答这个基本问题。我确实明白我可以用 my-keywords 构建一个正则表达式列表,如下所示:

(regexp-opt my-keywords)
;; output:
"\\(?:display\\|ex\\(?:\\(?:por\\|trac\\)t\\)\\)"

除此之外,我收集到我可以使用 pcomplete 或 company,或两者兼而有之——实际上我对任何解决方案都很好,但我该怎么做呢?

4

2 回答 2

1

Comint 也comint-dynamic-complete-functions从它的comint-completion-at-point函数中调用可定制的。派生模式通常会向该钩子添加功能(请参阅 参考资料shell-dynamic-complete-functions),例如。

(defconst my-keywords '("export" "extract" "display"))
(defun my-comint-dynamic-completion-function ()
  (when-let* ((bds (bounds-of-thing-at-point 'symbol))
              (beg (car bds))
              (end (cdr bds)))
    (when (> end beg)
      (list beg end my-keywords :annotation-function (lambda (_) "my-keywords")))))

(define-derived-mode my-comint-mode comint-mode "my mode"
  (add-hook 'comint-dynamic-complete-functions
            #'my-comint-dynamic-completion-function nil 'local)
  (make-local-variable 'company-backends)
  (cl-pushnew 'company-capf company-backends))

通过添加company-capf到您的功能中company-backends,您还将从您的完成点功能中获得公司支持(elisp-completion-at-point例如,参见用于显示完成候选人的帮助/位置/等的其他公司特定符号)。

于 2019-07-01T21:15:17.453 回答
1

感谢ergoemacs,我找到了第一个解决方案:

  1. 定义一个完成函数,它返回一个表单列表(start end my-keywords . nil)开始结束分隔要在点完成的实体。我为第一个关键字添加了一个调整以考虑程序提示。
  2. 将此函数添加到完成点函数中,在模式的定义中;
  3. 在模式映射中添加一个选项卡快捷方式到完成点。
(defconst my-keywords '("export" "extract" "display"))

;; 1 - custom completion function
(defun my-completion-at-point ()
  "This is the function to be used for the hook `completion-at-point-functions'."
  (interactive)
  (let* (
         (bds (bounds-of-thing-at-point 'symbol))
         (start (max (car bds) (comint-line-beginning-position)))
         (end (cdr bds)))
    (list start end xyz-keywords . nil )))

;; 2 - adding it to my-completion-at-point 
(define-derived-mode my-comint-mode comint-mode "My comint mode"
;; your  code....
(add-hook 'completion-at-point-functions 'my-completion-at-point nil 'local))

;; 3 - add a tab shortcut in the map of the mode
(defvar my-mode-map
  (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
    ;; your code...
    (define-key map "\t" 'completion-at-point)
    map))

于 2019-07-01T18:33:44.687 回答