You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复company-mode中可执行文件的自动补全问题?

Eshell中company-mode补全丢失./前缀导致命令执行错误的解决方法

问题描述

近期使用启用了company-mode的Doom Emacs,在Eshell中自动补全当前目录下的可执行文件时(输入./progr后按回车),补全后的命令会丢失./前缀,变成program而非预期的./program。执行该命令时出现错误提示:Wrong type argument: sequencep, 771。

原因分析

这是由于company-mode的Eshell补全后端(company-eshell)在处理相对路径前缀时存在逻辑问题,它会自动剥离掉./这类相对路径标识,导致Eshell无法识别这是当前目录下的可执行文件,转而在系统PATH中查找,最终找不到命令触发错误。

修复方法

  • 方法1:自定义company-eshell的补全处理逻辑
    在Doom Emacs配置文件(~/.doom.d/config.el)中添加以下代码,修改补全候选项处理逻辑,保留./前缀:

    (advice-add 'company-eshell--candidates :filter-return
                (lambda (candidates)
                  (let ((prefix (company-grab-symbol)))
                    (if (string-prefix-p "./" prefix)
                        (mapcar (lambda (c) (concat "./" c)) candidates)
                      candidates))))
    
  • 方法2:临时禁用Eshell中的company-mode
    如果不需要在Eshell中使用company-mode,可直接关闭:

    (add-hook 'eshell-mode-hook (lambda () (company-mode -1)))
    
  • 方法3:使用Eshell原生补全替代company-mode
    修改Eshell的TAB按键绑定,使用原生补全而非company-mode:

    (add-hook 'eshell-mode-hook
              (lambda ()
                (define-key eshell-mode-map (kbd "<tab>") 'eshell-pcomplete)))
    

栈追踪信息

开启toggle-debug-on-error后得到的错误栈:

error("%s: command not found" "program")
  eshell-find-interpreter("program" nil nil)
  eshell-external-command("program" nil)
  eshell-plain-command("program" nil)
  eshell-named-command("program")
  eval((eshell-named-command '"program"))
  eshell-do-eval((eshell-named-command '"program") nil)
  eshell-do-eval((prog1 (eshell-named-command '"program") (mapc #'funcall eshell-this-command-hook)) nil)
  (condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"program") (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))
  eval((condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"program") (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))
  eshell-do-eval((condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"program") (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))) nil)
  #f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;)()
  funcall(#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;))
  (let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;)))
  eval((let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;))))
  eshell-do-eval((let ((eshell-this-command-hook '(ignore))) (condition-case err (eshell-do-eval '(prog1 (eshell-named-command '"program") (mapc #'funcall eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))) nil)
  eshell-do-eval((progn (let ((eshell-this-command-hook '(ignore))) (condition-case err (eshell-do-eval '(prog1 (eshell-named-command ...) (mapc ... eshell-this-command-hook)) nil) ((debug error) (mapc #'funcall eshell-this-command-hook) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))) nil)
  (catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook '...)) (condition-case err (eshell-do-eval '... nil) ((debug error) (mapc ... eshell-this-command-hook) (eshell-errorn ...) (eshell-close-handles 1))))) nil))
  eval((catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook ...)) (condition-case err (eshell-do-eval ... nil) (... ... ... ...)))) nil)))
  eshell-do-eval((catch 'top-level (eshell-do-eval '(progn (let ((eshell-this-command-hook ...)) (condition-case err (eshell-do-eval ... nil) (... ... ... ...)))) nil)) nil)
  eshell-do-eval((progn 'nil (catch 'top-level (eshell-do-eval '(progn (let (...) (condition-case err ... ...))) nil)) (run-hooks 'eshell-post-command-hook)) nil)
  #f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;)()
  funcall(#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;))
  (let ((eshell-current-handles '[nil (t . 1) (t . 1)]) (eshell-current-subjob-p 'nil)) (funcall '#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;)))
  eval((let ((eshell-current-handles '[nil (t . 1) (t . 1)]) (eshell-current-subjob-p 'nil)) (funcall '#f(compiled-function () #&lt;bytecode -0x13dc3821b05c18d2&gt;))))
  eshell-do-eval((let ((eshell-current-handles '[nil (t . 1) (t . 1)]) eshell-current-subjob-p) (progn 'nil (catch 'top-level (eshell-do-eval '(progn (let ... ...)) nil)) (run-hooks 'eshell-post-command-hook))))
  eshell-resume-eval()
  eshell-eval-command((let ((eshell-current-handles '[nil (t . 1) (t . 1)]) eshell-current-subjob-p) (progn 'nil (catch 'top-level (eshell-do-eval '(progn (let ... ...)) nil)) (run-hooks 'eshell-post-command-hook))) "program")
  eshell-send-input(nil)
  funcall-interactively(eshell-send-input nil)
  command-execute(eshell-send-input)

内容的提问来源于Stack Exchange,提问作者Crowl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:05:24