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.v1
gometalinter --install --update
それぞれのlinterについては以下のような記事を参考にされたし。
ALE
ALEは、Vim8もしくはNeoVimで非同期にlinterを実行してくれるプラギンである。
Go以外にも様々な言語1に対応している。
似たようなプラギンは多数存在するわけだが、設定なしでもすぐ使えるという点がよい。
なにも考えなければインストールするだけで使える、便利。
Goでもいくつかのlinterを使えるようになっているが、デフォルトはgofmtになっているのでgometalinterにする必要がある。
plugin managerにはdein.vimを使っているのでその場合だと以下ような感じになる。
if &compatible
set nocompatible
endif
let s:dein_dir='~/.cache/dein/repos/github.com/Shougo/dein.vim'
set runtimepath+=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()
endif
filetype plugin indent on
syntax enable
" for ALE
let g:ale_lint_on_text_changed = 'never'
let g:ale_set_loclist = 0
let g:ale_set_quickfix = 1
let g:ale_sign_column_always = 1
let g:ale_lint_on_enter = 0
let g:ale_open_list = 1
let g:ale_keep_list_window_open = 0
" for go
let g:ale_linters.go ='gometalinter'
let g: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/font
brew install ricty --powerline --vim-powerline
terminalのfontをRictyPowelineにしつつ、ALEの設定に以下を追加する。
let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '⬥ ok']
let g:ale_sign_error = '⤫'
let g:ale_sign_warning = '⚠'
Nerd Fonts
icon fontをstatuslineに表示するためにNerd Fontsのパッチを以下の手順でRictyにあてあげる必要がある。
brew install fontforge
git clone https://github.com/ryanoasis/nerd-fonts
cd nerd-fonts
chmod +x font-patcher
fontforge -script ./font-patcher ~/Library/Fonts/Ricty\ Regular\ for\ Powerline.ttf --fontawesome --fontlinux --oct
icons --pomicons --powerline --powerlineextra
cp -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用の設定として以下を追加します。(長文)
let g: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 ? '' : '-'
endfunction
function! LightLineReadonly()
return &ft !~? 'help' && &readonly ? '' : ''
endfunction
function! LightLineFilepath() abort
let l:path_string = substitute(expand('%:h'), $HOME, '~', '')
if winwidth(0) < 120 && len(l:path_string) > 30
let l:path_string = substitute(l:path_string, '\v([^/])[^/]*%(/)@=', '\1', 'g')
endif
return l:path_string
endfunction
function! 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/84c78efa38b5c2fc1f659d1aac3face8
function! LightLineDenite()
let mode_str = substitute(denite#get_status_mode(), "-\\| ", "", "g")
call lightline#link(tolower(mode_str[0]))
return mode_str
endfunction
function! LightLineFugitive()
try
if expand('%:t') !~? 'Tagbar\|Gundo\|NERD' && &ft !~? 'vimfiler' && exists('*fugitive#head')
let mark = ' ' " edit here for cool mark
let _ = fugitive#head()
return strlen(_) ? mark._ : ''
endif
catch
endtry
return ''
endfunction
function! LightLineFileformat()
return winwidth(0) > 120 ? &fileformat . (exists('*WebDevIconsGetFileFormatSymbol') ? ' ' . WebDevIconsGetFileFormatSymbol() : '') : ''
endfunction
function! LightLineFiletype()
return winwidth(0) > 70 ? (strlen(&filetype) ? &filetype . (exists('*WebDevIconsGetFileTypeSymbol') ? ' ' . WebDevIconsGetFileTypeSymbol() : ''): 'no ft') : ''
endfunction
function! LightLineFileencoding()
return winwidth(0) > 120 ? (strlen(&fenc) ? &fenc : &enc) : ''
endfunction
function! 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() : ''
endfunction
function! LightLineCharCode() abort
if winwidth(0) <= 120
return ''
endif
" if char on cursor is `Λ̊`, :ascii returns below.
" <Λ> 923, 16進数 039b, 8進数 1633 < ̊> 778, 16進数 030a, 8進数 1412
redir => l:tmp | silent! ascii | redir END
let l:chars = []
call substitute(l:tmp, '<.>\s\+\d\+,\s\+\S\+ \x\+,\s\+\S\+ \d\+', '\=add(l:chars, submatch(0))', 'g')
if len(l:chars) == 0
return ''
endif
let l:ascii = []
for l:c in l:chars
let l:m = matchlist(l:c, '<\(.\)>\s\+\d\+,\s\+\S\+ \(\x\+\)')
if len(l:m) > 0
call add(l:ascii, printf('%s %s', l:m[1], l:m[2]))
endif
endfor
return join(l:ascii, ', ')
endfunction
function! LightLineAleError() abort
return s:ale_string(0)
endfunction
function! LightLineAleWarning() abort
return s:ale_string(1)
endfunction
function! LightLineAleOk() abort
return s:ale_string(2)
endfunction
function! s:ale_string(mode)
if !exists('g:ale_buffer_info')
return ''
endif
let l:buffer = bufnr('%')
let l:counts = ale#statusline#Count(l:buffer)
let [l:error_format, l:warning_format, l:no_errors] = g:ale_statusline_format
if a:mode == 0 " Error
let l:errors = l:counts.error + l:counts.style_error
return l:errors ? printf(l:error_format, l:errors) : ''
elseif a:mode == 1 " Warning
let l:warnings = l:counts.warning + l:counts.style_warning
return l:warnings ? printf(l:warning_format, l:warnings) : ''
endif
return l:counts.total == 0? l:no_errors: ''
endfunction
以上で完了。