Joxos
1
最近看到了company新的替代方案corfu,试了一下,在Windows上和lsp搭配的表现确实不错,但是好像不支持lsp中的snippet,求教各位大佬有没有什么解决方案。
这是与lsp相关的所有配置:
(use-package lsp-mode
:straight t
:custom
(lsp-completion-provider :none)
:init
(defun my/orderless-dispatch-flex-first (_pattern index _total)
(and (eq index 0) 'orderless-flex))
(defun my/lsp-mode-setup-completion ()
(setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
'(orderless)) (setq lsp-mode t))
(add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local)
(setq-local completion-at-point-functions (list (lsp-completion-at-point)))
:hook
((lsp-completion-mode . my/lsp-mode-setup-completion)
(python-mode . (lambda ()
(require 'lsp-pyright)
(lsp)))
这是与corfu有关的所有配置:
(use-package corfu
:straight t
:bind (:map corfu-map
("TAB" . 'corfu-insert)
("<backtab>" . 'corfu-complete)
("RET" . 'newline))
:custom
(corfu-auto t) ;; Enable auto completion
(corfu-quit-at-boundary t) ;; Automatically quit at word boundary
(corfu-quit-no-match t) ;; Automatically quit if there is no match
(corfu-preview-current nil) ;; Disable current candidate preview
:hook ((prog-mode . corfu-mode)
(shell-mode . corfu-mode)
(eshell-mode . (lambda ()
(setq-local corfu-quit-at-boundary t
corfu-quit-no-match t
corfu-auto nil)
(corfu-mode))))
:init
(corfu-global-mode))
在录制GIF时,yas-minor-mode已确认打开。
Joxos
2
我用 Corfu+Eglot,是支持snippet的。
估计是你 lsp-mode 的配置问题
eglot 我基本都没怎么设置
(use-package eglot
:defer t
:bind (:map eglot-mode-map
("C-c l a" . eglot-code-actions)
("C-c l r" . eglot-rename)
("C-c l f" . eglot-format)
("C-c l d" . eldoc))
:hook (eglot-managed-mode . (lambda () (flymake-mode -1)))
:config
(setq read-process-output-max (* 1024 1024))
(push :documentHighlightProvider eglot-ignored-server-capabilities)
(setq eldoc-echo-area-use-multiline-p nil))
Joxos
6
注释掉lsp后使用你的配置,还是没有snippet呀。
请问有没有snippet相关的配置,比如yasnippet?
你安装 yasnippet 和 yasnippet-snippets了吗?你装上这两个包应该就可以了。
这是我的配置:
;; YASnippet
(use-package yasnippet
:diminish yas-minor-mode
:hook ((prog-mode org-mode) . yas-minor-mode)
:bind (("C-c y i" . yas-insert-snippet)
("C-c y f" . yas-visit-snippet-file)
("C-c y n" . yas-new-snippet)
("C-c y t" . yas-tryout-snippet)
("C-c y l" . yas-describe-tables)
("C-c y g" . yas-global-mode)
("C-c y m" . yas-minor-mode)
("C-c y r" . yas-reload-all)
("C-c y x" . yas-expand)
:map yas-keymap
("C-i" . yas-next-field-or-maybe-expand))
:config
(yas-reload-all))
(use-package yasnippet-snippets
:defer t
:after yasnippet)
Joxos
8
大概明白了,你是用corfu补全代码,yasnippet展开snippet(C-i),是吗?
我这边看了一下,snippet是由clangd提供的。我是想可不可以tab补全后直接选中($0),然后再键入呢?
不是的,我就是直接按的回车(corfu-insert)接受补全,然后就会进行snippet的展开,光标就会落在 $0 的位置。
这个功能是 eglot 支持的,跟补全的前端无关(不管你是用 company,corfu,即使是只用默认的completion-at-point 都是可以的)
这是 eglot 官方的展示和解释:GitHub - joaotavora/eglot: A client for Language Server Protocol servers
我估计你的问题是其他配置引起的冲突,因为你 eglot 都没法使用 snippet。建议你用一个干净的配置测试:只安装 lsp-mode + corfu 或者 eglot + corfu 试试。
Joxos
10
多谢!找到原因了,是因为我将[tab]
绑定成了corfu-complete
。
corfu-complete
:
corfu-insert
:
以前一直没有理解这两个之间的差别,而我又想[enter]
直接换行,所以就绑错了。