0
0
.dotfiles/powerline-bin/powerline/renderers/shell/__init__.py

183 lines
5.1 KiB
Python
Raw Normal View History

2024-09-07 11:49:53 -04:00
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderer import Renderer
from powerline.theme import Theme
from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE
def int_to_rgb(num):
r = (num >> 16) & 0xff
g = (num >> 8) & 0xff
b = num & 0xff
return r, g, b
class PromptRenderer(Renderer):
'''Powerline generic prompt segment renderer'''
def __init__(self, old_widths=None, **kwargs):
super(PromptRenderer, self).__init__(**kwargs)
self.old_widths = old_widths if old_widths is not None else {}
def get_client_id(self, segment_info):
'''Get client ID given segment info
This is used by daemon to correctly cache widths for different clients
using a single renderer instance.
:param dict segment_info:
:ref:`Segment info dictionary <dev-segments-info>`. Out of it only
``client_id`` key is used. It is OK for this dictionary to not
contain this key.
:return: Any hashable value or ``None``.
'''
return segment_info.get('client_id') if isinstance(segment_info, dict) else None
def do_render(self, output_width, segment_info, side, theme, width=None, **kwargs):
client_id = self.get_client_id(segment_info)
if client_id is not None:
local_key = (client_id, side, None if theme is self.theme else id(theme))
key = (client_id, side, None)
did_width = False
if local_key[-1] != key[-1] and side == 'left':
try:
width = self.old_widths[key]
except KeyError:
pass
else:
did_width = True
if not did_width and width is not None:
if theme.cursor_space_multiplier is not None:
width = int(width * theme.cursor_space_multiplier)
elif theme.cursor_columns:
width -= theme.cursor_columns
if side == 'right':
try:
width -= self.old_widths[(client_id, 'left', local_key[-1])]
except KeyError:
pass
res = super(PromptRenderer, self).do_render(
output_width=True,
width=width,
theme=theme,
segment_info=segment_info,
side=side,
**kwargs
)
if client_id is not None:
self.old_widths[local_key] = res[-1]
ret = res if output_width else res[:-1]
if len(ret) == 1:
return ret[0]
else:
return ret
class ShellRenderer(PromptRenderer):
'''Powerline shell segment renderer.'''
escape_hl_start = ''
escape_hl_end = ''
term_truecolor = False
term_escape_style = 'auto'
tmux_escape = False
screen_escape = False
character_translations = Renderer.character_translations.copy()
def render(self, segment_info, **kwargs):
local_theme = segment_info.get('local_theme')
return super(ShellRenderer, self).render(
matcher_info=local_theme,
segment_info=segment_info,
**kwargs
)
def do_render(self, segment_info, **kwargs):
if self.term_escape_style == 'auto':
if segment_info['environ'].get('TERM') == 'fbterm':
self.used_term_escape_style = 'fbterm'
else:
self.used_term_escape_style = 'xterm'
else:
self.used_term_escape_style = self.term_escape_style
return super(ShellRenderer, self).do_render(segment_info=segment_info, **kwargs)
def hlstyle(self, fg=None, bg=None, attrs=None):
'''Highlight a segment.
If an argument is None, the argument is ignored. If an argument is
False, the argument is reset to the terminal defaults. If an argument
is a valid color or attribute, its added to the ANSI escape code.
'''
ansi = [0]
is_fbterm = self.used_term_escape_style == 'fbterm'
term_truecolor = not is_fbterm and self.term_truecolor
if fg is not None:
if fg is False or fg[0] is False:
ansi += [39]
else:
if term_truecolor:
ansi += [38, 2] + list(int_to_rgb(fg[1]))
else:
ansi += [38, 5, fg[0]]
if bg is not None:
if bg is False or bg[0] is False:
ansi += [49]
else:
if term_truecolor:
ansi += [48, 2] + list(int_to_rgb(bg[1]))
else:
ansi += [48, 5, bg[0]]
if attrs is not None:
if attrs is False:
ansi += [22]
else:
if attrs & ATTR_BOLD:
ansi += [1]
elif attrs & ATTR_ITALIC:
# Note: is likely not to work or even be inverse in place of
# italic. Omit using this in colorschemes.
ansi += [3]
elif attrs & ATTR_UNDERLINE:
ansi += [4]
if is_fbterm:
r = []
while ansi:
cur_ansi = ansi.pop(0)
if cur_ansi == 38:
ansi.pop(0)
r.append('\033[1;{0}}}'.format(ansi.pop(0)))
elif cur_ansi == 48:
ansi.pop(0)
r.append('\033[2;{0}}}'.format(ansi.pop(0)))
else:
r.append('\033[{0}m'.format(cur_ansi))
r = ''.join(r)
else:
r = '\033[{0}m'.format(';'.join(str(attr) for attr in ansi))
if self.tmux_escape:
r = '\033Ptmux;' + r.replace('\033', '\033\033') + '\033\\'
elif self.screen_escape:
r = '\033P' + r.replace('\033', '\033\033') + '\033\\'
return self.escape_hl_start + r + self.escape_hl_end
def get_theme(self, matcher_info):
if not matcher_info:
return self.theme
match = self.local_themes[matcher_info]
try:
return match['theme']
except KeyError:
match['theme'] = Theme(
theme_config=match['config'],
main_theme_config=self.theme_config,
**self.theme_kwargs
)
return match['theme']
renderer = ShellRenderer