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