handleCtrlC implements Ctrl+C's three-level precedence: in-flight cancel > popover close > quit arming. Each level fully handles the key, no fallthrough.
()
| 109 | // handleCtrlC implements Ctrl+C's three-level precedence: in-flight cancel > |
| 110 | // popover close > quit arming. Each level fully handles the key, no fallthrough. |
| 111 | func (m Model) handleCtrlC() (tea.Model, tea.Cmd) { |
| 112 | if m.cancel != nil { |
| 113 | // abortTurn flushes the partial block so streamed output stays |
| 114 | // visible, drains turn stats for a clean next banner, then unwinds |
| 115 | // the per-turn context. |
| 116 | dbgWritef("cancel", "user cancelled the turn (Ctrl+C)") |
| 117 | m.abortTurn(styleWarn.Render("✗ cancelled")) |
| 118 | m.quitArmedAt = time.Time{} |
| 119 | m.status = "" |
| 120 | return m, nil |
| 121 | } |
| 122 | if m.popoverOpen() { |
| 123 | m.closePopover() |
| 124 | m.quitArmedAt = time.Time{} |
| 125 | m.status = "" |
| 126 | return m, nil |
| 127 | } |
| 128 | if !m.quitArmedAt.IsZero() && time.Now().Before(m.quitArmedAt) { |
| 129 | return m, tea.Quit |
| 130 | } |
| 131 | m.quitArmedAt = time.Now().Add(3 * time.Second) |
| 132 | m.status = quitArmText |
| 133 | return m, tea.Tick(3*time.Second, func(time.Time) tea.Msg { return quitArmResetMsg{} }) |
| 134 | } |
| 135 | |
| 136 | // historyUp walks one step toward older entries; caller gates on cursor-on- |
| 137 | // first-line and popover closed. Empty history is a no-op. |
no test coverage detected