diff --git a/docs/source/installation/troubleshooting-common.rst b/docs/source/installation/troubleshooting-common.rst index c42a4238..98abdd54 100644 --- a/docs/source/installation/troubleshooting-common.rst +++ b/docs/source/installation/troubleshooting-common.rst @@ -19,6 +19,7 @@ I’m using tmux/screen and Powerline is colorless to ``"tmux"`` or ``"screen"``. Note that it is known to work perfectly in screen, but in tmux it may produce ugly spaces. + After an update something stopped working ----------------------------------------- diff --git a/docs/source/overview.rst b/docs/source/overview.rst index cc1dfbf2..f681e65b 100644 --- a/docs/source/overview.rst +++ b/docs/source/overview.rst @@ -164,13 +164,20 @@ is the absolute path to your Powerline installation directory: set fish_function_path $fish_function_path "{repository_root}/powerline/bindings/fish" powerline-setup +.. _tmux-statusline: + Tmux statusline --------------- -Add the following line to your :file:`tmux.conf`, where ``{repository_root}`` is -the absolute path to your Powerline installation directory:: +Add the following lines to your :file:`.tmux.conf`, where ``{repository_root}`` +is the absolute path to your Powerline installation directory:: - source '{repository_root}/powerline/bindings/tmux/powerline.conf' + source "{repository_root}/tmux/powerline.conf" + +.. note:: + The availability of the ``powerline-config`` command is required for + powerline support. You may specify location of this script via + ``$POWERLINE_CONFIG_COMMAND`` environment variable. IPython prompt -------------- diff --git a/powerline/bindings/config.py b/powerline/bindings/config.py new file mode 100644 index 00000000..83bab203 --- /dev/null +++ b/powerline/bindings/config.py @@ -0,0 +1,107 @@ +# vim:fileencoding=utf-8:noet + +from __future__ import absolute_import, unicode_literals, print_function + +from collections import namedtuple +import os +import subprocess +import re + + +TmuxVersionInfo = namedtuple('TmuxVersionInfo', ('major', 'minor', 'suffix')) + + +def get_tmux_executable_name(): + '''Returns tmux executable name + + It should be defined in POWERLINE_TMUX_EXE environment variable, otherwise + it is simply “tmux”. + ''' + + return os.environ.get('POWERLINE_TMUX_EXE', 'tmux') + + +def _run_tmux(runner, args): + return runner([get_tmux_executable_name()] + list(args)) + + +def run_tmux_command(*args): + '''Run tmux command, ignoring the output''' + _run_tmux(subprocess.check_call, args) + + +def get_tmux_output(*args): + '''Run tmux command and return its output''' + return _run_tmux(subprocess.check_output, args) + + +NON_DIGITS = re.compile('[^0-9]+') +DIGITS = re.compile('[0-9]+') +NON_LETTERS = re.compile('[^a-z]+') + + +def get_tmux_version(): + version_string = get_tmux_output('-V') + _, version_string = version_string.split(' ') + version_string = version_string.strip() + major, minor = version_string.split('.') + suffix = DIGITS.subn('', minor)[0] or None + minor = NON_DIGITS.subn('', minor)[0] + return TmuxVersionInfo(int(major), int(minor), suffix) + + +CONFIG_FILE_NAME = re.compile(r'powerline_tmux_(?P\d+)\.(?P\d+)(?P[a-z]+)?(?:_(?Pplus|minus))?\.conf') +CONFIG_MATCHERS = { + None: (lambda a, b: a.major == b.major and a.minor == b.minor), + 'plus': (lambda a, b: a[:2] <= b[:2]), + 'minus': (lambda a, b: a[:2] >= b[:2]), +} +CONFIG_PRIORITY = { + None: 3, + 'plus': 2, + 'minus': 1, +} + + +def list_all_tmux_configs(): + '''List all version-specific tmux configuration files''' + directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmux') + for root, dirs, files in os.walk(directory): + dirs[:] = () + for fname in files: + match = CONFIG_FILE_NAME.match(fname) + if match: + assert match.group('suffix') is None + yield ( + os.path.join(root, fname), + CONFIG_MATCHERS[match.group('mod')], + CONFIG_PRIORITY[match.group('mod')], + TmuxVersionInfo( + int(match.group('major')), + int(match.group('minor')), + match.group('suffix'), + ), + ) + + +def get_tmux_configs(version): + '''Get tmux configuration suffix given parsed tmux version + + :param TmuxVersionInfo version: Parsed tmux version. + ''' + for fname, matcher, priority, file_version in list_all_tmux_configs(): + if matcher(file_version, version): + yield (fname, priority + file_version.minor * 10 + file_version.major * 10000) + + +def source_tmux_files(): + '''Source relevant version-specific tmux configuration files + + Files are sourced in the following order: + * First relevant files with older versions are sourced. + * If files for same versions are to be sourced then first _minus files are + sourced, then _plus files and then files without _minus or _plus suffixes. + ''' + version = get_tmux_version() + for fname, priority in sorted(get_tmux_configs(version), key=(lambda v: v[1])): + run_tmux_command('source', fname) diff --git a/powerline/bindings/tmux/powerline.conf b/powerline/bindings/tmux/powerline.conf index 6facec9c..eb1176de 100644 --- a/powerline/bindings/tmux/powerline.conf +++ b/powerline/bindings/tmux/powerline.conf @@ -1,27 +1,22 @@ if-shell 'test -z "$POWERLINE_COMMAND"' 'if-shell "which powerline-client" "set-environment -g POWERLINE_COMMAND powerline-client" "set-environment -g POWERLINE_COMMAND powerline"' -run-shell "tmux set-environment -g TMUX_VERSION_MAJOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f1 | sed 's/[^0-9]*//g')" -run-shell "tmux set-environment -g TMUX_VERSION_MINOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f2 | sed 's/[^0-9]*//g')" +if-shell 'test -z "$POWERLINE_CONFIG_COMMAND"' 'set-environment -g POWERLINE_CONFIG_COMMAND powerline-config' + +# Don't version-check for this core functionality -- anything too old to +# support these options likely won't work well with powerline set -g status on set -g status-utf8 on set -g status-interval 2 -set -g status-fg colour231 -set -g status-bg colour234 set -g status-left-length 20 -# Version check for 'client_prefix' format functionality -if-shell '[ $TMUX_VERSION_MAJOR -gt 1 -o \( $TMUX_VERSION_MAJOR -eq 1 -a $TMUX_VERSION_MINOR -ge 8 \) ]' \ - "set -g status-left '#{?client_prefix,#[fg=colour254]#[bg=colour31]#[bold],#[fg=colour16]#[bg=colour254]#[bold]} #S #{?client_prefix,#[fg=colour31]#[bg=colour234]#[nobold],#[fg=colour254]#[bg=colour234]#[nobold]}#(eval $POWERLINE_COMMAND tmux left)'" \ - "set -g status-left '#[fg=colour16,bg=colour254,bold] #S #[fg=colour254,bg=colour234,nobold]#(eval $POWERLINE_COMMAND tmux left)'" set -g status-right '#(eval $POWERLINE_COMMAND tmux right -R pane_id=`tmux display -p "#D"`)' set -g status-right-length 150 set -g window-status-format "#[fg=colour244,bg=colour234]#I #[fg=colour240] #[default]#W " set -g window-status-current-format "#[fg=colour234,bg=colour31]#[fg=colour117,bg=colour31] #I  #[fg=colour231,bold]#W #[fg=colour31,bg=colour234,nobold]" -# Version check for window-status-last-style and/or window-status-last-fg functionality -if-shell '[ $TMUX_VERSION_MAJOR -gt 1 -o \( $TMUX_VERSION_MAJOR -eq 1 -a $TMUX_VERSION_MINOR -ge 9 \) ]' \ - "set -g window-status-last-style fg=colour31" \ - 'if-shell "[ $TMUX_VERSION_MAJOR -eq 1 -a $TMUX_VERSION_MINOR -ge 8 ]" "set -g window-status-last-fg colour31"' -set-window-option -g window-status-fg colour249 -set-window-option -g window-status-activity-attr none -set-window-option -g window-status-bell-attr none -set-window-option -g window-status-activity-fg yellow -set-window-option -g window-status-bell-fg red + +# Legacy status-left definition to be overwritten for tmux Versions 1.8+ +set -g status-left '#[fg=colour16,bg=colour254,bold] #S #[fg=colour254,bg=colour234,nobold]#(eval $POWERLINE_COMMAND tmux left)' + +# Simplify tmux version checking by using multiple config files. Source these +# config files based on the version in which tmux features were added and/or +# deprecated. By splitting these configuration options into separate files, +run-shell "eval $POWERLINE_CONFIG_COMMAND tmux source" # vim: ft=tmux diff --git a/powerline/bindings/tmux/powerline_tmux_1.8.conf b/powerline/bindings/tmux/powerline_tmux_1.8.conf new file mode 100644 index 00000000..d94daf39 --- /dev/null +++ b/powerline/bindings/tmux/powerline_tmux_1.8.conf @@ -0,0 +1,5 @@ +# powerline_tmux_1.8.conf +# tmux Version 1.8 introduces window-status-last-{attr,bg,fg}, which is +# deprecated for versions 1.9+, thus only applicable to version 1.8. +set -g window-status-last-fg colour31 +# vim: ft=tmux diff --git a/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf b/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf new file mode 100644 index 00000000..6baed844 --- /dev/null +++ b/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf @@ -0,0 +1,11 @@ +# powerline_tmux_legacy_common.conf +# tmux Version 1.8 and earlier (legacy) common options. The foo-{attr,bg,fg} +# options are deprecated starting with tmux Version 1.9. +set -g status-fg colour231 +set -g status-bg colour234 +set-window-option -g window-status-fg colour249 +set-window-option -g window-status-activity-attr none +set-window-option -g window-status-bell-attr none +set-window-option -g window-status-activity-fg yellow +set-window-option -g window-status-bell-fg red +# vim: ft=tmux diff --git a/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf b/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf new file mode 100644 index 00000000..a31bacfe --- /dev/null +++ b/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf @@ -0,0 +1,5 @@ +# powerline_tmux_1.8_plus.conf +# tmux Version 1.8 introduces the 'client_prefix' format variable, applicable +# for versions 1.8+ +set -g status-left '#{?client_prefix,#[fg=colour254]#[bg=colour31]#[bold],#[fg=colour16]#[bg=colour254]#[bold]} #S #{?client_prefix,#[fg=colour31]#[bg=colour234]#[nobold],#[fg=colour254]#[bg=colour234]#[nobold]}#(eval $POWERLINE_COMMAND tmux left)' +# vim: ft=tmux diff --git a/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf b/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf new file mode 100644 index 00000000..619b26d5 --- /dev/null +++ b/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf @@ -0,0 +1,8 @@ +# powerline_tmux_1.9_plus.conf +# Version 1.9 introduces the foo-style options, applicable to version 1.9+ +set -g status-style fg=colour231,bg=colour234 +set -g window-status-last-style fg=colour31 +set-window-option -g window-status-style fg=colour249 +set-window-option -g window-status-activity-style fg=yellow,none +set-window-option -g window-status-bell-style fg=red,none +# vim: ft=tmux diff --git a/scripts/powerline-config b/scripts/powerline-config new file mode 100755 index 00000000..151dc1d5 --- /dev/null +++ b/scripts/powerline-config @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8:noet +'''Script used to obtain powerline configuration''' + +import argparse + +try: + import powerline.bindings.config as config +except ImportError: + sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__))))) + import powerline.bindings.config as config # NOQA + + +TMUX_ACTIONS = { + 'source': (lambda args: config.source_tmux_files()), +} + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description=__doc__) + subparsers = parser.add_subparsers() + tmux_parser = subparsers.add_parser('tmux', help='Tmux-specific commands') + tmux_parser.add_argument( + 'function', + choices=tuple(TMUX_ACTIONS.values()), + metavar='action', + type=(lambda v: TMUX_ACTIONS.get(v)), + help='If action is "source" then version-specific tmux configuration files are sourced.' + ) + + args = parser.parse_args() + + args.function(args) diff --git a/setup.py b/setup.py index 0b449011..e341ceec 100755 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ setup( scripts=[ 'scripts/powerline', 'scripts/powerline-lint', + 'scripts/powerline-config', ], keywords='', packages=find_packages(exclude=('tests', 'tests.*')),