From 6c5316a05807fb91453fe107733b9c40011b2a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Silkeb=C3=A6kken?= Date: Tue, 20 Nov 2012 21:16:12 +0100 Subject: [PATCH] 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. --- examples/vim/powerline.py | 156 ++++++++++++++++++++----------------- examples/vim/powerline.vim | 20 ++++- 2 files changed, 101 insertions(+), 75 deletions(-) diff --git a/examples/vim/powerline.py b/examples/vim/powerline.py index 9da9973e..f4951744 100644 --- a/examples/vim/powerline.py +++ b/examples/vim/powerline.py @@ -70,87 +70,103 @@ 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 +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) + except vim.error: + vim_funcs['fghead'] = None + branch = '' + except TypeError: + branch = '' + if branch: + branch = '⭠ ' + branch + + # 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)] + + col_current = vim_funcs['col']('.') + + filepath, filename = os.path.split(vim_funcs['expand']('%:~:.')) + filename_color = 231 + if filepath: + filepath += os.sep + + if not filename: + filename = '[No Name]' + filename_color = 250 + + readonly = vim.eval('&ro ? "⭤ " : ""') + modified = vim.eval('&mod ? " +" : ""') + + try: + currenttag = vim_funcs['tbcurtag']('%s', '') + except vim.error: + vim_funcs['tbcurtag'] = None + currenttag = '' + except TypeError: + currenttag = '' + + 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']()] - try: - branch = vim_funcs['fghead'](5) - except vim.error: - vim_funcs['fghead'] = None - branch = '' - except TypeError: - branch = '' - 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)] - - col_current = vim_funcs['col']('.') - - filepath, filename = os.path.split(vim_funcs['expand']('%:~:.')) - filename_color = 231 - if filepath: - filepath += os.sep - - if not filename: - filename = '[No Name]' - filename_color = 250 - - readonly = vim.eval('&ro ? "⭤ " : ""') - modified = vim.eval('&mod ? " +" : ""') - - try: - currenttag = vim_funcs['tbcurtag']('%s', '') - except vim.error: - vim_funcs['tbcurtag'] = None - currenttag = '' - 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 = '' + 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 diff --git a/examples/vim/powerline.vim b/examples/vim/powerline.vim index 84cdefd5..4babdcb8 100644 --- a/examples/vim/powerline.vim +++ b/examples/vim/powerline.vim @@ -6,7 +6,7 @@ python sys.path.append(vim.eval('expand(":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