mirror of
https://github.com/sst/opencode.git
synced 2025-08-04 05:28:16 +00:00
/editor: non-successful editor exits should keep the text in the textarea
# Conflicts: # packages/tui/internal/tui/tui.go
This commit is contained in:
parent
969ad80ed2
commit
a1161fd0e8
2 changed files with 30 additions and 5 deletions
|
@ -27,6 +27,7 @@ type EditorComponent interface {
|
||||||
Content(width int) string
|
Content(width int) string
|
||||||
Lines() int
|
Lines() int
|
||||||
Value() string
|
Value() string
|
||||||
|
SetValue(value string)
|
||||||
Focused() bool
|
Focused() bool
|
||||||
Focus() (tea.Model, tea.Cmd)
|
Focus() (tea.Model, tea.Cmd)
|
||||||
Blur()
|
Blur()
|
||||||
|
@ -230,6 +231,10 @@ func (m *editorComponent) Value() string {
|
||||||
return m.textarea.Value()
|
return m.textarea.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *editorComponent) SetValue(value string) {
|
||||||
|
m.textarea.SetValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *editorComponent) Submit() (tea.Model, tea.Cmd) {
|
func (m *editorComponent) Submit() (tea.Model, tea.Cmd) {
|
||||||
value := strings.TrimSpace(m.Value())
|
value := strings.TrimSpace(m.Value())
|
||||||
if value == "" {
|
if value == "" {
|
||||||
|
|
|
@ -32,6 +32,11 @@ import (
|
||||||
// InterruptDebounceTimeoutMsg is sent when the interrupt key debounce timeout expires
|
// InterruptDebounceTimeoutMsg is sent when the interrupt key debounce timeout expires
|
||||||
type InterruptDebounceTimeoutMsg struct{}
|
type InterruptDebounceTimeoutMsg struct{}
|
||||||
|
|
||||||
|
// EditorRestoreMsg is sent when the external editor fails and we need to restore the original content
|
||||||
|
type EditorRestoreMsg struct {
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
// InterruptKeyState tracks the state of interrupt key presses for debouncing
|
// InterruptKeyState tracks the state of interrupt key presses for debouncing
|
||||||
type InterruptKeyState int
|
type InterruptKeyState int
|
||||||
|
|
||||||
|
@ -486,6 +491,9 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
// Reset interrupt key state after timeout
|
// Reset interrupt key state after timeout
|
||||||
a.interruptKeyState = InterruptKeyIdle
|
a.interruptKeyState = InterruptKeyIdle
|
||||||
a.editor.SetInterruptKeyInDebounce(false)
|
a.editor.SetInterruptKeyInDebounce(false)
|
||||||
|
case EditorRestoreMsg:
|
||||||
|
// Restore the original content to the textarea when editor fails
|
||||||
|
a.editor.SetValue(msg.Content)
|
||||||
case dialog.FindSelectedMsg:
|
case dialog.FindSelectedMsg:
|
||||||
return a.openFile(msg.FilePath)
|
return a.openFile(msg.FilePath)
|
||||||
}
|
}
|
||||||
|
@ -789,20 +797,32 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd)
|
||||||
c.Stdout = os.Stdout
|
c.Stdout = os.Stdout
|
||||||
c.Stderr = os.Stderr
|
c.Stderr = os.Stderr
|
||||||
cmd = tea.ExecProcess(c, func(err error) tea.Msg {
|
cmd = tea.ExecProcess(c, func(err error) tea.Msg {
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
|
// Check if the process exited with non-zero status
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Failed to open editor", "error", err)
|
if exitError, ok := err.(*exec.ExitError); ok {
|
||||||
return nil
|
slog.Warn("Editor exited with non-zero status", "exitCode", exitError.ExitCode())
|
||||||
|
// Restore original content when editor exits unsuccessfully
|
||||||
|
return EditorRestoreMsg{Content: value}
|
||||||
|
} else {
|
||||||
|
slog.Error("Failed to open editor", "error", err)
|
||||||
|
// Restore original content when editor fails to start
|
||||||
|
return EditorRestoreMsg{Content: value}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := os.ReadFile(tmpfile.Name())
|
content, err := os.ReadFile(tmpfile.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Failed to read file", "error", err)
|
slog.Error("Failed to read file", "error", err)
|
||||||
return nil
|
// Restore original content when file read fails
|
||||||
|
return EditorRestoreMsg{Content: value}
|
||||||
}
|
}
|
||||||
if len(content) == 0 {
|
if len(content) == 0 {
|
||||||
slog.Warn("Message is empty")
|
slog.Warn("Message is empty")
|
||||||
return nil
|
// Restore original content when message is empty
|
||||||
|
return EditorRestoreMsg{Content: value}
|
||||||
}
|
}
|
||||||
os.Remove(tmpfile.Name())
|
|
||||||
return app.SendMsg{
|
return app.SendMsg{
|
||||||
Text: string(content),
|
Text: string(content),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue