@@ -811,6 +811,67 @@ export function Prompt(props: PromptProps) {
811811 )
812812 }
813813
814+ function expandPasteExtmark ( extmark : { id : number ; start : number ; end : number } ) {
815+ const partIndex = store . extmarkToPartIndex . get ( extmark . id )
816+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
817+ if ( part ?. type !== "text" || ! part . source ?. text ) return false
818+
819+ const nextInput = store . prompt . input . slice ( 0 , extmark . start ) + part . text + store . prompt . input . slice ( extmark . end )
820+ const delta = part . text . length - ( extmark . end - extmark . start )
821+ const nextParts = store . prompt . parts
822+ . flatMap ( ( item , index ) => {
823+ if ( index === partIndex ) return [ ]
824+ const next = structuredClone ( unwrap ( item ) )
825+ if ( next . type === "agent" && next . source && next . source . start >= extmark . end ) {
826+ next . source . start += delta
827+ next . source . end += delta
828+ }
829+ if ( next . type === "file" && next . source ?. text && next . source . text . start >= extmark . end ) {
830+ next . source . text . start += delta
831+ next . source . text . end += delta
832+ }
833+ if ( next . type === "text" && next . source ?. text && next . source . text . start >= extmark . end ) {
834+ next . source . text . start += delta
835+ next . source . text . end += delta
836+ }
837+ return [ next ]
838+ } )
839+ . filter ( ( item ) : item is PromptInfo [ "parts" ] [ number ] => item !== undefined )
840+
841+ input . setText ( nextInput )
842+ setStore ( "prompt" , {
843+ input : nextInput ,
844+ parts : nextParts ,
845+ } )
846+ restoreExtmarksFromParts ( nextParts )
847+ input . cursorOffset = extmark . start + part . text . length
848+ return true
849+ }
850+
851+ function expandPasteBlockAtMouse ( event : MouseEvent ) {
852+ if ( event . button !== 0 ) return false
853+ const localX = event . x - input . x
854+ const localY = event . y - input . y
855+ if ( localX < 0 || localY < 0 || localX >= input . width || localY >= input . height ) return false
856+
857+ const previousOffset = input . cursorOffset
858+ input . editorView . setLocalSelection ( localX , localY , localX , localY , undefined , undefined , true , false )
859+ input . editorView . resetLocalSelection ( )
860+ const offset = input . cursorOffset
861+ const extmark = input . extmarks . getAllForTypeId ( promptPartTypeId ) . find ( ( item ) => {
862+ const partIndex = store . extmarkToPartIndex . get ( item . id )
863+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
864+ if ( part ?. type !== "text" ) return false
865+ return ( offset >= item . start && offset <= item . end ) || ( offset + 1 >= item . start && offset + 1 <= item . end )
866+ } )
867+ if ( ! extmark ) {
868+ input . cursorOffset = previousOffset
869+ return false
870+ }
871+
872+ return expandPasteExtmark ( extmark )
873+ }
874+
814875 const stashCommands = createMemo ( ( ) =>
815876 [
816877 {
@@ -1574,6 +1635,11 @@ export function Prompt(props: PromptProps) {
15741635 } , 0 )
15751636 } }
15761637 onMouseDown = { ( r : MouseEvent ) => r . target ?. focus ( ) }
1638+ onMouseUp = { ( event : MouseEvent ) => {
1639+ if ( ! expandPasteBlockAtMouse ( event ) ) return
1640+ event . preventDefault ( )
1641+ event . stopPropagation ( )
1642+ } }
15771643 focusedBackgroundColor = { theme . backgroundElement }
15781644 cursorColor = { props . disabled ? theme . backgroundElement : theme . text }
15791645 syntaxStyle = { syntax ( ) }
0 commit comments