kigo64
183
突然想到,不知道把 lsp-bridge-record-completion-items
加入到 corfu-auto-commands
有没有作用:
(defun lsp-bridge-record-completion-items (filepath prefix common items)
(dolist (buffer (buffer-list))
(when (string-equal (buffer-file-name buffer) filepath)
(setq-local lsp-bridge-completion-items items)
(setq-local lsp-bridge-completion-prefix prefix)
(setq-local lsp-bridge-completion-common common)
(message "lsp-bridge-record-completion-items: %s" items)
)))
(with-eval-after-load 'corfu
(add-to-list 'corfu-auto-commands 'lsp-bridge-record-completion-items)
)
试了一下,corfu 里面的补全项和 lsp-bridge-completion-items
一样。(只测试了 Python)
发现了 corfu 的一个bug, 发了个 PR 上去
2 个赞
把 lsp-bridge 和 corfu 放到一起宣传吧,哈哈哈哈哈。
1 个赞
嗯嗯,可以,必须的,我已经切到corfu有一段时间了
我有时间试一下 volar ,它的 takeover 模式有点麻烦
1 个赞
你这个补丁竟然修复了 corfu 在 Windows 系统上显示图标的一个 bug。不过对 kind-icon 有副作用。
可能还有别的问题。
加了补丁后全部能正常显示,只是后面多了半行。
没加补丁的话,后面的一行会被切掉一半。
如果行距调大的话,还会缩放图标,因为补丁改成了自动调整。
kigo64
190
我这样是有结果的,但是我不确定这种情况下是打字触发的还是 lsp-bridge 触发的
lsp-bridge 现在是文件有变动 0.1s 后向 lsp-server 请求补全。
一个新逻辑不知道会不会更好:capf 补全时候检查当前位置和之前位置是否属于同一个 symbol, 如果是,直接获取 lsp-bridge-completion-items;如果不是,向 lsp-bridge 发送补全请求,lsp-bridge 再找 lsp-server 请求。类似这样:
(defvar lsp-bridge--start nil)
(defun lsp-bridge-capf (&optional arg)
(let* ((bounds (bounds-of-thing-at-point 'symbol))
(start (or (car bounds) (point)))
(end (or (cdr bounds) (point))))
(if (equal start lsp-bridge--start)
(list start end
lsp-bridge-completion-items
:exclusive 'no)
(setq lsp-bridge--start start)
(lsp-bridge-call-async "do_completion" lsp-bridge-filepath (line-number-at-pos) (current-column) (lsp-bridge-char-before)) ;; do_completion 是 py 那边定义的函数,直接调用 `self.completion`。 同时取消 change_file 里面补全部分
(list start end '())
)))
这种基于位置的一般都比较脆弱,因为不光有添加,还有删除的逻辑,前后两次如果不是 self-insert-command, 一些高级文本操作有可能会导致 (point) 是相同但是内容不一样的情况。
不建议取巧,这种设计一旦遇到bug了,都不好反馈问题,哈哈哈哈。
好像 windows 下面用不了, enable-debug 和 log 之后看到一堆线程启动退出的 log。暂时不太方便研究,看其他人有没有遇到过。
应该是自动调整的,要不是 frame 内部完全靠各种加加减减,很难算对,而且代码还巨复杂。
1 个赞
Windows 下已经有人成功使用了,更新最新版本以后,看看能否重现问题。
corfu 里有这样一种操作,输入corfu-separator(默认是 shift+space),可以用作 orderless分隔符。如图,输入 a[shift+space]string可以继续匹配 a_long_long_string
.
但是现有 lsp-bridge 里会破坏这种行为。没太细研究,但是猜测原因可能是 change_file 触发 lsp-bridge 把他当成 a string
去做补全了
以后可以探测 corfu 的这种状态,避免发送 change_file 请求,我先研究一下 corfu 的文档,看看晚上能否把图标给弄了。
kigo64
198
lsp 的回包里面的 “kind” 就是图标了:
[{'label': 'a_long_long_string', 'kind': 6, 'data': {'workspacePath': '/Users/lijie/proj/test/main.py', 'filePath': '/Users/lijie/proj/test/main.py', 'position': {'line': 4, 'character': 6}, 'symbolLabel': 'a_long_long_string'}, 'sortText': '09.9999.a_long_long_string'}]
把 lsp-mode 里面的枚举抄过来,然后在 capf 的返回值里面加上 :company-kind
就行了, annotation 也差不多:
(defun lsp-bridge-capf ()
(let (
(bounds (bounds-of-thing-at-point 'symbol)))
(list (or (car bounds) (point))
(or (cdr bounds) (point))
lsp-bridge-completion-items
:exclusive 'no
:company-kind
(lambda (candidate) "Set icon here" (get-text-property 0 'kind candidate))
:annotation-function
(lambda (candidate)
"Extract annotation from CANDIDATE."
(get-text-property 0 'annotation candidate)))))
还有 :exit-function
, 后续展开 snippet 可以放在这里处理
我还没有研究 corfu 的代码,一般都是挂在 pre-command-hook 后面做命令或者按键事件拦截,我的理解,只有是 Emacs 的用户按键命令才会被 corfu-auto-commands 过滤到。
lsp-bridge-record-completion-items 完全是 Python 进程通过 IPC 进行的远程调用,Emacs没法从 pre-command-hook 拦截到。
kigo64
201
这样可以获取,但是需要 lsp-bridge 把 kind 传过来,然后写进 property. 可以参考 eglot-completion-at-point 的实现。
kind 需要在 python 代码里面处理,因为处理返回的 json 代码在那里面,比如放在 lsp-bridge-record-completion-items 调用里面作为参数传回来。现在的 lsp-bridge-record-completion-items 里面只获取了 label 这个属性。