Quit with Ctrl+C only; q is an ordinary key everywhere

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019reK4DUGYqDUjniWYJvwUW
This commit is contained in:
2026-10-21 10:20:18 +02:00
co-authored by Claude Opus 5.5
parent 60fd71bc92
commit 705d795e6d
6 changed files with 18 additions and 37 deletions
+2 -29
View File
@@ -25,9 +25,6 @@ type view struct {
onShow, onHide func()
// hints lists the keys that work in this view (shown in the status bar).
hints func() string
// captureKeys makes the global single-key shortcut (q) stands back
// while this view is shown, because its fields take typed text.
captureKeys bool
}
// App is the top-level arr-tui application.
@@ -160,7 +157,7 @@ func New(cfg *config.Config) *App {
{key: '3', name: "Library", body: library.root, onShow: library.activate, hints: libraryHints},
{key: '4', name: "Downloads", body: downloads.root, onShow: downloads.activate, onHide: downloads.deactivate, hints: downloads.hints},
{key: '5', name: "Calendar", body: calendar.root, onShow: calendar.activate, hints: calendarHints},
{key: '6', name: "Config", body: settings.root, onShow: settings.activate, hints: settingsHints, captureKeys: true},
{key: '6', name: "Config", body: settings.root, onShow: settings.activate, hints: settingsHints},
{key: '7', name: "Log", body: a.logs.root, onShow: a.logs.onShow, hints: logHints},
}
for i, v := range a.views {
@@ -439,11 +436,7 @@ func (a *App) renderStatus() {
if v.hints != nil {
parts = append(parts, v.hints())
}
if v.captureKeys { // q is text there
parts = append(parts, "F9 help · F1-F7 views")
} else {
parts = append(parts, "F9 help · F1-F7 · q quit")
}
parts = append(parts, "F9 help · F1-F7 · Ctrl+C quit")
hints = strings.Join(parts, " · ")
}
a.status.SetText("[gray]" + hints)
@@ -533,16 +526,6 @@ func (a *App) onlyFullOverlays() bool {
return true
}
// typing reports whether keystrokes belong to a text field or dialog and must
// not trigger global shortcuts.
func (a *App) typing() bool {
if len(a.overlays) > 0 || a.views[a.active].captureKeys {
return true
}
_, isInput := a.app.GetFocus().(*tview.InputField)
return isInput
}
func (a *App) handleKey(ev *tcell.EventKey) *tcell.EventKey {
if ev.Key() == tcell.KeyCtrlC {
a.app.Stop()
@@ -563,16 +546,6 @@ func (a *App) handleKey(ev *tcell.EventKey) *tcell.EventKey {
return nil
}
}
if a.typing() {
return ev
}
switch ev.Key() {
case tcell.KeyRune:
if ev.Rune() == 'q' {
a.app.Stop()
return nil
}
}
return ev
}
+8
View File
@@ -38,3 +38,11 @@ func TestOnlyFunctionKeysSwitchViews(t *testing.T) {
}
}
}
func TestQDoesNotQuit(t *testing.T) {
a := newTestApp(t)
ev := tcell.NewEventKey(tcell.KeyRune, 'q', 0)
if got := a.handleKey(ev); got != ev {
t.Error("q must be passed on as an ordinary key, not taken as quit")
}
}
+3 -4
View File
@@ -22,7 +22,7 @@ var helpSections = []helpSection{
{"F1-F7", "switch view (also from the release and episode lists)"},
{"Tab, Shift+Tab", "switch panel within a view"},
{"F9", "this help (works everywhere, also while typing)"},
{"q, Ctrl+C", "quit"},
{"Ctrl+C", "quit"},
{"Esc", "close a dialog / go back"},
}},
{title: "Movies and Series", items: []helpItem{
@@ -72,7 +72,6 @@ var helpSections = []helpSection{
{"Space", "toggle a checkbox; press a button"},
{"Test", "(button below the SABnzbd settings) checks the three services with the values typed in"},
{"Save, Revert", "(at the bottom) Save writes the file and applies everything at once; Revert discards edits"},
{"q", "is typed here as text (it does not quit); F9 opens this help"},
}},
{title: "Log (F7)", note: "Popups fade away by themselves; everything they said is kept here.", items: []helpItem{
{"↑↓, PgUp, PgDn", "scroll"},
@@ -138,12 +137,12 @@ func (a *App) showHelp() {
tv.SetBorderPadding(0, 0, 1, 0)
tv.SetText(text)
tv.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey {
if ev.Key() == tcell.KeyEsc || (ev.Key() == tcell.KeyRune && ev.Rune() == 'q') {
if ev.Key() == tcell.KeyEsc {
a.closeModal()
return nil
}
return ev
})
height := min(screenH-2, strings.Count(text, "\n")+2)
a.openModalHints(tv, width, height, "↑↓ PgUp PgDn scroll · Esc or q close")
a.openModalHints(tv, width, height, "↑↓ PgUp PgDn scroll · Esc close")
}