先说使用方法:
- samba服务器上安装最新gopls,启动
x.x.x.x是samba的ip地址,不指定ip会默认用ipv6启动。samba服务器上应该有完整的go环境,包括GOROOT/GOPATH这些环境变量配置。nohup gopls serve -listen=x.x.x.x:12345 &
- sublime安装package control(如果已经安装略过):sublime下按ctrl+shift+p,输入"install package control",点击。
- 下载修改过的LSP到sublime的packages目录(Preference-->Browse packages),ctrl+shift+p,输入Satisfy,点击"Package Control: Satisfy Dependencies"
- 配置:Preferences-->Package Settings-->LSP-->Settings,在clients下输入下面这段配置,其中tcp_host和tcp_port改成samba服务器的地址和gopls启动的端口,replace里面的路径则替换成实际的路径,格式是A:B,B是Linux服务器上的路径,A是映射到Windows下的路径,可以添加多个路径。command里面如果Windows装了gopls就写gopls,否则随便写个可执行文件名比如cmd都可以。
"gopls":{ "command":["gopls"], "enabled": true, "languageId": "go", "scopes": ["source.go"], "syntaxes":["Packages/Go/Go.sublime-syntax"], "tcp_port": 12345, "user_config":{ "tcp_host": "x.x.x.x", "uri_replace":{ "pub":[ { "keys":[ ["params", "textDocument", "uri"], ["params", "message"], ["params", "uri"], ["params", "items", "scopeUri"], ["result", "uri"], ["result", "edit", "documentChanges", "textDocument", "uri"] ], "replace":{ "///X:/gocode/":"///home/helloworld/gocode/" } } ] } } }
重启sublime即可。
接下来说一下背景&过程
我们的代码是放在Linux服务器上的,通过samba共享,在Windows环境下编辑。之前用vscode,但是卡顿严重,特别是保存的时候,就改用了sublime text。
用sublime之后,在没有自动补全的环境下写了很长一段时间代码,感觉有点影响效率。网上搜了一下,搜到了篇文章,发现作者遇到的问题和我的很相似,本想直接用,但是作者的路径替换是写死的,想搞成个可配置的,所以参考了作者的方法重新撸了一遍。
先fork了官方的库,然后clone下来。先改了transport以支持远端LSP服务器,这个比较简单,就是在配置里面加个tcp_host的选项,然后在创建socket的时候,如果配置了tcp_host则用tcp_host否则用'localhost'。比较头疼的是,路径替换,在参考的文章里面,作者是直接改了url.py,然后这个模块是一个相对底层的模块,没法引用config(不然会出现import环路)。这里说一下要做路径替换的原因:本地和远端的文件的路径是不一样的,比如sublime打开了x:\gocode\example.go,但是远端是不存在这个文件的,远端对应的文件是/home/helloworld/gocode/example.go,所以要进行路径替换,否则Windows发过去的文件路径远端识别不了,远端返回的文件路径本端也识别不了。
尝试了很多方法,发现都很难把配置传入到url.py里面,所以也先写死用着。然后想抓包看一下sublime和gopls是如何交互的,结果发现即使改了url.py,请求里面还是有一些路径没替换,也就是说有些请求是绕开了url里面的相关函数的。突然想到,在transport里面替换路径是最彻底的,所有请求和响应都要经过transport,而且transport里面已经传入了配置信息(tcp_host),是现成的。根据抓包的信息,配合transport的Python代码,确定了大概要对哪些字段进行替换。写完代码,重启sublime,一切正常。后来搜索抓到的包发现,还有一些字段要替换,只能再次修改代码,感觉这个不大好,于是把要替换的字段也做成了可配置。
一开始是用了settings这个现成的配置来存替换配置,但是抓包发现这个信息是会发送给gopls服务器的,感觉不是很合适,这个毕竟是给client用的配置,于是定义了一个user_define的配置段。
另外发现gopls有个问题,就是如果sublime打开了多个工程的源文件,后打开的工程gopls是无法正确处理的,PWD一直是前面打开的,没看gopls源码,猜测可能是只能有一个PWD。