【问题标题】:How do I add auto-completion to my custom comint mode in Emacs?如何在 Emacs 中为我的自定义 comint 模式添加自动完成功能?
【发布时间】:2019-11-11 22:15:10
【问题描述】:

我正在为旧的命令行工具编写一个 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,或两者兼而有之 - 实际上我对任何解决方案都很好,但我该怎么做呢?

【问题讨论】:

    标签: emacs autocomplete comint-mode


    【解决方案1】:

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

    1. 定义一个完成函数,该函数返回(start end my-keywords . nil) 形式的列表,其中startend 分隔要在该点完成的实体。我为第一个关键字添加了一个调整以考虑程序提示。
    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))
    
    

    【讨论】:

      【解决方案2】:

      Comint 还从其comint-completion-at-point 函数调用可自定义的comint-dynamic-complete-functions。派生模式通常会向这个钩子添加函数(参见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,例如用于显示完成候选人的帮助/位置/等的其他公司特定符号) .

      【讨论】:

      • 我的 emacs(Windows 上为 26.1)似乎不知道 when-let* 函数(Symbol 的函数定义为 void:when-let*)。这是你写的函数,还是我这边缺少的东西?
      • company-capf 真的很棒!
      • when-let*subr-x 中的宏(应该在emacs 26 中?我在27 中),您可以将(eval-when-compile (require 'subr-x)) 添加到您的文件中。通过在不匹配时返回 nil,您的 capf 函数可以委托给下一个 capf 函数(如果您有多个后端)
      猜你喜欢
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-20
      • 2014-09-26
      • 1970-01-01
      • 2012-02-06
      相关资源
      最近更新 更多