Problem
なんかGoを書いていると「のっぺりしている」と感じる。のっぺりしていて、どこが何をしているコードなのかパッと理解することがむずかしい。Rubyだとその正反対で、コードのコントラストがはっきりしているように感じる。
— Pocke(ぽっけ) SW-1309-2807-5790 (@p_ck_) 2018年12月31日
この違いが言語自体なのかSyntax Highlightか慣れかはわからんけど。
Goが多少冗長になっても良いという思想の言語だから、という点は大きそう。
— Pocke(ぽっけ) SW-1309-2807-5790 (@p_ck_) 2018年12月31日
Syntax Highlightの色数が少なく感じるからそこも関係していそうだけど、言語として区別する物が少ないからなのか単にハイライタの実装の違いかは定かではない。
慣れは一番わからない点ですね
先日このようなツイートをしたところ、多少の反響がありました。
普段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
エラーハンドリングのイディオムの部分だけ、コントラストが低くなっているのがわかると思います。 これによってコードのどこに注目したらがわかりやすくなります。
実装
次のファイルを、~/.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
結構ビカビカするので好みが分かれそうですが、併用するとよりコードが読みやすくなるかもしれません。
-
https://github.com/pocke/ptmux/blob/9dc55f866db9b5383102b7d38b88f736c2ee7330/main.go#L70-L84 この辺のコードです↩
-
私はfold機能は使っていませんが、気分でつけています。またconcealを指定しても面白いかもしれませんが、私はconcealは好きではないのでつけていません。↩