Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions doc/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ JSON
.. literalinclude:: ../examples/start-directory.json
:language: json

Environment variables
---------------------
Environment variable replacing
------------------------------

tmuxp will replace environment variables wrapped in curly brackets
for the following variables:
Expand Down Expand Up @@ -206,6 +206,23 @@ JSON
.. literalinclude:: ../examples/env-variables.json
:language: json

Environment variables
---------------------

tmuxp will set session environment variables.

YAML
~~~~

.. literalinclude:: ../examples/session-environment.yaml
:language: yaml

JSON
~~~~

.. literalinclude:: ../examples/session-environment.json
:language: json

Focusing
--------

Expand Down
15 changes: 15 additions & 0 deletions examples/session-environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"environment": {
"EDITOR": "/usr/bin/vim",
"HOME": "/tmp/hm",
},
"windows": [
{
"panes": [
null,
],
"window_name": "Blank pane test"
},
],
"session_name": "Environment variables test"
}
10 changes: 10 additions & 0 deletions examples/session-environment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
session_name: Environment variables test
environment:
EDITOR: /usr/bin/vim
HOME: /tmp/hm
windows:
# Emptiness will simply open a blank pane, if no shell_command_before.
# All these are equivalent
- window_name: Blank pane test
panes:
-
103 changes: 103 additions & 0 deletions tmuxp/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

class EnvironmentMixin(object):

"""Mixin class for managing session and server level environment
variables in tmux.

"""

_add_option = None

def __init__(self, add_option=None):
self._add_option = add_option

def set_environment(self, name, value):
"""Set environment ``$ tmux set-environment <name> <value>``.

:param name: the environment variable name. such as 'PATH'.
:type option: string
:param value: environment value.
:type value: string

"""

args = ['set-environment']
if self._add_option:
args += [self._add_option]

args += [name, value]

proc = self.cmd(*args)

if proc.stderr:
if isinstance(proc.stderr, list) and len(proc.stderr) == int(1):
proc.stderr = proc.stderr[0]
raise ValueError('tmux set-environment stderr: %s' % proc.stderr)

def unset_environment(self, name):
"""Unset environment variable ``$ tmux set-environment -u <name>``.

:param name: the environment variable name. such as 'PATH'.
:type option: string
"""

args = ['set-environment']
if self._add_option:
args += [self._add_option]
args += ['-u', name]

proc = self.cmd(*args)

if proc.stderr:
if isinstance(proc.stderr, list) and len(proc.stderr) == int(1):
proc.stderr = proc.stderr[0]
raise ValueError('tmux set-environment stderr: %s' % proc.stderr)

def remove_environment(self, name):
"""Remove environment variable ``$ tmux set-environment -r <name>``.

:param name: the environment variable name. such as 'PATH'.
:type option: string
"""

args = ['set-environment']
if self._add_option:
args += [self._add_option]
args += ['-r', name]

proc = self.cmd(*args)

if proc.stderr:
if isinstance(proc.stderr, list) and len(proc.stderr) == int(1):
proc.stderr = proc.stderr[0]
raise ValueError('tmux set-environment stderr: %s' % proc.stderr)

def show_environment(self, name=None):
"""Show environment ``$tmux show-environment -t [session] <name>``.

Return dict of environment variables for the session or the value of a
specific variable if the name is specified.

:param name: the environment variable name. such as 'PATH'.
:type option: string
"""
tmux_args = ['show-environment']
if self._add_option:
tmux_args += [self._add_option]
if name:
tmux_args += [name]
vars = self.cmd(*tmux_args).stdout
vars = [tuple(item.split('=', 1)) for item in vars]
vars_dict = {}
for t in vars:
if len(t) == 2:
vars_dict[t[0]] = t[1]
elif len(t) == 1:
vars_dict[t[0]] = True
else:
raise ValueError('unexpected variable %s', t)

if name:
return vars_dict.get(name)

return vars_dict
8 changes: 7 additions & 1 deletion tmuxp/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,13 @@ def expand(sconf, cwd=None, parent=None):
sconf['session_name'] = expandshell(sconf['session_name'])
if 'window_name' in sconf:
sconf['window_name'] = expandshell(sconf['window_name'])

if 'environment' in sconf:
for key in sconf['environment']:
val = sconf['environment'][key]
val = expandshell(val)
if any(val.startswith(a) for a in ['.', './']):
val = os.path.normpath(os.path.join(cwd, val))
sconf['environment'][key] = val
# Any config section, session, window, pane that can contain the
# 'shell_command' value
if 'start_directory' in sconf:
Expand Down
6 changes: 4 additions & 2 deletions tmuxp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
from . import formats, exc
from .session import Session
from .util import tmux_cmd, TmuxRelationalObject
from .common import EnvironmentMixin

logger = logging.getLogger(__name__)


class Server(TmuxRelationalObject):
class Server(TmuxRelationalObject, EnvironmentMixin):

"""The :term:`tmux(1)` server.

Expand Down Expand Up @@ -54,6 +55,7 @@ def __init__(
colors=None,
**kwargs
):
EnvironmentMixin.__init__(self, '-g')
self._windows = []
self._panes = []

Expand Down Expand Up @@ -383,7 +385,7 @@ def attach_session(self, target_session=None):

if proc.stderr:
raise exc.TmuxpException(proc.stderr)

def new_session(self,
session_name=None,
kill_session=False,
Expand Down
5 changes: 3 additions & 2 deletions tmuxp/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@

from . import util, formats, exc
from .window import Window
from .common import EnvironmentMixin

logger = logging.getLogger(__name__)


class Session(util.TmuxMappingObject, util.TmuxRelationalObject):
class Session(util.TmuxMappingObject, util.TmuxRelationalObject, EnvironmentMixin):

""":term:`tmux(1)` session.

Expand All @@ -28,7 +29,7 @@ class Session(util.TmuxMappingObject, util.TmuxRelationalObject):
childIdAttribute = 'window_id'

def __init__(self, server=None, **kwargs):

EnvironmentMixin.__init__(self)
self.server = server

if not 'session_id' in kwargs:
Expand Down
23 changes: 23 additions & 0 deletions tmuxp/testsuite/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,29 @@ def test_88_colors(self):
self.assertIn('-8', proc.cmd)
self.assertNotIn('-2', proc.cmd)

class Environment(TmuxTestCase):

def test_show_environment(self):
"""Server.show_environment() returns dict."""

vars = self.server.show_environment()
self.assertIsInstance(vars, dict)

def test_set_show_environment_single(self):
"""Set environment then Server.show_environment(key)."""

self.server.set_environment('FOO', 'BAR')
self.assertEqual('BAR', self.server.show_environment('FOO'))

self.server.set_environment('FOO', 'DAR')
self.assertEqual('DAR', self.server.show_environment('FOO'))

self.assertEqual('DAR', self.server.show_environment()['FOO'])

def test_show_environment_not_set(self):
"""Unset environment variable returns None."""
self.assertEqual(None, self.server.show_environment('BAR'))


def suite():
suite = unittest.TestSuite()
Expand Down
41 changes: 41 additions & 0 deletions tmuxp/testsuite/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,50 @@ def test_set_option_bad(self):
self.session.set_option('afewewfew', 43)


class Environment(TmuxTestCase):

def test_show_environment(self):
"""Session.show_environment() returns dict."""

vars = self.session.show_environment()
self.assertIsInstance(vars, dict)

def test_set_show_environment_single(self):
"""Set environment then Session.show_environment(key)."""

self.session.set_environment('FOO', 'BAR')
self.assertEqual('BAR', self.session.show_environment('FOO'))

self.session.set_environment('FOO', 'DAR')
self.assertEqual('DAR', self.session.show_environment('FOO'))

self.assertEqual('DAR', self.session.show_environment()['FOO'])

def test_show_environment_not_set(self):
"""Not set environment variable returns None."""
self.assertEqual(None, self.session.show_environment('BAR'))

def test_remove_environment(self):
"""Remove environment variable."""
self.assertEqual(None, self.session.show_environment('BAM'))
self.session.set_environment('BAM', 'OK')
self.assertEqual('OK', self.session.show_environment('BAM'))
self.session.remove_environment('BAM')
self.assertEqual(None, self.session.show_environment('BAM'))

def test_unset_environment(self):
"""Unset environment variable."""
self.assertEqual(None, self.session.show_environment('BAM'))
self.session.set_environment('BAM', 'OK')
self.assertEqual('OK', self.session.show_environment('BAM'))
self.session.unset_environment('BAM')
self.assertEqual(None, self.session.show_environment('BAM'))


def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(Options))
suite.addTest(unittest.makeSuite(Environment))
suite.addTest(unittest.makeSuite(SessionNewTest))
suite.addTest(unittest.makeSuite(SessionTest))
return suite
29 changes: 28 additions & 1 deletion tmuxp/testsuite/workspacebuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def test_focus_pane_index(self):
self.assertNotEqual(w.get('window_name'), 'man')

pane_path = '/usr'
for i in range(10):
for i in range(20):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails for me at a noticeable frequency with only 10 retries.

p = w.attached_pane()
p.server._update_panes()
if p.get('pane_current_path') == pane_path:
Expand Down Expand Up @@ -254,6 +254,32 @@ def test_window_options(self):
w.select_layout(wconf['layout'])


class EnvironmentVariables(TmuxTestCase):

yaml_config = """
session_name: test env vars
start_directory: '~'
environment:
FOO: BAR
PATH: /tmp
windows:
- layout: main-horizontal
panes:
- pane
window_name: editor
"""

def test_environment_variables(self):
sconfig = kaptan.Kaptan(handler='yaml')
sconfig = sconfig.import_config(self.yaml_config).get()
sconfig = config.expand(sconfig)

builder = WorkspaceBuilder(sconf=sconfig)
builder.build(self.session)

self.assertEqual('BAR', self.session.show_environment('FOO'))
self.assertEqual('/tmp', self.session.show_environment('PATH'))

class WindowAutomaticRename(TmuxTestCase):

yaml_config = """
Expand Down Expand Up @@ -869,4 +895,5 @@ def suite():
suite.addTest(unittest.makeSuite(WindowAutomaticRename))
suite.addTest(unittest.makeSuite(WindowIndexTest))
suite.addTest(unittest.makeSuite(WindowOptions))
suite.addTest(unittest.makeSuite(EnvironmentVariables))
return suite
3 changes: 3 additions & 0 deletions tmuxp/workspacebuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ def build(self, session=None):
except Exception as e:
self.session.kill_session()
raise(e)
if 'environment' in self.sconf:
for option, value in self.sconf['environment'].items():
self.session.set_environment(option, value)

for w, wconf in self.iter_create_windows(session):
assert(isinstance(w, Window))
Expand Down