on main help sign in
fix(bangmode): include bang commands in history
f342edfChristian Rocha
internal/ui/model/history.go+28
@@ -3,6 +3,7 @@ package model
3import (
3import (
4 "context"
4 "context"
5 "log/slog"
5 "log/slog"
6+ "strings"
6
7
7 tea "charm.land/bubbletea/v2"
8 tea "charm.land/bubbletea/v2"
8
9
@@ -36,6 +37,9 @@ func (m *UI) loadPromptHistory() tea.Cmd {
36 if text := msg.Content().Text; text != "" {
37 if text := msg.Content().Text; text != "" {
37 texts = append(texts, text)
38 texts = append(texts, text)
38 }
39 }
40+ for _, sc := range msg.ShellCommands() {
41+ texts = append(texts, "!"+sc.Command)
42+ }
39 }
43 }
40 return promptHistoryLoadedMsg{messages: texts}
44 return promptHistoryLoadedMsg{messages: texts}
41 }
45 }
@@ -93,6 +97,7 @@ func (m *UI) handleHistoryEscape(msg tea.Msg) tea.Cmd {
93 m.promptHistory.index = -1
97 m.promptHistory.index = -1
94 m.textarea.Reset()
98 m.textarea.Reset()
95 m.textarea.InsertString(m.promptHistory.draft)
99 m.textarea.InsertString(m.promptHistory.draft)
100+ m.syncBangModeFromTextarea()
96 return m.updateTextareaWithPrevHeight(nil, prevHeight)
101 return m.updateTextareaWithPrevHeight(nil, prevHeight)
97 }
102 }
98
103
@@ -108,6 +113,26 @@ func (m *UI) updateHistoryDraft(oldValue string) {
108 }
113 }
109}
114}
110
115
116+// syncBangModeFromTextarea engages or disengages bang mode based on
117+// whether the current textarea value starts with "!". The "!" prefix
118+// is stripped when entering bang mode and re-added when leaving it so
119+// the visible text always reflects the correct state.
120+func (m *UI) syncBangModeFromTextarea() {
121+ val := m.textarea.Value()
122+ hasBang := strings.HasPrefix(val, "!")
123+ if hasBang && !m.bangMode {
124+ m.bangMode = true
125+ m.bangWasEmpty = false
126+ m.textarea.SetValue(val[1:])
127+ m.textarea.MoveToBegin()
128+ } else if !hasBang && m.bangMode {
129+ m.bangMode = false
130+ m.bangWasEmpty = false
131+ }
132+ yolo := m.com.Workspace.PermissionSkipRequests()
133+ m.setEditorPrompt(yolo)
134+}
135+
111// historyPrev changes the text area content to the previous message in the history
136// historyPrev changes the text area content to the previous message in the history
112// it returns false if it could not find the previous message.
137// it returns false if it could not find the previous message.
113func (m *UI) historyPrev() bool {
138func (m *UI) historyPrev() bool {
@@ -125,6 +150,7 @@ func (m *UI) historyPrev() bool {
125 m.textarea.Reset()
150 m.textarea.Reset()
126 m.textarea.InsertString(m.promptHistory.messages[nextIndex])
151 m.textarea.InsertString(m.promptHistory.messages[nextIndex])
127 m.textarea.MoveToBegin()
152 m.textarea.MoveToBegin()
153+ m.syncBangModeFromTextarea()
128 return true
154 return true
129}
155}
130
156
@@ -139,11 +165,13 @@ func (m *UI) historyNext() bool {
139 m.promptHistory.index = -1
165 m.promptHistory.index = -1
140 m.textarea.Reset()
166 m.textarea.Reset()
141 m.textarea.InsertString(m.promptHistory.draft)
167 m.textarea.InsertString(m.promptHistory.draft)
168+ m.syncBangModeFromTextarea()
142 return true
169 return true
143 }
170 }
144 m.promptHistory.index = nextIndex
171 m.promptHistory.index = nextIndex
145 m.textarea.Reset()
172 m.textarea.Reset()
146 m.textarea.InsertString(m.promptHistory.messages[nextIndex])
173 m.textarea.InsertString(m.promptHistory.messages[nextIndex])
174+ m.syncBangModeFromTextarea()
147 return true
175 return true
148}
176}
149
177
internal/ui/model/ui.go+2−1
@@ -1014,6 +1014,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
1014 cmds = append(cmds, cmd)
1014 cmds = append(cmds, cmd)
1015 }
1015 }
1016 }
1016 }
1017+ cmds = append(cmds, m.loadPromptHistory())
1017 case hyperRefreshDoneMsg:
1018 case hyperRefreshDoneMsg:
1018 if cmd := m.handleSelectModel(msg.action); cmd != nil {
1019 if cmd := m.handleSelectModel(msg.action); cmd != nil {
1019 cmds = append(cmds, cmd)
1020 cmds = append(cmds, cmd)
@@ -2080,7 +2081,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
2080 m.setEditorPrompt(yolo)
2081 m.setEditorPrompt(yolo)
2081 m.randomizePlaceholders()
2082 m.randomizePlaceholders()
2082 m.historyReset()
2083 m.historyReset()
2083− return tea.Batch(m.runShellCommand(value), m.loadPromptHistory())
2084+ return tea.Batch(m.runShellCommand(value))
2084 }
2085 }
2085
2086
2086 attachments := m.attachments.List()
2087 attachments := m.attachments.List()