@@ -889,6 +889,9 @@ pub struct App {
889889 /// File injection warning dialog.
890890 /// Shown when oversized or binary files are detected in @refs.
891891 pub file_injection_dialog : crate :: file_injection_dialog:: FileInjectionDialogState ,
892+ /// When true, the next file injection size check uses limit 0 (no limit),
893+ /// letting files that were "allowed" through the warning dialog be injected.
894+ pub file_injection_force : bool ,
892895 /// First-launch onboarding welcome dialog.
893896 pub onboarding_dialog : crate :: onboarding_dialog:: OnboardingDialogState ,
894897 /// Effort-level picker (/effort with no args).
@@ -1340,6 +1343,7 @@ impl App {
13401343 bypass_permissions_dialog : crate :: bypass_permissions_dialog:: BypassPermissionsDialogState :: new ( ) ,
13411344 bypass_permissions_dialog_shown : false ,
13421345 file_injection_dialog : crate :: file_injection_dialog:: FileInjectionDialogState :: new ( ) ,
1346+ file_injection_force : false ,
13431347 onboarding_dialog : crate :: onboarding_dialog:: OnboardingDialogState :: new ( ) ,
13441348 effort_picker : crate :: effort_picker:: EffortPickerState :: new ( ) ,
13451349 key_input_dialog : crate :: key_input_dialog:: KeyInputDialogState :: new ( ) ,
@@ -2647,9 +2651,16 @@ impl App {
26472651 self . history_index = self . prompt_input . history_pos ;
26482652 }
26492653
2650- fn refresh_prompt_input ( & mut self ) {
2654+ pub fn refresh_prompt_input ( & mut self ) {
26512655 self . prompt_input . mode = self . prompt_mode ( ) ;
2652- self . prompt_input . update_suggestions ( PROMPT_SLASH_COMMANDS ) ;
2656+ if self . file_injection_dialog . visible {
2657+ // Don't update suggestions while the injection dialog is open.
2658+ self . sync_legacy_prompt_fields ( ) ;
2659+ return ;
2660+ }
2661+ let file_autocomplete_limit = self . config . file_autocomplete_limit ;
2662+ let file_autocomplete_show_hidden = self . config . file_autocomplete_show_hidden_files ;
2663+ self . prompt_input . update_suggestions ( PROMPT_SLASH_COMMANDS , file_autocomplete_limit, file_autocomplete_show_hidden) ;
26532664 self . sync_legacy_prompt_fields ( ) ;
26542665 }
26552666
@@ -2882,25 +2893,27 @@ impl App {
28822893
28832894 // File injection dialog: shown when oversized files are detected in @refs.
28842895 if self . file_injection_dialog . visible {
2896+ let is_directory_only = self . file_injection_dialog . is_directory_only ( ) ;
28852897 match key. code {
2886- KeyCode :: Char ( 'i' ) | KeyCode :: Char ( 'I' ) => {
2887- self . file_injection_dialog . selected = 0 ; // InjectAll
2888- }
2889- KeyCode :: Char ( 's' ) | KeyCode :: Char ( 'S' ) => {
2890- self . file_injection_dialog . selected = 1 ; // SkipOversized
2898+ KeyCode :: Enter => {
2899+ if is_directory_only {
2900+ // Directories can't be injected; Enter = abort, restore input.
2901+ if let Some ( input) = self . file_injection_dialog . pending_input . clone ( ) {
2902+ self . set_prompt_text ( input) ;
2903+ }
2904+ self . file_injection_dialog . dismiss ( ) ;
2905+ } else {
2906+ // Enter = inject (Allow).
2907+ self . file_injection_dialog . selected = 0 ;
2908+ self . file_injection_dialog . confirm ( ) ;
2909+ }
28912910 }
28922911 KeyCode :: Esc => {
2893- self . file_injection_dialog . selected = 2 ; // Abort
2894- self . file_injection_dialog . confirm ( ) ;
2895- // Restore input to prompt when aborting
2896- if let Some ( input) = & self . file_injection_dialog . pending_input {
2897- self . set_prompt_text ( input. clone ( ) ) ;
2912+ // Esc = abort, restore input.
2913+ if let Some ( input) = self . file_injection_dialog . pending_input . clone ( ) {
2914+ self . set_prompt_text ( input) ;
28982915 }
2899- }
2900- KeyCode :: Up | KeyCode :: Char ( 'k' ) => self . file_injection_dialog . select_prev ( ) ,
2901- KeyCode :: Down | KeyCode :: Char ( 'j' ) => self . file_injection_dialog . select_next ( ) ,
2902- KeyCode :: Enter => {
2903- self . file_injection_dialog . confirm ( ) ;
2916+ self . file_injection_dialog . dismiss ( ) ;
29042917 }
29052918 _ => { }
29062919 }
@@ -4171,12 +4184,17 @@ impl App {
41714184 self . refresh_prompt_input ( ) ;
41724185 }
41734186 KeyCode :: Enter if !self . is_streaming => {
4174- // If a slash-command suggestion is selected, accept it instead of submitting.
4187+ // If a suggestion is selected, accept it instead of submitting.
41754188 if !self . prompt_input . suggestions . is_empty ( )
41764189 && self . prompt_input . suggestion_index . is_some ( )
4177- && self . prompt_input . text . starts_with ( '/' )
41784190 {
4191+ let is_file_ref = self . prompt_input . suggestions
4192+ . get ( self . prompt_input . suggestion_index . unwrap ( ) )
4193+ . map_or ( false , |s| s. source == crate :: prompt_input:: TypeaheadSource :: FileRef ) ;
41794194 self . prompt_input . accept_suggestion ( ) ;
4195+ if is_file_ref {
4196+ self . prompt_input . insert_char ( ' ' ) ;
4197+ }
41804198 self . refresh_prompt_input ( ) ;
41814199 return false ;
41824200 }
@@ -4209,7 +4227,7 @@ impl App {
42094227 // when the cursor is already on the first/last visual row
42104228 // (issue #149 follow-up).
42114229 KeyCode :: Up => {
4212- if !self . prompt_input . suggestions . is_empty ( ) && self . prompt_input . text . starts_with ( '/' ) {
4230+ if !self . prompt_input . suggestions . is_empty ( ) && ( self . prompt_input . text . starts_with ( '/' ) || self . prompt_input . has_active_file_ref ( ) ) {
42134231 self . prompt_input . suggestion_prev ( ) ;
42144232 } else {
42154233 let area = self . last_input_area . get ( ) ;
@@ -4223,7 +4241,7 @@ impl App {
42234241 self . refresh_prompt_input ( ) ;
42244242 }
42254243 KeyCode :: Down => {
4226- if !self . prompt_input . suggestions . is_empty ( ) && self . prompt_input . text . starts_with ( '/' ) {
4244+ if !self . prompt_input . suggestions . is_empty ( ) && ( self . prompt_input . text . starts_with ( '/' ) || self . prompt_input . has_active_file_ref ( ) ) {
42274245 self . prompt_input . suggestion_next ( ) ;
42284246 } else {
42294247 let area = self . last_input_area . get ( ) ;
@@ -4673,29 +4691,53 @@ impl App {
46734691 self . refresh_global_search ( ) ;
46744692 false
46754693 }
4676- "submit" => !self . is_streaming ,
4694+ "submit" => {
4695+ if !self . is_streaming {
4696+ if !self . prompt_input . suggestions . is_empty ( )
4697+ && self . prompt_input . suggestion_index . is_some ( )
4698+ {
4699+ self . prompt_input . accept_suggestion ( ) ;
4700+ self . refresh_prompt_input ( ) ;
4701+ false
4702+ } else {
4703+ true
4704+ }
4705+ } else {
4706+ false
4707+ }
4708+ }
46774709 "historyPrev" => {
4678- // Slash-command suggestions take priority over history.
4710+ // Suggestions (slash commands or file refs) take priority over cursor/ history.
46794711 if !self . prompt_input . suggestions . is_empty ( )
4680- && self . prompt_input . text . starts_with ( '/' )
4712+ && ( self . prompt_input . text . starts_with ( '/' ) || self . prompt_input . has_active_file_ref ( ) )
46814713 {
46824714 self . prompt_input . suggestion_prev ( ) ;
46834715 self . refresh_prompt_input ( ) ;
4684- } else if !self . prompt_input . history . is_empty ( ) {
4685- self . prompt_input . history_up ( ) ;
4716+ } else {
4717+ let width = self . last_input_area . get ( ) . width . saturating_sub ( 4 ) as usize ;
4718+ let moved = !self . prompt_input . text . is_empty ( )
4719+ && self . prompt_input . move_visual_up ( width) ;
4720+ if !moved && !self . prompt_input . history . is_empty ( ) {
4721+ self . prompt_input . history_up ( ) ;
4722+ }
46864723 self . refresh_prompt_input ( ) ;
46874724 }
46884725 false
46894726 }
46904727 "historyNext" => {
4691- // Slash-command suggestions take priority over history.
4728+ // Suggestions (slash commands or file refs) take priority over cursor/ history.
46924729 if !self . prompt_input . suggestions . is_empty ( )
4693- && self . prompt_input . text . starts_with ( '/' )
4730+ && ( self . prompt_input . text . starts_with ( '/' ) || self . prompt_input . has_active_file_ref ( ) )
46944731 {
46954732 self . prompt_input . suggestion_next ( ) ;
46964733 self . refresh_prompt_input ( ) ;
4697- } else if self . prompt_input . history_pos . is_some ( ) {
4698- self . prompt_input . history_down ( ) ;
4734+ } else {
4735+ let width = self . last_input_area . get ( ) . width . saturating_sub ( 4 ) as usize ;
4736+ let moved = !self . prompt_input . text . is_empty ( )
4737+ && self . prompt_input . move_visual_down ( width) ;
4738+ if !moved && self . prompt_input . history_pos . is_some ( ) {
4739+ self . prompt_input . history_down ( ) ;
4740+ }
46994741 self . refresh_prompt_input ( ) ;
47004742 }
47014743 false
0 commit comments