Skip to content

Commit

Permalink
Server,Session,Window,Pane: Add .acmd
Browse files Browse the repository at this point in the history
  • Loading branch information
tony committed Dec 25, 2024
1 parent 94869ee commit e7fdf41
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 5 deletions.
49 changes: 48 additions & 1 deletion src/libtmux/pane.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import warnings
from typing import overload

from libtmux.common import has_gte_version, has_lt_version, tmux_cmd
from libtmux.common import AsyncTmuxCmd, has_gte_version, has_lt_version, tmux_cmd
from libtmux.constants import (
PANE_DIRECTION_FLAG_MAP,
RESIZE_ADJUSTMENT_DIRECTION_FLAG_MAP,
Expand Down Expand Up @@ -153,6 +153,53 @@ def cmd(

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

async def acmd(
self,
cmd: str,
*args: t.Any,
target: t.Optional[t.Union[str, int]] = None,
) -> AsyncTmuxCmd:
"""Execute tmux subcommand within pane context.
Automatically binds target by adding ``-t`` for object's pane ID to the
command. Pass ``target`` to keyword arguments to override.
Examples
--------
>>> import asyncio
>>> async def test_acmd():
... result = await pane.acmd('split-window', '-P')
... print(result.stdout[0])
>>> asyncio.run(test_acmd())
libtmux...:...
From raw output to an enriched `Pane` object:
>>> async def test_from_pane():
... pane_id_result = await pane.acmd(
... 'split-window', '-P', '-F#{pane_id}'
... )
... return Pane.from_pane_id(
... pane_id=pane_id_result.stdout[0],
... server=session.server
... )
>>> asyncio.run(test_from_pane())
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
Parameters
----------
target : str, optional
Optional custom target override. By default, the target is the pane ID.
Returns
-------
:meth:`server.cmd`
"""
if target is None:
target = self.pane_id

return await self.server.acmd(cmd, *args, target=target)

"""
Commands (tmux-like)
"""
Expand Down
97 changes: 94 additions & 3 deletions src/libtmux/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from . import exc, formats
from .common import (
AsyncTmuxCmd,
EnvironmentMixin,
PaneDict,
SessionDict,
Expand Down Expand Up @@ -197,8 +198,12 @@ def cmd(
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
>>> Window.from_window_id(window_id=session.cmd(
... 'new-window', '-P', '-F#{window_id}').stdout[0], server=session.server)
>>> Window.from_window_id(
... window_id=session.cmd(
... 'new-window', '-P', '-F#{window_id}'
... ).stdout[0],
... server=session.server,
... )
Window(@4 3:..., Session($1 libtmux_...))
Create a pane from a window:
Expand All @@ -209,7 +214,9 @@ def cmd(
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
>>> Pane.from_pane_id(pane_id=window.cmd(
... 'split-window', '-P', '-F#{pane_id}').stdout[0], server=window.server)
... 'split-window', '-P', '-F#{pane_id}').stdout[0],
... server=window.server
... )
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
Parameters
Expand Down Expand Up @@ -247,6 +254,90 @@ def cmd(

return tmux_cmd(*svr_args, *cmd_args)

async def acmd(
self,
cmd: str,
*args: t.Any,
target: t.Optional[t.Union[str, int]] = None,
) -> AsyncTmuxCmd:
"""Execute tmux command respective of socket name and file, return output.
Examples
--------
>>> import asyncio
>>> async def test_acmd():
... result = await server.acmd('display-message', 'hi')
... print(result.stdout)
>>> asyncio.run(test_acmd())
[]
New session:
>>> async def test_new_session():
... result = await server.acmd(
... 'new-session', '-d', '-P', '-F#{session_id}'
... )
... print(result.stdout[0])
>>> asyncio.run(test_new_session())
$...
Output of `tmux -L ... new-window -P -F#{window_id}` to a `Window` object:
>>> async def test_new_window():
... result = await session.acmd('new-window', '-P', '-F#{window_id}')
... window_id = result.stdout[0]
... window = Window.from_window_id(window_id=window_id, server=server)
... print(window)
>>> asyncio.run(test_new_window())
Window(@... ...:..., Session($... libtmux_...))
Create a pane from a window:
>>> async def test_split_window():
... result = await server.acmd('split-window', '-P', '-F#{pane_id}')
... print(result.stdout[0])
>>> asyncio.run(test_split_window())
%...
Output of `tmux -L ... split-window -P -F#{pane_id}` to a `Pane` object:
>>> async def test_pane():
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
... pane_id = result.stdout[0]
... pane = Pane.from_pane_id(pane_id=pane_id, server=server)
... print(pane)
>>> asyncio.run(test_pane())
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
Parameters
----------
target : str, optional
Optional custom target.
Returns
-------
:class:`common.AsyncTmuxCmd`
"""
svr_args: list[t.Union[str, int]] = [cmd]
cmd_args: list[t.Union[str, int]] = []
if self.socket_name:
svr_args.insert(0, f"-L{self.socket_name}")
if self.socket_path:
svr_args.insert(0, f"-S{self.socket_path}")
if self.config_file:
svr_args.insert(0, f"-f{self.config_file}")
if self.colors:
if self.colors == 256:
svr_args.insert(0, "-2")
elif self.colors == 88:
svr_args.insert(0, "-8")
else:
raise exc.UnknownColorOption

cmd_args = ["-t", str(target), *args] if target is not None else [*args]

return await AsyncTmuxCmd.run(*svr_args, *cmd_args)

@property
def attached_sessions(self) -> list[Session]:
"""Return active :class:`Session`s.
Expand Down
57 changes: 57 additions & 0 deletions src/libtmux/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from . import exc
from .common import (
AsyncTmuxCmd,
EnvironmentMixin,
WindowDict,
handle_option_error,
Expand Down Expand Up @@ -186,6 +187,62 @@ def cmd(
target = self.session_id
return self.server.cmd(cmd, *args, target=target)

async def acmd(
self,
cmd: str,
*args: t.Any,
target: t.Optional[t.Union[str, int]] = None,
) -> AsyncTmuxCmd:
"""Execute tmux subcommand within session context.
Automatically binds target by adding ``-t`` for object's session ID to the
command. Pass ``target`` to keyword arguments to override.
Examples
--------
>>> import asyncio
>>> async def test_acmd():
... result = await session.acmd('new-window', '-P')
... print(result.stdout[0])
>>> asyncio.run(test_acmd())
libtmux...:....0
From raw output to an enriched `Window` object:
>>> async def test_from_window():
... window_id_result = await session.acmd(
... 'new-window', '-P', '-F#{window_id}'
... )
... return Window.from_window_id(
... window_id=window_id_result.stdout[0],
... server=session.server
... )
>>> asyncio.run(test_from_window())
Window(@... ...:..., Session($1 libtmux_...))
Parameters
----------
target : str, optional
Optional custom target override. By default, the target is the session ID.
Returns
-------
:meth:`server.cmd`
Notes
-----
.. versionchanged:: 0.34
Passing target by ``-t`` is ignored. Use ``target`` keyword argument instead.
.. versionchanged:: 0.8
Renamed from ``.tmux`` to ``.cmd``.
"""
if target is None:
target = self.session_id
return await self.server.acmd(cmd, *args, target=target)

"""
Commands (tmux-like)
"""
Expand Down
51 changes: 50 additions & 1 deletion src/libtmux/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from libtmux.pane import Pane

from . import exc
from .common import PaneDict, WindowOptionDict, handle_option_error
from .common import AsyncTmuxCmd, PaneDict, WindowOptionDict, handle_option_error

if t.TYPE_CHECKING:
from .server import Server
Expand Down Expand Up @@ -175,6 +175,55 @@ def cmd(

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

async def acmd(
self,
cmd: str,
*args: t.Any,
target: t.Optional[t.Union[str, int]] = None,
) -> AsyncTmuxCmd:
"""Execute tmux subcommand within window context.
Automatically binds target by adding ``-t`` for object's window ID to the
command. Pass ``target`` to keyword arguments to override.
Examples
--------
Create a pane from a window:
>>> import asyncio
>>> async def test_acmd():
... result = await window.acmd('split-window', '-P', '-F#{pane_id}')
... print(result.stdout[0])
>>> asyncio.run(test_acmd())
%...
Magic, directly to a `Pane`:
>>> async def test_from_pane():
... pane_id_result = await session.acmd(
... 'split-window', '-P', '-F#{pane_id}'
... )
... return Pane.from_pane_id(
... pane_id=pane_id_result.stdout[0],
... server=session.server
... )
>>> asyncio.run(test_from_pane())
Pane(%... Window(@... ...:..., Session($1 libtmux_...)))
Parameters
----------
target : str, optional
Optional custom target override. By default, the target is the window ID.
Returns
-------
:meth:`server.cmd`
"""
if target is None:
target = self.window_id

return await self.server.acmd(cmd, *args, target=target)

"""
Commands (tmux-like)
"""
Expand Down

0 comments on commit e7fdf41

Please sign in to comment.