mirror of
https://github.com/sigoden/aichat
synced 2024-11-18 09:28:27 +00:00
chore: optimize readline multiline
This commit is contained in:
parent
4aab872ee1
commit
0ed0ad1fd2
@ -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 crate::config::{Config, SharedConfig};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use reedline::{
|
use reedline::{
|
||||||
default_emacs_keybindings, ColumnarMenu, DefaultCompleter, DefaultValidator, Emacs,
|
default_emacs_keybindings, ColumnarMenu, DefaultCompleter, Emacs, FileBackedHistory, KeyCode,
|
||||||
FileBackedHistory, KeyCode, KeyModifiers, Keybindings, Reedline, ReedlineEvent, ReedlineMenu,
|
KeyModifiers, Keybindings, Reedline, ReedlineEvent, ReedlineMenu,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MENU_NAME: &str = "completion_menu";
|
const MENU_NAME: &str = "completion_menu";
|
||||||
@ -36,7 +38,7 @@ impl Repl {
|
|||||||
.with_edit_mode(edit_mode)
|
.with_edit_mode(edit_mode)
|
||||||
.with_quick_completions(true)
|
.with_quick_completions(true)
|
||||||
.with_partial_completions(true)
|
.with_partial_completions(true)
|
||||||
.with_validator(Box::new(DefaultValidator))
|
.with_validator(Box::new(ReplValidator))
|
||||||
.with_ansi_colors(true);
|
.with_ansi_colors(true);
|
||||||
let prompt = ReplPrompt::new(config);
|
let prompt = ReplPrompt::new(config);
|
||||||
Ok(Self { editor, prompt })
|
Ok(Self { editor, prompt })
|
||||||
|
@ -3,6 +3,7 @@ mod handler;
|
|||||||
mod highlighter;
|
mod highlighter;
|
||||||
mod init;
|
mod init;
|
||||||
mod prompt;
|
mod prompt;
|
||||||
|
mod validator;
|
||||||
|
|
||||||
pub use self::abort::*;
|
pub use self::abort::*;
|
||||||
pub use self::handler::*;
|
pub use self::handler::*;
|
||||||
|
59
src/repl/validator.rs
Normal file
59
src/repl/validator.rs
Normal file
@ -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("{{}"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user