aboutsummaryrefslogtreecommitdiff
path: root/rust/src/editor.rs
blob: 6284570c323c29caeed330c95f5386ad151d8c29 (plain)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use termion::event::Key;
use crate::bel;

#[derive(Debug, Default)]
pub struct Editor {
    s: String,
    left: usize,
    cursor: usize,
    wid: usize,
}

impl Editor {
    pub fn keypress(&mut self, key: Key) -> Option<String> {
        let mut ret = None;

        match key {
            Key::Char('\n') => {
                ret = Some(String::new());
                std::mem::swap(ret.as_mut().unwrap(), &mut self.s);
                self.cursor = 0;
            }

            Key::Char(c) if !c.is_control() => {
                self.s.insert(self.cursor, c);
                self.cursor += 1;
            }

            Key::Backspace if self.cursor > 0 => {
                self.cursor -= 1;
                self.s.remove(self.cursor);
            }

            Key::Delete if self.s.len() > self.cursor => {
                self.s.remove(self.cursor);
            }

            Key::Home | Key::Ctrl('a') => {
                self.cursor = 0;
            }

            Key::End | Key::Ctrl('e') => {
                self.cursor = self.s.len();
            }

            Key::Left | Key::Ctrl('b') if self.cursor > 0 => {
                self.cursor -= 1;
            }

            Key::Right | Key::Ctrl('f') if self.cursor < self.s.len() => {
                self.cursor += 1;
            }

            Key::Ctrl('u') => {
                self.s.replace_range(0..self.cursor, "");
                self.cursor = 0;
            }

            _ => {
                bel::bel();
            }
        };

        self.fix_left();
        ret
    }

    pub fn set_wid(&mut self, wid: usize) {
        self.wid = wid;
        self.fix_left();
    }

    pub fn displayed(&self) -> (&str, usize) {
        let endidx = (self.left + self.wid).min(self.s.len());
        (&self.s[self.left .. endidx], self.cursor - self.left)
    }

    fn fix_left(&mut self) {
        self.left = self.left.min(self.cursor).max(self.cursor + 1 - self.wid.min(self.cursor + 1));
    }
}