@@ -17,9 +17,11 @@ import {
1717} from "@/utils/context-mentions"
1818import {
1919 SlashCommand ,
20+ slashCommandDeleteRegex ,
2021 shouldShowSlashCommandsMenu ,
2122 getMatchingSlashCommands ,
2223 insertSlashCommand ,
24+ removeSlashCommand ,
2325 validateSlashCommand ,
2426} from "@/utils/slash-commands"
2527import { useMetaKeyDetection , useShortcut } from "@/utils/hooks"
@@ -253,6 +255,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
253255 const [ selectedMenuIndex , setSelectedMenuIndex ] = useState ( - 1 )
254256 const [ selectedType , setSelectedType ] = useState < ContextMenuOptionType | null > ( null )
255257 const [ justDeletedSpaceAfterMention , setJustDeletedSpaceAfterMention ] = useState ( false )
258+ const [ justDeletedSpaceAfterSlashCommand , setJustDeletedSpaceAfterSlashCommand ] = useState ( false )
256259 const [ intendedCursorPosition , setIntendedCursorPosition ] = useState < number | null > ( null )
257260 const contextMenuContainerRef = useRef < HTMLDivElement > ( null )
258261 const [ showModelSelector , setShowModelSelector ] = useState ( false )
@@ -525,31 +528,59 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
525528 charBeforeCursor === " " || charBeforeCursor === "\n" || charBeforeCursor === "\r\n"
526529 const charAfterIsWhitespace =
527530 charAfterCursor === " " || charAfterCursor === "\n" || charAfterCursor === "\r\n"
528- // checks if char before cursor is whitespace after a mention
531+
532+ // Check if we're right after a space that follows a mention or slash command
529533 if (
530534 charBeforeIsWhitespace &&
531- inputValue . slice ( 0 , cursorPosition - 1 ) . match ( new RegExp ( mentionRegex . source + "$" ) ) // "$" is added to ensure the match occurs at the end of the string
535+ inputValue . slice ( 0 , cursorPosition - 1 ) . match ( new RegExp ( mentionRegex . source + "$" ) )
532536 ) {
537+ // File mention handling
533538 const newCursorPosition = cursorPosition - 1
534- // if mention is followed by another word, then instead of deleting the space separating them we just move the cursor to the end of the mention
535539 if ( ! charAfterIsWhitespace ) {
536540 event . preventDefault ( )
537541 textAreaRef . current ?. setSelectionRange ( newCursorPosition , newCursorPosition )
538542 setCursorPosition ( newCursorPosition )
539543 }
540544 setCursorPosition ( newCursorPosition )
541545 setJustDeletedSpaceAfterMention ( true )
542- } else if ( justDeletedSpaceAfterMention ) {
546+ setJustDeletedSpaceAfterSlashCommand ( false )
547+ } else if ( charBeforeIsWhitespace && inputValue . slice ( 0 , cursorPosition - 1 ) . match ( slashCommandDeleteRegex ) ) {
548+ // New slash command handling
549+ const newCursorPosition = cursorPosition - 1
550+ if ( ! charAfterIsWhitespace ) {
551+ event . preventDefault ( )
552+ textAreaRef . current ?. setSelectionRange ( newCursorPosition , newCursorPosition )
553+ setCursorPosition ( newCursorPosition )
554+ }
555+ setCursorPosition ( newCursorPosition )
556+ setJustDeletedSpaceAfterSlashCommand ( true )
557+ setJustDeletedSpaceAfterMention ( false )
558+ }
559+ // Handle the second backspace press for mentions or slash commands
560+ else if ( justDeletedSpaceAfterMention ) {
543561 const { newText, newPosition } = removeMention ( inputValue , cursorPosition )
544562 if ( newText !== inputValue ) {
545563 event . preventDefault ( )
546564 setInputValue ( newText )
547- setIntendedCursorPosition ( newPosition ) // Store the new cursor position in state
565+ setIntendedCursorPosition ( newPosition )
548566 }
549567 setJustDeletedSpaceAfterMention ( false )
550568 setShowContextMenu ( false )
551- } else {
569+ } else if ( justDeletedSpaceAfterSlashCommand ) {
570+ // New slash command deletion
571+ const { newText, newPosition } = removeSlashCommand ( inputValue , cursorPosition )
572+ if ( newText !== inputValue ) {
573+ event . preventDefault ( )
574+ setInputValue ( newText )
575+ setIntendedCursorPosition ( newPosition )
576+ }
577+ setJustDeletedSpaceAfterSlashCommand ( false )
578+ setShowSlashCommandsMenu ( false )
579+ }
580+ // Default case - reset flags if none of the above apply
581+ else {
552582 setJustDeletedSpaceAfterMention ( false )
583+ setJustDeletedSpaceAfterSlashCommand ( false )
553584 }
554585 }
555586 } ,
@@ -566,6 +597,10 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
566597 justDeletedSpaceAfterMention ,
567598 queryItems ,
568599 fileSearchResults ,
600+ showSlashCommandsMenu ,
601+ selectedSlashCommandsIndex ,
602+ slashCommandsQuery ,
603+ handleSlashCommandsSelect ,
569604 ] ,
570605 )
571606
@@ -792,7 +827,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
792827 if ( isValidCommand ) {
793828 const fullCommand = processedText . substring ( slashIndex , endIndex ) // includes slash
794829
795- const highlighted = `<mark class="slash-command-match -textarea-highlight">${ fullCommand } </mark>`
830+ const highlighted = `<mark class="mention-context -textarea-highlight">${ fullCommand } </mark>`
796831 processedText = processedText . substring ( 0 , slashIndex ) + highlighted + processedText . substring ( endIndex )
797832 }
798833 }
0 commit comments