diff --git a/CHANGES b/CHANGES index 6f74f52c80..20050128a7 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,13 @@ CURRENT ------- - [internal]: Renamed ``config.expandpath`` to ``config.expandshell``. +- [internal] [tests]: compat 2.7/3.3 wrapper for ``EnvironmentVarGuard`` for + testing. +- [shell_command_before]: You can now use environment variables inside of + ``start_directory``, ``before_script``, ``shell_command_before``, + ``session_name`` and ``window_name``. +- [docs] [examples]: add example for environmental variables, + ``examples/env-variables.json`` and ``examples/env-variables.yaml``. 0.8.1 ----- diff --git a/doc/examples.rst b/doc/examples.rst index 2aa0fe4687..f3000aed34 100644 --- a/doc/examples.rst +++ b/doc/examples.rst @@ -162,6 +162,50 @@ JSON .. literalinclude:: ../examples/start-directory.json :language: json +Environment variables +--------------------- + +tmuxp will replace environment variables wrapped in curly brackets +for the following variables: + +- ``start_directory`` +- ``before_script`` +- ``session_name`` +- ``window_name`` +- ``before_shell_command`` + +tmuxp replaces these variables before-hand with variables in the +terminal ``tmuxp`` invokes in. + +In this case of this example, assuming the username "user":: + + $ MY_ENV_VAR=foo tmuxp load examples/env-variables.yaml + +and your session name will be ``session - user (foo)``. + +Shell variables in ``shell_command`` do not support this type of +concatenation. ``shell_command`` and ``before_shell_command`` both +support normal shell variables, since they are sent into panes +automatically via ``send-key`` in ``tmux(1)``. See ``ls $PWD`` in +example. + +If you have a special case and would like to see behavior changed, +please make a ticket on the `issue tracker`_. + +.. _issue tracker: https://github.com/tony/tmuxp/issues + +YAML +~~~~ + +.. literalinclude:: ../examples/env-variables.yaml + :language: yaml + +JSON +~~~~ + +.. literalinclude:: ../examples/env-variables.json + :language: json + Focusing -------- diff --git a/examples/env-variables.json b/examples/env-variables.json new file mode 100644 index 0000000000..a39301b8b4 --- /dev/null +++ b/examples/env-variables.json @@ -0,0 +1,31 @@ +{ + "before_script": "{MY_ENV_VAR}/test3.sh", + "windows": [ + { + "panes": [ + { + "shell_command": [ + "tail -F /var/log/syslog" + ] + } + ], + "start_directory": "/var/log", + "window_name": "editor" + }, + { + "panes": [ + { + "shell_command": [ + "htop", + "ls $PWD" + ] + } + ], + "window_name": "logging for {USER}", + "automatic_rename": true + } + ], + "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 new file mode 100644 index 0000000000..b2075bf59b --- /dev/null +++ b/examples/env-variables.yaml @@ -0,0 +1,16 @@ +start_directory: "{PWD}/test" +shell_command_before: "echo {PWD}" +before_script: "{MY_ENV_VAR}/test3.sh" +session_name: session - {USER} ({MY_ENV_VAR}) +windows: +- window_name: editor + panes: + - shell_command: + - tail -F /var/log/syslog + start_directory: /var/log +- window_name: logging for {USER} + automatic_rename: true + panes: + - shell_command: + - htop + - ls $PWD diff --git a/tmuxp/_compat.py b/tmuxp/_compat.py index ca238300d3..a12b65b17f 100644 --- a/tmuxp/_compat.py +++ b/tmuxp/_compat.py @@ -33,6 +33,8 @@ from string import lower as ascii_lowercase import urlparse + from test import test_support as support + exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') def implements_to_string(cls): @@ -71,6 +73,8 @@ def console_to_str(s): import urllib.parse as urlparse from urllib.request import urlretrieve + from test import support + console_encoding = sys.__stdout__.encoding implements_to_string = _identity diff --git a/tmuxp/config.py b/tmuxp/config.py index 977009c6c2..17860b6baf 100644 --- a/tmuxp/config.py +++ b/tmuxp/config.py @@ -185,6 +185,11 @@ def expand(sconf, cwd=None, parent=None): if not cwd: cwd = os.getcwd() + if 'session_name' in sconf: + sconf['session_name'] = expandshell(sconf['session_name']) + if 'window_name' in sconf: + sconf['window_name'] = expandshell(sconf['window_name']) + # Any config section, session, window, pane that can contain the # 'shell_command' value if 'start_directory' in sconf: @@ -202,12 +207,12 @@ def expand(sconf, cwd=None, parent=None): start_path = os.path.normpath(os.path.join(cwd, start_path)) sconf['start_directory'] = start_path - if 'before_script' in sconf: - before_script = sconf['before_script'] - if any(before_script.startswith(a) for a in ['.', './']): - before_script = os.path.normpath(os.path.join(cwd, before_script)) - sconf['before_script'] = before_script + sconf['before_script'] = expandshell(sconf['before_script']) + if any(sconf['before_script'].startswith(a) for a in ['.', './']): + sconf['before_script'] = os.path.normpath( + os.path.join(cwd, sconf['before_script']) + ) if ( 'shell_command' in sconf and @@ -221,6 +226,14 @@ def expand(sconf, cwd=None, parent=None): ): sconf['shell_command_before'] = [sconf['shell_command_before']] + if ( + 'shell_command_before' in sconf and + isinstance(sconf['shell_command_before'], list) + ): + sconf['shell_command_before'] = [ + expandshell(scmd) for scmd in sconf['shell_command_before'] + ] + # recurse into window and pane config items if 'windows' in sconf: sconf['windows'] = [ diff --git a/tmuxp/testsuite/config.py b/tmuxp/testsuite/config.py index bbb44a6fa0..84455a7d0f 100644 --- a/tmuxp/testsuite/config.py +++ b/tmuxp/testsuite/config.py @@ -18,9 +18,11 @@ import kaptan from .. import config, exc +from .._compat import support from .helpers import TestCase + logger = logging.getLogger(__name__) TMUXP_DIR = os.path.join(os.path.dirname(__file__), '.tmuxp') current_dir = os.path.abspath(os.path.dirname(__file__)) @@ -1061,6 +1063,42 @@ def test_no_window_name(self): config.validate_schema(sconfig) +class ConfigExpandEnvironmentVariables(TestCase, unittest.TestCase): + def test_replaces_start_directory(self): + env_key = "TESTHEY92" + env_value = "HEYO1" + yaml_config = """ + start_directory: {TEST_VAR}/test + shell_command_before: {TEST_VAR}/test2 + before_script: {TEST_VAR}/test3 + session_name: hi - {TEST_VAR} + windows: + - window_name: editor + panes: + - shell_command: + - tail -F /var/log/syslog + start_directory: /var/log + - window_name: logging @ {TEST_VAR} + automatic_rename: true + panes: + - shell_command: + - htop + """.format( + TEST_VAR="${%s}" % env_key + ) + + sconfig = kaptan.Kaptan(handler='yaml') + sconfig = sconfig.import_config(yaml_config).get() + + with support.EnvironmentVarGuard() as env: + env.set(env_key, env_value) + sconfig = config.expand(sconfig) + self.assertEqual("%s/test" % env_value, sconfig['start_directory']) + self.assertIn("%s/test2" % env_value, sconfig['shell_command_before']) + self.assertEqual("%s/test3" % env_value, sconfig['before_script']) + self.assertEqual("hi - %s" % env_value, sconfig['session_name']) + self.assertEqual("logging @ %s" % env_value, sconfig['windows'][1]['window_name']) + def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ConfigBlankPanes)) @@ -1071,4 +1109,5 @@ def suite(): suite.addTest(unittest.makeSuite(ShellCommandBeforeTest)) suite.addTest(unittest.makeSuite(ShellCommandBeforeSession)) suite.addTest(unittest.makeSuite(TrickleRelativeStartDirectory)) + suite.addTest(unittest.makeSuite(ConfigExpandEnvironmentVariables)) return suite