@@ -72,6 +72,7 @@ struct App<'a> {
7272 popup_open : bool ,
7373 candidates : Vec < Candidate > ,
7474 popup_state : ListState ,
75+ autocomplete_enabled : bool ,
7576
7677 chord : Option < char > ,
7778
@@ -132,6 +133,7 @@ impl<'a> App<'a> {
132133 popup_open : false ,
133134 candidates : vec ! [ ] ,
134135 popup_state : ListState :: default ( ) ,
136+ autocomplete_enabled : true ,
135137 chord : None ,
136138 search : None ,
137139 palette : None ,
@@ -197,6 +199,11 @@ impl<'a> App<'a> {
197199 }
198200
199201 fn refresh_completions ( & mut self ) {
202+ if !self . autocomplete_enabled {
203+ self . candidates = vec ! [ ] ;
204+ self . popup_state . select ( None ) ;
205+ return ;
206+ }
200207 let expr = self . expr_text ( ) ;
201208 let cursor_byte = expr_cursor_byte ( & self . expr_area , & expr) ;
202209 let Some ( doc) = & self . parsed_doc else {
@@ -348,7 +355,7 @@ fn draw(frame: &mut Frame, app: &mut App) {
348355
349356fn draw_help_popup ( frame : & mut Frame , size : Rect ) {
350357 let w = 78u16 . min ( size. width . saturating_sub ( 4 ) ) ;
351- let h = 28u16 . min ( size. height . saturating_sub ( 2 ) ) ;
358+ let h = 44u16 . min ( size. height . saturating_sub ( 2 ) ) ;
352359 let x = size. x + ( size. width . saturating_sub ( w) ) / 2 ;
353360 let y = size. y + ( size. height . saturating_sub ( h) ) / 2 ;
354361 let area = Rect { x, y, width : w, height : h } ;
@@ -395,6 +402,7 @@ fn draw_help_popup(frame: &mut Frame, size: Rect) {
395402 row( vec![ key( "C-n" ) , key( "C-p" ) ] , "navigate" ) ,
396403 row( vec![ key( "⏎" ) , key( "Tab" ) ] , "accept" ) ,
397404 row( vec![ key( "C-g" ) , key( "Esc" ) ] , "close" ) ,
405+ row( vec![ key( "M-g i" ) ] , "toggle autocomplete on / off" ) ,
398406 Line :: from( "" ) ,
399407 hd( "Search & commands" ) ,
400408 row( vec![ key( "C-s" ) , key( "C-r" ) ] , "isearch forward / backward (repeat to advance)" ) ,
@@ -1306,6 +1314,24 @@ fn event_loop<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<(
13061314 continue ;
13071315 }
13081316
1317+ // chord resolution: last key was M-g
1318+ if app. chord == Some ( 'g' ) {
1319+ app. chord = None ;
1320+ // C-g cancels chord
1321+ if ctrl && matches ! ( key. code, KeyCode :: Char ( 'g' ) ) { continue ; }
1322+ // M-g i → toggle autocomplete
1323+ if matches ! ( key. code, KeyCode :: Char ( 'i' ) ) {
1324+ app. autocomplete_enabled = !app. autocomplete_enabled ;
1325+ if !app. autocomplete_enabled {
1326+ app. popup_open = false ;
1327+ app. candidates . clear ( ) ;
1328+ app. popup_state . select ( None ) ;
1329+ }
1330+ continue ;
1331+ }
1332+ continue ;
1333+ }
1334+
13091335 // chord resolution: last key was C-x
13101336 if app. chord == Some ( 'x' ) {
13111337 app. chord = None ;
@@ -1332,6 +1358,11 @@ fn event_loop<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<(
13321358 app. chord = Some ( 'x' ) ;
13331359 continue ;
13341360 }
1361+ // M-g begins chord (e.g. M-g i toggles autocomplete)
1362+ if alt && matches ! ( key. code, KeyCode :: Char ( 'g' ) ) {
1363+ app. chord = Some ( 'g' ) ;
1364+ continue ;
1365+ }
13351366
13361367 if matches ! ( key. code, KeyCode :: Esc ) && !app. popup_open {
13371368 return Ok ( ( ) ) ;
@@ -1639,6 +1670,7 @@ const COMMANDS: &[(&str, &str)] = &[
16391670 ( "toggle-regex" , "Toggle regex mode in next search" ) ,
16401671 ( "toggle-word" , "Toggle word (literal) mode in next search" ) ,
16411672 ( "focus-next" , "Cycle pane focus" ) ,
1673+ ( "toggle-autocomplete" , "Enable / disable expr completion popup" ) ,
16421674 ( "quit" , "Exit jetrocli" ) ,
16431675] ;
16441676
@@ -1778,6 +1810,14 @@ fn run_command(app: &mut App, name: &str) -> bool {
17781810 Focus :: Result => Focus :: Json ,
17791811 } ;
17801812 }
1813+ "toggle-autocomplete" => {
1814+ app. autocomplete_enabled = !app. autocomplete_enabled ;
1815+ if !app. autocomplete_enabled {
1816+ app. popup_open = false ;
1817+ app. candidates . clear ( ) ;
1818+ app. popup_state . select ( None ) ;
1819+ }
1820+ }
17811821 "quit" => return true ,
17821822 _ => { }
17831823 }
0 commit comments