@@ -218,6 +218,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
218218 ! value ||
219219 caret_position != value . length ||
220220 value . endsWith ( ' ' ) ||
221+ value . endsWith ( '\n' ) ||
221222 ! props . context_file_paths
222223 ) {
223224 return false
@@ -226,7 +227,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
226227 // Check if cursor is at the end of a shortened filename
227228 const text_before_cursor = value . substring ( 0 , caret_position )
228229 const filename_match = text_before_cursor . match (
229- / ( [ ^ \s , ; : . ! ? ` ] + \. [ ^ \s , ; : . ! ? ` ] + ) $ /
230+ / ( [ ^ \s , ; : . ! ? ` ] * \. [ ^ \s , ; : . ! ? ` ] + ) $ /
230231 )
231232
232233 if ( filename_match ) {
@@ -385,7 +386,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
385386 if ( cursor_pos > 0 ) {
386387 const text_before = display_value . substring ( 0 , cursor_pos )
387388 const filename_match = text_before . match (
388- / ( [ ^ \s , ; : . ! ? ` ] + \. [ ^ \s , ; : . ! ? ` ] + ) $ /
389+ / ( [ ^ \s , ; : . ! ? ` ] * \. [ ^ \s , ; : . ! ? ` ] + ) $ /
389390 )
390391
391392 if ( filename_match ) {
@@ -407,6 +408,75 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
407408 handle_key_down ( e )
408409 }
409410
411+ const handle_input_click = ( e : React . MouseEvent < HTMLDivElement > ) => {
412+ const target = e . target as HTMLElement
413+ if ( target . classList . contains ( styles [ 'file-keyword' ] ) ) {
414+ e . preventDefault ( )
415+ e . stopPropagation ( )
416+
417+ const input_element = input_ref . current
418+ if ( ! input_element ) return
419+
420+ const display_pos = get_caret_position_from_div ( input_element )
421+ const raw_pos = map_display_pos_to_raw_pos (
422+ display_pos ,
423+ props . value ,
424+ props . context_file_paths ?? [ ]
425+ )
426+
427+ let start_of_path = - 1
428+ let end_of_path = - 1
429+
430+ if ( props . value [ raw_pos ] === '`' ) {
431+ // case: raw_pos at start
432+ start_of_path = raw_pos
433+ end_of_path = props . value . indexOf ( '`' , start_of_path + 1 )
434+ } else if ( raw_pos > 0 && props . value [ raw_pos - 1 ] === '`' ) {
435+ // case: raw_pos at end
436+ end_of_path = raw_pos - 1
437+ const text_before = props . value . substring ( 0 , end_of_path )
438+ start_of_path = text_before . lastIndexOf ( '`' )
439+ }
440+
441+ if (
442+ start_of_path !== - 1 &&
443+ end_of_path !== - 1 &&
444+ start_of_path < end_of_path
445+ ) {
446+ const path_in_backticks = props . value . substring (
447+ start_of_path + 1 ,
448+ end_of_path
449+ )
450+ if ( props . context_file_paths ?. includes ( path_in_backticks ) ) {
451+ let leading_part = props . value . substring ( 0 , start_of_path )
452+ let trailing_part = props . value . substring ( end_of_path + 1 )
453+
454+ // Handle spacing.
455+ if ( leading_part . endsWith ( ' ' ) ) {
456+ leading_part = leading_part . slice ( 0 , - 1 )
457+ } else if ( trailing_part . startsWith ( ' ' ) ) {
458+ trailing_part = trailing_part . substring ( 1 )
459+ }
460+
461+ const new_value = leading_part + trailing_part
462+ const new_raw_cursor_pos = leading_part . length
463+ props . on_change ( new_value )
464+
465+ setTimeout ( ( ) => {
466+ if ( input_ref . current ) {
467+ const display_pos = map_raw_pos_to_display_pos (
468+ new_raw_cursor_pos ,
469+ new_value ,
470+ props . context_file_paths ?? [ ]
471+ )
472+ set_caret_position_for_div ( input_ref . current , display_pos )
473+ }
474+ } , 0 )
475+ }
476+ }
477+ }
478+ }
479+
410480 return (
411481 < div className = { styles . container } >
412482 { props . has_active_selection && props . is_in_code_completions_mode && (
@@ -459,6 +529,7 @@ export const ChatInput: React.FC<ChatInputProps> = (props) => {
459529 suppressContentEditableWarning = { true }
460530 onInput = { handle_input_change }
461531 onKeyDown = { custom_handle_key_down }
532+ onClick = { handle_input_click }
462533 autoFocus
463534 className = { cn ( styles . input , {
464535 [ styles [ 'input-with-tab-hint' ] ] : show_tab_hint
0 commit comments