# 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 reasons: `--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 sought 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)