mirror of
https://github.com/powerline/powerline.git
synced 2025-07-28 16:24:57 +02:00
Add output_width used for various shells
This commit is contained in:
parent
72b7744b98
commit
c97ab8055a
@ -27,15 +27,16 @@ class PowerlinePromptManager(PromptManager):
|
|||||||
powerline = self.non_prompt_powerline
|
powerline = self.non_prompt_powerline
|
||||||
else:
|
else:
|
||||||
powerline = self.prompt_powerline
|
powerline = self.prompt_powerline
|
||||||
res, res_nocolor = powerline.render(
|
res = powerline.render(
|
||||||
output_raw=True,
|
output_width=True,
|
||||||
|
output_raw=not color,
|
||||||
width=width,
|
width=width,
|
||||||
matcher_info=name,
|
matcher_info=name,
|
||||||
segment_info=self.powerline_segment_info,
|
segment_info=self.powerline_segment_info,
|
||||||
)
|
)
|
||||||
self.txtwidth = len(res_nocolor)
|
self.txtwidth = res[-1]
|
||||||
self.width = self.txtwidth
|
self.width = res[-1]
|
||||||
ret = res if color else res_nocolor
|
ret = res[0] if color else res[1]
|
||||||
if name == 'rewrite':
|
if name == 'rewrite':
|
||||||
return RewriteResult(ret)
|
return RewriteResult(ret)
|
||||||
else:
|
else:
|
||||||
|
@ -33,11 +33,14 @@ class PowerlinePrompt(BasePrompt):
|
|||||||
return string(self.p_str)
|
return string(self.p_str)
|
||||||
|
|
||||||
def set_p_str(self, width=None):
|
def set_p_str(self, width=None):
|
||||||
self.p_str, self.p_str_nocolor = (
|
self.p_str, self.p_str_nocolor, self.powerline_prompt_width = (
|
||||||
self.powerline.render(output_raw=True,
|
self.powerline.render(
|
||||||
|
output_raw=True,
|
||||||
|
output_width=True,
|
||||||
segment_info=self.powerline_segment_info,
|
segment_info=self.powerline_segment_info,
|
||||||
matcher_info=self.powerline_prompt_type,
|
matcher_info=self.powerline_prompt_type,
|
||||||
width=width)
|
width=width
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -58,7 +61,7 @@ class PowerlinePrompt1(PowerlinePrompt):
|
|||||||
def set_p_str(self):
|
def set_p_str(self):
|
||||||
super(PowerlinePrompt1, self).set_p_str()
|
super(PowerlinePrompt1, self).set_p_str()
|
||||||
self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
|
self.nrspaces = len(self.rspace.search(self.p_str_nocolor).group())
|
||||||
self.prompt_text_len = len(self.p_str_nocolor) - self.nrspaces
|
self.prompt_text_len = self.powerline_prompt_width - self.nrspaces
|
||||||
self.powerline_last_in['nrspaces'] = self.nrspaces
|
self.powerline_last_in['nrspaces'] = self.nrspaces
|
||||||
self.powerline_last_in['prompt_text_len'] = self.prompt_text_len
|
self.powerline_last_in['prompt_text_len'] = self.prompt_text_len
|
||||||
|
|
||||||
|
@ -15,11 +15,15 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def construct_returned_value(rendered_highlighted, segments, output_raw):
|
def construct_returned_value(rendered_highlighted, segments, width, output_raw, output_width):
|
||||||
if output_raw:
|
if not (output_raw or output_width):
|
||||||
return rendered_highlighted, ''.join((segment['_rendered_raw'] for segment in segments))
|
|
||||||
else:
|
|
||||||
return rendered_highlighted
|
return rendered_highlighted
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
(rendered_highlighted,)
|
||||||
|
+ ((''.join((segment['_rendered_raw'] for segment in segments)),) if output_raw else ())
|
||||||
|
+ ((width,) if output_width else ())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Renderer(object):
|
class Renderer(object):
|
||||||
@ -188,7 +192,7 @@ class Renderer(object):
|
|||||||
for line in range(theme.get_line_number() - 1, 0, -1):
|
for line in range(theme.get_line_number() - 1, 0, -1):
|
||||||
yield self.render(side=None, line=line, **kwargs)
|
yield self.render(side=None, line=line, **kwargs)
|
||||||
|
|
||||||
def render(self, mode=None, width=None, side=None, line=0, output_raw=False, segment_info=None, matcher_info=None):
|
def render(self, mode=None, width=None, side=None, line=0, output_raw=False, output_width=False, segment_info=None, matcher_info=None):
|
||||||
'''Render all segments.
|
'''Render all segments.
|
||||||
|
|
||||||
When a width is provided, low-priority segments are dropped one at
|
When a width is provided, low-priority segments are dropped one at
|
||||||
@ -213,6 +217,11 @@ class Renderer(object):
|
|||||||
Changes the output: if this parameter is ``True`` then in place of
|
Changes the output: if this parameter is ``True`` then in place of
|
||||||
one string this method outputs a pair ``(colored_string,
|
one string this method outputs a pair ``(colored_string,
|
||||||
colorless_string)``.
|
colorless_string)``.
|
||||||
|
:param bool output_width:
|
||||||
|
Changes the output: if this parameter is ``True`` then in place of
|
||||||
|
one string this method outputs a pair ``(colored_string,
|
||||||
|
string_width)``. Returns a three-tuple if ``output_raw`` is also
|
||||||
|
``True``: ``(colored_string, colorless_string, string_width)``.
|
||||||
:param dict segment_info:
|
:param dict segment_info:
|
||||||
Segment information. See also ``.get_segment_info()`` method.
|
Segment information. See also ``.get_segment_info()`` method.
|
||||||
:param matcher_info:
|
:param matcher_info:
|
||||||
@ -225,11 +234,24 @@ class Renderer(object):
|
|||||||
side=side,
|
side=side,
|
||||||
line=line,
|
line=line,
|
||||||
output_raw=output_raw,
|
output_raw=output_raw,
|
||||||
|
output_width=output_width,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
theme=theme,
|
theme=theme,
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_render(self, mode, width, side, line, output_raw, segment_info, theme):
|
def compute_divider_widths(self, theme):
|
||||||
|
return {
|
||||||
|
'left': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('left', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('left', 'soft')),
|
||||||
|
},
|
||||||
|
'right': {
|
||||||
|
'hard': self.strwidth(theme.get_divider('right', 'hard')),
|
||||||
|
'soft': self.strwidth(theme.get_divider('right', 'soft')),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def do_render(self, mode, width, side, line, output_raw, output_width, segment_info, theme):
|
||||||
'''Like Renderer.render(), but accept theme in place of matcher_info
|
'''Like Renderer.render(), but accept theme in place of matcher_info
|
||||||
'''
|
'''
|
||||||
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
||||||
@ -246,35 +268,36 @@ class Renderer(object):
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
current_width = 0
|
||||||
|
|
||||||
if not width:
|
if not width:
|
||||||
# No width specified, so we don't need to crop or pad anything
|
# No width specified, so we don't need to crop or pad anything
|
||||||
|
if output_width:
|
||||||
|
current_width = self._render_length(theme, segments, self.compute_divider_widths(theme))
|
||||||
return construct_returned_value(''.join([
|
return construct_returned_value(''.join([
|
||||||
segment['_rendered_hl']
|
segment['_rendered_hl']
|
||||||
for segment in self._render_segments(theme, segments)
|
for segment in self._render_segments(theme, segments)
|
||||||
]) + self.hlstyle(), segments, output_raw)
|
]) + self.hlstyle(), segments, current_width, output_raw, output_width)
|
||||||
|
|
||||||
divider_lengths = {
|
divider_widths = self.compute_divider_widths(theme)
|
||||||
'left': {
|
|
||||||
'hard': self.strwidth(theme.get_divider('left', 'hard')),
|
|
||||||
'soft': self.strwidth(theme.get_divider('left', 'soft')),
|
|
||||||
},
|
|
||||||
'right': {
|
|
||||||
'hard': self.strwidth(theme.get_divider('right', 'hard')),
|
|
||||||
'soft': self.strwidth(theme.get_divider('right', 'soft')),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create an ordered list of segments that can be dropped
|
# 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)
|
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:
|
for segment in segments_priority:
|
||||||
if self._render_length(theme, segments, divider_lengths) <= width:
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
if current_width <= width:
|
||||||
break
|
break
|
||||||
segments.remove(segment)
|
segments.remove(segment)
|
||||||
|
|
||||||
# Distribute the remaining space on spacer segments
|
# Distribute the remaining space on spacer segments
|
||||||
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
segments_spacers = [segment for segment in segments if segment['width'] == 'auto']
|
||||||
if segments_spacers:
|
if segments_spacers:
|
||||||
distribute_len, distribute_len_remainder = divmod(width - sum([segment['_len'] for segment in segments]), len(segments_spacers))
|
if not segments_priority:
|
||||||
|
# Update segment['_len'] and current_width if not already done
|
||||||
|
# (is not done in shells where there is nothing to remove
|
||||||
|
# because “priority” key is not specified)
|
||||||
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
distribute_len, distribute_len_remainder = divmod(width - current_width, len(segments_spacers))
|
||||||
for segment in segments_spacers:
|
for segment in segments_spacers:
|
||||||
if segment['align'] == 'l':
|
if segment['align'] == 'l':
|
||||||
segment['_space_right'] += distribute_len
|
segment['_space_right'] += distribute_len
|
||||||
@ -285,12 +308,17 @@ class Renderer(object):
|
|||||||
segment['_space_left'] += space_side + space_side_remainder
|
segment['_space_left'] += space_side + space_side_remainder
|
||||||
segment['_space_right'] += space_side
|
segment['_space_right'] += space_side
|
||||||
segments_spacers[0]['_space_right'] += distribute_len_remainder
|
segments_spacers[0]['_space_right'] += distribute_len_remainder
|
||||||
|
# `_len` key is not needed anymore, but current_width should have an
|
||||||
|
# actual value for various bindings.
|
||||||
|
current_width = width
|
||||||
|
elif output_width:
|
||||||
|
current_width = self._render_length(theme, segments, divider_widths)
|
||||||
|
|
||||||
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
rendered_highlighted = ''.join([segment['_rendered_hl'] for segment in self._render_segments(theme, segments)]) + self.hlstyle()
|
||||||
|
|
||||||
return construct_returned_value(rendered_highlighted, segments, output_raw)
|
return construct_returned_value(rendered_highlighted, segments, current_width, output_raw, output_width)
|
||||||
|
|
||||||
def _render_length(self, theme, segments, divider_lengths):
|
def _render_length(self, theme, segments, divider_widths):
|
||||||
'''Update segments lengths and return them
|
'''Update segments lengths and return them
|
||||||
'''
|
'''
|
||||||
segments_len = len(segments)
|
segments_len = len(segments)
|
||||||
@ -316,7 +344,7 @@ class Renderer(object):
|
|||||||
draw_divider = segment['draw_' + divider_type + '_divider']
|
draw_divider = segment['draw_' + divider_type + '_divider']
|
||||||
segment_len += segment['_space_left'] + segment['_space_right'] + outer_padding
|
segment_len += segment['_space_left'] + segment['_space_right'] + outer_padding
|
||||||
if draw_divider:
|
if draw_divider:
|
||||||
segment_len += divider_lengths[side][divider_type] + divider_spaces
|
segment_len += divider_widths[side][divider_type] + divider_spaces
|
||||||
|
|
||||||
segment['_len'] = segment_len
|
segment['_len'] = segment_len
|
||||||
ret += segment_len
|
ret += segment_len
|
||||||
|
@ -32,5 +32,9 @@ class IpythonRenderer(ShellRenderer):
|
|||||||
if 'theme' in match:
|
if 'theme' in match:
|
||||||
match['theme'].shutdown()
|
match['theme'].shutdown()
|
||||||
|
|
||||||
|
def render(self, *args, **kwargs):
|
||||||
|
# XXX super(ShellRenderer), *not* super(IpythonRenderer)
|
||||||
|
return super(ShellRenderer, self).render(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
renderer = IpythonRenderer
|
renderer = IpythonRenderer
|
||||||
|
@ -34,22 +34,22 @@ class ShellRenderer(Renderer):
|
|||||||
width = kwargs.pop('width', None)
|
width = kwargs.pop('width', None)
|
||||||
local_theme = segment_info.get('local_theme')
|
local_theme = segment_info.get('local_theme')
|
||||||
if client_id and local_theme:
|
if client_id and local_theme:
|
||||||
output_raw = False
|
output_width = False
|
||||||
try:
|
try:
|
||||||
width = self.old_widths[key]
|
width = self.old_widths[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
output_raw = True
|
output_width = True
|
||||||
ret = super(ShellRenderer, self).render(
|
ret = super(ShellRenderer, self).render(
|
||||||
output_raw=output_raw,
|
output_width=output_width,
|
||||||
width=width,
|
width=width,
|
||||||
matcher_info=local_theme,
|
matcher_info=local_theme,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
*args, **kwargs
|
*args, **kwargs
|
||||||
)
|
)
|
||||||
if output_raw:
|
if output_width:
|
||||||
self.old_widths[key] = len(ret[1])
|
self.old_widths[key] = ret[1]
|
||||||
ret = ret[0]
|
ret = ret[0]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user