tide独占补全后端

使用tide作为js/ts的补全后端,即使tide不能补全,也不会启用其他的补全后端

比如输入的代码是 "./|"(|代表光标位置),本意是希望启用 company-files 补全文件名,但是结果是并不会启用 company-files

即使将 company-backends 的第一个补全设置成 '(company-tide company-files)也不能实现补全文件名的效果,设置成'(company-files company-tide) 倒是能补全文件名,但自动导入模块的时候补全列表里面都是文件名,会多一个.ts.js,体验不好

有没有方法让 tide 在没有补全想的时候启用 company-backends里面的其他补全后端补全呢?

Company Try Hard

我绑定了c-c / 为company-files

试了下,这个package需要把company-tidecompany-files组合成一个 group backend,而且也还需要设置额外的快捷键或者手动调用company-try-hard函数,感觉更复杂了

我希望的效果是company-tide把控制权交出来,让后续的backend来补全

之前都是直接用M-x来执行company-files的,就是不想加入额外的操作

如果没有办法解决的话,也只好绑一个快捷键了,或者继续手动调用命令

lsp-mode + company-lsp能补全吗?typescript-language-server只是对tide对一个包装,功能完全一样。

没有用lsp,直接使用tide进行补全的

我觉得你这需求可能要去改company-tide的代码。

我猜应该是tide找不到候选就会返回终止信号,而不是另一个表示交出所有权的关键字,所以可能把返回的关键字改一下就行了…

可我最近没时间来折腾emacs😂,仅供参考

应该是,我看company-backends的文档说的只要返回nil就会交出控制权

但是company-tide的实现看不懂

所以问问,看有没有什么方法实现这个需求

如果确定是这样,直接改写company-tide让它返回nil不就好了?

不过看代码,如果找不到是应该返回nil的呀

(defun company-tide (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (cl-case command
    (interactive (company-begin-backend 'company-tide))
    (prefix (and
             (bound-and-true-p tide-mode)
             (-any-p #'derived-mode-p tide-supported-modes)
             (tide-current-server)
             (not (nth 4 (syntax-ppss)))
             (or (tide-completion-prefix) 'stop)))
    (candidates (cons :async
                      (lambda (cb)
                        (tide-command:completions arg cb))))
    (sorted t)
    (ignore-case tide-completion-ignore-case)
    (meta (tide-completion-meta arg))
    (annotation (tide-completion-annotation arg))
    (doc-buffer (tide-completion-doc-buffer arg))
    (post-completion (tide-post-completion arg))))

我已经记不得太清楚了, 但是不是把 (prefix ...)的最后一个stop改成nil就可以了?

我刚看了文档, 其中说prefix返回stop的意思是:

This tells company-mode that no other backends should be used for this completion.

所以, 我觉得把stop去掉或者改成nil就可以了.

链接: http://sixty-north.com/blog/writing-the-simplest-emacs-company-mode-backend

company 好像没有对 'stop 做什么特殊的处理

返回 'ok 和 'stop 一样

返回 nil 和 'stop 应该也一样

直接改了试试看呗

找到问题了,两方面的问题

一个问题是tide-completion-prefix这个函数的问题,返回的是一个字符串或者一个cons,在需要交出控制权的时候返回的是空字符串 ,而不是nil,这部分的改动就是对其返回值作判断,如果是空字符串则返回nil即可

第二个就是stop的问题了,stop会保留控制权,去掉即可

最终就是改两个函数定义即可

(defun tide-completion-prefix ()
  (if (and (tide-in-string-p)
           (looking-back
            (rx (or (and "import" (1+ space) (or ?\" ?') (0+ (not (any ?\" ?'))))
                    (and "from" (1+ space) (or ?\" ?') (0+ (not (any ?\" ?'))))
                    (and "import(" (or ?\" ?') (0+ (not (any ?\" ?'))))
                    (and "require(" (or ?\" ?') (0+ (not (any ?\" ?'))))))))
      (cons (company-grab (rx (or ?/ ?\" ?') (group (0+ (not (any ?\" ?'))))) 1) t)
    (let ((comp (company-grab-symbol-cons "\\." 1)))
      (if (and (tide-in-string-p)
               (stringp comp)
               (string-empty-p comp))
          nil
        comp))))
(defun company-tide (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (cl-case command
    (interactive (company-begin-backend 'company-tide))
    (prefix (and
             (bound-and-true-p tide-mode)
             (-any-p #'derived-mode-p tide-supported-modes)
             (tide-current-server)
             (not (nth 4 (syntax-ppss)))
             (tide-completion-prefix)))
    (candidates (cons :async
                      (lambda (cb)
                        (tide-command:completions arg cb))))
    (sorted t)
    (ignore-case tide-completion-ignore-case)
    (meta (tide-completion-meta arg))
    (annotation (tide-completion-annotation arg))
    (doc-buffer (tide-completion-doc-buffer arg))
    (post-completion (tide-post-completion arg))))
2 个赞