VSCode 擴展入門,後綴代碼補全的實現

我們項目組使用了 protobuf 作爲傳輸協議,其好處不用多說。可是由於 go 默認數字類型是 int,且 go 屬於強類型語言,切換類型就成了家常便飯。

一般來說,切換類型的步驟不外乎:

  1. 選中數字部分。
  2. 加括號。
  3. 輸入新類型。

時間長了,不免覺得有些複雜。 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 語言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章