1+ """Internal constants."""
2+
3+ import io
4+ import logging
15import typing as t
26from dataclasses import dataclass , field
37
48from libtmux ._internal .dataclasses import SkipDefaultFieldsReprMixin
9+ from libtmux ._internal .sparse_array import SparseArray , is_sparse_array_list
510
6- TerminalFeatures = dict [str , list [str ]]
11+ if t .TYPE_CHECKING :
12+ from typing_extensions import TypeAlias
713
814
915T = t .TypeVar ("T" )
1016
17+ TerminalFeatures = dict [str , list [str ]]
18+ HookArray : "TypeAlias" = "t.Dict[str, SparseArray[str]]"
1119
12- class TmuxArray (dict [int , T ], t .Generic [T ]):
13- """Support non-sequential indexes without raising IndexError."""
14-
15- def add (self , index : int , value : T ) -> None :
16- self [index ] = value
17-
18- def append (self , value : T ) -> None :
19- index = max (self .keys ()) + 1
20- self [index ] = value
21-
22- def iter_values (self ) -> t .Iterator [T ]:
23- for index in sorted (self .keys ()):
24- yield self [index ]
25-
26- def as_list (self ) -> list [T ]:
27- return [self [index ] for index in sorted (self .keys ())]
20+ logger = logging .getLogger (__name__ )
2821
2922
3023@dataclass (repr = False )
@@ -33,7 +26,7 @@ class ServerOptions(
3326):
3427 backspace : t .Optional [str ] = field (default = None )
3528 buffer_limit : t .Optional [int ] = field (default = None )
36- command_alias : TmuxArray [str ] = field (default_factory = TmuxArray )
29+ command_alias : SparseArray [str ] = field (default_factory = SparseArray )
3730 default_terminal : t .Optional [str ] = field (default = None )
3831 copy_command : t .Optional [str ] = field (default = None )
3932 escape_time : t .Optional [int ] = field (default = None )
@@ -47,8 +40,8 @@ class ServerOptions(
4740 prompt_history_limit : t .Optional [int ] = field (default = None )
4841 set_clipboard : t .Optional [t .Literal ["on" , "external" , "off" ]] = field (default = None )
4942 terminal_features : TerminalFeatures = field (default_factory = dict )
50- terminal_overrides : TmuxArray [str ] = field (default_factory = TmuxArray )
51- user_keys : TmuxArray [str ] = field (default_factory = TmuxArray )
43+ terminal_overrides : SparseArray [str ] = field (default_factory = SparseArray )
44+ user_keys : SparseArray [str ] = field (default_factory = SparseArray )
5245
5346 def __init__ (self , ** kwargs : object ) -> None :
5447 # Convert hyphenated keys to underscored attribute names and assign values
@@ -118,7 +111,7 @@ class SessionOptions(
118111 status_right_length : t .Optional [int ] = field (default = None )
119112 status_right_style : t .Optional [str ] = field (default = None )
120113 status_style : t .Optional [str ] = field (default = None )
121- update_environment : t . Optional [ list [ str ]] = field (default = None )
114+ update_environment : SparseArray [ str ] = field (default_factory = SparseArray )
122115 visual_activity : t .Optional [t .Literal ["on" , "off" , "both" ]] = field (default = None )
123116 visual_bell : t .Optional [t .Literal ["on" , "off" , "both" ]] = field (default = None )
124117 visual_silence : t .Optional [t .Literal ["on" , "off" , "both" ]] = field (default = None )
@@ -240,3 +233,224 @@ def __init__(self, **kwargs: object) -> None:
240233 key_underscored = key .replace ("-" , "_" )
241234 key_asterisk_removed = key_underscored .rstrip ("*" )
242235 setattr (self , key_asterisk_removed , value )
236+
237+
238+ @dataclass (repr = False )
239+ class Hooks (
240+ SkipDefaultFieldsReprMixin ,
241+ ):
242+ """tmux hooks data structure."""
243+
244+ # --- Tmux normal hooks ---
245+ # Run when a window has activity. See monitor-activity.
246+ alert_activity : SparseArray [str ] = field (default_factory = SparseArray )
247+ # Run when a window has received a bell. See monitor-bell.
248+ alert_bell : SparseArray [str ] = field (default_factory = SparseArray )
249+ # Run when a window has been silent. See monitor-silence.
250+ alert_silence : SparseArray [str ] = field (default_factory = SparseArray )
251+ # Run when a client becomes the latest active client of its session.
252+ client_active : SparseArray [str ] = field (default_factory = SparseArray )
253+ # Run when a client is attached.
254+ client_attached : SparseArray [str ] = field (default_factory = SparseArray )
255+ # Run when a client is detached.
256+ client_detached : SparseArray [str ] = field (default_factory = SparseArray )
257+ # Run when focus enters a client.
258+ client_focus_in : SparseArray [str ] = field (default_factory = SparseArray )
259+ # Run when focus exits a client.
260+ client_focus_out : SparseArray [str ] = field (default_factory = SparseArray )
261+ # Run when a client is resized.
262+ client_resized : SparseArray [str ] = field (default_factory = SparseArray )
263+ # Run when a client's attached session is changed.
264+ client_session_changed : SparseArray [str ] = field (default_factory = SparseArray )
265+ # Run when the program running in a pane exits, but remain-on-exit is on so the pane
266+ # has not closed.
267+ pane_died : SparseArray [str ] = field (default_factory = SparseArray )
268+ # Run when the program running in a pane exits.
269+ pane_exited : SparseArray [str ] = field (default_factory = SparseArray )
270+ # Run when the focus enters a pane, if the focus-events option is on.
271+ pane_focus_in : SparseArray [str ] = field (default_factory = SparseArray )
272+ # Run when the focus exits a pane, if the focus-events option is on.
273+ pane_focus_out : SparseArray [str ] = field (default_factory = SparseArray )
274+ # Run when the terminal clipboard is set using the xterm(1) escape sequence.
275+ pane_set_clipboard : SparseArray [str ] = field (default_factory = SparseArray )
276+ # Run when a new session created.
277+ session_created : SparseArray [str ] = field (default_factory = SparseArray )
278+ # Run when a session closed.
279+ session_closed : SparseArray [str ] = field (default_factory = SparseArray )
280+ # Run when a session is renamed.
281+ session_renamed : SparseArray [str ] = field (default_factory = SparseArray )
282+ # Run when a window is linked into a session.
283+ window_linked : SparseArray [str ] = field (default_factory = SparseArray )
284+ # Run when a window is renamed.
285+ window_renamed : SparseArray [str ] = field (default_factory = SparseArray )
286+ # Run when a window is resized. This may be after the client-resized hook is run.
287+ window_resized : SparseArray [str ] = field (default_factory = SparseArray )
288+ # Run when a window is unlinked from a session.
289+ window_unlinked : SparseArray [str ] = field (default_factory = SparseArray )
290+
291+ # --- Tmux control mode hooks ---
292+ # The client has detached.
293+ client_detached_control : SparseArray [str ] = field (default_factory = SparseArray )
294+ # The client is now attached to the session with ID session-id, which is named name.
295+ client_session_changed_control : SparseArray [str ] = field (
296+ default_factory = SparseArray ,
297+ )
298+ # An error has happened in a configuration file.
299+ config_error : SparseArray [str ] = field (default_factory = SparseArray )
300+ # The pane has been continued after being paused (if the pause-after flag is set,
301+ # see refresh-client -A).
302+ continue_control : SparseArray [str ] = field (default_factory = SparseArray )
303+ # The tmux client is exiting immediately, either because it is not attached to any
304+ # session or an error occurred.
305+ exit_control : SparseArray [str ] = field (default_factory = SparseArray )
306+ # New form of %output sent when the pause-after flag is set.
307+ extended_output : SparseArray [str ] = field (default_factory = SparseArray )
308+ # The layout of a window with ID window-id changed.
309+ layout_change : SparseArray [str ] = field (default_factory = SparseArray )
310+ # A message sent with the display-message command.
311+ message_control : SparseArray [str ] = field (default_factory = SparseArray )
312+ # A window pane produced output.
313+ output : SparseArray [str ] = field (default_factory = SparseArray )
314+ # The pane with ID pane-id has changed mode.
315+ pane_mode_changed : SparseArray [str ] = field (default_factory = SparseArray )
316+ # Paste buffer name has been changed.
317+ paste_buffer_changed : SparseArray [str ] = field (default_factory = SparseArray )
318+ # Paste buffer name has been deleted.
319+ paste_buffer_deleted : SparseArray [str ] = field (default_factory = SparseArray )
320+ # The pane has been paused (if the pause-after flag is set).
321+ pause_control : SparseArray [str ] = field (default_factory = SparseArray )
322+ # The client is now attached to the session with ID session-id, which is named name.
323+ session_changed_control : SparseArray [str ] = field (default_factory = SparseArray )
324+ # The current session was renamed to name.
325+ session_renamed_control : SparseArray [str ] = field (default_factory = SparseArray )
326+ # The session with ID session-id changed its active window to the window with ID
327+ # window-id.
328+ session_window_changed : SparseArray [str ] = field (default_factory = SparseArray )
329+ # A session was created or destroyed.
330+ sessions_changed : SparseArray [str ] = field (default_factory = SparseArray )
331+ # The value of the format associated with subscription name has changed to value.
332+ subscription_changed : SparseArray [str ] = field (default_factory = SparseArray )
333+ # The window with ID window-id was created but is not linked to the current session.
334+ unlinked_window_add : SparseArray [str ] = field (default_factory = SparseArray )
335+ # The window with ID window-id, which is not linked to the current session, was
336+ # closed.
337+ unlinked_window_close : SparseArray [str ] = field (default_factory = SparseArray )
338+ # The window with ID window-id, which is not linked to the current session, was
339+ # renamed.
340+ unlinked_window_renamed : SparseArray [str ] = field (default_factory = SparseArray )
341+ # The window with ID window-id was linked to the current session.
342+ window_add : SparseArray [str ] = field (default_factory = SparseArray )
343+ # The window with ID window-id closed.
344+ window_close : SparseArray [str ] = field (default_factory = SparseArray )
345+ # The layout of a window with ID window-id changed. The new layout is window-layout.
346+ # The window's visible layout is window-visible-layout and the window flags are
347+ # window-flags.
348+ window_layout_changed : SparseArray [str ] = field (default_factory = SparseArray )
349+ # The active pane in the window with ID window-id changed to the pane with ID
350+ # pane-id.
351+ window_pane_changed : SparseArray [str ] = field (default_factory = SparseArray )
352+ # The window with ID window-id was renamed to name.
353+ window_renamed_control : SparseArray [str ] = field (default_factory = SparseArray )
354+
355+ # --- After hooks - Run after specific tmux commands complete ---
356+ # Runs after 'bind-key' completes
357+ after_bind_key : SparseArray [str ] = field (default_factory = SparseArray )
358+ # Runs after 'capture-pane' completes
359+ after_capture_pane : SparseArray [str ] = field (default_factory = SparseArray )
360+ # Runs after 'copy-mode' completes
361+ after_copy_mode : SparseArray [str ] = field (default_factory = SparseArray )
362+ # Runs after 'display-message' completes
363+ after_display_message : SparseArray [str ] = field (default_factory = SparseArray )
364+ # Runs after 'display-panes' completes
365+ after_display_panes : SparseArray [str ] = field (default_factory = SparseArray )
366+ # Runs after 'kill-pane' completes
367+ after_kill_pane : SparseArray [str ] = field (default_factory = SparseArray )
368+ # Runs after 'list-buffers' completes
369+ after_list_buffers : SparseArray [str ] = field (default_factory = SparseArray )
370+ # Runs after 'list-clients' completes
371+ after_list_clients : SparseArray [str ] = field (default_factory = SparseArray )
372+ # Runs after 'list-keys' completes
373+ after_list_keys : SparseArray [str ] = field (default_factory = SparseArray )
374+ # Runs after 'list-panes' completes
375+ after_list_panes : SparseArray [str ] = field (default_factory = SparseArray )
376+ # Runs after 'list-sessions' completes
377+ after_list_sessions : SparseArray [str ] = field (default_factory = SparseArray )
378+ # Runs after 'list-windows' completes
379+ after_list_windows : SparseArray [str ] = field (default_factory = SparseArray )
380+ # Runs after 'load-buffer' completes
381+ after_load_buffer : SparseArray [str ] = field (default_factory = SparseArray )
382+ # Runs after 'lock-server' completes
383+ after_lock_server : SparseArray [str ] = field (default_factory = SparseArray )
384+ # Runs after 'new-session' completes
385+ after_new_session : SparseArray [str ] = field (default_factory = SparseArray )
386+ # Runs after 'new-window' completes
387+ after_new_window : SparseArray [str ] = field (default_factory = SparseArray )
388+ # Runs after 'paste-buffer' completes
389+ after_paste_buffer : SparseArray [str ] = field (default_factory = SparseArray )
390+ # Runs after 'pipe-pane' completes
391+ after_pipe_pane : SparseArray [str ] = field (default_factory = SparseArray )
392+ # Runs after 'queue' command is processed
393+ after_queue : SparseArray [str ] = field (default_factory = SparseArray )
394+ # Runs after 'refresh-client' completes
395+ after_refresh_client : SparseArray [str ] = field (default_factory = SparseArray )
396+ # Runs after 'rename-session' completes
397+ after_rename_session : SparseArray [str ] = field (default_factory = SparseArray )
398+ # Runs after 'rename-window' completes
399+ after_rename_window : SparseArray [str ] = field (default_factory = SparseArray )
400+ # Runs after 'resize-pane' completes
401+ after_resize_pane : SparseArray [str ] = field (default_factory = SparseArray )
402+ # Runs after 'resize-window' completes
403+ after_resize_window : SparseArray [str ] = field (default_factory = SparseArray )
404+ # Runs after 'save-buffer' completes
405+ after_save_buffer : SparseArray [str ] = field (default_factory = SparseArray )
406+ # Runs after 'select-layout' completes
407+ after_select_layout : SparseArray [str ] = field (default_factory = SparseArray )
408+ # Runs after 'select-pane' completes
409+ after_select_pane : SparseArray [str ] = field (default_factory = SparseArray )
410+ # Runs after 'select-window' completes
411+ after_select_window : SparseArray [str ] = field (default_factory = SparseArray )
412+ # Runs after 'send-keys' completes
413+ after_send_keys : SparseArray [str ] = field (default_factory = SparseArray )
414+ # Runs after 'set-buffer' completes
415+ after_set_buffer : SparseArray [str ] = field (default_factory = SparseArray )
416+ # Runs after 'set-environment' completes
417+ after_set_environment : SparseArray [str ] = field (default_factory = SparseArray )
418+ # Runs after 'set-hook' completes
419+ after_set_hook : SparseArray [str ] = field (default_factory = SparseArray )
420+ # Runs after 'set-option' completes
421+ after_set_option : SparseArray [str ] = field (default_factory = SparseArray )
422+ # Runs after 'show-environment' completes
423+ after_show_environment : SparseArray [str ] = field (default_factory = SparseArray )
424+ # Runs after 'show-messages' completes
425+ after_show_messages : SparseArray [str ] = field (default_factory = SparseArray )
426+ # Runs after 'show-options' completes
427+ after_show_options : SparseArray [str ] = field (default_factory = SparseArray )
428+ # Runs after 'split-window' completes
429+ after_split_window : SparseArray [str ] = field (default_factory = SparseArray )
430+ # Runs after 'unbind-key' completes
431+ after_unbind_key : SparseArray [str ] = field (default_factory = SparseArray )
432+
433+ @classmethod
434+ def from_stdout (cls , value : list [str ]) -> "Hooks" :
435+ from libtmux .options import (
436+ explode_arrays ,
437+ explode_complex ,
438+ parse_options_to_dict ,
439+ )
440+
441+ output_exploded = explode_complex (
442+ explode_arrays (
443+ parse_options_to_dict (
444+ io .StringIO ("\n " .join (value )),
445+ ),
446+ force_array = True ,
447+ ),
448+ )
449+
450+ assert is_sparse_array_list (output_exploded )
451+
452+ output_renamed : HookArray = {
453+ k .lstrip ("%" ).replace ("-" , "_" ): v for k , v in output_exploded .items ()
454+ }
455+
456+ return cls (** output_renamed )
0 commit comments