@@ -803,6 +803,67 @@ export function Prompt(props: PromptProps) {
803803 )
804804 }
805805
806+ function expandPasteExtmark ( extmark : { id : number ; start : number ; end : number } ) {
807+ const partIndex = store . extmarkToPartIndex . get ( extmark . id )
808+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
809+ if ( part ?. type !== "text" || ! part . source ?. text ) return false
810+
811+ const nextInput = store . prompt . input . slice ( 0 , extmark . start ) + part . text + store . prompt . input . slice ( extmark . end )
812+ const delta = part . text . length - ( extmark . end - extmark . start )
813+ const nextParts = store . prompt . parts
814+ . flatMap ( ( item , index ) => {
815+ if ( index === partIndex ) return [ ]
816+ const next = structuredClone ( unwrap ( item ) )
817+ if ( next . type === "agent" && next . source && next . source . start >= extmark . end ) {
818+ next . source . start += delta
819+ next . source . end += delta
820+ }
821+ if ( next . type === "file" && next . source ?. text && next . source . text . start >= extmark . end ) {
822+ next . source . text . start += delta
823+ next . source . text . end += delta
824+ }
825+ if ( next . type === "text" && next . source ?. text && next . source . text . start >= extmark . end ) {
826+ next . source . text . start += delta
827+ next . source . text . end += delta
828+ }
829+ return [ next ]
830+ } )
831+ . filter ( ( item ) : item is PromptInfo [ "parts" ] [ number ] => item !== undefined )
832+
833+ input . setText ( nextInput )
834+ setStore ( "prompt" , {
835+ input : nextInput ,
836+ parts : nextParts ,
837+ } )
838+ restoreExtmarksFromParts ( nextParts )
839+ input . cursorOffset = extmark . start + part . text . length
840+ return true
841+ }
842+
843+ function expandPasteBlockAtMouse ( event : MouseEvent ) {
844+ if ( event . button !== 0 ) return false
845+ const localX = event . x - input . x
846+ const localY = event . y - input . y
847+ if ( localX < 0 || localY < 0 || localX >= input . width || localY >= input . height ) return false
848+
849+ const previousOffset = input . cursorOffset
850+ input . editorView . setLocalSelection ( localX , localY , localX , localY , undefined , undefined , true , false )
851+ input . editorView . resetLocalSelection ( )
852+ const offset = input . cursorOffset
853+ const extmark = input . extmarks . getAllForTypeId ( promptPartTypeId ) . find ( ( item ) => {
854+ const partIndex = store . extmarkToPartIndex . get ( item . id )
855+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
856+ if ( part ?. type !== "text" ) return false
857+ return ( offset >= item . start && offset <= item . end ) || ( offset + 1 >= item . start && offset + 1 <= item . end )
858+ } )
859+ if ( ! extmark ) {
860+ input . cursorOffset = previousOffset
861+ return false
862+ }
863+
864+ return expandPasteExtmark ( extmark )
865+ }
866+
806867 const stashCommands = createMemo ( ( ) =>
807868 [
808869 {
@@ -1562,6 +1623,11 @@ export function Prompt(props: PromptProps) {
15621623 } , 0 )
15631624 } }
15641625 onMouseDown = { ( r : MouseEvent ) => r . target ?. focus ( ) }
1626+ onMouseUp = { ( event : MouseEvent ) => {
1627+ if ( ! expandPasteBlockAtMouse ( event ) ) return
1628+ event . preventDefault ( )
1629+ event . stopPropagation ( )
1630+ } }
15651631 focusedBackgroundColor = { theme . backgroundElement }
15661632 cursorColor = { props . disabled ? theme . backgroundElement : theme . text }
15671633 syntaxStyle = { syntax ( ) }
0 commit comments