好, 我知道了, 我看看
我看了一下 lsp-bridge 日志:
--- Send (notification): textDocument/didChange
{
"method": "textDocument/didChange",
"params": {
"textDocument": {
"uri": "file:///home/andy/test.ts",
"version": 14
},
"contentChanges": [
{
"range": {
"start": {
"line": 12,
"character": 11
},
"end": {
"line": 12,
"character": 11
}
},
"rangeLength": 0,
"text": "i"
}
]
},
"jsonrpc": "2.0"
}
Eval in Emacs: (lsp-bridge-search-file-words--record-items '())
--- Send (13176): textDocument/completion
{
"id": 13176,
"method": "textDocument/completion",
"params": {
"position": {
"line": 12,
"character": 12
},
"context": {
"triggerKind": 1
},
"textDocument": {
"uri": "file:///home/andy/test.ts"
}
},
"jsonrpc": "2.0"
}
--- Recv response typescript (13176): textDocument/completion
{
"jsonrpc": "2.0",
"id": 13176,
"result": [
{
"label": "id",
"kind": 5,
"sortText": "11",
"commitCharacters": [
".",
",",
"("
],
"data": {
"file": "/home/andy/test.ts",
"line": 13,
"offset": 13,
"entryNames": [
"id"
]
}
},
{
"label": "name",
"kind": 5,
"sortText": "11",
"commitCharacters": [
".",
",",
"("
],
"data": {
"file": "/home/andy/test.ts",
"line": 13,
"offset": 13,
"entryNames": [
"name"
]
}
}
]
}
上面日志就三句话, this. 以后输入 i
这个字符, 并发送 textDocument/didChange 和 textDocument/completion 请求, LSP Server 服务器返回的内容就包括 id
和 name
的补全列表。
按照道理来说, 输入 i
不应该返回 name
的, 但是 LSP Sever 返回了多余的 name, lsp-bridge 应该遵照协议显示 LSP Server 返回的所有补全项。
这个问题, 你需要研究一下 typescript-language-server 的配置, 或者给 typescript-language-server 报 bug, 这个问题不是 lsp-bridge 的 bug
this.base类型是any时
this.ba 补全 为this.base 然后输入点. 补全项就是tabnine而不是lsp的不匹配的东西
this.ba 继续输入base,没有使用lsp-bridge的补全来补全base时,输入点. 补全项就是lsp的奇怪东西。
这是不是我如果一直不使用lsp的补全,弹出的就一直还是最开头哪个this的补全项啊。。。。
用 lsp-mode
测了情况刚好相反,输入 i
之后就收不到 completion
返回了:
[Trace - 03:06:48 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 1
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 12
},
"end": {
"line": 10,
"character": 12
}
},
"rangeLength": 0,
"text": "."
}
]
}
[Trace - 03:06:48 PM] Sending request 'textDocument/completion - (22)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
},
"position": {
"line": 10,
"character": 13
},
"context": {
"triggerKind": 2,
"triggerCharacter": "."
}
}
[Trace - 03:06:48 PM] Received response 'textDocument/completion - (22)' in 50ms.
Result: {
"items": [
{
"label": "id",
"kind": 5,
"sortText": "11",
"commitCharacters": [
".",
",",
"("
],
"data": {
"file": "/Users/gqj/Downloads/test.ts",
"line": 11,
"offset": 14,
"entryNames": [
"id"
]
}
},
{
"label": "name",
"kind": 5,
"sortText": "11",
"commitCharacters": [
".",
",",
"("
],
"data": {
"file": "/Users/gqj/Downloads/test.ts",
"line": 11,
"offset": 14,
"entryNames": [
"name"
]
}
}
],
"isIncomplete": null
}
[Trace - 03:06:48 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/gqj/Downloads/test.ts",
"diagnostics": [
{
"range": {
"start": {
"line": 11,
"character": 8
},
"end": {
"line": 11,
"character": 12
}
},
"message": "Property 'this' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
[Trace - 03:06:50 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 2
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 13
}
},
"rangeLength": 0,
"text": "i"
}
]
}
[Trace - 03:06:50 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/gqj/Downloads/test.ts",
"diagnostics": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"message": "Property 'i' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
[Trace - 03:06:50 PM] Sending request 'textDocument/documentSymbol - (23)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
}
}
[Trace - 03:06:50 PM] Sending request 'textDocument/codeAction - (24)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
},
"range": {
"start": {
"line": 10,
"character": 14
},
"end": {
"line": 10,
"character": 14
}
},
"context": {
"diagnostics": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"message": "Property 'i' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
}
[Trace - 03:06:50 PM] Received response 'textDocument/documentSymbol - (23)' in 28ms.
Result: [
{
"name": "User",
"detail": "",
"kind": 11,
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 3,
"character": 1
}
},
"selectionRange": {
"start": {
"line": 0,
"character": 10
},
"end": {
"line": 0,
"character": 14
}
},
"children": [
{
"name": "id",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 2,
"character": 4
},
"end": {
"line": 2,
"character": 15
}
},
"selectionRange": {
"start": {
"line": 2,
"character": 4
},
"end": {
"line": 2,
"character": 6
}
},
"children": []
},
{
"name": "name",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 1,
"character": 4
},
"end": {
"line": 1,
"character": 17
}
},
"selectionRange": {
"start": {
"line": 1,
"character": 4
},
"end": {
"line": 1,
"character": 8
}
},
"children": []
}
]
},
{
"name": "UserAccount",
"detail": "",
"kind": 5,
"range": {
"start": {
"line": 5,
"character": 0
},
"end": {
"line": 14,
"character": 1
}
},
"selectionRange": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 17
}
},
"children": [
{
"name": "constructor",
"detail": "",
"kind": 9,
"range": {
"start": {
"line": 9,
"character": 4
},
"end": {
"line": 13,
"character": 5
}
},
"selectionRange": {
"start": {
"line": 9,
"character": 4
},
"end": {
"line": 13,
"character": 5
}
},
"children": []
},
{
"name": "id",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 7,
"character": 4
},
"end": {
"line": 7,
"character": 15
}
},
"selectionRange": {
"start": {
"line": 7,
"character": 4
},
"end": {
"line": 7,
"character": 6
}
},
"children": []
},
{
"name": "name",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 17
}
},
"selectionRange": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 8
}
},
"children": []
}
]
}
]
[Trace - 03:06:50 PM] Received response 'textDocument/codeAction - (24)' in 28ms.
Result: []
[Trace - 03:07:16 PM] Sending request 'textDocument/codeAction - (25)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
},
"range": {
"start": {
"line": 10,
"character": 14
},
"end": {
"line": 10,
"character": 14
}
},
"context": {
"diagnostics": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"message": "Property 'i' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
}
[Trace - 03:07:16 PM] Received response 'textDocument/codeAction - (25)' in 5ms.
Result: []
[Trace - 03:07:17 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 3
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"rangeLength": 1,
"text": ""
}
]
}
[Trace - 03:07:18 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 4
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 12
},
"end": {
"line": 10,
"character": 13
}
},
"rangeLength": 1,
"text": ""
}
]
}
[Trace - 03:07:18 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/gqj/Downloads/test.ts",
"diagnostics": []
}
[Trace - 03:07:18 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 5
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 12
},
"end": {
"line": 10,
"character": 12
}
},
"rangeLength": 0,
"text": "."
}
]
}
[Trace - 03:07:18 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/gqj/Downloads/test.ts",
"diagnostics": [
{
"range": {
"start": {
"line": 11,
"character": 8
},
"end": {
"line": 11,
"character": 12
}
},
"message": "Property 'this' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
[Trace - 03:07:19 PM] Sending notification 'textDocument/didChange'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts",
"version": 6
},
"contentChanges": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 13
}
},
"rangeLength": 0,
"text": "i"
}
]
}
[Trace - 03:07:20 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
"uri": "file:///Users/gqj/Downloads/test.ts",
"diagnostics": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"message": "Property 'i' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
[Trace - 03:07:20 PM] Sending request 'textDocument/documentSymbol - (26)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
}
}
[Trace - 03:07:20 PM] Sending request 'textDocument/codeAction - (27)'.
Params: {
"textDocument": {
"uri": "file:///Users/gqj/Downloads/test.ts"
},
"range": {
"start": {
"line": 10,
"character": 14
},
"end": {
"line": 10,
"character": 14
}
},
"context": {
"diagnostics": [
{
"range": {
"start": {
"line": 10,
"character": 13
},
"end": {
"line": 10,
"character": 14
}
},
"message": "Property 'i' does not exist on type 'UserAccount'.",
"severity": 1,
"code": 2339,
"source": "typescript",
"tags": []
}
]
}
}
[Trace - 03:07:20 PM] Received response 'textDocument/documentSymbol - (26)' in 27ms.
Result: [
{
"name": "User",
"detail": "",
"kind": 11,
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 3,
"character": 1
}
},
"selectionRange": {
"start": {
"line": 0,
"character": 10
},
"end": {
"line": 0,
"character": 14
}
},
"children": [
{
"name": "id",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 2,
"character": 4
},
"end": {
"line": 2,
"character": 15
}
},
"selectionRange": {
"start": {
"line": 2,
"character": 4
},
"end": {
"line": 2,
"character": 6
}
},
"children": []
},
{
"name": "name",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 1,
"character": 4
},
"end": {
"line": 1,
"character": 17
}
},
"selectionRange": {
"start": {
"line": 1,
"character": 4
},
"end": {
"line": 1,
"character": 8
}
},
"children": []
}
]
},
{
"name": "UserAccount",
"detail": "",
"kind": 5,
"range": {
"start": {
"line": 5,
"character": 0
},
"end": {
"line": 14,
"character": 1
}
},
"selectionRange": {
"start": {
"line": 5,
"character": 6
},
"end": {
"line": 5,
"character": 17
}
},
"children": [
{
"name": "constructor",
"detail": "",
"kind": 9,
"range": {
"start": {
"line": 9,
"character": 4
},
"end": {
"line": 13,
"character": 5
}
},
"selectionRange": {
"start": {
"line": 9,
"character": 4
},
"end": {
"line": 13,
"character": 5
}
},
"children": []
},
{
"name": "id",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 7,
"character": 4
},
"end": {
"line": 7,
"character": 15
}
},
"selectionRange": {
"start": {
"line": 7,
"character": 4
},
"end": {
"line": 7,
"character": 6
}
},
"children": []
},
{
"name": "name",
"detail": "",
"kind": 7,
"range": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 17
}
},
"selectionRange": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 8
}
},
"children": []
}
]
}
]
[Trace - 03:07:20 PM] Received response 'textDocument/codeAction - (27)' in 28ms.
Result: []
用 eglot
也是收到多余的项,但是 eglot 最终给用户的反馈却是正常的,不知它做了什么特别处理:
[client-notification] Thu Nov 3 19:41:39 2022:
(:jsonrpc "2.0" :method "textDocument/didChange" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts" :version 15)
:contentChanges
[(:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 13))
:rangeLength 0 :text "i")]))
[client-request] (id:64) Thu Nov 3 19:41:39 2022:
(:jsonrpc "2.0" :id 64 :method "textDocument/completion" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 14)
:context
(:triggerKind 1)))
[server-reply] (id:64) Thu Nov 3 19:41:39 2022:
(:jsonrpc "2.0" :id 64 :result
(:items
[(:label "id" :kind 5 :sortText "11" :commitCharacters
["." "," "("]
:data
(:file "/Volumes/HDD/Users/gqj/Downloads/test.ts" :line 11 :offset 15 :entryNames
["id"]))
(:label "name" :kind 5 :sortText "11" :commitCharacters
["." "," "("]
:data
(:file "/Volumes/HDD/Users/gqj/Downloads/test.ts" :line 11 :offset 15 :entryNames
["name"]))]
:isIncomplete :json-false))
[client-request] (id:65) Thu Nov 3 19:41:39 2022:
(:jsonrpc "2.0" :id 65 :method "completionItem/resolve" :params
(:label
#("id" 0 1
(eglot--lsp-item #1))
:kind 5 :sortText "11" :commitCharacters
["." "," "("]
:data
(:file "/Volumes/HDD/Users/gqj/Downloads/test.ts" :line 11 :offset 15 :entryNames
["id"])))
[server-reply] (id:65) Thu Nov 3 19:41:39 2022:
(:jsonrpc "2.0" :id 65 :result
(:label "id" :kind 5 :sortText "11" :commitCharacters
["." "," "("]
:data
(:file "/Volumes/HDD/Users/gqj/Downloads/test.ts" :line 11 :offset 15 :entryNames
["id"])
:detail "(property) UserAccount.id: number"))
[server-notification] Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :method "textDocument/publishDiagnostics" :params
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts" :diagnostics
[(:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 14))
:message "Property 'i' does not exist on type 'UserAccount'." :severity 1 :code 2339 :source "typescript" :tags
[])]))
[client-request] (id:66) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 66 :method "textDocument/signatureHelp" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 14)))
[client-request] (id:67) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 67 :method "textDocument/hover" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 14)))
[client-request] (id:68) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 68 :method "textDocument/documentHighlight" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 14)))
[server-reply] (id:66) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 66 :result nil)
[server-reply] (id:67) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 67 :result
(:contents
(:kind "markdown" :value "\n```typescript\nany\n```\n")
:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 14))))
[server-reply] (id:68) Thu Nov 3 19:41:40 2022:
(:jsonrpc "2.0" :id 68 :result
[])
[client-notification] Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :method "textDocument/didChange" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts" :version 17)
:contentChanges
[(:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 14))
:rangeLength 1 :text "")
(:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 13))
:rangeLength 0 :text "id")]))
[client-request] (id:69) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 69 :method "textDocument/signatureHelp" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 15)))
[client-request] (id:70) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 70 :method "textDocument/hover" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 15)))
[client-request] (id:71) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 71 :method "textDocument/documentHighlight" :params
(:textDocument
(:uri "file:///Volumes/HDD/Users/gqj/Downloads/test.ts")
:position
(:line 10 :character 15)))
[server-reply] (id:69) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 69 :result nil)
[server-reply] (id:70) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 70 :result
(:contents
(:kind "markdown" :value "\n```typescript\n(property) UserAccount.id: number\n```\n")
:range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 15))))
[server-reply] (id:71) Thu Nov 3 19:41:48 2022:
(:jsonrpc "2.0" :id 71 :result
[(:kind 2 :range
(:start
(:line 7 :character 4)
:end
(:line 7 :character 6)))
(:kind 2 :range
(:start
(:line 10 :character 13)
:end
(:line 10 :character 15)))
(:kind 2 :range
(:start
(:line 12 :character 13)
:end
(:line 12 :chara
那是补全前端按照前缀过滤了。
你要研究 typescript-language-server 的文档, 我不知道啊。
我给 typescript language server 提了 issue:
想要尽快解决问题,当然是报给最熟悉相关代码的人,一直在这里讨论很难有什么实质进展。
其实 typescript-language-server 没错,它返回的结果是完整结果,也就是 isIncomplete: false
,即 this.
和 this.i
补全项相同。
可能目前大多数所用的 ls 返回结果都是 incomplete,所以 lsp-bridge 显示正常,因而鲜有人报 bug。而 lsp-mode/eglot 上有前端过滤,所以 isIncomplete
是啥也不影响用户。
我测试了几款 ls,情况如下:
server | isIncomplete 值 | 实际结果集 | 结果符合预期 | lsp-bridge 显示 |
---|---|---|---|---|
pyright | True | incomplete | 符合✅ | 无多余的项 |
pylsp | False | incomplete | 不符 | 无多余的项 |
jedi | False | incomplete | 不符。可能传染给了 pylsp | 无多余的项 |
gopls | True | incomplete | 符合✅ | 无多余的项 |
rust-analyzer | True | complete | 不符 | 有多余的项🐞 |
typescript-language-server | False | complete | 符合✅ | 有多余的项🐞 |
solargraph | False | incomplete | 不符 | 无多余的项 |
所以我认为 lsp-bridge 也需要处理一下这个问题。
首先我试着在 completion.py 中过滤补全项,但是发现 lsp-bridge 会缓存上一次请求的结果,因此在 completion.py 中过滤会有漏网之虞:
- 输入
self.
(所有补全项已缓存) - 按
C-g
关闭补全菜单 - 按
i
激活补全 此时lsp-bridge
会先从缓存读取补全项(所有),然后再向 ls 发起请求,得到符合self.i
的补全项。
所以改为在 acm/acm-backend-lsp.el:acm-backend-lsp-candidates
中过滤。
这是我的修改 (鉴于目前发现存在 language server 错误标识 isIncomplete 的情况,所以一律对补全项进行过滤): Filter lsp completion · twlz0ne/lsp-bridge@ac5b1ac · GitHub
大佬测试这么多语言, 很严谨呀!
但是我强烈不建议在 Elisp 端做过滤, 因为像 volar 这样的变态 LSP Server, 它最多可以返回上万条的候选词列表, 如果在 Elisp 端做任何过滤, 都有可能导致用户输入一个字符就要对一万条候选词做Elisp模糊匹配, 最终结果是用户肉眼可见的前端补全 frame 卡顿。
大佬说的缓存的问题, 不应该存在啊, 因为 acm 菜单关闭后就会调用 acm-backend-lsp-clean lsp-bridge/acm-backend-lsp.el at fc7384d2850ad580fc32ecb490333fb4438cc099 · manateelazycat/lsp-bridge · GitHub 默认清空LSP返回的候选词列表, 是不是大佬的 acm-terminal.el 没有做 lsp-bridge/acm.el at fc7384d2850ad580fc32ecb490333fb4438cc099 · manateelazycat/lsp-bridge · GitHub 这个操作呀?
是我疏于对上游代码的跟踪了。
那就改为在 python 中过滤。
大佬, 有空还是把 acm-terminal.el 合并入 lsp-bridge 分支呀, 我改啥API的时候就一起帮你改了, 两个人干活搭把手。
好吧。我这几天看看。
大佬辛苦啦, 大家都很期待 acm-terminal.el, 我水平不够, 一直没有把 overlay frame 搞定。
折煞我也,担不起大佬这个称呼。
@manateelazycat @Young-people 过滤(在Python端)补丁已经 PR Filter lsp completion if isIncomplete is False by twlz0ne · Pull Request #401 · manateelazycat/lsp-bridge · GitHub 暂采用 fuzzy match。
那几个乱标 isIncomplete
的,要不要给他们提 issue?
我感觉老王喊人“大佬”就跟其他人喊“兄弟”一个意思。
哈哈哈, 兄弟好。
代码已经合并, 感谢大佬给力补丁。