From 40973ea5305172dc90a71bf7f5103d32c615a797 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 12 Apr 2013 23:45:42 +0400 Subject: [PATCH 01/19] Alter indentation --- powerline/segment.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/powerline/segment.py b/powerline/segment.py index 8a2483ff..d91ac028 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -39,17 +39,17 @@ def get_filler(data, segment): segment_getters = { - "function": get_function, - "string": get_string, - "filler": get_filler, - } + "function": get_function, + "string": get_string, + "filler": get_filler, +} 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) @@ -89,6 +89,6 @@ def gen_segment_getter(ext, path, theme_configs, default_module=None): '_len': 0, '_space_left': 0, '_space_right': 0, - } + } return get From 3ce068db9470e007825f63ea27f70a12b41cba13 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 10 Apr 2013 20:18:03 +0400 Subject: [PATCH 02/19] Make vim and ipython ext configurations optional --- powerline/lint/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index e5733a67..d151bbd3 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -427,7 +427,7 @@ main_spec = (Spec( theme=theme_spec(), local_themes=Spec() .unknown_spec(lambda *args: check_matcher_func('vim', *args), theme_spec()) - ), + ).optional(), ipython=Spec( colorscheme=colorscheme_spec(), theme=theme_spec(), @@ -436,7 +436,7 @@ main_spec = (Spec( out=theme_spec(), rewrite=theme_spec(), ), - ), + ).optional(), ).unknown_spec(check_ext, Spec( colorscheme=colorscheme_spec(), From ac88a0943613aa9afc61fd0f6acc5ddd87918f6a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 7 Apr 2013 14:03:45 +0400 Subject: [PATCH 03/19] Add renderer docstrings. --- powerline/renderer.py | 129 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 9 deletions(-) diff --git a/powerline/renderer.py b/powerline/renderer.py index 206be29e..26b18f75 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -19,11 +19,51 @@ def construct_returned_value(rendered_highlighted, segments, output_raw): class Renderer(object): + '''Object that is responsible for generating the highlighted string. + + :param dict theme_config: + Main theme configuration. + :param local_themes: + Local themes. Is to be used by subclasses from ``.get_theme()`` method, + base class only records this parameter to a ``.local_themes`` attribute. + :param dict theme_kwargs: + Keyword arguments for ``Theme`` class constructor. + :param Colorscheme colorscheme: + Colorscheme object that holds colors configuration. + :param PowerlineState pl: + Object used for logging. + :param int ambiwidth: + Width of the characters with east asian width unicode attribute equal to + ``A`` (Ambigious). + :param dict options: + Various options. Are normally not used by base renderer, but all options + are recorded as attributes. + ''' + segment_info = { 'environ': os.environ, 'getcwd': getattr(os, 'getcwdu', os.getcwd), 'home': os.environ.get('HOME'), } + '''Basic segment info. Is merged with local segment information by + ``.get_segment_info()`` method. Keys: + + ``environ`` + Object containing environment variables. Must define at least the + following methods: ``.__getitem__(var)`` that raises ``KeyError`` in + case requested environment variable is not present, ``.get(var, + default=None)`` that works like ``dict.get`` and be able to be passed to + ``Popen``. + + ``getcwd`` + Function that returns current working directory. Will be called without + any arguments, should return ``unicode`` or (in python-2) regular + string. + + ``home`` + String containing path to home directory. Should be ``unicode`` or (in + python-2) regular string or ``None``. + ''' def __init__(self, theme_config, @@ -31,6 +71,7 @@ class Renderer(object): theme_kwargs, colorscheme, pl, + ambiwidth=1, **options): self.__dict__.update(options) self.theme_config = theme_config @@ -41,24 +82,48 @@ class Renderer(object): self.theme_kwargs = theme_kwargs self.colorscheme = colorscheme self.width_data = { - 'N': 1, # Neutral - 'Na': 1, # Narrow - 'A': getattr(self, 'ambiwidth', 1), # Ambigious - 'H': 1, # Half-width - 'W': 2, # Wide - 'F': 2, # Fullwidth - } + 'N': 1, # Neutral + 'Na': 1, # Narrow + 'A': ambiwidth, # Ambigious + 'H': 1, # Half-width + 'W': 2, # Wide + 'F': 2, # Fullwidth + } def strwidth(self, string): + '''Function that returns string width. + + Is used to calculate the place given string occupies when handling + ``width`` argument to ``.render()`` method. Must take east asian width + into account. + + :param unicode string: + String whose width will be calculated. + + :return: unsigned integer. + ''' return sum((0 if combining(symbol) else self.width_data[east_asian_width(symbol)] for symbol in string)) def get_theme(self, matcher_info): + '''Get Theme object. + + Is to be overridden by subclasses to support local themes, this variant + only returns ``.theme`` attribute. + + :param matcher_info: + Parameter ``matcher_info`` that ``.render()`` method received. + Unused. + ''' return self.theme def shutdown(self): + '''Prepare for interpreter shutdown. The only job it is supposed to do + is calling ``.shutdown()`` method for all theme objects. Should be + overridden by subclasses in case they support local themes. + ''' self.theme.shutdown() - def get_highlighting(self, segment, mode): + def _get_highlighting(self, segment, mode): segment['highlight'] = self.colorscheme.get_highlighting(segment['highlight_group'], mode, segment.get('gradient_level')) if segment['divider_highlight_group']: segment['divider_highlight'] = self.colorscheme.get_highlighting(segment['divider_highlight_group'], mode) @@ -67,6 +132,21 @@ class Renderer(object): return segment def get_segment_info(self, segment_info): + '''Get segment information. + + Must return a dictionary containing at least ``home``, ``environ`` and + ``getcwd`` keys (see documentation for ``segment_info`` attribute). This + implementation merges ``segment_info`` dictionary passed to + ``.render()`` method with ``.segment_info`` attribute, preferring keys + from the former. It also replaces ``getcwd`` key with function returning + ``segment_info['environ']['PWD']`` in case ``PWD`` variable is + available. + + :param dict segment_info: + Segment information that was passed to ``.render()`` method. + + :return: dict with segment information. + ''' r = self.segment_info.copy() if segment_info: r.update(segment_info) @@ -82,12 +162,30 @@ class Renderer(object): with a negative priority are left. If one or more filler segments are provided they will fill the remaining space until the desired width is reached. + + :param str mode: + Mode string. Affects contents (colors and the set of segments) of + rendered string. + :param int width: + Maximum width text can occupy. May be exceeded if there are too much + non-removable segments. + :param str side: + One of ``left``, ``right``. Determines which side will be rendered. + If not present all sides are rendered. + :param bool output_raw: + Changes the output: if this parameter is ``True`` then in place of + one string this method outputs a pair ``(colored_string, + colorless_string)``. + :param dict segment_info: + Segment information. See also ``.get_segment_info()`` method. + :param matcher_info: + Matcher information. Is processed in ``.get_theme()`` method. ''' theme = self.get_theme(matcher_info) segments = theme.get_segments(side, self.get_segment_info(segment_info)) # Handle excluded/included segments for the current mode - segments = [self.get_highlighting(segment, mode) for segment in segments + segments = [self._get_highlighting(segment, mode) for segment in segments if mode not in segment['exclude_modes'] or (segment['include_modes'] and segment in segment['include_modes'])] segments = [segment for segment in self._render_segments(theme, segments)] @@ -199,10 +297,23 @@ class Renderer(object): @staticmethod def escape(string): + '''Method that escapes segment contents. + ''' return string def hlstyle(fg=None, bg=None, attr=None): + '''Output highlight style string. + + Assuming highlighted string looks like ``{style}{contents}`` this method + should output ``{style}``. If it is called without arguments this method + is supposed to reset style to its default. + ''' raise NotImplementedError def hl(self, contents, fg=None, bg=None, attr=None): + '''Output highlighted chunk. + + This implementation just outputs ``.hlstyle()`` joined with + ``contents``. + ''' return self.hlstyle(fg, bg, attr) + (contents or '') From 9250d794d7bd59952ac4b182959a098b1a9e9d4d Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 7 Apr 2013 14:32:20 +0400 Subject: [PATCH 04/19] Remove `pl` argument and first argument to `render*` from docs --- docs/source/powerline_autodoc.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/powerline_autodoc.py b/docs/source/powerline_autodoc.py index 38f0a4cb..613f9a85 100644 --- a/docs/source/powerline_autodoc.py +++ b/docs/source/powerline_autodoc.py @@ -44,7 +44,8 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter): if (arg == 'self' or (arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or - (method == 'render_one' and -i == len(argspec.args)) or + (arg == 'pl') or + (method.startswith('render') and 1-i == len(argspec.args)) or arg in args): continue if argspec.defaults and len(argspec.defaults) >= -i: @@ -64,7 +65,8 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter): args = [] defaults = [] for i, arg in zip(count(-1, -1), reversed(argspec.args)): - if (arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)): + if ((arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or + arg == 'pl'): continue if argspec.defaults and len(argspec.defaults) >= -i: default = argspec.defaults[i] From 587789ebda7be5fb09b798ac016d9f444ca0331a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 7 Apr 2013 19:09:03 +0400 Subject: [PATCH 05/19] =?UTF-8?q?Fix=20documentation=20for=20ThreadedSegme?= =?UTF-8?q?nt=20classes=20with=20@staticmethod=E2=80=99s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/powerline_autodoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/powerline_autodoc.py b/docs/source/powerline_autodoc.py index 613f9a85..87412cfa 100644 --- a/docs/source/powerline_autodoc.py +++ b/docs/source/powerline_autodoc.py @@ -45,7 +45,7 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter): (arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or (arg == 'pl') or - (method.startswith('render') and 1-i == len(argspec.args)) or + (method.startswith('render') and (1 if argspec.args[0] == 'self' else 0) - i == len(argspec.args)) or arg in args): continue if argspec.defaults and len(argspec.defaults) >= -i: From 49618fc4e34e303a3980bb4c111896a3bc7c07b1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 8 Apr 2013 22:59:14 +0400 Subject: [PATCH 06/19] Rename PowerlineState to PowerlineLogger --- powerline/__init__.py | 4 ++-- powerline/renderer.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/powerline/__init__.py b/powerline/__init__.py index ebc50ac7..fdbc33f3 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -23,7 +23,7 @@ def find_config_file(search_paths, config_file): raise IOError('Config file not found in search path: {0}'.format(config_file)) -class PowerlineState(object): +class PowerlineLogger(object): def __init__(self, use_daemon_threads, logger, ext): self.logger = logger self.ext = ext @@ -175,7 +175,7 @@ class Powerline(object): self.logger.addHandler(handler) if not self.pl: - self.pl = PowerlineState(self.use_daemon_threads, self.logger, self.ext) + self.pl = PowerlineLogger(self.use_daemon_threads, self.logger, self.ext) if not self.config_loader.pl: self.config_loader.pl = self.pl diff --git a/powerline/renderer.py b/powerline/renderer.py index 26b18f75..81ae00ab 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -30,7 +30,7 @@ class Renderer(object): Keyword arguments for ``Theme`` class constructor. :param Colorscheme colorscheme: Colorscheme object that holds colors configuration. - :param PowerlineState pl: + :param PowerlineLogger pl: Object used for logging. :param int ambiwidth: Width of the characters with east asian width unicode attribute equal to From a8eb0a247168c00517dbaccde11656f8a6292489 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 9 Apr 2013 08:18:37 +0400 Subject: [PATCH 07/19] Special-case None priority in place of -1 This extends priorities in both directions, uses slightly faster `is None` check, makes it consistent with `interval` special-casing also to `None` and makes lint able to use one simple `.type()` check in place of `.either()` one. --- docs/source/configuration.rst | 11 +++++------ powerline/lint/__init__.py | 2 +- powerline/renderer.py | 2 +- powerline/segment.py | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 949c77c8..40adca33 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -377,14 +377,13 @@ Themes can be aligned with the ``align`` property. ``priority`` - Optional segment priority. Segments with priority ``-1`` (the - default priority) will always be included, regardless of the width - of the prompt/statusline. + Optional segment priority. Segments with priority ``None`` (the default + priority, represented by ``null`` in json) will always be included, + regardless of the width of the prompt/statusline. - If the priority is ``0`` or more, the segment may be removed if the + If the priority is any number, the segment may be removed if the prompt/statusline width is too small for all the segments to be - rendered. A lower number means that the segment has a higher - priority. + rendered. A lower number means that the segment has a higher priority. Segments are removed according to their priority, with low priority segments being removed first. diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index d151bbd3..85695caf 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -818,7 +818,7 @@ segments_spec = Spec().optional().list( draw_soft_divider=Spec().type(bool).optional(), draw_inner_divider=Spec().type(bool).optional(), module=segment_module_spec(), - priority=Spec().either(Spec().cmp('eq', -1), Spec().cmp('ge', 0.0)).optional(), + priority=Spec().type(int, float, type(None)).optional(), after=Spec().type(unicode).optional(), before=Spec().type(unicode).optional(), width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(), diff --git a/powerline/renderer.py b/powerline/renderer.py index 81ae00ab..948d553c 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -195,7 +195,7 @@ class Renderer(object): return construct_returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw) # Create an ordered list of segments that can be dropped - segments_priority = [segment for segment in sorted(segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] > 0] + segments_priority = [segment for segment in sorted(segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] is not None] while sum([segment['_len'] for segment in segments]) > width and len(segments_priority): segments.remove(segments_priority[0]) segments_priority.pop(0) diff --git a/powerline/segment.py b/powerline/segment.py index d91ac028..9632206a 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -73,7 +73,7 @@ def gen_segment_getter(ext, path, theme_configs, default_module=None): 'contents_func': contents_func, 'contents': contents, 'args': get_key(segment, module, 'args', {}) if segment_type == 'function' else {}, - 'priority': segment.get('priority', -1), + 'priority': segment.get('priority', None), 'draw_hard_divider': segment.get('draw_hard_divider', True), 'draw_soft_divider': segment.get('draw_soft_divider', True), 'draw_inner_divider': segment.get('draw_inner_divider', False), From c7946cda3e3f3156aefd1e9f3a5c6bb6db7fbdb0 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 9 Apr 2013 08:38:04 +0400 Subject: [PATCH 08/19] Use different default for functions This makes it look up `powerline.segments.vim.virtualenv` in addition to virtualenv in colorscheme like it does with `segment_data`. --- powerline/segment.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/powerline/segment.py b/powerline/segment.py index 9632206a..497242e2 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -61,8 +61,18 @@ def gen_segment_getter(ext, path, theme_configs, default_module=None): get_segment_info = segment_getters[segment_type] except KeyError: raise TypeError('Unknown segment type: {0}'.format(segment_type)) - contents, contents_func, module = get_segment_info(data, segment) - highlight_group = segment_type != 'function' and segment.get('highlight_group') or segment.get('name') + + try: + contents, contents_func, module = get_segment_info(data, segment) + except Exception as e: + pl.exception('Failed to generate segment from {0!r}: {1}', segment, str(e), prefix='segment_generator') + return None + + if segment_type == 'function': + highlight_group = [module + '.' + segment['name'], segment['name']] + else: + highlight_group = segment.get('highlight_group') or segment.get('name') + return { 'name': segment.get('name'), 'type': segment_type, From 4dd9c5196e1f4898cd706e2219e3a9fa7eef6af9 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 12 Apr 2013 23:38:44 +0400 Subject: [PATCH 09/19] Respect segment.py highlight group handling in powerline-lint Either `highlight_group` or `name` key is enough to determine highlight group for non-function segments, but powerline-lint requires `highlight_group`. --- powerline/lint/__init__.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index 85695caf..6f0183fe 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -527,10 +527,11 @@ type_keys = { } required_keys = { 'function': set(), - 'string': set(('contents', 'highlight_group')), - 'filler': set(('highlight_group',)), + 'string': set(('contents',)), + 'filler': set(), } function_keys = set(('args', 'module')) +highlight_keys = set(('highlight_group', 'name')) def check_key_compatibility(segment, data, context, echoerr): @@ -542,6 +543,8 @@ def check_key_compatibility(segment, data, context, echoerr): problem_mark=segment_type.mark) return False, False, True + hadproblem = False + keys = set(segment) if not ((keys - generic_keys) < type_keys[segment_type]): unknown_keys = keys - generic_keys - type_keys[segment_type] @@ -550,7 +553,7 @@ def check_key_compatibility(segment, data, context, echoerr): problem='found keys not used with the current segment type: {0}'.format( ', '.join((unicode(key) for key in unknown_keys))), problem_mark=list(unknown_keys)[0].mark) - return True, False, True + hadproblem = True if not (keys > required_keys[segment_type]): missing_keys = required_keys[segment_type] - keys @@ -558,9 +561,15 @@ def check_key_compatibility(segment, data, context, echoerr): context_mark=context[-1][1].mark, problem='found missing required keys: {0}'.format( ', '.join((unicode(key) for key in missing_keys)))) - return True, False, True + hadproblem = True - return True, False, False + if not (segment_type == 'function' or (keys & highlight_keys)): + echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), + context_mark=context[-1][1].mark, + problem='found missing keys required to determine highlight group. Either highlight_group or name key must be present') + hadproblem = True + + return True, False, hadproblem def check_segment_module(module, data, context, echoerr): From 7e57010c1952e66e56bd6782b33baffd281091e2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 00:09:00 +0400 Subject: [PATCH 10/19] Move some code from powerline_autodoc to powerline.lib.inspect To make it available later in lint checker. --- docs/source/powerline_autodoc.py | 60 +++----------------------------- powerline/lint/inspect.py | 59 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 55 deletions(-) create mode 100644 powerline/lint/inspect.py diff --git a/docs/source/powerline_autodoc.py b/docs/source/powerline_autodoc.py index 87412cfa..4806c3cf 100644 --- a/docs/source/powerline_autodoc.py +++ b/docs/source/powerline_autodoc.py @@ -1,8 +1,8 @@ +# vim:fileencoding=utf-8:noet from sphinx.ext import autodoc -from sphinx.util.inspect import getargspec -from inspect import ArgSpec, formatargspec -from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment -from itertools import count +from inspect import formatargspec +from powerline.lint.inspect import getconfigargspec +from powerline.lib.threaded import ThreadedSegment try: from __builtin__ import unicode @@ -25,57 +25,7 @@ class ThreadedDocumenter(autodoc.FunctionDocumenter): super(ThreadedDocumenter, cls).can_document_member(member, membername, isattr, parent)) def format_args(self): - if isinstance(self.object, ThreadedSegment): - args = ['interval'] - defaults = [getattr(self.object, 'interval', 1)] - if self.object.update_first: - args.append('update_first') - defaults.append(True) - methods = ['render', 'set_state'] - if isinstance(self.object, KwThreadedSegment): - methods += ['key', 'render_one'] - - for method in methods: - if hasattr(self.object, method): - # Note: on = -i: - default = argspec.defaults[i] - defaults.append(default) - args.append(arg) - else: - args.insert(0, arg) - argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults)) - else: - if hasattr(self.object, 'powerline_origin'): - obj = self.object.powerline_origin - else: - obj = self.object - - argspec = getargspec(obj) - args = [] - defaults = [] - for i, arg in zip(count(-1, -1), reversed(argspec.args)): - if ((arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or - arg == 'pl'): - continue - if argspec.defaults and len(argspec.defaults) >= -i: - default = argspec.defaults[i] - defaults.append(default) - args.append(arg) - else: - args.insert(0, arg) - argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults)) - + argspec = getconfigargspec(self.object) return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\') diff --git a/powerline/lint/inspect.py b/powerline/lint/inspect.py new file mode 100644 index 00000000..6c2c0fab --- /dev/null +++ b/powerline/lint/inspect.py @@ -0,0 +1,59 @@ +# vim:fileencoding=utf-8:noet +from __future__ import absolute_import +from inspect import ArgSpec, getargspec +from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment +from itertools import count + +def getconfigargspec(obj): + if isinstance(obj, ThreadedSegment): + args = ['interval'] + defaults = [getattr(obj, 'interval', 1)] + if obj.update_first: + args.append('update_first') + defaults.append(True) + methods = ['render', 'set_state'] + if isinstance(obj, KwThreadedSegment): + methods += ['key', 'render_one'] + + for method in methods: + if hasattr(obj, method): + # Note: on = -i: + default = argspec.defaults[i] + defaults.append(default) + args.append(arg) + else: + args.insert(0, arg) + argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults)) + else: + if hasattr(obj, 'powerline_origin'): + obj = obj.powerline_origin + else: + obj = obj + + argspec = getargspec(obj) + args = [] + defaults = [] + for i, arg in zip(count(-1, -1), reversed(argspec.args)): + if ((arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None)) or + arg == 'pl'): + continue + if argspec.defaults and len(argspec.defaults) >= -i: + default = argspec.defaults[i] + defaults.append(default) + args.append(arg) + else: + args.insert(0, arg) + argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults)) + + return argspec From fee328666ff613ef10a3ec8896babeef2d59e04a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 14:20:54 +0400 Subject: [PATCH 11/19] Improve arguments checks --- powerline/lint/__init__.py | 201 +++++++++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 42 deletions(-) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index 6f0183fe..d8609ba1 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -3,6 +3,9 @@ from powerline import find_config_file, Powerline from powerline.lib.config import load_json_config from powerline.lint.markedjson.error import echoerr, MarkedError from powerline.segments.vim import vim_modes +from powerline.lint.inspect import getconfigargspec +from powerline.lint.markedjson.markedvalue import gen_marked_value +from powerline.lib.threaded import ThreadedSegment import itertools import sys import os @@ -25,8 +28,33 @@ def open_file(path): EMPTYTUPLE = tuple() +class JStr(unicode): + def join(self, iterable): + return super(JStr, self).join((unicode(item) for item in iterable)) + + +key_sep = JStr('/') +list_sep = JStr(', ') + + def context_key(context): - return '/'.join((unicode(c[0]) for c in context)) + return key_sep.join((c[0] for c in context)) + + +class DelayedEchoErr(object): + def __init__(self, echoerr): + self.echoerr = echoerr + self.errs = [] + + def __call__(self, *args, **kwargs): + self.errs.append((args, kwargs)) + + def echo_all(self): + for args, kwargs in self.errs: + self.echoerr(*args, **kwargs) + + def __nonzero__(self): + return not not self.errs class Spec(object): @@ -80,7 +108,7 @@ class Spec(object): context_mark=context_mark, problem='{0!r} must be a {1} instance, not {2}'.format( value, - ', '.join((t.__name__ for t in types)), + list_sep.join((t.__name__ for t in types)), type(value.value).__name__ ), problem_mark=value.mark) @@ -118,10 +146,7 @@ class Spec(object): return True, hadproblem def check_either(self, value, context_mark, data, context, echoerr, start, end): - errs = [] - - def new_echoerr(*args, **kwargs): - errs.append((args, kwargs)) + new_echoerr = DelayedEchoErr(echoerr) hadproblem = False for spec in self.specs[start:end]: @@ -131,8 +156,7 @@ class Spec(object): if not hadproblem: return True, False - for args, kwargs in errs: - echoerr(*args, **kwargs) + new_echoerr.echo_all() return False, hadproblem @@ -392,6 +416,7 @@ def check_config(d, theme, data, context, echoerr): return True, False, True return True, False, False + divider_spec = Spec().type(unicode).len('le', 3, lambda value: 'Divider {0!r} is too large!'.format(value)).copy divside_spec = Spec( @@ -551,7 +576,7 @@ def check_key_compatibility(segment, data, context, echoerr): echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), context_mark=context[-1][1].mark, problem='found keys not used with the current segment type: {0}'.format( - ', '.join((unicode(key) for key in unknown_keys))), + list_sep.join(unknown_keys)), problem_mark=list(unknown_keys)[0].mark) hadproblem = True @@ -560,7 +585,7 @@ def check_key_compatibility(segment, data, context, echoerr): echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), context_mark=context[-1][1].mark, problem='found missing required keys: {0}'.format( - ', '.join((unicode(key) for key in missing_keys)))) + list_sep.join(missing_keys))) hadproblem = True if not (segment_type == 'function' or (keys & highlight_keys)): @@ -619,28 +644,39 @@ def check_full_segment_data(segment, data, context, echoerr): return check_key_compatibility(segment_copy, data, context, echoerr) +def import_segment(name, data, context, echoerr, module=None): + if not module: + module = context[-2][1].get('module', context[0][1].get('default_module', 'powerline.segments.' + data['ext'])) + + with WithPath(data['import_paths']): + try: + func = getattr(__import__(unicode(module), fromlist=[unicode(name)]), unicode(name)) + except ImportError: + echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), + problem='failed to import module {0}'.format(module), + problem_mark=module.mark) + return None + except AttributeError: + echoerr(context='Error while loading segment function (key {key})'.format(key=context_key(context)), + problem='failed to load function {0} from module {1}'.format(name, module), + problem_mark=name.mark) + return None + + if not callable(func): + echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), + problem='imported "function" {0} from module {1} is not callable'.format(name, module), + problem_mark=module.mark) + return None + + return func + + def check_segment_name(name, data, context, echoerr): ext = data['ext'] if context[-2][1].get('type', 'function') == 'function': - module = context[-2][1].get('module', context[0][1].get('default_module', 'powerline.segments.' + ext)) - with WithPath(data['import_paths']): - try: - func = getattr(__import__(unicode(module), fromlist=[unicode(name)]), unicode(name)) - except ImportError: - echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), - problem='failed to import module {0}'.format(module), - problem_mark=module.mark) - return True, False, True - except AttributeError: - echoerr(context='Error while loading segment function (key {key})'.format(key=context_key(context)), - problem='failed to load function {0} from module {1}'.format(name, module), - problem_mark=name.mark) - return True, False, True + func = import_segment(name, data, context, echoerr) - if not callable(func): - echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), - problem='imported "function" {0} from module {1} is not callable'.format(name, module), - problem_mark=module.mark) + if not func: return True, False, True hl_groups = [] @@ -662,32 +698,32 @@ def check_segment_name(name, data, context, echoerr): if r: echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight group {0} not defined in the following colorschemes: {1}\n(Group name was obtained from function documentation.)'.format( - divider_hl_group, ', '.join(r)), + divider_hl_group, list_sep.join(r)), problem_mark=name.mark) hadproblem = True if hl_groups: greg = re.compile(r'``([^`]+)``( \(gradient\))?') - hl_groups = [[greg.match(subs).groups() for subs in s.split(' or ')] for s in (', '.join(hl_groups)).split(', ')] + hl_groups = [[greg.match(subs).groups() for subs in s.split(' or ')] for s in (list_sep.join(hl_groups)).split(', ')] for required_pack in hl_groups: rs = [hl_exists(hl_group, data, context, echoerr, allow_gradients=('force' if gradient else False)) for hl_group, gradient in required_pack] if all(rs): echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight groups list ({0}) with all groups not defined in some colorschemes\n(Group names were taken from function documentation.)'.format( - ', '.join((unicode(h[0]) for h in required_pack))), + list_sep.join((h[0] for h in required_pack))), problem_mark=name.mark) for r, h in zip(rs, required_pack): echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( - h[0], ', '.join(r))) + h[0], list_sep.join(r))) hadproblem = True else: r = hl_exists(name, data, context, echoerr, allow_gradients=True) if r: echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight group {0} not defined in the following colorschemes: {1}\n(If not specified otherwise in documentation, highlight group for function segments\nis the same as the function name.)'.format( - name, ', '.join(r)), + name, list_sep.join(r)), problem_mark=name.mark) hadproblem = True @@ -753,7 +789,7 @@ def check_highlight_group(hl_group, data, context, echoerr): if r: echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( - hl_group, ', '.join(r)), + hl_group, list_sep.join(r)), problem_mark=hl_group.mark) return True, False, True return True, False, False @@ -764,12 +800,12 @@ def check_highlight_groups(hl_groups, data, context, echoerr): if all(rs): echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight groups list ({0}) with all groups not defined in some colorschemes'.format( - ', '.join((unicode(h) for h in hl_groups))), + list_sep.join((unicode(h) for h in hl_groups))), problem_mark=hl_groups.mark) for r, hl_group in zip(rs, hl_groups): echoerr(context='Error while checking theme (key {key})'.format(key=context_key(context)), problem='found highlight group {0} not defined in the following colorschemes: {1}'.format( - hl_group, ', '.join(r)), + hl_group, list_sep.join(r)), problem_mark=hl_group.mark) return True, False, True return True, False, False @@ -807,11 +843,92 @@ def check_segment_data_key(key, data, context, echoerr): return True, False, False -# FIXME More checks, limit existing to ThreadedSegment instances only +threaded_args_specs = { + 'interval': Spec().cmp('gt', 0.0), + 'update_first': Spec().type(bool), + 'shutdown_event': Spec().error('Shutdown event must be set by powerline'), +} + + +def check_args_variant(segment, args, data, context, echoerr): + argspec = getconfigargspec(segment) + present_args = set(args) + all_args = set(argspec.args) + required_args = set(argspec.args[:-len(argspec.defaults)]) + + hadproblem = False + + if required_args - present_args: + echoerr(context='Error while checking segment arguments (key {key})'.format(key=context_key(context)), + context_mark=args.mark, + problem='some of the required keys are missing: {0}'.format(list_sep.join(required_args - present_args))) + hadproblem = True + + if not all_args >= present_args: + echoerr(context='Error while checking segment arguments (key {key})'.format(key=context_key(context)), + context_mark=args.mark, + problem='found unknown keys: {0}'.format(list_sep.join(present_args - all_args)), + problem_mark=next(iter(present_args - all_args)).mark) + hadproblem = True + + if isinstance(segment, ThreadedSegment): + for key in set(threaded_args_specs) & present_args: + proceed, khadproblem = threaded_args_specs[key].match(args[key], args.mark, data, context + ((key, args[key]),), echoerr) + if khadproblem: + hadproblem = True + if not proceed: + return hadproblem + + return hadproblem + + +def check_args(get_segment_variants, args, data, context, echoerr): + new_echoerr = DelayedEchoErr(echoerr) + count = 0 + hadproblem = False + for segment in get_segment_variants(data, context, new_echoerr): + count += 1 + shadproblem = check_args_variant(segment, args, data, context, echoerr) + if shadproblem: + hadproblem = True + + if not count: + hadproblem = True + new_echoerr.echo_all() + echoerr(context='Error while checking segment arguments (key {key})'.format(key=context_key(context)), + context_mark=context[-2][1].mark, + problem='no suitable segments found') + + return True, False, hadproblem + + +def get_one_segment_variant(data, context, echoerr): + name = context[-2][1].get('name') + if name: + func = import_segment(name, data, context, echoerr) + if func: + yield func + + +def get_all_possible_segments(data, context, echoerr): + name = context[-2][0] + module, name = (gen_marked_value(value, name.mark) for value in name.rpartition('.')[::2]) + if module: + func = import_segment(name, data, context, echoerr, module=module) + if func: + yield func + else: + for theme_config in data['ext_theme_configs'].values(): + for segments in theme_config.get('segments', {}).values(): + for segment in segments: + if segment.get('type', 'function') == 'function': + module = segment.get('module', context[0][1].get('default_module', 'powerline.segments.' + data['ext'])) + func = import_segment(name, data, context, echoerr, module=module) + if func: + yield func + + args_spec = Spec( - interval=Spec().cmp('gt', 0.0).optional(), - update_first=Spec().type(bool).optional(), - shutdown_event=Spec().error('Shutdown event must be set by powerline').optional(), pl=Spec().error('pl object must be set by powerline').optional(), segment_info=Spec().error('Segment info dictionary must be set by powerline').optional(), ).unknown_spec(Spec(), Spec()).optional().copy @@ -832,7 +949,7 @@ segments_spec = Spec().optional().list( before=Spec().type(unicode).optional(), width=Spec().either(Spec().unsigned(), Spec().cmp('eq', 'auto')).optional(), align=Spec().oneof(set('lr')).optional(), - args=args_spec(), + args=args_spec().func(lambda *args, **kwargs: check_args(get_one_segment_variant, *args, **kwargs)), contents=Spec().type(unicode).optional(), highlight_group=Spec().list( highlight_group_spec().re('^(?:(?!:divider$).)+$', @@ -849,7 +966,7 @@ theme_spec = (Spec( Spec( after=Spec().type(unicode).optional(), before=Spec().type(unicode).optional(), - args=args_spec(), + args=args_spec().func(lambda *args, **kwargs: check_args(get_all_possible_segments, *args, **kwargs)), contents=Spec().type(unicode).optional(), ), ).optional().context_message('Error while loading segment data (key {key})'), From ae691b7cd858bebd4609ad78c5ceaecb2275516f Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 14:47:39 +0400 Subject: [PATCH 12/19] Improve shown errors --- powerline/lint/__init__.py | 12 +++-- powerline/lint/markedjson/error.py | 3 ++ powerline/lint/markedjson/markedvalue.py | 58 +++++++++++++++++++++++- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index d8609ba1..726f255d 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -894,10 +894,12 @@ def check_args(get_segment_variants, args, data, context, echoerr): if not count: hadproblem = True - new_echoerr.echo_all() - echoerr(context='Error while checking segment arguments (key {key})'.format(key=context_key(context)), - context_mark=context[-2][1].mark, - problem='no suitable segments found') + if new_echoerr: + new_echoerr.echo_all() + else: + echoerr(context='Error while checking segment arguments (key {key})'.format(key=context_key(context)), + context_mark=context[-2][1].mark, + problem='no suitable segments found') return True, False, hadproblem @@ -912,7 +914,7 @@ def get_one_segment_variant(data, context, echoerr): def get_all_possible_segments(data, context, echoerr): name = context[-2][0] - module, name = (gen_marked_value(value, name.mark) for value in name.rpartition('.')[::2]) + module, name = name.rpartition('.')[::2] if module: func = import_segment(name, data, context, echoerr, module=module) if func: diff --git a/powerline/lint/markedjson/error.py b/powerline/lint/markedjson/error.py index 66fcacef..d1466675 100644 --- a/powerline/lint/markedjson/error.py +++ b/powerline/lint/markedjson/error.py @@ -29,6 +29,9 @@ class Mark: self.buffer = buffer self.pointer = pointer + def copy(self): + return Mark(self.name, self.line, self.column, self.buffer, self.pointer) + def get_snippet(self, indent=4, max_length=75): if self.buffer is None: return None diff --git a/powerline/lint/markedjson/markedvalue.py b/powerline/lint/markedjson/markedvalue.py index db45fd13..6a304b9f 100644 --- a/powerline/lint/markedjson/markedvalue.py +++ b/powerline/lint/markedjson/markedvalue.py @@ -1,17 +1,71 @@ __all__ = ['gen_marked_value', 'MarkedValue'] +try: + from __builtin__ import unicode +except ImportError: + unicode = str + + +def gen_new(cls): + def __new__(arg_cls, value, mark): + r = super(arg_cls, arg_cls).__new__(arg_cls, value) + r.mark = mark + r.value = value + return r + return __new__ + + +class MarkedUnicode(unicode): + __new__ = gen_new(unicode) + + def _proc_partition(self, part_result): + pointdiff = 1 + r = [] + for s in part_result: + mark = self.mark.copy() + # XXX Does not work properly with escaped strings, but this requires + # saving much more information in mark. + mark.column += pointdiff + mark.pointer += pointdiff + r.append(MarkedUnicode(s, mark)) + pointdiff += len(s) + return tuple(r) + + def rpartition(self, sep): + return self._proc_partition(super(MarkedUnicode, self).rpartition(sep)) + + def partition(self, sep): + return self._proc_partition(super(MarkedUnicode, self).partition(sep)) + + +class MarkedInt(int): + __new__ = gen_new(int) + + +class MarkedFloat(float): + __new__ = gen_new(float) + + class MarkedValue: def __init__(self, value, mark): self.mark = mark self.value = value +specialclasses = { + unicode: MarkedUnicode, + int: MarkedInt, + float: MarkedFloat, +} + classcache = {} -def gen_marked_value(value, mark): - if value.__class__ in classcache: +def gen_marked_value(value, mark, use_special_classes=True): + if use_special_classes and value.__class__ in specialclasses: + Marked = specialclasses[value.__class__] + elif value.__class__ in classcache: Marked = classcache[value.__class__] else: class Marked(MarkedValue): From 5e93d20fb84313fbeffed48822bf63173c2556ca Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 15:05:39 +0400 Subject: [PATCH 13/19] Do not sort segments that are always included --- powerline/renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerline/renderer.py b/powerline/renderer.py index 948d553c..848db1ea 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -195,7 +195,7 @@ class Renderer(object): return construct_returned_value(''.join([segment['_rendered_hl'] for segment in segments]) + self.hlstyle(), segments, output_raw) # Create an ordered list of segments that can be dropped - segments_priority = [segment for segment in sorted(segments, key=lambda segment: segment['priority'], reverse=True) if segment['priority'] is not None] + 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): segments.remove(segments_priority[0]) segments_priority.pop(0) From 4449489e5944c1736adf07cf4dbf7dec37069549 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 15:08:27 +0400 Subject: [PATCH 14/19] Do not use second argument to itertools.count --- powerline/lint/inspect.py | 8 ++++---- powerline/segments/vim.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/powerline/lint/inspect.py b/powerline/lint/inspect.py index 6c2c0fab..58c83a2c 100644 --- a/powerline/lint/inspect.py +++ b/powerline/lint/inspect.py @@ -20,16 +20,16 @@ def getconfigargspec(obj): # Note: on = -i: - default = argspec.defaults[i] + if argspec.defaults and len(argspec.defaults) >= i: + default = argspec.defaults[-i] defaults.append(default) args.append(arg) else: diff --git a/powerline/segments/vim.py b/powerline/segments/vim.py index cb05b74d..a6fcc203 100644 --- a/powerline/segments/vim.py +++ b/powerline/segments/vim.py @@ -274,6 +274,7 @@ def col_current(pl, segment_info): return str(segment_info['window'].cursor[1] + 1) +# TODO Add &textwidth-based gradient @window_cached def virtcol_current(pl): '''Return current visual column with concealed characters ingored From 25627363b04d0493b10a349a7aba1c0b0c60ee59 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 15:16:45 +0400 Subject: [PATCH 15/19] Do not use second argument to itertools.count in other place --- powerline/lint/inspect.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/powerline/lint/inspect.py b/powerline/lint/inspect.py index 58c83a2c..b0f0c7af 100644 --- a/powerline/lint/inspect.py +++ b/powerline/lint/inspect.py @@ -44,12 +44,12 @@ def getconfigargspec(obj): argspec = getargspec(obj) args = [] defaults = [] - for i, arg in zip(count(-1, -1), reversed(argspec.args)): + for i, arg in zip(count(1), reversed(argspec.args)): if ((arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None)) or arg == 'pl'): continue - if argspec.defaults and len(argspec.defaults) >= -i: - default = argspec.defaults[i] + if argspec.defaults and len(argspec.defaults) >= i: + default = argspec.defaults[-i] defaults.append(default) args.append(arg) else: From a4c59ded76d80fd99ad66e864cd60212a2c02996 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 15:44:08 +0400 Subject: [PATCH 16/19] Make tests more verbose and catch first KeyboardInterrupt --- tests/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.sh b/tests/test.sh index a8439ac7..c65e6668 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -3,7 +3,7 @@ FAILED=0 export PYTHONPATH="${PYTHONPATH}:`realpath .`" for file in tests/test_*.py ; do - if ! ${PYTHON} $file ; then + if ! ${PYTHON} $file --verbose --catch ; then FAILED=1 fi done From b883ac6ee83a9e91032576f1a7c909dde83e3887 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 18:51:49 +0400 Subject: [PATCH 17/19] Use same modeline in scripts/* as in other files --- scripts/powerline | 2 +- scripts/powerline-lint | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/powerline b/scripts/powerline index 925ee438..8cb88935 100755 --- a/scripts/powerline +++ b/scripts/powerline @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- +# vim:fileencoding=utf-8:noet '''Powerline prompt and statusline script.''' import sys import os diff --git a/scripts/powerline-lint b/scripts/powerline-lint index 6d2df701..6d20e38f 100755 --- a/scripts/powerline-lint +++ b/scripts/powerline-lint @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- +# vim:fileencoding=utf-8:noet '''Powerline configuration checker.''' import argparse from powerline.lint import check From 2d036c0de8cb3846e3c740a224d324f328f12ee4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 13 Apr 2013 19:21:11 +0400 Subject: [PATCH 18/19] Fix indentation of dictionaries --- tests/vim.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/vim.py b/tests/vim.py index aaf5e534..89b3e4df 100644 --- a/tests/vim.py +++ b/tests/vim.py @@ -316,13 +316,13 @@ class _Buffer(object): self.name = os.path.abspath(name) if name else None _buf_scopes[bufnr] = {} _buf_options[bufnr] = { - 'modified': 0, - 'readonly': 0, - 'fileformat': 'unix', - 'filetype': '', - 'buftype': '', - 'fileencoding': 'utf-8', - } + 'modified': 0, + 'readonly': 0, + 'fileformat': 'unix', + 'filetype': '', + 'buftype': '', + 'fileencoding': 'utf-8', + } _buf_lines[bufnr] = [''] from copy import copy _undostate[bufnr] = [copy(_buf_lines[bufnr])] @@ -393,9 +393,9 @@ def _init(): @_vim def _get_segment_info(): mode_translations = { - chr(ord('V') - 0x40): '^V', - chr(ord('S') - 0x40): '^S', - } + chr(ord('V') - 0x40): '^V', + chr(ord('S') - 0x40): '^S', + } mode = _mode mode = mode_translations.get(mode, mode) return { From 2a6a4a07e6471b352785cdbcea80eae3043a96c2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 16 Apr 2013 07:58:24 +0400 Subject: [PATCH 19/19] Replace {path} with {repository_root} Closes #429 --- docs/source/overview.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/source/overview.rst b/docs/source/overview.rst index 19850793..1300ef12 100644 --- a/docs/source/overview.rst +++ b/docs/source/overview.rst @@ -91,12 +91,12 @@ Usage Vim statusline -------------- -Add the following line to your :file:`vimrc`, where ``{path}`` is the +Add the following line to your :file:`vimrc`, where ``{repository_root}`` is the absolute path to your Powerline installation directory: .. code-block:: vim - set rtp+={path}/powerline/bindings/vim + set rtp+={repository_root}/powerline/bindings/vim If you're using Vundle or Pathogen and don't want Powerline functionality in any other applications, simply add Powerline as a bundle and point the path @@ -115,22 +115,22 @@ Shell prompts Bash prompt ^^^^^^^^^^^ -Add the following line to your :file:`bashrc`, where ``{path}`` is the -absolute path to your Powerline installation directory: +Add the following line to your :file:`bashrc`, where ``{repository_root}`` is +the absolute path to your Powerline installation directory: .. code-block:: bash - . {path}/powerline/bindings/bash/powerline.sh + . {repository_root}/powerline/bindings/bash/powerline.sh Zsh prompt ^^^^^^^^^^ -Add the following line to your :file:`zshrc`, where ``{path}`` is the +Add the following line to your :file:`zshrc`, where ``{repository_root}`` is the absolute path to your Powerline installation directory: .. code-block:: bash - . {path}/powerline/bindings/zsh/powerline.zsh + . {repository_root}/powerline/bindings/zsh/powerline.zsh If you are not satisfied with powerline speed in this case, compile zpython branch from https://bitbucket.org/ZyX_I/zsh. @@ -138,10 +138,10 @@ branch from https://bitbucket.org/ZyX_I/zsh. Tmux statusline --------------- -Add the following line to your :file:`tmux.conf`, where ``{path}`` is the -absolute path to your Powerline installation directory:: +Add the following line to your :file:`tmux.conf`, where ``{repository_root}`` is +the absolute path to your Powerline installation directory:: - source '{path}/powerline/bindings/tmux/powerline.conf' + source '{repository_root}/powerline/bindings/tmux/powerline.conf' IPython prompt -------------- @@ -174,12 +174,12 @@ Awesome widget .. note:: The Powerline widget will spawn a shell script that runs in the background and updates the statusline with ``awesome-client``. -Add the following to your :file:`rc.lua`, where ``{path}`` is the absolute -path to your Powerline installation directory: +Add the following to your :file:`rc.lua`, where ``{repository_root}`` is the +absolute path to your Powerline installation directory: .. code-block:: lua - package.path = package.path .. ';{path}/powerline/bindings/awesome/?.lua' + package.path = package.path .. ';{repository_root}/powerline/bindings/awesome/?.lua' require('powerline') Then add the ``powerline_widget`` to your ``wibox``: