Edited at

vim-lspでできること

最近になってようやくlspを使い始めたのですが、結局補完とエラー取得と定義ジャンプしかしていないなーと思ったので、他にどんな事ができるのかを調べて見ました。

設定方法等はvim-lspのREADMEWikiを見たら行けるかと思います。

基本的にはヘルプで確認すればいいんですが、僕のLSPに対する知識のなさと英語力のなさで結構わからない事があったのでメモがわりに書きます。

基本的にできることは次の通りです。

Command
Description

:LspCodeAction
Gets a list of possible commands that can be applied to a file so it can be fixed (quick fix)

:LspDeclaration
Go to declaration

:LspDefinition
Go to definition

:LspDocumentDiagnostics
Get current document diagnostics information

:LspDocumentFormat
Format entire document

:LspDocumentRangeFormat
Format document selection

:LspDocumentSymbol
Show document symbols

:LspHover
Show hover information

:LspImplementation
Show implementation of interface

:LspNextError
jump to next error

:LspPreviousError
jump to previous error

:LspReferences
Find references

:LspRename
Rename symbol

:LspStatus
Show the status of the language server

:LspTypeDefinition
Go to type definition

:LspWorkspaceSymbol
Search/Show workspace symbol

上から一つづつ見ていこうと思います。


LspCodeAction


Gets a list of possible commands that can be applied to a file so it can be

fixed (quick fix).


codeに対して可能なコマンドのリストを取得するみたいな感じですね。

go・python等で試して見たんですけど、何も出てこなかったのでどういうコマンドかわかる人がいれば教えていただけると助かります:bow:


LspDeclaration


Go to declaration. Useful for languages such as C/C++ where there is a clear

distinction between declaration and definition.


宣言場所へのジャンプですかね。

CやC++みたいに宣言する場所と実装する場所が異なる言語で使用可能のようです。

僕にはあまり使う場面が想像できなかったので特にこのメソッドを使うことは無いかな。


LspDefinition


Go to definition.


これは定義場所にジャンプしてくれるメソッドのようです。

カーソルの下にあるメソッドを定義している場所に飛んでくれます。


LspDocumentDiagnostics


Gets the current document diagnostics.


ファイルの診断を行ってくれます。

要するに、errorやwarningの取得みたいな感じらしい。

quickfixでエラーの場所を表示してくれます。

以下の変数を1, 0(defaultは1)を切り替えることで、診断を自動で行うかを判断してくれるらしい。

vimが重たいなと思ったら、0にするのもいいかもしれない。

また、別のプラグインを使う場合にも0にしておくと競合しなくて済みそう。


.vimrc

let g:lsp_diagnostics_enabled = 0


また、エラーの表示をファイルに直接したい場合は以下のような設定でsign表示の設定をすればいいです。

※ 現在(2019/3/6)signの表示はneovimではできないらしい。詳しくはissueを確認してください。

→ 対応したみたいです。(2019/8/8追記)


.vimrc

let g:lsp_signs_enabled = 1

let g:lsp_diagnostics_echo_cursor = 1

他に、signのアイコンなどを変えたい場合は以下のように設定できます。


.vimrc

let g:lsp_signs_error = {'text': '✗'}

let g:lsp_signs_warning = {'text': '‼', 'icon': '/path/to/some/icon'}
let g:lsp_signs_hint = {'icon': '/path/to/some/other/icon'}


LspDocumentFormat


Format the entire document.


現在開いているファイルのフォーマットを修正してくれるらしいです。

これは結構便利そう。

保存時に使うにはLspDocumentFormatSyncを使ってください。

同期処理をしないとFormat修正が保存されないからかな?

ただし、保存時に動作を持って行かれるので、中断されるのが嫌な人は使わない方がいいかも?


.vimrc

autocmd BufWritePre <buffer> LspDocumentFormatSync



LspDocumentRangeFormat


Format the current document selection.


これは選択範囲をFormatしてくれるみたいですね。

特に説明いらないかも。

というか使わないかも。。


LspDocumentSymbol


Gets the symbols for the current document.


そのドキュメントの中のシンボルが出ます。

以下のようなgoのファイルで実行すると、quickfixウィンドウで以下のようなその下のような結果が出ます。

定義場所にジャンプするのに便利かもしれないけど、これもあまり使う機会が無いかも?


main.go

package main

import "fmt"

type testStruct struct {
content string
}

func (a testStruct) Print() {
fmt.Println(a.content)
}

func main() {
var a = testStruct{content: "テスト"}
a.Print()
}



quickfix

main.go|6 col 2| field : content

main.go|5 col 6| class : testStruct
main.go|9 col 16| method : Print
main.go|13 col 6| function : main
main.go|14 col 6| variable : a


LspHover


Gets the hover information and displays it in the |preview-window|.


現在のカーソルの下にあるシンボルの情報をpreview windowに出してくれるらしいですね。

よくIDE等にある↓みたいな動きをイメージしてると思うんですけど、あまりvimでは使わないかも。。

hovers.gif

⬇︎ 2019/8/8 追記

vimのpopupやneovimのfloating windowに対応したみたいなので、以下のような表示になります。

パッと確認したい時に便利です!!

僕は何かのシンボルについて調べたい時は:LspHoverでざっくり確認

→ もうちょっと詳しく調べたい時は :LspDefinition:LspTypeDefinitionで定義場所に飛んで確認する。

というように使っています。

スクリーンショット 2019-08-08 12.00.48.png


LspImplementation


Find all implementation of interface.


全実装とinterfaceを見つけ出してくれるみたいです。

以下のようなコードがあったとします。(#の左側がカーソルの位置)


main.go

package main

import "fmt"

type testInterface interface {
print()
}

type testStruct struct {
content string
}

func (a testStruct) print() {
fmt.Println(a.content)
}

func main() {
var a testInterface
a# = testStruct{content: "テスト"}
a.print()
}


ここで:LspImplementationと入力すると、以下のようなquickfixウィンドウが出てきます。

こんな感じで、aの構造体が実装されている場所とinterfaceの場所が出てきます。

Language Serverにはbingoを使っているんですが、2つ同じ物が出てくるのはバグなんでしょうか。。

main.go|5 col 6| type testInterface interface {

main.go|9 col 6| type testStruct struct {
main.go|9 col 6| type testStruct struct {
main.go|5 col 6| type testInterface interface {

メソッドにもこのコマンドは使えるみたいで先程の main.goの a.print()print()の部分にカーソルを置いて、:LspImplementationを実行すると、以下のような結果になります。

testInterface の部分への参照も出てますね!

testStructprint()への参照が2つ含まれてるのも相変わらずですが。。

main.go|6 col 2| print()

main.go|13 col 21| func (a testStruct) print() {
main.go|13 col 21| func (a testStruct) print() {


LspNextError


Jump to Next err diagnostics


これはdiagnosticsの次のエラーにジャンプするためのコマンドですね


LspPreviousError


Jump to Previous err diagnostics


これはdiagnosticsの前のエラーにジャンプするためのコマンドですね

:LspNextError:LspPreviousErrorは使う場合は、vimrcにショートカットキーを追加しておくといいかと思います。

例)

nnoremap <silent> ]e  :LspNextError<CR>

nnoremap <silent> [e :LspPreviousError<CR>


LspReferences


Find all references.


これはカーソル以下にあるシンボルがどこで参照されているのかを見つけるためのコマンドみたいです。

以下のようなコードがあるとします。(#の左側がカーソルの位置)


main.go

package main

import "fmt"

type testInterface interface {
print()
}

type testStruct struct {
content string
}

func (a testStruct) print() {
fmt.Println(a.content)
}

func main() {
var a testInterface
a# = testStruct{content: "テスト"}
a.print()

a.print()

a.print()
}


ここで:LspReferencesを実行すると以下のような結果になります。

変数aがその下で参照されている場所が表示されているのが分かります。


quickfix

main.go|19 col 2| a = testStruct{content: "テスト"}

main.go|20 col 2| a.print()
main.go|22 col 2| a.print()
main.go|24 col 2| a.print()


LspRename


Rename the symbol.


これはカーソルの下にあるシンボルの名前を変更するコマンドです。

そのシンボルが関連する名前を全て変えてくれるものです。


main.go

package main

import "fmt"

type testInterface interface {
print()
}

type testStruct struct {
content string
}

func (a testStruct) print() {
fmt.Println(a.content)
}

func main() {
var a testInterface
a# = testStruct{content: "テスト"}
a.print()

a.print()

a.print()
}


このときに :LspRenameを行うとmain関数の中で出てくる全ての aという変数が指定した名前に変更されます。

これは結構便利そうですね。


LspStatus


Prints the status of all registered servers.


これはサーバーの状態が表示されます。

ステータスには以下の6つがあります。

サーバーが正常に起動していれば、runningになるかと思います。


  • unknown server

  • exited

  • starting

  • failed

  • running

  • not running


LspTypeDefinition


Go to the type definition.


これはそのシンボルのタイプへの定義ジャンプになります。

例えば以下のようなファイルがあるとします。(#の左側がカーソルの位置)


main.go

package main

import "fmt"

type testInterface interface {
print()
}

type testStruct struct {
content string
}

func (a testStruct) print() {
fmt.Println(a.content)
}

func main() {
var a testInterface
a# = testStruct{content: "テスト"}
a.print()

a.print()

a.print()
}


ここで:LspDefinitionを行うと、aが定義されている行にジャンプするので以下の行の場所にジャンプします。

    var a testInterface

しかし、 :LspTypeDefinitionを用いるとaのタイプであるtestInterfaceの定義場所までジャンプします。

type testInterface interface {

:LspDefinition:LspTypeDefinitionは使い分けが少し難しいですが、結構使えるのではないかなと思います。


LspWorkspaceSymbol


Search and show workspace symbols.


これはWorkspace全体のSymbolを検索するためのコマンドみたいです。

先程の:LspDocumentSymbolではそのファイルで定義されているシンボルのみの検索でしたが、他にもimportしたファイルなどのシンボルまで検索できるようでした。

実際に以下のようなファイルで:LspWorkspaceSymbolを実行して、printを検索してみます。

すると、main.goで定義したprint以外にimportしているfmtprintまで出てきました。

どのようなコマンドが使えるのかを調べるときに便利なのかもしれないです。


main.go

package main

import "fmt"

type testInterface interface {
print()
}

type testStruct struct {
content string
}

func (a testStruct) print() {
fmt.Println(a.content)
}

func main() {
var a testInterface
a = testStruct{content: "テスト"}
a.print()
}