tl;dr
- Vim8 or NeoVimからgometalinterを使う
- linterプラギンとしてALEを使う
- 画像のような表示にするためにNerd Fontsを使う
gometalinter
Go用のlinterはいくつかあるがこれらを統合的に扱えるようにしたものである。
サポートしているlinterはgithub上に記載されている。
https://github.com/alecthomas/gometalinter#supported-linters
Install
go get -u gopkg.in/alecthomas/gometalinter.v1gometalinter --install --update
それぞれのlinterについては以下のような記事を参考にされたし。
- Go の CI で Lint と カバレッジ回して非人間的なレビューは自動化しよう in 2016年
- Go Meta Linter がサポートするツールまとめ
ALE
ALEは、Vim8もしくはNeoVimで非同期にlinterを実行してくれるプラギンである。
Go以外にも様々な言語1に対応している。
似たようなプラギンは多数存在するわけだが、設定なしでもすぐ使えるという点がよい。
なにも考えなければインストールするだけで使える、便利。
Goでもいくつかのlinterを使えるようになっているが、デフォルトはgofmtになっているのでgometalinterにする必要がある。
plugin managerにはdein.vimを使っているのでその場合だと以下ような感じになる。
if&compatiblesetnocompatibleendiflet s:dein_dir='~/.cache/dein/repos/github.com/Shougo/dein.vim'setruntimepath+=s:dein_dir
if dein#load_state('~/.cache/dein')call dein#begin({)call dein#add(s:dein_dir)call dein#add('w0rp/ale')call dein#end()call dein#save_state()endiffiletype plugin indent onsyntax enable
" for ALEletg:ale_lint_on_text_changed ='never'letg:ale_set_loclist =0letg:ale_set_quickfix =1letg:ale_sign_column_always =1letg:ale_lint_on_enter =0letg:ale_open_list =1letg:ale_keep_list_window_open =0" for goletg:ale_linters.go='gometalinter'letg:ale_go_gometalinter_options ='--fast --enable=staticcheck --enable=gosimple --enable=unused'
g:ale_go_gometalinter_options
でgometalinter実行時のoptionを渡せる。--fast
は実行に時間のかかるlinterを除いて実行してくれる。
上記の設定だとファイル保存時にlintしてくれる。非同期に実行するとはいえ、--fast
なしだともっさりしてしまうのでつけている。
それ以外の--enable
はお好みで追加。
これだけでALEがgometalinterを実行してくれるようになる。
Powerline
linter結果にPowerlineフォントを使う。
みんな大好きRictyのpowerlineパッチのインストールは以下。
brew tap sanemat/fontbrew install ricty --powerline --vim-powerline
terminalのfontをRictyPowelineにしつつ、ALEの設定に以下を追加する。
letg:ale_statusline_format = ['⨉ %d','⚠ %d','⬥ ok']
letg:ale_sign_error ='⤫'letg:ale_sign_warning ='⚠'
Nerd Fonts
icon fontをstatuslineに表示するためにNerd Fontsのパッチを以下の手順でRictyにあてあげる必要がある。
brew install fontforgegit clone https://github.com/ryanoasis/nerd-fontscd nerd-fontschmod +x font-patcherfontforge -script ./font-patcher ~/Library/Fonts/Ricty\ Regular\ for\ Powerline.ttf --fontawesome --fontlinux --octicons --pomicons --powerline --powerlineextracp -f ./Ricty\ Regular\ for\ Powerline\ Nerd\ Font\ Plus\ Font\ Awesome\ Plus\ Octicons\ Plus\ Pomicons\ Plus\ Font\ Linux.ttf ~/Library/Fonts/fc-cache -vf
nerd-fontsのcloneにはそれなりに時間がかかるのでcoffeeでも飲むとよい
ここで作ったフォントをiTerm2とかの設定で使うようにする。
ALEの設定に以下を追加。
lightline
statuslineにはlightline.vimを使う。
またlightlineのcolorthemeにtender.vimを使い、NerdFontを表示するためにvim-deviconsをいれる。
プラギンの追加のところに以下を追記。
ちなみにvim-deviconsを先に読み込む必要がある。
call dein#add('ryanoasis/vim-devicons')call dein#add('itchyny/lightline.vim')call dein#add('jacoborus/tender.vim')
lightline用の設定として以下を追加します。(長文)
letg:lightline = {
\ 'colorscheme': 'tender',
\ 'active': {
\ 'left': [ [ 'mode','paste' ], [ 'fugitive','filename' ] ],
\ 'right': [ [ 'lineinfo' ], ['percent'], [ 'ale_error','ale_warning','ale_ok','char_code','fileformat','fileencoding','filetype' ] ]
\ },
\ 'component_function': {
\ 'fugitive': 'LightLineFugitive',
\ 'filename': 'LightLineFilename',
\ 'fileformat': 'LightLineFileformat',
\ 'filetype': 'LightLineFiletype',
\ 'fileencoding': 'LightLineFileencoding',
\ 'mode': 'LightLineMode',
\ 'char_code': 'LightLineCharCode',
\ },
\ 'component_function_visible_condition': {
\ 'mode': 1,
\ },
\ 'component_expand': {
\ 'ale_error': 'LightLineAleError',
\ 'ale_warning': 'LightLineAleWarning',
\ 'ale_ok': 'LightLineAleOk',
\ },
\ 'component_type': {
\ 'ale_error': 'error',
\ 'ale_waring': 'waring',
\ 'ale_ok': 'ok',
\ },
\ 'separator': {'left': '⮀','right': '⮂'},
\ 'subseparator': {'left': '⮁','right': '⮃'}
\ }
augroup LightLineOnALE
autocmd!
autocmd User ALELint call lightline#update()
augroup END
function! LightLineModified()return&ft=~'help' ? '' : &modified ? '' : &modifiable ? '' : '-'endfunctionfunction! LightLineReadonly()return&ft!~? 'help'&& &readonly ? '' : ''endfunctionfunction! LightLineFilepath() abort
letl:path_string = substitute(expand('%:h'), $HOME,'~','')ifwinwidth(0)<120&& len(l:path_string)>30letl:path_string = substitute(l:path_string,'\v([^/])[^/]*%(/)@=','\1','g')endifreturnl:path_string
endfunctionfunction! LightLineFilename()let fname = expand('%:t')return fname =='ControlP' ? g:lightline.ctrlp_item :
\ fname =='__Tagbar__' ? g:lightline.fname :
\ fname =~'__Gundo\|NERD_tree' ? '' :
\ &ft=='vimfiler' ? vimfiler#get_status_string() :
\ &ft=='denite' ? LightLineDenite() :
\ &ft=='vimshell' ? vimshell#get_status_string() :
\ (''!= LightLineReadonly() ? LightLineReadonly() . ' ' : '') .
\ (''!= fname ? LightLineFilepath().' '.fname : '[No Name]') .
\ (''!= LightLineModified() ? ' ' . LightLineModified() : '')endfunction" ref. https://gist.github.com/pocari/84c78efa38b5c2fc1f659d1aac3face8function! LightLineDenite()let mode_str = substitute(denite#get_status_mode(),"-\\| ","","g")call lightline#link(tolower(mode_str[0]))return mode_str
endfunctionfunction! LightLineFugitive()tryif expand('%:t')!~? 'Tagbar\|Gundo\|NERD'&& &ft!~? 'vimfiler'&& exists('*fugitive#head')let mark =' '" edit here for cool marklet _ = fugitive#head()return strlen(_) ? mark._ : ''endifcatchendtryreturn''endfunctionfunction! LightLineFileformat()returnwinwidth(0)>120 ? &fileformat . (exists('*WebDevIconsGetFileFormatSymbol') ? ' ' . WebDevIconsGetFileFormatSymbol() : '') : ''endfunctionfunction! LightLineFiletype()returnwinwidth(0)>70 ? (strlen(&filetype) ? &filetype . (exists('*WebDevIconsGetFileTypeSymbol') ? ' ' . WebDevIconsGetFileTypeSymbol() : ''): 'no ft') : ''endfunctionfunction! LightLineFileencoding()returnwinwidth(0)>120 ? (strlen(&fenc) ? &fenc : &enc) : ''endfunctionfunction! LightLineMode()let fname = expand('%:t')return fname =='__Tagbar__' ? 'Tagbar' :
\ fname =='ControlP' ? 'CtrlP' :
\ fname =='__Gundo__' ? 'Gundo' :
\ fname =='__Gundo_Preview__' ? 'Gundo Preview' :
\ fname =~'NERD_tree' ? 'NERDTree' :
\ &ft=='unite' ? 'Unite' :
\ &ft=='denite' ? 'Denite' :
\ &ft=='vimfiler' ? 'VimFiler' :
\ &ft=='vimshell' ? 'VimShell' :
\ winwidth(0)>60 ? lightline#mode() : ''endfunctionfunction! LightLineCharCode() abort
ifwinwidth(0)<=120return''endif " if char on cursor is `Λ̊`, :ascii returns below. " <Λ> 923, 16進数 039b, 8進数 1633 < ̊> 778, 16進数 030a, 8進数 1412redir=>l:tmp |silent!ascii|redir END
letl:chars = []
call substitute(l:tmp,'<.>\s\+\d\+,\s\+\S\+ \x\+,\s\+\S\+ \d\+','\=add(l:chars, submatch(0))','g')if len(l:chars)==0return''endifletl:ascii= []
forl:cinl:chars
letl:m= matchlist(l:c,'<\(.\)>\s\+\d\+,\s\+\S\+ \(\x\+\)')if len(l:m)>0call add(l:ascii, printf('%s %s',l:m[1],l:m[2]))endifendforreturnjoin(l:ascii,', ')endfunctionfunction! LightLineAleError() abort
return s:ale_string(0)endfunctionfunction! LightLineAleWarning() abort
return s:ale_string(1)endfunctionfunction! LightLineAleOk() abort
return s:ale_string(2)endfunctionfunction! s:ale_string(mode)if!exists('g:ale_buffer_info')return''endifletl:buffer = bufnr('%')letl:counts = ale#statusline#Count(l:buffer)let [l:error_format,l:warning_format,l:no_errors] =g:ale_statusline_format
ifa:mode==0" Errorletl:errors =l:counts.error +l:counts.style_error
returnl:errors ? printf(l:error_format,l:errors) : ''elseifa:mode==1" Warningletl:warnings =l:counts.warning +l:counts.style_warning
returnl:warnings ? printf(l:warning_format,l:warnings) : ''endifreturnl:counts.total ==0? l:no_errors: ''endfunction
以上で完了。