Add support for above lines as described in #462
Support is not mirrored in shell bindings yet
This commit is contained in:
parent
a65ea01d38
commit
61006d8fe1
|
@ -413,6 +413,25 @@ class Powerline(object):
|
||||||
pass
|
pass
|
||||||
return FailedUnicode(safe_unicode(e))
|
return FailedUnicode(safe_unicode(e))
|
||||||
|
|
||||||
|
def render_above_lines(self, *args, **kwargs):
|
||||||
|
'''Like .render(), but for ``self.renderer.render_above_lines()``
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
self.update_renderer()
|
||||||
|
for line in self.renderer.render_above_lines(*args, **kwargs):
|
||||||
|
yield line
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
self.exception('Failed to render: {0}', str(e))
|
||||||
|
except Exception as e:
|
||||||
|
# Updates e variable to new value, masking previous one.
|
||||||
|
# Normally it is the same exception (due to raise in case pl is
|
||||||
|
# unset), but it may also show error in logger. Note that latter
|
||||||
|
# is not logged by logger for obvious reasons, thus this also
|
||||||
|
# prevents us from seeing logger traceback.
|
||||||
|
pass
|
||||||
|
yield FailedUnicode(safe_unicode(e))
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
'''Shut down all background threads. Must be run only prior to exiting
|
'''Shut down all background threads. Must be run only prior to exiting
|
||||||
current application.
|
current application.
|
||||||
|
|
|
@ -175,7 +175,20 @@ class Renderer(object):
|
||||||
r['getcwd'] = lambda: r['environ']['PWD']
|
r['getcwd'] = lambda: r['environ']['PWD']
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def render(self, mode=None, width=None, side=None, output_raw=False, segment_info=None, matcher_info=None):
|
def render_above_lines(self, **kwargs):
|
||||||
|
'''Render all segments in the {theme}/segments/above list
|
||||||
|
|
||||||
|
Rendering happens in the reversed order. Parameters are the same as in
|
||||||
|
.render() method.
|
||||||
|
|
||||||
|
:yield: rendered line.
|
||||||
|
'''
|
||||||
|
|
||||||
|
theme = self.get_theme(kwargs.get('matcher_info', None))
|
||||||
|
for line in range(theme.get_line_number() - 1, 0, -1):
|
||||||
|
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):
|
||||||
'''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
|
||||||
|
@ -193,6 +206,9 @@ class Renderer(object):
|
||||||
:param str side:
|
:param str side:
|
||||||
One of ``left``, ``right``. Determines which side will be rendered.
|
One of ``left``, ``right``. Determines which side will be rendered.
|
||||||
If not present all sides are rendered.
|
If not present all sides are rendered.
|
||||||
|
:param int line:
|
||||||
|
Line number for which segments should be obtained. Is counted from
|
||||||
|
zero (botmost line).
|
||||||
:param bool output_raw:
|
:param bool output_raw:
|
||||||
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,
|
||||||
|
@ -203,7 +219,7 @@ class Renderer(object):
|
||||||
Matcher information. Is processed in ``.get_theme()`` method.
|
Matcher information. Is processed in ``.get_theme()`` method.
|
||||||
'''
|
'''
|
||||||
theme = self.get_theme(matcher_info)
|
theme = self.get_theme(matcher_info)
|
||||||
segments = theme.get_segments(side, self.get_segment_info(segment_info, mode))
|
segments = theme.get_segments(side, line, self.get_segment_info(segment_info, mode))
|
||||||
|
|
||||||
# Handle excluded/included segments for the current mode
|
# Handle excluded/included segments for the current mode
|
||||||
segments = [self._get_highlighting(segment, mode) for segment in segments
|
segments = [self._get_highlighting(segment, mode) for segment in segments
|
||||||
|
|
|
@ -51,7 +51,7 @@ def get_argparser(parser=None, *args, **kwargs):
|
||||||
parser = argparse.ArgumentParser
|
parser = argparse.ArgumentParser
|
||||||
p = parser(*args, **kwargs)
|
p = parser(*args, **kwargs)
|
||||||
p.add_argument('ext', nargs=1)
|
p.add_argument('ext', nargs=1)
|
||||||
p.add_argument('side', nargs='?', choices=('left', 'right'))
|
p.add_argument('side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'))
|
||||||
p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
p.add_argument('-r', '--renderer_module', metavar='MODULE', type=str)
|
||||||
p.add_argument('-w', '--width', type=int)
|
p.add_argument('-w', '--width', type=int)
|
||||||
p.add_argument('--last_exit_code', metavar='INT', type=int)
|
p.add_argument('--last_exit_code', metavar='INT', type=int)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
from powerline.segment import gen_segment_getter
|
from powerline.segment import gen_segment_getter
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
def requires_segment_info(func):
|
def requires_segment_info(func):
|
||||||
|
@ -9,6 +10,13 @@ def requires_segment_info(func):
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
def new_empty_segment_line():
|
||||||
|
return {
|
||||||
|
'left': [],
|
||||||
|
'right': []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Theme(object):
|
class Theme(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
ext,
|
ext,
|
||||||
|
@ -20,10 +28,7 @@ class Theme(object):
|
||||||
shutdown_event=None):
|
shutdown_event=None):
|
||||||
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
self.dividers = theme_config.get('dividers', common_config['dividers'])
|
||||||
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
self.spaces = theme_config.get('spaces', common_config['spaces'])
|
||||||
self.segments = {
|
self.segments = []
|
||||||
'left': [],
|
|
||||||
'right': [],
|
|
||||||
}
|
|
||||||
self.EMPTY_SEGMENT = {
|
self.EMPTY_SEGMENT = {
|
||||||
'contents': None,
|
'contents': None,
|
||||||
'highlight': {'fg': False, 'bg': False, 'attr': 0}
|
'highlight': {'fg': False, 'bg': False, 'attr': 0}
|
||||||
|
@ -33,25 +38,29 @@ class Theme(object):
|
||||||
if top_theme_config:
|
if top_theme_config:
|
||||||
theme_configs.append(top_theme_config)
|
theme_configs.append(top_theme_config)
|
||||||
get_segment = gen_segment_getter(pl, ext, common_config['paths'], theme_configs, theme_config.get('default_module'))
|
get_segment = gen_segment_getter(pl, ext, common_config['paths'], theme_configs, theme_config.get('default_module'))
|
||||||
for side in ['left', 'right']:
|
for segdict in itertools.chain((theme_config['segments'],),
|
||||||
for segment in theme_config['segments'].get(side, []):
|
theme_config['segments'].get('above', ())):
|
||||||
segment = get_segment(segment, side)
|
self.segments.append(new_empty_segment_line())
|
||||||
if not run_once:
|
for side in ['left', 'right']:
|
||||||
if segment['startup']:
|
for segment in segdict.get(side, []):
|
||||||
try:
|
segment = get_segment(segment, side)
|
||||||
segment['startup'](pl, shutdown_event)
|
if not run_once:
|
||||||
except Exception as e:
|
if segment['startup']:
|
||||||
pl.error('Exception during {0} startup: {1}', segment['name'], str(e))
|
try:
|
||||||
continue
|
segment['startup'](pl, shutdown_event)
|
||||||
self.segments[side].append(segment)
|
except Exception as e:
|
||||||
|
pl.error('Exception during {0} startup: {1}', segment['name'], str(e))
|
||||||
|
continue
|
||||||
|
self.segments[-1][side].append(segment)
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
for segments in self.segments.values():
|
for line in self.segments:
|
||||||
for segment in segments:
|
for segments in line.values():
|
||||||
try:
|
for segment in segments:
|
||||||
segment['shutdown']()
|
try:
|
||||||
except TypeError:
|
segment['shutdown']()
|
||||||
pass
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def get_divider(self, side='left', type='soft'):
|
def get_divider(self, side='left', type='soft'):
|
||||||
'''Return segment divider.'''
|
'''Return segment divider.'''
|
||||||
|
@ -60,15 +69,22 @@ class Theme(object):
|
||||||
def get_spaces(self):
|
def get_spaces(self):
|
||||||
return self.spaces
|
return self.spaces
|
||||||
|
|
||||||
def get_segments(self, side=None, segment_info=None):
|
def get_line_number(self):
|
||||||
|
return len(self.segments)
|
||||||
|
|
||||||
|
def get_segments(self, side=None, line=0, segment_info=None):
|
||||||
'''Return all segments.
|
'''Return all segments.
|
||||||
|
|
||||||
Function segments are called, and all segments get their before/after
|
Function segments are called, and all segments get their before/after
|
||||||
and ljust/rjust properties applied.
|
and ljust/rjust properties applied.
|
||||||
|
|
||||||
|
:param int line:
|
||||||
|
Line number for which segments should be obtained. Is counted from
|
||||||
|
zero (botmost line).
|
||||||
'''
|
'''
|
||||||
for side in [side] if side else ['left', 'right']:
|
for side in [side] if side else ['left', 'right']:
|
||||||
parsed_segments = []
|
parsed_segments = []
|
||||||
for segment in self.segments[side]:
|
for segment in self.segments[line][side]:
|
||||||
if segment['type'] == 'function':
|
if segment['type'] == 'function':
|
||||||
self.pl.prefix = segment['name']
|
self.pl.prefix = segment['name']
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -10,6 +10,12 @@ except ImportError:
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
|
||||||
from powerline.shell import ShellPowerline, get_argparser, finish_args # NOQA
|
from powerline.shell import ShellPowerline, get_argparser, finish_args # NOQA
|
||||||
|
|
||||||
|
def write(output):
|
||||||
|
try:
|
||||||
|
sys.stdout.write(output)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
sys.stdout.write(output.encode('utf-8'))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = get_argparser(description=__doc__).parse_args()
|
args = get_argparser(description=__doc__).parse_args()
|
||||||
finish_args(args)
|
finish_args(args)
|
||||||
|
@ -17,13 +23,21 @@ if __name__ == '__main__':
|
||||||
segment_info = {'args': args, 'environ': os.environ}
|
segment_info = {'args': args, 'environ': os.environ}
|
||||||
if args.renderer_arg:
|
if args.renderer_arg:
|
||||||
segment_info.update(args.renderer_arg)
|
segment_info.update(args.renderer_arg)
|
||||||
rendered = powerline.render(
|
if args.side.startswith('above'):
|
||||||
width=args.width,
|
for line in powerline.render_above_lines(
|
||||||
side=args.side,
|
width=args.width,
|
||||||
segment_info=segment_info,
|
segment_info=segment_info,
|
||||||
mode=os.environ.get('_POWERLINE_MODE'),
|
mode=os.environ.get('_POWERLINE_MODE'),
|
||||||
)
|
):
|
||||||
try:
|
write(line)
|
||||||
sys.stdout.write(rendered)
|
sys.stdout.write('\n')
|
||||||
except UnicodeEncodeError:
|
args.side = args.side[len('above'):]
|
||||||
sys.stdout.write(rendered.encode('utf-8'))
|
|
||||||
|
if args.side:
|
||||||
|
rendered = powerline.render(
|
||||||
|
width=args.width,
|
||||||
|
side=args.side,
|
||||||
|
segment_info=segment_info,
|
||||||
|
mode=os.environ.get('_POWERLINE_MODE'),
|
||||||
|
)
|
||||||
|
write(rendered)
|
||||||
|
|
Loading…
Reference in New Issue