summaryrefslogtreecommitdiffstats
path: root/src/repl/validator.rs
blob: d829911f55ab7bca938b6193b5e05f43127c53f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use reedline::{ValidationResult, Validator};

/// A default validator which checks for mismatched quotes and brackets
#[allow(clippy::module_name_repetitions)]
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("{{}"));
    }
}