Skip to content

Commit b356b92

Browse files
authored
refactor,docs: Streamline and document direct commands (#527)
### Cleanups (#527) - Streamline `{Server,Session,Window,Pane}.cmd()`, across all usages to: - Use `cmd: str` as first positional - Removed unused keyword arguments `**kwargs` ### Renamings (#527) - `Session.attached_window` renamed to `Session.active_window` - `Session.attached_window` deprecated - `Session.attached_pane` renamed to `Session.active_pane` - `Session.attached_pane` deprecated - `Window.attached_pane` renamed to `Window.active_pane` - `Window.attached_pane` deprecated ### Improvements (#527) - `Server.attached_windows` now users `QueryList`'s `.filter()` ### Documentation (#527) - Document `.cmd` in README and quickstart - Add doctests and improve docstrings to `cmd()` methods across: - `Server.cmd()` - `Session.cmd()` - `Window.cmd()` - `Pane.cmd()`
2 parents e76360a + e7eb5a5 commit b356b92

17 files changed

+400
-167
lines changed

CHANGES

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,34 @@ $ pip install --user --upgrade --pre libtmux
1515

1616
<!-- To maintainers and contributors: Please add notes for the forthcoming version above -->
1717

18+
### Cleanups (#527)
19+
20+
- Streamline `{Server,Session,Window,Pane}.cmd()`, across all usages to:
21+
- Use `cmd: str` as first positional
22+
- Removed unused keyword arguments `**kwargs`
23+
24+
### Renamings (#527)
25+
26+
- `Session.attached_window` renamed to {meth}`Session.active_window`
27+
- `Session.attached_window` deprecated
28+
- `Session.attached_pane` renamed to {meth}`Session.active_pane`
29+
- `Session.attached_pane` deprecated
30+
- `Window.attached_pane` renamed to {meth}`Window.active_pane`
31+
- `Window.attached_pane` deprecated
32+
33+
### Improvements (#527)
34+
35+
- `Server.attached_windows` now users `QueryList`'s `.filter()`
36+
37+
### Documentation (#527)
38+
39+
- Document `.cmd` in README and quickstart
40+
- Add doctests and improve docstrings to `cmd()` methods across:
41+
- {meth}`Server.cmd()`
42+
- {meth}`Session.cmd()`
43+
- {meth}`Window.cmd()`
44+
- {meth}`Pane.cmd()`
45+
1846
## libtmux 0.30.2 (2024-02-16)
1947

2048
### Development
@@ -80,7 +108,7 @@ _Maintenance only, no bug fixes or new features_
80108

81109
## libtmux 0.28.0 (2024-02-14)
82110

83-
### Breaking change
111+
### Breaking changes
84112

85113
#### Detached / unselected by default (#523)
86114

@@ -164,7 +192,7 @@ Tip: If {meth}`Pane.resize()` was not taking affect <= 0.27.1, try to resize wit
164192

165193
## libtmux 0.26.0 (2024-02-06)
166194

167-
### Breaking change
195+
### Breaking changes
168196

169197
- `get_by_id()` (already deprecated) keyword argument renamed from `id` to
170198
`Server.get_by_id(session_id)`, `Session.get_by_id(window_id)`, and `Window.get_by_id(pane_id)` (#514)

README.md

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ Connect to a live tmux session:
5353

5454
```python
5555
>>> import libtmux
56-
>>> s = libtmux.Server()
57-
>>> s
56+
>>> svr = libtmux.Server()
57+
>>> svr
5858
Server(socket_path=/tmp/tmux-.../default)
5959
```
6060

@@ -66,6 +66,49 @@ current tmux server / session / window pane.
6666
[ptpython]: https://github.com/prompt-toolkit/ptpython
6767
[ipython]: https://ipython.org/
6868

69+
Run any tmux command, respective of context:
70+
71+
Honors tmux socket name and path:
72+
73+
```python
74+
>>> server = Server(socket_name='libtmux_doctest')
75+
>>> server.cmd('display-message', 'hello world')
76+
<libtmux...>
77+
```
78+
79+
New session:
80+
81+
```python
82+
>>> server.cmd('new-session', '-d', '-P', '-F#{session_id}').stdout[0]
83+
'$2'
84+
```
85+
86+
```python
87+
>>> session.cmd('new-window', '-P').stdout[0]
88+
'libtmux...:2.0'
89+
```
90+
91+
Time for some tech, direct to a rich, `Window` object:
92+
93+
```python
94+
>>> Window.from_window_id(window_id=session.cmd('new-window', '-P', '-F#{window_id}').stdout[0], server=session.server)
95+
Window(@2 2:..., Session($1 libtmux_...))
96+
```
97+
98+
Create a pane from a window:
99+
100+
```python
101+
>>> window.cmd('split-window', '-P', '-F#{pane_id}').stdout[0]
102+
'%2'
103+
```
104+
105+
Magic, directly to a `Pane`:
106+
107+
```python
108+
>>> Pane.from_pane_id(pane_id=session.cmd('split-window', '-P', '-F#{pane_id}').stdout[0], server=session.server)
109+
Pane(%... Window(@1 1:..., Session($1 libtmux_...)))
110+
```
111+
69112
List sessions:
70113

71114
```python
@@ -87,43 +130,57 @@ Direct lookup:
87130
Session($1 ...)
88131
```
89132

90-
Find session by dict lookup:
133+
Filter sesions:
91134

92135
```python
93136
>>> server.sessions[0].rename_session('foo')
94137
Session($1 foo)
95-
>>> server.sessions.filter(session_name="foo")[0]
138+
>>> server.sessions.filter(session_name="foo")
139+
[Session($1 foo)]
140+
>>> server.sessions.get(session_name="foo")
96141
Session($1 foo)
97142
```
98143

99144
Control your session:
100145

101146
```python
102-
>>> session.rename_session('foo')
103-
Session($1 foo)
104-
>>> session.new_window(attach=False, window_name="ha in the bg")
105-
Window(@2 2:ha in the bg, Session($1 foo))
106-
>>> session.kill_window("ha in")
147+
>>> session
148+
Session($1 ...)
149+
150+
>>> session.rename_session('my-session')
151+
Session($1 my-session)
107152
```
108153

109154
Create new window in the background (don't switch to it):
110155

111156
```python
112-
>>> session.new_window(attach=False, window_name="ha in the bg")
113-
Window(@2 2:ha in the bg, Session($1 ...))
157+
>>> bg_window = session.new_window(attach=False, window_name="ha in the bg")
158+
>>> bg_window
159+
Window(@... 2:ha in the bg, Session($1 ...))
160+
161+
# Session can search the window
162+
>>> session.windows.filter(window_name__startswith="ha")
163+
[Window(@... 2:ha in the bg, Session($1 ...))]
164+
165+
# Directly
166+
>>> session.windows.get(window_name__startswith="ha")
167+
Window(@... 2:ha in the bg, Session($1 ...))
168+
169+
# Clean up
170+
>>> bg_window.kill()
114171
```
115172

116173
Close window:
117174

118175
```python
119-
>>> w = session.attached_window
176+
>>> w = session.active_window
120177
>>> w.kill()
121178
```
122179

123180
Grab remaining tmux window:
124181

125182
```python
126-
>>> window = session.attached_window
183+
>>> window = session.active_window
127184
>>> window.split_window(attach=False)
128185
Pane(%2 Window(@1 1:... Session($1 ...)))
129186
```

conftest.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
import pytest
1515
from _pytest.doctest import DoctestItem
1616

17+
from libtmux.pane import Pane
1718
from libtmux.pytest_plugin import USING_ZSH
19+
from libtmux.server import Server
20+
from libtmux.session import Session
21+
from libtmux.window import Window
1822

1923
if t.TYPE_CHECKING:
2024
from libtmux.session import Session
@@ -30,11 +34,15 @@ def add_doctest_fixtures(
3034
"""Configure doctest fixtures for pytest-doctest."""
3135
if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"):
3236
request.getfixturevalue("set_home")
37+
doctest_namespace["Server"] = Server
38+
doctest_namespace["Session"] = Session
39+
doctest_namespace["Window"] = Window
40+
doctest_namespace["Pane"] = Pane
3341
doctest_namespace["server"] = request.getfixturevalue("server")
3442
session: "Session" = request.getfixturevalue("session")
3543
doctest_namespace["session"] = session
36-
doctest_namespace["window"] = session.attached_window
37-
doctest_namespace["pane"] = session.attached_pane
44+
doctest_namespace["window"] = session.active_window
45+
doctest_namespace["pane"] = session.active_pane
3846
doctest_namespace["request"] = request
3947

4048

docs/quickstart.md

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,44 @@ equivalent to `$ tmux -L mysocket`.
120120
`server` is now a living object bound to the tmux server's Sessions,
121121
Windows and Panes.
122122

123+
## Raw, contextual commands
124+
125+
New session:
126+
127+
```python
128+
>>> server.cmd('new-session', '-d', '-P', '-F#{session_id}').stdout[0]
129+
'$2'
130+
```
131+
132+
```python
133+
>>> session.cmd('new-window', '-P').stdout[0]
134+
'libtmux...:2.0'
135+
```
136+
137+
Time for some tech, direct to a rich, `Window` object:
138+
139+
```python
140+
>>> Window.from_window_id(window_id=session.cmd('new-window', '-P', '-F#{window_id}').stdout[0], server=session.server)
141+
Window(@2 2:..., Session($1 libtmux_...))
142+
```
143+
144+
Create a pane from a window:
145+
146+
```python
147+
>>> window.cmd('split-window', '-P', '-F#{pane_id}').stdout[0]
148+
'%2'
149+
```
150+
151+
Magic, directly to a `Pane`:
152+
153+
```python
154+
>>> Pane.from_pane_id(pane_id=session.cmd('split-window', '-P', '-F#{pane_id}').stdout[0], server=session.server)
155+
Pane(%... Window(@1 1:..., Session($1 libtmux_...)))
156+
```
157+
123158
## Find your {class}`Session`
124159

125-
If you have multiple tmux sessions open, you can see that all of the
126-
methods in {class}`Server` are available.
160+
If you have multiple tmux sessions open, all methods in {class}`Server` are available.
127161

128162
We can list sessions with {meth}`Server.sessions`:
129163

@@ -268,11 +302,11 @@ through active {class}`Window`'s.
268302

269303
## Manipulating windows
270304

271-
Now that we know how to create windows, let's use one. Let's use {meth}`Session.attached_window()`
305+
Now that we know how to create windows, let's use one. Let's use {meth}`Session.active_window()`
272306
to grab our current window.
273307

274308
```python
275-
>>> window = session.attached_window
309+
>>> window = session.active_window
276310
```
277311

278312
`window` now has access to all of the objects inside of {class}`Window`.
@@ -286,7 +320,7 @@ Pane(%2 Window(@1 ...:..., Session($1 ...)))
286320

287321
Powered up. Let's have a break down:
288322

289-
1. `window = session.attached_window()` gave us the {class}`Window` of the current attached to window.
323+
1. `window = session.active_window()` gave us the {class}`Window` of the current attached to window.
290324
2. `attach=False` assures the cursor didn't switch to the newly created pane.
291325
3. Returned the created {class}`Pane`.
292326

docs/reference/properties.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ from libtmux.neo import Obj
7575
The same concepts apply for {class}`~libtmux.Window`:
7676

7777
```python
78-
>>> window = session.attached_window
78+
>>> window = session.active_window
7979

8080
>>> window
8181
Window(@1 ...:..., Session($1 ...))
@@ -109,7 +109,7 @@ Use attribute access for details not accessible via properties:
109109
Get the {class}`~libtmux.Pane`:
110110

111111
```python
112-
>>> pane = window.attached_pane
112+
>>> pane = window.active_pane
113113

114114
>>> pane
115115
Pane(%1 Window(@1 ...:..., Session($1 libtmux_...)))

docs/topics/traversal.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,27 @@ Window(@1 ...:..., Session($1 ...))
7171
Grab the currently focused window from session:
7272

7373
```python
74-
>>> session.attached_window
74+
>>> session.active_window
7575
Window(@1 ...:..., Session($1 ...))
7676
```
7777

7878
Grab the currently focused {class}`Pane` from session:
7979

8080
```python
81-
>>> session.attached_pane
81+
>>> session.active_pane
8282
Pane(%1 Window(@1 ...:..., Session($1 ...)))
8383
```
8484

8585
Assign the attached {class}`~libtmux.Pane` to `p`:
8686

8787
```python
88-
>>> p = session.attached_pane
88+
>>> p = session.active_pane
8989
```
9090

9191
Access the window/server of a pane:
9292

9393
```python
94-
>>> p = session.attached_pane
94+
>>> p = session.active_pane
9595
>>> p.window
9696
Window(@1 ...:..., Session($1 ...))
9797

src/libtmux/common.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,20 +187,21 @@ def getenv(self, name: str) -> Optional[t.Union[str, bool]]:
187187

188188

189189
class tmux_cmd:
190-
""":term:`tmux(1)` command via :py:mod:`subprocess`.
190+
"""Run any :term:`tmux(1)` command through :py:mod:`subprocess`.
191191
192192
Examples
193193
--------
194-
.. code-block:: python
194+
Create a new session, check for error:
195195
196-
proc = tmux_cmd('new-session', '-s%' % 'my session')
196+
>>> proc = tmux_cmd(f'-L{server.socket_name}', 'new-session', '-d', '-P', '-F#S')
197+
>>> if proc.stderr:
198+
... raise exc.LibTmuxException(
199+
... 'Command: %s returned error: %s' % (proc.cmd, proc.stderr)
200+
... )
201+
...
197202
198-
if proc.stderr:
199-
raise exc.LibTmuxException(
200-
'Command: %s returned error: %s' % (proc.cmd, proc.stderr)
201-
)
202-
203-
print('tmux command returned %s' % proc.stdout)
203+
>>> print(f'tmux command returned {" ".join(proc.stdout)}')
204+
tmux command returned 2
204205
205206
Equivalent to:
206207
@@ -214,7 +215,7 @@ class tmux_cmd:
214215
Renamed from ``tmux`` to ``tmux_cmd``.
215216
"""
216217

217-
def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
218+
def __init__(self, *args: t.Any) -> None:
218219
tmux_bin = shutil.which("tmux")
219220
if not tmux_bin:
220221
raise exc.TmuxCommandNotFound()

0 commit comments

Comments
 (0)