@@ -6,6 +6,7 @@ use std::{
66 iter:: FromIterator ,
77} ;
88
9+ use crate :: lines:: LoadedLine ;
910use crossterm:: event:: { self , Event , KeyCode , KeyEvent , KeyModifiers } ;
1011use ratatui:: {
1112 layout:: { Position , Rect , Size } ,
@@ -14,184 +15,8 @@ use ratatui::{
1415 DefaultTerminal , Frame ,
1516} ;
1617
17- mod lines {
18- pub struct LoadedLine {
19- chars : Vec < char > ,
20- }
21-
22- impl LoadedLine {
23- pub fn empty ( ) -> LoadedLine {
24- LoadedLine { chars : vec ! [ ] }
25- }
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 }
33- }
34- pub fn len ( & self ) -> usize {
35- self . chars . len ( )
36- }
37- pub fn push ( & mut self , c : char ) {
38- self . chars . push ( c) ;
39- }
40- pub fn insert ( & mut self , index : usize , c : char ) {
41- self . chars . insert ( index, c) ;
42- }
43- pub fn remove ( & mut self , index : usize ) {
44- self . chars . remove ( index) ;
45- }
46- pub fn extend ( & mut self , line : LoadedLine ) {
47- self . chars . extend ( line. chars ) ;
48- }
49- pub fn char_get_mut ( & mut self , index : usize ) -> Option < & mut char > {
50- self . chars . get_mut ( index)
51- }
52- pub fn char_get ( & self , index : usize ) -> Option < & char > {
53- self . chars . get ( index)
54- }
55- pub fn split_off ( & mut self , x : usize ) -> Vec < char > {
56- self . chars . split_off ( x)
57- }
58- pub fn chars_iter ( & self ) -> std:: slice:: Iter < ' _ , char > {
59- self . chars . iter ( )
60- }
61- }
62- }
63-
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\n line2\n line3\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\n line2\n line3\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-
194- use lines:: LoadedLine ;
18+ pub mod chunks;
19+ pub mod lines;
19520
19621// TODO
19722// How to represent edited content?
0 commit comments