@@ -11,6 +11,7 @@ use crate::{
1111
1212use ratatui:: {
1313 layout:: Rect ,
14+ style:: { Color , Style } ,
1415 widgets:: { Block , Clear , Paragraph } ,
1516 Frame ,
1617} ;
@@ -19,27 +20,44 @@ use anyhow::Result;
1920
2021use crossterm:: event:: { Event , KeyCode } ;
2122
23+ #[ derive( Debug ) ]
24+ pub struct GotoLineContext {
25+ pub max_line : usize ,
26+ }
27+
28+ #[ derive( Debug ) ]
29+ pub struct GotoLineOpen {
30+ pub context : GotoLineContext ,
31+ }
32+
2233pub struct GotoLinePopup {
2334 visible : bool ,
24- line : String ,
35+ input : String ,
36+ line_number : usize ,
2537 key_config : SharedKeyConfig ,
2638 queue : Queue ,
2739 theme : SharedTheme ,
40+ invalid_input : bool ,
41+ context : GotoLineContext ,
2842}
2943
3044impl GotoLinePopup {
3145 pub fn new ( env : & Environment ) -> Self {
3246 Self {
3347 visible : false ,
34- line : String :: new ( ) ,
48+ input : String :: new ( ) ,
3549 key_config : env. key_config . clone ( ) ,
3650 queue : env. queue . clone ( ) ,
3751 theme : env. theme . clone ( ) ,
52+ invalid_input : false ,
53+ context : GotoLineContext { max_line : 0 } ,
54+ line_number : 0 ,
3855 }
3956 }
4057
41- pub fn open ( & mut self ) {
58+ pub fn open ( & mut self , open : GotoLineOpen ) {
4259 self . visible = true ;
60+ self . context = open. context ;
4361 }
4462}
4563
@@ -63,41 +81,67 @@ impl Component for GotoLinePopup {
6381 if let Event :: Key ( key) = event {
6482 if key_match ( key, self . key_config . keys . exit_popup ) {
6583 self . visible = false ;
66- self . line . clear ( ) ;
84+ self . input . clear ( ) ;
6785 self . queue . push ( InternalEvent :: PopupStackPop ) ;
6886 } else if let KeyCode :: Char ( c) = key. code {
69- if c. is_ascii_digit ( ) {
70- // I'd assume it's unusual for people to blame
71- // files with milions of lines
72- if self . line . len ( ) < 6 {
73- self . line . push ( c) ;
74- }
87+ if c. is_ascii_digit ( ) || c == '-' {
88+ self . input . push ( c) ;
7589 }
7690 } else if key. code == KeyCode :: Backspace {
77- self . line . pop ( ) ;
91+ self . input . pop ( ) ;
7892 } else if key_match ( key, self . key_config . keys . enter ) {
7993 self . visible = false ;
80- if !self . line . is_empty ( ) {
94+ if self . invalid_input {
95+ self . queue . push ( InternalEvent :: ShowErrorMsg (
96+ format ! ( "Invalid input: only numbers between -{0} and {0} (included) are allowed" , self . context. max_line) )
97+ ,
98+ ) ;
99+ } else if !self . input . is_empty ( ) {
81100 self . queue . push ( InternalEvent :: GotoLine (
82- self . line . parse :: < usize > ( ) ? ,
101+ self . line_number ,
83102 ) ) ;
84103 }
85104 self . queue . push ( InternalEvent :: PopupStackPop ) ;
86- self . line . clear ( ) ;
105+ self . input . clear ( ) ;
106+ self . invalid_input = false ;
107+ }
108+ }
109+ match self . input . parse :: < isize > ( ) {
110+ Ok ( input) => {
111+ if input. unsigned_abs ( ) > self . context . max_line {
112+ self . invalid_input = true ;
113+ } else {
114+ self . invalid_input = false ;
115+ self . line_number = if input > 0 {
116+ input. unsigned_abs ( )
117+ } else {
118+ self . context . max_line
119+ - input. unsigned_abs ( )
120+ }
121+ }
122+ }
123+ Err ( _) => {
124+ if !self . input . is_empty ( ) {
125+ self . invalid_input = true ;
126+ }
87127 }
88- return Ok ( EventState :: Consumed ) ;
89128 }
129+ return Ok ( EventState :: Consumed ) ;
90130 }
91-
92131 Ok ( EventState :: NotConsumed )
93132 }
94133}
95134
96135impl DrawableComponent for GotoLinePopup {
97136 fn draw ( & self , f : & mut Frame , area : Rect ) -> Result < ( ) > {
98137 if self . is_visible ( ) {
99- let input = Paragraph :: new ( self . line . as_str ( ) )
100- . style ( self . theme . text ( true , false ) )
138+ let style = if self . invalid_input {
139+ Style :: default ( ) . fg ( Color :: Red )
140+ } else {
141+ self . theme . text ( true , false )
142+ } ;
143+ let input = Paragraph :: new ( self . input . as_str ( ) )
144+ . style ( style)
101145 . block ( Block :: bordered ( ) . title ( "Go to Line" ) ) ;
102146
103147 let input_area = ui:: centered_rect_absolute ( 15 , 3 , area) ;
0 commit comments