Skip to content

Commit ee8ba3f

Browse files
author
Noam Lewis
committed
chunk WIP
1 parent e9516eb commit ee8ba3f

File tree

1 file changed

+139
-4
lines changed

1 file changed

+139
-4
lines changed

src/main.rs

Lines changed: 139 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ mod lines {
2323
pub fn empty() -> LoadedLine {
2424
LoadedLine { chars: vec![] }
2525
}
26-
pub fn new(chars: Vec<char>) -> LoadedLine {
27-
LoadedLine { chars }
26+
pub fn new(chars: &[char]) -> LoadedLine {
27+
LoadedLine {
28+
chars: Vec::from(chars),
29+
}
30+
}
31+
pub fn from_vec(chars: Vec<char>) -> LoadedLine {
32+
LoadedLine { chars: chars }
2833
}
2934
pub fn len(&self) -> usize {
3035
self.chars.len()
@@ -56,6 +61,136 @@ mod lines {
5661
}
5762
}
5863

64+
mod chunks {
65+
66+
use std::slice::{RSplit, Split};
67+
68+
use crate::lines::LoadedLine;
69+
70+
pub struct Chunk<'a> {
71+
file_offset: u64,
72+
is_modified: bool,
73+
data: &'a [char],
74+
}
75+
76+
impl Chunk<'_> {
77+
pub fn from_disk(file_offset: u64, data: &[char]) -> Chunk {
78+
Chunk {
79+
file_offset,
80+
is_modified: false,
81+
data,
82+
}
83+
}
84+
85+
pub fn lines_iter(&self) -> ChunkLinesIter {
86+
ChunkLinesIter {
87+
chunk: self,
88+
forward: self.data.split(Box::new(|c: &char| *c == '\n')),
89+
back: self.data.rsplit(Box::new(|c: &char| *c == '\n')),
90+
}
91+
}
92+
}
93+
94+
pub struct ChunkLinesIter<'a> {
95+
chunk: &'a Chunk<'a>,
96+
forward: Split<'a, char, Box<dyn FnMut(&char) -> bool>>,
97+
back: RSplit<'a, char, Box<dyn FnMut(&char) -> bool>>,
98+
}
99+
100+
impl<'a> Iterator for ChunkLinesIter<'a> {
101+
type Item = LoadedLine;
102+
103+
fn next(&mut self) -> Option<Self::Item> {
104+
let line = self.forward.next();
105+
return line.map(LoadedLine::new);
106+
}
107+
}
108+
109+
impl<'a> DoubleEndedIterator for ChunkLinesIter<'a> {
110+
fn next_back(&mut self) -> Option<Self::Item> {
111+
let line = self.back.next();
112+
return line.map(LoadedLine::new);
113+
}
114+
}
115+
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
120+
use chunks::Chunk;
121+
122+
#[test]
123+
fn test_chunk_lines_iter() {
124+
let data: Vec<char> = "line1\nline2\nline3\n".chars().collect();
125+
let chunk = Chunk::from_disk(0, &data);
126+
let mut iter = chunk.lines_iter();
127+
128+
assert_eq!(
129+
iter.next().unwrap().chars_iter().collect::<String>(),
130+
"line1"
131+
);
132+
assert_eq!(
133+
iter.next().unwrap().chars_iter().collect::<String>(),
134+
"line2"
135+
);
136+
assert_eq!(
137+
iter.next().unwrap().chars_iter().collect::<String>(),
138+
"line3"
139+
);
140+
141+
assert_eq!(iter.next().unwrap().chars_iter().collect::<String>(), "");
142+
assert!(iter.next().is_none());
143+
}
144+
145+
#[test]
146+
fn test_chunk_lines_iter_empty() {
147+
let data: Vec<char> = "".chars().collect();
148+
let chunk = Chunk::from_disk(0, &data);
149+
let mut iter = chunk.lines_iter();
150+
151+
assert_eq!(iter.next().unwrap().chars_iter().collect::<String>(), "");
152+
assert!(iter.next().is_none());
153+
}
154+
155+
#[test]
156+
fn test_chunk_lines_iter_no_newline() {
157+
let data: Vec<char> = "line1".chars().collect();
158+
let chunk = Chunk::from_disk(0, &data);
159+
let mut iter = chunk.lines_iter();
160+
161+
assert_eq!(
162+
iter.next().unwrap().chars_iter().collect::<String>(),
163+
"line1"
164+
);
165+
assert!(iter.next().is_none());
166+
}
167+
168+
#[test]
169+
fn test_chunk_lines_iter_double_ended() {
170+
let data: Vec<char> = "line1\nline2\nline3\n".chars().collect();
171+
let chunk = Chunk::from_disk(0, &data);
172+
let mut iter = chunk.lines_iter();
173+
174+
assert_eq!(
175+
iter.next_back().unwrap().chars_iter().collect::<String>(),
176+
""
177+
);
178+
assert_eq!(
179+
iter.next_back().unwrap().chars_iter().collect::<String>(),
180+
"line3"
181+
);
182+
assert_eq!(
183+
iter.next_back().unwrap().chars_iter().collect::<String>(),
184+
"line2"
185+
);
186+
assert_eq!(
187+
iter.next_back().unwrap().chars_iter().collect::<String>(),
188+
"line1"
189+
);
190+
assert!(iter.next_back().is_none());
191+
}
192+
}
193+
59194
use lines::LoadedLine;
60195

61196
// TODO
@@ -65,7 +200,7 @@ use lines::LoadedLine;
65200
//
66201
// Other editors:
67202
// - emacs: gap buffer
68-
// - vim: rope
203+
// - vim: rope (https://github.com/vim/vim/blob/master/src/memline.c and https://github.com/vim/vim/blob/master/src/memfile.c)
69204
//
70205
// Idea:
71206
// List of contiguous chunks: (disk_offset, data, is_modified).
@@ -340,7 +475,7 @@ impl State {
340475
self.cursor.y += 1;
341476
self.cursor.x = 0;
342477
self.lines
343-
.insert(self.cursor.y as usize, LoadedLine::new(new_line));
478+
.insert(self.cursor.y as usize, LoadedLine::from_vec(new_line));
344479
}
345480

346481
fn draw_frame(&self, frame: &mut Frame) {

0 commit comments

Comments
 (0)