我們項目組使用了 protobuf 作爲傳輸協議,其好處不用多說。可是由於 go 默認數字類型是 int,且 go 屬於強類型語言,切換類型就成了家常便飯。
一般來說,切換類型的步驟不外乎:
- 選中數字部分。
- 加括號。
- 輸入新類型。
時間長了,不免覺得有些複雜。 Goland 是支持自定義後綴代碼補全的,只需要合理設置即可。
而 vscode + gopls 沒有對後綴代碼補全的支持,需要通過擴展支持。 已有的插件 https://github.com/yokoe/vscode-postfix-go 是一個接近的選擇,支持 len
這類表達。可惜沒有提供 int
相關的支持。
在 issue 提出建議沒有收到迴應後,我決定在他的基礎進行補充,畢竟兩種表達相差不多。
Fork
首先將原項目 fork 出來,對作者信息以及許可證進行修改。
npm
vscode 擴展是通過 ts/js 實現的,自然少不了 npm 的使用。在 sudo pacman -S npm
安裝好 npm 後,在項目目錄使用 sudo npm install
進行安裝。雖然不熟悉 npm 但我想這一步和 go install
應該相差無幾。
~/code/vscode-postfix-go (master) [05:14:53]
p1gd0g$sudo npm install
> [email protected] postinstall
> node ./node_modules/vscode/bin/install
Detected VS Code engine version: ^1.12.0
Found minimal version that qualifies engine range: 1.12.0
Fetching vscode.d.ts from: https://raw.githubusercontent.com/Microsoft/vscode/72672be0b7d3eef0784077b880615f91b7ec85aa/src/vs/vscode.d.ts
vscode.d.ts successfully installed!
Code
在項目中很容易就可以找到對應後綴代碼補全的代碼。
比如 len 的實現:
export class LenTemplate extends BaseExpressionTemplate {
buildCompletionItem (code: string, position: vsc.Position) {
const dotIdx = code.lastIndexOf('.', position.character)
const codeBeforeDot = code.substr(0, dotIdx)
let lastComponent = getLastComponent(codeBeforeDot)
let builder = CompletionItemBuilder
.create('len', lastComponent)
.description(`len(expr)`)
builder.insertText('len(' + lastComponent + ')')
builder.deleteTextBeforeCursor(position, lastComponent.length + 1)
return builder.build()
}
}
和 type 的實現:
export class TypeTemplate extends BaseExpressionTemplate {
constructor (private keyword: string) {
super()
}
buildCompletionItem (code: string, position: vsc.Position) {
return CompletionItemBuilder
.create(this.keyword, code)
.description(`type expr ${this.keyword}`)
.replace(`type {{expr}} ${this.keyword} {\n${getIndentCharacters()}\${0}\n}`, position, true)
.build()
}
}
我們要做的就是將兩者結合起來。我想即使是沒有接觸 js/ts 的同學,只要有一定的基礎,不難完成這一目標。 具體的思路不做介紹,結果如下:
export class IntTemplate extends BaseExpressionTemplate {
constructor(private keyword: string) {
super()
}
buildCompletionItem(code: string, position: vsc.Position) {
const dotIdx = code.lastIndexOf('.', position.character)
const codeBeforeDot = code.substr(0, dotIdx)
let lastComponent = getLastComponent(codeBeforeDot)
let builder = CompletionItemBuilder
.create(this.keyword, lastComponent)
.description(this.keyword + '(expr)')
builder.insertText(this.keyword + '(' + lastComponent + ')')
builder.deleteTextBeforeCursor(position, lastComponent.length + 1)
return builder.build()
}
}
Debug
通過 vscode 自帶的調試,就可以看到我們想要的結果。
Package & Publish
打包和發佈的流程請參考官方文檔。https://code.visualstudio.com/api/working-with-extensions/publishing-extension
發佈成功後即可在 vscode 擴展上商店中看到我們自己的擴展。
以上內容不限於 go 語言。