company mode 怎样同时使用lsp-mode和yasinppet?「已解决」

手动设置 company后端如下:

  (setq company-backends '((company-capf :with company-yasnippet)
                           (company-dabbrev-code company-keywords company-files)
                           (company-dabbrev)))

开启自动配置的情况

如果lsp-mode的 lsp-auto-configure如果设置为t的话,会在后端中再添加一个 company-capf 变成了:

(company-capf
 (company-capf :with company-yasnippet)
 (company-dabbrev-code company-keywords company-files)
 (company-dabbrev))

导致 company-yasinppet 无法使用。此时如果使用

(with-current-buffer "app.rs" (setq company-backends '((company-capf :with company-yasnippet)
                                                       (company-dabbrev-code company-keywords company-files)
                                                       (company-dabbrev))))

将后端还原的话,这两个插件是可以配合使用的。

关闭自动配置的情况

关闭自动配置的情况下,lsp-mode 不会修改company-backends ,但是compan-capf和company-yasinppet都不会生效,使用compan-diag信息如下:

Emacs 28.0.50 (x86_64-pc-linux-gnu) of 2020-07-13 on m
Company 0.9.13

company-backends: ((company-capf :with company-yasnippet)
 (company-dabbrev-code company-keywords company-files)
 (company-dabbrev))

Used backend: (company-dabbrev-code company-keywords company-files)

Major mode: rust-mode
Prefix: #("if" 0 2
  (fontified t face font-lock-keyword-face))

Completions:
  #("if" 0 2 (company-backend company-keywords))

我输入的if,正常的话company-yasinppet应该可以补全的,但是实际上确使用的第二组后端。

以下是我现在的配置:

(use-package
  lsp-mode
  :ensure t
  :defer t
  :hook ((lsp-mode . lsp-enable-which-key-integration))
  :init ;;
  ;; (setq lsp-auto-configure nil)
  (setq lsp-prefer-capf t)
  (setq lsp-enable-snippet t)
  (setq lsp-keymap-prefix "C-l")
  (setq lsp-enable-completion-at-point t)

  (setq lsp-keep-workspace-alive nil)
  (setq lsp-enable-file-watchers nil)
  (setq lsp-enable-semantic-highlighting nil)
  (setq lsp-enable-symbol-highlighting nil)
  :config (require 'lsp-clients))
(use-package
  lsp-ui
  :ensure t
  :after lsp-mode
  :commands lsp-ui-mode
  :custom (lsp-ui-doc-position (quote at-point))
  ;; (lsp-ui-doc-use-webkit t)
  (lsp-ui-sideline-enable t)
  (lsp-ui-doc-enable nil)
  (lsp-ui-doc-border "orange")
  :hook (lsp-mode . lsp-ui-mode))


;; Auto complete
(use-package
  company
  :ensure t
  :defer t
  :hook (prog-mode . company-mode)
  :init ;; Don't convert to downcase.
  (setq-default company-dabbrev-downcase nil)
  :bind (("C-<tab>" . company-complete-common)
         ;;
         :map company-active-map        ;
         ("C-n" . company-select-next)
         ("C-p" . company-select-previous)
         ("C-s" . company-filter-candidates)
         ("<tab>" . company-complete-selection)
         ("TAB" . company-complete-selection)
         ("<return>" . company-complete-selection) ; 终端下无效
         ("RET" . company-complete-selection)      ; 终端下生效
         :map company-filter-map                   ;
         ("C-n" . company-select-next)
         ("C-p" . company-select-previous)
         ("<tab>" . company-complete-selection)
         ("TAB" . company-complete-selection)
         ("<return>" . company-complete-selection) ; 终端下无效
         ("RET" . company-complete-selection)      ; 终端下生效
         :map company-search-map                   ;
         ("C-n" . company-select-next)
         ("C-p" . company-select-previous)
         ("<tab>" . company-complete-selection)
         ("TAB" . company-complete-selection)
         ("<return>" . company-complete-selection) ; 终端下无效
         ("RET" . company-complete-selection)      ; 终端下生效
         )
  :custom                               ;
  (company-minimum-prefix-length 1)
  (company-idle-delay 0.0)
  :config                               ;
  (setq company-backends '((company-capf :with company-yasnippet)
                           (company-dabbrev-code company-keywords company-files)
                           (company-dabbrev)))
  (setq company-frontends '(company-pseudo-tooltip-frontend company-echo-metadata-frontend)))

(use-package
  yasnippet
  :ensure t
  :defer t
  :hook (company-mode . yas-minor-mode)
  :config                               ;
  (yas-reload-all))
(use-package
  yasnippet-snippets
  :ensure t
  :config (yas-reload-all))

请问应该如何正确配置,使lsp和yasinppet可以同时进行补全呢?

看了一圈lsp-mode好像没有提供特别好的办法。参考doom的配置,使用hook重新设置backends算是可以正常使用了。

贴下doom的代码:

  (add-hook! 'lsp-completion-mode-hook
    (defun +lsp-init-company-backends-h ()
      (when lsp-completion-mode
        (set (make-local-variable 'company-backends)
             (cons +lsp-company-backends
                   (remove +lsp-company-backends
                           (remq 'company-capf company-backends)))))))

我也遇到这个问题了,我把doom的这段代码放到我的 use-package lsp-mode 里面没有效果呢,楼主可以放出你自己的这段配置让我学习学习么

粗略看了一下上面的代码:add-hook要在lsp执行之前,一般即是打开一个文件的时候。我看了下我这里似乎没有lsp-completion-mode这个变量,可能是因为没更新,你可以看看有没有或者直接去掉它。

lsp-auto-configure是比较有用的,所以这里这个问题我也有。基本是同样用hook在lsp自动设置后再改回来,但是我的方案也有问题,时灵时不灵。所以我的M-:历史里有一句(setq-local company-backends my-company-backends),如果backends不对就手动M-: (setq-local company-backends my-company-backends)……

我找到了楼主了github,下面是配置,在我这里可用,楼主的配置写的好规整

(use-package
  lsp-mode
  :ensure t
  :defer t
  :hook ((lsp-mode . lsp-enable-which-key-integration))
  :init ;;
  ;; (setq lsp-auto-configure nil)
  (setq lsp-prefer-capf t)
  (setq lsp-enable-snippet t)
  (setq lsp-keymap-prefix "C-l")
  (setq lsp-enable-completion-at-point t)
  (setq lsp-keep-workspace-alive nil)
  (setq lsp-enable-file-watchers nil)
  (setq lsp-enable-semantic-highlighting nil)
  (setq lsp-enable-symbol-highlighting nil)
  (setq lsp-enable-text-document-color nil)
  (setq lsp-enable-folding nil)
  (setq lsp-enable-indentation nil)
  (setq lsp-enable-on-type-formatting nil)
  ;; (setq lsp-log-io t)
  (add-hook 'lsp-completion-mode-hook (lambda ()
                                        (when lsp-completion-mode
                                          (set (make-local-variable 'company-backends)
                                               (remq 'company-capf company-backends)))))
  :config (require 'lsp-clients))