Implement segment truncation

Closes #161 (requires implementation for specific segments though)
This commit is contained in:
ZyX 2014-08-30 18:19:56 +04:00
parent d6c603daf0
commit 2505d0b827
4 changed files with 55 additions and 12 deletions

View File

@ -102,6 +102,16 @@ powerline:
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
@ -251,10 +261,11 @@ Segment dictionary contains the following keys:
``width``, ``align``
:ref:`Width and align options <config-themes-seg-align>`. May be ``None``.
``expand``
Partially applied :ref:`expand function <dev-segments-expand>`. Accepts
``pl``, ``amount`` and ``segment`` positional parameters, keyword parameters
from :ref:`args <config-themes-seg-args>` key were applied.
``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

View File

@ -1,9 +1,12 @@
# vim:fileencoding=utf-8:noet
from powerline.theme import Theme
from unicodedata import east_asian_width, combining
import os
from unicodedata import east_asian_width, combining
from itertools import chain
from powerline.theme import Theme
try:
NBSP = unicode(' ', 'utf-8')
except NameError:
@ -262,11 +265,17 @@ class Renderer(object):
# Create an ordered list of segments that can be dropped
segments_priority = sorted((segment for segment in segments if segment['priority'] is not None), key=lambda segment: segment['priority'], reverse=True)
for segment in segments_priority:
current_width = self._render_length(theme, segments, divider_widths)
if current_width <= width:
break
segments.remove(segment)
no_priority_segments = filter(lambda segment: segment['priority'] is None, segments)
current_width = self._render_length(theme, segments, divider_widths)
if current_width > width:
for segment in chain(segments_priority, no_priority_segments):
if segment['truncate'] is not None:
segment['contents'] = segment['truncate'](self.pl, current_width - width, segment)
for segment in segments_priority:
if current_width <= width:
break
segments.remove(segment)
current_width = self._render_length(theme, segments, divider_widths)
# Distribute the remaining space on spacer segments
segments_spacers = [segment for segment in segments if segment['expand'] is not None]

View File

@ -93,7 +93,7 @@ def get_attr_func(contents_func, key, args, is_space_func=False):
try:
return func(pl=pl, amount=amount, segment=segment, **args)
except Exception as e:
pl.exception('Exception while computing segment expansion: {0}', str(e))
pl.exception('Exception while computing {0} function: {1}', key, str(e))
return segment['contents'] + (' ' * amount)
return expand_func
else:
@ -292,6 +292,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
'width': None,
'align': None,
'expand': None,
'truncate': None,
'startup': None,
'shutdown': None,
'mode': None,
@ -305,6 +306,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
startup_func = get_attr_func(_contents_func, 'startup', args)
shutdown_func = getattr(_contents_func, 'shutdown', None)
expand_func = get_attr_func(_contents_func, 'expand', args, True)
truncate_func = get_attr_func(_contents_func, 'truncate', args, True)
if hasattr(_contents_func, 'powerline_requires_filesystem_watcher'):
create_watcher = lambda: create_file_watcher(pl, common_config['watcher'])
@ -319,6 +321,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
shutdown_func = None
contents_func = None
expand_func = None
truncate_func = None
return {
'name': name or function_name,
@ -339,6 +342,7 @@ def gen_segment_getter(pl, ext, common_config, theme_configs, default_module, ge
'width': segment.get('width'),
'align': segment.get('align', 'l'),
'expand': expand_func,
'truncate': truncate_func,
'startup': startup_func,
'shutdown': shutdown_func,
'mode': None,

View File

@ -494,6 +494,25 @@ class TestSegmentAttributes(TestRender):
}
self.assertRenderEqual(p, '{56} ----pl,{6-}>>{--}', width=10)
@add_args
def test_truncate(self, p, config):
def m1(divider=',', **kwargs):
return divider.join(kwargs.keys()) + divider
def truncate(pl, amount, segment, **kwargs):
return segment['contents'][:-amount]
m1.truncate = truncate
sys.modules['bar'] = Args(m1=m1)
config['themes/test/default']['segments'] = {
'left': [
{
'function': 'bar.m1'
}
]
}
self.assertRenderEqual(p, '{56} p{6-}>>{--}', width=4)
class TestSegmentData(TestRender):
@add_args