diff options
Diffstat (limited to 'docs/source/develop/segments.rst')
-rw-r--r-- | docs/source/develop/segments.rst | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst new file mode 100644 index 0000000..543ddd5 --- /dev/null +++ b/docs/source/develop/segments.rst @@ -0,0 +1,547 @@ +.. _dev-segments: + +**************** +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 + something needs to be logged. + +``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). + +.. note:: + For powerline-lint to work properly the following things may be needed: + + #. If segment is a :py:class:`powerline.segments.Segment` instance and used + arguments are scattered over multiple methods + :py:meth:`powerline.segments.Segment.argspecobjs` should be overridden in + subclass to tell powerline-lint which objects should be inspected for + arguments. + #. If segment takes some arguments that are never listed, but accessed via + ``kwargs.get()`` or previous function cannot be used for whatever reason + :py:meth:`powerline.segments.Segment.additional_args` should be + overridden in subclass. + #. If user is expected to use one :ref:`name <config-themes-seg-name>` for + multiple segments which cannot be linked to the segment function + automatically by powerline-lint (e.g. because there are no instances of + the segments in question in the default configuration) + :py:func:`powerline.lint.checks.register_common_name` function should be + used. + +Object representing segment may have the following attributes used by +powerline: + +``powerline_requires_segment_info`` + This attribute controls whether segment will receive ``segment_info`` + argument: if it is present argument will be received. + +``powerline_requires_filesystem_watcher`` + This attribute controls whether segment will receive ``create_watcher`` + argument: if it is present argument will be received. + +``powerline_segment_datas`` + This attribute must be a dictionary containing ``top_theme: segment_data`` + mapping where ``top_theme`` is any theme name (it is expected that all of + the names from :ref:`top-level themes list <config-top_themes-list>` are + present) and ``segment_data`` is a dictionary like the one that is contained + inside :ref:`segment_data dictionary in configuration + <config-themes-segment_data>`. This attribute should be used to specify + default theme-specific values for *third-party* segments: powerline + theme-specific values go directly to :ref:`top-level themes + <config-themes>`. + +.. _dev-segments-startup: + +``startup`` + This attribute must be a callable which accepts the following keyword + arguments: + + * ``pl``: :py:class:`powerline.PowerlineLogger` instance which is to be used + for logging. + * ``shutdown_event``: :py:class:`Event` object which will be set when + powerline will be shut down. + * Any arguments found in user configuration for the given segment (i.e. + :ref:`args key <config-themes-seg-args>`). + + This function is called at powerline startup when using long-running + processes (e.g. powerline in vim, in zsh with libzpython, in ipython or in + powerline daemon) and not called when ``powerline-render`` executable is + used (more specific: when :py:class:`powerline.Powerline` constructor + received true ``run_once`` argument). + +.. _dev-segments-shutdown: + +``shutdown`` + This attribute must be a callable that accepts no arguments and shuts down + threads and frees any other resources allocated in ``startup`` method of the + segment in question. + + This function is not called when ``startup`` method is not called. + +.. _dev-segments-expand: + +``expand`` + This attribute must be a callable that accepts the following keyword + arguments: + + * ``pl``: :py:class:`powerline.PowerlineLogger` instance which is to be used + for logging. + * ``amount``: integer number representing amount of display cells result + must occupy. + + .. warning:: + “Amount of display cells” is *not* number of Unicode codepoints, string + length, or byte count. It is suggested that this function should look + something like ``return (' ' * amount) + segment['contents']`` where + ``' '`` may be replaced with anything that is known to occupy exactly + one display cell. + * ``segment``: :ref:`segment dictionary <dev-segments-segment>`. + * Any arguments found in user configuration for the given segment (i.e. + :ref:`args key <config-themes-seg-args>`). + + It must return new value of :ref:`contents <dev-segments-seg-contents>` key. + +.. _dev-segments-truncate: + +``truncate`` + Like :ref:`expand function <dev-segments-expand>`, but for truncating + segments. Here ``amount`` means the number of display cells which must be + freed. + + This function is called for all segments before powerline starts purging + them to free space. + +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_groups': [segment_name], + }] + +.. _dev-segments-return: + +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: + +.. _dev-segments-contents: + +``contents`` + Text displayed by segment. Should be a ``unicode`` (Python2) or ``str`` + (Python3) instance. + +``literal_contents`` + Text that needs to be output literally (i.e. without passing through + :py:meth:`powerline.renderer.strwidth` to determine length, through + :py:meth:`powerline.renderer.escape` to escape special characters and + through :py:meth:`powerline.renderer.hl` to highlight it). Should be a tuple + ``(contents_length, contents)`` where ``contents_length`` is an integer and + ``contents`` is a ``unicode`` (Python2) or ``str`` (Python3) instance. + + If this key is present and its second value is true then other contents keys + (:ref:`contents <dev-segments-contents>`, :ref:`after + <config-themes-seg-after>`, :ref:`before <config-themes-seg-before>`) will + be ignored. + + .. note:: + If target is inclusion of the segment in powerline upstream all segment + functions that output *only* subsegments with ``literal_contents`` key + must contain the following string in documentation:: + + No highlight groups are used (literal segment). + + String must be present on the separate line. + +.. _dev-segments-draw_inner_divider: + +``draw_hard_divider``, ``draw_soft_divider``, ``draw_inner_divider`` + Determines whether given divider should be drawn. All have the same meaning + as :ref:`the similar keys in configuration <config-themes-seg-draw_divider>` + (:ref:`draw_inner_divider <config-themes-seg-draw_inner_divider>`). + +.. _dev-segments-highlight_groups: + +``highlight_groups`` + Determines segment highlighting. Refer to :ref:`themes documentation + <config-themes-seg-highlight_groups>` for more details. + + Defaults to the name of the segment. + + .. note:: + If target is inclusion of the segment in powerline upstream all used + highlighting groups must be specified 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 the 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. + + All groups must be specified 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 target is inclusion of the segment in powerline upstream used divider + highlight group must be specified in the segment documentation in the + form:: + + Divider highlight group used: ``group``. + + This text must not wrap and all divider highlight group names are + supposed to end 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_groups + <dev-segments-highlight_groups>` 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. + +``_*`` + Keys starting with underscore are reserved for powerline and must not be + returned. + +``__*`` + Keys starting with two underscores are reserved for the segment functions, + specifically for :ref:`expand function <dev-segments-expand>`. + +.. _dev-segments-segment: + +Segment dictionary +================== + +Segment dictionary contains the following keys: + +* All keys returned by segment function (if it was used). + +* All of the following keys: + + ``name`` + Segment name: value of the :ref:`name key <config-themes-seg-name>` or + function name (last component of the :ref:`function key + <config-themes-seg-function>`). May be ``None``. + + ``type`` + :ref:`Segment type <config-themes-seg-type>`. Always represents actual type + and is never ``None``. + + ``highlight_groups``, ``divider_highlight_group`` + Used highlight groups. May be ``None``. + + ``highlight_group_prefix`` + If this key is present then given prefix will be prepended to each highlight + group (both regular and divider) used by this segment in a form + ``{prefix}:{group}`` (note the colon). This key is mostly useful for + :ref:`segment listers <dev-listers>`. + + .. _dev-segments-seg-around: + + ``before``, ``after`` + Value of :ref:`before <config-themes-seg-before>` or :ref:`after + <config-themes-seg-after>` configuration options. May be ``None`` as well as + an empty string. + + ``contents_func`` + Function used to get segment contents. May be ``None``. + + .. _dev-segments-seg-contents: + + ``contents`` + Actual segment contents, excluding dividers and :ref:`before/after + <dev-segments-seg-around>`. May be ``None``. + + ``priority`` + :ref:`Segment priority <config-themes-seg-priority>`. May be ``None`` for no + priority (such segments are always shown). + + ``draw_soft_divider``, ``draw_hard_divider``, ``draw_inner_divider`` + :ref:`Divider control flags <dev-segments-draw_inner_divider>`. + + ``side`` + Segment side: ``right`` or ``left``. + + ``display_condition`` + Contains function that takes three position parameters: + :py:class:`powerline.PowerlineLogger` instance, :ref:`segment_info + <dev-segments-info>` dictionary and current mode and returns either ``True`` + or ``False`` to indicate whether particular segment should be processed. + + This key is constructed based on :ref:`exclude_/include_modes keys + <config-themes-seg-exclude_modes>` and :ref:`exclude_/include_function keys + <config-themes-seg-exclude_function>`. + + ``width``, ``align`` + :ref:`Width and align options <config-themes-seg-align>`. May be ``None``. + + ``expand``, ``truncate`` + Partially applied :ref:`expand <dev-segments-expand>` or :ref:`truncate + <dev-segments-truncate>` function. Accepts ``pl``, ``amount`` and + ``segment`` positional parameters, keyword parameters from :ref:`args + <config-themes-seg-args>` key were applied. + + ``startup`` + Partially applied :ref:`startup function <dev-segments-startup>`. Accepts + ``pl`` and ``shutdown_event`` positional parameters, keyword parameters from + :ref:`args <config-themes-seg-args>` key were applied. + + ``shutdown`` + :ref:`Shutdown function <dev-segments-shutdown>`. Accepts no argument. + +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:: + ``os.environ`` must not ever be used: + + * If segment is run in the daemon this way it will get daemon’s + environment which is not correct. + * If segment is run in Vim or in zsh with libzpython ``os.environ`` will + contain Vim or zsh environ *at the moment Python interpreter was + loaded*. + +``getcwd`` + Function that returns current working directory being called with no + arguments. ``os.getcwd`` must not be used for the same reasons the use of + ``os.environ`` is forbidden, 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. ``vim.current.window`` or ``vim.windows[number - 1]`` + may be used to obtain such object. May be a false object, in which case any + of this object’s properties must not be used. + +``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. It is + safe to assume that this ID is hashable and supports equality comparison, + but no other assumptions about it should be used. Currently uses integer + numbers incremented each time window is created. + +``buffer`` + ``vim.Buffer`` object. One may be obtained 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 iteration over ``vim.buffers`` and checking their ``number`` + attributes should be performed. + +``bufnr`` + Buffer number. + +``tabpage`` + ``vim.Tabpage`` object. One may be obtained using ``vim.current.tabpage`` or + ``vim.tabpages[number - 1]``. May be a false object, in which case no + object’s properties can be used. + +``tabnr`` + Tabpage number. + +``mode`` + Current mode. + +``encoding`` + Value of ``&encoding`` from the time when powerline was initialized. It + should be used to convert return values. + +.. note:: + 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 ``window_cached`` decorator is used, “current + tabpage” restriction may be safely ignored if segment is not supposed to be + used in tabline. + +.. warning:: + Powerline is being tested with vim-7.0.112 (some minor sanity check) and + latest Vim. This means that most of the functionality like + ``vim.Window.number``, ``vim.*.vars``, ``vim.*.options`` or even ``dir(vim + object)`` should be avoided in segments that want to be included in the + upstream. + +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. Is either one integer, + ``sig{name}`` or ``sig{name}+core`` (latter two are only seen in ``rc`` + shell). + + ``last_pipe_status`` + List of exit codes returned by last programs in the pipe or some false + object. Only available in ``zsh`` and ``rc``. Is a list of either + integers, ``sig{name}`` or ``sig{name}+core`` (latter two are only seen + in ``rc`` shell). + + ``jobnum`` + Number of background jobs. + + ``renderer_arg`` + Dictionary containing some keys that are additional arguments used by + shell bindings. *This attribute must not be used 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. In tmux this is the same as :ref:`pane_id + <dev-seginfo-shell-renarg-pane_id>`. + + 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. + + .. _dev-seginfo-shell-renarg-pane_id: + + ``pane_id`` + Identifier unique to each tmux pane. Is always an integer, optional. + Obtained by using ``tmux display -p '#D'``, then all leading spaces + and per cent signs are stripped and the result is converted into an + integer. + + 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``). + +Pdb +--- + +``pdb`` + Currently active :py:class:`pdb.Pdb` instance. + +``curframe`` + Frame which will be run next. Note: due to the existence of + :py:func:`powerline.listers.pdb.frame_lister` one must not use + ``segment_info['pdb'].curframe``. + +``initial_stack_length`` + Equal to the length of :py:attr:`pdb.Pdb.stack` at the first invocation of + the prompt decremented by one. + +i3wm +---- + +``mode`` + Currently active i3 mode (as a string). + +``output`` + ``xrandr`` output name currently drawing to. Currently only available + in lemonbar bindings. + +``workspace`` + dictionary containing the workspace name under the key ``"name"`` and + boolean values for the ``"visible"``, ``"urgent"`` and ``"focused"`` + keys, indicating the state of the workspace. Currently only provided by + the :py:func:`powerline.listers.i3wm.workspace_lister` lister. + +Segment class +============= + +.. autoclass:: powerline.segments.Segment + :members: + +PowerlineLogger class +===================== + +.. autoclass:: powerline.PowerlineLogger + :members: + :undoc-members: |