From 356cb43ea27d1f0d7597cf2ce0aefebc62bcc3d3 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 29 Aug 2014 20:11:26 +0400 Subject: [PATCH] Add `powerline_segment_datas` attribute Fixes #1035 --- docs/source/configuration/reference.rst | 2 + docs/source/develop/segments.rst | 11 +++++ powerline/__init__.py | 10 +++-- powerline/segment.py | 19 ++++++-- powerline/theme.py | 11 ++++- tests/test_configuration.py | 59 ++++++++++++++++++++++--- 6 files changed, 99 insertions(+), 13 deletions(-) diff --git a/docs/source/configuration/reference.rst b/docs/source/configuration/reference.rst index 9277e4f9..d4e8e432 100644 --- a/docs/source/configuration/reference.rst +++ b/docs/source/configuration/reference.rst @@ -265,6 +265,8 @@ extension-specific key ` or from :ref:`default_top_theme common configuration key `. Powerline ships with the following top themes: +.. _config-top_themes-list: + ========================== ==================================================== Theme Description ========================== ==================================================== diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst index a17fd1b1..fe802818 100644 --- a/docs/source/develop/segments.rst +++ b/docs/source/develop/segments.rst @@ -40,6 +40,17 @@ powerline: This attribute controls whether segment will receive ``create_watcher`` argument: if it is present argument will be received. +``powerline_segment_datas`` + This attribute must be a dictionary containing ``top_theme: segment_data`` + mapping where ``top_theme`` is any theme name (it is expected that all of + the names from :ref:`top-level themes list ` are + present) and ``segment_data`` is a dictionary like the one that is contained + inside :ref:`segment_data dictionary in configuration + `. This attribute should be used to specify + default theme-specific values for *third-party* segments: powerline + theme-specific values go directly to :ref:`top-level themes + `. + ``startup`` This attribute must be a callable which accepts the following keyword arguments: diff --git a/powerline/__init__.py b/powerline/__init__.py index 1bc6fa06..d94329d2 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -485,13 +485,15 @@ class Powerline(object): self.ext_config = config['ext'][self.ext] + top_theme = ( + self.ext_config.get('top_theme') + or self.common_config['default_top_theme'] + ) self.theme_levels = ( - os.path.join('themes', ( - self.ext_config.get('top_theme') - or self.common_config['default_top_theme'] - )), + os.path.join('themes', top_theme), os.path.join('themes', self.ext, '__main__'), ) + self.renderer_options['theme_kwargs']['top_theme'] = top_theme if self.ext_config != self.prev_ext_config: ext_config_differs = True diff --git a/powerline/segment.py b/powerline/segment.py index d75be664..7513a92b 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -4,7 +4,7 @@ from __future__ import absolute_import, unicode_literals, division, print_functi from powerline.lib.watcher import create_file_watcher -def list_segment_key_values(segment, theme_configs, key, module=None, default=None): +def list_segment_key_values(segment, theme_configs, segment_data, key, module=None, default=None): try: yield segment[key] except KeyError: @@ -32,6 +32,11 @@ def list_segment_key_values(segment, theme_configs, key, module=None, default=No yield segment_data[name][key] except KeyError: pass + if segment_data is not None: + try: + yield segment_data[key] + except KeyError: + pass yield default @@ -173,14 +178,15 @@ def process_segment(pl, side, segment_info, parsed_segments, segment, mode): parsed_segments.append(segment) -def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, get_module_attr): +def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, get_module_attr, top_theme): data = { 'default_module': default_module or 'powerline.segments.' + ext, 'get_module_attr': get_module_attr, + 'segment_data': None, } def get_key(merge, segment, module, key, default=None): - return get_segment_key(merge, segment, theme_configs, key, module, default) + return get_segment_key(merge, segment, theme_configs, data['segment_data'], key, module, default) data['get_key'] = get_key def get(segment, side): @@ -199,6 +205,13 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge if not get_key(False, segment, module, 'display', True): return None + segment_datas = getattr(_contents_func, 'powerline_segment_datas', None) + if segment_datas: + try: + data['segment_data'] = segment_datas[top_theme] + except KeyError: + pass + if segment_type == 'function': highlight_group = [module + '.' + segment['name'], segment['name']] else: diff --git a/powerline/theme.py b/powerline/theme.py index fe494457..2c15886d 100644 --- a/powerline/theme.py +++ b/powerline/theme.py @@ -30,6 +30,7 @@ class Theme(object): common_config, pl, get_module_attr, + top_theme, main_theme_config=None, run_once=False, shutdown_event=None): @@ -54,7 +55,15 @@ class Theme(object): theme_configs = [theme_config] if main_theme_config: theme_configs.append(main_theme_config) - get_segment = gen_segment_getter(pl, ext, common_config, theme_configs, theme_config.get('default_module'), get_module_attr) + get_segment = gen_segment_getter( + pl, + ext, + common_config, + theme_configs, + theme_config.get('default_module'), + get_module_attr, + top_theme + ) for segdict in itertools.chain((theme_config['segments'],), theme_config['segments'].get('above', ())): self.segments.append(new_empty_segment_line()) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 39bb9d20..87817ed6 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1,13 +1,18 @@ # vim:fileencoding=utf-8:noet from __future__ import unicode_literals, absolute_import, division -import tests.vim as vim_module -from tests import TestCase -from tests.lib.config_mock import get_powerline, get_powerline_raw, swap_attributes -from functools import wraps -from copy import deepcopy + import sys import os +from functools import wraps +from copy import deepcopy + +import tests.vim as vim_module + +from tests import TestCase +from tests.lib.config_mock import get_powerline, get_powerline_raw, swap_attributes +from tests.lib import Args + def highlighted_string(s, group, **kwargs): ret = { @@ -428,6 +433,50 @@ class TestModes(TestRender): self.assertRenderEqual(p, '{56} s2{6-}>>{--}', mode='m3') +class TestSegmentAttributes(TestRender): + @add_args + def test_no_attributes(self, p, config): + def m1(divider=',', **kwargs): + return divider.join(kwargs.keys()) + divider + sys.modules['bar'] = Args(m1=m1) + config['themes/test/default']['segments'] = { + 'left': [ + { + 'name': 'm1', + 'module': 'bar' + } + ] + } + self.assertRenderEqual(p, '{56} pl,{6-}>>{--}') + + @add_args + def test_segment_datas(self, p, config): + def m1(divider=',', **kwargs): + return divider.join(kwargs.keys()) + divider + m1.powerline_segment_datas = { + 'powerline': { + 'args': { + 'divider': ';' + } + }, + 'ascii': { + 'args': { + 'divider': '--' + } + } + } + sys.modules['bar'] = Args(m1=m1) + config['themes/test/default']['segments'] = { + 'left': [ + { + 'name': 'm1', + 'module': 'bar' + } + ] + } + self.assertRenderEqual(p, '{56} pl;{6-}>>{--}') + + class TestVim(TestCase): def test_environ_update(self): # Regression test: test that segment obtains environment from vim, not