Improve repl autocorrect and error handling

* Combine comparison algorithims for autocorrect

* clear zephyr functions

* remove redundant comments because co-pilot is stupid and i probably will never try to use it again

* implement basic tab completion

* fix unused items

* Make workflow check code quality

* split code quality into its own file

* make action fail on bad formatting

* change workflow to nightly

* f it, code quality is considered breaking

* fix forgetting to set toolchain back to nightly when rewriting workflow (😔)

* Add condition for too little arguments

* run cargo fmt

* remove unneeded feature directive
This commit is contained in:
Chance 2024-12-09 20:28:28 -05:00 committed by GitHub
parent b4f31785d4
commit 3aba3aea1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 170 additions and 42 deletions

View file

@ -9,9 +9,9 @@ use log::debug;
use parking_lot::Mutex;
use regex::Regex;
use rustyline::{
error::ReadlineError, highlight::Highlighter, hint::HistoryHinter, history::DefaultHistory,
Cmd, Completer, ConditionalEventHandler, Editor, Event, EventContext, EventHandler, Helper,
Hinter, KeyEvent, RepeatCount, Validator,
completion::Completer, error::ReadlineError, highlight::Highlighter, hint::HistoryHinter,
history::DefaultHistory, Cmd, Completer, ConditionalEventHandler, Editor, Event, EventContext,
EventHandler, Helper, Hinter, KeyEvent, RepeatCount, Validator,
};
use crate::{
@ -19,8 +19,44 @@ use crate::{
utils::logger::LOGGER,
};
struct CommandCompleter;
impl CommandCompleter {
fn new() -> Self {
CommandCompleter {}
}
}
impl Completer for CommandCompleter {
type Candidate = String;
fn complete(
&self,
line: &str,
pos: usize,
_ctx: &rustyline::Context<'_>,
) -> rustyline::Result<(usize, Vec<Self::Candidate>)> {
let binding = COMMAND_LIST.commands.read();
let filtered_commands: Vec<_> = binding
.iter()
.filter(|command| command.name.starts_with(line))
.collect();
let completions: Vec<String> = filtered_commands
.iter()
.filter(|command| command.name.starts_with(&line[..pos]))
.map(|command| command.name[pos..].to_string())
.collect();
Ok((pos, completions))
}
}
#[derive(Completer, Helper, Hinter, Validator)]
struct MyHelper(#[rustyline(Hinter)] HistoryHinter);
struct MyHelper {
#[rustyline(Hinter)]
hinter: HistoryHinter,
#[rustyline(Completer)]
completer: CommandCompleter,
}
impl Highlighter for MyHelper {
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
@ -142,6 +178,11 @@ fn tokenize(command: &str) -> Vec<String> {
tokens
}
pub fn parse_command(input: &str) -> anyhow::Result<Vec<String>> {
let pattern = Regex::new(r"[;|\n]").unwrap();
let commands: Vec<String> = pattern.split(input).map(|s| String::from(s)).collect();
Ok(commands)
}
pub fn evaluate_command(input: &str) -> anyhow::Result<()> {
if input.trim().is_empty() {
println!("Empty command, skipping. type 'help' for a list of commands.");
@ -176,7 +217,10 @@ pub fn evaluate_command(input: &str) -> anyhow::Result<()> {
pub async fn handle_repl() -> anyhow::Result<()> {
let mut rl = Editor::<MyHelper, DefaultHistory>::new()?;
rl.set_helper(Some(MyHelper(HistoryHinter::new())));
rl.set_helper(Some(MyHelper {
hinter: HistoryHinter::new(),
completer: CommandCompleter::new(),
}));
rl.bind_sequence(
KeyEvent::from('`'),