Skip to content

Commit 92d5249

Browse files
committed
Server,Session,Window,Pane: Add .acmd
1 parent 86e6e4c commit 92d5249

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,
@@ -201,6 +201,53 @@ def cmd(
201201

202202
return self.server.cmd(cmd, *args, target=target)
203203

204+
async def acmd(
205+
self,
206+
cmd: str,
207+
*args: t.Any,
208+
target: str | int | None = None,
209+
) -> AsyncTmuxCmd:
210+
"""Execute tmux subcommand within pane context.
211+
212+
Automatically binds target by adding ``-t`` for object's pane ID to the
213+
command. Pass ``target`` to keyword arguments to override.
214+
215+
Examples
216+
--------
217+
>>> import asyncio
218+
>>> async def test_acmd():
219+
... result = await pane.acmd('split-window', '-P')
220+
... print(result.stdout[0])
221+
>>> asyncio.run(test_acmd())
222+
libtmux...:...
223+
224+
From raw output to an enriched `Pane` object:
225+
226+
>>> async def test_from_pane():
227+
... pane_id_result = await pane.acmd(
228+
... 'split-window', '-P', '-F#{pane_id}'
229+
... )
230+
... return Pane.from_pane_id(
231+
... pane_id=pane_id_result.stdout[0],
232+
... server=session.server
233+
... )
234+
>>> asyncio.run(test_from_pane())
235+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
236+
237+
Parameters
238+
----------
239+
target : str, optional
240+
Optional custom target override. By default, the target is the pane ID.
241+
242+
Returns
243+
-------
244+
:meth:`server.cmd`
245+
"""
246+
if target is None:
247+
target = self.pane_id
248+
249+
return await self.server.acmd(cmd, *args, target=target)
250+
204251
"""
205252
Commands (tmux-like)
206253
"""

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,
@@ -251,8 +252,12 @@ def cmd(
251252
252253
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
253254
254-
>>> Window.from_window_id(window_id=session.cmd(
255-
... 'new-window', '-P', '-F#{window_id}').stdout[0], server=session.server)
255+
>>> Window.from_window_id(
256+
... window_id=session.cmd(
257+
... 'new-window', '-P', '-F#{window_id}'
258+
... ).stdout[0],
259+
... server=session.server,
260+
... )
256261
Window(@4 3:..., Session($1 libtmux_...))
257262
258263
Create a pane from a window:
@@ -263,7 +268,9 @@ def cmd(
263268
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
264269
265270
>>> Pane.from_pane_id(pane_id=window.cmd(
266-
... 'split-window', '-P', '-F#{pane_id}').stdout[0], server=window.server)
271+
... 'split-window', '-P', '-F#{pane_id}').stdout[0],
272+
... server=window.server
273+
... )
267274
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
268275
269276
Parameters
@@ -301,6 +308,90 @@ def cmd(
301308

302309
return tmux_cmd(*svr_args, *cmd_args)
303310

311+
async def acmd(
312+
self,
313+
cmd: str,
314+
*args: t.Any,
315+
target: str | int | None = None,
316+
) -> AsyncTmuxCmd:
317+
"""Execute tmux command respective of socket name and file, return output.
318+
319+
Examples
320+
--------
321+
>>> import asyncio
322+
>>> async def test_acmd():
323+
... result = await server.acmd('display-message', 'hi')
324+
... print(result.stdout)
325+
>>> asyncio.run(test_acmd())
326+
[]
327+
328+
New session:
329+
330+
>>> async def test_new_session():
331+
... result = await server.acmd(
332+
... 'new-session', '-d', '-P', '-F#{session_id}'
333+
... )
334+
... print(result.stdout[0])
335+
>>> asyncio.run(test_new_session())
336+
$...
337+
338+
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
339+
340+
>>> async def test_new_window():
341+
... result = await session.acmd('new-window', '-P', '-F#{window_id}')
342+
... window_id = result.stdout[0]
343+
... window = Window.from_window_id(window_id=window_id, server=server)
344+
... print(window)
345+
>>> asyncio.run(test_new_window())
346+
Window(@... ...:..., Session($... libtmux_...))
347+
348+
Create a pane from a window:
349+
350+
>>> async def test_split_window():
351+
... result = await server.acmd('split-window', '-P', '-F#{pane_id}')
352+
... print(result.stdout[0])
353+
>>> asyncio.run(test_split_window())
354+
%...
355+
356+
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
357+
358+
>>> async def test_pane():
359+
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
360+
... pane_id = result.stdout[0]
361+
... pane = Pane.from_pane_id(pane_id=pane_id, server=server)
362+
... print(pane)
363+
>>> asyncio.run(test_pane())
364+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
365+
366+
Parameters
367+
----------
368+
target : str, optional
369+
Optional custom target.
370+
371+
Returns
372+
-------
373+
:class:`common.AsyncTmuxCmd`
374+
"""
375+
svr_args: list[str | int] = [cmd]
376+
cmd_args: list[str | int] = []
377+
if self.socket_name:
378+
svr_args.insert(0, f"-L{self.socket_name}")
379+
if self.socket_path:
380+
svr_args.insert(0, f"-S{self.socket_path}")
381+
if self.config_file:
382+
svr_args.insert(0, f"-f{self.config_file}")
383+
if self.colors:
384+
if self.colors == 256:
385+
svr_args.insert(0, "-2")
386+
elif self.colors == 88:
387+
svr_args.insert(0, "-8")
388+
else:
389+
raise exc.UnknownColorOption
390+
391+
cmd_args = ["-t", str(target), *args] if target is not None else [*args]
392+
393+
return await AsyncTmuxCmd.run(*svr_args, *cmd_args)
394+
304395
@property
305396
def attached_sessions(self) -> list[Session]:
306397
"""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,
@@ -234,6 +235,62 @@ def cmd(
234235
target = self.session_id
235236
return self.server.cmd(cmd, *args, target=target)
236237

238+
async def acmd(
239+
self,
240+
cmd: str,
241+
*args: t.Any,
242+
target: str | int | None = None,
243+
) -> AsyncTmuxCmd:
244+
"""Execute tmux subcommand within session context.
245+
246+
Automatically binds target by adding ``-t`` for object's session ID to the
247+
command. Pass ``target`` to keyword arguments to override.
248+
249+
Examples
250+
--------
251+
>>> import asyncio
252+
>>> async def test_acmd():
253+
... result = await session.acmd('new-window', '-P')
254+
... print(result.stdout[0])
255+
>>> asyncio.run(test_acmd())
256+
libtmux...:....0
257+
258+
From raw output to an enriched `Window` object:
259+
260+
>>> async def test_from_window():
261+
... window_id_result = await session.acmd(
262+
... 'new-window', '-P', '-F#{window_id}'
263+
... )
264+
... return Window.from_window_id(
265+
... window_id=window_id_result.stdout[0],
266+
... server=session.server
267+
... )
268+
>>> asyncio.run(test_from_window())
269+
Window(@... ...:..., Session($1 libtmux_...))
270+
271+
Parameters
272+
----------
273+
target : str, optional
274+
Optional custom target override. By default, the target is the session ID.
275+
276+
Returns
277+
-------
278+
:meth:`server.cmd`
279+
280+
Notes
281+
-----
282+
.. versionchanged:: 0.34
283+
284+
Passing target by ``-t`` is ignored. Use ``target`` keyword argument instead.
285+
286+
.. versionchanged:: 0.8
287+
288+
Renamed from ``.tmux`` to ``.cmd``.
289+
"""
290+
if target is None:
291+
target = self.session_id
292+
return await self.server.acmd(cmd, *args, target=target)
293+
237294
"""
238295
Commands (tmux-like)
239296
"""

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
import sys
@@ -226,6 +226,55 @@ def cmd(
226226

227227
return self.server.cmd(cmd, *args, target=target)
228228

229+
async def acmd(
230+
self,
231+
cmd: str,
232+
*args: t.Any,
233+
target: str | int | None = None,
234+
) -> AsyncTmuxCmd:
235+
"""Execute tmux subcommand within window context.
236+
237+
Automatically binds target by adding ``-t`` for object's window ID to the
238+
command. Pass ``target`` to keyword arguments to override.
239+
240+
Examples
241+
--------
242+
Create a pane from a window:
243+
244+
>>> import asyncio
245+
>>> async def test_acmd():
246+
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
247+
... print(result.stdout[0])
248+
>>> asyncio.run(test_acmd())
249+
%...
250+
251+
Magic, directly to a `Pane`:
252+
253+
>>> async def test_from_pane():
254+
... pane_id_result = await session.acmd(
255+
... 'split-window', '-P', '-F#{pane_id}'
256+
... )
257+
... return Pane.from_pane_id(
258+
... pane_id=pane_id_result.stdout[0],
259+
... server=session.server
260+
... )
261+
>>> asyncio.run(test_from_pane())
262+
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
263+
264+
Parameters
265+
----------
266+
target : str, optional
267+
Optional custom target override. By default, the target is the window ID.
268+
269+
Returns
270+
-------
271+
:meth:`server.cmd`
272+
"""
273+
if target is None:
274+
target = self.window_id
275+
276+
return await self.server.acmd(cmd, *args, target=target)
277+
229278
"""
230279
Commands (tmux-like)
231280
"""

0 commit comments

Comments
 (0)