summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2023-03-12 07:54:18 +0800
committersigoden <sigoden@gmail.com>2023-03-12 07:54:18 +0800
commit0ed0ad1fd26cccb9f41379e2f0f2c77fca43c608 (patch)
treef0e44c0fd0d62c7a8ddb3ffe77f8e5687d855b5d
parent4aab872ee1033df31827a35a1af2ee9f1ec2e2e7 (diff)
downloadaichat-0ed0ad1fd26cccb9f41379e2f0f2c77fca43c608.tar.gz
chore: optimize readline multiline
-rw-r--r--src/repl/init.rs10
-rw-r--r--src/repl/mod.rs1
-rw-r--r--src/repl/validator.rs59
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("{{}"));
+ }
+}