@@ -17,8 +17,8 @@ import (
1717 "slices"
1818 "strconv"
1919 "strings"
20โ "unicode"
2120 "time"
21+ "unicode"
2222
2323 "charm.land/bubbles/v2/help"
2424 "charm.land/bubbles/v2/key"
@@ -3879,6 +3879,28 @@ func (m *UI) newSession() tea.Cmd {
38793879 )
38803880}
38813881
3882+// checkBangModeAfterPaste engages bang mode when pasted text starts with
3883+// optional whitespace followed by "!". It strips the prefix and adjusts
3884+// the cursor, mirroring the keypress bang-mode entry logic.
3885+func (m *UI) checkBangModeAfterPaste() {
3886+ if m.bangMode {
3887+ return
3888+ }
3889+ val := m.textarea.Value()
3890+ trimmed := strings.TrimLeftFunc(val, unicode.IsSpace)
3891+ if !strings.HasPrefix(trimmed, "!") {
3892+ return
3893+ }
3894+ m.bangMode = true
3895+ m.bangWasEmpty = true
3896+ stripped := trimmed[1:]
3897+ m.textarea.SetValue(stripped)
3898+ col := m.textarea.Column()
3899+ m.textarea.SetCursorColumn(max(0, col-(len(val)-len(stripped))))
3900+ yolo := m.com.Workspace.PermissionSkipRequests()
3901+ m.setEditorPrompt(yolo)
3902+}
3903+
38823904// handlePasteMsg handles a paste message.
38833905func (m *UI) handlePasteMsg(msg tea.PasteMsg) tea.Cmd {
38843906 // Normalize \r\n before the textarea sanitizer sees it.
@@ -3939,7 +3961,9 @@ func (m *UI) handlePasteMsg(msg tea.PasteMsg) tea.Cmd {
39393961 }
39403962 if !allExistsAndValid() {
39413963 prevHeight := m.textarea.Height()
3942โ return m.updateTextareaWithPrevHeight(msg, prevHeight)
3964+ cmd := m.updateTextareaWithPrevHeight(msg, prevHeight)
3965+ m.checkBangModeAfterPaste()
3966+ return cmd
39433967 }
39443968
39453969 var cmds []tea.Cmd