From 03597319039268261f5f8aa05461bdb479ab6b99 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 15 Jun 2016 22:53:02 -0500 Subject: [PATCH 1/3] Add ability to specify session/global options Ability to specify ``options`` and ``global_options`` via configuration. Also you can specify environment variables via that. Add tests for it. Update libtmux to v0.5 See also: #65 --- CHANGES | 5 ++ examples/env-variables.json | 24 +++--- examples/env-variables.yaml | 3 +- requirements/base.txt | 2 +- tests/fixtures/config/expand1.py | 4 +- tests/fixtures/config/shell_command_before.py | 6 +- .../workspacebuilder/env_var_options.yaml | 13 ++++ .../workspacebuilder/global_options.yaml | 12 +++ .../workspacebuilder/pane_ordering.yaml | 2 +- .../workspacebuilder/session_options.yaml | 12 +++ tests/test_config.py | 41 ++++++----- tests/test_workspacebuilder.py | 73 ++++++++++++++++--- tmuxp/config.py | 17 +++++ tmuxp/workspacebuilder.py | 6 ++ 14 files changed, 171 insertions(+), 49 deletions(-) create mode 100644 tests/fixtures/workspacebuilder/env_var_options.yaml create mode 100644 tests/fixtures/workspacebuilder/global_options.yaml create mode 100644 tests/fixtures/workspacebuilder/session_options.yaml diff --git a/CHANGES b/CHANGES index 5c38f84560..8197765b90 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,11 @@ Changelog Here you can find the recent changes to tmuxp +- :feature:`65` Ability to specify ``options`` and ``global_options`` via + configuration. Also you can specify environment variables via that. + + Include tests. + - :release:`1.1.1 <2016-06-02>` - :bug:`167 backported` fix attaching multiple sessions - :bug:`165 backported` fix typo in error output, thanks @fpietka diff --git a/examples/env-variables.json b/examples/env-variables.json index 00e22bd13c..d3294eb551 100644 --- a/examples/env-variables.json +++ b/examples/env-variables.json @@ -1,5 +1,5 @@ { - "before_script": "${MY_ENV_VAR}/test3.sh", + "before_script": "${MY_ENV_VAR}/test3.sh", "windows": [ { "panes": [ @@ -8,24 +8,26 @@ "tail -F /var/log/syslog" ] } - ], - "start_directory": "/var/log", + ], + "start_directory": "/var/log", "window_name": "editor" - }, + }, { "panes": [ { "shell_command": [ - "htop", + "htop", "ls $PWD" ] } ], - "window_name": "logging for {USER}", - "automatic_rename": true + "window_name": "logging for ${USER}", + "options": { + "automatic-rename": true + } } - ], - "shell_command_before": "echo ${PWD}", - "start_directory": "${PWD}/test", + ], + "shell_command_before": "echo ${PWD}", + "start_directory": "${PWD}/test", "session_name": "session - ${USER} (${MY_ENV_VAR})" -} +} \ No newline at end of file diff --git a/examples/env-variables.yaml b/examples/env-variables.yaml index 5607d1a32a..d2c584be90 100644 --- a/examples/env-variables.yaml +++ b/examples/env-variables.yaml @@ -9,7 +9,8 @@ windows: - tail -F /var/log/syslog start_directory: /var/log - window_name: logging for ${USER} - automatic_rename: true + options: + automatic-rename: true panes: - shell_command: - htop diff --git a/requirements/base.txt b/requirements/base.txt index 960fb62de0..3dbf30ff5f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ kaptan>=0.5.7 -libtmux==0.4.1 +libtmux==0.5 click==6.6 colorama diff --git a/tests/fixtures/config/expand1.py b/tests/fixtures/config/expand1.py index bd90ce4547..4c75c410bb 100644 --- a/tests/fixtures/config/expand1.py +++ b/tests/fixtures/config/expand1.py @@ -32,7 +32,7 @@ }, { 'start_directory': '/var/log', - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ { 'shell_command': 'htop' @@ -95,7 +95,7 @@ }, { 'start_directory': '/var/log', - 'options': {'automatic_rename': True}, + 'options': {'automatic-rename': True}, 'panes': [ {'shell_command': ['htop']}, {'shell_command': ['vim']} diff --git a/tests/fixtures/config/shell_command_before.py b/tests/fixtures/config/shell_command_before.py index f4d9107799..caf9504b3f 100644 --- a/tests/fixtures/config/shell_command_before.py +++ b/tests/fixtures/config/shell_command_before.py @@ -40,7 +40,7 @@ ] }, { - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ {'shell_command': ['htop']} ] @@ -92,7 +92,7 @@ ] }, { - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ {'shell_command': ['htop']} ] @@ -155,7 +155,7 @@ }, { 'start_directory': '/', - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ { 'shell_command': ['htop'] diff --git a/tests/fixtures/workspacebuilder/env_var_options.yaml b/tests/fixtures/workspacebuilder/env_var_options.yaml new file mode 100644 index 0000000000..494fbe36ce --- /dev/null +++ b/tests/fixtures/workspacebuilder/env_var_options.yaml @@ -0,0 +1,13 @@ +session_name: test env vars for options +start_directory: '~' +global_options: + visual-silence: ${VISUAL_SILENCE} +options: + repeat-time: 738 +windows: +- window_name: moo + layout: main-horizontal + options: + main-pane-height: ${MAIN_PANE_HEIGHT} + panes: + - pane diff --git a/tests/fixtures/workspacebuilder/global_options.yaml b/tests/fixtures/workspacebuilder/global_options.yaml new file mode 100644 index 0000000000..99c6131a14 --- /dev/null +++ b/tests/fixtures/workspacebuilder/global_options.yaml @@ -0,0 +1,12 @@ +session_name: test global options +start_directory: '~' +global_options: + repeat-time: 493 + status-position: 'top' +windows: +- layout: main-horizontal + panes: + - pane + - pane + - pane + window_name: moo diff --git a/tests/fixtures/workspacebuilder/pane_ordering.yaml b/tests/fixtures/workspacebuilder/pane_ordering.yaml index 52d4796a88..1d6d54418c 100644 --- a/tests/fixtures/workspacebuilder/pane_ordering.yaml +++ b/tests/fixtures/workspacebuilder/pane_ordering.yaml @@ -2,7 +2,7 @@ session_name: sampleconfig start_directory: {HOME} windows: - options: - - automatic_rename: on + automatic-rename: on layout: tiled panes: - cd /usr/bin diff --git a/tests/fixtures/workspacebuilder/session_options.yaml b/tests/fixtures/workspacebuilder/session_options.yaml new file mode 100644 index 0000000000..788c795a5c --- /dev/null +++ b/tests/fixtures/workspacebuilder/session_options.yaml @@ -0,0 +1,12 @@ +session_name: test session options +start_directory: '~' +options: + default-shell: /bin/sh + default-command: /bin/sh +windows: +- layout: main-horizontal + panes: + - pane + - pane + - pane + window_name: moo diff --git a/tests/test_config.py b/tests/test_config.py index d0ddc77971..c45a27706b 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -9,7 +9,6 @@ import kaptan import pytest -from libtmux.test import EnvironmentVarGuard from tmuxp import config, exc from . import example_dir @@ -129,7 +128,7 @@ def test_config_expand2(): ] }, { - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ {'shell_command': ['htop']} ] @@ -158,7 +157,7 @@ def test_config_expand2(): }, { 'options': { - 'automatic_rename': True, + 'automatic-rename': True, }, 'panes': [ 'htop' @@ -213,7 +212,7 @@ def test_inline_config(): }, { 'options': { - 'automatic_rename': True, + 'automatic-rename': True, }, 'panes': [ { @@ -257,7 +256,7 @@ def test_inline_config(): ] }, { - 'options': {'automatic_rename': True, }, + 'options': {'automatic-rename': True, }, 'panes': [ { 'shell_command': ['htop'], @@ -363,7 +362,7 @@ def test_no_session_name(): - tail -F /var/log/syslog start_directory: /var/log - window_name: logging - automatic_rename: true + automatic-rename: true panes: - shell_command: - htop @@ -399,7 +398,7 @@ def test_no_window_name(): shell_command: - tail -F /var/log/syslog start_directory: /var/log - - automatic_rename: true + - automatic-rename: true panes: - shell_command: - htop @@ -413,14 +412,18 @@ def test_no_window_name(): assert excinfo.matches('missing "window_name"') -def test_replaces_start_directory(): +def test_replaces_env_variables(monkeypatch): env_key = "TESTHEY92" - env_value = "HEYO1" + env_val = "HEYO1" yaml_config = """ start_directory: {TEST_VAR}/test shell_command_before: {TEST_VAR}/test2 before_script: {TEST_VAR}/test3 session_name: hi - {TEST_VAR} + options: + default-command: {TEST_VAR}/lol + global_options: + default-shell: {TEST_VAR}/moo windows: - window_name: editor panes: @@ -428,7 +431,7 @@ def test_replaces_start_directory(): - tail -F /var/log/syslog start_directory: /var/log - window_name: logging @ {TEST_VAR} - automatic_rename: true + automatic-rename: true panes: - shell_command: - htop @@ -438,12 +441,12 @@ def test_replaces_start_directory(): sconfig = load_yaml(yaml_config) - with EnvironmentVarGuard() as env: - env.set(env_key, env_value) - sconfig = config.expand(sconfig) - assert "%s/test" % env_value == sconfig['start_directory'] - assert "%s/test2" % env_value in sconfig['shell_command_before'] - assert "%s/test3" % env_value == sconfig['before_script'] - assert "hi - %s" % env_value == sconfig['session_name'] - assert "logging @ %s" % env_value == \ - sconfig['windows'][1]['window_name'] + monkeypatch.setenv(env_key, env_val) + sconfig = config.expand(sconfig) + assert "%s/test" % env_val == sconfig['start_directory'] + assert "%s/test2" % env_val in sconfig['shell_command_before'] + assert "%s/test3" % env_val == sconfig['before_script'] + assert "hi - %s" % env_val == sconfig['session_name'] + assert "%s/moo" % env_val == sconfig['global_options']['default-shell'] + assert "%s/lol" % env_val == sconfig['options']['default-command'] + assert "logging @ %s" % env_val == sconfig['windows'][1]['window_name'] diff --git a/tests/test_workspacebuilder.py b/tests/test_workspacebuilder.py index 77fb3d0e0a..082f4aefe1 100644 --- a/tests/test_workspacebuilder.py +++ b/tests/test_workspacebuilder.py @@ -103,7 +103,7 @@ def test_focus_pane_index(session): assert w.name != 'man' pane_path = '/usr' - for i in range(20): + for _ in range(20): p = w.attached_pane p.server._update_panes() if p.current_path == pane_path: @@ -121,7 +121,7 @@ def test_focus_pane_index(session): p = None pane_path = '/' - for i in range(10): + for _ in range(10): p = window3.attached_pane p.server._update_panes() if p.current_path == pane_path: @@ -164,7 +164,7 @@ def assertIsMissing(cmd, hist): session.cmd('send-keys', ' fc -ln -1') session.cmd('send-keys', 'Enter') - for i in range(10): + for _ in range(10): time.sleep(0.1) # Get the contents of the pane @@ -182,6 +182,57 @@ def assertIsMissing(cmd, hist): assert correct, "Unknown sent command: [%s]" % sent_cmd +def test_session_options(session): + yaml_config = loadfixture("workspacebuilder/session_options.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + assert "/bin/sh" in s.show_option('default-shell') + assert "/bin/sh" in s.show_option('default-command') + + +def test_global_options(session): + yaml_config = loadfixture("workspacebuilder/global_options.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + assert "top" in s.show_option('status-position', g=True) + assert 493 == s.show_option('repeat-time', g=True) + + +def test_global_session_env_options(session, monkeypatch): + visual_silence = 'on' + monkeypatch.setenv('VISUAL_SILENCE', visual_silence) + repeat_time = 738 + monkeypatch.setenv('REPEAT_TIME', repeat_time) + main_pane_height = 8 + monkeypatch.setenv('MAIN_PANE_HEIGHT', main_pane_height) + + yaml_config = loadfixture("workspacebuilder/env_var_options.yaml") + s = session + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + sconfig = config.expand(sconfig) + + builder = WorkspaceBuilder(sconf=sconfig) + builder.build(session=session) + + assert visual_silence in s.show_option('visual-silence', g=True) + assert repeat_time == s.show_option('repeat-time') + assert main_pane_height == \ + s.attached_window.show_window_option('main-pane-height') + + def test_window_options(session): yaml_config = loadfixture("workspacebuilder/window_options.yaml") s = session @@ -217,7 +268,7 @@ def test_window_shell(session): for w, wconf in builder.iter_create_windows(s): if 'window_shell' in wconf: assert wconf['window_shell'] == text_type('top') - for i in range(10): + for _ in range(10): session.server._update_windows() if w['window_name'] != 'top': break @@ -265,7 +316,7 @@ def test_automatic_rename_option(session): assert s.name != 'tmuxp' w = s.windows[0] - for i in range(10): + for _ in range(10): session.server._update_windows() if w.name != 'sh': break @@ -276,7 +327,7 @@ def test_automatic_rename_option(session): pane_base_index = w.show_window_option('pane-base-index', g=True) w.select_pane(pane_base_index) - for i in range(10): + for _ in range(10): session.server._update_windows() if w.name == 'sh': break @@ -285,7 +336,7 @@ def test_automatic_rename_option(session): assert w.name == text_type('sh') w.select_pane('-D') - for i in range(10): + for _ in range(10): session.server._update_windows() if w['window_name'] != 'sh': break @@ -345,7 +396,7 @@ def test_start_directory(session, tmpdir): for path, window in zip(dirs, session.windows): for p in window.panes: - for i in range(60): + for _ in range(60): p.server._update_panes() pane_path = p.current_path if pane_path is None: @@ -411,7 +462,7 @@ def test_start_directory_relative(session, tmpdir): for path, window in zip(dirs, session.windows): for p in window.panes: - for i in range(60): + for _ in range(60): p.server._update_panes() # Handle case where directories resolve to /private/ in OSX pane_path = p.current_path @@ -480,7 +531,7 @@ def test_pane_order(session): # at 0 since python list. pane_path = pane_paths[p_index - pane_base_index] - for i in range(60): + for _ in range(60): p.server._update_panes() if p.current_path == pane_path: break @@ -506,7 +557,7 @@ def test_window_index(session): builder = WorkspaceBuilder(sconf=sconfig) - for window, wconf in builder.iter_create_windows(session): + for window, _ in builder.iter_create_windows(session): expected_index = name_index_map[window['window_name']] assert int(window['window_index']) == expected_index diff --git a/tmuxp/config.py b/tmuxp/config.py index c81bc71e4b..20aa9dd7f7 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -198,6 +198,23 @@ def expand(sconf, cwd=None, parent=None): if any(val.startswith(a) for a in ['.', './']): val = os.path.normpath(os.path.join(cwd, val)) sconf['environment'][key] = val + if 'global_options' in sconf: + for key in sconf['global_options']: + val = sconf['global_options'][key] + if isinstance(val, string_types): + val = expandshell(val) + if any(val.startswith(a) for a in ['.', './']): + val = os.path.normpath(os.path.join(cwd, val)) + sconf['global_options'][key] = val + if 'options' in sconf: + for key in sconf['options']: + val = sconf['options'][key] + if isinstance(val, string_types): + val = expandshell(val) + if any(val.startswith(a) for a in ['.', './']): + val = os.path.normpath(os.path.join(cwd, val)) + sconf['options'][key] = val + # Any config section, session, window, pane that can contain the # 'shell_command' value if 'start_directory' in sconf: diff --git a/tmuxp/workspacebuilder.py b/tmuxp/workspacebuilder.py index 90a43ef955..1d741be177 100644 --- a/tmuxp/workspacebuilder.py +++ b/tmuxp/workspacebuilder.py @@ -161,6 +161,12 @@ def build(self, session=None): except Exception as e: self.session.kill_session() raise e + if 'options' in self.sconf: + for option, value in self.sconf['options'].items(): + self.session.set_option(option, value) + if 'global_options' in self.sconf: + for option, value in self.sconf['global_options'].items(): + self.session.set_option(option, value, g=True) if 'environment' in self.sconf: for option, value in self.sconf['environment'].items(): self.session.set_environment(option, value) From f0dcee451099e10f1ab990be49e9ad49ff4e57dd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 15 Jun 2016 23:04:33 -0500 Subject: [PATCH 2/3] Add example for tmux options See also: #65 --- doc/examples.rst | 16 ++++++++++++---- examples/{automatic-rename.json => options.json} | 9 ++++++++- examples/{automatic-rename.yaml => options.yaml} | 5 +++++ 3 files changed, 25 insertions(+), 5 deletions(-) rename examples/{automatic-rename.json => options.json} (72%) rename examples/{automatic-rename.yaml => options.yaml} (64%) diff --git a/doc/examples.rst b/doc/examples.rst index 78bb173003..84f27f4d72 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -166,13 +166,15 @@ Environment variable replacing ------------------------------ tmuxp will replace environment variables wrapped in curly brackets -for the following variables: +for values of these settings: - ``start_directory`` - ``before_script`` - ``session_name`` - ``window_name`` - ``shell_command_before`` +- ``global_options`` +- ``options`` in session scope and window scope tmuxp replaces these variables before-hand with variables in the terminal ``tmuxp`` invokes in. @@ -278,19 +280,25 @@ JSON .. literalinclude:: ../examples/window-index.json :language: json -Automatic Rename +Set tmux options ---------------- +Works with global (server-wide) options, session options +and window options. + +Including ``automatic-rename``, ``default-shell``, +``default-command``, etc. + YAML ~~~~ -.. literalinclude:: ../examples/automatic-rename.yaml +.. literalinclude:: ../examples/options.yaml :language: yaml JSON ~~~~ -.. literalinclude:: ../examples/automatic-rename.json +.. literalinclude:: ../examples/options.json :language: json Main pane height diff --git a/examples/automatic-rename.json b/examples/options.json similarity index 72% rename from examples/automatic-rename.json rename to examples/options.json index 87c9d09ca0..c7df08b61c 100644 --- a/examples/automatic-rename.json +++ b/examples/options.json @@ -26,5 +26,12 @@ } ], "session_name": "test window options", - "start_directory": "~" + "start_directory": "~", + "global_options": { + "default-shell": "/bin/sh", + "default-command": "/bin/sh" + }, + "options": { + "main-pane-height": "${MAIN_PANE_HEIGHT}" + } } \ No newline at end of file diff --git a/examples/automatic-rename.yaml b/examples/options.yaml similarity index 64% rename from examples/automatic-rename.yaml rename to examples/options.yaml index fbbe8f08e4..2e6c108a4a 100644 --- a/examples/automatic-rename.yaml +++ b/examples/options.yaml @@ -1,5 +1,10 @@ session_name: test window options start_directory: '~' +global_options: + default-shell: /bin/sh + default-command: /bin/sh +options: + main-pane-height: ${MAIN_PANE_HEIGHT} # works with en variables windows: - layout: main-horizontal options: From bce44406fb0af1cfb6340e8f8d01815444293bcc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 15 Jun 2016 23:37:26 -0500 Subject: [PATCH 3/3] Allow failures for tmux master --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7d98d31be5..81879adbc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,9 @@ env: - TMUX_VERSION=2.0 - TMUX_VERSION=1.8 - TMUX_VERSION=1.9a +matrix: + allow_failures: + - env: TMUX_VERSION=master before_install: - export PIP_USE_MIRRORS=true - pip install --upgrade pytest # https://github.com/travis-ci/travis-ci/issues/4873