diff --git a/.local.vimrc b/.local.vimrc index ac676144..edf53ee8 100644 --- a/.local.vimrc +++ b/.local.vimrc @@ -4,5 +4,5 @@ " " [1]: http://www.vim.org/scripts/script.php?script_id=3393 " [2]: https://github.com/thinca/vim-localrc -let g:syntastic_python_flake8_args = '--ignore=W191,E501,E121,E122,E123,E128,E225,W291,E126' +let g:syntastic_python_flake8_args = '--ignore=W191,E501,E128,W291,E126,E101' let b:syntastic_checkers = ['flake8'] diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 96ebab7f..e31718f8 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -18,7 +18,7 @@ Getting started already exist. * Clearly describe the issue. - * If the issue is a bug: Make sure you include steps to reproduce, and + * If the issue is a bug: make sure you include steps to reproduce, and include the earliest revision that you know has the issue. * Fork the repository on GitHub. @@ -60,12 +60,13 @@ Programming style * The project uses *tabs for indentation* and *spaces for alignment*, this is also included in a vim modeline on top of every script file. -* Run your code through ``flake8 - --ignore=W191,E501,E121,E122,E123,E128,E225`` to fix any style errors. Use - common sense regarding whitespace warnings, not all ``flake8`` warnings - need to be fixed. +* Run your code through ``flake8 --ignore=W191,E501,E128,W291,E126,E101`` to fix + any style errors. Use common sense regarding whitespace warnings, not all + ``flake8`` warnings need to be fixed. * Trailing whitespace to indicate a continuing paragraph is OK in comments, documentation and commit messages. +* It is allowed to have too long lines. It is advised though to avoid lines + wider then a hundred of characters. Submitting changes ================== diff --git a/docs/source/configuration/reference.rst b/docs/source/configuration/reference.rst index 63181e44..9d166292 100644 --- a/docs/source/configuration/reference.rst +++ b/docs/source/configuration/reference.rst @@ -34,6 +34,8 @@ Common configuration is a subdictionary that is a value of ``common`` key in letters, Cyrillic letters). Valid values: any positive integer; it is suggested that you only set it to 1 (default) or 2. +.. _config-common-watcher: + ``watcher`` Select filesystem watcher. Variants are @@ -65,6 +67,8 @@ Common configuration is a subdictionary that is a value of ``common`` key in :ref:`module segment option <config-themes-seg-module>`. Paths defined here have priority when searching for modules. +.. _config-common-log: + ``log_file`` Defines path which will hold powerline logs. If not present, logging will be done to stderr. @@ -121,7 +125,16 @@ Common configuration is a subdictionary that is a value of ``ext`` key in is either ``matcher_module.module_attribute`` or ``module_attribute`` (``matcher_module`` defaults to ``powerline.matchers.vim``) and ``module_attribute`` should point to a function that returns boolean value - indicating that current buffer has (not) matched conditions. + indicating that current buffer has (not) matched conditions. There is an + exception for ``matcher_name`` though: if it is ``__tabline__`` no functions + are loaded. This special theme is used for ``tabline`` Vim option. + + For shell and ipython it is a simple ``{prompt_type : theme_name}``, where + ``prompt_type`` is a string with no special meaning (specifically it does + not refer to any Python function). Shell has ``continuation``, and + ``select`` prompts with rather self-explanatory names, IPython has ``in2``, + ``out`` and ``rewrite`` prompts (refer to IPython documentation for more + details) while ``in`` prompt is the default. ``components`` Determines which extension components should be enabled. This key is highly @@ -239,7 +252,7 @@ Themes ====== :Location: :file:`powerline/themes/{top_theme}.json`, - :file:`powerline/themes/__main__.json`, + :file:`powerline/themes/{extension}/__main__.json`, :file:`powerline/themes/{extension}/{name}.json` Theme files are processed in order given: definitions from each next file @@ -318,6 +331,8 @@ ascii Theme without any unicode characters at all .. note:: Top-level themes are out of equation here: they are merged before the above merging process happens. +.. _config-themes-segments: + ``segments`` A dict with a ``left`` and a ``right`` lists, consisting of segment dictionaries. Shell themes may also contain ``above`` list of dictionaries. @@ -424,6 +439,8 @@ ascii Theme without any unicode characters at all Segments are removed according to their priority, with low priority segments being removed first. + .. _config-themes-seg-draw_divider: + ``draw_hard_divider``, ``draw_soft_divider`` Whether to draw a divider between this and the adjacent segment. The adjacent segment is to the *right* for segments on the *left* side, and diff --git a/docs/source/develop.rst b/docs/source/develop.rst new file mode 100644 index 00000000..e7b29cc7 --- /dev/null +++ b/docs/source/develop.rst @@ -0,0 +1,11 @@ +*************** +Developer guide +*************** + +.. toctree:: + :maxdepth: 2 + :glob: + + develop/segments + develop/local-themes + develop/extensions diff --git a/docs/source/develop/extensions.rst b/docs/source/develop/extensions.rst new file mode 100644 index 00000000..9f4437d6 --- /dev/null +++ b/docs/source/develop/extensions.rst @@ -0,0 +1,47 @@ +******************************** +Creating new powerline extension +******************************** + +Powerline extension is a code that tells powerline how to highlight and display +segments in some set of applications. Specifically this means + +#. Creating a :py:class:`powerline.Powerline` subclass that knows how to obtain + :ref:`local configuration overrides <local-configuration-overrides>`. It also + knows how to load local themes, but not when to apply them. + + Instance of this class is the only instance that interacts directly with + bindings code, so it has a proxy :py:meth:`powerline.Powerline.render` and + :py:meth:`powerline.Powerline.shutdown` methods and other methods which may + be useful for bindings. + + This subclass must be placed directly in :file:`powerline` directory (e.g. in + :file:`powerline/vim.py`) and named like ``VimPowerline`` (version of the + file name without directory and extension and first capital letter + + ``Powerline``). There is no technical reason for naming classes like this. +#. Creating a :py:class:`powerline.renderer.Renderer` subclass that knows how to + highlight a segment or reset highlighting to the default value (only makes + sense in prompts). It is also responsible for selecting local themes and + computing text width. + + This subclass must be placed directly in :file:`powerline/renderers` + directory (if you are creating powerline extension for a set of applications + use :file:`powerline/renderers/{ext}/*.py`) and named like ``ExtRenderer`` or + ``AppPromptRenderer``. For technical reasons the class itself must be + referenced in ``renderer`` module attribute thus allowing only one renderer + per one module. +#. Creating an extension bindings. These are to be placed in + :file:`powerline/bindings/{ext}` and may contain virtually anything which may + be required for powerline to work inside given applications, assuming it does + not fit in other places. + +Powerline class +=============== + +.. autoclass:: powerline.Powerline + :members: + +Renderer class +============== + +.. autoclass:: powerline.renderer.Renderer + :members: diff --git a/docs/source/develop/local-themes.rst b/docs/source/develop/local-themes.rst new file mode 100644 index 00000000..e1ca6483 --- /dev/null +++ b/docs/source/develop/local-themes.rst @@ -0,0 +1,59 @@ +************ +Local themes +************ + +From the user point of view local themes are the regular themes with a specific +scope where they are applied (i.e. specific vim window or specific kind of +prompt). Used themes are defined in :ref:`local_themes key +<config-ext-local_themes>`. + +Vim local themes +================ + +Vim is the only available extension that has a wide variaty of options for local +themes. It is the only extension where local theme key refers to a function as +described in :ref:`local_themes value documentation <config-ext-local_themes>`. + +This function always takes a single value named ``matcher_info`` which is the +same dictionary as :ref:`segment_info dictionary <dev-segment_info-vim>`. Unlike +segments it takes this single argument as a *positional* argument, not as +a keyword one. + +Matcher function should return a boolean value: ``True`` if theme applies for +the given ``matcher_info`` dictionary or ``False`` if it is not. When one of the +matcher functions returns ``True`` powerline takes the corresponding theme at +uses it for the given window. Matchers are not tested in any particular order. + +In addition to :ref:`local_themes configuration key <config-ext-local_themes>` +developer of some plugin which wishes to support powerline without including his +code in powerline tree may use +:py:meth:`powerline.vim.VimPowerline.add_local_theme` method. It accepts two +arguments: matcher name (same as in :ref:`local_themes +<config-ext-local_themes>`) and dictionary with theme. This dictionary is merged +with :ref:`top theme <config-ext-top_theme>` and +:file:`powerline/themes/vim/__main__.json`. Note that if user already specified +your matcher in his configuration file ``KeyError`` is raised. + +Other local themes +================== + +Except for Vim only IPython and shells have local themes. Unlike Vim these +themes are names with no special meaning (they do not refer to or cause loading +of any Python functions): + ++---------+------------+-------------------------------------------------------+ +|Extension|Theme name |Description | ++---------+------------+-------------------------------------------------------+ +|Shell |continuation|Shown for unfinished command (unclosed quote, | +| | |unfinished cycle). | +| +------------+-------------------------------------------------------+ +| |select |Shown for ``select`` command available in some shells. | ++---------+------------+-------------------------------------------------------+ +|IPython |in2 |Continuation prompt: shown for unfinished (multiline) | +| | |expression, unfinished class or function definition. | +| +------------+-------------------------------------------------------+ +| |out |Displayed before the result. | +| +------------+-------------------------------------------------------+ +| |rewrite |Displayed before the actually executed code when | +| | |``autorewrite`` IPython feature is enabled. | ++---------+------------+-------------------------------------------------------+ diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst new file mode 100644 index 00000000..592f3052 --- /dev/null +++ b/docs/source/develop/segments.rst @@ -0,0 +1,278 @@ +**************** +Writing segments +**************** + +Each powerline segment is a callable object. It is supposed to be either +a Python function or :py:class:`powerline.segments.Segment` class. As a callable +object it should receive the following arguments: + +.. note:: All received arguments are keyword arguments. + +``pl`` + A :py:class:`powerline.PowerlineLogger` instance. It must be used every time + you need to log something. + +``segment_info`` + A dictionary. It is only received if callable has + ``powerline_requires_segment_info`` attribute. + + Refer to :ref:`segment_info detailed description <dev-segments-info>` for + further details. + +``create_watcher`` + Function that will create filesystem watcher once called. Which watcher will + be created exactly is controlled by :ref:`watcher configuration option + <config-common-watcher>`. + +And also any other argument(s) specified by user in :ref:`args key +<config-themes-seg-args>` (no additional arguments by default). + +This callable object should may return either a string (``unicode`` in Python2 +or ``str`` in Python3, *not* ``str`` in Python2 or ``bytes`` in Python3) object +or a list of dictionaries. String object is a short form of the following return +value: + +.. code-block:: python + + [{ + 'contents': original_return, + 'highlight_group': [segment_name], + }] + +Returned list is a list of segments treated independently, except for +:ref:`draw_inner_divider key <dev-segments-draw_inner_divider>`. + +All keys in segments returned by the function override those obtained from +:ref:`configuration <config-themes-segments>` and have the same meaning. + +Detailed description of used dictionary keys: + +``contents`` + Text displayed by segment. Should be a ``unicode`` (Python2) or ``str`` + (Python3) instance. + +``draw_hard_divider``, ``draw_soft_divider`` + Determines whether given divider should be drawn. Both have the same meaning + as :ref:`the similar keys in configuration + <config-themes-seg-draw_divider>`. + +.. _dev-segments-draw_inner_divider: + +``draw_inner_divider`` + Determines whether *any* divider between segments returned by function + should be drawn. Defaults to ``False``. + +.. _dev-segments-highlight_group: + +``highlight_group`` + Determines segment highlighting. Refer to :ref:`themes documentation + <config-themes-seg-highlight_group>` for more details. + + Defaults to the name of the segment. + + .. note:: + If you want to include your segment in powerline you must specify all + highlighting groups used in the segment documentation in the form:: + + Highlight groups used: ``g1``[ or ``g2``]*[, ``g3`` (gradient)[ or ``g4``]*]*. + + I.e. use:: + + Highlight groups used: ``foo_gradient`` (gradient) or ``foo``, ``bar``. + + to specify that your segment uses *either* ``foo_gradient`` group or + ``foo`` group *and* ``bar`` group meaning that ``powerline-lint`` will + check that at least one of the first two groups is defined (and if + ``foo_gradient`` is defined it must use at least one gradient color) and + third group is defined as well. + + You must specify all groups on one line. + +``divider_highlight_group`` + Determines segment divider highlight group. Only applicable for soft + dividers: colors for hard dividers are determined by colors of adjacent + segments. + + .. note:: + If you want to include your segment in powerline you must specify used + groups in the segment documentation in the form:: + + Divider highlight group used: ``group``. + + This text must not wrap and you are supposed to end all divider + highlight group names with ``:divider``: e.g. ``cwd:divider``. + +``gradient_level`` + First and the only key that may not be specified in user configuration. It + determines which color should be used for this segment when one of the + highlighting groups specified by :ref:`highlight_group + <dev-segments-highlight_group>` was defined to use the color gradient. + + This key may have any value from 0 to 100 inclusive, value is supposed to be + an ``int`` or ``float`` instance. + + No error occurs if segment has this key, but no used highlight groups use + gradient color. + +Segments layout +=============== + +Powerline segments are all located in one of the ``powerline.segments`` +submodules. For extension-specific segments ``powerline.segments.{ext}`` module +should be used (e.g. ``powerline.segments.shell``), for extension-agnostic there +is ``powerline.segments.common``. + +Plugin-specific segments (currently only those that are specific to vim plugins) +should live in ``powerline.segments.{ext}.plugin.{plugin_name}``: e.g. +``powerline.segments.vim.plugin.gundo``. + +.. _dev-segments-info: + +Segment information used in various extensions +============================================== + +Each ``segment_info`` value should be a dictionary with at least the following +keys: + +``environ`` + Current environment, may be an alias to ``os.environ``. Is guaranteed to + have ``__getitem__`` and ``get`` methods and nothing more. + + .. warning:: + You must not ever use ``os.environ``. If your segment is run in daemon + you will get daemon’s environment which is not correct. If your segment + is run in Vim or in zsh with libzpython you will get Vim or zsh + environment at python startup. + +``getcwd`` + Function that returns current working directory being called with no + arguments. You must not use ``os.getcwd`` for the same reasons you must not + use ``os.environ``, except that current working directory is valid in Vim + and zsh (but not in daemon). + +``home`` + Current home directory. May be false. + +.. _dev-segment_info-vim: + +Vim +--- + +Vim ``segment_info`` argument is a dictionary with the following keys: + +``window`` + ``vim.Window`` object. You may obtain one using ``vim.current.window`` or + ``vim.windows[number - 1]``. May be a false object, in which case you should + not use any of this objects’ properties. + +``winnr`` + Window number. Same as ``segment_info['window'].number`` *assuming* Vim is + new enough for ``vim.Window`` object to have ``number`` attribute. + +``window_id`` + Internal powerline window id, unique for each newly created window. You + should assume that this ID is hashable and supports equality comparison, but + you must not use any other assumptions about it. Currently uses integer + numbers incremented each time window is created. + +``buffer`` + ``vim.Buffer`` object. You may obtain one using ``vim.current.buffer``, + ``segment_info['window'].buffer`` or ``vim.buffers[some_number]``. Note that + in the latter case depending on vim version ``some_number`` may be ``bufnr`` + or the internal Vim buffer index which is *not* buffer number. For this + reason to get ``vim.Buffer`` object other then stored in ``segment_info`` + dictionary you must iterate over ``vim.buffers`` and check their ``number`` + attributes. + +``bufnr`` + Buffer number. + +``tabpage`` + ``vim.Tabpage`` object. You may obtain one using ``vim.current.tabpage`` or + ``vim.tabpages[number - 1]``. May be a false object, in which case you + should not use any of this objects’ properties. + +``tabnr`` + Tabpage number. + +``mode`` + Current mode. + +.. note:: + Your segment generally should not assume that it is run for the current + window, current buffer or current tabpage. “Current window” and “current + buffer” restrictions may be ignored if you use ``window_cached`` decorator, + “current tabpage” restriction may be safely ignored if you do not plan to + ever see your segment in the tabline. + +.. warning:: + Powerline is being tested with vim-7.2 and will be tested with it until + travis changes used vim version. This means that you may not use most of the + functionality like ``vim.Window.number``, ``vim.*.vars``, ``vim.*.options`` + or even ``dir(vim object)`` if you want your segment to be included in + powerline. + +Shell +----- + +``args`` + Parsed shell arguments: a ``argparse.Namespace`` object. Check out + ``powerline-render --help`` for the list of all available arguments. + Currently it is expected to contain at least the following attributes: + + ``last_exit_code`` + Exit code returned by last shell command. + + ``last_pipe_status`` + List of exit codes returned by last programs in the pipe or some false + object. Only available in ``zsh``. + + ``jobnum`` + Number of background jobs. + + ``renderer_arg`` + Dictionary containing some keys that are additional arguments used by + shell bindings. *You must not use this attribute directly*: all + arguments from this dictionary are merged with ``segment_info`` + dictionary. Known to have at least the following keys: + + ``client_id`` + Identifier unique to one shell instance. Is used to record instance + state by powerline daemon. + + It is not guaranteed that existing client ID will not be retaken + when old shell with this ID quit: usually process PID is used as + a client ID. + + It is also not guaranteed that client ID will be process PID, number + or something else at all. It is guaranteed though that client ID + will be some hashable object which supports equality comparison. + + ``local_theme`` + Local theme that will be used by shell. One should not rely on the + existence of this key. + + Other keys, if any, are specific to segments. + +Ipython +------- + +``ipython`` + Some object which has ``prompt_count`` attribute. Currently it is guaranteed + to have only this attribute. + + Attribute ``prompt_count`` contains the so-called “history count” + (equivalent to ``\N`` in ``in_template``). + +Segment class +============= + +.. autoclass:: powerline.segments.Segment + :members: + +PowerlineLogger class +===================== + +.. autoclass:: powerline.PowerlineLogger + :members: + :undoc-members: diff --git a/docs/source/index.rst b/docs/source/index.rst index bab34ecb..e97a17ad 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,6 +10,7 @@ Powerline installation usage configuration + develop troubleshooting tips-and-tricks license-and-credits diff --git a/docs/source/tips-and-tricks.rst b/docs/source/tips-and-tricks.rst index 9961b8eb..b2216b12 100644 --- a/docs/source/tips-and-tricks.rst +++ b/docs/source/tips-and-tricks.rst @@ -14,6 +14,7 @@ statusline: .. code-block:: vim set laststatus=2 " Always display the statusline in all windows + set showtabline=2 " Always display the tabline, even if there is only one tab set noshowmode " Hide the default mode text (e.g. -- INSERT -- below the statusline) .. _tips-and-tricks-urxvt: diff --git a/powerline/__init__.py b/powerline/__init__.py index f78b1135..9587fb6c 100644 --- a/powerline/__init__.py +++ b/powerline/__init__.py @@ -36,6 +36,24 @@ def _find_config_files(search_paths, config_file, config_loader=None, loader_cal class PowerlineLogger(object): + '''Proxy class for logging.Logger instance + + It emits messages in format ``{ext}:{prefix}:{message}`` where + + ``{ext}`` + is a used powerline extension (e.g. “vim”, “shell”, “ipython”). + ``{prefix}`` + is a local prefix, usually a segment name. + ``{message}`` + is the original message passed to one of the logging methods. + + Each of the methods (``critical``, ``exception``, ``info``, ``error``, + ``warn``, ``debug``) expects to receive message in an ``str.format`` format, + not in printf-like format. + + Log is saved to the location :ref:`specified by user <config-common-log>`. + ''' + def __init__(self, use_daemon_threads, logger, ext): self.logger = logger self.ext = ext @@ -261,23 +279,26 @@ class Powerline(object): colorschemes, render module (``powerline.renders.{ext}``). :param str renderer_module: Overrides renderer module (defaults to ``ext``). Should be the name of - the package imported like this: ``powerline.renders.{render_module}``. - If this parameter contains a dot, ``powerline.renderers.`` is not + the package imported like this: ``powerline.renderers.{render_module}``. + If this parameter contains a dot ``powerline.renderers.`` is not prepended. There is also a special case for renderers defined in toplevel modules: ``foo.`` (note: dot at the end) tries to get renderer from module ``foo`` (because ``foo`` (without dot) tries to get renderer - from module ``powerline.renderers.foo``). + from module ``powerline.renderers.foo``). When ``.foo`` (with leading + dot) variant is used ``renderer_module`` will be + ``powerline.renderers.{ext}{renderer_module}``. :param bool run_once: - Determines whether .renderer.render() method will be run only once + Determines whether :py:meth:`render` method will be run only once during python session. :param Logger logger: - If present, no new logger will be created and this logger will be used. + If present no new logger will be created and the provided logger will be + used. :param bool use_daemon_threads: - Use daemon threads for. + When creating threads make them daemon ones. :param Event shutdown_event: - Use this Event as shutdown_event. + Use this Event as shutdown_event instead of creating new event. :param ConfigLoader config_loader: - Class that manages (re)loading of configuration. + Instance of the class that manages (re)loading of the configuration. ''' def __init__(self, @@ -289,15 +310,20 @@ class Powerline(object): shutdown_event=None, config_loader=None): self.ext = ext - self.renderer_module = renderer_module or ext self.run_once = run_once self.logger = logger self.use_daemon_threads = use_daemon_threads - if '.' not in self.renderer_module: - self.renderer_module = 'powerline.renderers.' + self.renderer_module - elif self.renderer_module[-1] == '.': - self.renderer_module = self.renderer_module[:-1] + if not renderer_module: + self.renderer_module = 'powerline.renderers.' + ext + elif '.' not in renderer_module: + self.renderer_module = 'powerline.renderers.' + renderer_module + elif renderer_module.startswith('.'): + self.renderer_module = 'powerline.renderers.' + ext + renderer_module + elif renderer_module.endswith('.'): + self.renderer_module = renderer_module[:-1] + else: + self.renderer_module = renderer_module self.find_config_files = generate_config_finder(self.get_config_paths) diff --git a/powerline/bindings/bash/powerline.sh b/powerline/bindings/bash/powerline.sh index e44d9da2..1a5ab763 100644 --- a/powerline/bindings/bash/powerline.sh +++ b/powerline/bindings/bash/powerline.sh @@ -53,7 +53,7 @@ _powerline_prompt() { # Arguments: side, last_exit_code, jobnum $POWERLINE_COMMAND shell $1 \ --width="${COLUMNS:-$(_powerline_columns_fallback)}" \ - -r bash_prompt \ + -r.bash \ --last_exit_code=$2 \ --jobnum=$3 \ --renderer_arg="client_id=$$" @@ -64,7 +64,7 @@ _powerline_set_prompt() { local jobnum="$(jobs -p|wc -l)" PS1="$(_powerline_prompt aboveleft $last_exit_code $jobnum)" if test -n "$POWERLINE_SHELL_CONTINUATION$POWERLINE_BASH_CONTINUATION" ; then - PS2="$(_powerline_local_prompt left -rbash_prompt $last_exit_code $jobnum continuation)" + PS2="$(_powerline_local_prompt left -r.bash $last_exit_code $jobnum continuation)" fi if test -n "$POWERLINE_SHELL_SELECT$POWERLINE_BASH_SELECT" ; then PS3="$(_powerline_local_prompt left '' $last_exit_code $jobnum select)" @@ -79,7 +79,7 @@ _powerline_setup_prompt() { fi test "x$PROMPT_COMMAND" != "x${PROMPT_COMMAND%_powerline_set_prompt*}" || PROMPT_COMMAND=$'_powerline_set_prompt\n'"${PROMPT_COMMAND}" - PS2="$(_powerline_local_prompt left -rbash_prompt 0 0 continuation)" + PS2="$(_powerline_local_prompt left -r.bash 0 0 continuation)" PS3="$(_powerline_local_prompt left '' 0 0 select)" } diff --git a/powerline/bindings/shell/powerline.sh b/powerline/bindings/shell/powerline.sh index 3fc2b434..8940c028 100644 --- a/powerline/bindings/shell/powerline.sh +++ b/powerline/bindings/shell/powerline.sh @@ -122,8 +122,8 @@ _powerline_tmux_set_columns() { _powerline_set_renderer_arg() { case "$1" in - bb|ash) _POWERLINE_RENDERER_ARG="-rbash_prompt" ;; - mksh|ksh) _POWERLINE_RENDERER_ARG="-rksh_prompt" ;; + bb|ash) _POWERLINE_RENDERER_ARG="-r .bash" ;; + mksh|ksh) _POWERLINE_RENDERER_ARG="-r .ksh" ;; bash|dash) _POWERLINE_RENDERER_ARG= ;; esac } diff --git a/powerline/bindings/tcsh/powerline.tcsh b/powerline/bindings/tcsh/powerline.tcsh index 48155466..ac93341b 100644 --- a/powerline/bindings/tcsh/powerline.tcsh +++ b/powerline/bindings/tcsh/powerline.tcsh @@ -27,8 +27,8 @@ if ( { $POWERLINE_CONFIG shell --shell=tcsh uses prompt } ) then alias _powerline_above '$POWERLINE_COMMAND shell above --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS' endif - alias _powerline_set_prompt 'set prompt="`$POWERLINE_COMMAND shell left -r tcsh_prompt --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS`"' - alias _powerline_set_rprompt 'set rprompt="`$POWERLINE_COMMAND shell right -r tcsh_prompt --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS` "' + alias _powerline_set_prompt 'set prompt="`$POWERLINE_COMMAND shell left -r .tcsh --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS`"' + alias _powerline_set_rprompt 'set rprompt="`$POWERLINE_COMMAND shell right -r .tcsh --renderer_arg=client_id=$$ --last_exit_code=$POWERLINE_STATUS --width=$POWERLINE_COLUMNS` "' alias _powerline_set_columns 'set POWERLINE_COLUMNS=`stty size|cut -d" " -f2` ; set POWERLINE_COLUMNS=`expr $POWERLINE_COLUMNS - 2`' alias precmd 'set POWERLINE_STATUS=$? ; '"`alias precmd`"' ; _powerline_set_columns ; _powerline_above ; _powerline_set_prompt ; _powerline_set_rprompt' diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py index 444490b5..b6ccde1a 100644 --- a/powerline/bindings/zsh/__init__.py +++ b/powerline/bindings/zsh/__init__.py @@ -26,7 +26,7 @@ def get_var_config(var): class Args(object): __slots__ = ('last_pipe_status', 'last_exit_code') ext = ['shell'] - renderer_module = 'zsh_prompt' + renderer_module = '.zsh' @property def config(self): diff --git a/powerline/bindings/zsh/powerline.zsh b/powerline/bindings/zsh/powerline.zsh index 0bc2c50e..8a7078f1 100644 --- a/powerline/bindings/zsh/powerline.zsh +++ b/powerline/bindings/zsh/powerline.zsh @@ -129,7 +129,7 @@ _powerline_setup_prompt() { POWERLINE_COMMAND=( "$($POWERLINE_CONFIG shell command)" ) fi - local add_args='-r zsh_prompt' + local add_args='-r .zsh' add_args+=' --last_exit_code=$?' add_args+=' --last_pipe_status="$pipestatus"' add_args+=' --renderer_arg="client_id=$$"' diff --git a/powerline/config_files/config.json b/powerline/config_files/config.json index 4968fc6b..a5389b6c 100644 --- a/powerline/config_files/config.json +++ b/powerline/config_files/config.json @@ -34,10 +34,10 @@ "help": "help", "quickfix": "quickfix", - "powerline.matchers.plugin.nerdtree.nerdtree": "plugin_nerdtree", - "powerline.matchers.plugin.ctrlp.ctrlp": "plugin_ctrlp", - "powerline.matchers.plugin.gundo.gundo": "plugin_gundo", - "powerline.matchers.plugin.gundo.gundo_preview": "plugin_gundo-preview" + "powerline.matchers.vim.plugin.nerdtree.nerdtree": "plugin_nerdtree", + "powerline.matchers.vim.plugin.ctrlp.ctrlp": "plugin_ctrlp", + "powerline.matchers.vim.plugin.gundo.gundo": "plugin_gundo", + "powerline.matchers.vim.plugin.gundo.gundo_preview": "plugin_gundo-preview" } }, "wm": { diff --git a/powerline/config_files/themes/vim/default.json b/powerline/config_files/themes/vim/default.json index 3998e187..1f9348bb 100644 --- a/powerline/config_files/themes/vim/default.json +++ b/powerline/config_files/themes/vim/default.json @@ -55,13 +55,13 @@ }, { "exclude_modes": ["nc"], - "module": "powerline.segments.plugin.syntastic", + "module": "powerline.segments.vim.plugin.syntastic", "name": "syntastic", "priority": 50 }, { "exclude_modes": ["nc"], - "module": "powerline.segments.plugin.tagbar", + "module": "powerline.segments.vim.plugin.tagbar", "name": "current_tag", "draw_soft_divider": false, "priority": 50 diff --git a/powerline/config_files/themes/vim/plugin_ctrlp.json b/powerline/config_files/themes/vim/plugin_ctrlp.json index 02015b78..ae814c30 100644 --- a/powerline/config_files/themes/vim/plugin_ctrlp.json +++ b/powerline/config_files/themes/vim/plugin_ctrlp.json @@ -1,5 +1,5 @@ { - "default_module": "powerline.segments.plugin.ctrlp", + "default_module": "powerline.segments.vim.plugin.ctrlp", "segments": { "left": [ { diff --git a/powerline/config_files/themes/vim/plugin_nerdtree.json b/powerline/config_files/themes/vim/plugin_nerdtree.json index 95495db1..ee142cde 100644 --- a/powerline/config_files/themes/vim/plugin_nerdtree.json +++ b/powerline/config_files/themes/vim/plugin_nerdtree.json @@ -1,5 +1,5 @@ { - "default_module": "powerline.segments.plugin.nerdtree", + "default_module": "powerline.segments.vim.plugin.nerdtree", "segments": { "left": [ { diff --git a/powerline/ipython.py b/powerline/ipython.py index 5fc66b34..bc244d6d 100644 --- a/powerline/ipython.py +++ b/powerline/ipython.py @@ -26,7 +26,7 @@ class IpythonPowerline(Powerline): def __init__(self, is_prompt, old_widths): super(IpythonPowerline, self).__init__( 'ipython', - renderer_module=('ipython_prompt' if is_prompt else 'ipython'), + renderer_module=('.prompt' if is_prompt else None), use_daemon_threads=True ) self.old_widths = old_widths diff --git a/powerline/lib/vcs/__init__.py b/powerline/lib/vcs/__init__.py index 1029bc3f..58a4883d 100644 --- a/powerline/lib/vcs/__init__.py +++ b/powerline/lib/vcs/__init__.py @@ -194,7 +194,7 @@ class TreeStatusCache(dict): if self.tw(key, logger=logger, ignore_event=getattr(repo, 'ignore_event', None)): self.pop(key, None) except OSError as e: - logger.warn('Failed to check %s for changes, with error: %s'% key, e) + logger.warn('Failed to check %s for changes, with error: %s' % key, e) return self.cache_and_get(key, repo.status) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index a1749790..7ce152fb 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -432,7 +432,7 @@ def check_matcher_func(ext, match_name, data, context, echoerr): match_function = match_name with WithPath(import_paths): try: - func = getattr(__import__(match_module, fromlist=[match_function]), unicode(match_function)) + func = getattr(__import__(str(match_module), fromlist=[str(match_function)]), str(match_function)) except ImportError: echoerr(context='Error while loading matcher functions', problem='failed to load module {0}'.format(match_module), @@ -823,7 +823,7 @@ def check_key_compatibility(segment, data, context, echoerr): def check_segment_module(module, data, context, echoerr): with WithPath(data['import_paths']): try: - __import__(unicode(module)) + __import__(str(module)) except ImportError as e: if echoerr.logger.level >= logging.DEBUG: echoerr.logger.exception(e) @@ -875,7 +875,7 @@ def import_segment(name, data, context, echoerr, module=None): with WithPath(data['import_paths']): try: - func = getattr(__import__(unicode(module), fromlist=[unicode(name)]), unicode(name)) + func = getattr(__import__(str(module), fromlist=[str(name)]), str(name)) except ImportError: echoerr(context='Error while checking segments (key {key})'.format(key=context_key(context)), problem='failed to import module {0}'.format(module), @@ -1252,7 +1252,7 @@ segment_spec = Spec( ).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})'), right=segments_spec().context_message('Error while loading segments from right side (key {key})'), ).func( diff --git a/powerline/matcher.py b/powerline/matcher.py index 5578d282..37049e2f 100644 --- a/powerline/matcher.py +++ b/powerline/matcher.py @@ -13,7 +13,7 @@ def gen_matcher_getter(ext, import_paths): oldpath = sys.path sys.path = import_paths + sys.path try: - return getattr(__import__(match_module, fromlist=[match_function]), match_function) + return getattr(__import__(str(match_module), fromlist=[str(match_function)]), match_function) finally: sys.path = oldpath return get diff --git a/powerline/matchers/vim.py b/powerline/matchers/vim/__init__.py similarity index 100% rename from powerline/matchers/vim.py rename to powerline/matchers/vim/__init__.py diff --git a/powerline/matchers/plugin/__init__.py b/powerline/matchers/vim/plugin/__init__.py similarity index 100% rename from powerline/matchers/plugin/__init__.py rename to powerline/matchers/vim/plugin/__init__.py diff --git a/powerline/matchers/plugin/ctrlp.py b/powerline/matchers/vim/plugin/ctrlp.py similarity index 100% rename from powerline/matchers/plugin/ctrlp.py rename to powerline/matchers/vim/plugin/ctrlp.py diff --git a/powerline/matchers/plugin/gundo.py b/powerline/matchers/vim/plugin/gundo.py similarity index 100% rename from powerline/matchers/plugin/gundo.py rename to powerline/matchers/vim/plugin/gundo.py diff --git a/powerline/matchers/plugin/nerdtree.py b/powerline/matchers/vim/plugin/nerdtree.py similarity index 100% rename from powerline/matchers/plugin/nerdtree.py rename to powerline/matchers/vim/plugin/nerdtree.py diff --git a/powerline/renderers/ipython.py b/powerline/renderers/ipython/__init__.py similarity index 100% rename from powerline/renderers/ipython.py rename to powerline/renderers/ipython/__init__.py diff --git a/powerline/renderers/ipython_prompt.py b/powerline/renderers/ipython/prompt.py similarity index 100% rename from powerline/renderers/ipython_prompt.py rename to powerline/renderers/ipython/prompt.py diff --git a/powerline/renderers/shell.py b/powerline/renderers/shell/__init__.py similarity index 100% rename from powerline/renderers/shell.py rename to powerline/renderers/shell/__init__.py diff --git a/powerline/renderers/bash_prompt.py b/powerline/renderers/shell/bash.py similarity index 100% rename from powerline/renderers/bash_prompt.py rename to powerline/renderers/shell/bash.py diff --git a/powerline/renderers/ksh_prompt.py b/powerline/renderers/shell/ksh.py similarity index 100% rename from powerline/renderers/ksh_prompt.py rename to powerline/renderers/shell/ksh.py diff --git a/powerline/renderers/tcsh_prompt.py b/powerline/renderers/shell/tcsh.py similarity index 87% rename from powerline/renderers/tcsh_prompt.py rename to powerline/renderers/shell/tcsh.py index adbb91c9..261b081a 100644 --- a/powerline/renderers/tcsh_prompt.py +++ b/powerline/renderers/shell/tcsh.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals -from powerline.renderers.zsh_prompt import ZshPromptRenderer +from powerline.renderers.shell.zsh import ZshPromptRenderer class TcshPromptRenderer(ZshPromptRenderer): diff --git a/powerline/renderers/zsh_prompt.py b/powerline/renderers/shell/zsh.py similarity index 100% rename from powerline/renderers/zsh_prompt.py rename to powerline/renderers/shell/zsh.py diff --git a/powerline/segment.py b/powerline/segment.py index 97538813..cde42398 100644 --- a/powerline/segment.py +++ b/powerline/segment.py @@ -58,8 +58,9 @@ def get_function(data, segment): oldpath = sys.path sys.path = data['path'] + sys.path segment_module = str(segment.get('module', data['default_module'])) + name = str(segment['name']) try: - return None, getattr(__import__(segment_module, fromlist=[segment['name']]), segment['name']), segment_module + return None, getattr(__import__(segment_module, fromlist=[name]), name), segment_module finally: sys.path = oldpath diff --git a/powerline/segments/__init__.py b/powerline/segments/__init__.py index 3c2da39c..8199b3cc 100644 --- a/powerline/segments/__init__.py +++ b/powerline/segments/__init__.py @@ -13,7 +13,14 @@ __path__ = extend_path(__path__, __name__) class Segment(object): '''Base class for any segment that is not a function - Required for powerline.lint.inspect to work properly. + Required for powerline.lint.inspect to work properly: it defines methods for + omitting existing or adding new arguments. + + .. note:: + Until python-3.4 ``inspect.getargspec`` does not support querying + callable classes for arguments of their ``__call__`` method, requiring + to use this method directly (i.e. before 3.4 you should write + ``getargspec(obj.__call__)`` in place of ``getargspec(obj)``). ''' if sys.version_info < (3, 4): def argspecobjs(self): diff --git a/powerline/segments/common.py b/powerline/segments/common.py index 84a32a15..eaef499f 100644 --- a/powerline/segments/common.py +++ b/powerline/segments/common.py @@ -1130,7 +1130,7 @@ def _get_battery(pl): what, dbus_interface=devinterface ) - if int(devget('Type'))!= 2: + if int(devget('Type')) != 2: pl.debug('Not using DBUS+UPower with {0}: invalid type', devpath) continue if not bool(devget('IsPresent')): diff --git a/powerline/segments/vim.py b/powerline/segments/vim/__init__.py similarity index 100% rename from powerline/segments/vim.py rename to powerline/segments/vim/__init__.py diff --git a/powerline/segments/plugin/__init__.py b/powerline/segments/vim/plugin/__init__.py similarity index 100% rename from powerline/segments/plugin/__init__.py rename to powerline/segments/vim/plugin/__init__.py diff --git a/powerline/segments/plugin/ctrlp.py b/powerline/segments/vim/plugin/ctrlp.py similarity index 100% rename from powerline/segments/plugin/ctrlp.py rename to powerline/segments/vim/plugin/ctrlp.py diff --git a/powerline/segments/plugin/nerdtree.py b/powerline/segments/vim/plugin/nerdtree.py similarity index 100% rename from powerline/segments/plugin/nerdtree.py rename to powerline/segments/vim/plugin/nerdtree.py diff --git a/powerline/segments/plugin/syntastic.py b/powerline/segments/vim/plugin/syntastic.py similarity index 100% rename from powerline/segments/plugin/syntastic.py rename to powerline/segments/vim/plugin/syntastic.py diff --git a/powerline/segments/plugin/tagbar.py b/powerline/segments/vim/plugin/tagbar.py similarity index 100% rename from powerline/segments/plugin/tagbar.py rename to powerline/segments/vim/plugin/tagbar.py diff --git a/powerline/shell.py b/powerline/shell.py index 513a6974..25d07258 100644 --- a/powerline/shell.py +++ b/powerline/shell.py @@ -50,7 +50,7 @@ def get_argparser(parser=None, *args, **kwargs): p.add_argument('ext', nargs=1, help='Extension: application for which powerline command is launched (usually `shell\' or `tmux\')') p.add_argument('side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'), help='Side: `left\' and `right\' represent left and right side respectively, `above\' emits lines that are supposed to be printed just above the prompt and `aboveleft\' is like concatenating `above\' with `left\' with the exception that only one Python instance is used in this case.') p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str, - help='Renderer module. Usually something like `bash_prompt\' or `zsh_prompt\', is supposed to be set only in shell-specific bindings file.') + help='Renderer module. Usually something like `.bash\' or `.zsh\', is supposed to be set only in shell-specific bindings file.') p.add_argument('-w', '--width', type=int, help='Maximum prompt with. Triggers truncation of some segments') p.add_argument('--last_exit_code', metavar='INT', type=int, help='Last exit code') p.add_argument('--last_pipe_status', metavar='LIST', default='', type=lambda s: [int(status) for status in s.split()], help='Like above, but is supposed to contain space-separated array of statuses, representing exit statuses of commands in one pipe.') diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index f1ff683a..5af43eee 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -42,7 +42,7 @@ class TestParser(TestCase): (['shell', '--config_path'], 'expected one argument'), (['shell', '--renderer_arg'], 'expected one argument'), (['shell', '--jobnum'], 'expected one argument'), - (['-r', 'zsh_prompt'], 'too few arguments|the following arguments are required: ext'), + (['-r', '.zsh'], 'too few arguments|the following arguments are required: ext'), (['shell', '--last_exit_code', 'i'], 'invalid int value'), (['shell', '--last_pipe_status', '1 i'], 'invalid <lambda> value'), ]: @@ -57,12 +57,12 @@ class TestParser(TestCase): err = StrIO() with replace_attr(sys, 'stdout', out, 'stderr', err): for argv, expargs in [ - (['shell'], {'ext': ['shell']}), - (['shell', '-r', 'zsh_prompt'], {'ext': ['shell'], 'renderer_module': 'zsh_prompt'}), + (['shell'], {'ext': ['shell']}), + (['shell', '-r', '.zsh'], {'ext': ['shell'], 'renderer_module': '.zsh'}), ([ 'shell', 'left', - '-r', 'zsh_prompt', + '-r', '.zsh', '--last_exit_code', '10', '--last_pipe_status', '10 20 30', '--jobnum=10', @@ -76,7 +76,7 @@ class TestParser(TestCase): ], { 'ext': ['shell'], 'side': 'left', - 'renderer_module': 'zsh_prompt', + 'renderer_module': '.zsh', 'last_exit_code': 10, 'last_pipe_status': [10, 20, 30], 'jobnum': 10, diff --git a/tests/test_provided_config_files.py b/tests/test_provided_config_files.py index 45cffcf6..da160ab1 100644 --- a/tests/test_provided_config_files.py +++ b/tests/test_provided_config_files.py @@ -86,7 +86,7 @@ class TestConfig(TestCase): def test_zsh(self): from powerline.shell import ShellPowerline - args = Args(last_pipe_status=[1, 0], jobnum=0, ext=['shell'], renderer_module='zsh_prompt') + args = Args(last_pipe_status=[1, 0], jobnum=0, ext=['shell'], renderer_module='.zsh') segment_info = {'args': args} with ShellPowerline(args, run_once=False) as powerline: powerline.render(segment_info=segment_info) @@ -102,7 +102,7 @@ class TestConfig(TestCase): def test_bash(self): from powerline.shell import ShellPowerline - args = Args(last_exit_code=1, jobnum=0, ext=['shell'], renderer_module='bash_prompt', config={'ext': {'shell': {'theme': 'default_leftonly'}}}) + args = Args(last_exit_code=1, jobnum=0, ext=['shell'], renderer_module='.bash', config={'ext': {'shell': {'theme': 'default_leftonly'}}}) with ShellPowerline(args, run_once=False) as powerline: powerline.render(segment_info={'args': args}) with ShellPowerline(args, run_once=False) as powerline: