Skip to content

Commit 115f4ca

Browse files
various improvements, NS HELP support
1 parent 7d657a0 commit 115f4ca

3 files changed

Lines changed: 106 additions & 45 deletions

File tree

sable_ircd/src/command/handlers/help.rs

Lines changed: 102 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use super::*;
33
use itertools::Itertools;
44

55
#[command_handler("HELP", "UHELP")]
6-
/// HELP [<topic>]
6+
/// HELP \[\<topic\>\]
77
///
88
/// HELP displays information for topic requested.
99
/// If no topic is requested, it will list available
@@ -15,60 +15,119 @@ fn help_handler(
1515
source: UserSource,
1616
topic: Option<&str>,
1717
) -> CommandResult {
18-
// TODO: oper help? (and if oper help is on the same command, UHELP like solanum?)
18+
// TODO: better restricted mechanism?
1919
// TODO: non-command help topics
2020
let is_oper = command.command().to_ascii_uppercase() != "UHELP" && source.is_oper();
2121

2222
match topic {
23-
Some(s) => {
24-
let topic = s.to_ascii_uppercase();
25-
let topic = topic
26-
.split_once(' ')
27-
.map_or(topic.clone(), |(t, _)| t.to_string());
23+
Some(t) => {
24+
let topic = t.to_ascii_uppercase();
25+
let topic = topic.split_once(' ').map_or(topic.clone(), |(t, _)| t.to_string());
26+
if let Some(mut lines) = get_help(&server.command_dispatcher, &topic, is_oper) {
27+
response.numeric(make_numeric!(
28+
HelpStart,
29+
&topic,
30+
lines.next().unwrap().as_ref()
31+
));
32+
for line in lines {
33+
response.numeric(make_numeric!(HelpText, &topic, line.as_ref()));
34+
}
35+
response.numeric(make_numeric!(EndOfHelp, &topic));
36+
return Ok(());
37+
} else {
38+
response.numeric(make_numeric!(HelpNotFound, &topic));
39+
}
40+
}
41+
None => {
42+
let topic = "*";
43+
response.numeric(make_numeric!(HelpStart, &topic, "Available help topics:"));
44+
response.numeric(make_numeric!(HelpText, &topic, ""));
45+
for line in list_help(&server.command_dispatcher, is_oper) {
46+
response.numeric(make_numeric!(HelpText, &topic, line.as_ref()));
47+
}
48+
response.numeric(make_numeric!(EndOfHelp, &topic));
49+
}
50+
};
51+
Ok(())
52+
}
2853

29-
if let Some(cmd) = server.get_command(&topic) {
30-
if cmd.docs.len() > 0 {
31-
// TODO
32-
if cmd.restricted && is_oper {
33-
response.numeric(make_numeric!(HelpNotFound, &topic));
34-
return Ok(());
35-
}
36-
let mut lines = cmd.docs.iter();
37-
response.numeric(make_numeric!(
38-
HelpStart,
39-
&topic,
40-
lines.next().unwrap_or(&topic.as_str())
41-
));
42-
for line in lines {
43-
response.numeric(make_numeric!(HelpText, &topic, line));
44-
}
45-
response.numeric(make_numeric!(EndOfHelp, &topic));
46-
return Ok(());
54+
#[command_handler("HELP", "UHELP", in("NS"))]
55+
/// NS HELP \[\<topic\>\]
56+
///
57+
/// Displays information about the topic requested.
58+
fn ns_help_handler(
59+
command: &dyn Command,
60+
response: &dyn CommandResponse,
61+
server: &ClientServer,
62+
source: UserSource,
63+
topic: Option<&str>,
64+
) -> CommandResult {
65+
let is_oper = command.command().to_ascii_uppercase() != "UHELP" && source.is_oper();
66+
let dispatcher = CommandDispatcher::with_category("NS");
67+
68+
match topic {
69+
Some(t) => {
70+
let topic = t.to_ascii_uppercase();
71+
let topic = topic.split_once(' ').map_or(topic.clone(), |(t, _)| t.to_string());
72+
if let Some(mut lines) = get_help(&dispatcher, &topic, is_oper) {
73+
response.numeric(make_numeric!(
74+
HelpStart,
75+
&topic,
76+
lines.next().unwrap().as_ref()
77+
));
78+
for line in lines {
79+
response.numeric(make_numeric!(HelpText, &topic, line.as_ref()));
4780
}
81+
response.numeric(make_numeric!(EndOfHelp, &topic));
82+
return Ok(());
83+
} else {
84+
response.numeric(make_numeric!(HelpNotFound, &topic));
4885
}
49-
response.numeric(make_numeric!(HelpNotFound, &topic));
5086
}
5187
None => {
5288
let topic = "*";
53-
response.numeric(make_numeric!(HelpStart, topic, "Available help topics:"));
54-
response.numeric(make_numeric!(HelpText, topic, ""));
55-
for chunk in &server
56-
.iter_commands()
57-
.filter_map(|(k, v)| {
58-
if !v.restricted || is_oper {
59-
Some(k.to_ascii_uppercase())
60-
} else {
61-
None
62-
}
63-
})
64-
.sorted()
65-
.chunks(4)
66-
{
67-
let line = format!("{:16}", chunk.format(" "));
68-
response.numeric(make_numeric!(HelpText, topic, &line));
89+
response.numeric(make_numeric!(HelpStart, &topic, "Available help topics:"));
90+
response.numeric(make_numeric!(HelpText, &topic, ""));
91+
for line in list_help(&dispatcher, is_oper) {
92+
response.numeric(make_numeric!(HelpText, &topic, line.as_ref()));
6993
}
70-
response.numeric(make_numeric!(EndOfHelp, topic));
94+
response.numeric(make_numeric!(EndOfHelp, &topic));
7195
}
7296
};
7397
Ok(())
7498
}
99+
100+
fn get_help(
101+
dispatcher: &CommandDispatcher,
102+
topic: &str,
103+
is_oper: bool,
104+
) -> Option<impl Iterator<Item = impl AsRef<str>>> {
105+
if let Some(cmd) = dispatcher.get_command(&topic) {
106+
if cmd.docs.len() > 0 {
107+
if cmd.restricted && !is_oper {
108+
return None;
109+
}
110+
return Some(cmd.docs.iter());
111+
}
112+
}
113+
return None;
114+
}
115+
116+
fn list_help(dispatcher: &CommandDispatcher, is_oper: bool) -> Vec<impl AsRef<str>> {
117+
let mut lines = vec![];
118+
for chunk in &dispatcher
119+
.iter_commands()
120+
.filter_map(|(k, v)| {
121+
if (!v.restricted || is_oper) && (v.docs.len() > 0) {
122+
Some(k.to_ascii_uppercase())
123+
} else {
124+
None
125+
}
126+
})
127+
.sorted()
128+
.chunks(4)
129+
{
130+
lines.push(format!("{:16}", chunk.format(" ")));
131+
}
132+
lines
133+
}

sable_ircd/src/server/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub struct ClientServer {
7474
stored_response_sinks: RwLock<MessageSinkRepository>,
7575

7676
action_submitter: UnboundedSender<CommandAction>,
77-
command_dispatcher: command::CommandDispatcher,
77+
pub command_dispatcher: command::CommandDispatcher,
7878

7979
connections: RwLock<ConnectionCollection>,
8080
/// Connections which either did not complete registration or completed it recently,

sable_macros/src/command_handler.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ pub fn command_docs(attrs: &[Attribute]) -> Vec<String> {
5959
})) => Some(s.value()),
6060
_ => None,
6161
})
62-
.map(|s| s.strip_prefix(' ').unwrap_or(&s).trim_end().to_owned())
62+
// XXX: markdown-stripping could be a bit more robust
63+
.map(|s| s.strip_prefix(' ').unwrap_or(&s).trim_end()
64+
.replace(r"\[", "[").replace(r"\]", "]").replace(r"\<", "<").replace(r"\>", ">"))
6365
.collect()
6466
}
6567

0 commit comments

Comments
 (0)