Skip to content

Commit d22778c

Browse files
committed
Server,Session,Window,Pane: Add .acmd
1 parent cfad639 commit d22778c

File tree

4 files changed

+249
-5
lines changed

4 files changed

+249
-5
lines changed

Diff for: src/libtmux/pane.py

+48-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import typing as t
1414
import warnings
1515

16-
from libtmux.common import has_gte_version, has_lt_version, tmux_cmd
16+
from libtmux.common import AsyncTmuxCmd, has_gte_version, has_lt_version, tmux_cmd
1717
from libtmux.constants import (
1818
PANE_DIRECTION_FLAG_MAP,
1919
RESIZE_ADJUSTMENT_DIRECTION_FLAG_MAP,
@@ -154,6 +154,53 @@ def cmd(
154154

155155
return self.server.cmd(cmd, *args, target=target)
156156

157+
async def acmd(
158+
self,
159+
cmd: str,
160+
*args: t.Any,
161+
target: str | int | None = None,
162+
) -> AsyncTmuxCmd:
163+
"""Execute tmux subcommand within pane context.
164+
165+
Automatically binds target by adding ``-t`` for object's pane ID to the
166+
command. Pass ``target`` to keyword arguments to override.
167+
168+
Examples
169+
--------
170+
>>> import asyncio
171+
>>> async def test_acmd():
172+
... result = await pane.acmd('split-window', '-P')
173+
... print(result.stdout[0])
174+
>>> asyncio.run(test_acmd())
175+
libtmux...:...
176+
177+
From raw output to an enriched `Pane` object:
178+
179+
>>> async def test_from_pane():
180+
... pane_id_result = await pane.acmd(
181+
... 'split-window', '-P', '-F#{pane_id}'
182+
... )
183+
... return Pane.from_pane_id(
184+
... pane_id=pane_id_result.stdout[0],
185+
... server=session.server
186+
... )
187+
>>> asyncio.run(test_from_pane())
188+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
189+
190+
Parameters
191+
----------
192+
target : str, optional
193+
Optional custom target override. By default, the target is the pane ID.
194+
195+
Returns
196+
-------
197+
:meth:`server.cmd`
198+
"""
199+
if target is None:
200+
target = self.pane_id
201+
202+
return await self.server.acmd(cmd, *args, target=target)
203+
157204
"""
158205
Commands (tmux-like)
159206
"""

Diff for: src/libtmux/server.py

+94-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from . import exc, formats
2626
from .common import (
27+
AsyncTmuxCmd,
2728
EnvironmentMixin,
2829
PaneDict,
2930
SessionDict,
@@ -199,8 +200,12 @@ def cmd(
199200
200201
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
201202
202-
>>> Window.from_window_id(window_id=session.cmd(
203-
... 'new-window', '-P', '-F#{window_id}').stdout[0], server=session.server)
203+
>>> Window.from_window_id(
204+
... window_id=session.cmd(
205+
... 'new-window', '-P', '-F#{window_id}'
206+
... ).stdout[0],
207+
... server=session.server,
208+
... )
204209
Window(@4 3:..., Session($1 libtmux_...))
205210
206211
Create a pane from a window:
@@ -211,7 +216,9 @@ def cmd(
211216
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
212217
213218
>>> Pane.from_pane_id(pane_id=window.cmd(
214-
... 'split-window', '-P', '-F#{pane_id}').stdout[0], server=window.server)
219+
... 'split-window', '-P', '-F#{pane_id}').stdout[0],
220+
... server=window.server
221+
... )
215222
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
216223
217224
Parameters
@@ -249,6 +256,90 @@ def cmd(
249256

250257
return tmux_cmd(*svr_args, *cmd_args)
251258

259+
async def acmd(
260+
self,
261+
cmd: str,
262+
*args: t.Any,
263+
target: str | int | None = None,
264+
) -> AsyncTmuxCmd:
265+
"""Execute tmux command respective of socket name and file, return output.
266+
267+
Examples
268+
--------
269+
>>> import asyncio
270+
>>> async def test_acmd():
271+
... result = await server.acmd('display-message', 'hi')
272+
... print(result.stdout)
273+
>>> asyncio.run(test_acmd())
274+
[]
275+
276+
New session:
277+
278+
>>> async def test_new_session():
279+
... result = await server.acmd(
280+
... 'new-session', '-d', '-P', '-F#{session_id}'
281+
... )
282+
... print(result.stdout[0])
283+
>>> asyncio.run(test_new_session())
284+
$...
285+
286+
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
287+
288+
>>> async def test_new_window():
289+
... result = await session.acmd('new-window', '-P', '-F#{window_id}')
290+
... window_id = result.stdout[0]
291+
... window = Window.from_window_id(window_id=window_id, server=server)
292+
... print(window)
293+
>>> asyncio.run(test_new_window())
294+
Window(@... ...:..., Session($... libtmux_...))
295+
296+
Create a pane from a window:
297+
298+
>>> async def test_split_window():
299+
... result = await server.acmd('split-window', '-P', '-F#{pane_id}')
300+
... print(result.stdout[0])
301+
>>> asyncio.run(test_split_window())
302+
%...
303+
304+
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
305+
306+
>>> async def test_pane():
307+
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
308+
... pane_id = result.stdout[0]
309+
... pane = Pane.from_pane_id(pane_id=pane_id, server=server)
310+
... print(pane)
311+
>>> asyncio.run(test_pane())
312+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
313+
314+
Parameters
315+
----------
316+
target : str, optional
317+
Optional custom target.
318+
319+
Returns
320+
-------
321+
:class:`common.AsyncTmuxCmd`
322+
"""
323+
svr_args: list[str | int] = [cmd]
324+
cmd_args: list[str | int] = []
325+
if self.socket_name:
326+
svr_args.insert(0, f"-L{self.socket_name}")
327+
if self.socket_path:
328+
svr_args.insert(0, f"-S{self.socket_path}")
329+
if self.config_file:
330+
svr_args.insert(0, f"-f{self.config_file}")
331+
if self.colors:
332+
if self.colors == 256:
333+
svr_args.insert(0, "-2")
334+
elif self.colors == 88:
335+
svr_args.insert(0, "-8")
336+
else:
337+
raise exc.UnknownColorOption
338+
339+
cmd_args = ["-t", str(target), *args] if target is not None else [*args]
340+
341+
return await AsyncTmuxCmd.run(*svr_args, *cmd_args)
342+
252343
@property
253344
def attached_sessions(self) -> list[Session]:
254345
"""Return active :class:`Session`s.

Diff for: src/libtmux/session.py

+57
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from . import exc
2424
from .common import (
25+
AsyncTmuxCmd,
2526
EnvironmentMixin,
2627
WindowDict,
2728
handle_option_error,
@@ -189,6 +190,62 @@ def cmd(
189190
target = self.session_id
190191
return self.server.cmd(cmd, *args, target=target)
191192

193+
async def acmd(
194+
self,
195+
cmd: str,
196+
*args: t.Any,
197+
target: str | int | None = None,
198+
) -> AsyncTmuxCmd:
199+
"""Execute tmux subcommand within session context.
200+
201+
Automatically binds target by adding ``-t`` for object's session ID to the
202+
command. Pass ``target`` to keyword arguments to override.
203+
204+
Examples
205+
--------
206+
>>> import asyncio
207+
>>> async def test_acmd():
208+
... result = await session.acmd('new-window', '-P')
209+
... print(result.stdout[0])
210+
>>> asyncio.run(test_acmd())
211+
libtmux...:....0
212+
213+
From raw output to an enriched `Window` object:
214+
215+
>>> async def test_from_window():
216+
... window_id_result = await session.acmd(
217+
... 'new-window', '-P', '-F#{window_id}'
218+
... )
219+
... return Window.from_window_id(
220+
... window_id=window_id_result.stdout[0],
221+
... server=session.server
222+
... )
223+
>>> asyncio.run(test_from_window())
224+
Window(@... ...:..., Session($1 libtmux_...))
225+
226+
Parameters
227+
----------
228+
target : str, optional
229+
Optional custom target override. By default, the target is the session ID.
230+
231+
Returns
232+
-------
233+
:meth:`server.cmd`
234+
235+
Notes
236+
-----
237+
.. versionchanged:: 0.34
238+
239+
Passing target by ``-t`` is ignored. Use ``target`` keyword argument instead.
240+
241+
.. versionchanged:: 0.8
242+
243+
Renamed from ``.tmux`` to ``.cmd``.
244+
"""
245+
if target is None:
246+
target = self.session_id
247+
return await self.server.acmd(cmd, *args, target=target)
248+
192249
"""
193250
Commands (tmux-like)
194251
"""

Diff for: src/libtmux/window.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from libtmux.pane import Pane
2626

2727
from . import exc
28-
from .common import PaneDict, WindowOptionDict, handle_option_error
28+
from .common import AsyncTmuxCmd, PaneDict, WindowOptionDict, handle_option_error
2929

3030
if t.TYPE_CHECKING:
3131
from .server import Server
@@ -177,6 +177,55 @@ def cmd(
177177

178178
return self.server.cmd(cmd, *args, target=target)
179179

180+
async def acmd(
181+
self,
182+
cmd: str,
183+
*args: t.Any,
184+
target: str | int | None = None,
185+
) -> AsyncTmuxCmd:
186+
"""Execute tmux subcommand within window context.
187+
188+
Automatically binds target by adding ``-t`` for object's window ID to the
189+
command. Pass ``target`` to keyword arguments to override.
190+
191+
Examples
192+
--------
193+
Create a pane from a window:
194+
195+
>>> import asyncio
196+
>>> async def test_acmd():
197+
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
198+
... print(result.stdout[0])
199+
>>> asyncio.run(test_acmd())
200+
%...
201+
202+
Magic, directly to a `Pane`:
203+
204+
>>> async def test_from_pane():
205+
... pane_id_result = await session.acmd(
206+
... 'split-window', '-P', '-F#{pane_id}'
207+
... )
208+
... return Pane.from_pane_id(
209+
... pane_id=pane_id_result.stdout[0],
210+
... server=session.server
211+
... )
212+
>>> asyncio.run(test_from_pane())
213+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
214+
215+
Parameters
216+
----------
217+
target : str, optional
218+
Optional custom target override. By default, the target is the window ID.
219+
220+
Returns
221+
-------
222+
:meth:`server.cmd`
223+
"""
224+
if target is None:
225+
target = self.window_id
226+
227+
return await self.server.acmd(cmd, *args, target=target)
228+
180229
"""
181230
Commands (tmux-like)
182231
"""

0 commit comments

Comments
 (0)