reactive_graph_client/client/repl/
repl_helper.rs

1use std::borrow::Cow;
2
3use clap::Parser;
4use colored::Colorize;
5use rustyline::Context;
6use rustyline::Helper;
7use rustyline::Result;
8use rustyline::completion::Completer;
9use rustyline::highlight::Highlighter;
10use rustyline::hint::Hinter;
11use rustyline::validate::ValidationContext;
12use rustyline::validate::ValidationResult;
13use rustyline::validate::Validator;
14use shellwords::split;
15
16use crate::client::repl::args::ReplArgs;
17use crate::client::repl::hint::HinterMatch;
18
19pub struct ReplHelper {}
20
21impl ReplHelper {
22    pub fn new() -> Self {
23        Self {}
24    }
25}
26
27impl Completer for ReplHelper {
28    type Candidate = &'static str;
29}
30
31impl Highlighter for ReplHelper {
32    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
33        Cow::Owned(hint.cyan().to_string())
34    }
35}
36
37impl Validator for ReplHelper {
38    fn validate(&self, _: &mut ValidationContext) -> Result<ValidationResult> {
39        Ok(ValidationResult::Valid(None))
40    }
41}
42
43impl Hinter for ReplHelper {
44    type Hint = HinterMatch;
45
46    fn hint(&self, line: &str, _pos: usize, _ctx: &Context<'_>) -> Option<Self::Hint> {
47        let Ok(args) = split(line).map(|mut args| {
48            args.insert(0, String::from(" "));
49            args
50        }) else {
51            return None;
52        };
53        let hinter_match = match ReplArgs::try_parse_from(args.clone()) {
54            Ok(command) => HinterMatch::new_from_args_and_command(args, command),
55            Err(error) => HinterMatch::new_from_args_and_error(args, error),
56        };
57        Some(hinter_match)
58    }
59}
60
61impl Helper for ReplHelper {}