@@ -25,6 +25,7 @@ struct State {
2525 status_text : String ,
2626 file : Option < std:: fs:: File > ,
2727 file_offset : u64 ,
28+ window_offset : Position ,
2829}
2930
3031impl State {
@@ -66,10 +67,28 @@ impl State {
6667 terminal : & mut ratatui:: Terminal < ratatui:: prelude:: CrosstermBackend < io:: Stdout > > ,
6768 ) -> Result < ( ) , io:: Error > {
6869 self . status_text = format ! ( "Line {}, Column {}" , self . cursor. y, self . cursor. x) ;
70+
71+ self . scroll_to_cursor ( terminal. get_frame ( ) . area ( ) ) ;
72+
6973 terminal. draw ( |x| self . draw_frame ( x) ) ?;
7074 Ok ( ( ) )
7175 }
7276
77+ fn scroll_to_cursor ( & mut self , window_area : Rect ) {
78+ // bring cursor into view
79+
80+ let text_area = Rect :: new ( 0 , 0 , window_area. width , window_area. height - 1 ) ;
81+ if self . cursor . y > text_area. height - 1 {
82+ if self . cursor . y - ( text_area. height - 1 ) > self . window_offset . y {
83+ self . window_offset . y = self . cursor . y - ( text_area. height - 1 ) ;
84+ }
85+ }
86+ if self . cursor . y < self . window_offset . y {
87+ self . window_offset . y = self . cursor . y ;
88+ }
89+ assert ! ( self . window_offset. y <= self . cursor. y) ;
90+ }
91+
7392 fn handle_event ( & mut self , event : Event ) -> bool {
7493 match event {
7594 Event :: Key ( KeyEvent {
@@ -221,7 +240,6 @@ impl State {
221240 let window_area = frame. area ( ) ;
222241 let text_area = Rect :: new ( 0 , 0 , window_area. width , window_area. height - 1 ) ;
223242 let status_area = Rect :: new ( 0 , window_area. height - 1 , window_area. width , 1 ) ;
224-
225243 let left_margin_width = self . left_margin_width ( ) ;
226244
227245 let render_line = |pair : ( usize , & Vec < char > ) | -> Line < ' _ > {
@@ -242,15 +260,21 @@ impl State {
242260 } ;
243261
244262 frame. render_widget (
245- Text :: from_iter ( self . lines . iter ( ) . enumerate ( ) . map ( render_line) ) ,
263+ Text :: from_iter (
264+ self . lines
265+ . iter ( )
266+ . enumerate ( )
267+ . skip ( self . window_offset . y as usize )
268+ . map ( render_line) ,
269+ ) ,
246270 text_area,
247271 ) ;
248272
249273 frame. render_widget ( self . status_text . clone ( ) , status_area) ;
250274
251275 frame. set_cursor_position ( Position :: new (
252- self . cursor . x + left_margin_width + 1 ,
253- self . cursor . y ,
276+ self . cursor . x + left_margin_width + 1 - self . window_offset . x ,
277+ self . cursor . y - self . window_offset . y ,
254278 ) ) ;
255279 }
256280
@@ -365,6 +389,7 @@ fn main() -> io::Result<()> {
365389 let terminal = ratatui:: init ( ) ;
366390 let mut state: State = State {
367391 lines : vec ! [ vec![ ] ] ,
392+ window_offset : Position :: new ( 0 , 0 ) ,
368393 cursor : Position :: new ( 0 , 0 ) ,
369394 insert_mode : true ,
370395 status_text : String :: new ( ) ,
0 commit comments