1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
17pub enum Slash {
18 Help,
19 Room,
20 New,
21 Stop,
22 Halt,
23 Release,
24 Model,
25 Effort,
26 Approve,
27 Deny,
28 Web,
29 Quit,
30 Serving,
31 Remote,
32 Acp,
33 Wire,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum Offered {
39 Cli,
40 WebUi,
41 Both,
42}
43
44impl Offered {
45 #[must_use]
47 pub const fn as_str(self) -> &'static str {
48 match self {
49 Self::Cli => "cli",
50 Self::WebUi => "webui",
51 Self::Both => "both",
52 }
53 }
54
55 #[must_use]
57 pub const fn in_the_cli(self) -> bool {
58 match self {
59 Self::Cli | Self::Both => true,
60 Self::WebUi => false,
61 }
62 }
63}
64
65impl Slash {
66 pub const ALL: [Slash; 16] = [
68 Self::Help,
69 Self::Room,
70 Self::New,
71 Self::Stop,
72 Self::Halt,
73 Self::Release,
74 Self::Model,
75 Self::Effort,
76 Self::Approve,
77 Self::Deny,
78 Self::Web,
79 Self::Quit,
80 Self::Serving,
81 Self::Remote,
82 Self::Acp,
83 Self::Wire,
84 ];
85
86 #[must_use]
88 pub const fn spelling(self) -> &'static str {
89 match self {
90 Self::Help => "/help",
91 Self::Room => "/room",
92 Self::New => "/new",
93 Self::Stop => "/stop",
94 Self::Halt => "/halt",
95 Self::Release => "/release",
96 Self::Model => "/model",
97 Self::Effort => "/effort",
98 Self::Approve => "/approve",
99 Self::Deny => "/deny",
100 Self::Web => "/web",
101 Self::Quit => "/quit",
102 Self::Serving => "/serving",
103 Self::Remote => "/remote",
104 Self::Acp => "/acp",
105 Self::Wire => "/wire",
106 }
107 }
108
109 #[must_use]
111 pub const fn takes(self) -> &'static str {
112 match self {
113 Self::Help | Self::New | Self::Stop | Self::Web | Self::Quit | Self::Serving => "",
114 Self::Room => "<addr>",
115 Self::Halt | Self::Release => "[--all]",
116 Self::Model | Self::Approve | Self::Deny => "[<id>]",
117 Self::Effort => "[<level>]",
118 Self::Remote => "<verb>",
119 Self::Acp => "[<text>]",
120 Self::Wire => "<verb> [<json>]",
121 }
122 }
123
124 #[must_use]
126 pub const fn offered(self) -> Offered {
127 match self {
128 Self::Help
129 | Self::Room
130 | Self::New
131 | Self::Stop
132 | Self::Halt
133 | Self::Release
134 | Self::Model
135 | Self::Effort
136 | Self::Quit
137 | Self::Acp => Offered::Both,
138 Self::Approve | Self::Deny | Self::Web | Self::Serving | Self::Remote | Self::Wire => {
139 Offered::Cli
140 }
141 }
142 }
143
144 #[must_use]
146 pub const fn says(self) -> &'static str {
147 match self {
148 Self::Help => "list these verbs",
149 Self::Room => "choose the room plain lines go to",
150 Self::New => "start a new session in this room",
151 Self::Stop => "stop the run working in this room",
152 Self::Halt => "hold this room's building, or with --all the whole city",
153 Self::Release => "let this room's building work again, or with --all the whole city",
154 Self::Model => "show the model, or choose one the city's endpoints offer",
155 Self::Effort => "show the thinking level, or choose one the model offers",
156 Self::Approve => "approve the waiting request, or the one with this id",
157 Self::Deny => "deny the waiting request, or the one with this id",
158 Self::Web => "open the WebUI and quiet this terminal; Esc comes back",
159 Self::Quit => "close the city",
160 Self::Serving => "where this city listens, and what is running in it",
161 Self::Remote => {
162 "open|pair|close|devices|revoke: the door a device reaches the city through"
163 }
164 Self::Acp => "find an ACP agent, or read a pasted launch line",
165 Self::Wire => "send any wire command or question, its body as JSON",
166 }
167 }
168
169 #[must_use]
171 pub fn parse(word: &str) -> Option<Slash> {
172 let bare = word.strip_prefix('/').unwrap_or(word);
173 Self::ALL
174 .into_iter()
175 .find(|verb| verb.spelling().strip_prefix('/') == Some(bare))
176 }
177}