diff --git a/powerline/bindings/config.py b/powerline/bindings/config.py index 19bf17c5..9e46748a 100644 --- a/powerline/bindings/config.py +++ b/powerline/bindings/config.py @@ -8,9 +8,11 @@ import sys from powerline.config import POWERLINE_ROOT, TMUX_CONFIG_DIRECTORY from powerline.lib.config import ConfigLoader from powerline import generate_config_finder, load_config, create_logger, PowerlineLogger, finish_common_config +from powerline.tmux import TmuxPowerline from powerline.lib.shell import which -from powerline.bindings.tmux import TmuxVersionInfo, run_tmux_command, get_tmux_version +from powerline.bindings.tmux import TmuxVersionInfo, run_tmux_command, set_tmux_environment, get_tmux_version from powerline.lib.encoding import get_preferred_output_encoding +from powerline.renderers.tmux import attr_to_tmux_attr CONFIG_FILE_NAME = re.compile(r'powerline_tmux_(?P\d+)\.(?P\d+)(?P[a-z]+)?(?:_(?Pplus|minus))?\.conf') @@ -28,8 +30,7 @@ CONFIG_PRIORITY = { def list_all_tmux_configs(): '''List all version-specific tmux configuration files''' - directory = TMUX_CONFIG_DIRECTORY - for root, dirs, files in os.walk(directory): + for root, dirs, files in os.walk(TMUX_CONFIG_DIRECTORY): dirs[:] = () for fname in files: match = CONFIG_FILE_NAME.match(fname) @@ -66,15 +67,86 @@ def source_tmux_files(pl, args): sourced, then _plus files and then files without _minus or _plus suffixes. ''' version = get_tmux_version(pl) + run_tmux_command('source', os.path.join(TMUX_CONFIG_DIRECTORY, 'powerline-base.conf')) for fname, priority in sorted(get_tmux_configs(version), key=(lambda v: v[1])): run_tmux_command('source', fname) if not os.environ.get('POWERLINE_COMMAND'): cmd = deduce_command() if cmd: - run_tmux_command('set-environment', '-g', 'POWERLINE_COMMAND', deduce_command()) + set_tmux_environment('POWERLINE_COMMAND', deduce_command(), remove=False) run_tmux_command('refresh-client') +def init_environment(pl, args): + '''Initialize tmux environment from tmux configuration + ''' + powerline = TmuxPowerline(args.config_path) + # TODO Move configuration files loading out of Powerline object and use it + # directly + powerline.update_renderer() + # FIXME Use something more stable then `theme_kwargs` + colorscheme = powerline.renderer_options['theme_kwargs']['colorscheme'] + + def get_highlighting(group): + return colorscheme.get_highlighting([group], None) + + for varname, highlight_group in ( + ('_POWERLINE_BACKGROUND_COLOR', 'background'), + ('_POWERLINE_ACTIVE_WINDOW_STATUS_COLOR', 'active_window_status'), + ('_POWERLINE_WINDOW_STATUS_COLOR', 'window_status'), + ('_POWERLINE_ACTIVITY_STATUS_COLOR', 'activity_status'), + ('_POWERLINE_BELL_STATUS_COLOR', 'bell_status'), + ('_POWERLINE_WINDOW_COLOR', 'window'), + ('_POWERLINE_WINDOW_DIVIDER_COLOR', 'window:divider'), + ('_POWERLINE_WINDOW_CURRENT_COLOR', 'window:current'), + ('_POWERLINE_WINDOW_NAME_COLOR', 'window_name'), + ('_POWERLINE_SESSION_COLOR', 'session'), + ): + highlight = get_highlighting(highlight_group) + set_tmux_environment(varname, powerline.renderer.hlstyle(**highlight)[2:-1]) + for varname, prev_group, next_group in ( + ('_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR', 'window', 'window:current'), + ('_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR', 'window:current', 'window'), + ('_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR', 'session', 'background'), + ): + prev_highlight = get_highlighting(prev_group) + next_highlight = get_highlighting(next_group) + set_tmux_environment( + varname, + powerline.renderer.hlstyle( + fg=prev_highlight['bg'], + bg=next_highlight['bg'], + attr=0, + )[2:-1] + ) + for varname, attr, group in ( + ('_POWERLINE_ACTIVE_WINDOW_FG', 'fg', 'active_window_status'), + ('_POWERLINE_WINDOW_STATUS_FG', 'fg', 'window_status'), + ('_POWERLINE_ACTIVITY_STATUS_FG', 'fg', 'activity_status'), + ('_POWERLINE_ACTIVITY_STATUS_ATTR', 'attr', 'activity_status'), + ('_POWERLINE_BELL_STATUS_FG', 'fg', 'bell_status'), + ('_POWERLINE_BELL_STATUS_ATTR', 'attr', 'bell_status'), + ('_POWERLINE_BACKGROUND_FG', 'fg', 'background'), + ('_POWERLINE_BACKGROUND_BG', 'bg', 'background'), + ('_POWERLINE_SESSION_FG', 'fg', 'session'), + ('_POWERLINE_SESSION_BG', 'bg', 'session'), + ('_POWERLINE_SESSION_ATTR', 'attr', 'session'), + ('_POWERLINE_SESSION_PREFIX_FG', 'fg', 'session:prefix'), + ('_POWERLINE_SESSION_PREFIX_BG', 'bg', 'session:prefix'), + ('_POWERLINE_SESSION_PREFIX_ATTR', 'attr', 'session:prefix'), + ): + if attr == 'attr': + attrs = attr_to_tmux_attr(get_highlighting(group)[attr]) + set_tmux_environment(varname, ']#['.join(attrs)) + set_tmux_environment(varname + '_LEGACY', ','.join(attrs)) + else: + set_tmux_environment(varname, 'colour' + str(get_highlighting(group)[attr][0])) + + left_dividers = powerline.renderer.theme.dividers['left'] + set_tmux_environment('_POWERLINE_LEFT_HARD_DIVIDER', left_dividers['hard']) + set_tmux_environment('_POWERLINE_LEFT_SOFT_DIVIDER', left_dividers['soft']) + + def get_main_config(args): find_config_files = generate_config_finder() config_loader = ConfigLoader(run_once=True) diff --git a/powerline/bindings/tmux/__init__.py b/powerline/bindings/tmux/__init__.py index d56abde4..6ccda8b5 100644 --- a/powerline/bindings/tmux/__init__.py +++ b/powerline/bindings/tmux/__init__.py @@ -37,6 +37,22 @@ def get_tmux_output(pl, *args): return _run_tmux(lambda cmd: run_cmd(pl, cmd), args) +def set_tmux_environment(varname, value, remove=True): + '''Set tmux global environment variable + + :param str varname: + Name of the variable to set. + :param str value: + Variable value. + :param bool remove: + True if variable should be removed from the environment prior to + attaching any client (runs ``tmux set-environment -r {varname}``). + ''' + run_tmux_command('set-environment', '-g', varname, value) + if remove: + run_tmux_command('set-environment', '-r', varname) + + NON_DIGITS = re.compile('[^0-9]+') DIGITS = re.compile('[0-9]+') NON_LETTERS = re.compile('[^a-z]+') diff --git a/powerline/bindings/tmux/powerline-base.conf b/powerline/bindings/tmux/powerline-base.conf new file mode 100644 index 00000000..add06afa --- /dev/null +++ b/powerline/bindings/tmux/powerline-base.conf @@ -0,0 +1,12 @@ +set -g status on +set -g status-utf8 on +set -g status-interval 2 +set -g status-left-length 20 +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 "#[$_POWERLINE_WINDOW_COLOR] #I #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W " +set -g window-status-current-format "#[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#[$_POWERLINE_WINDOW_CURRENT_COLOR]#I $_POWERLINE_LEFT_SOFT_DIVIDER#[$_POWERLINE_WINDOW_NAME_COLOR]#W #[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER" + +# Legacy status-left definition to be overwritten for tmux Versions 1.8+ +set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(eval \$POWERLINE_COMMAND tmux left)" +# vim: ft=tmux diff --git a/powerline/bindings/tmux/powerline.conf b/powerline/bindings/tmux/powerline.conf index b8a07517..8eb11dab 100644 --- a/powerline/bindings/tmux/powerline.conf +++ b/powerline/bindings/tmux/powerline.conf @@ -1,18 +1,6 @@ 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-left-length 20 -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]" - -# 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)' +run-shell 'eval $POWERLINE_CONFIG_COMMAND tmux setenv' # 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 diff --git a/powerline/bindings/tmux/powerline_tmux_1.8.conf b/powerline/bindings/tmux/powerline_tmux_1.8.conf index 720206be..fbcd2a58 100644 --- a/powerline/bindings/tmux/powerline_tmux_1.8.conf +++ b/powerline/bindings/tmux/powerline_tmux_1.8.conf @@ -1,5 +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 -qg window-status-last-fg colour31 +set -qg window-status-last-fg "$_POWERLINE_ACTIVE_WINDOW_FG" # 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 index 6baed844..284eee08 100644 --- a/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf +++ b/powerline/bindings/tmux/powerline_tmux_1.8_minus.conf @@ -1,11 +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 +set -g status-fg "$_POWERLINE_BACKGROUND_FG" +set -g status-bg "$_POWERLINE_BACKGROUND_BG" +set-window-option -g window-status-fg "$_POWERLINE_WINDOW_STATUS_FG" +set-window-option -g window-status-activity-attr "$_POWERLINE_ACTIVITY_STATUS_ATTR_LEGACY" +set-window-option -g window-status-bell-attr "$_POWERLINE_BELL_STATUS_ATTR_LEGACY" +set-window-option -g window-status-activity-fg "$_POWERLINE_ACTIVITY_STATUS_FG" +set-window-option -g window-status-bell-fg "$_POWERLINE_BELL_STATUS_FG" # 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 index 1ad9cdb3..d3e1e153 100644 --- a/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf +++ b/powerline/bindings/tmux/powerline_tmux_1.8_plus.conf @@ -1,5 +1,5 @@ # powerline_tmux_1.8_plus.conf # tmux Version 1.8 introduces the 'client_prefix' format variable, applicable # for versions 1.8+ -set -qg 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 -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(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 index b053b6ee..7ab9a8b3 100644 --- a/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf +++ b/powerline/bindings/tmux/powerline_tmux_1.9_plus.conf @@ -1,8 +1,8 @@ # powerline_tmux_1.9_plus.conf # Version 1.9 introduces the foo-style options, applicable to version 1.9+ -set -qg status-style fg=colour231,bg=colour234 -set -qg window-status-last-style fg=colour31 -set-window-option -qg window-status-style fg=colour249 -set-window-option -qg window-status-activity-style fg=yellow,none -set-window-option -qg window-status-bell-style fg=red,none +set-option -qg status-style "$_POWERLINE_BACKGROUND_COLOR" +set-option -qg window-status-last-style "$_POWERLINE_ACTIVE_WINDOW_STATUS_COLOR" +set-window-option -qg window-status-style "$_POWERLINE_WINDOW_STATUS_COLOR" +set-window-option -qg window-status-activity-style "$_POWERLINE_ACTIVITY_STATUS_COLOR" +set-window-option -qg window-status-bell-style "$_POWERLINE_BELL_STATUS_COLOR" # vim: ft=tmux diff --git a/powerline/commands/config.py b/powerline/commands/config.py index 0f7b78ed..9211b54b 100644 --- a/powerline/commands/config.py +++ b/powerline/commands/config.py @@ -20,6 +20,7 @@ class StrFunction(object): TMUX_ACTIONS = { 'source': StrFunction(config.source_tmux_files, 'source'), + 'setenv': StrFunction(config.init_environment, 'setenv'), } @@ -42,6 +43,7 @@ class ConfigArgParser(argparse.ArgumentParser): def get_argparser(ArgumentParser=ConfigArgParser): parser = ArgumentParser(description='Script used to obtain powerline configuration.') + 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.') subparsers = parser.add_subparsers() tmux_parser = subparsers.add_parser('tmux', help='Tmux-specific commands') tmux_parser.add_argument( @@ -49,7 +51,7 @@ def get_argparser(ArgumentParser=ConfigArgParser): 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.' + help='If action is `source\' then version-specific tmux configuration files are sourced, if it is `setenv\' then special (prefixed with `_POWERLINE\') tmux global environment variables are filled with data from powerline configuration.' ) shell_parser = subparsers.add_parser('shell', help='Shell-specific commands') diff --git a/powerline/config_files/colors.json b/powerline/config_files/colors.json index 6bfadf7b..1564f182 100644 --- a/powerline/config_files/colors.json +++ b/powerline/config_files/colors.json @@ -3,6 +3,7 @@ "black": 16, "white": 231, + "green": 2, "darkestgreen": 22, "darkgreen": 28, "mediumgreen": 70, @@ -32,6 +33,7 @@ "brightorange": 208, "brightestorange": 214, + "yellow": 11, "brightyellow": 220, "gray0": 233, @@ -46,6 +48,11 @@ "gray9": 250, "gray10": 252, + "gray11": 234, + "gray90": 254, + + "gray70": [249, "b3b3b3"], + "lightyellowgreen": 106, "gold3": 178, "orangered": 202, diff --git a/powerline/config_files/colorschemes/default.json b/powerline/config_files/colorschemes/default.json index 2c138bd3..899f162a 100644 --- a/powerline/config_files/colorschemes/default.json +++ b/powerline/config_files/colorschemes/default.json @@ -1,6 +1,7 @@ { "name": "Default", "groups": { + "background": { "fg": "white", "bg": "gray0", "attr": [] }, "background:divider": { "fg": "gray5", "bg": "gray0", "attr": [] }, "session": { "fg": "black", "bg": "gray10", "attr": ["bold"] }, "date": { "fg": "gray8", "bg": "gray2", "attr": [] }, diff --git a/powerline/config_files/colorschemes/tmux/default.json b/powerline/config_files/colorschemes/tmux/default.json new file mode 100644 index 00000000..3745fd5a --- /dev/null +++ b/powerline/config_files/colorschemes/tmux/default.json @@ -0,0 +1,14 @@ +{ + "groups": { + "active_window_status": {"fg": "darkblue", "bg": "gray0", "attr": []}, + "window_status": {"fg": "gray70", "bg": "gray0", "attr": []}, + "activity_status": {"fg": "yellow", "bg": "gray0", "attr": []}, + "bell_status": {"fg": "red", "bg": "gray0", "attr": []}, + "window": {"fg": "gray6", "bg": "gray11", "attr": []}, + "window:divider": {"fg": "gray4", "bg": "gray11", "attr": []}, + "window:current": {"fg": "mediumcyan", "bg": "darkblue", "attr": []}, + "window_name": {"fg": "white", "bg": "darkblue", "attr": ["bold"]}, + "session": {"fg": "black", "bg": "gray90", "attr": ["bold"]}, + "session:prefix": {"fg": "gray90", "bg": "darkblue", "attr": ["bold"]} + } +} diff --git a/powerline/renderers/tmux.py b/powerline/renderers/tmux.py index 97deda9f..7e7d5abd 100644 --- a/powerline/renderers/tmux.py +++ b/powerline/renderers/tmux.py @@ -5,6 +5,26 @@ from powerline.renderer import Renderer from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE +def attr_to_tmux_attr(attr): + if attr is False: + return ['nobold', 'noitalics', 'nounderscore'] + else: + ret = [] + if attr & ATTR_BOLD: + ret += ['bold'] + else: + ret += ['nobold'] + if attr & ATTR_ITALIC: + ret += ['italics'] + else: + ret += ['noitalics'] + if attr & ATTR_UNDERLINE: + ret += ['underscore'] + else: + ret += ['nounderscore'] + return ret + + class TmuxRenderer(Renderer): '''Powerline tmux segment renderer.''' @@ -28,21 +48,7 @@ class TmuxRenderer(Renderer): else: tmux_attr += ['bg=colour' + str(bg[0])] if attr is not None: - if attr is False: - tmux_attr += ['nobold', 'noitalics', 'nounderscore'] - else: - if attr & ATTR_BOLD: - tmux_attr += ['bold'] - else: - tmux_attr += ['nobold'] - if attr & ATTR_ITALIC: - tmux_attr += ['italics'] - else: - tmux_attr += ['noitalics'] - if attr & ATTR_UNDERLINE: - tmux_attr += ['underscore'] - else: - tmux_attr += ['nounderscore'] + tmux_attr += attr_to_tmux_attr(attr) return '#[' + ','.join(tmux_attr) + ']' def get_segment_info(self, segment_info, mode): diff --git a/powerline/tmux.py b/powerline/tmux.py new file mode 100644 index 00000000..15f42127 --- /dev/null +++ b/powerline/tmux.py @@ -0,0 +1,16 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +from powerline import Powerline + + +class TmuxPowerline(Powerline): + def init(self, config_paths): + self.paths = config_paths + return super(TmuxPowerline, self).init('tmux') + + def get_config_paths(self): + if self.paths: + return self.paths + else: + return super(TmuxPowerline, self).get_config_paths() diff --git a/tests/test_shells/input.tmux b/tests/test_shells/input.tmux new file mode 100644 index 00000000..d6364d16 --- /dev/null +++ b/tests/test_shells/input.tmux @@ -0,0 +1,4 @@ +echo $TMUX +exit +kill-server + diff --git a/tests/test_shells/tmux.conf b/tests/test_shells/tmux.conf new file mode 100644 index 00000000..1f5143f5 --- /dev/null +++ b/tests/test_shells/tmux.conf @@ -0,0 +1,2 @@ +source powerline/bindings/tmux/powerline.conf +set -g default-shell tests/shell/path/dash