Vim/NeoVimの表示で左側にGitの変更状況を表示したり 色々と言語サポートを表示したりすることが出来ますが、 サクッとマウスなどでコピペする際、それらが表示されていると文字として認識されて 余計な文字までコピーされてしまいます。
その辺り一時的に表示を消してコピペをしたり出来るようにする設定について。
消したいもの
消したいものは以下のもの。
- list: 文末の空白やタブなど
- nowrap: 長い行を折り返さないで隠す設定
- signcolumn: Gitの変更やエラーなどの状況。
- 文末以降のチルダ(EndOfBuffer)
- coc-pyrightによる型ヒント
他にもプラグインや設定によってはあるかもしれませんが、 現状自分の設定だとこんなものでした。
各種設定変更方法
list
文末の空白やタブなどを可視化する設定。
listcharsで設定された各種状態の可視化をするかしないかを決める値です。
これは
set nolist
としてやれば消えます。
再び見せる場合には
set list
もともとnolistになっている可能性もあるので、最初の状態を取得しておきます。
let g:default_list = &list
setに関する値を取得したい場合には&を使って取ることができます。
これで隠したいときは
set nolist
で必ずnolistにし、戻したいときは
let &list = g:default_list
とすることで、もとの状態に戻します。
setには直接変数を与えることは出来ませんが、上のようにlet &<var>とすることで
変数をsetの設定に渡すことが出来ます。
この設定はウィンドウ(表示されている枠)毎に設定されています。(setでもsetlocalでも変わらない。)
Ref: help nolist
'list' 'nolist' 'list' boolean (default off) local to window
nowrap
長い行を複数行にせずにスクロールのような形で画面移動して見に行くようにする設定。
これは
set wrap
とすると画面内に複数行で表示されるようになります。
ただ、これに関しては現状では最初からwrapで運用してますが、一応考慮に入れておきます。
この設定もウィンドウ毎に設定されています。
signcolumn
左側に1列か数列文の情報表示をする設定。
プラグインでGitの変更状態を表示させたり、言語サポートプラグインで文法エラーを表示したりする事ができます。
これを消すには
set signcolumn=no
signcolumnにはautoなどの値が入っているので、最初に
let g:default_signcolumn = &signcolumn
で値を取得しておいて戻す際には
let &signcolumn = g:default_signcolumn
とします。
スペルチェック
追記: 2022/11/06
スペルチェックを有効にしていると間違ったスペルに下線が付いたりします。
これは
set spell
の設定で有効になり、
set nospell
で無効にできます。
この下線はコピペする際には取得されないのでちょっと用途がずれますが、 コードの見た目から邪魔なものをなくしてみたい、という時にも使いたいのでこれも追加。
スペルチェックに関しては別途、
nnoremap <silent> <Leader>s :setlocal spell!<CR>
という設定を入れていて<Leader>sでトグルするようにもしています。
追記ここまで
文末以降のチルダ
短いファイルを表示する際、Vimのウィンドウがファイルよりも長い場合、
ファイル外の下部の部分に関しては~で始まるラインとして表示されます。
これに関しては直接方法はなく、この表示部分のシンタックスグループのテキストの色を 背景と同じにする、ということで消します。
この~はEndOfBufferというシンタックスグループで管理されています。
通常はこれがNonTextの言うシンタックスグループにリンクされていて、
EndOfBuffer自体では指定をしていません。
NonTextを使っているものがざっと見なかったですが、とりあえずこの両方を
背景と同じ色にしておけばOK。
バックグラウンドの色に関してはIgnoreというシンタックスグループがあり、
この文字の色が背景と同じ色になって見せないようになっています。
これらの色は
let g:default_nontext_fg = synIDattr(hlID('NonText'), 'fg')
let g:default_endofbuffer_fg = synIDattr(hlID('EndOfBuffer'), 'fg')
if g:default_endofbuffer_fg == ""
let g:default_endofbuffer_fg = g:default_nontext_fg
endif
let g:ignore_fg = synIDattr(hlID('Ignore'), 'fg')
みたいな感じで取得できます。
hlIDというのがグループ名からIDを取得する関数で、synIDattrでそのIDに関する情報を取得できます。
synIDattrの2つ目以降の引数にほしい情報名を入れて取得。
ここではfg、つまりはテキストの色を取得しています。(2つ目以降、複数を指定することも可能。)
EndOfBufferに関しては指定が無いこともあるので、後で戻す際に空欄のままだとエラーになるので
もし指定がない場合はNonTextのものを入れておきます。
これで、隠したいときは
execute "highlight NonText ctermfg=" . g:ignore_fg . " guifg=" . g:ignore_fg
execute "highlight EndOfBuffer ctermfg=" . g:ignore_fg . " guifg=" . g:ignore_fg
としてIgnoreの色にします。
highlightに対して直接変数を与えることはできませんが、コマンドを文字列にしてからexecuteに渡すことで変数を使うことが出来ます。
一応ctermfg, guifg両方を指定していますがgvimを使わないとかターミナルでは使わないとかあればどちらかだけでも。
これを元に戻すには
execute "highlight NonText ctermfg=" . g:default_nontext_fg . " guifg=" . g:default_nontext_fg
execute "highlight EndOfBuffer ctermfg=" . g:default_endofbuffer_fg . " guifg=" . g:default_endofbuffer_fg
とすればOK。
これらのハイライト設定は常にグローバルで、 バッファごととかウィンドウごとにはなりません。
頑張ればできるかもしれませんが、結構面倒な感じなので現状では変更はグローバルな変更の状態になっています。
追記: 2022/11/06
シンタックスグループに関しては以下のような関数を用意して取得するように更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
hlIDで取得したIDからsynIDtransを使うことで
そのIDが別のグループにリンクされているとそのリンク先の情報が得られます。
もし、そのリンク先も別のグループにリンクされていたとすると
最終的なリンク先までsynIDtrans一発でたどり着くことができます。
もしリンクされていなければそのままそのIDが返されます。
これを使って
1
| |
とすることで元の状態を保持しておいて後で戻すための情報をコマンドとして保存しておきます。
基本的に背景色は無いグループですが、一応変わる可能性も考えて 背景色も保存して変更するようにしました。
これで、
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
のように、ハイライトがかかっているときには必要なものをIgnoreにリンクして
戻すときは最初に保存したコマンドを実行する、という形にすることでスッキリ出来ました。
追記ここまで
coc-pyrightによる型ヒント
coc.nvimのサポートプラグインのcoc-pyrightでは最近型ヒントが付けられていない部分に対して 型ヒントを表示してくれる機能が追加されました。
1 2 | |
みたいな関数があると、返り値はintが予想されますが、これに対して、
1 2 | |
のように表示してくれます。(-> intの部分)
追記: 2022/11/06
NeoVimだとこのように表示されますが、 Vimだと下の実際の文法と同じ様な表示になります。
-> intの部分を非文字として追加して表示することが出来るようです。
その場合にはコピペするとそのまま使えるコードになります。
追記ここまで
関数の返り値の他、変数の型ヒントも表示してくれます。
ただし、きちんと型ヒントを書くと
1 2 | |
のように:より前に書かないといけないので、coc-pyrightで表示されたものをそのままコピペするとエラーになります。
これは~/.vim/coc-settings.json(~/.config/nvim/coc-settings.json)の中で、
"pyright.inlayHints.functionReturnTypes": false,
"pyright.inlayHints.variableTypes": false,
とすると無効化出来ます。
有効にしている場合には(調べた限り)それぞれを変更することは出来ませんが、
CocCommand document.toggleInlayHint
というコマンドを実行することで表示を消したり表示したりすることが出来ます。 現状では表示する、消す、といったコマンドはないようでトグルするだけです。
この設定はバッファごと(つまりは開いたファイルごと)の変更になります。
追記: 2022/11/06
Inlay Hintは言語によってあるものとないものがあり、ないものを開いてこのコマンドを使うと
[coc.nvim] Inlay hint provider not found for current document
と言ったエラーが出ます。 無視してしまっても良いのですが、これに関しては、
1 2 3 | |
のようにinlayHintというProviderがあるかないか、を調べる関数があるのでそれを使うことで余計なエラーを出さずに実行できるようになります。
追記ここまで
coc.nvimのErrorなどに対する下線など
追記: 2022/11/06
coc.nvimで文法エラーなどを検出するとその部分に上のsigncolumよる表示とともに 該当の部分に下線が引かれたりします。
これもコピペには直接作用しませんが、すっきり表示するために消したいな、と思い設定を入れてみました。
これらはCocXXXHighlight(XXX=Unused, Error, Warning, Info, Hint)というグループがあり
これらが下線や取り消し線、背景色を薄く塗るグループにリンクされています。
https://github.com/neoclide/coc.nvim/blob/2692b894a2d4c17d2def60969e6af078dcda1a12/plugin/coc.vim#L511
上のリンクにあるように、これらは
`hi default link CocErrorHighlight
のようにdefault linkが使われているため、なんらか変更行ったあとにhighlight clearすることで戻すことが出来ます。
なのでこれらに関しては最初に設定は取得せずに、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
のように、ハイライトがついているときはcterm, ctermbgなどをNONEにしてしまい、
戻すときはclearで戻すようにしました。
追記ここまで
coc.nvimのpopupやその他もろもろ
追記: 2022/11/06
coc.nvimがつけるものが結構色々あって、一つはErrorなどになっている部分にカーソルがあるとpopupが出ることがあります。
その状態でコピペするとその部分がとれてしまうので、一度別の場所にカーソルを動かすなどしないといけません。
これに関しては
call coc#float#close_all()
を呼ぶことで消すことが出来ます。
これらのポップアップはカーソルをもう一度移動して戻すと再表示されてしまいますが、 一時的には消した状態を維持できます。
ポップアップが出ないようにcoc.nvim自体を無効化することも考えられますが、 それがちょっとうまくいきませんでした。
CocDisable、CocEnableというコマンドがあって無効化、有効化が出来るんですが、
これらのコマンドを実行しても残るものがあって、
下にあるようにclearmatchesなどを使って一通り消せるとはあり、もしこれでうまく行けば
シンタックスグループなども逐次変更せずにすみます。
ただ、Inlay Hintに関しては独立しているのか残ってしまいました。
Cleanup syntax highlighting on :CocDisable / :CocRestart · Issue #1268 · neoclide/coc.nvim
さらに微妙なのが、なぜかCocDisableを最初にした直後はdocument.toggleInlayHintをしても消えず、
その後このコマンドを実行するとCocEnable、CocDisableの状態に関係なくtoggleが実行されます。
これによってどうやってもうまく制御出来なかったのでCocDisableを使うのはやめました。
b:coc_enabledやb:coc_diagnostic_disableといった状態を制御する変数も用意されていますがこれらも
思ったようには使えず。
また、clearmatchesを使ってしまうと戻すのに別途コマンドが色々必要になることもあって結構面倒です。
なので最終的にはcoc.nvim自体は有効にしたまま必要なシンタックスグループなどを直接変更するなどして対処しています。
追記ここまで
変更設定
以下の様な関数とキーバインドを用意してさっと変えられるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
この設定で<Leader>cと押すたびに表示変更が行われます。
(<Leader>はデフォルトではバックスラッシュ。自分の設定では,になっているのでこのトグルは,cで行う。)
coc.nvimに関してはプラグインが入っている場合にのみ実行されるようにしています。
ここではdein.vimを使って管理しているのでそれを使ってチェック。
一番最初にこの関数が実行された際にデフォルトの表示設定をグローバル変数に記録しておきます。
トグルの状態に関してはb:current_viewというバッファ変数に記録しておきます。
ちょっとやっかいなのは
listなどsetに関するもの: ウィンドウ(w)highlight: グローバル(g)- cocの
InlayHint: バッファ(b)
でそれぞれの状態の変更範囲が違うところ。
ToggleViewを実行すると、highlightはすべての箇所で変更されますが、
listなどは現在のウィンドウのみで変更されます。
さらにcocのInlayHintに関してはバッファ単位なので、もし同じファイルを2つのウィンドウに分けて表示している場合にはその両方で変更されます。
ホントはすべてウィンドウ毎に変更できれば良いのですが、かなり面倒なので現状ではこのような感じまでで。
InlayHintに関してはOn/Offを指定する方法はないため、これがバッファごとということを踏まえて
状態の保存の変数はb:current_viedwというバッファ変数にしてこの状態と揃えるようにしています。
これによって、一時的にlistだけが消えたウィンドウなどが出来てしまいますが、
そのウィンドウで<Leader>cを2回以上押せばすべてが揃って表示、または非表示の状態にすることが出来ます。

これを

こんな感じに。
追記: 2022/11/06
アップデート版は以下の通り
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
NeoVimでは

が

Vimでは

が

の状態に。
コードちょっと変更してエラーとかを少し追加してあります。 popupの例も。
あと、CocErrorHighlightなどによる下線が何故か最初の例だと出てませんが、ここだと__main__の右の行末のスペースなどの部分に下線が出ているものがあって、
これもちゃんと消えてるのが確認出来ると思います。
何故か最初の例だとmain関数がif文の中にあったので移動。。。
追記ここまで
