Skip to content

terminator_dbus ¤

Terminator D-Bus package.

Python library to interact with Terminator through D-Bus.

Classes:

  • LayoutTree –

    Inspect one window's layout without making further D-Bus calls.

  • TerminalExtension –

    Call the bundled plugin and decode its layout queries into Python objects.

  • Terminator –

    Provide Python methods for Terminator's complete D-Bus interface.

  • TerminatorError –

    Report a terminal creation failure returned by Terminator.

Functions:

  • get_bus_name –

    Return the D-Bus service and interface name for a display.

  • get_parser –

    Return the CLI argument parser.

  • install_plugin –

    Install the bundled plugin in Terminator's plugin directory.

  • main –

    Run the main program.

Attributes:

  • BUS_BASE (Final) –

    Base name of Terminator's D-Bus service and interface.

  • BUS_PATH (Final) –

    Object path of Terminator's D-Bus service.

  • EXTENSION_INTERFACE –

    D-Bus interface exported by the bundled Terminator plugin.

  • EXTENSION_PATH –

    Object path exported by the bundled Terminator plugin.

BUS_BASE module-attribute ¤

BUS_BASE: Final = 'net.tenshu.Terminator2'

Base name of Terminator's D-Bus service and interface.

BUS_PATH module-attribute ¤

BUS_PATH: Final = '/net/tenshu/Terminator2'

Object path of Terminator's D-Bus service.

EXTENSION_INTERFACE module-attribute ¤

EXTENSION_INTERFACE = 'net.tenshu.Terminator2.Extension'

D-Bus interface exported by the bundled Terminator plugin.

EXTENSION_PATH module-attribute ¤

EXTENSION_PATH = '/net/tenshu/Terminator2/Extension'

Object path exported by the bundled Terminator plugin.

LayoutTree ¤

LayoutTree(data: Mapping[str, Any])

Inspect one window's layout without making further D-Bus calls.

Snapshots remain unchanged when the live layout changes. Fetch a new tree after a mutation to see the current parents, children, ratios, and focus. Terminal node IDs are their UUIDs. Other node IDs are opaque strings.

Parameters:

  • data ¤

    (Mapping[str, Any]) –

    Decoded result of the extension's get_tree method.

Methods:

  • get_ancestors –

    Return parents from the nearest split or tab through the window.

  • get_children –

    Return children in tab order, left/right order, or above/below order.

  • get_neighbors –

    Return all terminals sharing the requested edge in the same tab.

  • get_node –

    Return a node record; raise KeyError if the ID is absent.

  • get_parent –

    Return a node's parent, or None for the window root.

  • get_sibling –

    Return the other branch of a split, or None outside a split.

Attributes:

Source code in src/terminator_dbus/_internal/tree.py
51
52
53
54
def __init__(self, data: Mapping[str, Any]) -> None:
    self.root = data["root"]
    self.nodes = {name: dict(node) for name, node in data["nodes"].items()}
    self.focused_uuid = data["focused_uuid"]

focused_uuid instance-attribute ¤

focused_uuid: str | None = data['focused_uuid']

UUID of the focused terminal in this window, if any.

nodes instance-attribute ¤

nodes: dict[str, dict[str, Any]] = {
    name: dict(node) for name, node in data["nodes"].items()
}

Node IDs mapped to their layout records.

root instance-attribute ¤

root: str = data['root']

ID of the window node.

get_ancestors ¤

get_ancestors(node_id: str) -> list[dict[str, Any]]

Return parents from the nearest split or tab through the window.

Source code in src/terminator_dbus/_internal/tree.py
69
70
71
72
73
74
75
76
def get_ancestors(self, node_id: str) -> list[dict[str, Any]]:
    """Return parents from the nearest split or tab through the window."""
    ancestors = []
    parent = self.get_parent(node_id)
    while parent is not None:
        ancestors.append(parent)
        parent = self.get_parent(parent["id"])
    return ancestors

get_children ¤

get_children(node_id: str) -> list[dict[str, Any]]

Return children in tab order, left/right order, or above/below order.

Source code in src/terminator_dbus/_internal/tree.py
65
66
67
def get_children(self, node_id: str) -> list[dict[str, Any]]:
    """Return children in tab order, left/right order, or above/below order."""
    return [self.get_node(child) for child in self.get_node(node_id)["children"]]

get_neighbors ¤

get_neighbors(
    uuid: str, direction: str
) -> list[dict[str, Any]]

Return all terminals sharing the requested edge in the same tab.

Directions are right, left, above, and below. Results follow display order along the shared edge. There is no wrapping at tab edges. Rectangles use normalized tab coordinates and ignore separator widths.

Raises:

  • KeyError –

    The UUID is absent from the snapshot.

  • ValueError –

    The node is not a terminal, or the direction is invalid.

Source code in src/terminator_dbus/_internal/tree.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def get_neighbors(self, uuid: str, direction: str) -> list[dict[str, Any]]:
    """Return all terminals sharing the requested edge in the same tab.

    Directions are `right`, `left`, `above`, and `below`. Results follow
    display order along the shared edge. There is no wrapping at tab edges.
    Rectangles use normalized tab coordinates and ignore separator widths.

    Raises:
        KeyError: The UUID is absent from the snapshot.
        ValueError: The node is not a terminal, or the direction is invalid.
    """
    if direction not in {"right", "left", "above", "below"}:
        raise ValueError(f"Unknown neighbor direction: {direction}")
    source = self.get_node(uuid)
    if source["type"] != "terminal":
        raise ValueError("Neighbors require a terminal UUID")
    x, y, width, height = source["rect"]
    matches = []
    for node in self.nodes.values():
        if node["type"] != "terminal" or node["tab"] != source["tab"] or node["id"] == uuid:
            continue
        nx, ny, nw, nh = node["rect"]
        if direction in {"left", "right"}:
            edge = nx + nw if direction == "left" else nx
            source_edge = x if direction == "left" else x + width
            overlap = min(y + height, ny + nh) - max(y, ny)
            order = ny
        else:
            edge = ny + nh if direction == "above" else ny
            source_edge = y if direction == "above" else y + height
            overlap = min(x + width, nx + nw) - max(x, nx)
            order = nx
        if overlap > _EPSILON and math.isclose(edge, source_edge, abs_tol=_EPSILON):
            matches.append((order, node))
    return [node for _, node in sorted(matches, key=lambda item: item[0])]

get_node ¤

get_node(node_id: str) -> dict[str, Any]

Return a node record; raise KeyError if the ID is absent.

Source code in src/terminator_dbus/_internal/tree.py
56
57
58
def get_node(self, node_id: str) -> dict[str, Any]:
    """Return a node record; raise `KeyError` if the ID is absent."""
    return self.nodes[node_id]

get_parent ¤

get_parent(node_id: str) -> dict[str, Any] | None

Return a node's parent, or None for the window root.

Source code in src/terminator_dbus/_internal/tree.py
60
61
62
63
def get_parent(self, node_id: str) -> dict[str, Any] | None:
    """Return a node's parent, or `None` for the window root."""
    parent = self.get_node(node_id)["parent"]
    return None if parent is None else self.get_node(parent)

get_sibling ¤

get_sibling(node_id: str) -> dict[str, Any] | None

Return the other branch of a split, or None outside a split.

Source code in src/terminator_dbus/_internal/tree.py
78
79
80
81
82
83
def get_sibling(self, node_id: str) -> dict[str, Any] | None:
    """Return the other branch of a split, or `None` outside a split."""
    parent = self.get_parent(node_id)
    if parent is None or parent["type"] != "split":
        return None
    return next(child for child in self.get_children(parent["id"]) if child["id"] != node_id)

TerminalExtension ¤

TerminalExtension(client: Terminator)

Call the bundled plugin and decode its layout queries into Python objects.

Access this client through Terminator.extension. Remote operations act on the live layout. Methods on a returned LayoutTree use its local snapshot.

Parameters:

  • client ¤

    (Terminator) –

    Terminator client whose connection the extension will reuse.

Methods:

  • focus –

    Select a terminal's tab and focus its window and shell.

  • get_ancestors –

    Inspect current ancestors from the nearest parent through the window.

  • get_children –

    Inspect current children in display order.

  • get_neighbors –

    Inspect all terminals sharing the requested edge in the current tab.

  • get_node –

    Inspect a node in the current layout.

  • get_parent –

    Inspect the current parent, or return None for a window root.

  • get_sibling –

    Inspect the other branch of the current parent split, if any.

  • get_tree –

    Return a local layout snapshot for the window containing this node.

  • move_node –

    Move a terminal or subtree beside another node without restarting shells.

  • new_tab –

    Create a tab with optional command and directory settings.

  • rotate_subtree –

    Rotate a split clockwise or counterclockwise, preserving node IDs.

  • set_split_ratio –

    Set the first branch's share of space, strictly between zero and one.

  • split –

    Create a terminal right, left, above, or below the source.

  • split_node –

    Add a terminal beside an existing terminal or entire split subtree.

  • swap_children –

    Exchange both branches while keeping the split's divider ratio.

Source code in src/terminator_dbus/_internal/extension.py
77
78
def __init__(self, client: Terminator) -> None:
    self._client = client

focus ¤

focus(uuid: str) -> None

Select a terminal's tab and focus its window and shell.

Source code in src/terminator_dbus/_internal/extension.py
157
158
159
def focus(self, uuid: str) -> None:
    """Select a terminal's tab and focus its window and shell."""
    self._call("focus", uuid, signature="s")

get_ancestors ¤

get_ancestors(node_id: str) -> list[dict[str, Any]]

Inspect current ancestors from the nearest parent through the window.

Source code in src/terminator_dbus/_internal/extension.py
108
109
110
def get_ancestors(self, node_id: str) -> list[dict[str, Any]]:
    """Inspect current ancestors from the nearest parent through the window."""
    return self._query("get_ancestors", node_id)

get_children ¤

get_children(node_id: str) -> list[dict[str, Any]]

Inspect current children in display order.

Source code in src/terminator_dbus/_internal/extension.py
104
105
106
def get_children(self, node_id: str) -> list[dict[str, Any]]:
    """Inspect current children in display order."""
    return self._query("get_children", node_id)

get_neighbors ¤

get_neighbors(
    uuid: str, direction: str
) -> list[dict[str, Any]]

Inspect all terminals sharing the requested edge in the current tab.

Source code in src/terminator_dbus/_internal/extension.py
116
117
118
def get_neighbors(self, uuid: str, direction: str) -> list[dict[str, Any]]:
    """Inspect all terminals sharing the requested edge in the current tab."""
    return self._query("get_neighbors", uuid, direction, signature="ss")

get_node ¤

get_node(node_id: str) -> dict[str, Any]

Inspect a node in the current layout.

Source code in src/terminator_dbus/_internal/extension.py
96
97
98
def get_node(self, node_id: str) -> dict[str, Any]:
    """Inspect a node in the current layout."""
    return self._query("get_node", node_id)

get_parent ¤

get_parent(node_id: str) -> dict[str, Any] | None

Inspect the current parent, or return None for a window root.

Source code in src/terminator_dbus/_internal/extension.py
100
101
102
def get_parent(self, node_id: str) -> dict[str, Any] | None:
    """Inspect the current parent, or return `None` for a window root."""
    return self._query("get_parent", node_id)

get_sibling ¤

get_sibling(node_id: str) -> dict[str, Any] | None

Inspect the other branch of the current parent split, if any.

Source code in src/terminator_dbus/_internal/extension.py
112
113
114
def get_sibling(self, node_id: str) -> dict[str, Any] | None:
    """Inspect the other branch of the current parent split, if any."""
    return self._query("get_sibling", node_id)

get_tree ¤

get_tree(uuid: str) -> LayoutTree

Return a local layout snapshot for the window containing this node.

Source code in src/terminator_dbus/_internal/extension.py
92
93
94
def get_tree(self, uuid: str) -> _LayoutTree:
    """Return a local layout snapshot for the window containing this node."""
    return _LayoutTree(self._query("get_tree", uuid))

move_node ¤

move_node(
    node_id: str, target_id: str, direction: str
) -> str

Move a terminal or subtree beside another node without restarting shells.

Nodes may belong to different tabs or windows. The returned ID denotes the new split enclosing the target and moved node. Empty source splits, tabs, and windows are removed. Moving into one's own subtree is invalid.

Source code in src/terminator_dbus/_internal/extension.py
148
149
150
151
152
153
154
155
def move_node(self, node_id: str, target_id: str, direction: str) -> str:
    """Move a terminal or subtree beside another node without restarting shells.

    Nodes may belong to different tabs or windows. The returned ID denotes
    the new split enclosing the target and moved node. Empty source splits,
    tabs, and windows are removed. Moving into one's own subtree is invalid.
    """
    return str(self._call("move_node", node_id, target_id, direction, signature="sss"))

new_tab ¤

new_tab(
    uuid: str, options: Mapping[str, str] | None = None
) -> str

Create a tab with optional command and directory settings.

Source code in src/terminator_dbus/_internal/extension.py
120
121
122
def new_tab(self, uuid: str, options: Mapping[str, str] | None = None) -> str:
    """Create a tab with optional `command` and `directory` settings."""
    return str(self._call("new_tab", uuid, dict(options or {}), signature="sa{ss}"))

rotate_subtree ¤

rotate_subtree(
    node_id: str, direction: str = "clockwise"
) -> str

Rotate a split clockwise or counterclockwise, preserving node IDs.

Source code in src/terminator_dbus/_internal/extension.py
144
145
146
def rotate_subtree(self, node_id: str, direction: str = "clockwise") -> str:
    """Rotate a split `clockwise` or `counterclockwise`, preserving node IDs."""
    return str(self._call("rotate_subtree", node_id, direction, signature="ss"))

set_split_ratio ¤

set_split_ratio(node_id: str, ratio: float) -> None

Set the first branch's share of space, strictly between zero and one.

Source code in src/terminator_dbus/_internal/extension.py
128
129
130
def set_split_ratio(self, node_id: str, ratio: float) -> None:
    """Set the first branch's share of space, strictly between zero and one."""
    self._call("set_split_ratio", node_id, ratio, signature="sd")

split ¤

split(
    uuid: str,
    direction: str,
    options: Mapping[str, str] | None = None,
) -> str

Create a terminal right, left, above, or below the source.

Source code in src/terminator_dbus/_internal/extension.py
124
125
126
def split(self, uuid: str, direction: str, options: Mapping[str, str] | None = None) -> str:
    """Create a terminal `right`, `left`, `above`, or `below` the source."""
    return str(self._call("split", uuid, direction, dict(options or {}), signature="ssa{ss}"))

split_node ¤

split_node(
    node_id: str,
    direction: str,
    options: Mapping[str, str] | None = None,
) -> str

Add a terminal beside an existing terminal or entire split subtree.

Omitted launch options inherit from the subtree's first terminal in display order, subject to Terminator's profile inheritance setting.

Source code in src/terminator_dbus/_internal/extension.py
136
137
138
139
140
141
142
def split_node(self, node_id: str, direction: str, options: Mapping[str, str] | None = None) -> str:
    """Add a terminal beside an existing terminal or entire split subtree.

    Omitted launch options inherit from the subtree's first terminal in
    display order, subject to Terminator's profile inheritance setting.
    """
    return str(self._call("split_node", node_id, direction, dict(options or {}), signature="ssa{ss}"))

swap_children ¤

swap_children(node_id: str) -> None

Exchange both branches while keeping the split's divider ratio.

Source code in src/terminator_dbus/_internal/extension.py
132
133
134
def swap_children(self, node_id: str) -> None:
    """Exchange both branches while keeping the split's divider ratio."""
    self._call("swap_children", node_id, signature="s")

Terminator ¤

Terminator(
    *,
    bus: BusConnection | None = None,
    display: str | None = None,
    bus_name: str | None = None,
)

Provide Python methods for Terminator's complete D-Bus interface.

The client keeps one session-bus connection and reuses proxies. Built-in methods send known signatures directly, so they do not need introspection. Plugin interfaces can be discovered and called through dynamic proxies or the generic call method.

Parameters:

  • bus ¤

    (BusConnection | None, default: None ) –

    An existing D-Bus connection. A session-bus connection is created when this argument is not set.

  • display ¤

    (str | None, default: None ) –

    GDK display name used to calculate Terminator's D-Bus name. Overrides TERMINATOR_DBUS_NAME when specified.

  • bus_name ¤

    (str | None, default: None ) –

    Exact D-Bus service name. Overrides TERMINATOR_DBUS_NAME when specified. When both connection settings are unset, a non-empty TERMINATOR_DBUS_NAME selects the service before the current desktop display.

Raises:

  • ValueError –

    Both display and bus_name were specified.

  • DBusException –

    The session bus or Terminator service is not available.

Methods:

  • bg_img –

    Set the background image of one terminal.

  • bg_img_all –

    Set the background image of all terminals.

  • call –

    Call an arbitrary method on Terminator or a plugin's D-Bus interface.

  • discover_interfaces –

    Discover exported D-Bus interfaces and create their dynamic proxies.

  • get_focused_terminal –

    Return the focused terminal UUID, if a terminal has focus.

  • get_interface –

    Create a dynamic proxy for an interface exported by Terminator or a plugin.

  • get_tab –

    Return the parent tab identifier of a terminal.

  • get_tab_title –

    Return the parent tab title of a terminal, if it has one.

  • get_terminals –

    Return the UUID of every terminal.

  • get_window –

    Return the parent window UUID of a terminal.

  • get_window_title –

    Return the parent window title of a terminal.

  • hsplit –

    Split a terminal horizontally and return the new terminal UUID.

  • new_tab –

    Create a tab beside a terminal and return the new terminal UUID.

  • new_tab_cmdline –

    Create a tab from serialized Terminator command-line options.

  • new_window –

    Create a window and return its first terminal UUID.

  • new_window_cmdline –

    Create a window from serialized Terminator command-line options.

  • reload_configuration –

    Reload the configuration of all terminals.

  • set_tab_title –

    Set a terminal's parent tab title.

  • switch_profile –

    Switch one terminal to a profile.

  • switch_profile_all –

    Switch all terminals to a profile.

  • toggle_visibility_cmdline –

    Toggle the visibility of every Terminator window.

  • unhide_cmdline –

    Show every hidden Terminator window.

  • vsplit –

    Split a terminal vertically and return the new terminal UUID.

Attributes:

  • bus_name (str) –

    Return the D-Bus service and interface name used by this client.

  • extension (TerminalExtension) –

    Return a typed client for the bundled terminal and layout extension.

Source code in src/terminator_dbus/_internal/client.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def __init__(
    self,
    *,
    bus: BusConnection | None = None,
    display: str | None = None,
    bus_name: str | None = None,
) -> None:
    if display is not None and bus_name is not None:
        raise ValueError("display and bus_name cannot both be specified")

    self._bus_name = get_bus_name(display) if bus_name is None else bus_name
    self._bus = dbus.SessionBus() if bus is None else bus
    proxy = self._bus.get_object(self.bus_name, BUS_PATH, introspect=False)
    self._proxies: dict[tuple[str, bool], ProxyObject] = {(BUS_PATH, False): proxy}
    self._interface = dbus.Interface(proxy, self.bus_name)

bus_name property ¤

bus_name: str

Return the D-Bus service and interface name used by this client.

extension property ¤

extension: TerminalExtension

Return a typed client for the bundled terminal and layout extension.

bg_img ¤

bg_img(uuid: str, options: Mapping[str, str]) -> None

Set the background image of one terminal.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

  • options ¤

    (Mapping[str, str]) –

    Mapping with the image path in the file key.

Source code in src/terminator_dbus/_internal/client.py
365
366
367
368
369
370
371
372
def bg_img(self, uuid: str, options: Mapping[str, str]) -> None:
    """Set the background image of one terminal.

    Parameters:
        uuid: Target terminal UUID.
        options: Mapping with the image path in the `file` key.
    """
    self._call("bg_img", uuid, _options(options), signature="vv")

bg_img_all ¤

bg_img_all(options: Mapping[str, str]) -> None

Set the background image of all terminals.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Mapping with the image path in the file key.

Source code in src/terminator_dbus/_internal/client.py
357
358
359
360
361
362
363
def bg_img_all(self, options: Mapping[str, str]) -> None:
    """Set the background image of all terminals.

    Parameters:
        options: Mapping with the image path in the `file` key.
    """
    self._call("bg_img_all", _options(options), signature="v")

call ¤

call(
    method_name: str,
    *args: object,
    interface: str | None = None,
    object_path: str = BUS_PATH,
    signature: str | None = None,
) -> Any

Call an arbitrary method on Terminator or a plugin's D-Bus interface.

Parameters:

  • method_name ¤

    (str) –

    D-Bus method to call.

  • *args ¤

    (object, default: () ) –

    Positional arguments sent to the method.

  • interface ¤

    (str | None, default: None ) –

    D-Bus interface name. Defaults to Terminator's built-in interface.

  • object_path ¤

    (str, default: BUS_PATH ) –

    D-Bus object path exported by the selected Terminator service.

  • signature ¤

    (str | None, default: None ) –

    Input signature. When unset, the proxy uses introspection to find the signature. An empty string declares a method with no inputs.

Returns:

  • Any –

    The original D-Bus result. Plugin results are not converted or

  • Any –

    checked for error strings.

Raises:

  • DBusException –

    The object, interface, or method is unavailable, or the remote method raises an exception.

  • TerminatorError –

    A built-in terminal creation method returned an ERROR: response.

Source code in src/terminator_dbus/_internal/client.py
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
def call(
    self,
    method_name: str,
    *args: object,
    interface: str | None = None,
    object_path: str = BUS_PATH,
    signature: str | None = None,
) -> Any:
    """Call an arbitrary method on Terminator or a plugin's D-Bus interface.

    Parameters:
        method_name: D-Bus method to call.
        *args: Positional arguments sent to the method.
        interface: D-Bus interface name. Defaults to Terminator's built-in interface.
        object_path: D-Bus object path exported by the selected Terminator service.
        signature: Input signature. When unset, the proxy uses introspection
            to find the signature. An empty string declares a method with no inputs.

    Returns:
        The original D-Bus result. Plugin results are not converted or
        checked for error strings.

    Raises:
        dbus.DBusException: The object, interface, or method is unavailable,
            or the remote method raises an exception.
        TerminatorError: A built-in terminal creation method returned an
            `ERROR:` response.
    """
    interface_name = self.bus_name if interface is None else interface
    builtin = object_path == BUS_PATH and interface_name == self.bus_name
    if builtin and signature is not None:
        target = self._interface
    else:
        target = self.get_interface(interface_name, object_path=object_path, introspect=signature is None)
    method = target.get_dbus_method(method_name)
    result = method(*args, signature=signature)
    if (
        builtin
        and method_name in {"new_window", "new_tab", "hsplit", "vsplit"}
        and isinstance(result, str)
        and result.startswith("ERROR:")
    ):
        raise TerminatorError(method_name, result)
    return result

discover_interfaces ¤

discover_interfaces(
    object_path: str = "/", *, recursive: bool = True
) -> dict[str, dict[str, Interface]]

Discover exported D-Bus interfaces and create their dynamic proxies.

Discovery reports interfaces exported by the running Terminator process. It does not list installed or disabled Python plugins. Standard D-Bus and built-in Terminator interfaces are included.

Parameters:

  • object_path ¤

    (str, default: '/' ) –

    Object path where discovery starts. The root path finds plugin objects anywhere in the selected service.

  • recursive ¤

    (bool, default: True ) –

    Follow child objects described by introspection.

Returns:

  • dict[str, dict[str, Interface]] –

    Object paths mapped to interface names and their dynamic proxies.

  • dict[str, dict[str, Interface]] –

    Nodes with no interfaces are omitted.

Raises:

  • DBusException –

    An object cannot be introspected, or the Terminator service is unavailable.

  • ParseError –

    An object returns invalid XML.

Source code in src/terminator_dbus/_internal/client.py
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def discover_interfaces(
    self,
    object_path: str = "/",
    *,
    recursive: bool = True,
) -> dict[str, dict[str, dbus.Interface]]:
    """Discover exported D-Bus interfaces and create their dynamic proxies.

    Discovery reports interfaces exported by the running Terminator
    process. It does not list installed or disabled Python plugins.
    Standard D-Bus and built-in Terminator interfaces are included.

    Parameters:
        object_path: Object path where discovery starts. The root path
            finds plugin objects anywhere in the selected service.
        recursive: Follow child objects described by introspection.

    Returns:
        Object paths mapped to interface names and their dynamic proxies.
        Nodes with no interfaces are omitted.

    Raises:
        dbus.DBusException: An object cannot be introspected, or the
            Terminator service is unavailable.
        xml.etree.ElementTree.ParseError: An object returns invalid XML.
    """
    discovered: dict[str, dict[str, dbus.Interface]] = {}
    pending: list[tuple[str, ET.Element | None]] = [(object_path, None)]
    visited: set[str] = set()
    while pending:
        path, node = pending.pop()
        if path in visited:
            continue
        visited.add(path)
        if node is None:
            description = self.call(
                "Introspect",
                interface="org.freedesktop.DBus.Introspectable",
                object_path=path,
                signature="",
            )
            # The selected Terminator process supplies the introspection XML.
            node = ET.fromstring(str(description))  # noqa: S314
        interfaces = {
            element.attrib["name"]: self.get_interface(element.attrib["name"], object_path=path)
            for element in node.findall("interface")
        }
        if interfaces:
            discovered[path] = interfaces
        if recursive:
            for child in reversed(node.findall("node")):
                child_path = f"{path.rstrip('/')}/{child.attrib['name']}"
                # A child with contents includes its full introspection description.
                pending.append((child_path, child if len(child) else None))
    return discovered

get_focused_terminal ¤

get_focused_terminal() -> str | None

Return the focused terminal UUID, if a terminal has focus.

Source code in src/terminator_dbus/_internal/client.py
410
411
412
def get_focused_terminal(self) -> str | None:
    """Return the focused terminal UUID, if a terminal has focus."""
    return _optional_string(self._call("get_focused_terminal", signature=""))

get_interface ¤

get_interface(
    interface: str,
    *,
    object_path: str = BUS_PATH,
    introspect: bool = True,
) -> Interface

Create a dynamic proxy for an interface exported by Terminator or a plugin.

Methods are available as attributes on the returned interface. For example, a plugin that exports new_tab can be called with plugin.new_tab(uuid, command). These calls return raw D-Bus results.

Parameters:

  • interface ¤

    (str) –

    D-Bus interface name.

  • object_path ¤

    (str, default: BUS_PATH ) –

    D-Bus object path exported by the selected Terminator service.

  • introspect ¤

    (bool, default: True ) –

    Use introspection to find method signatures. Disable this when every call supplies its own signature.

Returns:

  • Interface –

    A dbus.Interface using the client's existing bus connection.

  • Interface –

    Proxies for the same path and introspection setting are reused.

Raises:

  • DBusException –

    The Terminator service is unavailable.

Source code in src/terminator_dbus/_internal/client.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
def get_interface(self, interface: str, *, object_path: str = BUS_PATH, introspect: bool = True) -> dbus.Interface:
    """Create a dynamic proxy for an interface exported by Terminator or a plugin.

    Methods are available as attributes on the returned interface. For
    example, a plugin that exports `new_tab` can be called with
    `plugin.new_tab(uuid, command)`. These calls return raw D-Bus results.

    Parameters:
        interface: D-Bus interface name.
        object_path: D-Bus object path exported by the selected Terminator service.
        introspect: Use introspection to find method signatures. Disable
            this when every call supplies its own signature.

    Returns:
        A `dbus.Interface` using the client's existing bus connection.
        Proxies for the same path and introspection setting are reused.

    Raises:
        dbus.DBusException: The Terminator service is unavailable.
    """
    key = object_path, introspect
    if key not in self._proxies:
        self._proxies[key] = self._bus.get_object(self.bus_name, object_path, introspect=introspect)
    return dbus.Interface(self._proxies[key], interface)

get_tab ¤

get_tab(uuid: str) -> str | None

Return the parent tab identifier of a terminal.

Terminator does not assign UUIDs to tabs. It currently returns an empty string for a terminal in a notebook and no value otherwise.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

Source code in src/terminator_dbus/_internal/client.py
430
431
432
433
434
435
436
437
438
439
def get_tab(self, uuid: str) -> str | None:
    """Return the parent tab identifier of a terminal.

    Terminator does not assign UUIDs to tabs. It currently returns an
    empty string for a terminal in a notebook and no value otherwise.

    Parameters:
        uuid: Target terminal UUID.
    """
    return _optional_string(self._call("get_tab", uuid, signature="v"))

get_tab_title ¤

get_tab_title(uuid: str) -> str | None

Return the parent tab title of a terminal, if it has one.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

Source code in src/terminator_dbus/_internal/client.py
441
442
443
444
445
446
447
def get_tab_title(self, uuid: str) -> str | None:
    """Return the parent tab title of a terminal, if it has one.

    Parameters:
        uuid: Target terminal UUID.
    """
    return _optional_string(self._call("get_tab_title", uuid, signature="v"))

get_terminals ¤

get_terminals() -> list[str]

Return the UUID of every terminal.

Source code in src/terminator_dbus/_internal/client.py
406
407
408
def get_terminals(self) -> list[str]:
    """Return the UUID of every terminal."""
    return [str(uuid) for uuid in self._call("get_terminals", signature="")]

get_window ¤

get_window(uuid: str) -> str

Return the parent window UUID of a terminal.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

Source code in src/terminator_dbus/_internal/client.py
414
415
416
417
418
419
420
def get_window(self, uuid: str) -> str:
    """Return the parent window UUID of a terminal.

    Parameters:
        uuid: Target terminal UUID.
    """
    return str(self._call("get_window", uuid, signature="v"))

get_window_title ¤

get_window_title(uuid: str) -> str

Return the parent window title of a terminal.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

Source code in src/terminator_dbus/_internal/client.py
422
423
424
425
426
427
428
def get_window_title(self, uuid: str) -> str:
    """Return the parent window title of a terminal.

    Parameters:
        uuid: Target terminal UUID.
    """
    return str(self._call("get_window_title", uuid, signature="v"))

hsplit ¤

hsplit(
    uuid: str, options: Mapping[str, str] | None = None
) -> str

Split a terminal horizontally and return the new terminal UUID.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

  • options ¤

    (Mapping[str, str] | None, default: None ) –

    Optional execute command and title for the new terminal.

Returns:

  • str –

    The new terminal UUID.

Raises:

Source code in src/terminator_dbus/_internal/client.py
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
def hsplit(self, uuid: str, options: Mapping[str, str] | None = None) -> str:
    """Split a terminal horizontally and return the new terminal UUID.

    Parameters:
        uuid: Target terminal UUID.
        options: Optional `execute` command and `title` for the new
            terminal.

    Returns:
        The new terminal UUID.

    Raises:
        TerminatorError: Terminator returned an `ERROR:` response.
    """
    return str(self._call("hsplit", uuid, _options(options), signature="vv"))

new_tab ¤

new_tab(uuid: str) -> str

Create a tab beside a terminal and return the new terminal UUID.

Parameters:

  • uuid ¤

    (str) –

    UUID of a terminal in the target window.

Returns:

  • str –

    The new terminal UUID.

Raises:

Source code in src/terminator_dbus/_internal/client.py
339
340
341
342
343
344
345
346
347
348
349
350
351
def new_tab(self, uuid: str) -> str:
    """Create a tab beside a terminal and return the new terminal UUID.

    Parameters:
        uuid: UUID of a terminal in the target window.

    Returns:
        The new terminal UUID.

    Raises:
        TerminatorError: Terminator returned an `ERROR:` response.
    """
    return str(self._call("new_tab", uuid, signature="v"))

new_tab_cmdline ¤

new_tab_cmdline(options: Mapping[str, str]) -> None

Create a tab from serialized Terminator command-line options.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Complete option mapping produced by Terminator's command line parser. Keys and values must be strings.

Source code in src/terminator_dbus/_internal/client.py
304
305
306
307
308
309
310
311
def new_tab_cmdline(self, options: Mapping[str, str]) -> None:
    """Create a tab from serialized Terminator command-line options.

    Parameters:
        options: Complete option mapping produced by Terminator's command
            line parser. Keys and values must be strings.
    """
    self._call("new_tab_cmdline", _options(options), signature="a{ss}")

new_window ¤

new_window() -> str

Create a window and return its first terminal UUID.

Raises:

Source code in src/terminator_dbus/_internal/client.py
331
332
333
334
335
336
337
def new_window(self) -> str:
    """Create a window and return its first terminal UUID.

    Raises:
        TerminatorError: Terminator returned an `ERROR:` response.
    """
    return str(self._call("new_window", signature=""))

new_window_cmdline ¤

new_window_cmdline(options: Mapping[str, str]) -> None

Create a window from serialized Terminator command-line options.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Complete option mapping produced by Terminator's command line parser. Keys and values must be strings.

Source code in src/terminator_dbus/_internal/client.py
295
296
297
298
299
300
301
302
def new_window_cmdline(self, options: Mapping[str, str]) -> None:
    """Create a window from serialized Terminator command-line options.

    Parameters:
        options: Complete option mapping produced by Terminator's command
            line parser. Keys and values must be strings.
    """
    self._call("new_window_cmdline", _options(options), signature="a{ss}")

reload_configuration ¤

reload_configuration() -> None

Reload the configuration of all terminals.

Source code in src/terminator_dbus/_internal/client.py
353
354
355
def reload_configuration(self) -> None:
    """Reload the configuration of all terminals."""
    self._call("reload_configuration", signature="")

set_tab_title ¤

set_tab_title(
    uuid: str, options: Mapping[str, str]
) -> None

Set a terminal's parent tab title.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

  • options ¤

    (Mapping[str, str]) –

    Mapping with the new title in the tab-title key.

Source code in src/terminator_dbus/_internal/client.py
449
450
451
452
453
454
455
456
def set_tab_title(self, uuid: str, options: Mapping[str, str]) -> None:
    """Set a terminal's parent tab title.

    Parameters:
        uuid: Target terminal UUID.
        options: Mapping with the new title in the `tab-title` key.
    """
    self._call("set_tab_title", uuid, _options(options), signature="vv")

switch_profile ¤

switch_profile(
    uuid: str, options: Mapping[str, str]
) -> None

Switch one terminal to a profile.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

  • options ¤

    (Mapping[str, str]) –

    Mapping with the profile name in the profile key.

Source code in src/terminator_dbus/_internal/client.py
458
459
460
461
462
463
464
465
def switch_profile(self, uuid: str, options: Mapping[str, str]) -> None:
    """Switch one terminal to a profile.

    Parameters:
        uuid: Target terminal UUID.
        options: Mapping with the profile name in the `profile` key.
    """
    self._call("switch_profile", uuid, _options(options), signature="vv")

switch_profile_all ¤

switch_profile_all(options: Mapping[str, str]) -> None

Switch all terminals to a profile.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Mapping with the profile name in the profile key.

Source code in src/terminator_dbus/_internal/client.py
467
468
469
470
471
472
473
def switch_profile_all(self, options: Mapping[str, str]) -> None:
    """Switch all terminals to a profile.

    Parameters:
        options: Mapping with the profile name in the `profile` key.
    """
    self._call("switch_profile_all", _options(options), signature="v")

toggle_visibility_cmdline ¤

toggle_visibility_cmdline(
    options: Mapping[str, str],
) -> None

Toggle the visibility of every Terminator window.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Serialized command-line options. Terminator currently ignores the values.

Source code in src/terminator_dbus/_internal/client.py
313
314
315
316
317
318
319
320
def toggle_visibility_cmdline(self, options: Mapping[str, str]) -> None:
    """Toggle the visibility of every Terminator window.

    Parameters:
        options: Serialized command-line options. Terminator currently
            ignores the values.
    """
    self._call("toggle_visibility_cmdline", _options(options), signature="a{ss}")

unhide_cmdline ¤

unhide_cmdline(options: Mapping[str, str]) -> None

Show every hidden Terminator window.

Parameters:

  • options ¤

    (Mapping[str, str]) –

    Serialized command-line options. Terminator currently ignores the values.

Source code in src/terminator_dbus/_internal/client.py
322
323
324
325
326
327
328
329
def unhide_cmdline(self, options: Mapping[str, str]) -> None:
    """Show every hidden Terminator window.

    Parameters:
        options: Serialized command-line options. Terminator currently
            ignores the values.
    """
    self._call("unhide_cmdline", _options(options), signature="a{ss}")

vsplit ¤

vsplit(
    uuid: str, options: Mapping[str, str] | None = None
) -> str

Split a terminal vertically and return the new terminal UUID.

Parameters:

  • uuid ¤

    (str) –

    Target terminal UUID.

  • options ¤

    (Mapping[str, str] | None, default: None ) –

    Optional execute command and title for the new terminal.

Returns:

  • str –

    The new terminal UUID.

Raises:

Source code in src/terminator_dbus/_internal/client.py
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
def vsplit(self, uuid: str, options: Mapping[str, str] | None = None) -> str:
    """Split a terminal vertically and return the new terminal UUID.

    Parameters:
        uuid: Target terminal UUID.
        options: Optional `execute` command and `title` for the new
            terminal.

    Returns:
        The new terminal UUID.

    Raises:
        TerminatorError: Terminator returned an `ERROR:` response.
    """
    return str(self._call("vsplit", uuid, _options(options), signature="vv"))

TerminatorError ¤

TerminatorError(method: str, message: str)

Bases: DBusException

Report a terminal creation failure returned by Terminator.

This exception is also caught by handlers for dbus.DBusException.

Parameters:

  • method ¤

    (str) –

    D-Bus method that failed.

  • message ¤

    (str) –

    Original response from Terminator, including the ERROR: prefix.

Attributes:

  • message (str) –

    Original response from Terminator, including the ERROR: prefix.

  • method (str) –

    D-Bus method that failed.

Source code in src/terminator_dbus/_internal/client.py
109
110
111
112
113
def __init__(self, method: str, message: str) -> None:
    """Keep the failed method and original response with the exception."""
    super().__init__(f"{method}: {message}")
    self.method = method
    self.message = message

message instance-attribute ¤

message: str = message

Original response from Terminator, including the ERROR: prefix.

method instance-attribute ¤

method: str = method

D-Bus method that failed.

get_bus_name ¤

get_bus_name(display: str | None = None) -> str

Return the D-Bus service and interface name for a display.

Terminator appends the MD5 digest of its GDK display name to net.tenshu.Terminator2. It removes the screen suffix before it creates the digest. For example, :0 and :0.0 use the same D-Bus name.

Parameters:

  • display ¤

    (str | None, default: None ) –

    GDK display name. When unset, TERMINATOR_DBUS_NAME is used if non-empty, followed by the current desktop display.

Returns:

  • str –

    The environment's service name, the display-specific name, or the

  • str –

    base name when no display is known.

Source code in src/terminator_dbus/_internal/client.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def get_bus_name(display: str | None = None) -> str:
    """Return the D-Bus service and interface name for a display.

    Terminator appends the MD5 digest of its GDK display name to
    `net.tenshu.Terminator2`. It removes the screen suffix before it creates
    the digest. For example, `:0` and `:0.0` use the same D-Bus name.

    Parameters:
        display: GDK display name. When unset, `TERMINATOR_DBUS_NAME` is used
            if non-empty, followed by the current desktop display.

    Returns:
        The environment's service name, the display-specific name, or the
        base name when no display is known.
    """
    if display is None:
        if bus_name := os.environ.get("TERMINATOR_DBUS_NAME"):
            return bus_name
        display = _default_display()
    if not display:
        return BUS_BASE

    display_without_screen = display.partition(".")[0]
    display_digest = hashlib.md5(display_without_screen.encode(), usedforsecurity=False).hexdigest()
    return f"{BUS_BASE}{display_digest}"

get_parser ¤

get_parser() -> ArgumentParser

Return the CLI argument parser.

Returns:

Source code in src/terminator_dbus/_internal/cli.py
49
50
51
52
53
54
55
56
57
58
59
60
61
def get_parser() -> argparse.ArgumentParser:
    """Return the CLI argument parser.

    Returns:
        An argparse parser.
    """
    parser = argparse.ArgumentParser(prog="terminator-dbus")
    parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {debug._get_version()}")
    parser.add_argument("--debug-info", action=_DebugInfo, help="Print debug information.")
    commands = parser.add_subparsers(dest="command")
    install = commands.add_parser("install-plugin", help="Install the bundled Terminator plugin.")
    install.add_argument("--directory", help="Use this plugin directory instead of Terminator's default.")
    return parser

install_plugin ¤

install_plugin(directory: str | Path | None = None) -> Path

Install the bundled plugin in Terminator's plugin directory.

Enable TerminatorDBusExtension in Terminator's preferences after installation. The installed file is independent of the Python environment that installs it. Repeated calls update the installed plugin to the bundled version.

Parameters:

  • directory ¤

    (str | Path | None, default: None ) –

    Plugin directory. Defaults to $XDG_CONFIG_HOME/terminator/plugins, or ~/.config/terminator/plugins when the variable is absent or empty.

Returns:

  • Path –

    The installed plugin path.

Raises:

  • OSError –

    If the plugin directory or file cannot be written.

Source code in src/terminator_dbus/_internal/extension.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def install_plugin(directory: str | Path | None = None) -> Path:
    """Install the bundled plugin in Terminator's plugin directory.

    Enable `TerminatorDBusExtension` in Terminator's preferences after installation.
    The installed file is independent of the Python environment that installs it.
    Repeated calls update the installed plugin to the bundled version.

    Parameters:
        directory: Plugin directory. Defaults to `$XDG_CONFIG_HOME/terminator/plugins`,
            or `~/.config/terminator/plugins` when the variable is absent or empty.

    Returns:
        The installed plugin path.

    Raises:
        OSError: If the plugin directory or file cannot be written.
    """
    if directory is None:
        configuration = Path(os.environ.get("XDG_CONFIG_HOME") or Path.home() / ".config")
        directory = configuration / "terminator" / "plugins"
    destination = Path(directory).expanduser() / "terminator_dbus_extension.py"
    destination.parent.mkdir(parents=True, exist_ok=True)
    resource = files("terminator_dbus").joinpath("plugin", destination.name)
    destination.write_bytes(resource.read_bytes())
    return destination

main ¤

main(args: list[str] | None = None) -> int

Run the main program.

This function is executed when you type terminator-dbus or python -m terminator_dbus.

Parameters:

  • args ¤

    (list[str] | None, default: None ) –

    Arguments passed from the command line.

Returns:

  • int –

    An exit code.

Source code in src/terminator_dbus/_internal/cli.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def main(args: list[str] | None = None) -> int:
    """Run the main program.

    This function is executed when you type `terminator-dbus` or `python -m terminator_dbus`.

    Parameters:
        args: Arguments passed from the command line.

    Returns:
        An exit code.
    """
    parser = get_parser()
    opts = parser.parse_args(args=args)
    if opts.command == "install-plugin":
        try:
            path = install_plugin(opts.directory)
        except OSError as error:
            print(f"Could not install Terminator plugin: {error}", file=sys.stderr)
            return 1
        print(f"Installed {path}\nEnable TerminatorDBusExtension in Terminator's Preferences > Plugins.")
    else:
        parser.print_help()
    return 0