def player_dbus(self, player_name, bus_name, player_path, iface_prop, iface_player): try: import dbus except ImportError: pl.exception('Could not add {0} segment: requires dbus module', player_name) return bus = dbus.SessionBus() try: player = bus.get_object(bus_name, player_path) iface = dbus.Interface(player, iface_prop) info = iface.Get(iface_player, 'Metadata') status = iface.Get(iface_player, 'PlaybackStatus') except dbus.exceptions.DBusException: return if not info: return album = u(info.get('xesam:album')) title = u(info.get('xesam:title')) artist = info.get('xesam:artist') state = self._convert_state(status) if artist: artist = u(artist[0]) return { 'state': state, 'album': album, 'artist': artist, 'title': title, 'total': self._convert_seconds(info.get('mpris:length') / 1e6), }
def player_dbus(self, player_name, bus_name, player_path, iface_prop, iface_player): try: import dbus except ImportError: pl.exception('Could not add {0} segment: requires python-dbus', player_name) return bus = dbus.SessionBus() try: player = bus.get_object(bus_name, player_path) iface = dbus.Interface(player, iface_prop) info = iface.Get(iface_player, 'Metadata') status = iface.Get(iface_player, 'PlaybackStatus') except dbus.exceptions.DBusException: return if not info: return album = u(info.get('xesam:album')) title = u(info.get('xesam:title')) artist = info.get('xesam:artist') state = self._convert_state(status) if artist: artist = u(artist[0]) return { 'state': state, 'album': album, 'artist': artist, 'title': title, 'total': self._convert_seconds(info.get('mpris:length') / 1e6), }
def get_var_config(var): try: val = zsh.getvalue(var) if isinstance(val, dict): return mergeargs([parsedotval((u(k), u(v))) for k, v in val.items()]) elif isinstance(val, (unicode, str, bytes)): return mergeargs(parse_override_var(u(val))) else: return None except: return None
def cwd(pl, segment_info, dir_shorten_len=None, dir_limit_depth=None, use_path_separator=False): """Return the current working directory. Returns a segment list to create a breadcrumb-like effect. :param int dir_shorten_len: shorten parent directory names to this length (e.g. :file:`/long/path/to/powerline` → :file:`/l/p/t/powerline`) :param int dir_limit_depth: limit directory depth to this number (e.g. :file:`/long/path/to/powerline` → :file:`⋯/to/powerline`) :param bool use_path_separator: Use path separator in place of soft divider. Divider highlight group used: ``cwd:divider``. Highlight groups used: ``cwd:current_folder`` or ``cwd``. It is recommended to define all highlight groups. """ try: cwd = u(segment_info["getcwd"]()) except OSError as e: if e.errno == 2: # user most probably deleted the directory # this happens when removing files from Mercurial repos for example pl.warn("Current directory not found") cwd = "[not found]" else: raise home = segment_info["home"] if home: home = u(home) cwd = re.sub("^" + re.escape(home), "~", cwd, 1) cwd_split = cwd.split(os.sep) cwd_split_len = len(cwd_split) cwd = [i[0:dir_shorten_len] if dir_shorten_len and i else i for i in cwd_split[:-1]] + [cwd_split[-1]] if dir_limit_depth and cwd_split_len > dir_limit_depth + 1: del (cwd[0:-dir_limit_depth]) cwd.insert(0, "⋯") ret = [] if not cwd[0]: cwd[0] = "/" draw_inner_divider = not use_path_separator for part in cwd: if not part: continue if use_path_separator: part += os.sep ret.append( {"contents": part, "divider_highlight_group": "cwd:divider", "draw_inner_divider": draw_inner_divider} ) ret[-1]["highlight_group"] = ["cwd:current_folder", "cwd"] if use_path_separator: ret[-1]["contents"] = ret[-1]["contents"][:-1] if len(ret) > 1 and ret[0]["contents"][0] == os.sep: ret[0]["contents"] = ret[0]["contents"][1:] return ret
def get_segments(self, side=None, line=0, segment_info=None, mode=None): '''Return all segments. Function segments are called, and all segments get their before/after 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']: parsed_segments = [] for segment in self.segments[line][side]: # No segment-local modes at this point if mode not in segment['exclude_modes'] and ( not segment['include_modes'] or mode in segment['include_modes'] ): process_segment(self.pl, side, segment_info, parsed_segments, segment, mode) for segment in parsed_segments: segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after'] # Align segment contents if segment['width'] and segment['width'] != 'auto': if segment['align'] == 'l': segment['contents'] = segment['contents'].ljust(segment['width']) elif segment['align'] == 'r': segment['contents'] = segment['contents'].rjust(segment['width']) elif segment['align'] == 'c': segment['contents'] = segment['contents'].center(segment['width']) # We need to yield a copy of the segment, or else mode-dependent # segment contents can't be cached correctly e.g. when caching # non-current window contents for vim statuslines yield segment.copy()
def f(*args, **kwargs): from powerline.lib.unicode import u ret = func(*args, **kwargs) if isinstance(ret, bytes): ret = u(ret) return ret
def test_expected_result(p, test, last_attempt, last_attempt_cb, attempts): expected_text, attrs = test['expected_result'] result = None while attempts: actual_text, all_attrs = p.get_row(test['row'], attrs) if actual_text == expected_text: return True attempts -= 1 print('Actual result does not match expected. Attempts left: {0}.'. format(attempts)) sleep(2) print('Result:') print(actual_text) print('Expected:') print(expected_text) print('Attributes:') print(all_attrs) print('Screen:') screen, screen_attrs = p.get_screen(attrs) print(screen) print(screen_attrs) print('_' * 80) print('Diff:') print('=' * 80) print(''.join( (u(line) for line in ndiff([actual_text + '\n'], [expected_text + '\n'])))) if last_attempt and last_attempt_cb: last_attempt_cb() return False
def test_expected_result(p, test, last_attempt, last_attempt_cb, attempts): expected_text, attrs = test['expected_result'] result = None while attempts: actual_text, all_attrs = p.get_row(test['row'], attrs) if actual_text == expected_text: return True attempts -= 1 print('Actual result does not match expected. Attempts left: {0}.'.format(attempts)) sleep(2) print('Result:') print(actual_text) print('Expected:') print(expected_text) print('Attributes:') print(all_attrs) print('Screen:') screen, screen_attrs = p.get_screen(attrs) print(screen) print(screen_attrs) print('_' * 80) print('Diff:') print('=' * 80) print(''.join(( u(line) for line in ndiff([actual_text + '\n'], [expected_text + '\n'])) )) if last_attempt and last_attempt_cb: last_attempt_cb() return False
def __str__(self): zsh.eval('_POWERLINE_PARSER_STATE="${(%):-%_}"') zsh.eval('_POWERLINE_SHORTENED_PATH="${(%):-%~}"') try: mode = u(zsh.getvalue('_POWERLINE_MODE')) except IndexError: mode = None try: default_mode = u(zsh.getvalue('_POWERLINE_DEFAULT_MODE')) except IndexError: default_mode = None segment_info = { 'args': self.args, 'environ': environ, 'client_id': 1, 'local_theme': self.theme, 'parser_state': zsh.getvalue('_POWERLINE_PARSER_STATE'), 'shortened_path': zsh.getvalue('_POWERLINE_SHORTENED_PATH'), 'mode': mode, 'default_mode': default_mode, } zsh.setvalue('_POWERLINE_PARSER_STATE', None) zsh.setvalue('_POWERLINE_SHORTENED_PATH', None) try: zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT') except IndexError: zle_rprompt_indent = 1 r = '' if self.above: for line in self.powerline.render_above_lines( width=zsh.columns() - zle_rprompt_indent, segment_info=segment_info, ): r += line + '\n' r += self.powerline.render( width=zsh.columns(), side=self.side, segment_info=segment_info, mode=mode, ) if type(r) is not str: if type(r) is bytes: return r.decode(get_preferred_output_encoding(), 'replace') else: return r.encode(get_preferred_output_encoding(), 'replace') return r
def __init__(self, ext, theme_config, common_config, pl, get_module_attr, top_theme, colorscheme, main_theme_config=None, run_once=False, shutdown_event=None): self.colorscheme = colorscheme self.dividers = theme_config['dividers'] self.dividers = dict(( (key, dict((k, u(v)) for k, v in val.items())) for key, val in self.dividers.items() )) try: self.cursor_space_multiplier = 1 - (theme_config['cursor_space'] / 100) except KeyError: self.cursor_space_multiplier = None self.cursor_columns = theme_config.get('cursor_columns') self.spaces = theme_config['spaces'] self.outer_padding = int(theme_config.get('outer_padding', 1)) self.segments = [] self.EMPTY_SEGMENT = { 'contents': None, 'highlight': {'fg': False, 'bg': False, 'attrs': 0} } self.pl = pl theme_configs = [theme_config] if main_theme_config: theme_configs.append(main_theme_config) get_segment = gen_segment_getter( pl, ext, common_config, theme_configs, theme_config.get('default_module'), get_module_attr, top_theme ) for segdict in itertools.chain((theme_config['segments'],), theme_config['segments'].get('above', ())): self.segments.append(new_empty_segment_line()) for side in ['left', 'right']: for segment in segdict.get(side, []): segment = get_segment(segment, side) if segment: if not run_once: if segment['startup']: try: segment['startup'](pl, shutdown_event) except Exception as e: pl.error('Exception during {0} startup: {1}', segment['name'], str(e)) continue self.segments[-1][side].append(segment)
def __str__(self): parser_state = u(zsh_expand('${(%):-%_}')) shortened_path = u(zsh_expand('${(%):-%~}')) try: mode = u(zsh.getvalue('_POWERLINE_MODE')) except IndexError: mode = None try: default_mode = u(zsh.getvalue('_POWERLINE_DEFAULT_MODE')) except IndexError: default_mode = None segment_info = { 'args': self.args, 'environ': environ, 'client_id': 1, 'local_theme': self.theme, 'parser_state': parser_state, 'shortened_path': shortened_path, 'mode': mode, 'default_mode': default_mode, } try: zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT') except IndexError: zle_rprompt_indent = 1 r = '' if self.above: for line in self.powerline.render_above_lines( width=zsh.columns() - zle_rprompt_indent, segment_info=segment_info, ): if line: r += line + '\n' r += self.powerline.render( width=zsh.columns(), side=self.side, segment_info=segment_info, mode=mode, ) if type(r) is not str: if type(r) is bytes: return r.decode(get_preferred_output_encoding(), 'replace') else: return r.encode(get_preferred_output_encoding(), 'replace') return r
def get_shortened_path(self, pl, segment_info, shorten_home=True, **kwargs): try: path = u(segment_info['getcwd']()) except OSError as e: if e.errno == 2: # user most probably deleted the directory # this happens when removing files from Mercurial repos for example pl.warn('Current directory not found') return "[not found]" else: raise if shorten_home: home = segment_info['home'] if home: home = u(home) if path.startswith(home): path = '~' + path[len(home):] return path
def get_segments(self, side=None, line=0, segment_info=None, mode=None): '''Return all segments. Function segments are called, and all segments get their before/after 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']: parsed_segments = [] for segment in self.segments[line][side]: if segment['display_condition'](self.pl, segment_info, mode): process_segment( self.pl, side, segment_info, parsed_segments, segment, mode, self.colorscheme, ) for segment in parsed_segments: self.pl.prefix = segment['name'] try: width = segment['width'] align = segment['align'] if width == 'auto' and segment['expand'] is None: segment['expand'] = expand_functions.get(align) if segment['expand'] is None: self.pl.error('Align argument must be “r”, “l” or “c”, not “{0}”', align) try: segment['contents'] = segment['before'] + u( segment['contents'] if segment['contents'] is not None else '' ) + segment['after'] except Exception as e: self.pl.exception('Failed to compute segment contents: {0}', str(e)) segment['contents'] = safe_unicode(segment.get('contents')) # Align segment contents if segment['width'] and segment['width'] != 'auto': if segment['align'] == 'l': segment['contents'] = segment['contents'].ljust(segment['width']) elif segment['align'] == 'r': segment['contents'] = segment['contents'].rjust(segment['width']) elif segment['align'] == 'c': segment['contents'] = segment['contents'].center(segment['width']) # We need to yield a copy of the segment, or else mode-dependent # segment contents can’t be cached correctly e.g. when caching # non-current window contents for vim statuslines yield segment.copy() except Exception as e: self.pl.exception('Failed to compute segment: {0}', str(e)) fallback = get_fallback_segment() fallback.update(side=side) yield fallback
def __init__(self, ext, theme_config, common_config, pl, get_module_attr, top_theme, colorscheme, main_theme_config=None, run_once=False, shutdown_event=None): self.colorscheme = colorscheme self.dividers = theme_config['dividers'] self.dividers = dict(( (key, dict((k, u(v)) for k, v in val.items())) for key, val in self.dividers.items() )) try: self.cursor_space_multiplier = 1 - (theme_config['cursor_space'] / 100) except KeyError: self.cursor_space_multiplier = None self.cursor_columns = theme_config.get('cursor_columns') self.spaces = theme_config['spaces'] self.segments = [] self.EMPTY_SEGMENT = { 'contents': None, 'highlight': {'fg': False, 'bg': False, 'attr': 0} } self.pl = pl theme_configs = [theme_config] if main_theme_config: theme_configs.append(main_theme_config) get_segment = gen_segment_getter( pl, ext, common_config, theme_configs, theme_config.get('default_module'), get_module_attr, top_theme ) for segdict in itertools.chain((theme_config['segments'],), theme_config['segments'].get('above', ())): self.segments.append(new_empty_segment_line()) for side in ['left', 'right']: for segment in segdict.get(side, []): segment = get_segment(segment, side) if segment: if not run_once: if segment['startup']: try: segment['startup'](pl, shutdown_event) except Exception as e: pl.error('Exception during {0} startup: {1}', segment['name'], str(e)) continue self.segments[-1][side].append(segment)
def test_expected_result(p, expected_result, cols, rows, print_logs): last_line = [] for col in range(cols): last_line.append(p[rows - 1, col]) attempts = 3 result = None while attempts: result = tuple(((key, ''.join((i.text for i in subline))) for key, subline in groupby( last_line, lambda i: i.cell_properties_key))) if result == expected_result: return True attempts -= 1 print('Actual result does not match expected. Attempts left: {0}.'. format(attempts)) sleep(2) print('Result:') shesc_result = ''.join( ('{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in result)) print(shesc_result) print(result) print('Expected:') shesc_expected_result = ''.join( ('{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in expected_result)) print(shesc_expected_result) p.send(b'powerline-config tmux setup\n') sleep(5) print('Screen:') screen = [] for i in range(rows): screen.append([]) for j in range(cols): screen[-1].append(p[i, j]) print('\n'.join(''.join(('{0}{1}\x1b[m'.format( cell_properties_key_to_shell_escape(i.cell_properties_key), i.text) for i in line)) for line in screen)) a = shesc_result.replace('\x1b', '\\e') + '\n' b = shesc_expected_result.replace('\x1b', '\\e') + '\n' print('_' * 80) print('Diff:') print('=' * 80) print(''.join((u(line) for line in ndiff([a], [b])))) if print_logs: for f in glob1(VTERM_TEST_DIR, '*.log'): print('_' * 80) print(os.path.basename(f) + ':') print('=' * 80) with open(f, 'r') as F: for line in F: sys.stdout.write(line) os.unlink(f) return False
def test_expected_result(p, expected_result, cols, rows): last_line = [] for col in range(cols): last_line.append(p[rows - 1, col]) attempts = 10 result = None while attempts: result = tuple(( (key, ''.join((i.text for i in subline))) for key, subline in groupby(last_line, lambda i: i.cell_properties_key) )) if result == expected_result: return True attempts -= 1 print('Actual result does not match expected. Attempts left: {0}.'.format(attempts)) sleep(2) print('Result:') shesc_result = ''.join(( '{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in result )) print(shesc_result) print('Expected:') shesc_expected_result = ''.join(( '{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in expected_result )) print(shesc_expected_result) p.send(b'powerline-config tmux setup\n') sleep(5) print('Screen:') screen = [] for i in range(rows): screen.append([]) for j in range(cols): screen[-1].append(p[i, j]) print('\n'.join( ''.join(( '{0}{1}\x1b[m'.format( cell_properties_key_to_shell_escape(i.cell_properties_key), i.text ) for i in line )) for line in screen )) a = shesc_result.replace('\x1b', '\\e') + '\n' b = shesc_expected_result.replace('\x1b', '\\e') + '\n' print('_' * 80) print('Diff:') print('=' * 80) print(''.join((u(line) for line in ndiff([a], [b])))) return False
def test_expected_result(p, test, last_attempt, last_attempt_cb, attempts): debugging_tests = not not os.environ.get('_POWERLINE_DEBUGGING_TESTS') expected_text, attrs = test['expected_result'] result = None while attempts: if 'row' in test: row = test['row'] else: row = p.dim.rows - 1 while row >= 0 and not p[row, 0].text: row -= 1 if row < 0: row = 0 actual_text, all_attrs = p.get_row(row, attrs) if actual_text == expected_text: return True attempts -= 1 print( 'Actual result does not match expected for row {0}. Attempts left: {1}.' .format(row, attempts)) sleep(2) print('Result (row {0}):'.format(row)) print(actual_text) print('Expected:') print(expected_text) print('Attributes:') for v, k in sorted( ((v, k) for k, v in all_attrs.items()), key=(lambda t: '%02u'.format(t[0]) if isinstance(t[0], int) else t[0]), ): print('{k!r}: {v!r},'.format(v=v, k=k)) print('Screen:') screen, screen_attrs = p.get_screen(attrs, use_escapes=debugging_tests) print(screen) print(screen_attrs) print('_' * 80) print('Diff:') print('=' * 80) print(''.join( (u(line) for line in ndiff([actual_text + '\n'], [expected_text + '\n'])))) if last_attempt and last_attempt_cb: last_attempt_cb() return False
def test_expected_result(p, test, last_attempt, last_attempt_cb, attempts): debugging_tests = not not os.environ.get('_POWERLINE_DEBUGGING_TESTS') expected_text, attrs = test['expected_result'] result = None while attempts: if 'row' in test: row = test['row'] else: row = p.dim.rows - 1 while row >= 0 and not p[row, 0].text: row -= 1 if row < 0: row = 0 actual_text, all_attrs = p.get_row(row, attrs) if actual_text == expected_text: return True attempts -= 1 print('Actual result does not match expected for row {0}. Attempts left: {1}.'.format( row, attempts)) sleep(2) print('Result (row {0}):'.format(row)) print(actual_text) print('Expected:') print(expected_text) print('Attributes:') for v, k in sorted( ((v, k) for k, v in all_attrs.items()), key=(lambda t: '%02u'.format(t[0]) if isinstance(t[0], int) else t[0]), ): print('{k!r}: {v!r},'.format(v=v, k=k)) print('Screen:') screen, screen_attrs = p.get_screen(attrs, use_escapes=debugging_tests) print(screen) print(screen_attrs) print('_' * 80) print('Diff:') print('=' * 80) print(''.join(( u(line) for line in ndiff([actual_text + '\n'], [expected_text + '\n'])) )) if last_attempt and last_attempt_cb: last_attempt_cb() return False
def parse_argument(*args, **kwargs): is_option = args[0].startswith('-') is_long_option = args[0].startswith('--') is_short_option = is_option and not is_long_option action = kwargs.get('action', 'store_true') multi = kwargs.get('action') in ('append',) nargs = kwargs.get('nargs') or (1 if kwargs.get('metavar') or action in ('append',) else 0) return Argument( names=args, help=u(kwargs.get('help', '')), choices=[str(choice) for choice in kwargs.get('choices', [])], metavar=kwargs.get('metavar') or args[-1].lstrip('-').replace('-', '_').upper(), required=kwargs.get('required', False) if is_option else ( kwargs.get('nargs') not in ('?',)), nargs=nargs, multi=multi, is_option=is_option, is_long_option=is_long_option, is_short_option=is_short_option, can_be_joined=(is_short_option and not multi and not nargs) )
def get_segments(self, side=None, line=0, segment_info=None, mode=None): '''Return all segments. Function segments are called, and all segments get their before/after 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']: parsed_segments = [] for segment in self.segments[line][side]: # No segment-local modes at this point if mode not in segment['exclude_modes'] and ( not segment['include_modes'] or mode in segment['include_modes']): process_segment(self.pl, side, segment_info, parsed_segments, segment, mode) for segment in parsed_segments: segment['contents'] = segment['before'] + u( segment['contents'] if segment['contents'] is not None else '') + segment['after'] # Align segment contents if segment['width'] and segment['width'] != 'auto': if segment['align'] == 'l': segment['contents'] = segment['contents'].ljust( segment['width']) elif segment['align'] == 'r': segment['contents'] = segment['contents'].rjust( segment['width']) elif segment['align'] == 'c': segment['contents'] = segment['contents'].center( segment['width']) # We need to yield a copy of the segment, or else mode-dependent # segment contents can't be cached correctly e.g. when caching # non-current window contents for vim statuslines yield segment.copy()
def int_or_sig(s): if s.startswith('sig'): return u(s) else: return int(s)
def get_segments(self, side=None, segment_info=None): '''Return all segments. Function segments are called, and all segments get their before/after and ljust/rjust properties applied. ''' for side in [side] if side else ['left', 'right']: parsed_segments = [] for segment in self.segments[side]: if segment['type'] == 'function': self.pl.prefix = segment['name'] try: contents = segment['contents_func'](self.pl, segment_info) except Exception as e: self.pl.exception('Exception while computing segment: {0}', str(e)) continue if contents is None: continue if isinstance(contents, list): segment_base = segment.copy() if contents: draw_divider_position = -1 if side == 'left' else 0 for key, i, newval in ( ('before', 0, ''), ('after', -1, ''), ('draw_soft_divider', draw_divider_position, True), ('draw_hard_divider', draw_divider_position, True), ): try: contents[i][key] = segment_base.pop(key) segment_base[key] = newval except KeyError: pass draw_inner_divider = None if side == 'right': append = parsed_segments.append else: pslen = len(parsed_segments) append = lambda item: parsed_segments.insert(pslen, item) for subsegment in (contents if side == 'right' else reversed(contents)): segment_copy = segment_base.copy() segment_copy.update(subsegment) if draw_inner_divider is not None: segment_copy['draw_soft_divider'] = draw_inner_divider draw_inner_divider = segment_copy.pop('draw_inner_divider', None) append(segment_copy) else: segment['contents'] = contents parsed_segments.append(segment) elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None): parsed_segments.append(segment) else: continue for segment in parsed_segments: segment['contents'] = segment['before'] + u(segment['contents'] if segment['contents'] is not None else '') + segment['after'] # Align segment contents if segment['width'] and segment['width'] != 'auto': if segment['align'] == 'l': segment['contents'] = segment['contents'].ljust(segment['width']) elif segment['align'] == 'r': segment['contents'] = segment['contents'].rjust(segment['width']) elif segment['align'] == 'c': segment['contents'] = segment['contents'].center(segment['width']) # We need to yield a copy of the segment, or else mode-dependent # segment contents can't be cached correctly e.g. when caching # non-current window contents for vim statuslines yield segment.copy()
def main(): VTERM_TEST_DIR = os.path.abspath('tests/vterm') vterm_path = os.path.join(VTERM_TEST_DIR, 'path') socket_path = os.path.join(VTERM_TEST_DIR, 'tmux-socket') rows = 50 cols = 200 tmux_exe = os.path.join(vterm_path, 'tmux') try: p = ExpectProcess( lib='tests/bot-ci/deps/libvterm/libvterm.so', rows=rows, cols=cols, cmd=tmux_exe, args=[ # Specify full path to tmux socket (testing tmux instance must # not interfere with user one) '-S', socket_path, # Force 256-color mode '-2', # Request verbose logging just in case '-v', # Specify configuration file '-f', os.path.abspath('powerline/bindings/tmux/powerline.conf'), # Run bash three times 'new-session', 'bash --norc --noprofile -i', ';', 'new-window', 'bash --norc --noprofile -i', ';', 'new-window', 'bash --norc --noprofile -i', ';', ], cwd=VTERM_TEST_DIR, env={ # Reasoning: # 1. vt* TERMs (used to be vt100 here) make tmux-1.9 use # different and identical colors for inactive windows. This # is not like tmux-1.6: foreground color is different from # separator color and equal to (0, 102, 153) for some reason # (separator has correct color). tmux-1.8 is fine, so are # older versions (though tmux-1.6 and tmux-1.7 do not have # highlighting for previously active window) and my system # tmux-1.9a. # 2. screen, xterm and some other non-256color terminals both # have the same issue and make libvterm emit complains like # `Unhandled CSI SGR 3231`. # 3. screen-256color, xterm-256color and other -256color # terminals make libvterm emit complains about unhandled # escapes to stderr. # 4. `st-256color` does not have any of the above problems, but # it may be not present on the target system because it is # installed with x11-terms/st and not with sys-libs/ncurses. # # For the given reasons decision was made: to fix tmux-1.9 tests # and not make libvterm emit any data to stderr st-256color # $TERM should be used, up until libvterm has its own terminfo # database entry (if it ever will). To make sure that relevant # terminfo entry is present on the target system it should be # distributed with powerline test package. To make distribution # not require modifying anything outside of powerline test # directory TERMINFO variable is set. 'TERMINFO': os.path.join(VTERM_TEST_DIR, 'terminfo'), 'TERM': 'st-256color', 'PATH': vterm_path, 'SHELL': os.path.join(''), 'POWERLINE_CONFIG_PATHS': os.path.abspath('powerline/config_files'), 'POWERLINE_COMMAND': 'powerline-render', 'POWERLINE_THEME_OVERRIDES': ( 'default.segments.right=[{"type":"string","name":"s1","highlight_groups":["cwd"]}];' 'default.segments.left=[{"type":"string","name":"s2","highlight_groups":["background"]}];' 'default.segment_data.s1.contents=S1 string here;' 'default.segment_data.s2.contents=S2 string here;' ), 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''), 'PYTHONPATH': os.environ.get('PYTHONPATH', ''), }, ) p.start() sleep(10) last_line = [] for col in range(cols): last_line.append(p[rows - 1, col]) result = tuple(( (key, ''.join((i.text for i in subline))) for key, subline in groupby(last_line, lambda i: i.cell_properties_key) )) expected_result_new = ( (((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '), (((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '), (((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '), (((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1 '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '), (((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '), (((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '), (((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '), (((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '), (((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '), ) expected_result_old = ( (((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '), (((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '), (((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '), (((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1 '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '), (((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '), (((102, 204, 255), (0, 102, 153), 0, 0, 0), '2 | '), (((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '), (((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '), (((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '), (((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '), (((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '), ) print('Result:') shesc_result = ''.join(( '{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in result )) print(shesc_result) print('Expected:') tmux_version = get_tmux_version(get_fallback_logger()) if tmux_version < (1, 8): expected_result = expected_result_old else: expected_result = expected_result_new shesc_expected_result = ''.join(( '{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) for key, text in expected_result )) print(shesc_expected_result) if result == expected_result: return True else: p.send(b'powerline-config tmux setup\n') sleep(5) print('Screen:') screen = [] for i in range(rows): screen.append([]) for j in range(cols): screen[-1].append(p[i, j]) print('\n'.join( ''.join(( '{0}{1}\x1b[m'.format( cell_properties_key_to_shell_escape(i.cell_properties_key), i.text ) for i in line )) for line in screen )) a = shesc_result.replace('\x1b', '\\e') + '\n' b = shesc_expected_result.replace('\x1b', '\\e') + '\n' print('_' * 80) print('Diff:') print('=' * 80) print(''.join((u(line) for line in ndiff([a], [b])))) return False finally: check_call([tmux_exe, '-S', socket_path, 'kill-server'], env={ 'PATH': vterm_path, 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''), })
def emit(record): message = u(record.message) if record.exc_text: message += '\n' + u(record.exc_text) vim.eval(b'add(g:powerline_log_messages, ' + python_to_vim(message) + b')')
def __init__(self, varname): super(VimVarHandler, self).__init__() utf_varname = u(varname) self.vim_varname = utf_varname.encode('ascii') vim.command('unlet! g:' + utf_varname) vim.command('let g:' + utf_varname + ' = []')
def test_u(self): self.assertStringsIdentical('Test', plu.u('Test')) self.assertStringsIdentical('Test', plu.u(b'Test')) self.assertStringsIdentical('«»', plu.u(b'\xC2\xAB\xC2\xBB')) self.assertRaises(UnicodeDecodeError, plu.u, b'\xFF')
def int_or_sig(s): if s.startswith("sig"): return u(s) else: return int(s)
def emit(self, record): message = u(record.message) if record.exc_text: message += '\n' + u(record.exc_text) vim.eval(b'add(g:' + self.vim_varname + b', ' + python_to_vim(message) + b')')
def get_segments(self, side=None, segment_info=None): '''Return all segments. Function segments are called, and all segments get their before/after and ljust/rjust properties applied. ''' for side in [side] if side else ['left', 'right']: parsed_segments = [] for segment in self.segments[side]: if segment['type'] == 'function': self.pl.prefix = segment['name'] try: contents = segment['contents_func'](self.pl, segment_info) except Exception as e: self.pl.exception( 'Exception while computing segment: {0}', str(e)) continue if contents is None: continue if isinstance(contents, list): segment_base = segment.copy() if contents: draw_divider_position = -1 if side == 'left' else 0 for key, i, newval in ( ('before', 0, ''), ('after', -1, ''), ('draw_soft_divider', draw_divider_position, True), ('draw_hard_divider', draw_divider_position, True), ): try: contents[i][key] = segment_base.pop(key) segment_base[key] = newval except KeyError: pass draw_inner_divider = None if side == 'right': append = parsed_segments.append else: pslen = len(parsed_segments) append = lambda item: parsed_segments.insert( pslen, item) for subsegment in (contents if side == 'right' else reversed(contents)): segment_copy = segment_base.copy() segment_copy.update(subsegment) if draw_inner_divider is not None: segment_copy[ 'draw_soft_divider'] = draw_inner_divider draw_inner_divider = segment_copy.pop( 'draw_inner_divider', None) append(segment_copy) else: segment['contents'] = contents parsed_segments.append(segment) elif segment['width'] == 'auto' or (segment['type'] == 'string' and segment['contents'] is not None): parsed_segments.append(segment) else: continue for segment in parsed_segments: segment['contents'] = segment['before'] + u( segment['contents'] if segment['contents'] is not None else '') + segment['after'] # Align segment contents if segment['width'] and segment['width'] != 'auto': if segment['align'] == 'l': segment['contents'] = segment['contents'].ljust( segment['width']) elif segment['align'] == 'r': segment['contents'] = segment['contents'].rjust( segment['width']) elif segment['align'] == 'c': segment['contents'] = segment['contents'].center( segment['width']) # We need to yield a copy of the segment, or else mode-dependent # segment contents can't be cached correctly e.g. when caching # non-current window contents for vim statuslines yield segment.copy()
def _powerline_test_render_function(*args, **kwargs): ret = _powerline_old_render(*args, **kwargs) vim.eval('add(g:statusline_values, %s)' % json.dumps(u(ret))) return ret
def cwd(pl, segment_info, dir_shorten_len=None, dir_limit_depth=None, use_path_separator=False, ellipsis='⋯'): '''Return the current working directory. Returns a segment list to create a breadcrumb-like effect. :param int dir_shorten_len: shorten parent directory names to this length (e.g. :file:`/long/path/to/powerline` → :file:`/l/p/t/powerline`) :param int dir_limit_depth: limit directory depth to this number (e.g. :file:`/long/path/to/powerline` → :file:`⋯/to/powerline`) :param bool use_path_separator: Use path separator in place of soft divider. :param str ellipsis: Specifies what to use in place of omitted directories. Use None to not show this subsegment at all. Divider highlight group used: ``cwd:divider``. Highlight groups used: ``cwd:current_folder`` or ``cwd``. It is recommended to define all highlight groups. ''' try: cwd = u(segment_info['getcwd']()) except OSError as e: if e.errno == 2: # user most probably deleted the directory # this happens when removing files from Mercurial repos for example pl.warn('Current directory not found') cwd = "[not found]" else: raise home = segment_info['home'] if home: home = u(home) cwd = re.sub('^' + re.escape(home), '~', cwd, 1) cwd_split = cwd.split(os.sep) cwd_split_len = len(cwd_split) cwd = [i[0:dir_shorten_len] if dir_shorten_len and i else i for i in cwd_split[:-1]] + [cwd_split[-1]] if dir_limit_depth and cwd_split_len > dir_limit_depth + 1: del(cwd[0:-dir_limit_depth]) if ellipsis is not None: cwd.insert(0, ellipsis) ret = [] if not cwd[0]: cwd[0] = '/' draw_inner_divider = not use_path_separator for part in cwd: if not part: continue if use_path_separator: part += os.sep ret.append({ 'contents': part, 'divider_highlight_group': 'cwd:divider', 'draw_inner_divider': draw_inner_divider, }) ret[-1]['highlight_group'] = ['cwd:current_folder', 'cwd'] if use_path_separator: ret[-1]['contents'] = ret[-1]['contents'][:-1] if len(ret) > 1 and ret[0]['contents'][0] == os.sep: ret[0]['contents'] = ret[0]['contents'][1:] return ret
def cwd(pl, segment_info, dir_shorten_len=None, dir_limit_depth=None, use_path_separator=False, ellipsis='⋯'): '''Return the current working directory. Returns a segment list to create a breadcrumb-like effect. :param int dir_shorten_len: shorten parent directory names to this length (e.g. :file:`/long/path/to/powerline` → :file:`/l/p/t/powerline`) :param int dir_limit_depth: limit directory depth to this number (e.g. :file:`/long/path/to/powerline` → :file:`⋯/to/powerline`) :param bool use_path_separator: Use path separator in place of soft divider. :param str ellipsis: Specifies what to use in place of omitted directories. Use None to not show this subsegment at all. Divider highlight group used: ``cwd:divider``. Highlight groups used: ``cwd:current_folder`` or ``cwd``. It is recommended to define all highlight groups. ''' try: cwd = u(segment_info['getcwd']()) except OSError as e: if e.errno == 2: # user most probably deleted the directory # this happens when removing files from Mercurial repos for example pl.warn('Current directory not found') cwd = "[not found]" else: raise home = segment_info['home'] if home: home = u(home) cwd = re.sub('^' + re.escape(home), '~', cwd, 1) cwd_split = cwd.split(os.sep) cwd_split_len = len(cwd_split) cwd = [ i[0:dir_shorten_len] if dir_shorten_len and i else i for i in cwd_split[:-1] ] + [cwd_split[-1]] if dir_limit_depth and cwd_split_len > dir_limit_depth + 1: del (cwd[0:-dir_limit_depth]) if ellipsis is not None: cwd.insert(0, ellipsis) ret = [] if not cwd[0]: cwd[0] = '/' draw_inner_divider = not use_path_separator for part in cwd: if not part: continue if use_path_separator: part += os.sep ret.append({ 'contents': part, 'divider_highlight_group': 'cwd:divider', 'draw_inner_divider': draw_inner_divider, }) ret[-1]['highlight_group'] = ['cwd:current_folder', 'cwd'] if use_path_separator: ret[-1]['contents'] = ret[-1]['contents'][:-1] if len(ret) > 1 and ret[0]['contents'][0] == os.sep: ret[0]['contents'] = ret[0]['contents'][1:] return ret