lightline
はVimのステータスライン表示をリッチにしてくれる
プラグインです。
色々な情報を自分の好きな様に表示できますが、
画面が狭くなったりした時に必要な情報から表示するように、
と言ったことをするためにちょっと工夫したことについて。
lightline
Vimでステータスライン表示を変更するプラグインは
powerline、
vim-airline
などいくつかありますが、
lightline
はそれらを踏まえた上で出てきた比較的新しいプラグインで
他のに比べて動作も軽快なので使っています。
画面幅によって表示させる項目を変える
上の導入時にも画面幅によって項目を変更することはやっていましたが、
この時は関数の呼ばれる順番とかを余り考えていませんでした。
たまたま上手く行くようになってましたが、
今回ちょっとvimrcを見直してる中できちんと想定通り動く様に変更しました。
取り敢えず設定を載せておくとこんな感じ。
.vimrc
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
| let g:lightline = {
\'colorscheme': 'jellybeans',
\'active': {
\'left': [['prepare', 'mode', 'filename'], ['fugitive']],
\'right': [['lineinfo'], ['fileinfo'], ['ale']]},
\'component_visible_condition': {
\'fugitive': '(exists("*fugitive#head") && ""!=fugitive#head())'},
\'component_function': {
\'prepare': 'LLPrepare',
\'mode': 'LLMode',
\'filename': 'LLFileName',
\'fugitive': 'LLFugitive',
\'fileinfo': 'LLFileInfo',
\'lineinfo': 'LLLineInfo',
\'ale': 'LLAle',
\},
\ 'separator': { 'left': '', 'right': '' },
\ 'subseparator': { 'left': '', 'right': '' }
\}
let g:lightline.inactive = g:lightline.active
function! LLPrepare()
let g:ll_mode = ''
let g:ll_filename = ''
let g:ll_fugitive = ''
let g:ll_fileinfo = ''
let g:ll_lineinfo = ''
let g:ll_ale = ''
let l:ww = winwidth('.')
let l:total_len = 0
let g:ll_mode = lightline#mode() . (&paste ? ' P' : '')
if g:ll_mode !=# ''
let l:total_len += strlen(g:ll_mode) + 2
if l:ww < l:total_len
return ''
endif
endif
let g:ll_lineinfo = printf('%d/%d:%d', line('.'), line('$'), col('.'))
if g:ll_lineinfo !=# ''
let l:total_len += strlen(g:ll_lineinfo) + 2
if l:ww < l:total_len
let g:ll_lineinfo = ''
return ''
endif
endif
let g:ll_filename = expand('%:t') . (&filetype !~? 'help' && &readonly ? ' RO' : '') . (&modifiable && &modified ? ' +' : '')
if g:ll_filename !=# ''
let l:total_len += strlen(g:ll_filename) + 2
if l:ww < l:total_len
let g:ll_filename = ''
return ''
endif
endif
let g:ll_fileinfo = &fileformat . ' ' . (strlen(&fileencoding) ? &fileencoding : &encoding) . ' ' . (strlen(&filetype) ? &filetype : 'no')
if g:ll_fileinfo !=# ''
let l:total_len += strlen(g:ll_fileinfo) + 2
if l:ww < l:total_len
let g:ll_fileinfo = ''
return ''
endif
endif
let g:ll_ale = LLGetAle()
if g:ll_ale !=# ''
let l:total_len += strlen(g:ll_ale) + 2
if l:ww < l:total_len
let g:ll_ale = ''
return ''
endif
endif
let g:ll_fugitive = exists('*fugitive#head') ? fugitive#head() : ''
if g:ll_fugitive !=# ''
let l:total_len += strlen(g:ll_fugitive) + 2
if l:ww < l:total_len
let g:ll_fugitive = ''
return ''
endif
endif
return ''
endfunction
function! LLMode()
return g:ll_mode
endfunction
function! LLFileName()
return g:ll_filename
endfunction
function! LLFugitive()
return g:ll_fugitive
endfunction
function! LLFileInfo()
return g:ll_fileinfo
endfunction
function! LLLineInfo()
return g:ll_lineinfo
endfunction
function! LLAle()
return g:ll_ale
endfunction
if dein#tap('ale')
function! LLGetAle()
let l:count = ale#statusline#Count(bufnr(''))
let l:errors = l:count.error + l:count.style_error
let l:warnings = l:count.warning + l:count.style_warning
return l:count.total == 0 ? 'OK' : 'E:' . l:errors . ' W:' . l:warnings
endfunction
else
function! LLGetAle()
return ''
endfunction
endif
|
注目すべきところは
prepare
という疑似項目を作って最初に全ての項目を準備しているところです。
lightlineではacvive
に登録された項目に対して
component_function
等によって表示するものを指定できます。
left
、right
の項目にそれぞれ3つずつ違う背景色に置くことが出来、
各領域には複数の項目を置くことも可能です。
上のだと['prepare', 'mode', 'filename']
は左側の一番左側の領域、
['fugitive']
は左側の真ん中の領域、
['lineinfo;']
は右側の一番右側の領域に表示されます。
ただし、表示するものが空白(''
)な場合はなにも表示されません。
表示される時は両側にスペースが入りますが、なにも表示されない場合はこのスペースも入りません。
今やりたいことは、各項目の表示文字数を調べて、
スペース数等も考慮したその合計が画面幅よりも大きいような場合には
表示項目を減らしてきれいに載せる、ということ。
ここで重要になってくるのは、各acvive
項目はここでは関数を呼んでその
返り値を表示するようになってますが、
その関数がどのような順番で呼ばれるか、ということ。
lightline
ではkのg:lightline
で設定されたactive
の項目の中から、
まずはleft
の中の左側から、
次にright
の中の左側の領域から評価されていきます。
配列の順番としてはleft
の項目の右側にある項目から、
次にright
の項目の右側にある項目から、と言った感じに評価されていきます。
以前はこの辺あまり考えず、
各項目にあてる関数の中で他の項目の文字数なんかもカウントしながら
取捨選択してましたが、たまたま重要なものを左側に置いていく関係で
それでも上手くいっていました。
ただ順番を変えたり表示したい項目を変えると上手く行かなくなるので
ちょっと見直して上の様にまず一番最初に呼ばれるprepare
の項目に
LLPrepare
という必要な文字列を準備するだけで空文字を変えず関数をあてました。
この中で一つ一つ使う項目を取得していって、
もしこれまでの物と合わせて画面幅(winwidth('.')
で取得)より
大きくなってしまった場合にはその項目は空文字にして以降の文字も空文字のままにしています。
各項目の文字数には両側にスペースが入るため+2
しています。
LLPrepare
をもうちょっときれいに上手く書けるかもしれませんが、
取り敢えずこの中の評価順序を変えれば
重要なものから選んで表示していくことが出来ます。
さらにはVim起動中に画面の大きさが変わっても都度評価し直して
表示を整えてくれます。