1use rmux_proto::{HookName, RmuxError, ScopeSelector, SessionName, Target, WindowTarget};
2
3use super::types::{HookClass, HookGlobalRoot};
4
5pub fn validate_hook_scope(hook: HookName, scope: &ScopeSelector) -> Result<(), RmuxError> {
7 let _ = hook_class(hook);
8 let _ = scope;
9 Ok(())
10}
11
12pub fn validate_hook_registration(hook: HookName, scope: &ScopeSelector) -> Result<(), RmuxError> {
15 if !hook_is_supported_for_registration(hook) {
16 return Err(RmuxError::Message(format!(
17 "{} is not supported: rmux does not dispatch this hook",
18 hook_name(hook)
19 )));
20 }
21
22 validate_hook_scope(hook, scope)
23}
24
25#[must_use]
27pub fn hook_natural_scope_for_target(hook: HookName, target: Target) -> ScopeSelector {
28 match target {
29 Target::Session(session_name) => ScopeSelector::Session(session_name),
30 Target::Window(target) => match hook_class(hook) {
31 HookClass::Session => ScopeSelector::Session(target.session_name().clone()),
32 HookClass::Window | HookClass::Pane => ScopeSelector::Window(target),
33 },
34 Target::Pane(target) => match hook_class(hook) {
35 HookClass::Session => ScopeSelector::Session(target.session_name().clone()),
36 HookClass::Window | HookClass::Pane => ScopeSelector::Window(
37 WindowTarget::with_window(target.session_name().clone(), target.window_index()),
38 ),
39 },
40 }
41}
42
43#[must_use]
45pub fn hook_explicit_scope_for_target(hook: HookName, target: Target) -> ScopeSelector {
46 match target {
47 Target::Session(session_name) => ScopeSelector::Session(session_name),
48 Target::Window(target) => match hook_class(hook) {
49 HookClass::Session => ScopeSelector::Session(target.session_name().clone()),
50 HookClass::Window | HookClass::Pane => ScopeSelector::Window(target),
51 },
52 Target::Pane(target) => match hook_class(hook) {
53 HookClass::Session => ScopeSelector::Session(target.session_name().clone()),
54 HookClass::Window => ScopeSelector::Window(WindowTarget::with_window(
55 target.session_name().clone(),
56 target.window_index(),
57 )),
58 HookClass::Pane => ScopeSelector::Pane(target),
59 },
60 }
61}
62
63#[must_use]
66pub fn hook_natural_scope_for_session_target(
67 hook: HookName,
68 session_name: SessionName,
69 window_index: u32,
70 _pane_index: u32,
71) -> ScopeSelector {
72 match hook_class(hook) {
73 HookClass::Session => ScopeSelector::Session(session_name),
74 HookClass::Window | HookClass::Pane => {
75 ScopeSelector::Window(WindowTarget::with_window(session_name, window_index))
76 }
77 }
78}
79
80pub(super) const fn hook_inventory() -> [HookName; 70] {
81 [
82 HookName::AfterBindKey,
83 HookName::AfterCapturePane,
84 HookName::AfterCopyMode,
85 HookName::AfterDisplayMessage,
86 HookName::AfterDisplayPanes,
87 HookName::AfterKillPane,
88 HookName::AfterListBuffers,
89 HookName::AfterListClients,
90 HookName::AfterListKeys,
91 HookName::AfterListPanes,
92 HookName::AfterListSessions,
93 HookName::AfterListWindows,
94 HookName::AfterLoadBuffer,
95 HookName::AfterLockServer,
96 HookName::AfterNewSession,
97 HookName::AfterNewWindow,
98 HookName::AfterPasteBuffer,
99 HookName::AfterPipePane,
100 HookName::AfterQueue,
101 HookName::AfterRefreshClient,
102 HookName::AfterRenameSession,
103 HookName::AfterRenameWindow,
104 HookName::AfterResizePane,
105 HookName::AfterResizeWindow,
106 HookName::AfterSaveBuffer,
107 HookName::AfterSelectLayout,
108 HookName::AfterSelectPane,
109 HookName::AfterSelectWindow,
110 HookName::AfterSendKeys,
111 HookName::AfterSetBuffer,
112 HookName::AfterSetEnvironment,
113 HookName::AfterSetHook,
114 HookName::AfterSetOption,
115 HookName::AfterShowEnvironment,
116 HookName::AfterShowMessages,
117 HookName::AfterShowOptions,
118 HookName::AfterSplitWindow,
119 HookName::AfterUnbindKey,
120 HookName::AlertActivity,
121 HookName::AlertBell,
122 HookName::AlertSilence,
123 HookName::ClientActive,
124 HookName::ClientAttached,
125 HookName::ClientDetached,
126 HookName::ClientFocusIn,
127 HookName::ClientFocusOut,
128 HookName::ClientResized,
129 HookName::ClientSessionChanged,
130 HookName::ClientLightTheme,
131 HookName::ClientDarkTheme,
132 HookName::CommandError,
133 HookName::PaneDied,
134 HookName::PaneExited,
135 HookName::PaneFocusIn,
136 HookName::PaneFocusOut,
137 HookName::PaneModeChanged,
138 HookName::PaneSetClipboard,
139 HookName::PaneTitleChanged,
140 HookName::SessionClosed,
141 HookName::SessionCreated,
142 HookName::SessionRenamed,
143 HookName::SessionWindowChanged,
144 HookName::WindowLayoutChanged,
145 HookName::WindowLinked,
146 HookName::WindowPaneChanged,
147 HookName::WindowRenamed,
148 HookName::WindowResized,
149 HookName::WindowUnlinked,
150 HookName::PasteBufferChanged,
151 HookName::PasteBufferDeleted,
152 ]
153}
154
155pub(super) const fn hook_class(hook: HookName) -> HookClass {
156 match hook {
157 HookName::WindowLayoutChanged
158 | HookName::WindowPaneChanged
159 | HookName::WindowRenamed
160 | HookName::WindowResized => HookClass::Window,
161 HookName::PaneDied
162 | HookName::PaneExited
163 | HookName::PaneFocusIn
164 | HookName::PaneFocusOut
165 | HookName::PaneModeChanged
166 | HookName::PaneSetClipboard
167 | HookName::PaneTitleChanged => HookClass::Pane,
168 HookName::AfterBindKey
169 | HookName::AfterCapturePane
170 | HookName::AfterCopyMode
171 | HookName::AfterDisplayMessage
172 | HookName::AfterDisplayPanes
173 | HookName::AfterKillPane
174 | HookName::AfterListBuffers
175 | HookName::AfterListClients
176 | HookName::AfterListKeys
177 | HookName::AfterListPanes
178 | HookName::AfterListSessions
179 | HookName::AfterListWindows
180 | HookName::AfterLoadBuffer
181 | HookName::AfterLockServer
182 | HookName::AfterNewSession
183 | HookName::AfterNewWindow
184 | HookName::AfterPasteBuffer
185 | HookName::AfterPipePane
186 | HookName::AfterQueue
187 | HookName::AfterRefreshClient
188 | HookName::AfterRenameSession
189 | HookName::AfterRenameWindow
190 | HookName::AfterResizePane
191 | HookName::AfterResizeWindow
192 | HookName::AfterSaveBuffer
193 | HookName::AfterSelectLayout
194 | HookName::AfterSelectPane
195 | HookName::AfterSelectWindow
196 | HookName::AfterSendKeys
197 | HookName::AfterSetBuffer
198 | HookName::AfterSetEnvironment
199 | HookName::AfterSetHook
200 | HookName::AfterSetOption
201 | HookName::AfterShowEnvironment
202 | HookName::AfterShowMessages
203 | HookName::AfterShowOptions
204 | HookName::AfterSplitWindow
205 | HookName::AfterUnbindKey
206 | HookName::AlertActivity
207 | HookName::AlertBell
208 | HookName::AlertSilence
209 | HookName::ClientActive
210 | HookName::ClientAttached
211 | HookName::ClientDetached
212 | HookName::ClientFocusIn
213 | HookName::ClientFocusOut
214 | HookName::ClientResized
215 | HookName::ClientSessionChanged
216 | HookName::ClientLightTheme
217 | HookName::ClientDarkTheme
218 | HookName::CommandError
219 | HookName::SessionCreated
220 | HookName::SessionClosed
221 | HookName::SessionRenamed
222 | HookName::SessionWindowChanged
223 | HookName::WindowLinked
224 | HookName::WindowUnlinked
225 | HookName::PasteBufferChanged
226 | HookName::PasteBufferDeleted => HookClass::Session,
227 }
228}
229
230pub(super) const fn root_for_hook(hook: HookName) -> HookGlobalRoot {
231 match hook_class(hook) {
232 HookClass::Session => HookGlobalRoot::Session,
233 HookClass::Window | HookClass::Pane => HookGlobalRoot::Window,
234 }
235}
236
237#[must_use]
239pub const fn hook_global_root(hook: HookName) -> HookGlobalRoot {
240 root_for_hook(hook)
241}
242
243pub(super) const fn hook_is_visible_in_show_hooks(hook: HookName) -> bool {
244 !matches!(
245 hook,
246 HookName::PasteBufferChanged | HookName::PasteBufferDeleted
247 )
248}
249
250const fn hook_is_supported_for_registration(hook: HookName) -> bool {
251 !matches!(
252 hook,
253 HookName::PasteBufferChanged | HookName::PasteBufferDeleted
254 )
255}
256
257const fn hook_name(hook: HookName) -> &'static str {
258 hook.as_str()
259}