@@ -188,7 +188,7 @@ export const PromptInput = React.memo(function PromptInput({
188188 const showMenu = slashMenu . length > 0 ;
189189 const promptHistoryKey = React . useMemo ( ( ) => promptHistory . join ( "\0" ) , [ promptHistory ] ) ;
190190 const hasRunningProcess = runningProcesses && runningProcesses . size > 0 ;
191- const hasCollapsedMarkers = hasActivePasteMarkers ( buffer . text ) ;
191+ const hasCollapsedMarkers = hasActivePasteMarkers ( buffer . text , pastesRef . current ) ;
192192 const hasExpandedRegions = expandedRegionsRef . current . size > 0 ;
193193 const processOrPasteHint = hasRunningProcess
194194 ? " · ctrl+o view output"
@@ -431,12 +431,12 @@ export const PromptInput = React.memo(function PromptInput({
431431 }
432432
433433 if ( key . delete ) {
434- updateBuffer ( ( s ) => deletePasteMarkerForward ( s ) ?? deleteForward ( s ) ) ;
434+ updateBuffer ( ( s ) => deletePasteMarkerForward ( s , pastesRef . current ) ?? deleteForward ( s ) ) ;
435435 return ;
436436 }
437437
438438 if ( key . backspace ) {
439- updateBuffer ( ( s ) => deletePasteMarkerBackward ( s ) ?? backspace ( s ) ) ;
439+ updateBuffer ( ( s ) => deletePasteMarkerBackward ( s , pastesRef . current ) ?? backspace ( s ) ) ;
440440 return ;
441441 }
442442
@@ -872,7 +872,7 @@ export const PromptInput = React.memo(function PromptInput({
872872 borderDimColor
873873 >
874874 < PromptPrefixLine busy = { busy } />
875- < Text > { renderBufferWithCursor ( buffer , ! disabled && hasTerminalFocus , placeholder ) } </ Text >
875+ < Text > { renderBufferWithCursor ( buffer , ! disabled && hasTerminalFocus , placeholder , pastesRef . current ) } </ Text >
876876 { inlineHint ? < Text dimColor > { inlineHint } </ Text > : null }
877877 </ Box >
878878 < RawModelDropdown
@@ -986,9 +986,15 @@ export function getPromptReturnKeyAction(key: Pick<InputKey, "return" | "shift"
986986 return "submit" ;
987987}
988988
989- export function renderBufferWithCursor ( state : PromptBufferState , isFocused : boolean , placeholder ?: string ) : string {
989+ export function renderBufferWithCursor (
990+ state : PromptBufferState ,
991+ isFocused : boolean ,
992+ placeholder ?: string ,
993+ validPastes ?: Map < number , string >
994+ ) : string {
990995 const text = state . text || "" ;
991996 const cursor = Math . max ( 0 , Math . min ( state . cursor , text . length ) ) ;
997+ const validIds = validPastes ?? new Map < number , string > ( ) ;
992998
993999 if ( text . length === 0 && placeholder ) {
9941000 if ( ! isFocused ) {
@@ -997,26 +1003,27 @@ export function renderBufferWithCursor(state: PromptBufferState, isFocused: bool
9971003 return renderCursorCell ( " " ) + chalk . dim ( ` ${ placeholder } ` ) ;
9981004 }
9991005
1006+ if ( text . length === 0 ) {
1007+ return isFocused ? renderCursorCell ( " " ) : "" ;
1008+ }
1009+
10001010 if ( ! isFocused ) {
1001- return highlightPasteMarkersInText ( text ) ;
1011+ return highlightPasteMarkersInText ( text , validIds ) ;
10021012 }
10031013
1004- // Focused: scan through the text, highlight paste markers, and insert
1005- // the cursor cell at the correct position. This approach handles the
1006- // case where the cursor sits at the start of (or inside) a paste marker.
1007- return renderFocusedText ( text , cursor ) ;
1014+ return renderFocusedText ( text , cursor , validIds ) ;
10081015}
10091016
1010- /** Highlight paste markers in a plain string (no cursor). */
1011- function highlightPasteMarkersInText ( s : string ) : string {
1017+ function highlightPasteMarkersInText ( s : string , validIds : Map < number , string > ) : string {
10121018 if ( ! s . includes ( "[paste #" ) ) return s ;
10131019 PASTE_MARKER_REGEX . lastIndex = 0 ;
10141020 let result = "" ;
10151021 let pos = 0 ;
10161022 let match : RegExpExecArray | null ;
10171023 while ( ( match = PASTE_MARKER_REGEX . exec ( s ) ) !== null ) {
10181024 result += s . slice ( pos , match . index ) ;
1019- result += chalk . yellow ( match [ 0 ] ) ;
1025+ const id = Number . parseInt ( match [ 1 ] ! , 10 ) ;
1026+ result += validIds . has ( id ) ? chalk . yellow ( match [ 0 ] ) : match [ 0 ] ;
10201027 pos = match . index + match [ 0 ] . length ;
10211028 }
10221029 result += s . slice ( pos ) ;
@@ -1029,7 +1036,7 @@ function highlightPasteMarkersInText(s: string): string {
10291036 * anywhere (including inside or at the boundary of a paste marker) and the
10301037 * marker will still be highlighted correctly.
10311038 */
1032- function renderFocusedText ( text : string , cursor : number ) : string {
1039+ function renderFocusedText ( text : string , cursor : number , validIds : Map < number , string > ) : string {
10331040 let result = "" ;
10341041 let pos = 0 ;
10351042 PASTE_MARKER_REGEX . lastIndex = 0 ;
@@ -1038,14 +1045,15 @@ function renderFocusedText(text: string, cursor: number): string {
10381045 while ( ( match = PASTE_MARKER_REGEX . exec ( text ) ) !== null ) {
10391046 const markerStart = match . index ;
10401047 const markerEnd = match . index + match [ 0 ] . length ;
1048+ const id = Number . parseInt ( match [ 1 ] ! , 10 ) ;
1049+ const isReal = validIds . has ( id ) ;
10411050
10421051 // 1. Non-marker segment before this marker.
10431052 result += renderTextSegmentWithCursor ( text , pos , markerStart , cursor , false ) ;
10441053 pos = markerStart ;
10451054
1046- // 2. Marker segment — highlighted with chalk.yellow.
1047- // The cursor may fall inside it.
1048- result += renderTextSegmentWithCursor ( text , pos , markerEnd , cursor , true ) ;
1055+ // 2. Marker segment — highlighted only if it corresponds to a real paste.
1056+ result += renderTextSegmentWithCursor ( text , pos , markerEnd , cursor , isReal ) ;
10491057 pos = markerEnd ;
10501058 }
10511059
0 commit comments