191 lines
6.9 KiB
Python
191 lines
6.9 KiB
Python
# vim:fileencoding=utf-8:noet
|
|
# WARNING: using unicode_literals causes errors in argparse
|
|
from __future__ import (division, absolute_import, print_function)
|
|
|
|
import argparse
|
|
import sys
|
|
|
|
from itertools import chain
|
|
|
|
from powerline.lib.overrides import parsedotval, parse_override_var
|
|
from powerline.lib.dict import mergeargs
|
|
from powerline.lib.encoding import get_preferred_arguments_encoding
|
|
from powerline.lib.unicode import u, unicode
|
|
from powerline.bindings.wm import wm_threads
|
|
|
|
|
|
if sys.version_info < (3,):
|
|
encoding = get_preferred_arguments_encoding()
|
|
|
|
def arg_to_unicode(s):
|
|
return unicode(s, encoding, 'replace') if not isinstance(s, unicode) else s # NOQA
|
|
else:
|
|
def arg_to_unicode(s):
|
|
return s
|
|
|
|
|
|
def finish_args(parser, environ, args, is_daemon=False):
|
|
'''Do some final transformations
|
|
|
|
Transforms ``*_override`` arguments into dictionaries, adding overrides from
|
|
environment variables. Transforms ``renderer_arg`` argument into dictionary
|
|
as well, but only if it is true.
|
|
|
|
:param dict environ:
|
|
Environment from which additional overrides should be taken from.
|
|
:param args:
|
|
Arguments object returned by
|
|
:py:meth:`argparse.ArgumentParser.parse_args`. Will be modified
|
|
in-place.
|
|
|
|
:return: Object received as second (``args``) argument.
|
|
'''
|
|
args.config_override = mergeargs(chain(
|
|
parse_override_var(environ.get('POWERLINE_CONFIG_OVERRIDES', '')),
|
|
(parsedotval(v) for v in args.config_override or ()),
|
|
))
|
|
args.theme_override = mergeargs(chain(
|
|
parse_override_var(environ.get('POWERLINE_THEME_OVERRIDES', '')),
|
|
(parsedotval(v) for v in args.theme_override or ()),
|
|
))
|
|
if args.renderer_arg:
|
|
args.renderer_arg = mergeargs((parsedotval(v) for v in args.renderer_arg), remove=True)
|
|
if 'pane_id' in args.renderer_arg:
|
|
if isinstance(args.renderer_arg['pane_id'], (bytes, unicode)):
|
|
try:
|
|
args.renderer_arg['pane_id'] = int(args.renderer_arg['pane_id'].lstrip(' %'))
|
|
except ValueError:
|
|
pass
|
|
if 'client_id' not in args.renderer_arg:
|
|
args.renderer_arg['client_id'] = args.renderer_arg['pane_id']
|
|
args.config_path = (
|
|
[path for path in environ.get('POWERLINE_CONFIG_PATHS', '').split(':') if path]
|
|
+ (args.config_path or [])
|
|
)
|
|
if args.ext[0].startswith('wm.'):
|
|
if not is_daemon:
|
|
parser.error('WM bindings must be used with daemon only')
|
|
elif args.ext[0][3:] not in wm_threads:
|
|
parser.error('WM binding not found')
|
|
elif not args.side:
|
|
parser.error('expected one argument')
|
|
return args
|
|
|
|
|
|
def int_or_sig(s):
|
|
if s.startswith('sig'):
|
|
return u(s)
|
|
else:
|
|
return int(s)
|
|
|
|
|
|
def get_argparser(ArgumentParser=argparse.ArgumentParser):
|
|
parser = ArgumentParser(description='Powerline prompt and statusline script.')
|
|
parser.add_argument(
|
|
'ext', nargs=1,
|
|
help='Extension: application for which powerline command is launched '
|
|
'(usually `shell\' or `tmux\'). Also supports `wm.\' extensions: '
|
|
+ ', '.join(('`wm.' + key + '\'' for key in wm_threads.keys())) + '.'
|
|
)
|
|
parser.add_argument(
|
|
'side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'),
|
|
help='Side: `left\' and `right\' represent left and right side '
|
|
'respectively, `above\' emits lines that are supposed to be printed '
|
|
'just above the prompt and `aboveleft\' is like concatenating '
|
|
'`above\' with `left\' with the exception that only one Python '
|
|
'instance is used in this case. May be omitted for `wm.*\' extensions.'
|
|
)
|
|
parser.add_argument(
|
|
'-r', '--renderer-module', metavar='MODULE', type=str,
|
|
help='Renderer module. Usually something like `.bash\' or `.zsh\' '
|
|
'(with leading dot) which is `powerline.renderers.{ext}{MODULE}\', '
|
|
'may also be full module name (must contain at least one dot or '
|
|
'end with a dot in case it is top-level module) or '
|
|
'`powerline.renderers\' submodule (in case there are no dots).'
|
|
)
|
|
parser.add_argument(
|
|
'-w', '--width', type=int,
|
|
help='Maximum prompt with. Triggers truncation of some segments.'
|
|
)
|
|
parser.add_argument(
|
|
'--last-exit-code', metavar='INT', type=int_or_sig,
|
|
help='Last exit code.'
|
|
)
|
|
parser.add_argument(
|
|
'--last-pipe-status', metavar='LIST', default='',
|
|
type=lambda s: [int_or_sig(status) for status in s.split()],
|
|
help='Like above, but is supposed to contain space-separated array '
|
|
'of statuses, representing exit statuses of commands in one pipe.'
|
|
)
|
|
parser.add_argument(
|
|
'--jobnum', metavar='INT', type=int,
|
|
help='Number of jobs.'
|
|
)
|
|
parser.add_argument(
|
|
'-c', '--config-override', metavar='KEY.KEY=VALUE', type=arg_to_unicode,
|
|
action='append',
|
|
help='Configuration overrides for `config.json\'. Is translated to a '
|
|
'dictionary and merged with the dictionary obtained from actual '
|
|
'JSON configuration: KEY.KEY=VALUE is translated to '
|
|
'`{"KEY": {"KEY": VALUE}}\' and then merged recursively. '
|
|
'VALUE may be any JSON value, values that are not '
|
|
'`null\', `true\', `false\', start with digit, `{\', `[\' '
|
|
'are treated like strings. If VALUE is omitted '
|
|
'then corresponding key is removed.'
|
|
)
|
|
parser.add_argument(
|
|
'-t', '--theme-override', metavar='THEME.KEY.KEY=VALUE', type=arg_to_unicode,
|
|
action='append',
|
|
help='Like above, but theme-specific. THEME should point to '
|
|
'an existing and used theme to have any effect, but it is fine '
|
|
'to use any theme here.'
|
|
)
|
|
parser.add_argument(
|
|
'-R', '--renderer-arg',
|
|
metavar='KEY=VAL', type=arg_to_unicode, action='append',
|
|
help='Like above, but provides argument for renderer. Is supposed '
|
|
'to be used only by shell bindings to provide various data like '
|
|
'last-exit-code or last-pipe-status (they are not using '
|
|
'`--renderer-arg\' for historical resons: `--renderer-arg\' '
|
|
'was added later).'
|
|
)
|
|
parser.add_argument(
|
|
'-p', '--config-path', action='append', metavar='PATH',
|
|
help='Path to configuration directory. If it is present then '
|
|
'configuration files will only be seeked in the provided path. '
|
|
'May be provided multiple times to search in a list of directories.'
|
|
)
|
|
parser.add_argument(
|
|
'--socket', metavar='ADDRESS', type=str,
|
|
help='Socket address to use in daemon clients. Is always UNIX domain '
|
|
'socket on linux and file socket on Mac OS X. Not used here, '
|
|
'present only for compatibility with other powerline clients. '
|
|
'This argument must always be the first one and be in a form '
|
|
'`--socket ADDRESS\': no `=\' or short form allowed '
|
|
'(in other powerline clients, not here).'
|
|
)
|
|
return parser
|
|
|
|
|
|
def write_output(args, powerline, segment_info, write):
|
|
if args.renderer_arg:
|
|
segment_info.update(args.renderer_arg)
|
|
if args.side.startswith('above'):
|
|
for line in powerline.render_above_lines(
|
|
width=args.width,
|
|
segment_info=segment_info,
|
|
mode=segment_info.get('mode', None),
|
|
):
|
|
if line:
|
|
write(line + '\n')
|
|
args.side = args.side[len('above'):]
|
|
|
|
if args.side:
|
|
rendered = powerline.render(
|
|
width=args.width,
|
|
side=args.side,
|
|
segment_info=segment_info,
|
|
mode=segment_info.get('mode', None),
|
|
)
|
|
write(rendered)
|