fix trailing body passed to commands
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
ddc8c3b46c
commit
49033db2b8
1 changed files with 34 additions and 5 deletions
|
@ -1,7 +1,7 @@
|
||||||
use std::{panic::AssertUnwindSafe, sync::Arc, time::Instant};
|
use std::{panic::AssertUnwindSafe, sync::Arc, time::Instant};
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
use conduit::{error, trace, utils::string::common_prefix, Error, Result};
|
use conduit::{checked, error, trace, utils::string::common_prefix, Error, Result};
|
||||||
use futures_util::future::FutureExt;
|
use futures_util::future::FutureExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::{
|
events::{
|
||||||
|
@ -60,8 +60,11 @@ fn reply(mut content: RoomMessageEventContent, reply_id: Option<OwnedEventId>) -
|
||||||
|
|
||||||
// Parse and process a message from the admin room
|
// Parse and process a message from the admin room
|
||||||
async fn process(services: Arc<Services>, msg: &str) -> CommandOutput {
|
async fn process(services: Arc<Services>, msg: &str) -> CommandOutput {
|
||||||
let mut lines = msg.lines().filter(|l| !l.trim().is_empty());
|
let lines = msg.lines().filter(|l| !l.trim().is_empty());
|
||||||
let command = lines.next().expect("each string has at least one line");
|
let command = lines
|
||||||
|
.clone()
|
||||||
|
.next()
|
||||||
|
.expect("each string has at least one line");
|
||||||
let (parsed, body) = match parse_command(command) {
|
let (parsed, body) = match parse_command(command) {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -71,12 +74,12 @@ async fn process(services: Arc<Services>, msg: &str) -> CommandOutput {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let timer = Instant::now();
|
let body = parse_body(AdminCommand::command(), &body, lines.skip(1).collect()).expect("trailing body parsed");
|
||||||
let body: Vec<&str> = body.iter().map(String::as_str).collect();
|
|
||||||
let context = Command {
|
let context = Command {
|
||||||
services: &services,
|
services: &services,
|
||||||
body: &body,
|
body: &body,
|
||||||
};
|
};
|
||||||
|
let timer = Instant::now();
|
||||||
let result = Box::pin(admin::process(parsed, &context)).await;
|
let result = Box::pin(admin::process(parsed, &context)).await;
|
||||||
let elapsed = timer.elapsed();
|
let elapsed = timer.elapsed();
|
||||||
conduit::debug!(?command, ok = result.is_ok(), "command processed in {elapsed:?}");
|
conduit::debug!(?command, ok = result.is_ok(), "command processed in {elapsed:?}");
|
||||||
|
@ -95,6 +98,32 @@ fn parse_command(command_line: &str) -> Result<(AdminCommand, Vec<String>), Stri
|
||||||
Ok((com, argv))
|
Ok((com, argv))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_body<'a>(mut cmd: clap::Command, body: &'a [String], lines: Vec<&'a str>) -> Result<Vec<&'a str>> {
|
||||||
|
let mut start = 1;
|
||||||
|
'token: for token in body.iter().skip(1) {
|
||||||
|
let cmd_ = cmd.clone();
|
||||||
|
for sub in cmd_.get_subcommands() {
|
||||||
|
if sub.get_name() == *token {
|
||||||
|
start = checked!(start + 1)?;
|
||||||
|
cmd = sub.clone();
|
||||||
|
continue 'token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// positional arguments have to be skipped too
|
||||||
|
let num_posargs = cmd_.get_positionals().count();
|
||||||
|
start = checked!(start + num_posargs)?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(body
|
||||||
|
.iter()
|
||||||
|
.skip(start)
|
||||||
|
.map(String::as_str)
|
||||||
|
.chain(lines)
|
||||||
|
.collect::<Vec<&'a str>>())
|
||||||
|
}
|
||||||
|
|
||||||
fn complete_command(mut cmd: clap::Command, line: &str) -> String {
|
fn complete_command(mut cmd: clap::Command, line: &str) -> String {
|
||||||
let argv = parse_line(line);
|
let argv = parse_line(line);
|
||||||
let mut ret = Vec::<String>::with_capacity(argv.len().saturating_add(1));
|
let mut ret = Vec::<String>::with_capacity(argv.len().saturating_add(1));
|
||||||
|
|
Loading…
Add table
Reference in a new issue