@@ -17,6 +17,7 @@ import (
1717 "slices"
1818 "strconv"
1919 "strings"
20+ "unicode"
2021 "time"
2122
2223 "charm.land/bubbles/v2/help"
@@ -2182,19 +2183,24 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
21822183 cmds = append(cmds, m.updateTextareaWithPrevHeight(msg, prevHeight))
21832184
21842185 // Bang mode: enter when "!" is typed at the start of the
2185โ // prompt (either on an empty prompt or prepended to existing
2186โ // text). Exit on backspace clearing the last character.
2186+ // prompt, optionally preceded by whitespace (either on an
2187+ // empty/whitespace-only prompt or prepended to existing text).
2188+ // Exit on backspace clearing the last character.
21872189 newVal := m.textarea.Value()
2188โ if !m.bangMode && strings.HasPrefix(newVal, "!") && !strings.HasPrefix(curValue, "!") {
2190+ trimmedNew := strings.TrimLeftFunc(newVal, unicode.IsSpace)
2191+ trimmedCur := strings.TrimLeftFunc(curValue, unicode.IsSpace)
2192+ if !m.bangMode && strings.HasPrefix(trimmedNew, "!") && !strings.HasPrefix(trimmedCur, "!") {
21892193 m.bangMode = true
21902194 m.bangWasEmpty = len(strings.TrimSpace(curValue)) == 0
2191โ // Strip the leading "!" from the textarea while preserving
2192โ // the cursor position relative to the command text.
2195+ // Strip leading whitespace and the "!" from the textarea
2196+ // while preserving the cursor position relative to the
2197+ // command text.
21932198 col := m.textarea.Column()
21942199 line := m.textarea.Line()
2195โ m.textarea.SetValue(newVal[1:])
2196โ m.textarea.SetCursorColumn(max(0, col-1))
2197โ _ = line // cursor line doesn't change; first char removed
2200+ stripped := trimmedNew[1:]
2201+ m.textarea.SetValue(stripped)
2202+ m.textarea.SetCursorColumn(max(0, col-(len(newVal)-len(stripped))))
2203+ _ = line // cursor line doesn't change; prefix removed
21982204 yolo := m.com.Workspace.PermissionSkipRequests()
21992205 m.setEditorPrompt(yolo)
22002206 } else if m.bangMode && newVal == "" && curValue != "" {