Skip to content

Commit

Permalink
add help autocorrection
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacherr committed Sep 15, 2024
1 parent 5abb609 commit fb91212
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 8 deletions.
39 changes: 39 additions & 0 deletions assyst-core/src/command/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,45 @@ impl ParseArgument for Vec<Word> {
}
}

impl ParseArgument for Vec<WordAutocomplete> {
async fn parse_raw_message(ctxt: &mut RawMessageParseCtxt<'_>, label: Label) -> Result<Self, TagParseError> {
let mut items = Vec::new();

// `Option<T>`'s parser takes care of recovering from low severity errors
// and any `Err`s returned are fatal, so we can just use `?`
while let Some(value) = <Option<WordAutocomplete>>::parse_raw_message(ctxt, label.clone()).await? {
items.push(value)
}

Ok(items)
}

async fn parse_command_option(
ctxt: &mut InteractionCommandParseCtxt<'_>,
label: Label,
) -> Result<Self, TagParseError> {
let text = WordAutocomplete::parse_command_option(ctxt, label).await?;
let items = text
.0
.split_ascii_whitespace()
.map(|y| WordAutocomplete(y.to_owned()))
.collect::<Vec<_>>();

Ok(items)
}

fn as_command_option(name: &str) -> CommandOption {
StringBuilder::new(name, "text input")
.autocomplete(true)
.required(true)
.build()
}

fn usage(name: &str) -> String {
format!("<{name}[]>")
}
}

/// A time argument such as `1h20m30s`.
#[derive(Debug)]
pub struct Time {
Expand Down
38 changes: 33 additions & 5 deletions assyst-core/src/command/misc/help.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::time::Duration;

use anyhow::bail;
use assyst_common::config::CONFIG;
use assyst_proc_macro::command;
use assyst_string_fmt::{Ansi, Markdown};

use crate::command::arguments::Word;
use crate::assyst::ThreadSafeAssyst;
use crate::command::arguments::WordAutocomplete;
use crate::command::autocomplete::AutocompleteData;
use crate::command::registry::{find_command_by_name, get_or_init_commands};
use crate::command::{Availability, Category, Command, CommandCtxt};

async fn help_autocomplete(_assyst: ThreadSafeAssyst, data: AutocompleteData) -> Vec<String> {
let commands = get_or_init_commands();
// remove all aliases
let mut deduped = HashMap::new();
for command in commands {
if command.1.metadata().access != Availability::Dev || CONFIG.dev.admin_users.contains(&data.user.id.get()) {
deduped.insert(command.1.metadata().name, *command.1);
}
}

let mut names = HashSet::<String>::new();
for command in deduped {
if let Some(s) = command.1.subcommands() {
for c in s {
names.insert(format!("{} {}", command.0, c.0));
}
}
names.insert(command.0.to_owned());
}

names.into_iter().collect()
}

#[command(
description = "get command help",
aliases = ["cmds", "commands", "h"],
Expand All @@ -19,7 +44,10 @@ use crate::command::{Availability, Category, Command, CommandCtxt};
usage = "<category|command>",
examples = ["", "misc", "ping", "tag create"]
)]
pub async fn help(ctxt: CommandCtxt<'_>, labels: Option<Vec<Word>>) -> anyhow::Result<()> {
pub async fn help(
ctxt: CommandCtxt<'_>,
#[autocomplete = "crate::command::misc::help::help_autocomplete"] labels: Option<Vec<WordAutocomplete>>,
) -> anyhow::Result<()> {
let cmds = get_or_init_commands();
let labels = labels.unwrap_or_default();

Expand All @@ -42,7 +70,7 @@ pub async fn help(ctxt: CommandCtxt<'_>, labels: Option<Vec<Word>>) -> anyhow::R

let mut labels = labels.into_iter();
// if we have some argument
if let Some(Word(base_command)) = labels.next() {
if let Some(WordAutocomplete(base_command)) = labels.next() {
// if the base is a command
if let Some(mut command) = find_command_by_name(&base_command) {
let mut meta = command.metadata();
Expand All @@ -55,7 +83,7 @@ pub async fn help(ctxt: CommandCtxt<'_>, labels: Option<Vec<Word>>) -> anyhow::R

// If there are more arguments, follow the chain of subcommands and build up the usage
// along the way
for Word(mut label) in labels {
for WordAutocomplete(mut label) in labels {
let metadata = command.metadata();
usage += metadata.name;
usage += " ";
Expand Down
2 changes: 1 addition & 1 deletion assyst-core/src/command/misc/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ pub async fn search(ctxt: CommandCtxt<'_>, query: Word, user: Option<User>) -> a
cooldown = Duration::from_secs(5),
access = Availability::Public,
category = Category::Misc,
usage = "[name]",
usage = "",
examples = [""],
guild_only = true
)]
Expand Down
4 changes: 2 additions & 2 deletions assyst-flux-iface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl FluxHandler {
FluxStep::Input(i) => {
let hash = hash_buffer(&i);
let path = format!("/tmp/{hash}");
fs::write(&path, &i).await?;
fs::write(&path, &i).await.context("failed to write input file")?;
input_file_paths.push(path.clone());

args.push("-i".to_owned());
Expand Down Expand Up @@ -194,7 +194,7 @@ impl FluxHandler {
let _defer = CompilingCompleteDefer {};

let res = exec_sync(&format!(
"cd {} && rm {FLUX_PATH} && mold -run ~/.cargo/bin/cargo build -q --release",
"cd {} && rm -f {FLUX_PATH} && mold -run ~/.cargo/bin/cargo build -q --release",
if CONFIG.dev.flux_workspace_root_path_override.is_empty() {
FLUX_DIR
} else {
Expand Down

0 comments on commit fb91212

Please sign in to comment.