diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index e1d3f59a..25cf05fb 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -145,9 +145,13 @@ Common configuration is a subdictionary that is a value of ``ext`` key in Defines the colorscheme used for this extension. ``theme`` + .. _config-ext-theme: + Defines the theme used for this extension. ``local_themes`` + .. _config-ext-local_themes: + Defines themes used when certain conditions are met, e.g. for buffer-specific statuslines in vim. Requires a custom matcher and theme. @@ -219,6 +223,21 @@ Themes ``default_module`` Python module where segments will be looked by default. +.. _config-themes-segment_data: + +``segment_data`` + A dict where keys are segment names or strings ``{module}.{name}``. Used to + specify default values for various keys: + :ref:`after `, + :ref:`before `, + :ref:`contents ` (only for string segments + if :ref:`name ` is defined), + :ref:`args ` (only for function segments). When + using :ref:`local themes ` values of these keys are + first searched in the segment description, then in ``segment_data`` key of + a local theme, then in ``segment_data`` key of a :ref:`default theme + `. + ``segments`` A dict with a ``left`` and a ``right`` list, consisting of segment dicts. Each segment has the following options: @@ -257,9 +276,13 @@ Themes available in the colorscheme is used. ``before`` + .. _config-themes-seg-before: + A string which will be prepended to the segment contents. ``after`` + .. _config-themes-seg-after: + A string which will be appended to the segment contents. ``contents`` @@ -268,6 +291,8 @@ Themes Segment contents, only required for ``string`` segments. ``args`` + .. _config-themes-seg-args: + A dict of arguments to be passed to a ``function`` segment. ``align`` diff --git a/powerline/config_files/themes/vim/default.json b/powerline/config_files/themes/vim/default.json index afbd40b9..543d717e 100644 --- a/powerline/config_files/themes/vim/default.json +++ b/powerline/config_files/themes/vim/default.json @@ -1,4 +1,19 @@ { + "segment_data": { + "branch": { + "before": " " + }, + "modified_indicator": { + "args": { "text": "+" } + }, + "line_percent": { + "args": { "gradient": true }, + "after": "%" + }, + "line_current_symbol": { + "contents": " " + } + }, "segments": { "left": [ { @@ -14,7 +29,6 @@ "name": "branch", "exclude_modes": ["nc"], "priority": 60, - "before": " ", "divider_highlight_group": "branch:divider" }, { @@ -38,7 +52,6 @@ }, { "name": "modified_indicator", - "args": { "text": "+" }, "before": " " }, { @@ -70,15 +83,13 @@ }, { "name": "line_percent", - "args": { "gradient": true }, "priority": 30, - "after": "%", "width": 4, "align": "r" }, { "type": "string", - "contents": " ", + "name": "line_current_symbol", "highlight_group": ["line_current_symbol", "line_current"] }, { diff --git a/powerline/config_files/themes/vim/help.json b/powerline/config_files/themes/vim/help.json index 83961cba..9fb5320c 100644 --- a/powerline/config_files/themes/vim/help.json +++ b/powerline/config_files/themes/vim/help.json @@ -15,15 +15,13 @@ "right": [ { "name": "line_percent", - "args": { "gradient": true }, "priority": 30, - "after": "%", "width": 4, "align": "r" }, { "type": "string", - "contents": " ", + "name": "line_current_symbol", "highlight_group": ["line_current_symbol", "line_current"] }, { diff --git a/powerline/renderer.py b/powerline/renderer.py index 17b7a738..684b702e 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -7,6 +7,7 @@ from powerline.theme import Theme class Renderer(object): def __init__(self, theme_config, local_themes, theme_kwargs, **options): self.__dict__.update(options) + self.theme_config = theme_config self.theme = Theme(theme_config=theme_config, **theme_kwargs) self.local_themes = local_themes self.theme_kwargs = theme_kwargs @@ -21,7 +22,7 @@ class Renderer(object): if matcher(matcher_info): match = self.local_themes[matcher] if 'config' in match: - match['theme'] = Theme(theme_config=match.pop('config'), **self.theme_kwargs) + match['theme'] = Theme(theme_config=match.pop('config'), top_theme_config=self.theme_config, **self.theme_kwargs) return match['theme'] else: return self.theme diff --git a/powerline/segment.py b/powerline/segment.py index 999195e1..d8fd8170 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -4,18 +4,34 @@ from importlib import import_module import sys +def get_segment_key(segment, theme_configs, key, module=None, default=None): + try: + return segment[key] + except KeyError: + if 'name' in segment: + name = segment['name'] + for theme_config in theme_configs: + if 'segment_data' in theme_config: + for segment_key in ((module+'.'+name, name) if module else (name,)): + try: + return theme_config['segment_data'][segment_key][key] + except KeyError: + pass + return default + + def get_function(data, segment): oldpath = sys.path sys.path = data['path'] + sys.path segment_module = str(segment.get('module', data['default_module'])) try: - return None, getattr(import_module(segment_module), segment['name']), '{0}.{1}'.format(segment_module, segment['name']) + return None, getattr(import_module(segment_module), segment['name']), segment_module finally: sys.path = oldpath def get_string(data, segment): - return segment.get('contents'), None, None + return data['get_key'](segment, None, 'contents'), None, None def get_filler(data, segment): @@ -29,11 +45,14 @@ segment_getters = { } -def gen_segment_getter(ext, path, default_module=None): +def gen_segment_getter(ext, path, theme_configs, default_module=None): data = { - "default_module": default_module or 'powerline.segments.'+ext, - "path": path + 'default_module': default_module or 'powerline.segments.'+ext, + 'path': path, } + def get_key(segment, module, key, default=None): + return get_segment_key(segment, theme_configs, key, module, default) + data['get_key'] = get_key def get(segment, side): segment_type = segment.get('type', 'function') @@ -41,19 +60,18 @@ def gen_segment_getter(ext, path, default_module=None): get_segment_info = segment_getters[segment_type] except KeyError: raise TypeError('Unknown segment type: {0}'.format(segment_type)) - contents, contents_func, key = get_segment_info(data, segment) + contents, contents_func, module = get_segment_info(data, segment) highlight_group = segment.get('highlight_group', segment.get('name')) divider_highlight_group = segment.get('divider_highlight_group') return { - 'key': key, 'type': segment_type, 'highlight_group': highlight_group, 'divider_highlight_group': divider_highlight_group, - 'before': segment.get('before', ''), - 'after': segment.get('after', ''), + 'before': get_key(segment, module, 'before', ''), + 'after': get_key(segment, module, 'after', ''), 'contents_func': contents_func, 'contents': contents, - 'args': segment.get('args', {}), + 'args': get_key(segment, module, 'args', {}) if segment_type == 'function' else {}, 'priority': segment.get('priority', -1), 'draw_divider': segment.get('draw_divider', True), 'side': side, diff --git a/powerline/theme.py b/powerline/theme.py index d6d98fe6..db503866 100644 --- a/powerline/theme.py +++ b/powerline/theme.py @@ -18,7 +18,7 @@ def requires_segment_info(func): class Theme(object): - def __init__(self, ext, colorscheme, theme_config, common_config, segment_info=None): + def __init__(self, ext, colorscheme, theme_config, common_config, top_theme_config=None, segment_info=None): self.colorscheme = colorscheme self.dividers = theme_config.get('dividers', common_config['dividers']) self.spaces = theme_config.get('spaces', common_config['spaces']) @@ -31,7 +31,10 @@ class Theme(object): 'highlight': defaultdict(lambda: {'fg': False, 'bg': False, 'attr': 0}) } self.segment_info = segment_info - get_segment = gen_segment_getter(ext, common_config['paths'], theme_config.get('default_module')) + theme_configs = [theme_config] + if top_theme_config: + theme_configs.append(top_theme_config) + get_segment = gen_segment_getter(ext, common_config['paths'], theme_configs, theme_config.get('default_module')) for side in ['left', 'right']: self.segments[side].extend((get_segment(segment, side) for segment in theme_config['segments'].get(side, [])))