aboutsummaryrefslogtreecommitdiffstats
path: root/src/linebuf.rs
blob: 548ec7514cc0954dfb21a1b1583872637f3dd0eb (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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::cursor::*;
use std::io::Write;

pub struct LineBuf {
    pre: Vec<u8>,
    post: Vec<u8>,
    dirty: bool,
}

impl Default for LineBuf {
    fn default() -> Self {
        Self::new()
    }
}

#[allow(unused)]
impl LineBuf {
    pub fn new() -> Self {
        Self {
            pre: Vec::new(),
            post: Vec::new(),
            dirty: false,
        }
    }

    pub fn del_left(&mut self) -> Option<u8> {
        self.dirty = true;
        self.pre.pop()
    }

    pub fn del_right(&mut self) -> Option<u8> {
        self.dirty = true;
        self.post.pop()
    }

    pub fn len(&self) -> usize {
        self.pre.len() + self.post.len()
    }

    pub fn left(&mut self) -> bool {
        if let Some(byte) = self.del_left() {
            self.post.push(byte);
            true
        } else {
            false
        }
    }

    pub fn right(&mut self) -> bool {
        if let Some(byte) = self.del_right() {
            self.pre.push(byte);
            true
        } else {
            false
        }
    }

    pub fn all_left(&mut self) -> usize {
        let n = self.pre.len();
        while self.left() {}
        n
    }

    pub fn all_right(&mut self) -> usize {
        let n = self.post.len();
        while self.right() {}
        n
    }

    pub fn get_left(&self) -> Option<u8>{
        self.pre.last().cloned()
    }

    pub fn get_right(&self) -> Option<u8>{
        self.post.last().cloned()
    }

    pub fn add(&mut self, chr: u8) {
        self.dirty = true;
        self.pre.push(chr);
    }

    pub fn is_empty(&self) -> bool {
        self.pre.is_empty() && self.post.is_empty()
    }

    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    /// sets content all to the left
    pub fn set_content(&mut self, buf: Vec<u8>) {
        self.pre = buf;
        self.post = Vec::new();
    }

    pub fn pre(&self) -> &[u8] {
        &self.pre
    }

    pub fn into_bytes(&self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(self.pre.len() + self.post.len());
        buf.extend_from_slice(&self.pre);
        for b in self.post.iter().rev() {
            buf.push(*b);
        }
        buf
    }

    pub fn distance_from_right_end(&self) -> usize {
        self.post.len()
    }

    /// returns the whole contents of the buffer, and empties it in the process
    pub fn dump(&mut self) -> Vec<u8> {
        while self.right() {}
        let mut buf = Vec::new();
        core::mem::swap(&mut self.pre, &mut buf);
        self.dirty = false;
        buf
    }

    pub fn clear(&mut self) {
        self.pre.clear();
        self.post.clear();
        self.dirty = false;
    }

    pub fn display_pre(&self) {
        std::io::stdout().write_all(&self.pre).unwrap();
    }

    /// TODO: kinda ugly that this is here
    pub fn display_post(&self, post: &[u8]) {
        for &x in self.post.iter().rev() {
            std::io::stdout().write_all(&[x]).unwrap();
        }
        std::io::stdout().write_all(post).unwrap();
        move_cursor(Direction::Left, self.post.len() + post.len());
        std::io::stdout().flush().unwrap();
    }
}