mirror of
https://github.com/powerline/powerline.git
synced 2025-07-05 21:14:55 +02:00
commit
1cc46c7126
@ -272,6 +272,12 @@ Themes
|
|||||||
highlighting group is defined in the :ref:`highlight_group
|
highlighting group is defined in the :ref:`highlight_group
|
||||||
option <config-themes-seg-highlight_group>`.
|
option <config-themes-seg-highlight_group>`.
|
||||||
|
|
||||||
|
``segments_list``
|
||||||
|
Sub-list of segments. This list only allows :ref:`name
|
||||||
|
<config-themes-seg-name>`, :ref:`segments
|
||||||
|
<config-themes-seg-segments>` and :ref:`args
|
||||||
|
<config-themes-seg-args>` options.
|
||||||
|
|
||||||
``module``
|
``module``
|
||||||
.. _config-themes-seg-module:
|
.. _config-themes-seg-module:
|
||||||
|
|
||||||
@ -282,7 +288,7 @@ Themes
|
|||||||
``name``
|
``name``
|
||||||
.. _config-themes-seg-name:
|
.. _config-themes-seg-name:
|
||||||
|
|
||||||
Function name, only required for function segments.
|
Function name, only required for function and list segments.
|
||||||
|
|
||||||
``highlight_group``
|
``highlight_group``
|
||||||
.. _config-themes-seg-highlight_group:
|
.. _config-themes-seg-highlight_group:
|
||||||
@ -366,3 +372,6 @@ Themes
|
|||||||
|
|
||||||
Boolean. If false disables displaying of the segment.
|
Boolean. If false disables displaying of the segment.
|
||||||
Defaults to ``True``.
|
Defaults to ``True``.
|
||||||
|
|
||||||
|
``segments``
|
||||||
|
A list of subsegments.
|
||||||
|
@ -84,10 +84,10 @@ else:
|
|||||||
|
|
||||||
def bufvar_exists(buffer, varname): # NOQA
|
def bufvar_exists(buffer, varname): # NOQA
|
||||||
if not buffer or buffer.number == vim.current.buffer.number:
|
if not buffer or buffer.number == vim.current.buffer.number:
|
||||||
return vim.eval('exists("b:{0}")'.format(varname))
|
return int(vim.eval('exists("b:{0}")'.format(varname)))
|
||||||
else:
|
else:
|
||||||
return vim.eval('has_key(getbufvar({0}, ""), {1})'
|
return int(vim.eval('has_key(getbufvar({0}, ""), {1})'
|
||||||
.format(buffer.number, varname))
|
.format(buffer.number, varname)))
|
||||||
|
|
||||||
def vim_getwinvar(segment_info, varname): # NOQA
|
def vim_getwinvar(segment_info, varname): # NOQA
|
||||||
result = vim.eval('getwinvar({0}, "{1}")'.format(segment_info['winnr'], varname))
|
result = vim.eval('getwinvar({0}, "{1}")'.format(segment_info['winnr'], varname))
|
||||||
@ -104,6 +104,79 @@ else:
|
|||||||
return getbufvar(info['bufnr'], '&' + option)
|
return getbufvar(info['bufnr'], '&' + option)
|
||||||
|
|
||||||
|
|
||||||
|
if hasattr(vim, 'tabpages'):
|
||||||
|
current_tabpage = lambda: vim.current.tabpage
|
||||||
|
list_tabpages = lambda: vim.tabpages
|
||||||
|
else:
|
||||||
|
class FalseObject(object):
|
||||||
|
@staticmethod
|
||||||
|
def __nonzero__():
|
||||||
|
return False
|
||||||
|
|
||||||
|
__bool__ = __nonzero__
|
||||||
|
|
||||||
|
def get_buffer(number):
|
||||||
|
for buffer in vim.buffers:
|
||||||
|
if buffer.number == number:
|
||||||
|
return buffer
|
||||||
|
raise KeyError(number)
|
||||||
|
|
||||||
|
class WindowVars(object):
|
||||||
|
__slots__ = ('tabnr', 'winnr')
|
||||||
|
|
||||||
|
def __init__(self, window):
|
||||||
|
self.tabnr = window.tabnr
|
||||||
|
self.winnr = window.number
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
has_key = vim.eval('has_key(gettabwinvar({0}, {1}, ""), "{2}")'.format(self.tabnr, self.winnr, key))
|
||||||
|
if has_key == '0':
|
||||||
|
raise KeyError
|
||||||
|
return vim.eval('gettabwinvar({0}, {1}, "{2}")'.format(self.tabnr, self.winnr, key))
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
try:
|
||||||
|
return self[key]
|
||||||
|
except KeyError:
|
||||||
|
return default
|
||||||
|
|
||||||
|
class Window(FalseObject):
|
||||||
|
__slots__ = ('tabnr', 'number', '_vars')
|
||||||
|
|
||||||
|
def __init__(self, tabnr, number):
|
||||||
|
self.tabnr = tabnr
|
||||||
|
self.number = number
|
||||||
|
self.vars = WindowVars(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def buffer(self):
|
||||||
|
return get_buffer(int(vim.eval('tabpagebuflist({0})[{1}]'.format(self.tabnr, self.number - 1))))
|
||||||
|
|
||||||
|
class Tabpage(FalseObject):
|
||||||
|
__slots__ = ('number',)
|
||||||
|
|
||||||
|
def __init__(self, number):
|
||||||
|
self.number = number
|
||||||
|
|
||||||
|
def __eq__(self, tabpage):
|
||||||
|
if not isinstance(tabpage, Tabpage):
|
||||||
|
raise NotImplementedError
|
||||||
|
return self.number == tabpage.number
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window(self):
|
||||||
|
return Window(self.number, int(vim.eval('tabpagewinnr({0})'.format(self.number))))
|
||||||
|
|
||||||
|
def _last_tab_nr():
|
||||||
|
return int(vim.eval('tabpagenr("$")'))
|
||||||
|
|
||||||
|
def current_tabpage(): # NOQA
|
||||||
|
return Tabpage(int(vim.eval('tabpagenr()')))
|
||||||
|
|
||||||
|
def list_tabpages(): # NOQA
|
||||||
|
return [Tabpage(nr) for nr in range(1, _last_tab_nr() + 1)]
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3,) or not hasattr(vim, 'bindeval'):
|
if sys.version_info < (3,) or not hasattr(vim, 'bindeval'):
|
||||||
getbufvar = vim_get_func('getbufvar')
|
getbufvar = vim_get_func('getbufvar')
|
||||||
else:
|
else:
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
"file_name_empty": "file_directory",
|
"file_name_empty": "file_directory",
|
||||||
"line_percent": "information:additional",
|
"line_percent": "information:additional",
|
||||||
"line_count": "line_current",
|
"line_count": "line_current",
|
||||||
"position": "information:additional"
|
"position": "information:additional",
|
||||||
|
"single_tab": "line_current",
|
||||||
|
"many_tabs": "line_current",
|
||||||
|
"tabnr": "file_directory"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
"colorscheme": "default",
|
"colorscheme": "default",
|
||||||
"theme": "default",
|
"theme": "default",
|
||||||
"local_themes": {
|
"local_themes": {
|
||||||
|
"__tabline__": "tabline",
|
||||||
|
|
||||||
"cmdwin": "cmdwin",
|
"cmdwin": "cmdwin",
|
||||||
"help": "help",
|
"help": "help",
|
||||||
"quickfix": "quickfix",
|
"quickfix": "quickfix",
|
||||||
|
44
powerline/config_files/themes/vim/tabline.json
Normal file
44
powerline/config_files/themes/vim/tabline.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"default_module": "powerline.segments.vim",
|
||||||
|
"segments": {
|
||||||
|
"left": [
|
||||||
|
{
|
||||||
|
"type": "segment_list",
|
||||||
|
"name": "tabbuflister",
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"name": "tabnr",
|
||||||
|
"after": " ",
|
||||||
|
"draw_soft_divider": false,
|
||||||
|
"exclude_modes": ["tab", "buf"],
|
||||||
|
"priority": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "file_directory",
|
||||||
|
"draw_soft_divider": false,
|
||||||
|
"priority": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "file_name",
|
||||||
|
"args": {
|
||||||
|
"display_no_file": true
|
||||||
|
},
|
||||||
|
"priority": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"highlight_group": ["background"],
|
||||||
|
"draw_soft_divider": false,
|
||||||
|
"draw_hard_divider": false,
|
||||||
|
"width": "auto"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"right": [
|
||||||
|
{
|
||||||
|
"name": "single_tab"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -71,6 +71,8 @@ class DelayedEchoErr(EchoErr):
|
|||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return not not self.errs
|
return not not self.errs
|
||||||
|
|
||||||
|
__bool__ = __nonzero__
|
||||||
|
|
||||||
|
|
||||||
class Spec(object):
|
class Spec(object):
|
||||||
def __init__(self, **keys):
|
def __init__(self, **keys):
|
||||||
@ -93,15 +95,21 @@ class Spec(object):
|
|||||||
self.did_type = True
|
self.did_type = True
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def copy(self):
|
def copy(self, copied=None):
|
||||||
return self.__class__()._update(self.__dict__)
|
copied = copied or {}
|
||||||
|
try:
|
||||||
|
return copied[id(self)]
|
||||||
|
except KeyError:
|
||||||
|
instance = self.__class__()
|
||||||
|
copied[id(self)] = instance
|
||||||
|
return self.__class__()._update(self.__dict__, copied)
|
||||||
|
|
||||||
def _update(self, d):
|
def _update(self, d, copied):
|
||||||
self.__dict__.update(d)
|
self.__dict__.update(d)
|
||||||
self.keys = copy(self.keys)
|
self.keys = copy(self.keys)
|
||||||
self.checks = copy(self.checks)
|
self.checks = copy(self.checks)
|
||||||
self.uspecs = copy(self.uspecs)
|
self.uspecs = copy(self.uspecs)
|
||||||
self.specs = [spec.copy() for spec in self.specs]
|
self.specs = [spec.copy(copied) for spec in self.specs]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def unknown_spec(self, keyfunc, spec):
|
def unknown_spec(self, keyfunc, spec):
|
||||||
@ -379,6 +387,9 @@ class WithPath(object):
|
|||||||
def check_matcher_func(ext, match_name, data, context, echoerr):
|
def check_matcher_func(ext, match_name, data, context, echoerr):
|
||||||
import_paths = [os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', [])]
|
import_paths = [os.path.expanduser(path) for path in context[0][1].get('common', {}).get('paths', [])]
|
||||||
|
|
||||||
|
if match_name == '__tabline__':
|
||||||
|
return True, False
|
||||||
|
|
||||||
match_module, separator, match_function = match_name.rpartition('.')
|
match_module, separator, match_function = match_name.rpartition('.')
|
||||||
if not separator:
|
if not separator:
|
||||||
match_module = 'powerline.matchers.{0}'.format(ext)
|
match_module = 'powerline.matchers.{0}'.format(ext)
|
||||||
@ -681,13 +692,14 @@ type_keys = {
|
|||||||
'function': set(('args', 'module', 'draw_inner_divider')),
|
'function': set(('args', 'module', 'draw_inner_divider')),
|
||||||
'string': set(('contents', 'type', 'highlight_group', 'divider_highlight_group')),
|
'string': set(('contents', 'type', 'highlight_group', 'divider_highlight_group')),
|
||||||
'filler': set(('type', 'highlight_group', 'divider_highlight_group')),
|
'filler': set(('type', 'highlight_group', 'divider_highlight_group')),
|
||||||
|
'segment_list': set(('segments', 'module', 'args', 'type')),
|
||||||
}
|
}
|
||||||
required_keys = {
|
required_keys = {
|
||||||
'function': set(),
|
'function': set(('name',)),
|
||||||
'string': set(('contents',)),
|
'string': set(('contents',)),
|
||||||
'filler': set(),
|
'filler': set(),
|
||||||
|
'segment_list': set(('name', 'segments',)),
|
||||||
}
|
}
|
||||||
function_keys = set(('args', 'module'))
|
|
||||||
highlight_keys = set(('highlight_group', 'name'))
|
highlight_keys = set(('highlight_group', 'name'))
|
||||||
|
|
||||||
|
|
||||||
@ -712,7 +724,7 @@ def check_key_compatibility(segment, data, context, echoerr):
|
|||||||
problem_mark=list(unknown_keys)[0].mark)
|
problem_mark=list(unknown_keys)[0].mark)
|
||||||
hadproblem = True
|
hadproblem = True
|
||||||
|
|
||||||
if not (keys > required_keys[segment_type]):
|
if not (keys >= required_keys[segment_type]):
|
||||||
missing_keys = required_keys[segment_type] - keys
|
missing_keys = required_keys[segment_type] - keys
|
||||||
echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)),
|
echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)),
|
||||||
context_mark=context[-1][1].mark,
|
context_mark=context[-1][1].mark,
|
||||||
@ -862,7 +874,7 @@ def check_segment_name(name, data, context, echoerr):
|
|||||||
hadproblem = True
|
hadproblem = True
|
||||||
|
|
||||||
return True, False, hadproblem
|
return True, False, hadproblem
|
||||||
else:
|
elif context[-2][1].get('type') != 'segment_list':
|
||||||
if name not in context[0][1].get('segment_data', {}):
|
if name not in context[0][1].get('segment_data', {}):
|
||||||
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
top_theme_name = data['main_config'].get('ext', {}).get(ext, {}).get('theme', None)
|
||||||
if data['theme'] == top_theme_name:
|
if data['theme'] == top_theme_name:
|
||||||
@ -1070,32 +1082,34 @@ args_spec = Spec(
|
|||||||
).unknown_spec(Spec(), Spec()).optional().copy
|
).unknown_spec(Spec(), Spec()).optional().copy
|
||||||
highlight_group_spec = Spec().type(unicode).copy
|
highlight_group_spec = Spec().type(unicode).copy
|
||||||
segment_module_spec = Spec().type(unicode).func(check_segment_module).optional().copy
|
segment_module_spec = Spec().type(unicode).func(check_segment_module).optional().copy
|
||||||
segments_spec = Spec().optional().list(
|
sub_segments_spec = Spec()
|
||||||
Spec(
|
segment_spec = Spec(
|
||||||
type=Spec().oneof(type_keys).optional(),
|
type=Spec().oneof(type_keys).optional(),
|
||||||
name=Spec().re('^[a-zA-Z_]\w+$').func(check_segment_name).optional(),
|
name=Spec().re('^[a-zA-Z_]\w+$').func(check_segment_name).optional(),
|
||||||
exclude_modes=Spec().list(vim_mode_spec()).optional(),
|
exclude_modes=Spec().list(vim_mode_spec()).optional(),
|
||||||
include_modes=Spec().list(vim_mode_spec()).optional(),
|
include_modes=Spec().list(vim_mode_spec()).optional(),
|
||||||
draw_hard_divider=Spec().type(bool).optional(),
|
draw_hard_divider=Spec().type(bool).optional(),
|
||||||
draw_soft_divider=Spec().type(bool).optional(),
|
draw_soft_divider=Spec().type(bool).optional(),
|
||||||
draw_inner_divider=Spec().type(bool).optional(),
|
draw_inner_divider=Spec().type(bool).optional(),
|
||||||
display=Spec().type(bool).optional(),
|
display=Spec().type(bool).optional(),
|
||||||
module=segment_module_spec(),
|
module=segment_module_spec(),
|
||||||
priority=Spec().type(int, float, type(None)).optional(),
|
priority=Spec().type(int, float, type(None)).optional(),
|
||||||
after=Spec().type(unicode).optional(),
|
after=Spec().type(unicode).optional(),
|
||||||
before=Spec().type(unicode).optional(),
|
before=Spec().type(unicode).optional(),
|
||||||
width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(),
|
width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(),
|
||||||
align=Spec().oneof(set('lr')).optional(),
|
align=Spec().oneof(set('lr')).optional(),
|
||||||
args=args_spec().func(lambda *args, **kwargs: check_args(get_one_segment_variant, *args, **kwargs)),
|
args=args_spec().func(lambda *args, **kwargs: check_args(get_one_segment_variant, *args, **kwargs)),
|
||||||
contents=Spec().type(unicode).optional(),
|
contents=Spec().type(unicode).optional(),
|
||||||
highlight_group=Spec().list(
|
highlight_group=Spec().list(
|
||||||
highlight_group_spec().re('^(?:(?!:divider$).)+$',
|
highlight_group_spec().re('^(?:(?!:divider$).)+$',
|
||||||
lambda value: 'it is recommended that only divider highlight group names end with ":divider"')
|
lambda value: 'it is recommended that only divider highlight group names end with ":divider"')
|
||||||
).func(check_highlight_groups).optional(),
|
).func(check_highlight_groups).optional(),
|
||||||
divider_highlight_group=highlight_group_spec().func(check_highlight_group).re(':divider$',
|
divider_highlight_group=highlight_group_spec().func(check_highlight_group).re(':divider$',
|
||||||
lambda value: 'it is recommended that divider highlight group names end with ":divider"').optional(),
|
lambda value: 'it is recommended that divider highlight group names end with ":divider"').optional(),
|
||||||
).func(check_full_segment_data),
|
segments=sub_segments_spec,
|
||||||
).copy
|
).func(check_full_segment_data)
|
||||||
|
sub_segments_spec.optional().list(segment_spec)
|
||||||
|
segments_spec = Spec().optional().list(segment_spec).copy
|
||||||
segdict_spec=Spec(
|
segdict_spec=Spec(
|
||||||
left=segments_spec().context_message('Error while loading segments from left side (key {key})'),
|
left=segments_spec().context_message('Error while loading segments from left side (key {key})'),
|
||||||
right=segments_spec().context_message('Error while loading segments from right side (key {key})'),
|
right=segments_spec().context_message('Error while loading segments from right side (key {key})'),
|
||||||
|
@ -222,20 +222,44 @@ class Renderer(object):
|
|||||||
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
||||||
|
|
||||||
# Handle excluded/included segments for the current mode
|
# Handle excluded/included segments for the current mode
|
||||||
segments = [self._get_highlighting(segment, mode) for segment in segments
|
segments = [
|
||||||
if mode not in segment['exclude_modes'] and (not segment['include_modes'] or mode in segment['include_modes'])]
|
self._get_highlighting(segment, segment['mode'] or mode)
|
||||||
|
for segment in segments
|
||||||
segments = [segment for segment in self._render_segments(theme, segments)]
|
if (
|
||||||
|
mode not in segment['exclude_modes']
|
||||||
|
and (
|
||||||
|
not segment['include_modes']
|
||||||
|
or mode in segment['include_modes']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
if not width:
|
if not width:
|
||||||
# No width specified, so we don't need to crop or pad anything
|
# No width specified, so we don't need to crop or pad anything
|
||||||
return construct_returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw)
|
return construct_returned_value(''.join([
|
||||||
|
segment['_rendered_hl']
|
||||||
|
for segment in self._render_segments(theme, segments)
|
||||||
|
]) + self.hlstyle(), segments, output_raw)
|
||||||
|
|
||||||
|
divider_lengths = {
|
||||||
|
'left': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('left', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('left', 'soft')),
|
||||||
|
},
|
||||||
|
'right': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('right', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('right', 'soft')),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
length = self._render_length(theme, segments, divider_lengths)
|
||||||
|
|
||||||
# Create an ordered list of segments that can be dropped
|
# Create an ordered list of segments that can be dropped
|
||||||
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
|
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
|
||||||
while sum([segment['_len'] for segment in segments]) > width and len(segments_priority):
|
for segment in segments_priority:
|
||||||
segments.remove(segments_priority[0])
|
if self._render_length(theme, segments, divider_lengths) <= width:
|
||||||
segments_priority.pop(0)
|
break
|
||||||
|
segments.remove(segment)
|
||||||
|
|
||||||
# Distribute the remaining space on spacer segments
|
# Distribute the remaining space on spacer segments
|
||||||
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
||||||
@ -256,6 +280,38 @@ class Renderer(object):
|
|||||||
|
|
||||||
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
||||||
|
|
||||||
|
def _render_length(self, theme, segments, divider_lengths):
|
||||||
|
'''Update segments lengths and return them
|
||||||
|
'''
|
||||||
|
segments_len = len(segments)
|
||||||
|
ret = 0
|
||||||
|
divider_spaces = theme.get_spaces()
|
||||||
|
for index, segment in enumerate(segments):
|
||||||
|
side = segment['side']
|
||||||
|
if segment['_contents_len'] is None:
|
||||||
|
segment_len = segment['_contents_len'] = self.strwidth(segment['contents'])
|
||||||
|
else:
|
||||||
|
segment_len = segment['_contents_len']
|
||||||
|
|
||||||
|
prev_segment = segments[index - 1] if index > 0 else theme.EMPTY_SEGMENT
|
||||||
|
next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT
|
||||||
|
compare_segment = next_segment if side == 'left' else prev_segment
|
||||||
|
divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
|
||||||
|
|
||||||
|
outer_padding = int(bool(
|
||||||
|
(index == 0 and side == 'left') or
|
||||||
|
(index == segments_len - 1 and side == 'right')
|
||||||
|
))
|
||||||
|
|
||||||
|
draw_divider = segment['draw_' + divider_type + '_divider']
|
||||||
|
segment_len += segment['_space_left'] + segment['_space_right'] + outer_padding
|
||||||
|
if draw_divider:
|
||||||
|
segment_len += divider_lengths[side][divider_type] + divider_spaces
|
||||||
|
|
||||||
|
segment['_len'] = segment_len
|
||||||
|
ret += segment_len
|
||||||
|
return ret
|
||||||
|
|
||||||
def _render_segments(self, theme, segments, render_highlighted=True):
|
def _render_segments(self, theme, segments, render_highlighted=True):
|
||||||
'''Internal segment rendering method.
|
'''Internal segment rendering method.
|
||||||
|
|
||||||
@ -268,19 +324,19 @@ class Renderer(object):
|
|||||||
statusline if render_highlighted is True.
|
statusline if render_highlighted is True.
|
||||||
'''
|
'''
|
||||||
segments_len = len(segments)
|
segments_len = len(segments)
|
||||||
|
divider_spaces = theme.get_spaces()
|
||||||
|
|
||||||
for index, segment in enumerate(segments):
|
for index, segment in enumerate(segments):
|
||||||
segment['_rendered_raw'] = ''
|
side = segment['side']
|
||||||
segment['_rendered_hl'] = ''
|
|
||||||
|
|
||||||
prev_segment = segments[index - 1] if index > 0 else theme.EMPTY_SEGMENT
|
prev_segment = segments[index - 1] if index > 0 else theme.EMPTY_SEGMENT
|
||||||
next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT
|
next_segment = segments[index + 1] if index < segments_len - 1 else theme.EMPTY_SEGMENT
|
||||||
compare_segment = next_segment if segment['side'] == 'left' else prev_segment
|
compare_segment = next_segment if side == 'left' else prev_segment
|
||||||
outer_padding = ' ' if (index == 0 and segment['side'] == 'left') or (index == segments_len - 1 and segment['side'] == 'right') else ''
|
outer_padding = int(bool(
|
||||||
|
(index == 0 and side == 'left') or
|
||||||
|
(index == segments_len - 1 and side == 'right')
|
||||||
|
)) * ' '
|
||||||
divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
|
divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
|
||||||
|
|
||||||
divider_raw = theme.get_divider(segment['side'], divider_type)
|
|
||||||
divider_spaces = theme.get_spaces()
|
|
||||||
divider_highlighted = ''
|
divider_highlighted = ''
|
||||||
contents_raw = segment['contents']
|
contents_raw = segment['contents']
|
||||||
contents_highlighted = ''
|
contents_highlighted = ''
|
||||||
@ -288,48 +344,64 @@ class Renderer(object):
|
|||||||
|
|
||||||
# Pad segments first
|
# Pad segments first
|
||||||
if draw_divider:
|
if draw_divider:
|
||||||
if segment['side'] == 'left':
|
divider_raw = theme.get_divider(side, divider_type).replace(' ', NBSP)
|
||||||
contents_raw = outer_padding + (segment['_space_left'] * ' ') + contents_raw + ((divider_spaces + segment['_space_right']) * ' ')
|
if side == 'left':
|
||||||
|
contents_raw = (
|
||||||
|
outer_padding + (segment['_space_left'] * ' ')
|
||||||
|
+ contents_raw
|
||||||
|
+ ((divider_spaces + segment['_space_right']) * ' ')
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
contents_raw = ((divider_spaces + segment['_space_left']) * ' ') + contents_raw + (segment['_space_right'] * ' ') + outer_padding
|
contents_raw = (
|
||||||
|
((divider_spaces + segment['_space_left']) * ' ')
|
||||||
|
+ contents_raw
|
||||||
|
+ (segment['_space_right'] * ' ') + outer_padding
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if segment['side'] == 'left':
|
if side == 'left':
|
||||||
contents_raw = outer_padding + (segment['_space_left'] * ' ') + contents_raw + (segment['_space_right'] * ' ')
|
contents_raw = (
|
||||||
|
outer_padding + (segment['_space_left'] * ' ')
|
||||||
|
+ contents_raw
|
||||||
|
+ (segment['_space_right'] * ' ')
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
contents_raw = (segment['_space_left'] * ' ') + contents_raw + (segment['_space_right'] * ' ') + outer_padding
|
contents_raw = (
|
||||||
|
(segment['_space_left'] * ' ')
|
||||||
|
+ contents_raw
|
||||||
|
+ (segment['_space_right'] * ' ') + outer_padding
|
||||||
|
)
|
||||||
|
|
||||||
# Replace spaces with no-break spaces
|
# Replace spaces with no-break spaces
|
||||||
divider_raw = divider_raw.replace(' ', NBSP)
|
|
||||||
contents_raw = contents_raw.translate(self.np_character_translations)
|
contents_raw = contents_raw.translate(self.np_character_translations)
|
||||||
|
|
||||||
# Apply highlighting to padded dividers and contents
|
# Apply highlighting to padded dividers and contents
|
||||||
if render_highlighted:
|
if render_highlighted:
|
||||||
if divider_type == 'soft':
|
if draw_divider:
|
||||||
divider_highlight_group_key = 'highlight' if segment['divider_highlight_group'] is None else 'divider_highlight'
|
if divider_type == 'soft':
|
||||||
divider_fg = segment[divider_highlight_group_key]['fg']
|
divider_highlight_group_key = 'highlight' if segment['divider_highlight_group'] is None else 'divider_highlight'
|
||||||
divider_bg = segment[divider_highlight_group_key]['bg']
|
divider_fg = segment[divider_highlight_group_key]['fg']
|
||||||
else:
|
divider_bg = segment[divider_highlight_group_key]['bg']
|
||||||
divider_fg = segment['highlight']['bg']
|
else:
|
||||||
divider_bg = compare_segment['highlight']['bg']
|
divider_fg = segment['highlight']['bg']
|
||||||
divider_highlighted = self.hl(divider_raw, divider_fg, divider_bg, False)
|
divider_bg = compare_segment['highlight']['bg']
|
||||||
|
divider_highlighted = self.hl(divider_raw, divider_fg, divider_bg, False)
|
||||||
contents_highlighted = self.hl(self.escape(contents_raw), **segment['highlight'])
|
contents_highlighted = self.hl(self.escape(contents_raw), **segment['highlight'])
|
||||||
|
|
||||||
# Append padded raw and highlighted segments to the rendered segment variables
|
# Append padded raw and highlighted segments to the rendered segment variables
|
||||||
if draw_divider:
|
if draw_divider:
|
||||||
if segment['side'] == 'left':
|
if side == 'left':
|
||||||
segment['_rendered_raw'] += contents_raw + divider_raw
|
segment['_rendered_raw'] = contents_raw + divider_raw
|
||||||
segment['_rendered_hl'] += contents_highlighted + divider_highlighted
|
segment['_rendered_hl'] = contents_highlighted + divider_highlighted
|
||||||
else:
|
else:
|
||||||
segment['_rendered_raw'] += divider_raw + contents_raw
|
segment['_rendered_raw'] = divider_raw + contents_raw
|
||||||
segment['_rendered_hl'] += divider_highlighted + contents_highlighted
|
segment['_rendered_hl'] = divider_highlighted + contents_highlighted
|
||||||
else:
|
else:
|
||||||
if segment['side'] == 'left':
|
if side == 'left':
|
||||||
segment['_rendered_raw'] += contents_raw
|
segment['_rendered_raw'] = contents_raw
|
||||||
segment['_rendered_hl'] += contents_highlighted
|
segment['_rendered_hl'] = contents_highlighted
|
||||||
else:
|
else:
|
||||||
segment['_rendered_raw'] += contents_raw
|
segment['_rendered_raw'] = contents_raw
|
||||||
segment['_rendered_hl'] += contents_highlighted
|
segment['_rendered_hl'] = contents_highlighted
|
||||||
segment['_len'] = self.strwidth(segment['_rendered_raw'])
|
|
||||||
yield segment
|
yield segment
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from powerline.bindings.vim import vim_get_func, environ
|
from powerline.bindings.vim import vim_get_func, environ, current_tabpage
|
||||||
from powerline.renderer import Renderer
|
from powerline.renderer import Renderer
|
||||||
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
|
||||||
from powerline.theme import Theme
|
from powerline.theme import Theme
|
||||||
@ -53,15 +53,19 @@ class VimRenderer(Renderer):
|
|||||||
raise KeyError('There is already a local theme with given matcher')
|
raise KeyError('There is already a local theme with given matcher')
|
||||||
self.local_themes[matcher] = theme
|
self.local_themes[matcher] = theme
|
||||||
|
|
||||||
|
def get_matched_theme(self, match):
|
||||||
|
try:
|
||||||
|
return match['theme']
|
||||||
|
except KeyError:
|
||||||
|
match['theme'] = Theme(theme_config=match['config'], top_theme_config=self.theme_config, **self.theme_kwargs)
|
||||||
|
return match['theme']
|
||||||
|
|
||||||
def get_theme(self, matcher_info):
|
def get_theme(self, matcher_info):
|
||||||
|
if matcher_info is None:
|
||||||
|
return self.get_matched_theme(self.local_themes[None])
|
||||||
for matcher in self.local_themes.keys():
|
for matcher in self.local_themes.keys():
|
||||||
if matcher(matcher_info):
|
if matcher and matcher(matcher_info):
|
||||||
match = self.local_themes[matcher]
|
return self.get_matched_theme(self.local_themes[matcher])
|
||||||
try:
|
|
||||||
return match['theme']
|
|
||||||
except KeyError:
|
|
||||||
match['theme'] = Theme(theme_config=match['config'], top_theme_config=self.theme_config, **self.theme_kwargs)
|
|
||||||
return match['theme']
|
|
||||||
else:
|
else:
|
||||||
return self.theme
|
return self.theme
|
||||||
|
|
||||||
@ -80,28 +84,36 @@ class VimRenderer(Renderer):
|
|||||||
def get_segment_info(self, segment_info, mode):
|
def get_segment_info(self, segment_info, mode):
|
||||||
return segment_info or self.segment_info
|
return segment_info or self.segment_info
|
||||||
|
|
||||||
def render(self, window, window_id, winnr):
|
def render(self, window=None, window_id=None, winnr=None):
|
||||||
'''Render all segments.'''
|
'''Render all segments.'''
|
||||||
if window is vim.current.window:
|
|
||||||
mode = vim_mode(1)
|
|
||||||
mode = mode_translations.get(mode, mode)
|
|
||||||
else:
|
|
||||||
mode = 'nc'
|
|
||||||
segment_info = self.segment_info.copy()
|
segment_info = self.segment_info.copy()
|
||||||
segment_info.update({
|
if window is not None:
|
||||||
'window': window,
|
if window is vim.current.window:
|
||||||
'mode': mode,
|
mode = vim_mode(1)
|
||||||
'window_id': window_id,
|
mode = mode_translations.get(mode, mode)
|
||||||
'winnr': winnr,
|
else:
|
||||||
})
|
mode = 'nc'
|
||||||
segment_info['buffer'] = segment_info['window'].buffer
|
segment_info.update(
|
||||||
segment_info['bufnr'] = segment_info['buffer'].number
|
window=window,
|
||||||
winwidth = segment_info['window'].width
|
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
|
||||||
|
else:
|
||||||
|
mode = None
|
||||||
|
winwidth = int(vim.eval('&columns'))
|
||||||
|
matcher_info = None
|
||||||
statusline = super(VimRenderer, self).render(
|
statusline = super(VimRenderer, self).render(
|
||||||
mode=mode,
|
mode=mode,
|
||||||
width=winwidth,
|
width=winwidth,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
matcher_info=segment_info,
|
matcher_info=matcher_info,
|
||||||
)
|
)
|
||||||
return statusline
|
return statusline
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ segment_getters = {
|
|||||||
"function": get_function,
|
"function": get_function,
|
||||||
"string": get_string,
|
"string": get_string,
|
||||||
"filler": get_filler,
|
"filler": get_filler,
|
||||||
|
"segment_list": get_function,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -59,6 +60,69 @@ def get_attr_func(contents_func, key, args):
|
|||||||
return lambda pl, shutdown_event: func(pl=pl, shutdown_event=shutdown_event, **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):
|
||||||
|
for subsegment_info, subsegment_update in lister(pl=pl, segment_info=segment_info, **patcher_args):
|
||||||
|
for subsegment in subsegments:
|
||||||
|
if subsegment_update:
|
||||||
|
subsegment = subsegment.copy()
|
||||||
|
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)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def process_segment(pl, side, segment_info, parsed_segments, segment):
|
||||||
|
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)
|
||||||
|
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()
|
||||||
|
if contents:
|
||||||
|
draw_divider_position = -1 if side == 'left' else 0
|
||||||
|
for key, i, newval in (
|
||||||
|
('before', 0, ''),
|
||||||
|
('after', -1, ''),
|
||||||
|
('draw_soft_divider', draw_divider_position, True),
|
||||||
|
('draw_hard_divider', draw_divider_position, True),
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
contents[i][key] = segment_base.pop(key)
|
||||||
|
segment_base[key] = newval
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
draw_inner_divider = None
|
||||||
|
if side == 'right':
|
||||||
|
append = parsed_segments.append
|
||||||
|
else:
|
||||||
|
pslen = len(parsed_segments)
|
||||||
|
append = lambda item: parsed_segments.insert(pslen, item)
|
||||||
|
|
||||||
|
for subsegment in (contents if side == 'right' else reversed(contents)):
|
||||||
|
segment_copy = segment_base.copy()
|
||||||
|
segment_copy.update(subsegment)
|
||||||
|
if draw_inner_divider is not None:
|
||||||
|
segment_copy['draw_soft_divider'] = draw_inner_divider
|
||||||
|
draw_inner_divider = segment_copy.pop('draw_inner_divider', None)
|
||||||
|
append(segment_copy)
|
||||||
|
else:
|
||||||
|
segment['contents'] = contents
|
||||||
|
parsed_segments.append(segment)
|
||||||
|
elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None):
|
||||||
|
parsed_segments.append(segment)
|
||||||
|
|
||||||
|
|
||||||
def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=None):
|
def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=None):
|
||||||
data = {
|
data = {
|
||||||
'default_module': default_module or 'powerline.segments.' + ext,
|
'default_module': default_module or 'powerline.segments.' + ext,
|
||||||
@ -90,8 +154,50 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||||||
else:
|
else:
|
||||||
highlight_group = segment.get('highlight_group') or segment.get('name')
|
highlight_group = segment.get('highlight_group') or segment.get('name')
|
||||||
|
|
||||||
if segment_type == 'function':
|
if segment_type in ('function', 'segment_list'):
|
||||||
args = dict(((str(k), v) for k, v in get_key(segment, module, 'args', {}).items()))
|
args = dict(((str(k), v) for k, v in get_key(segment, module, 'args', {}).items()))
|
||||||
|
|
||||||
|
if segment_type == 'segment_list':
|
||||||
|
# Handle startup and shutdown of _contents_func?
|
||||||
|
subsegments = [
|
||||||
|
get(subsegment, side)
|
||||||
|
for subsegment in segment['segments']
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
'name': segment.get('name'),
|
||||||
|
'type': segment_type,
|
||||||
|
'highlight_group': None,
|
||||||
|
'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,
|
||||||
|
patcher_args=args,
|
||||||
|
subsegments=subsegments,
|
||||||
|
lister=_contents_func,
|
||||||
|
),
|
||||||
|
'contents': None,
|
||||||
|
'priority': None,
|
||||||
|
'draw_soft_divider': None,
|
||||||
|
'draw_hard_divider': None,
|
||||||
|
'draw_inner_divider': None,
|
||||||
|
'side': side,
|
||||||
|
'exclude_modes': segment.get('exclude_modes', []),
|
||||||
|
'include_modes': segment.get('include_modes', []),
|
||||||
|
'width': None,
|
||||||
|
'align': None,
|
||||||
|
'startup': None,
|
||||||
|
'shutdown': None,
|
||||||
|
'mode': None,
|
||||||
|
'_rendered_raw': '',
|
||||||
|
'_rendered_hl': '',
|
||||||
|
'_len': None,
|
||||||
|
'_contents_len': None,
|
||||||
|
'_space_left': 0,
|
||||||
|
'_space_right': 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
if segment_type == 'function':
|
||||||
startup_func = get_attr_func(_contents_func, 'startup', args)
|
startup_func = get_attr_func(_contents_func, 'startup', args)
|
||||||
shutdown_func = get_attr_func(_contents_func, 'shutdown', None)
|
shutdown_func = get_attr_func(_contents_func, 'shutdown', None)
|
||||||
|
|
||||||
@ -117,7 +223,6 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||||||
'after': get_key(segment, module, 'after', ''),
|
'after': get_key(segment, module, 'after', ''),
|
||||||
'contents_func': contents_func,
|
'contents_func': contents_func,
|
||||||
'contents': contents,
|
'contents': contents,
|
||||||
'args': args if segment_type == 'function' else {},
|
|
||||||
'priority': segment.get('priority', None),
|
'priority': segment.get('priority', None),
|
||||||
'draw_hard_divider': segment.get('draw_hard_divider', True),
|
'draw_hard_divider': segment.get('draw_hard_divider', True),
|
||||||
'draw_soft_divider': segment.get('draw_soft_divider', True),
|
'draw_soft_divider': segment.get('draw_soft_divider', True),
|
||||||
@ -129,9 +234,11 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module=Non
|
|||||||
'align': segment.get('align', 'l'),
|
'align': segment.get('align', 'l'),
|
||||||
'startup': startup_func,
|
'startup': startup_func,
|
||||||
'shutdown': shutdown_func,
|
'shutdown': shutdown_func,
|
||||||
|
'mode': None,
|
||||||
'_rendered_raw': '',
|
'_rendered_raw': '',
|
||||||
'_rendered_hl': '',
|
'_rendered_hl': '',
|
||||||
'_len': 0,
|
'_len': None,
|
||||||
|
'_contents_len': None,
|
||||||
'_space_left': 0,
|
'_space_left': 0,
|
||||||
'_space_right': 0,
|
'_space_right': 0,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@ except ImportError:
|
|||||||
|
|
||||||
from powerline.bindings.vim import (vim_get_func, getbufvar, vim_getbufoption,
|
from powerline.bindings.vim import (vim_get_func, getbufvar, vim_getbufoption,
|
||||||
buffer_name, vim_getwinvar,
|
buffer_name, vim_getwinvar,
|
||||||
register_buffer_cache)
|
register_buffer_cache, current_tabpage,
|
||||||
|
list_tabpages)
|
||||||
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
||||||
from powerline.lib import add_divider_highlight_group
|
from powerline.lib import add_divider_highlight_group
|
||||||
from powerline.lib.vcs import guess, tree_status
|
from powerline.lib.vcs import guess, tree_status
|
||||||
@ -485,3 +486,138 @@ def trailing_whitespace(pl, segment_info):
|
|||||||
ret = None
|
ret = None
|
||||||
trailing_whitespace_cache[bufnr] = (changedtick, ret)
|
trailing_whitespace_cache[bufnr] = (changedtick, ret)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@requires_segment_info
|
||||||
|
def tabnr(pl, segment_info, show_current=False):
|
||||||
|
'''Show tabpage number
|
||||||
|
|
||||||
|
:param bool show_current:
|
||||||
|
If False do not show current tabpage number. This is default because
|
||||||
|
tabnr is by default only present in tabline.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
tabnr = segment_info['tabnr']
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
if show_current or tabnr != current_tabpage().number:
|
||||||
|
return str(tabnr)
|
||||||
|
|
||||||
|
|
||||||
|
def single_tab(pl, single_text='Bufs', multiple_text='Tabs'):
|
||||||
|
'''Show one text if there is only one tab and another if there are many
|
||||||
|
|
||||||
|
Mostly useful for tabline to indicate what kind of data is shown there.
|
||||||
|
|
||||||
|
:param str single_text:
|
||||||
|
Text displayed when there is only one tabpage. May be None if you do not
|
||||||
|
want to display anything.
|
||||||
|
:param str multiple_text:
|
||||||
|
Text displayed when there is more then one tabpage. May be None if you
|
||||||
|
do not want to display anything.
|
||||||
|
|
||||||
|
Highlight groups used: ``single_tab``, ``many_tabs``.
|
||||||
|
'''
|
||||||
|
if len(list_tabpages()) == 1:
|
||||||
|
return single_text and [{
|
||||||
|
'contents': single_text,
|
||||||
|
'highlight_group': ['single_tab'],
|
||||||
|
}]
|
||||||
|
else:
|
||||||
|
return multiple_text and [{
|
||||||
|
'contents': multiple_text,
|
||||||
|
'highlight_group': ['many_tabs'],
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
|
def tabpage_updated_segment_info(segment_info, tabpage):
|
||||||
|
segment_info = segment_info.copy()
|
||||||
|
window = tabpage.window
|
||||||
|
buffer = window.buffer
|
||||||
|
segment_info.update(
|
||||||
|
tabpage=tabpage,
|
||||||
|
tabnr=tabpage.number,
|
||||||
|
window=window,
|
||||||
|
winnr=window.number,
|
||||||
|
window_id=int(window.vars.get('powerline_window_id', -1)),
|
||||||
|
buffer=buffer,
|
||||||
|
bufnr=buffer.number,
|
||||||
|
)
|
||||||
|
return segment_info
|
||||||
|
|
||||||
|
|
||||||
|
@requires_segment_info
|
||||||
|
def tablister(pl, segment_info):
|
||||||
|
'''List all tab pages in segment_info format
|
||||||
|
|
||||||
|
Specifically generates a list of segment info dictionaries with ``window``,
|
||||||
|
``winnr``, ``window_id``, ``buffer`` and ``bufnr`` keys set to tab-local
|
||||||
|
ones and additional ``tabpage`` and ``tabnr`` keys.
|
||||||
|
|
||||||
|
Sets segment ``mode`` to either ``tab`` (for current tab page) or ``nc``
|
||||||
|
(for all other tab pages).
|
||||||
|
|
||||||
|
Works best with vim-7.4 or later: earlier versions miss tabpage object and
|
||||||
|
thus window objects are not available as well.
|
||||||
|
'''
|
||||||
|
cur_tabpage = current_tabpage()
|
||||||
|
cur_tabnr = cur_tabpage.number
|
||||||
|
|
||||||
|
def add_multiplier(tabpage, dct):
|
||||||
|
dct['priority_multiplier'] = 1 + (0.001 * abs(tabpage.number - cur_tabnr))
|
||||||
|
return dct
|
||||||
|
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
tabpage_updated_segment_info(segment_info, tabpage),
|
||||||
|
add_multiplier(tabpage, {'mode': ('tab' if tabpage == cur_tabpage else 'nc')})
|
||||||
|
)
|
||||||
|
for tabpage in list_tabpages()
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def buffer_updated_segment_info(segment_info, buffer):
|
||||||
|
segment_info = segment_info.copy()
|
||||||
|
segment_info.update(
|
||||||
|
window=None,
|
||||||
|
winnr=None,
|
||||||
|
window_id=None,
|
||||||
|
buffer=buffer,
|
||||||
|
bufnr=buffer.number,
|
||||||
|
)
|
||||||
|
return segment_info
|
||||||
|
|
||||||
|
|
||||||
|
@requires_segment_info
|
||||||
|
def bufferlister(pl, segment_info):
|
||||||
|
'''List all buffers in segment_info format
|
||||||
|
|
||||||
|
Specifically generates a list of segment info dictionaries with ``buffer``
|
||||||
|
and ``bufnr`` keys set to buffer-specific ones, ``window``, ``winnr`` and
|
||||||
|
``window_id`` keys unset.
|
||||||
|
|
||||||
|
Sets segment ``mode`` to either ``buf`` (for current buffer) or ``nc``
|
||||||
|
(for all other buffers).
|
||||||
|
'''
|
||||||
|
cur_buffer = vim.current.buffer
|
||||||
|
cur_bufnr = cur_buffer.number
|
||||||
|
|
||||||
|
def add_multiplier(buffer, dct):
|
||||||
|
dct['priority_multiplier'] = 1 + (0.001 * abs(buffer.number - cur_bufnr))
|
||||||
|
return dct
|
||||||
|
|
||||||
|
return [
|
||||||
|
(
|
||||||
|
buffer_updated_segment_info(segment_info, buffer),
|
||||||
|
add_multiplier(buffer, {'mode': ('tab' if buffer == cur_buffer else 'nc')})
|
||||||
|
)
|
||||||
|
for buffer in vim.buffers
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@requires_segment_info
|
||||||
|
def tabbuflister(*args, **kwargs):
|
||||||
|
if len(list_tabpages()) == 1:
|
||||||
|
return bufferlister(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
return tablister(*args, **kwargs)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
|
|
||||||
from powerline.segment import gen_segment_getter
|
from powerline.segment import gen_segment_getter, process_segment
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
@ -32,6 +32,11 @@ class Theme(object):
|
|||||||
run_once=False,
|
run_once=False,
|
||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
||||||
|
self.dividers = dict((
|
||||||
|
(key, dict((k, u(v))
|
||||||
|
for k, v in val.items()))
|
||||||
|
for key, val in self.dividers.items()
|
||||||
|
))
|
||||||
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
||||||
self.segments = []
|
self.segments = []
|
||||||
self.EMPTY_SEGMENT = {
|
self.EMPTY_SEGMENT = {
|
||||||
@ -91,53 +96,7 @@ class Theme(object):
|
|||||||
for side in [side] if side else ['left', 'right']:
|
for side in [side] if side else ['left', 'right']:
|
||||||
parsed_segments = []
|
parsed_segments = []
|
||||||
for segment in self.segments[line][side]:
|
for segment in self.segments[line][side]:
|
||||||
if segment['type'] == 'function':
|
process_segment(self.pl, side, segment_info, parsed_segments, segment)
|
||||||
self.pl.prefix = segment['name']
|
|
||||||
try:
|
|
||||||
contents = segment['contents_func'](self.pl, segment_info)
|
|
||||||
except Exception as e:
|
|
||||||
self.pl.exception('Exception while computing segment: {0}', str(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
if contents is None:
|
|
||||||
continue
|
|
||||||
if isinstance(contents, list):
|
|
||||||
segment_base = segment.copy()
|
|
||||||
if contents:
|
|
||||||
draw_divider_position = -1 if side == 'left' else 0
|
|
||||||
for key, i, newval in (
|
|
||||||
('before', 0, ''),
|
|
||||||
('after', -1, ''),
|
|
||||||
('draw_soft_divider', draw_divider_position, True),
|
|
||||||
('draw_hard_divider', draw_divider_position, True),
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
contents[i][key] = segment_base.pop(key)
|
|
||||||
segment_base[key] = newval
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
draw_inner_divider = None
|
|
||||||
if side == 'right':
|
|
||||||
append = parsed_segments.append
|
|
||||||
else:
|
|
||||||
pslen = len(parsed_segments)
|
|
||||||
append = lambda item: parsed_segments.insert(pslen, item)
|
|
||||||
|
|
||||||
for subsegment in (contents if side == 'right' else reversed(contents)):
|
|
||||||
segment_copy = segment_base.copy()
|
|
||||||
segment_copy.update(subsegment)
|
|
||||||
if draw_inner_divider is not None:
|
|
||||||
segment_copy['draw_soft_divider'] = draw_inner_divider
|
|
||||||
draw_inner_divider = segment_copy.pop('draw_inner_divider', None)
|
|
||||||
append(segment_copy)
|
|
||||||
else:
|
|
||||||
segment['contents'] = contents
|
|
||||||
parsed_segments.append(segment)
|
|
||||||
elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None):
|
|
||||||
parsed_segments.append(segment)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
for segment in parsed_segments:
|
for segment in parsed_segments:
|
||||||
segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after']
|
segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after']
|
||||||
# Align segment contents
|
# Align segment contents
|
||||||
|
@ -72,7 +72,8 @@ class VimPowerline(Powerline):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
self.get_matcher = gen_matcher_getter(self.ext, self.import_paths)
|
self.get_matcher = gen_matcher_getter(self.ext, self.import_paths)
|
||||||
return dict(((self.get_matcher(key), {'config': self.load_theme_config(val)})
|
return dict(((None if key == '__tabline__' else self.get_matcher(key),
|
||||||
|
{'config': self.load_theme_config(val)})
|
||||||
for key, val in local_themes.items()))
|
for key, val in local_themes.items()))
|
||||||
|
|
||||||
def get_config_paths(self):
|
def get_config_paths(self):
|
||||||
@ -141,6 +142,9 @@ class VimPowerline(Powerline):
|
|||||||
return 'No window {0}'.format(window_id)
|
return 'No window {0}'.format(window_id)
|
||||||
return self.render(window, window_id, winnr)
|
return self.render(window, window_id, winnr)
|
||||||
|
|
||||||
|
def tabline(self):
|
||||||
|
return self.render()
|
||||||
|
|
||||||
def new_window(self):
|
def new_window(self):
|
||||||
window, window_id, winnr = self.win_idx(None)
|
window, window_id, winnr = self.win_idx(None)
|
||||||
return self.render(window, window_id, winnr)
|
return self.render(window, window_id, winnr)
|
||||||
@ -202,3 +206,4 @@ def setup(pyeval=None, pycmd=None, can_replace_pyeval=True):
|
|||||||
# Is immediately changed after new_window function is run. Good for global
|
# Is immediately changed after new_window function is run. Good for global
|
||||||
# value.
|
# value.
|
||||||
vim.command('set statusline=%!{pyeval}(\'powerline.new_window()\')'.format(pyeval=pyeval))
|
vim.command('set statusline=%!{pyeval}(\'powerline.new_window()\')'.format(pyeval=pyeval))
|
||||||
|
vim.command('set tabline=%!{pyeval}(\'powerline.tabline()\')'.format(pyeval=pyeval))
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/vim -S
|
#!/usr/bin/vim -S
|
||||||
set nocompatible
|
set nocompatible
|
||||||
|
tabedit abc
|
||||||
|
tabedit def
|
||||||
try
|
try
|
||||||
source powerline/bindings/vim/plugin/powerline.vim
|
source powerline/bindings/vim/plugin/powerline.vim
|
||||||
catch
|
catch
|
||||||
@ -16,4 +18,4 @@ if len(mess)>1
|
|||||||
call writefile(mess, 'message.fail')
|
call writefile(mess, 'message.fail')
|
||||||
cquit
|
cquit
|
||||||
endif
|
endif
|
||||||
quit!
|
qall!
|
||||||
|
@ -32,7 +32,7 @@ class TestConfig(TestCase):
|
|||||||
local_themes_raw = json.load(f)['ext']['vim']['local_themes']
|
local_themes_raw = json.load(f)['ext']['vim']['local_themes']
|
||||||
# Don't run tests on external/plugin segments
|
# Don't run tests on external/plugin segments
|
||||||
local_themes = dict((k, v) for (k, v) in local_themes_raw.items())
|
local_themes = dict((k, v) for (k, v) in local_themes_raw.items())
|
||||||
self.assertEqual(len(buffers), len(local_themes))
|
self.assertEqual(len(buffers), len(local_themes) - 1)
|
||||||
outputs = {}
|
outputs = {}
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
@ -53,6 +53,8 @@ class TestConfig(TestCase):
|
|||||||
outputs[out] = (i, (args, kwargs), mode)
|
outputs[out] = (i, (args, kwargs), mode)
|
||||||
|
|
||||||
with vim_module._with('bufname', '/tmp/foo.txt'):
|
with vim_module._with('bufname', '/tmp/foo.txt'):
|
||||||
|
out = powerline.render()
|
||||||
|
outputs[out] = (-1, (None, None), 'tab')
|
||||||
with vim_module._with('globals', powerline_config_path=cfg_path):
|
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?', '!'))
|
exclude = set(('no', 'v', 'V', VBLOCK, 's', 'S', SBLOCK, 'R', 'Rv', 'c', 'cv', 'ce', 'r', 'rm', 'r?', '!'))
|
||||||
try:
|
try:
|
||||||
|
@ -787,6 +787,25 @@ class TestVim(TestCase):
|
|||||||
self.assertEqual(trailing_whitespace(), None)
|
self.assertEqual(trailing_whitespace(), None)
|
||||||
self.assertEqual(trailing_whitespace(), None)
|
self.assertEqual(trailing_whitespace(), None)
|
||||||
|
|
||||||
|
def test_tabnr(self):
|
||||||
|
pl = Pl()
|
||||||
|
segment_info = vim_module._get_segment_info()
|
||||||
|
self.assertEqual(vim.tabnr(pl=pl, segment_info=segment_info, show_current=True), '1')
|
||||||
|
self.assertEqual(vim.tabnr(pl=pl, segment_info=segment_info, show_current=False), None)
|
||||||
|
|
||||||
|
def test_single_tab(self):
|
||||||
|
pl = Pl()
|
||||||
|
single_tab = partial(vim.single_tab, pl=pl)
|
||||||
|
with vim_module._with('tabpage'):
|
||||||
|
self.assertEqual(single_tab(), [{'highlight_group': ['many_tabs'], 'contents': 'Tabs'}])
|
||||||
|
self.assertEqual(single_tab(single_text='s', multiple_text='m'), [{'highlight_group': ['many_tabs'], 'contents': 'm'}])
|
||||||
|
self.assertEqual(single_tab(multiple_text='m'), [{'highlight_group': ['many_tabs'], 'contents': 'm'}])
|
||||||
|
self.assertEqual(single_tab(single_text='s'), [{'highlight_group': ['many_tabs'], 'contents': 'Tabs'}])
|
||||||
|
self.assertEqual(single_tab(), [{'highlight_group': ['single_tab'], 'contents': 'Bufs'}])
|
||||||
|
self.assertEqual(single_tab(single_text='s', multiple_text='m'), [{'highlight_group': ['single_tab'], 'contents': 's'}])
|
||||||
|
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'}])
|
||||||
|
|
||||||
|
|
||||||
old_cwd = None
|
old_cwd = None
|
||||||
|
|
||||||
|
34
tests/test_tabline.vim
Executable file
34
tests/test_tabline.vim
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/vim -S
|
||||||
|
source powerline/bindings/vim/plugin/powerline.vim
|
||||||
|
edit abc
|
||||||
|
tabedit def
|
||||||
|
tabedit ghi
|
||||||
|
|
||||||
|
try
|
||||||
|
let &columns = 80
|
||||||
|
let result = eval(&tabline[2:])
|
||||||
|
catch
|
||||||
|
call writefile(['Exception while evaluating &tabline', v:exception], 'message.fail')
|
||||||
|
cquit
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if result isnot# '%#Pl_240_5789784_235_2500134_NONE# 1 %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#abc %#Pl_244_8421504_235_2500134_NONE# %#Pl_240_5789784_235_2500134_NONE#2 %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#def %#Pl_235_2500134_240_5789784_NONE# %#Pl_250_12369084_240_5789784_NONE#./%#Pl_231_16777215_240_5789784_bold#ghi %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE# %#Pl_252_13684944_236_3158064_NONE# %#Pl_235_2500134_252_13684944_bold# Tabs '
|
||||||
|
call writefile(['Unexpected result', result], 'message.fail')
|
||||||
|
cquit
|
||||||
|
endif
|
||||||
|
|
||||||
|
tabonly!
|
||||||
|
|
||||||
|
try
|
||||||
|
let result = eval(&tabline[2:])
|
||||||
|
catch
|
||||||
|
call writefile(['Exception while evaluating &tabline', v:exception], 'message.fail')
|
||||||
|
cquit
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if result isnot# '%#Pl_240_5789784_235_2500134_NONE# ./%#Pl_244_8421504_235_2500134_bold#abc %#Pl_244_8421504_235_2500134_NONE# %#Pl_240_5789784_235_2500134_NONE#./%#Pl_244_8421504_235_2500134_bold#def %#Pl_235_2500134_240_5789784_NONE# %#Pl_250_12369084_240_5789784_NONE#./%#Pl_231_16777215_240_5789784_bold#ghi %#Pl_240_5789784_236_3158064_NONE# %#Pl_231_16777215_236_3158064_NONE# %#Pl_252_13684944_236_3158064_NONE# %#Pl_235_2500134_252_13684944_bold# Bufs '
|
||||||
|
call writefile(['Unexpected result (2)', result], 'message.fail')
|
||||||
|
cquit
|
||||||
|
endif
|
||||||
|
|
||||||
|
qall!
|
313
tests/vim.py
313
tests/vim.py
@ -2,12 +2,13 @@
|
|||||||
_log = []
|
_log = []
|
||||||
vars = {}
|
vars = {}
|
||||||
vvars = {'version': 703}
|
vvars = {'version': 703}
|
||||||
_window = 0
|
_tabpage = 0
|
||||||
_mode = 'n'
|
_mode = 'n'
|
||||||
_buf_purge_events = set()
|
_buf_purge_events = set()
|
||||||
options = {
|
options = {
|
||||||
'paste': 0,
|
'paste': 0,
|
||||||
'ambiwidth': 'single',
|
'ambiwidth': 'single',
|
||||||
|
'columns': 80,
|
||||||
}
|
}
|
||||||
_last_bufnr = 0
|
_last_bufnr = 0
|
||||||
_highlights = {}
|
_highlights = {}
|
||||||
@ -29,6 +30,12 @@ def _set_thread_id():
|
|||||||
_set_thread_id()
|
_set_thread_id()
|
||||||
|
|
||||||
|
|
||||||
|
def _print_log():
|
||||||
|
for item in _log:
|
||||||
|
print (item)
|
||||||
|
_log[:] = ()
|
||||||
|
|
||||||
|
|
||||||
def _vim(func):
|
def _vim(func):
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from threading import current_thread
|
from threading import current_thread
|
||||||
@ -67,6 +74,10 @@ class _Buffers(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.d = {}
|
self.d = {}
|
||||||
|
|
||||||
|
@_vim
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.d)
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return self.d[item]
|
return self.d[item]
|
||||||
@ -75,38 +86,35 @@ class _Buffers(object):
|
|||||||
def __setitem__(self, item, value):
|
def __setitem__(self, item, value):
|
||||||
self.d[item] = value
|
self.d[item] = value
|
||||||
|
|
||||||
|
@_vim
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.d.values())
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return item in self.d
|
return item in self.d
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __nonzero__(self):
|
def _keys(self):
|
||||||
return bool(self.d)
|
|
||||||
|
|
||||||
@_vim
|
|
||||||
def keys(self):
|
|
||||||
return self.d.keys()
|
return self.d.keys()
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def pop(self, *args, **kwargs):
|
def _pop(self, *args, **kwargs):
|
||||||
return self.d.pop(*args, **kwargs)
|
return self.d.pop(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
buffers = _Buffers()
|
buffers = _Buffers()
|
||||||
|
|
||||||
|
|
||||||
class _Windows(object):
|
class _ObjList(object):
|
||||||
@_vim
|
@_vim
|
||||||
def __init__(self):
|
def __init__(self, objtype):
|
||||||
self.l = []
|
self.l = []
|
||||||
|
self.objtype = objtype
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return self.l[item]
|
return self.l[item - int(item > 0)]
|
||||||
|
|
||||||
@_vim
|
|
||||||
def __setitem__(self, item, value):
|
|
||||||
self.l[item] = value
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
@ -117,24 +125,22 @@ class _Windows(object):
|
|||||||
return iter(self.l)
|
return iter(self.l)
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def __nonzero__(self):
|
def _pop(self, idx):
|
||||||
return not not self.l
|
obj = self.l.pop(idx - 1)
|
||||||
|
for moved_obj in self.l[idx - 1:]:
|
||||||
@_vim
|
moved_obj.number -= 1
|
||||||
def _pop(self, *args, **kwargs):
|
return obj
|
||||||
return self.l.pop(*args, **kwargs)
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _append(self, *args, **kwargs):
|
def _append(self, *args, **kwargs):
|
||||||
return self.l.append(*args, **kwargs)
|
return self.l.append(*args, **kwargs)
|
||||||
|
|
||||||
|
@_vim
|
||||||
windows = _Windows()
|
def _new(self, *args, **kwargs):
|
||||||
|
number = len(self) + 1
|
||||||
|
new_obj = self.objtype(number, *args, **kwargs)
|
||||||
@_vim
|
self._append(new_obj)
|
||||||
def _buffer():
|
return new_obj
|
||||||
return windows[_window - 1].buffer.number
|
|
||||||
|
|
||||||
|
|
||||||
def _construct_result(r):
|
def _construct_result(r):
|
||||||
@ -227,23 +233,50 @@ def eval(expr):
|
|||||||
import re
|
import re
|
||||||
match = re.match(r'^getwinvar\((\d+), "(\w+)"\)$', expr)
|
match = re.match(r'^getwinvar\((\d+), "(\w+)"\)$', expr)
|
||||||
if not match:
|
if not match:
|
||||||
raise NotImplementedError
|
raise NotImplementedError(expr)
|
||||||
winnr = int(match.group(1))
|
winnr = int(match.group(1))
|
||||||
varname = match.group(2)
|
varname = match.group(2)
|
||||||
return _emul_getwinvar(winnr, varname)
|
return _emul_getwinvar(winnr, varname)
|
||||||
elif expr.startswith('has_key('):
|
elif expr.startswith('has_key('):
|
||||||
import re
|
import re
|
||||||
match = re.match(r'^has_key\(getwinvar\((\d+), ""\), "(\w+)"\)$', expr)
|
match = re.match(r'^has_key\(getwinvar\((\d+), ""\), "(\w+)"\)$', expr)
|
||||||
if not match:
|
if match:
|
||||||
raise NotImplementedError
|
winnr = int(match.group(1))
|
||||||
winnr = int(match.group(1))
|
varname = match.group(2)
|
||||||
varname = match.group(2)
|
return 0 + (varname in current.tabpage.windows[winnr].vars)
|
||||||
return 0 + (varname in windows[winnr - 1].vars)
|
else:
|
||||||
|
match = re.match(r'^has_key\(gettabwinvar\((\d+), (\d+), ""\), "(\w+)"\)$', expr)
|
||||||
|
if not match:
|
||||||
|
raise NotImplementedError(expr)
|
||||||
|
tabnr = int(match.group(1))
|
||||||
|
winnr = int(match.group(2))
|
||||||
|
varname = match.group(3)
|
||||||
|
return 0 + (varname in tabpages[tabnr].windows[winnr].vars)
|
||||||
elif expr == 'getbufvar("%", "NERDTreeRoot").path.str()':
|
elif expr == 'getbufvar("%", "NERDTreeRoot").path.str()':
|
||||||
import os
|
import os
|
||||||
assert os.path.basename(buffers[_buffer()].name).startswith('NERD_tree_')
|
assert os.path.basename(current.buffer.name).startswith('NERD_tree_')
|
||||||
return '/usr/include'
|
return '/usr/include'
|
||||||
raise NotImplementedError
|
elif expr == 'tabpagenr()':
|
||||||
|
return current.tabpage.number
|
||||||
|
elif expr == 'tabpagenr("$")':
|
||||||
|
return len(tabpages)
|
||||||
|
elif expr.startswith('tabpagewinnr('):
|
||||||
|
tabnr = int(expr[len('tabpagewinnr('):-1])
|
||||||
|
return tabpages[tabnr].window.number
|
||||||
|
elif expr.startswith('tabpagebuflist('):
|
||||||
|
import re
|
||||||
|
match = re.match(r'tabpagebuflist\((\d+)\)\[(\d+)\]', expr)
|
||||||
|
tabnr = int(match.group(1))
|
||||||
|
winnr = int(match.group(2)) + 1
|
||||||
|
return tabpages[tabnr].windows[winnr].buffer.number
|
||||||
|
elif expr.startswith('gettabwinvar('):
|
||||||
|
import re
|
||||||
|
match = re.match(r'gettabwinvar\((\d+), (\d+), "(\w+)"\)', expr)
|
||||||
|
tabnr = int(match.group(1))
|
||||||
|
winnr = int(match.group(2))
|
||||||
|
varname = match.group(3)
|
||||||
|
return tabpages[tabnr].windows[winnr].vars[varname]
|
||||||
|
raise NotImplementedError(expr)
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
@ -277,7 +310,7 @@ def _emul_getbufvar(bufnr, varname):
|
|||||||
import re
|
import re
|
||||||
if varname[0] == '&':
|
if varname[0] == '&':
|
||||||
if bufnr == '%':
|
if bufnr == '%':
|
||||||
bufnr = buffers[_buffer()].number
|
bufnr = current.buffer.number
|
||||||
if bufnr not in buffers:
|
if bufnr not in buffers:
|
||||||
return ''
|
return ''
|
||||||
try:
|
try:
|
||||||
@ -289,7 +322,7 @@ def _emul_getbufvar(bufnr, varname):
|
|||||||
return ''
|
return ''
|
||||||
elif re.match('^[a-zA-Z_]+$', varname):
|
elif re.match('^[a-zA-Z_]+$', varname):
|
||||||
if bufnr == '%':
|
if bufnr == '%':
|
||||||
bufnr = buffers[_buffer()].number
|
bufnr = current.buffer.number
|
||||||
if bufnr not in buffers:
|
if bufnr not in buffers:
|
||||||
return ''
|
return ''
|
||||||
return buffers[bufnr].vars[varname]
|
return buffers[bufnr].vars[varname]
|
||||||
@ -299,25 +332,25 @@ def _emul_getbufvar(bufnr, varname):
|
|||||||
@_vim
|
@_vim
|
||||||
@_str_func
|
@_str_func
|
||||||
def _emul_getwinvar(winnr, varname):
|
def _emul_getwinvar(winnr, varname):
|
||||||
return windows[winnr - 1].vars.get(varname, '')
|
return current.tabpage.windows[winnr].vars.get(varname, '')
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_setwinvar(winnr, varname, value):
|
def _emul_setwinvar(winnr, varname, value):
|
||||||
windows[winnr - 1].vars[varname] = value
|
current.tabpage.windows[winnr].vars[varname] = value
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_virtcol(expr):
|
def _emul_virtcol(expr):
|
||||||
if expr == '.' or isinstance(expr, list):
|
if expr == '.' or isinstance(expr, list):
|
||||||
return windows[_window - 1].cursor[1] + 1
|
return current.window.cursor[1] + 1
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_getpos(expr):
|
def _emul_getpos(expr):
|
||||||
if expr == '.' or expr == 'v':
|
if expr == '.' or expr == 'v':
|
||||||
return [0, windows[_window - 1].cursor[0] + 1, windows[_window - 1].cursor[1] + 1, 0]
|
return [0, current.window.cursor[0] + 1, current.window.cursor[1] + 1, 0]
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@ -342,7 +375,7 @@ def _emul_fnamemodify(path, modstring):
|
|||||||
def _emul_expand(expr):
|
def _emul_expand(expr):
|
||||||
global _abuf
|
global _abuf
|
||||||
if expr == '<abuf>':
|
if expr == '<abuf>':
|
||||||
return _abuf or _buffer()
|
return _abuf or current.buffer.number
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@ -362,7 +395,7 @@ def _emul_exists(varname):
|
|||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_line2byte(line):
|
def _emul_line2byte(line):
|
||||||
buflines = _buf_lines[_buffer()]
|
buflines = current.buffer._buf_lines
|
||||||
if line == len(buflines) + 1:
|
if line == len(buflines) + 1:
|
||||||
return sum((len(s) for s in buflines)) + 1
|
return sum((len(s) for s in buflines)) + 1
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -370,8 +403,8 @@ def _emul_line2byte(line):
|
|||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _emul_line(expr):
|
def _emul_line(expr):
|
||||||
cursorline = windows[_window - 1].cursor[0] + 1
|
cursorline = current.window.cursor[0] + 1
|
||||||
numlines = len(_buf_lines[_buffer()])
|
numlines = len(current.buffer._buf_lines)
|
||||||
if expr == 'w0':
|
if expr == 'w0':
|
||||||
return max(cursorline - 5, 1)
|
return max(cursorline - 5, 1)
|
||||||
if expr == 'w$':
|
if expr == 'w$':
|
||||||
@ -395,16 +428,15 @@ def _emul_bufname(bufnr):
|
|||||||
return b''
|
return b''
|
||||||
|
|
||||||
|
|
||||||
_window_ids = [None]
|
|
||||||
_window_id = 0
|
_window_id = 0
|
||||||
|
|
||||||
|
|
||||||
class _Window(object):
|
class _Window(object):
|
||||||
def __init__(self, buffer=None, cursor=(1, 0), width=80):
|
def __init__(self, number, buffer=None, cursor=(1, 0), width=80):
|
||||||
global _window_id
|
global _window_id
|
||||||
self.cursor = cursor
|
self.cursor = cursor
|
||||||
self.width = width
|
self.width = width
|
||||||
self.number = len(windows) + 1
|
self.number = number
|
||||||
if buffer:
|
if buffer:
|
||||||
if type(buffer) is _Buffer:
|
if type(buffer) is _Buffer:
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
@ -412,19 +444,45 @@ class _Window(object):
|
|||||||
self.buffer = _Buffer(**buffer)
|
self.buffer = _Buffer(**buffer)
|
||||||
else:
|
else:
|
||||||
self.buffer = _Buffer()
|
self.buffer = _Buffer()
|
||||||
windows._append(self)
|
|
||||||
_window_id += 1
|
_window_id += 1
|
||||||
_window_ids.append(_window_id)
|
self._window_id = _window_id
|
||||||
self.options = {}
|
self.options = {}
|
||||||
self.vars = {}
|
self.vars = {
|
||||||
|
'powerline_window_id': self._window_id,
|
||||||
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<window ' + str(self.number - 1) + '>'
|
return '<window ' + str(self.number - 1) + '>'
|
||||||
|
|
||||||
|
|
||||||
_buf_lines = {}
|
class _Tabpage(object):
|
||||||
_undostate = {}
|
def __init__(self, number):
|
||||||
_undo_written = {}
|
self.windows = _ObjList(_Window)
|
||||||
|
self.number = number
|
||||||
|
|
||||||
|
def _new_window(self, **kwargs):
|
||||||
|
self.window = self.windows._new(**kwargs)
|
||||||
|
return self.window
|
||||||
|
|
||||||
|
def _close_window(self, winnr, open_window=True):
|
||||||
|
curwinnr = self.window.number
|
||||||
|
win = self.windows._pop(winnr)
|
||||||
|
if self.windows and winnr == curwinnr:
|
||||||
|
self.window = self.windows[-1]
|
||||||
|
elif open_window:
|
||||||
|
current.tabpage._new_window()
|
||||||
|
return win
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
while self.windows:
|
||||||
|
self._close_window(1, False)
|
||||||
|
tabpages._pop(self.number)
|
||||||
|
_tabpage = len(tabpages)
|
||||||
|
|
||||||
|
|
||||||
|
tabpages = _ObjList(_Tabpage)
|
||||||
|
|
||||||
|
|
||||||
_abuf = None
|
_abuf = None
|
||||||
|
|
||||||
|
|
||||||
@ -446,10 +504,9 @@ class _Buffer(object):
|
|||||||
'fileencoding': 'utf-8',
|
'fileencoding': 'utf-8',
|
||||||
'textwidth': 80,
|
'textwidth': 80,
|
||||||
}
|
}
|
||||||
_buf_lines[bufnr] = ['']
|
self._buf_lines = ['']
|
||||||
from copy import copy
|
self._undostate = [self._buf_lines[:]]
|
||||||
_undostate[bufnr] = [copy(_buf_lines[bufnr])]
|
self._undo_written = len(self._undostate)
|
||||||
_undo_written[bufnr] = len(_undostate[bufnr])
|
|
||||||
buffers[bufnr] = self
|
buffers[bufnr] = self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -471,27 +528,27 @@ class _Buffer(object):
|
|||||||
self._name = os.path.abspath(name)
|
self._name = os.path.abspath(name)
|
||||||
|
|
||||||
def __getitem__(self, line):
|
def __getitem__(self, line):
|
||||||
return _buf_lines[self.number][line]
|
return self._buf_lines[line]
|
||||||
|
|
||||||
def __setitem__(self, line, value):
|
def __setitem__(self, line, value):
|
||||||
self.options['modified'] = 1
|
self.options['modified'] = 1
|
||||||
self.vars['changedtick'] += 1
|
self.vars['changedtick'] += 1
|
||||||
_buf_lines[self.number][line] = value
|
self._buf_lines[line] = value
|
||||||
from copy import copy
|
from copy import copy
|
||||||
_undostate[self.number].append(copy(_buf_lines[self.number]))
|
self._undostate.append(copy(self._buf_lines))
|
||||||
|
|
||||||
def __setslice__(self, *args):
|
def __setslice__(self, *args):
|
||||||
self.options['modified'] = 1
|
self.options['modified'] = 1
|
||||||
self.vars['changedtick'] += 1
|
self.vars['changedtick'] += 1
|
||||||
_buf_lines[self.number].__setslice__(*args)
|
self._buf_lines.__setslice__(*args)
|
||||||
from copy import copy
|
from copy import copy
|
||||||
_undostate[self.number].append(copy(_buf_lines[self.number]))
|
self._undostate.append(copy(self._buf_lines))
|
||||||
|
|
||||||
def __getslice__(self, *args):
|
def __getslice__(self, *args):
|
||||||
return _buf_lines[self.number].__getslice__(*args)
|
return self._buf_lines.__getslice__(*args)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(_buf_lines[self.number])
|
return len(self._buf_lines)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<buffer ' + str(self.name) + '>'
|
return '<buffer ' + str(self.name) + '>'
|
||||||
@ -514,22 +571,20 @@ class _Buffer(object):
|
|||||||
exec(event, __main__.__dict__)
|
exec(event, __main__.__dict__)
|
||||||
finally:
|
finally:
|
||||||
_abuf = None
|
_abuf = None
|
||||||
if _buf_lines:
|
|
||||||
_buf_lines.pop(bufnr)
|
|
||||||
if _undostate:
|
|
||||||
_undostate.pop(bufnr)
|
|
||||||
if _undo_written:
|
|
||||||
_undo_written.pop(bufnr)
|
|
||||||
|
|
||||||
|
|
||||||
class _Current(object):
|
class _Current(object):
|
||||||
@property
|
@property
|
||||||
def buffer(self):
|
def buffer(self):
|
||||||
return buffers[_buffer()]
|
return self.window.buffer
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def window(self):
|
def window(self):
|
||||||
return windows[_window - 1]
|
return self.tabpage.window
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tabpage(self):
|
||||||
|
return tabpages[_tabpage - 1]
|
||||||
|
|
||||||
|
|
||||||
current = _Current()
|
current = _Current()
|
||||||
@ -549,7 +604,7 @@ def _init():
|
|||||||
for varname, value in globals().items():
|
for varname, value in globals().items():
|
||||||
if varname[0] != '_':
|
if varname[0] != '_':
|
||||||
_dict[varname] = value
|
_dict[varname] = value
|
||||||
_new()
|
_tabnew()
|
||||||
return _dict
|
return _dict
|
||||||
|
|
||||||
|
|
||||||
@ -561,12 +616,17 @@ def _get_segment_info():
|
|||||||
}
|
}
|
||||||
mode = _mode
|
mode = _mode
|
||||||
mode = mode_translations.get(mode, mode)
|
mode = mode_translations.get(mode, mode)
|
||||||
|
window = current.window
|
||||||
|
buffer = current.buffer
|
||||||
|
tabpage = current.tabpage
|
||||||
return {
|
return {
|
||||||
'window': windows[_window - 1],
|
'window': window,
|
||||||
'winnr': _window,
|
'winnr': window.number,
|
||||||
'buffer': buffers[_buffer()],
|
'buffer': buffer,
|
||||||
'bufnr': _buffer(),
|
'bufnr': buffer.number,
|
||||||
'window_id': _window_ids[_window],
|
'tabpage': tabpage,
|
||||||
|
'tabnr': tabpage.number,
|
||||||
|
'window_id': window._window_id,
|
||||||
'mode': mode,
|
'mode': mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,85 +648,78 @@ def _start_mode(mode):
|
|||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _undo():
|
def _undo():
|
||||||
if len(_undostate[_buffer()]) == 1:
|
if len(current.buffer._undostate) == 1:
|
||||||
return
|
return
|
||||||
_undostate[_buffer()].pop(-1)
|
buffer = current.buffer
|
||||||
_buf_lines[_buffer()] = _undostate[_buffer()][-1]
|
buffer._undostate.pop(-1)
|
||||||
buf = current.buffer
|
buffer._buf_lines = buffer._undostate[-1]
|
||||||
if _undo_written[_buffer()] == len(_undostate[_buffer()]):
|
if buffer._undo_written == len(buffer._undostate):
|
||||||
buf.options['modified'] = 0
|
buffer.options['modified'] = 0
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _edit(name=None):
|
def _edit(name=None):
|
||||||
global _last_bufnr
|
if current.buffer.name is None:
|
||||||
if _buffer() and buffers[_buffer()].name is None:
|
buffer = current.buffer
|
||||||
buf = buffers[_buffer()]
|
buffer.name = name
|
||||||
buf.name = name
|
|
||||||
else:
|
else:
|
||||||
buf = _Buffer(name)
|
buffer = _Buffer(name)
|
||||||
windows[_window - 1].buffer = buf
|
current.window.buffer = buffer
|
||||||
|
|
||||||
|
|
||||||
|
@_vim
|
||||||
|
def _tabnew(name=None):
|
||||||
|
global windows
|
||||||
|
tabpage = tabpages._new()
|
||||||
|
windows = tabpage.windows
|
||||||
|
_tabpage = len(tabpages)
|
||||||
|
_new(name)
|
||||||
|
return tabpage
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _new(name=None):
|
def _new(name=None):
|
||||||
global _window
|
current.tabpage._new_window(buffer={'name': name})
|
||||||
_Window(buffer={'name': name})
|
|
||||||
_window = len(windows)
|
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _split():
|
def _split():
|
||||||
global _window
|
current.tabpage._new_window(buffer=current.buffer)
|
||||||
_Window(buffer=buffers[_buffer()])
|
|
||||||
_window = len(windows)
|
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
|
||||||
def _del_window(winnr):
|
|
||||||
win = windows._pop(winnr - 1)
|
|
||||||
_window_ids.pop(winnr)
|
|
||||||
return win
|
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _close(winnr, wipe=True):
|
def _close(winnr, wipe=True):
|
||||||
global _window
|
win = current.tabpage._close_window(winnr)
|
||||||
win = _del_window(winnr)
|
|
||||||
if _window == winnr:
|
|
||||||
_window = len(windows)
|
|
||||||
if wipe:
|
if wipe:
|
||||||
for w in windows:
|
for w in current.tabpage.windows:
|
||||||
if w.buffer.number == win.buffer.number:
|
if w.buffer.number == win.buffer.number:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
_bw(win.buffer.number)
|
_bw(win.buffer.number)
|
||||||
if not windows:
|
|
||||||
_Window()
|
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _bw(bufnr=None):
|
def _bw(bufnr=None):
|
||||||
bufnr = bufnr or _buffer()
|
bufnr = bufnr or current.buffer.number
|
||||||
winnr = 1
|
winnr = 1
|
||||||
for win in windows:
|
for win in current.tabpage.windows:
|
||||||
if win.buffer.number == bufnr:
|
if win.buffer.number == bufnr:
|
||||||
_close(winnr, wipe=False)
|
_close(winnr, wipe=False)
|
||||||
winnr += 1
|
winnr += 1
|
||||||
buffers.pop(bufnr)
|
buffers._pop(bufnr)
|
||||||
if not buffers:
|
if not buffers:
|
||||||
_Buffer()
|
_Buffer()
|
||||||
_b(max(buffers.keys()))
|
_b(max(buffers._keys()))
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _b(bufnr):
|
def _b(bufnr):
|
||||||
windows[_window - 1].buffer = buffers[bufnr]
|
current.window.buffer = buffers[bufnr]
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _set_cursor(line, col):
|
def _set_cursor(line, col):
|
||||||
windows[_window - 1].cursor = (line, col)
|
current.window.cursor = (line, col)
|
||||||
if _mode == 'n':
|
if _mode == 'n':
|
||||||
_launch_event('CursorMoved')
|
_launch_event('CursorMoved')
|
||||||
elif _mode == 'i':
|
elif _mode == 'i':
|
||||||
@ -675,12 +728,12 @@ def _set_cursor(line, col):
|
|||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _get_buffer():
|
def _get_buffer():
|
||||||
return buffers[_buffer()]
|
return current.buffer
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _set_bufoption(option, value, bufnr=None):
|
def _set_bufoption(option, value, bufnr=None):
|
||||||
buffers[bufnr or _buffer()].options[option] = value
|
buffers[bufnr or current.buffer.number].options[option] = value
|
||||||
if option == 'filetype':
|
if option == 'filetype':
|
||||||
_launch_event('FileType')
|
_launch_event('FileType')
|
||||||
|
|
||||||
@ -691,7 +744,7 @@ class _WithNewBuffer(object):
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.call()
|
self.call()
|
||||||
self.bufnr = _buffer()
|
self.bufnr = current.buffer.number
|
||||||
return _get_segment_info()
|
return _get_segment_info()
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
@ -720,7 +773,7 @@ class _WithBufOption(object):
|
|||||||
self.new = new
|
self.new = new
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.buffer = buffers[_buffer()]
|
self.buffer = current.buffer
|
||||||
self.old = _set_dict(self.buffer.options, self.new, _set_bufoption)[0]
|
self.old = _set_dict(self.buffer.options, self.new, _set_bufoption)[0]
|
||||||
|
|
||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
@ -768,7 +821,7 @@ class _WithBufName(object):
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
import os
|
import os
|
||||||
buffer = buffers[_buffer()]
|
buffer = current.buffer
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.old = buffer.name
|
self.old = buffer.name
|
||||||
buffer.name = self.new
|
buffer.name = self.new
|
||||||
@ -780,6 +833,18 @@ class _WithBufName(object):
|
|||||||
self.buffer.name = self.old
|
self.buffer.name = self.old
|
||||||
|
|
||||||
|
|
||||||
|
class _WithNewTabPage(object):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.args = args
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.tab = _tabnew(*self.args, **self.kwargs)
|
||||||
|
|
||||||
|
def __exit__(self, *args):
|
||||||
|
self.tab._close()
|
||||||
|
|
||||||
|
|
||||||
@_vim
|
@_vim
|
||||||
def _with(key, *args, **kwargs):
|
def _with(key, *args, **kwargs):
|
||||||
if key == 'buffer':
|
if key == 'buffer':
|
||||||
@ -795,11 +860,13 @@ def _with(key, *args, **kwargs):
|
|||||||
elif key == 'globals':
|
elif key == 'globals':
|
||||||
return _WithDict(vars, **kwargs)
|
return _WithDict(vars, **kwargs)
|
||||||
elif key == 'wvars':
|
elif key == 'wvars':
|
||||||
return _WithDict(windows[_window - 1].vars, **kwargs)
|
return _WithDict(current.window.vars, **kwargs)
|
||||||
elif key == 'environ':
|
elif key == 'environ':
|
||||||
return _WithDict(_environ, **kwargs)
|
return _WithDict(_environ, **kwargs)
|
||||||
elif key == 'split':
|
elif key == 'split':
|
||||||
return _WithSplit()
|
return _WithSplit()
|
||||||
|
elif key == 'tabpage':
|
||||||
|
return _WithNewTabPage(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class error(Exception):
|
class error(Exception):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user