Merge pull request #1007 from ZyX-I/tab-modified-indicator

Add tab_modified indicator
This commit is contained in:
Nikolai Aleksandrovich Pavlov 2014-08-22 22:04:29 +04:00
commit 6e128c14ba
10 changed files with 141 additions and 59 deletions

View File

@ -136,6 +136,12 @@ else:
if hasattr(vim, 'tabpages'):
current_tabpage = lambda: vim.current.tabpage
list_tabpages = lambda: vim.tabpages
def list_tabpage_buffers_segment_info(segment_info):
return (
{'buffer': window.buffer, 'bufnr': window.buffer.number}
for window in segment_info['tabpage'].windows
)
else:
class FalseObject(object):
@staticmethod
@ -205,6 +211,24 @@ else:
def list_tabpages(): # NOQA
return [Tabpage(nr) for nr in range(1, _last_tab_nr() + 1)]
class TabBufSegmentInfo(dict):
def __getitem__(self, key):
try:
return super(TabBufSegmentInfo, self).__getitem__(key)
except KeyError:
if key != 'buffer':
raise
else:
buffer = get_buffer(super(TabBufSegmentInfo, self).__getitem__('bufnr'))
self['buffer'] = buffer
return buffer
def list_tabpage_buffers_segment_info(segment_info):
return (
TabBufSegmentInfo(bufnr=int(bufnrstr))
for bufnrstr in vim.eval('tabpagebuflist({0})'.format(segment_info['tabnr']))
)
class VimEnviron(object):
@staticmethod

View File

@ -30,6 +30,11 @@
},
"priority": 10
},
{
"name": "tab_modified_indicator",
"exclude_modes": ["buf", "buf_nc"],
"priority": 5
},
{
"name": "modified_indicator",
"exclude_modes": ["tab", "tab_nc"],

View File

@ -147,10 +147,17 @@ class Renderer(object):
'''
self.theme.shutdown()
def _get_highlighting(self, segment, mode):
segment['highlight'] = self.colorscheme.get_highlighting(segment['highlight_group'], mode, segment.get('gradient_level'))
def _set_highlighting(self, segment):
segment['highlight'] = self.colorscheme.get_highlighting(
segment['highlight_group'],
segment['mode'],
segment.get('gradient_level')
)
if segment['divider_highlight_group']:
segment['divider_highlight'] = self.colorscheme.get_highlighting(segment['divider_highlight_group'], mode)
segment['divider_highlight'] = self.colorscheme.get_highlighting(
segment['divider_highlight_group'],
segment['mode']
)
else:
segment['divider_highlight'] = None
return segment
@ -254,19 +261,10 @@ class Renderer(object):
def do_render(self, mode, width, side, line, output_raw, output_width, segment_info, theme):
'''Like Renderer.render(), but accept theme in place of matcher_info
'''
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
# Handle excluded/included segments for the current mode
segments = [
self._get_highlighting(segment, segment_mode)
for segment, segment_mode in (
(segment, segment['mode'] or mode)
for segment in segments
) if (
segment_mode not in segment['exclude_modes']
and (
not segment['include_modes']
or segment_mode in segment['include_modes']
)
self._set_highlighting(segment)
for segment in (
theme.get_segments(side, line, self.get_segment_info(segment_info, mode), mode)
)
]

View File

@ -84,15 +84,16 @@ class VimRenderer(Renderer):
def get_segment_info(self, segment_info, mode):
return segment_info or self.segment_info
def render(self, window=None, window_id=None, winnr=None):
def render(self, window=None, window_id=None, winnr=None, is_tabline=False):
'''Render all segments.'''
segment_info = self.segment_info.copy()
if window is not None:
if window is vim.current.window:
mode = vim_mode(1)
mode = mode_translations.get(mode, mode)
else:
mode = 'nc'
segment_info.update(
window=window,
mode=mode,
@ -104,16 +105,12 @@ class VimRenderer(Renderer):
segment_info['tabnr'] = segment_info['tabpage'].number
segment_info['bufnr'] = segment_info['buffer'].number
winwidth = segment_info['window'].width
matcher_info = segment_info
else:
mode = None
winwidth = int(vim.eval('&columns'))
matcher_info = None
statusline = super(VimRenderer, self).render(
mode=mode,
width=winwidth,
segment_info=segment_info,
matcher_info=matcher_info,
matcher_info=(None if is_tabline else segment_info),
)
return statusline

View File

@ -1,8 +1,6 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals, division, print_function
import sys
from powerline.lib.watcher import create_file_watcher
@ -90,7 +88,7 @@ def get_attr_func(contents_func, key, args):
return lambda pl, shutdown_event: func(pl=pl, shutdown_event=shutdown_event, **args)
def process_segment_lister(pl, segment_info, parsed_segments, side, lister, subsegments, patcher_args):
def process_segment_lister(pl, segment_info, parsed_segments, side, mode, lister, subsegments, patcher_args):
for subsegment_info, subsegment_update in lister(pl=pl, segment_info=segment_info, **patcher_args):
draw_inner_divider = subsegment_update.pop('draw_inner_divider', False)
old_pslen = len(parsed_segments)
@ -100,7 +98,18 @@ def process_segment_lister(pl, segment_info, parsed_segments, side, lister, subs
subsegment.update(subsegment_update)
if subsegment_update['priority_multiplier'] and subsegment['priority']:
subsegment['priority'] *= subsegment_update['priority_multiplier']
process_segment(pl, side, subsegment_info, parsed_segments, subsegment)
subsegment_mode = subsegment_update.get('mode')
if subsegment_mode and (
subsegment_mode in subsegment['exclude_modes']
or (
subsegment['include_modes']
and subsegment_mode not in subsegment['include_modes']
)
):
continue
process_segment(pl, side, subsegment_info, parsed_segments, subsegment, subsegment_mode or mode)
new_pslen = len(parsed_segments)
if new_pslen > old_pslen + 1 and draw_inner_divider is not None:
for i in range(old_pslen, new_pslen - 1) if side == 'left' else range(old_pslen + 1, new_pslen):
@ -108,22 +117,27 @@ def process_segment_lister(pl, segment_info, parsed_segments, side, lister, subs
return None
def process_segment(pl, side, segment_info, parsed_segments, segment):
def process_segment(pl, side, segment_info, parsed_segments, segment, mode):
segment = segment.copy()
segment['mode'] = mode
if segment['type'] in ('function', 'segment_list'):
pl.prefix = segment['name']
try:
if segment['type'] == 'function':
contents = segment['contents_func'](pl, segment_info)
else:
contents = segment['contents_func'](pl, segment_info, parsed_segments, side)
contents = segment['contents_func'](pl, segment_info, parsed_segments, side, mode)
except Exception as e:
pl.exception('Exception while computing segment: {0}', str(e))
return
if contents is None:
return
if isinstance(contents, list):
segment_base = segment.copy()
# Needs copying here, but it was performed at the very start of the
# function
segment_base = segment
if contents:
draw_divider_position = -1 if side == 'left' else 0
for key, i, newval in (
@ -206,8 +220,8 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
'divider_highlight_group': None,
'before': None,
'after': None,
'contents_func': lambda pl, segment_info, parsed_segments, side: process_segment_lister(
pl, segment_info, parsed_segments, side,
'contents_func': lambda pl, segment_info, parsed_segments, side, mode: process_segment_lister(
pl, segment_info, parsed_segments, side, mode,
patcher_args=args,
subsegments=subsegments,
lister=_contents_func,

View File

@ -15,7 +15,8 @@ from collections import defaultdict
from powerline.bindings.vim import (vim_get_func, getbufvar, vim_getbufoption,
buffer_name, vim_getwinvar,
register_buffer_cache, current_tabpage,
list_tabpages)
list_tabpages,
list_tabpage_buffers_segment_info)
from powerline.theme import requires_segment_info, requires_filesystem_watcher
from powerline.lib import add_divider_highlight_group
from powerline.lib.vcs import guess, tree_status
@ -167,6 +168,24 @@ def modified_indicator(pl, segment_info, text='+'):
return text if int(vim_getbufoption(segment_info, 'modified')) else None
@requires_segment_info
def tab_modified_indicator(pl, segment_info, text='+'):
'''Return a file modified indicator for tabpages.
:param string text:
text to display if any buffer in the current tab is modified
Highlight groups used: ``tab_modified_indicator`` or ``modified_indicator``.
'''
for buf_segment_info in list_tabpage_buffers_segment_info(segment_info):
if int(vim_getbufoption(buf_segment_info, 'modified')):
return [{
'contents': text,
'highlight_group': ['tab_modified_indicator', 'modified_indicator'],
}]
return None
@requires_segment_info
def paste_indicator(pl, segment_info, text='PASTE'):
'''Return a paste mode indicator.
@ -427,7 +446,6 @@ def col_current(pl, segment_info):
return str(segment_info['window'].cursor[1] + 1)
# TODO Add &textwidth-based gradient
@window_cached
def virtcol_current(pl, gradient=True):
'''Return current visual column with concealed characters ingored

View File

@ -90,7 +90,7 @@ class Theme(object):
def get_line_number(self):
return len(self.segments)
def get_segments(self, side=None, line=0, segment_info=None):
def get_segments(self, side=None, line=0, segment_info=None, mode=None):
'''Return all segments.
Function segments are called, and all segments get their before/after
@ -103,7 +103,11 @@ class Theme(object):
for side in [side] if side else ['left', 'right']:
parsed_segments = []
for segment in self.segments[line][side]:
process_segment(self.pl, side, segment_info, parsed_segments, segment)
# No segment-local modes at this point
if mode not in segment['exclude_modes'] and (
not segment['include_modes'] or mode in segment['include_modes']
):
process_segment(self.pl, side, segment_info, parsed_segments, segment, mode)
for segment in parsed_segments:
segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after']
# Align segment contents

View File

@ -4,7 +4,7 @@ from __future__ import absolute_import
import sys
from powerline.bindings.vim import vim_get_func, vim_getvar
from powerline import Powerline
from powerline import Powerline, FailedUnicode
from powerline.lib import mergedicts
import vim
from itertools import count
@ -228,15 +228,14 @@ class VimPowerline(Powerline):
def statusline(self, window_id):
window, window_id, winnr = self.win_idx(window_id) or (None, None, None)
if not window:
return 'No window {0}'.format(window_id)
return FailedUnicode('No window {0}'.format(window_id))
return self.render(window, window_id, winnr)
def tabline(self):
return self.render()
return self.render(*self.win_idx(None), is_tabline=True)
def new_window(self):
window, window_id, winnr = self.win_idx(None)
return self.render(window, window_id, winnr)
return self.render(*self.win_idx(None))
if not hasattr(vim, 'bindeval'):
# Method for PowerlinePyeval function. Is here to reduce the number of

View File

@ -53,7 +53,7 @@ class TestConfig(TestCase):
outputs[out] = (i, (args, kwargs), mode)
with vim_module._with('bufname', '/tmp/foo.txt'):
out = powerline.render()
out = powerline.render(vim_module.current.window, 1, vim_module.current.window.number, is_tabline=True)
outputs[out] = (-1, (None, None), 'tab')
with vim_module._with('globals', powerline_config_path=cfg_path):
exclude = set(('no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!'))

View File

@ -903,6 +903,29 @@ class TestVim(TestCase):
self.assertEqual(single_tab(multiple_text='m'), [{'highlight_group': ['single_tab'], 'contents': 'Bufs'}])
self.assertEqual(single_tab(single_text='s'), [{'highlight_group': ['single_tab'], 'contents': 's'}])
def test_segment_info(self):
pl = Pl()
with vim_module._with('tabpage'):
with vim_module._with('buffer', '1') as segment_info:
self.assertEqual(vim.tab_modified_indicator(pl=pl, segment_info=segment_info), None)
vim_module.current.buffer[0] = ' '
self.assertEqual(vim.tab_modified_indicator(pl=pl, segment_info=segment_info), [{
'contents': '+',
'highlight_group': ['tab_modified_indicator', 'modified_indicator'],
}])
vim_module._undo()
self.assertEqual(vim.tab_modified_indicator(pl=pl, segment_info=segment_info), None)
old_buffer = vim_module.current.buffer
vim_module._new('2')
segment_info = vim_module._get_segment_info()
self.assertEqual(vim.tab_modified_indicator(pl=pl, segment_info=segment_info), None)
old_buffer[0] = ' '
self.assertEqual(vim.modified_indicator(pl=pl, segment_info=segment_info), None)
self.assertEqual(vim.tab_modified_indicator(pl=pl, segment_info=segment_info), [{
'contents': '+',
'highlight_group': ['tab_modified_indicator', 'modified_indicator'],
}])
old_cwd = None