lsp-bridge -- 速度最快的语法补全插件

@manateelazycat 大佬,我在使用 sdcv 时,遇到关键词比较长的情况, annotation 会显示不出来或显示一半。



当尝试将 lsp-bridge/acm/acm.el 的 acm-menu-render-items 函数中设置 acm-indent-pixel 的部分(第 874~880 行)注释掉后



annotation 就紧跟关键字显示了。尽管有些过长的 annotation 还是无法显示完整,但也比之前好了很多。



当然,这不是 lsp-bridge 本身的问题。因为在绝大多数情况下,这个设置在使用中是很正常显示的。

是我个人自定义 sdcv 词典的问题。所以有一个小小的奢望,大佬是否可以考虑在这一段代码前

 (unless annotation-not-exits
  (propertize " "
              'display
              (acm-indent-pixel
               (if (equal acm-string-width-function 'string-pixel-width)
                   (- (+ acm-menu-max-length-cache (* 20 (string-pixel-width " "))) item-length)
                 (ceiling (* (frame-char-width) (- (+ acm-menu-max-length-cache 20) item-length)))))))



加一个用户可设置的开关,比如类似

(setq custom-acm-indent-pixel nil)

(if (not custom-acm-indent-pixel)
	(unless annotation-not-exits
	  (propertize " "
				  'display
				  (acm-indent-pixel
				   (if (equal acm-string-width-function 'string-pixel-width)
					   (- (+ acm-menu-max-length-cache (* 20 (string-pixel-width " "))) item-length)
					 (ceiling (* (frame-char-width) (- (+ acm-menu-max-length-cache 20) item-length)))))))
  )

当用户不去设置 custom-acm-indent-pixel 时,一切照旧。

当用户开启 custom-acm-indent-pixel 时

(setq custom-acm-indent-pixel t)

就不使用这段代码了,从而实现 annotation 紧跟关键字显示。

只是一个小小的提议或奢望!因为没有太多时间了解 acm-indent-pixel 这个变量对 lsp-bridge 整体的影响。所以如果大佬觉得没必要或比较麻烦、影响整体功能,可以忽略我的这个奢望。我还是会一如既往得开心使用 lsp-bridge 的! :blush:

提交了一个PR,Org roam 在仅有一个完全匹配候选项时不会隐藏补全。

略微修改了注释,使其符合实际表现。如果存在其他候选项,即使其他候选项和第一个完全一致(如 Search Word),补全也不会被隐藏。 如图 Screenshot 2024-06-09 at 11.52.54

另外修复了之前自己提交时的缩进问题,之前我没有关闭 indent-tabs-mode,导致出现了许多 tab。这似乎是默认设置,lsp-bridge 有许多贡献代码的开发者,类似的项目通常使用 .dir-locals.el 来统一格式,如 use-package,是否需要在 lsp-bridge 中也添加?

另一个问题是 acm-quick-access。这一功能在 acm-quick-access-use-number-selectnil (默认值)时,输入数字仍会关闭补全。

这是因为在 acm-mode-map 里,已经定义了 (define-key map "1" #'acm-insert-number-or-complete-candiate),且这一函数默认在 lsp-bridge-completion-stop-commands 中。仅在设置 t 时绑定函数或许是一个不错的选择?

Done

https://github.com/manateelazycat/lsp-bridge/commit/d8a7ce8db749cc15bea37ab4f3d6270fc50c322f

把你的字典想办法给我吧, 我看看能否改一下代码, 我尽量不写脏补丁。

1 个赞

感谢大佬帮助! :blush:
邮件已发,邮件主题为 “sdcv 词典及 annotation”。请大佬查收一下,有空看一下就好,不急。

这个补丁增加了对 csharp:/meta 协议的支持, 从原理上来说, csharp 类似 Java, 跳转定义之前, 都需要从编译器那里临时获取源代码, 然后再创建临时文件写入源代码进行跳转。

1 个赞

我刚刚试了一下, 可以正常显示呀。

:scream:从图片上看,确实显示得很正常。

看来应该是我这边的问题。那我自查修正试试。 :blush:
大佬辛苦啦!非常感谢!:+1:t2:

刚刚合并了社区大佬的补丁

lsp-bridge 现在不但支持远端服务器的代码补全, 还支持远端服务器容器内代码补全!

远端代码补全的设计和VSCode是类似的, 源代码和LSP Server都是运行在远端服务器里的, 这样既可以利用远端服务器的超大编译资源, 又可以做到实时代码补全, 性能嘎嘎的。

3 个赞

你客气了, 有问题随时找我。

1 个赞

建议你升级到 Emacs 29 或者 Emacs 30, Emacs 29 以上支持像素级的对齐。

好的👌🏻。目前使用的是 29.3 版本。
初步推测,可能是我使用了 perfect-margin 居中插件,或者字体设置过大造成的。
一会儿到家后,:face_with_monocle:我先排查一下插件冲突和配置,再安装 30 版本的试试看。然后再向大佬反馈!:blush:

1 个赞

经过测试,确实是与 perfect-margin 和字号大小有关。
在 2k (2560 x 1440) 分辨率, 100% scale 的屏幕显示中, 测试结果为:

我的 emacs 字体大小设置方式为

(set-face-attribute 'default nil :font "SauceCodePro Nerd Font 30" :weight 'ExtraLight)

字体大小 30,不使用 perfect-margin 的显示效果,会显示不完整。所以跟字体大小(或设置方式)有关。



字体大小 24~28 之间,使用 perfect-margin 的效果,显示不完整。所以跟 perfect-margin 有关。



字体大小 28,不使用 perfect-margin,显示完整、正常了。



即使 emacs 在不满屏的状态下,显示也完整、正常。



在不满屏的状态下,偶尔有出现显示不完整的情况。但我个人觉得这不是问题,通常都是满屏使用的,所以无妨。



不满屏的状态下,通过调小字号的方式可以得到完整显示的效果



经过一系列尝试,找出了问题的原因,主要是因为使用了 perfect-margin 这个 package。其次,是我设置的字号过大。

目前设置了合适的字号,关闭 perfect-margin 功能,在使用 sdcv 时已经达到了比较满意的效果。 :blush:特此反馈。

测试用 Emacs 版本为 29.3 和 30,两个版本效果一致
测试系统为 Linux Arch
在 Windows 11 上测试了 Emacs 29.3,效果与 Linux 系统上的一致。

1 个赞

今天推送了几个补丁, 让C#反编译的源代码和当前文件共享一个LSP server, 这样就可以继续在反编译的文件继续跳转其他代码定义了。

Java、C#、Deno这些LSP Server 都有一个特性, 反编译出来的源码必须和原始文件共享 LSP server, 否则会因为缺乏项目信息无法进一步跳转定义。

@manateelazycat 检测languageId 传入的参数有误

id-detect: pro: "/Users/liuyinz/code/repo/day-n-night", fp: "/Users/liuyinz/Code/repo/day-n-night/index.html", server: "/Users/liuyinz/code/repo/day-n-night#vscode-html-language-server", ext: "html", final: nil

我打印出来 pyhton端传来的是

server: "/Users/liuyinz/code/repo/day-n-night#vscode-html-language-server", 应当只传入 server name 就行了, 没必要传入冗余信息,要不然还要截取井号后面的内容才能做匹配.

Done

https://github.com/manateelazycat/lsp-bridge/commit/62721ebf9559a041bdac2f75777c13ec39651735

1 个赞

我发现 任何一种 major-mode 都要在 lsp-bridge-single-lang-server-mode-list 里面有对应的 server, 然后才会进行函数判断,否则的话连判断函数都不会启动, zsh的问题在于它属于 sh-mode

如果我在 lsp-bridge-single-lang-server-mode-list 移除了sh-mode,那么判断函数无法启动, 如果不移除的话,那我在判断函数里识别到了zsh文件,我又无法拦截,因为返回nil的话, bash-language-server还是会作为fallback启动的, 返回其他字段比如 “no-server” 又直接报错.

所以希望在判断函数中增加第三种返回值: stop-match 之类的

  • 如果是 nil, 那么就继续去 mode-list, extension继续查找
  • 如果是 stop-match, 那么就终止server查找,不启动任何server
  • 如果是string, 那么就直接返回

核心问题是 major-mode和 server 也不是一一对应的关系, 也会有其他的情况不需要启动server,所以需要一个终止信号.

我们先梳理一下哈:

lsp-bridge 做启动判断的标准是先看 mode 是否存在 lsp-bridge-default-mode-hooks 中, 只有存在 lsp-bridge-default-mode-hooks 中的 mode 才能加载 lsp-bridge 代码

lsp-bridge 代码加载以后会按照下面的优先级进行依次判断, 如果匹配某一个阶段就启动 lsp server, 都不匹配就自动禁用。

  1. lsp-bridge-get-multi-lang-server-by-project
  2. lsp-bridge-multi-lang-server-extension-list
  3. lsp-bridge-multi-lang-server-mode-list
  4. lsp-bridge-get-single-lang-server-by-project
  5. lsp-bridge-single-lang-server-extension-list
  6. lsp-bridge-single-lang-server-mode-list

针对 zsh 文件这种情况, zsh 首先属于 sh-mode, 也就是 lsp-bridge-default-mode-hooks 默认的 sh-mode-hook 不移除, lsp-bridge 就会尝试启动, 你就可以在上面步骤的第4步 lsp-bridge-get-single-lang-server-by-project 编写自定义规则对 zsh 文件进行拦截呀?

可问题是怎么拦截呢? 识别是zsh文件后返回nil 它就会进行第五步,第六步然后fallback启动 bash-language-server,如果返回非法字符串会直接报错.