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