Merge pull request #1007 from ZyX-I/tab-modified-indicator
Add tab_modified indicator
This commit is contained in:
commit
6e128c14ba
|
@ -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
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
]
|
||||
|
||||
|
|
|
@ -84,36 +84,33 @@ 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,
|
||||
window_id=window_id,
|
||||
winnr=winnr,
|
||||
buffer=window.buffer,
|
||||
tabpage=current_tabpage(),
|
||||
)
|
||||
segment_info['tabnr'] = segment_info['tabpage'].number
|
||||
segment_info['bufnr'] = segment_info['buffer'].number
|
||||
winwidth = segment_info['window'].width
|
||||
matcher_info = segment_info
|
||||
|
||||
if window is vim.current.window:
|
||||
mode = vim_mode(1)
|
||||
mode = mode_translations.get(mode, mode)
|
||||
else:
|
||||
mode = None
|
||||
winwidth = int(vim.eval('&columns'))
|
||||
matcher_info = None
|
||||
mode = 'nc'
|
||||
|
||||
segment_info.update(
|
||||
window=window,
|
||||
mode=mode,
|
||||
window_id=window_id,
|
||||
winnr=winnr,
|
||||
buffer=window.buffer,
|
||||
tabpage=current_tabpage(),
|
||||
)
|
||||
segment_info['tabnr'] = segment_info['tabpage'].number
|
||||
segment_info['bufnr'] = segment_info['buffer'].number
|
||||
winwidth = segment_info['window'].width
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -13,9 +13,10 @@ except ImportError:
|
|||
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)
|
||||
buffer_name, vim_getwinvar,
|
||||
register_buffer_cache, current_tabpage,
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?', '!'))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue