1use std::{collections::HashMap, sync::Arc};
2
3use crate::{CommandId, DefaultKeybinding, WhenExpr};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum OsAction {
8 Cut,
9 Copy,
10 Paste,
11 SelectAll,
12 Undo,
13 Redo,
14}
15
16#[derive(Default)]
17pub struct CommandRegistry {
22 commands: HashMap<CommandId, CommandMeta>,
23}
24
25#[derive(Debug, Clone)]
26pub struct CommandMeta {
28 pub title: Arc<str>,
29 pub description: Option<Arc<str>>,
30 pub category: Option<Arc<str>>,
31 pub keywords: Vec<Arc<str>>,
32 pub default_keybindings: Vec<DefaultKeybinding>,
33 pub when: Option<WhenExpr>,
34 pub os_action: Option<OsAction>,
35 pub scope: CommandScope,
36 pub hidden: bool,
37 pub repeatable: bool,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum CommandScope {
43 Widget,
45 Window,
47 App,
49}
50
51impl CommandMeta {
52 pub fn new(title: impl Into<Arc<str>>) -> Self {
53 Self {
54 title: title.into(),
55 description: None,
56 category: None,
57 keywords: Vec::new(),
58 default_keybindings: Vec::new(),
59 when: None,
60 os_action: None,
61 scope: CommandScope::Window,
62 hidden: false,
63 repeatable: false,
64 }
65 }
66
67 pub fn with_description(mut self, description: impl Into<Arc<str>>) -> Self {
68 self.description = Some(description.into());
69 self
70 }
71
72 pub fn with_category(mut self, category: impl Into<Arc<str>>) -> Self {
73 self.category = Some(category.into());
74 self
75 }
76
77 pub fn with_keywords(
78 mut self,
79 keywords: impl IntoIterator<Item = impl Into<Arc<str>>>,
80 ) -> Self {
81 self.keywords = keywords.into_iter().map(Into::into).collect();
82 self
83 }
84
85 pub fn with_default_keybindings(
86 mut self,
87 bindings: impl IntoIterator<Item = DefaultKeybinding>,
88 ) -> Self {
89 self.default_keybindings = bindings.into_iter().collect();
90 self
91 }
92
93 pub fn with_when(mut self, when: WhenExpr) -> Self {
94 self.when = Some(when);
95 self
96 }
97
98 pub fn with_os_action(mut self, os_action: OsAction) -> Self {
99 self.os_action = Some(os_action);
100 self
101 }
102
103 pub fn with_scope(mut self, scope: CommandScope) -> Self {
104 self.scope = scope;
105 self
106 }
107
108 pub fn hidden(mut self) -> Self {
109 self.hidden = true;
110 self
111 }
112
113 pub fn repeatable(mut self) -> Self {
114 self.repeatable = true;
115 self
116 }
117}
118
119impl CommandRegistry {
120 pub fn register(&mut self, id: CommandId, meta: CommandMeta) {
121 self.commands.insert(id, meta);
122 }
123
124 pub fn get(&self, id: CommandId) -> Option<&CommandMeta> {
125 self.commands.get(&id)
126 }
127
128 pub fn iter(&self) -> impl Iterator<Item = (&CommandId, &CommandMeta)> {
129 self.commands.iter()
130 }
131}