@@ -725,6 +725,67 @@ export function Prompt(props: PromptProps) {
725725 )
726726 }
727727
728+ function expandPasteExtmark ( extmark : { id : number ; start : number ; end : number } ) {
729+ const partIndex = store . extmarkToPartIndex . get ( extmark . id )
730+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
731+ if ( part ?. type !== "text" || ! part . source ?. text ) return false
732+
733+ const nextInput = store . prompt . input . slice ( 0 , extmark . start ) + part . text + store . prompt . input . slice ( extmark . end )
734+ const delta = part . text . length - ( extmark . end - extmark . start )
735+ const nextParts = store . prompt . parts
736+ . flatMap ( ( item , index ) => {
737+ if ( index === partIndex ) return [ ]
738+ const next = structuredClone ( unwrap ( item ) )
739+ if ( next . type === "agent" && next . source && next . source . start >= extmark . end ) {
740+ next . source . start += delta
741+ next . source . end += delta
742+ }
743+ if ( next . type === "file" && next . source ?. text && next . source . text . start >= extmark . end ) {
744+ next . source . text . start += delta
745+ next . source . text . end += delta
746+ }
747+ if ( next . type === "text" && next . source ?. text && next . source . text . start >= extmark . end ) {
748+ next . source . text . start += delta
749+ next . source . text . end += delta
750+ }
751+ return [ next ]
752+ } )
753+ . filter ( ( item ) : item is PromptInfo [ "parts" ] [ number ] => item !== undefined )
754+
755+ input . setText ( nextInput )
756+ setStore ( "prompt" , {
757+ input : nextInput ,
758+ parts : nextParts ,
759+ } )
760+ restoreExtmarksFromParts ( nextParts )
761+ input . cursorOffset = extmark . start + part . text . length
762+ return true
763+ }
764+
765+ function expandPasteBlockAtMouse ( event : MouseEvent ) {
766+ if ( event . button !== 0 ) return false
767+ const localX = event . x - input . x
768+ const localY = event . y - input . y
769+ if ( localX < 0 || localY < 0 || localX >= input . width || localY >= input . height ) return false
770+
771+ const previousOffset = input . cursorOffset
772+ input . editorView . setLocalSelection ( localX , localY , localX , localY , undefined , undefined , true , false )
773+ input . editorView . resetLocalSelection ( )
774+ const offset = input . cursorOffset
775+ const extmark = input . extmarks . getAllForTypeId ( promptPartTypeId ) . find ( ( item ) => {
776+ const partIndex = store . extmarkToPartIndex . get ( item . id )
777+ const part = partIndex === undefined ? undefined : store . prompt . parts [ partIndex ]
778+ if ( part ?. type !== "text" ) return false
779+ return ( offset >= item . start && offset <= item . end ) || ( offset + 1 >= item . start && offset + 1 <= item . end )
780+ } )
781+ if ( ! extmark ) {
782+ input . cursorOffset = previousOffset
783+ return false
784+ }
785+
786+ return expandPasteExtmark ( extmark )
787+ }
788+
728789 const stashCommands = createMemo ( ( ) =>
729790 [
730791 {
@@ -1460,6 +1521,11 @@ export function Prompt(props: PromptProps) {
14601521 } , 0 )
14611522 } }
14621523 onMouseDown = { ( r : MouseEvent ) => r . target ?. focus ( ) }
1524+ onMouseUp = { ( event : MouseEvent ) => {
1525+ if ( ! expandPasteBlockAtMouse ( event ) ) return
1526+ event . preventDefault ( )
1527+ event . stopPropagation ( )
1528+ } }
14631529 focusedBackgroundColor = { theme . backgroundElement }
14641530 cursorColor = { props . disabled ? theme . backgroundElement : theme . text }
14651531 syntaxStyle = { syntax ( ) }
0 commit comments