Skip to content

Commit 20c2af5

Browse files
committed
feat(internal[constants]): Add Hooks data structure
1 parent 41e29b0 commit 20c2af5

File tree

1 file changed

+244
-2
lines changed

1 file changed

+244
-2
lines changed

src/libtmux/_internal/constants.py

Lines changed: 244 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
1+
"""Internal constants."""
2+
3+
import io
4+
import logging
15
import typing as t
26
from dataclasses import dataclass, field
37

48
from libtmux._internal.dataclasses import SkipDefaultFieldsReprMixin
59

6-
TerminalFeatures = t.Dict[str, t.List[str]]
10+
if t.TYPE_CHECKING:
11+
from typing_extensions import TypeAlias, TypeGuard
712

13+
from libtmux.options import ExplodedComplexUntypedOptionsDict
814

915
T = t.TypeVar("T")
1016

17+
TerminalFeatures = t.Dict[str, t.List[str]]
18+
HookArray: "TypeAlias" = "t.Dict[str, TmuxArray[str]]"
19+
20+
logger = logging.getLogger(__name__)
21+
22+
23+
def is_tmux_array_list(
24+
items: "ExplodedComplexUntypedOptionsDict",
25+
) -> "TypeGuard[HookArray]":
26+
return all(
27+
isinstance(
28+
v,
29+
TmuxArray,
30+
)
31+
for k, v in items.items()
32+
)
33+
1134

1235
class TmuxArray(t.Dict[int, T], t.Generic[T]):
1336
"""Support non-sequential indexes without raising IndexError."""
@@ -118,7 +141,7 @@ class SessionOptions(
118141
status_right_length: t.Optional[int] = field(default=None)
119142
status_right_style: t.Optional[str] = field(default=None)
120143
status_style: t.Optional[str] = field(default=None)
121-
update_environment: t.Optional[t.List[str]] = field(default=None)
144+
update_environment: TmuxArray[str] = field(default_factory=TmuxArray)
122145
visual_activity: t.Optional[t.Literal["on", "off", "both"]] = field(default=None)
123146
visual_bell: t.Optional[t.Literal["on", "off", "both"]] = field(default=None)
124147
visual_silence: t.Optional[t.Literal["on", "off", "both"]] = field(default=None)
@@ -240,3 +263,222 @@ def __init__(self, **kwargs: object) -> None:
240263
key_underscored = key.replace("-", "_")
241264
key_asterisk_removed = key_underscored.rstrip("*")
242265
setattr(self, key_asterisk_removed, value)
266+
267+
268+
@dataclass(repr=False)
269+
class Hooks(
270+
SkipDefaultFieldsReprMixin,
271+
):
272+
"""tmux hooks data structure."""
273+
274+
# --- Tmux normal hooks ---
275+
# Run when a window has activity. See monitor-activity.
276+
alert_activity: TmuxArray[str] = field(default_factory=TmuxArray)
277+
# Run when a window has received a bell. See monitor-bell.
278+
alert_bell: TmuxArray[str] = field(default_factory=TmuxArray)
279+
# Run when a window has been silent. See monitor-silence.
280+
alert_silence: TmuxArray[str] = field(default_factory=TmuxArray)
281+
# Run when a client becomes the latest active client of its session.
282+
client_active: TmuxArray[str] = field(default_factory=TmuxArray)
283+
# Run when a client is attached.
284+
client_attached: TmuxArray[str] = field(default_factory=TmuxArray)
285+
# Run when a client is detached.
286+
client_detached: TmuxArray[str] = field(default_factory=TmuxArray)
287+
# Run when focus enters a client.
288+
client_focus_in: TmuxArray[str] = field(default_factory=TmuxArray)
289+
# Run when focus exits a client.
290+
client_focus_out: TmuxArray[str] = field(default_factory=TmuxArray)
291+
# Run when a client is resized.
292+
client_resized: TmuxArray[str] = field(default_factory=TmuxArray)
293+
# Run when a client's attached session is changed.
294+
client_session_changed: TmuxArray[str] = field(default_factory=TmuxArray)
295+
# Run when the program running in a pane exits, but remain-on-exit is on so the pane
296+
# has not closed.
297+
pane_died: TmuxArray[str] = field(default_factory=TmuxArray)
298+
# Run when the program running in a pane exits.
299+
pane_exited: TmuxArray[str] = field(default_factory=TmuxArray)
300+
# Run when the focus enters a pane, if the focus-events option is on.
301+
pane_focus_in: TmuxArray[str] = field(default_factory=TmuxArray)
302+
# Run when the focus exits a pane, if the focus-events option is on.
303+
pane_focus_out: TmuxArray[str] = field(default_factory=TmuxArray)
304+
# Run when the terminal clipboard is set using the xterm(1) escape sequence.
305+
pane_set_clipboard: TmuxArray[str] = field(default_factory=TmuxArray)
306+
# Run when a new session created.
307+
session_created: TmuxArray[str] = field(default_factory=TmuxArray)
308+
# Run when a session closed.
309+
session_closed: TmuxArray[str] = field(default_factory=TmuxArray)
310+
# Run when a session is renamed.
311+
session_renamed: TmuxArray[str] = field(default_factory=TmuxArray)
312+
# Run when a window is linked into a session.
313+
window_linked: TmuxArray[str] = field(default_factory=TmuxArray)
314+
# Run when a window is renamed.
315+
window_renamed: TmuxArray[str] = field(default_factory=TmuxArray)
316+
# Run when a window is resized. This may be after the client-resized hook is run.
317+
window_resized: TmuxArray[str] = field(default_factory=TmuxArray)
318+
# Run when a window is unlinked from a session.
319+
window_unlinked: TmuxArray[str] = field(default_factory=TmuxArray)
320+
321+
# --- Tmux control mode hooks ---
322+
# The client has detached.
323+
client_detached_control: TmuxArray[str] = field(default_factory=TmuxArray)
324+
# The client is now attached to the session with ID session-id, which is named name.
325+
client_session_changed_control: TmuxArray[str] = field(default_factory=TmuxArray)
326+
# An error has happened in a configuration file.
327+
config_error: TmuxArray[str] = field(default_factory=TmuxArray)
328+
# The pane has been continued after being paused (if the pause-after flag is set,
329+
# see refresh-client -A).
330+
continue_control: TmuxArray[str] = field(default_factory=TmuxArray)
331+
# The tmux client is exiting immediately, either because it is not attached to any
332+
# session or an error occurred.
333+
exit_control: TmuxArray[str] = field(default_factory=TmuxArray)
334+
# New form of %output sent when the pause-after flag is set.
335+
extended_output: TmuxArray[str] = field(default_factory=TmuxArray)
336+
# The layout of a window with ID window-id changed.
337+
layout_change: TmuxArray[str] = field(default_factory=TmuxArray)
338+
# A message sent with the display-message command.
339+
message_control: TmuxArray[str] = field(default_factory=TmuxArray)
340+
# A window pane produced output.
341+
output: TmuxArray[str] = field(default_factory=TmuxArray)
342+
# The pane with ID pane-id has changed mode.
343+
pane_mode_changed: TmuxArray[str] = field(default_factory=TmuxArray)
344+
# Paste buffer name has been changed.
345+
paste_buffer_changed: TmuxArray[str] = field(default_factory=TmuxArray)
346+
# Paste buffer name has been deleted.
347+
paste_buffer_deleted: TmuxArray[str] = field(default_factory=TmuxArray)
348+
# The pane has been paused (if the pause-after flag is set).
349+
pause_control: TmuxArray[str] = field(default_factory=TmuxArray)
350+
# The client is now attached to the session with ID session-id, which is named name.
351+
session_changed_control: TmuxArray[str] = field(default_factory=TmuxArray)
352+
# The current session was renamed to name.
353+
session_renamed_control: TmuxArray[str] = field(default_factory=TmuxArray)
354+
# The session with ID session-id changed its active window to the window with ID
355+
# window-id.
356+
session_window_changed: TmuxArray[str] = field(default_factory=TmuxArray)
357+
# A session was created or destroyed.
358+
sessions_changed: TmuxArray[str] = field(default_factory=TmuxArray)
359+
# The value of the format associated with subscription name has changed to value.
360+
subscription_changed: TmuxArray[str] = field(default_factory=TmuxArray)
361+
# The window with ID window-id was created but is not linked to the current session.
362+
unlinked_window_add: TmuxArray[str] = field(default_factory=TmuxArray)
363+
# The window with ID window-id, which is not linked to the current session, was
364+
# closed.
365+
unlinked_window_close: TmuxArray[str] = field(default_factory=TmuxArray)
366+
# The window with ID window-id, which is not linked to the current session, was
367+
# renamed.
368+
unlinked_window_renamed: TmuxArray[str] = field(default_factory=TmuxArray)
369+
# The window with ID window-id was linked to the current session.
370+
window_add: TmuxArray[str] = field(default_factory=TmuxArray)
371+
# The window with ID window-id closed.
372+
window_close: TmuxArray[str] = field(default_factory=TmuxArray)
373+
# The layout of a window with ID window-id changed. The new layout is window-layout.
374+
# The window's visible layout is window-visible-layout and the window flags are
375+
# window-flags.
376+
window_layout_changed: TmuxArray[str] = field(default_factory=TmuxArray)
377+
# The active pane in the window with ID window-id changed to the pane with ID
378+
# pane-id.
379+
window_pane_changed: TmuxArray[str] = field(default_factory=TmuxArray)
380+
# The window with ID window-id was renamed to name.
381+
window_renamed_control: TmuxArray[str] = field(default_factory=TmuxArray)
382+
383+
# --- After hooks - Run after specific tmux commands complete ---
384+
# Runs after 'bind-key' completes
385+
after_bind_key: TmuxArray[str] = field(default_factory=TmuxArray)
386+
# Runs after 'capture-pane' completes
387+
after_capture_pane: TmuxArray[str] = field(default_factory=TmuxArray)
388+
# Runs after 'copy-mode' completes
389+
after_copy_mode: TmuxArray[str] = field(default_factory=TmuxArray)
390+
# Runs after 'display-message' completes
391+
after_display_message: TmuxArray[str] = field(default_factory=TmuxArray)
392+
# Runs after 'display-panes' completes
393+
after_display_panes: TmuxArray[str] = field(default_factory=TmuxArray)
394+
# Runs after 'kill-pane' completes
395+
after_kill_pane: TmuxArray[str] = field(default_factory=TmuxArray)
396+
# Runs after 'list-buffers' completes
397+
after_list_buffers: TmuxArray[str] = field(default_factory=TmuxArray)
398+
# Runs after 'list-clients' completes
399+
after_list_clients: TmuxArray[str] = field(default_factory=TmuxArray)
400+
# Runs after 'list-keys' completes
401+
after_list_keys: TmuxArray[str] = field(default_factory=TmuxArray)
402+
# Runs after 'list-panes' completes
403+
after_list_panes: TmuxArray[str] = field(default_factory=TmuxArray)
404+
# Runs after 'list-sessions' completes
405+
after_list_sessions: TmuxArray[str] = field(default_factory=TmuxArray)
406+
# Runs after 'list-windows' completes
407+
after_list_windows: TmuxArray[str] = field(default_factory=TmuxArray)
408+
# Runs after 'load-buffer' completes
409+
after_load_buffer: TmuxArray[str] = field(default_factory=TmuxArray)
410+
# Runs after 'lock-server' completes
411+
after_lock_server: TmuxArray[str] = field(default_factory=TmuxArray)
412+
# Runs after 'new-session' completes
413+
after_new_session: TmuxArray[str] = field(default_factory=TmuxArray)
414+
# Runs after 'new-window' completes
415+
after_new_window: TmuxArray[str] = field(default_factory=TmuxArray)
416+
# Runs after 'paste-buffer' completes
417+
after_paste_buffer: TmuxArray[str] = field(default_factory=TmuxArray)
418+
# Runs after 'pipe-pane' completes
419+
after_pipe_pane: TmuxArray[str] = field(default_factory=TmuxArray)
420+
# Runs after 'queue' command is processed
421+
after_queue: TmuxArray[str] = field(default_factory=TmuxArray)
422+
# Runs after 'refresh-client' completes
423+
after_refresh_client: TmuxArray[str] = field(default_factory=TmuxArray)
424+
# Runs after 'rename-session' completes
425+
after_rename_session: TmuxArray[str] = field(default_factory=TmuxArray)
426+
# Runs after 'rename-window' completes
427+
after_rename_window: TmuxArray[str] = field(default_factory=TmuxArray)
428+
# Runs after 'resize-pane' completes
429+
after_resize_pane: TmuxArray[str] = field(default_factory=TmuxArray)
430+
# Runs after 'resize-window' completes
431+
after_resize_window: TmuxArray[str] = field(default_factory=TmuxArray)
432+
# Runs after 'save-buffer' completes
433+
after_save_buffer: TmuxArray[str] = field(default_factory=TmuxArray)
434+
# Runs after 'select-layout' completes
435+
after_select_layout: TmuxArray[str] = field(default_factory=TmuxArray)
436+
# Runs after 'select-pane' completes
437+
after_select_pane: TmuxArray[str] = field(default_factory=TmuxArray)
438+
# Runs after 'select-window' completes
439+
after_select_window: TmuxArray[str] = field(default_factory=TmuxArray)
440+
# Runs after 'send-keys' completes
441+
after_send_keys: TmuxArray[str] = field(default_factory=TmuxArray)
442+
# Runs after 'set-buffer' completes
443+
after_set_buffer: TmuxArray[str] = field(default_factory=TmuxArray)
444+
# Runs after 'set-environment' completes
445+
after_set_environment: TmuxArray[str] = field(default_factory=TmuxArray)
446+
# Runs after 'set-hook' completes
447+
after_set_hook: TmuxArray[str] = field(default_factory=TmuxArray)
448+
# Runs after 'set-option' completes
449+
after_set_option: TmuxArray[str] = field(default_factory=TmuxArray)
450+
# Runs after 'show-environment' completes
451+
after_show_environment: TmuxArray[str] = field(default_factory=TmuxArray)
452+
# Runs after 'show-messages' completes
453+
after_show_messages: TmuxArray[str] = field(default_factory=TmuxArray)
454+
# Runs after 'show-options' completes
455+
after_show_options: TmuxArray[str] = field(default_factory=TmuxArray)
456+
# Runs after 'split-window' completes
457+
after_split_window: TmuxArray[str] = field(default_factory=TmuxArray)
458+
# Runs after 'unbind-key' completes
459+
after_unbind_key: TmuxArray[str] = field(default_factory=TmuxArray)
460+
461+
@classmethod
462+
def from_stdout(cls, value: t.List[str]) -> "Hooks":
463+
from libtmux.options import (
464+
explode_arrays,
465+
explode_complex,
466+
parse_options_to_dict,
467+
)
468+
469+
output_exploded = explode_complex(
470+
explode_arrays(
471+
parse_options_to_dict(
472+
io.StringIO("\n".join(value)),
473+
),
474+
force_array=True,
475+
),
476+
)
477+
478+
assert is_tmux_array_list(output_exploded)
479+
480+
output_renamed: HookArray = {
481+
k.lstrip("%").replace("-", "_"): v for k, v in output_exploded.items()
482+
}
483+
484+
return cls(**output_renamed)

0 commit comments

Comments
 (0)