Make vim example work with split and inactive windows

This commit introduces a bunch of changes. Most importantly, it ensures
that split windows and inactive windows work as expected. This is
accomplished with some clever workarounds for vim's statusline
limitations.

Vim statuslines evaluated using the %! statusline item are always
evaluated in the buffer context and not in the statusline's owner
window's context, and this made the previous implementation show the
same statusline for all windows. The only way to ensure that the correct
statusline is rendered to the correct window is to walk through all
windows, and setting the statuslines with a reference to the current
window number every time the current window is changed. This is
accomplished by a set of BufEnter, BufLeave, etc. autocommands.

The Syntastic segment has been temporarily removed due to errors when
referencing the statusline function before Syntastic has been loaded.
This commit is contained in:
Kim Silkebækken 2012-11-20 21:16:12 +01:00
parent a532da4834
commit 6c5316a058
2 changed files with 101 additions and 75 deletions

View File

@ -70,16 +70,24 @@ vim_funcs = {
'col': get_vim_func('col', rettype=int),
'expand': get_vim_func('expand'),
'tbcurtag': get_vim_func('tagbar#currenttag'),
'sstlflag': get_vim_func('SyntasticStatuslineFlag'),
'hlexists': get_vim_func('hlexists', rettype=int),
}
getwinvar = get_vim_func('getwinvar')
setwinvar = get_vim_func('setwinvar')
def statusline():
winwidth = vim_funcs['winwidth'](0)
# Prepare segment contents
mode = modes[vim_funcs['mode']()]
def statusline(winnr):
winwidth = vim_funcs['winwidth'](winnr)
current = getwinvar(winnr, 'current')
windata = getwinvar(winnr, 'powerline')
if current:
# Recreate segment data for each redraw if we're in the current window
line_current = vim_funcs['line']('.')
line_end = vim_funcs['line']('$')
line_percent = line_current * 100 // line_end
try:
branch = vim_funcs['fghead'](5)
@ -91,10 +99,6 @@ def statusline():
if branch:
branch = '' + branch
line_current = vim_funcs['line']('.')
line_end = vim_funcs['line']('$')
line_percent = line_current * 100 // line_end
# Fun gradient colored percent segment
line_percent_gradient = [160, 166, 172, 178, 184, 190]
line_percent_color = line_percent_gradient[int((len(line_percent_gradient) - 1) * line_percent / 100)]
@ -121,36 +125,48 @@ def statusline():
except TypeError:
currenttag = ''
# The Syntastic segment is center aligned (filler segment on each side) to show off how the filler segments work
# Not necessarily how it's going to look in the final theme
set_global_var('syntastic_stl_format', '%E{ ERRORS (%e) ⭡ %fe }%W{ WARNINGS (%w) ⭡ %fw } ⮁')
try:
syntastic = vim_funcs['sstlflag']()
except vim.error:
vim_funcs['sstlflag'] = None
syntastic = ''
except TypeError:
syntastic = ''
windata = {
'paste': vim.eval('&paste ? "PASTE" : ""'),
'branch': branch,
'readonly': readonly,
'filepath': filepath,
'filename': filename,
'filename_color': filename_color,
'modified': modified,
'currenttag': currenttag,
'fileformat': vim.eval('&ff'),
'fileencoding': vim.eval('&fenc'),
'filetype': vim.eval('&ft'),
'line_percent': str(line_percent).rjust(3) + '%',
'line_percent_color': line_percent_color,
'linecurrent': str(line_current).rjust(3),
'colcurrent': ':' + str(col_current).ljust(2),
}
setwinvar(winnr, 'powerline', windata)
mode = modes[vim_funcs['mode']()]
if not current:
mode = None
powerline = Powerline([
Segment(mode, 22, 148, attr=Segment.ATTR_BOLD),
Segment(vim.eval('&paste ? "PASTE" : ""'), 231, 166, attr=Segment.ATTR_BOLD),
Segment(branch, 250, 240, priority=10),
Segment(readonly, 196, 240, draw_divider=False),
Segment(filepath, 250, 240, draw_divider=False, priority=5),
Segment(filename, filename_color, 240, attr=Segment.ATTR_BOLD, draw_divider=not len(modified)),
Segment(modified, 220, 240, attr=Segment.ATTR_BOLD),
Segment(currenttag, 246, 236, draw_divider=False, priority=100),
Segment(windata['paste'], 231, 166, attr=Segment.ATTR_BOLD),
Segment(windata['branch'], 250, 240, priority=10),
Segment(windata['readonly'], 196, 240, draw_divider=False),
Segment(windata['filepath'], 250, 240, draw_divider=False, priority=5),
Segment(windata['filename'], windata['filename_color'], 240, attr=Segment.ATTR_BOLD, draw_divider=not len(windata['modified'])),
Segment(windata['modified'], 220, 240, attr=Segment.ATTR_BOLD),
Segment(windata['currenttag'], 246, 236, draw_divider=False, priority=100),
Segment(filler=True, fg=236, bg=236),
Segment(syntastic, 214, 236, attr=Segment.ATTR_BOLD, draw_divider=False, priority=100),
Segment(filler=True, fg=236, bg=236),
Segment(vim.eval('&ff'), 247, 236, side='r', priority=50),
Segment(vim.eval('&fenc'), 247, 236, side='r', priority=50),
Segment(vim.eval('&ft'), 247, 236, side='r', priority=50),
Segment(str(line_percent).rjust(3) + '%', line_percent_color, 240, side='r', priority=30),
Segment(windata['fileformat'], 247, 236, side='r', priority=50),
Segment(windata['fileencoding'], 247, 236, side='r', priority=50),
Segment(windata['filetype'], 247, 236, side='r', priority=50),
Segment(windata['line_percent'], windata['line_percent_color'], 240, side='r', priority=30),
Segment('', 239, 252, side='r'),
Segment(str(line_current).rjust(3), 235, 252, attr=Segment.ATTR_BOLD, side='r', draw_divider=False),
Segment(':' + str(col_current).ljust(2), 244, 252, side='r', priority=30, draw_divider=False),
Segment(windata['linecurrent'], 235, 252, attr=Segment.ATTR_BOLD, side='r', draw_divider=False),
Segment(windata['colcurrent'], 244, 252, side='r', priority=30, draw_divider=False),
])
renderer = VimSegmentRenderer()
@ -176,6 +192,4 @@ def statusline():
return stl
statusline()
# vim: ft=python ts=4 sts=4 sw=4 noet

View File

@ -6,7 +6,7 @@ python sys.path.append(vim.eval('expand("<sfile>:h:h:h")'))
python from examples.vim.powerline import statusline
if exists('*pyeval')
let s:pyeval=function('pyeval')
let s:pyeval = function('pyeval')
else
python import json
function! s:pyeval(e)
@ -14,8 +14,20 @@ else
endfunction
endif
function! DynStl()
return s:pyeval('statusline()')
function! Powerline(winnr)
return s:pyeval('statusline('. a:winnr .')')
endfunction
set stl=%!DynStl()
function! s:WinDoPowerline()
if ! exists('w:powerline')
let w:powerline = {}
endif
let &l:stl = '%!Powerline('. winnr() .')'
endfunction
augroup Powerline
autocmd!
autocmd BufEnter,BufWinEnter,WinEnter * let w:current = 1 | let currwin = winnr() | windo call s:WinDoPowerline() | exec currwin . 'wincmd w'
autocmd BufLeave,BufWinLeave,WinLeave * let w:current = 0
augroup END