Skip to content

Commit 1228422

Browse files
committed
Updating the location of the before_script plugin method execution. Updating corresponding tests. Starting on the documentation
1 parent 3a4bef3 commit 1228422

File tree

10 files changed

+224
-27
lines changed

10 files changed

+224
-27
lines changed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Table of Contents
2828
quickstart
2929
examples
3030
cli
31+
plugin_system
3132
developing
3233
api
3334
history

docs/plugin_system.rst

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
.. _plugin_system:
2+
3+
=============
4+
Plugin System
5+
=============
6+
7+
The plugin system allows users to customize and extend different aspects of
8+
tmuxp without the need to change tmuxp itself.
9+
10+
11+
Using a Plugin
12+
--------------
13+
14+
To use a plugin, install it in your local python environment and add it to
15+
your tmuxp configuration file.
16+
17+
Example Configurations
18+
^^^^^^^^^^^^^^^^^^^^^^
19+
YAML
20+
~~~~
21+
22+
.. literalinclude:: ../examples/plugin-system.yaml
23+
:language: yaml
24+
25+
JSON
26+
~~~~
27+
28+
.. literalinclude:: ../examples/plugin-system.json
29+
:language: json
30+
31+
.. _poetry: https://python-poetry.org/
32+
33+
34+
Developing a Plugin
35+
-------------------
36+
37+
.. module:: tmuxp
38+
39+
Plugin API
40+
^^^^^^^^^^
41+
42+
.. automethod:: tmuxp.plugin.TmuxpPluginInterface.before_workspace_builder
43+
.. automethod:: tmuxp.plugin.TmuxpPluginInterface.on_window_create
44+
.. automethod:: tmuxp.plugin.TmuxpPluginInterface.after_window_finished
45+
.. automethod:: tmuxp.plugin.TmuxpPluginInterface.before_script
46+
.. automethod:: tmuxp.plugin.TmuxpPluginInterface.reattach
47+
48+
49+
Example Plugin
50+
--------------
51+
52+
Tmuxp expects all plugins to be class within a python submodule named
53+
``plugin`` that is within a python module that is installed in the local
54+
python environment. A plugin interface is provided by tmuxp to inherit.
55+
56+
`poetry`_ is the chosen python package manager for tmuxp. It is highly
57+
suggested to use it when developing tmuxp plugins; however, ``pip`` will work
58+
just as well.
59+
60+
.. code-block:: bash
61+
62+
python_module
63+
├── my_plugin_module
64+
│   ├── __init__.py
65+
│   └── plugin.py
66+
├── pyproject.toml # Poetry's module configuration file
67+
└── setup.py # pip's module configuration file
68+
69+
The `plugin.py` file could contain something like the following:
70+
71+
.. code-block:: python
72+
73+
from tmuxp.plugin import TmuxpPluginInterface
74+
import datetime
75+
76+
class MyTmuxpPlugin(TmuxpPluginInterface):
77+
def __init__(self):
78+
super.__init__(self)
79+
80+
def before_workspace_builder(self, session):
81+
session.rename_session('my-new-session-name')
82+
83+
def reattach(self, session):
84+
now = datetime.datetime.now().strftime('%Y-%m-%d')
85+
session.rename_session('session_{}'.format(now))
86+
87+
Once this plugin is installed in the local python environment, it can be used
88+
in a configuration file like the following:
89+
90+
.. code-block: yaml
91+
92+
session_name: plugin example
93+
plugins:
94+
- my_plugin_module.plugin.MyTmuxpPlugin
95+
# ... the rest of your config

examples/plugin-system.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"session_name": "plugin-system",
3+
"plugins": [
4+
"tmuxp_plugin_extended_build.plugin.PluginExtendedBuild"
5+
],
6+
"windows": [
7+
{
8+
"window_name": "editor",
9+
"layout": "tiled",
10+
"shell_command_before": [
11+
"cd ~/"
12+
],
13+
"panes": [
14+
{
15+
"shell_command": [
16+
"cd /var/log",
17+
"ls -al | grep *.log"
18+
]
19+
},
20+
"echo \"hello world\""
21+
]
22+
}
23+
]
24+
}

examples/plugin-system.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
session_name: plugin-system
2+
plugins:
3+
- 'tmuxp_plugin_extended_build.plugin.PluginExtendedBuild'
4+
windows:
5+
- window_name: editor
6+
layout: tiled
7+
shell_command_before:
8+
- cd ~/
9+
panes:
10+
- shell_command:
11+
- cd /var/log
12+
- ls -al | grep *.log
13+
- echo "hello world"

tests/fixtures/workspacebuilder/plugin_multiple_plugins.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
session_name: plugin-test-multiple-plugins
22
plugins:
33
- 'tmuxp_test_plugin_bwb.plugin.PluginBeforeWorkspaceBuilder'
4-
- 'tmuxp_test_plugin_bs.plugin.PluginBeforeScript'
54
- 'tmuxp_test_plugin_owc.plugin.PluginOnWindowCreate'
65
- 'tmuxp_test_plugin_awf.plugin.PluginAfterWindowFinished'
76
windows:

tests/test_cli.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,22 @@ def test_ls_cli(monkeypatch, tmpdir):
959959
assert cli_output == '\n'.join(stems) + '\n'
960960

961961

962+
def test_plugin_system_before_script(server, monkeypatch):
963+
# this is an implementation test. Since this testsuite may be ran within
964+
# a tmux session by the developer himself, delete the TMUX variable
965+
# temporarily.
966+
monkeypatch.delenv('TMUX', raising=False)
967+
session_file = curjoin("workspacebuilder/plugin_bs.yaml")
968+
969+
# open it detached
970+
session = load_workspace(
971+
session_file, socket_name=server.socket_name, detached=True
972+
)
973+
974+
assert isinstance(session, libtmux.Session)
975+
assert session.name == 'plugin_test_bs'
976+
977+
962978
def test_reattach_plugins(server):
963979
config_plugins = loadfixture("workspacebuilder/plugin_r.yaml")
964980

@@ -977,4 +993,4 @@ def test_reattach_plugins(server):
977993

978994
proc = builder.session.cmd('display-message', '-p', "'#S'")
979995

980-
assert proc.stdout[0] == "'plugin_test_r'"
996+
assert proc.stdout[0] == "'plugin_test_r'"

tests/test_workspacebuilder.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -710,22 +710,6 @@ def test_plugin_system_before_workspace_builder(session):
710710
assert proc.stdout[0] == "'plugin_test_bwb'"
711711

712712

713-
def test_plugin_system_before_script(session):
714-
config_plugins = loadfixture("workspacebuilder/plugin_bs.yaml")
715-
716-
sconfig = kaptan.Kaptan(handler='yaml')
717-
sconfig = sconfig.import_config(config_plugins).get()
718-
sconfig = config.expand(sconfig)
719-
720-
builder = WorkspaceBuilder(sconf=sconfig)
721-
assert len(builder.plugins) > 0
722-
723-
builder.build(session=session)
724-
725-
proc = session.cmd('display-message', '-p', "'#S'")
726-
assert proc.stdout[0] == "'plugin_test_bs'"
727-
728-
729713
def test_plugin_system_on_window_create(session):
730714
config_plugins = loadfixture("workspacebuilder/plugin_owc.yaml")
731715

@@ -806,7 +790,7 @@ def test_plugin_system_multiple_plugins(session):
806790

807791
# Drop through to the before_script plugin hook
808792
proc = session.cmd('display-message', '-p', "'#S'")
809-
assert proc.stdout[0] == "'plugin_test_bs'"
793+
assert proc.stdout[0] == "'plugin_test_bwb'"
810794

811795
# Drop through to the after_window_finished. This won't succeed
812796
# unless on_window_create succeeds because of how the test plugin

tmuxp/cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,10 @@ def load_workspace(
601601
else:
602602
sys.exit()
603603

604+
# Runs after before_script
605+
for plugin in builder.plugins:
606+
plugin.before_script(builder.session)
607+
604608
return builder.session
605609

606610

tmuxp/plugin.py

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,83 @@
11
class TmuxpPluginInterface:
22
def __init__(self):
3+
"""
4+
Initialize plugin interface.
5+
"""
36
pass
47

58
def before_workspace_builder(self, session):
6-
pass
9+
"""
10+
Provide a session hook previous to creating the workspace.
711
8-
def before_script(self, session):
9-
pass
12+
Parameters
13+
----------
14+
session : :class:`libtmux.Session`
15+
session to hook into
1016
11-
def reattach(self, session):
17+
Notes
18+
-----
19+
This runs after the session has been created but before any of
20+
the windows/panes/commands are entered.
21+
"""
1222
pass
1323

1424
def on_window_create(self, window):
25+
"""
26+
Provide a window hook previous to creating the window.
27+
28+
Parameters
29+
----------
30+
window: :class:`libtmux.Window`
31+
window to hook into
32+
33+
Notes
34+
-----
35+
This runs runs before anything is created in the windows, like panes.
36+
"""
1537
pass
1638

1739
def after_window_finished(self, window):
40+
"""
41+
Provide a window hook after creating the window.
42+
43+
Parameters
44+
----------
45+
window: :class:`libtmux.Window`
46+
window to hook into
47+
48+
Notes
49+
-----
50+
This runs after everything has been created in the window, including
51+
the paes and all of the commands for the panes. It also runs after the
52+
``options_after`` have been applied to the window.
53+
"""
1854
pass
55+
56+
def before_script(self, session):
57+
"""
58+
Provide a session hook after the workspace has been built.
59+
60+
Parameters
61+
----------
62+
session : :class:`libtmux.Session`
63+
session to hook into
64+
65+
Notes
66+
-----
67+
This runs after the workspace has been loaded with ``tmuxp load``. It
68+
augments instead of replaces the ``before_script`` section of the
69+
configuration. If changes to the session need to be made prior to
70+
anything being built, please use ``before_workspace_builder`` instead.
71+
"""
72+
pass
73+
74+
def reattach(self, session):
75+
"""
76+
Provide a session hook before reattaching to the session.
77+
78+
Parameters
79+
----------
80+
session : :class:`libtmux.Session`
81+
session to hook into
82+
"""
83+
pass

tmuxp/workspacebuilder.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ def build(self, session=None):
207207
for option, value in self.sconf['environment'].items():
208208
self.session.set_environment(option, value)
209209

210-
# Runs after before_script
211-
for plugin in self.plugins:
212-
plugin.before_script(self.session)
213-
214210
for w, wconf in self.iter_create_windows(session):
215211
assert isinstance(w, Window)
216212

0 commit comments

Comments
 (0)