Skip to main content

rmux_core/hooks/
rules.rs

1use rmux_proto::{HookName, RmuxError, ScopeSelector};
2
3use super::types::{HookClass, HookGlobalRoot};
4
5/// Validates that a hook may be stored at the requested scope.
6pub 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
35/// Validates that rmux ships the requested hook and that it may be stored at
36/// the requested scope.
37pub 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}