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