pockestrap

Programmer's memo

VimでGoのコードをコントラスト高く表示する

Problem

先日このようなツイートをしたところ、多少の反響がありました。

普段Goを書いていると、なぜか「コードがのっぺりしている」と感じてしまいます。 コードにメリハリがなく、自分が探している処理がなんなのか、このコードは何をしているのかを一瞬で見分けることができません。 一方Rubyを書いている時にはそのようなことはあまりなく、コードのコントラストがはっきりしていると感じています。

このコードのコントラストの差の原因はいくつか考えられます。 言語のデザインやSyntax Highlightの充実、また言語への習熟度も原因として考えられるでしょう。

Target

今回はこの問題を解決するために、言語のデザインとSyntax Highlightに注目しました。

Go言語には、エラーを大域脱出で扱わずに関数の戻り値として扱う特徴があります。 そのためGo言語を書いていると次のようなコードが頻出します。

v, err := doSomething(arg)
if err != nil {
  return nil, err
}

このif err != nil以降の3行はGo言語を書いていると必ず出てくるコード片です。

私はこれがGo言語のコードが「のっぺりしている」と感じる大きな原因の1つだと推測しました。 何故ならば、このコード片は頻出する上に決まりきったことしかしていません。 そして3行もスペースを取っています。行数が多い分、doSomething(arg)の呼び出しよりも目立っているようにすら感じます。

Solution

そこで私はif err != nilを目立たなくしてしまえばよいのではと考え、VimのSyntax Highlightを調整しました。 その結果、次のようになりました。1

f:id:Pocke:20190102153603p:plain
Before
f:id:Pocke:20190102153606p:plain
After

エラーハンドリングのイディオムの部分だけ、コントラストが低くなっているのがわかると思います。 これによってコードのどこに注目したらがわかりやすくなります。

実装

次のファイルを、~/.vim/after/syntax/go.vimとして保存するだけです。2

syn match goExtIfErr "\v^\s*if\s+err\s*\!\=\s*nil\s*\{\s*\_$\_.\s*return.+\_$\_.\s*\}" fold
hi def link goExtIfErr Comment

これにより、エラーハンドリングのイディオムがコメントと同じ文字色でハイライトされます。

なお私はコメントよりもさらに暗い色でハイライトしたかったため、カラースキームに次の行を追記しました。

hi goExtIfErr  ctermfg=darkGray

まとめ

ソースコード中の頻出するイディオムを暗くすることで、より重要なコードを目立たせる方法について紹介しました。 この記事によって、VimでGoをより快適に編集できるようになれば幸いです。

おまけ

vim-goを使っている場合、次のコードを.vimrcに追記するとより多くの要素がハイライトされるようになります。

let g:go_highlight_array_whitespace_error = 1
let g:go_highlight_chan_whitespace_error = 1
let g:go_highlight_extra_types = 1
let g:go_highlight_space_tab_error = 1
let g:go_highlight_trailing_whitespace_error = 1
let g:go_highlight_operators = 1
let g:go_highlight_functions = 1
let g:go_highlight_function_arguments = 1
let g:go_highlight_function_calls = 1
let g:go_highlight_fields = 1
let g:go_highlight_types = 1
let g:go_highlight_build_constraints = 1
let g:go_highlight_generate_tags = 1
let g:go_highlight_variable_assignments = 1
let g:go_highlight_variable_declarations = 1
f:id:Pocke:20190102153606p:plain
Before
f:id:Pocke:20190102154051p:plain
After

結構ビカビカするので好みが分かれそうですが、併用するとよりコードが読みやすくなるかもしれません。


  1. https://github.com/pocke/ptmux/blob/9dc55f866db9b5383102b7d38b88f736c2ee7330/main.go#L70-L84 この辺のコードです

  2. 私はfold機能は使っていませんが、気分でつけています。またconcealを指定しても面白いかもしれませんが、私はconcealは好きではないのでつけていません。