diff options
| author | sigoden <sigoden@gmail.com> | 2023-03-12 07:54:18 +0800 |
|---|---|---|
| committer | sigoden <sigoden@gmail.com> | 2023-03-12 07:54:18 +0800 |
| commit | 0ed0ad1fd26cccb9f41379e2f0f2c77fca43c608 (patch) | |
| tree | f0e44c0fd0d62c7a8ddb3ffe77f8e5687d855b5d /src | |
| parent | 4aab872ee1033df31827a35a1af2ee9f1ec2e2e7 (diff) | |
| download | aichat-0ed0ad1fd26cccb9f41379e2f0f2c77fca43c608.tar.gz | |
chore: optimize readline multiline
Diffstat (limited to 'src')
| -rw-r--r-- | src/repl/init.rs | 10 | ||||
| -rw-r--r-- | src/repl/mod.rs | 1 | ||||
| -rw-r--r-- | src/repl/validator.rs | 59 |
3 files changed, 66 insertions, 4 deletions
diff --git a/src/repl/init.rs b/src/repl/init.rs index 6914cdc..ae337ee 100644 --- a/src/repl/init.rs +++ b/src/repl/init.rs @@ -1,11 +1,13 @@ -use super::{highlighter::ReplHighlighter, prompt::ReplPrompt, REPL_COMMANDS}; +use super::{ + highlighter::ReplHighlighter, prompt::ReplPrompt, validator::ReplValidator, REPL_COMMANDS, +}; use crate::config::{Config, SharedConfig}; use anyhow::{Context, Result}; use reedline::{ - default_emacs_keybindings, ColumnarMenu, DefaultCompleter, DefaultValidator, Emacs, - FileBackedHistory, KeyCode, KeyModifiers, Keybindings, Reedline, ReedlineEvent, ReedlineMenu, + default_emacs_keybindings, ColumnarMenu, DefaultCompleter, Emacs, FileBackedHistory, KeyCode, + KeyModifiers, Keybindings, Reedline, ReedlineEvent, ReedlineMenu, }; const MENU_NAME: &str = "completion_menu"; @@ -36,7 +38,7 @@ impl Repl { .with_edit_mode(edit_mode) .with_quick_completions(true) .with_partial_completions(true) - .with_validator(Box::new(DefaultValidator)) + .with_validator(Box::new(ReplValidator)) .with_ansi_colors(true); let prompt = ReplPrompt::new(config); Ok(Self { editor, prompt }) diff --git a/src/repl/mod.rs b/src/repl/mod.rs index f44a5bf..337afb3 100644 --- a/src/repl/mod.rs +++ b/src/repl/mod.rs @@ -3,6 +3,7 @@ mod handler; mod highlighter; mod init; mod prompt; +mod validator; pub use self::abort::*; pub use self::handler::*; diff --git a/src/repl/validator.rs b/src/repl/validator.rs new file mode 100644 index 0000000..e1f6e99 --- /dev/null +++ b/src/repl/validator.rs @@ -0,0 +1,59 @@ +use reedline::{ValidationResult, Validator}; + +/// A default validator which checks for mismatched quotes and brackets +pub struct ReplValidator; + +impl Validator for ReplValidator { + fn validate(&self, line: &str) -> ValidationResult { + if incomplete_brackets(line) { + ValidationResult::Incomplete + } else { + ValidationResult::Complete + } + } +} + +fn incomplete_brackets(line: &str) -> bool { + let mut balance: Vec<char> = Vec::new(); + let mut symbol = None; + for c in line.chars() { + match symbol { + Some(s) => match (s, c) { + ('{', '}') | ('(', ')') => { + balance.pop(); + } + _ if s == c => { + balance.push(c); + } + _ => {} + }, + None => match c { + '{' | '(' => { + balance.push(c); + symbol = Some(c) + } + _ => {} + }, + } + } + + !balance.is_empty() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_incomplete_brackets() { + assert!(incomplete_brackets("{")); + assert!(incomplete_brackets("(")); + assert!(!incomplete_brackets("{}")); + assert!(!incomplete_brackets("()")); + assert!(!incomplete_brackets("{ab\nc}")); + assert!(!incomplete_brackets("(ab\nc)")); + assert!(!incomplete_brackets("{[}")); + assert!(!incomplete_brackets("{{{{{}}}}}")); + assert!(incomplete_brackets("{{}")); + } +} |
