Make the screen explain itself: labels, tools, help pages, hints

For developers new to submodules (notes/usability-plan.md, D32):
- x and X read "restore to pin" and "restore committed pins"
- problems only, filter and fetch are shown in the footer
- ? shows every key in titled columns, then a legend of the status
  words, symbols and spine roles; esc closes it
- u reads "pull (fast-forward)" on the superproject
- the detail pane suggests f when the last fetch is old
- a hint above the footer until the first key
- the header says "staged", like the tree

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 23:26:32 +02:00
co-authored by Claude Opus 5.5
parent b205576759
commit c9932932bb
19 changed files with 816 additions and 78 deletions
+42
View File
@@ -66,3 +66,45 @@ func TestQuitAndUpdate(t *testing.T) {
t.Errorf("ctrl+c must quit without updating, got update to %q", m2.(Model).UpdateTo())
}
}
func TestHintUntilTheFirstKey(t *testing.T) {
m := newUpdateModel("")
if !m.(Model).extraLine() || !strings.Contains(m.View(), "new here?") {
t.Fatal("no hint on start")
}
m, _ = press(m, "j")
if m.(Model).extraLine() || strings.Contains(m.View(), "new here?") {
t.Error("the hint must go away with the first key")
}
}
func TestEscClosesTheHelp(t *testing.T) {
for _, presses := range []int{1, 2} { // the keys page, the legend
m := newUpdateModel("")
for range presses {
m, _ = press(m, "?")
}
if !m.(Model).footer.HelpOpen() {
t.Fatalf("%d × ?: no help", presses)
}
m, _ = pressKey(m, tea.KeyEsc)
if m.(Model).footer.HelpOpen() {
t.Errorf("%d × ?: esc must close the help", presses)
}
}
}
func TestEscClosesTheHelpBeforeTheFilter(t *testing.T) {
m := newUpdateModel("")
m, _ = press(m, "/")
m, _ = pressKey(m, tea.KeyEnter) // keys back to the tree, the filter stays
m, _ = press(m, "?")
m, _ = pressKey(m, tea.KeyEsc)
if mm := m.(Model); mm.footer.HelpOpen() || !mm.filtering {
t.Errorf("first esc: help open %v, filtering %v; want the help closed, the filter kept", mm.footer.HelpOpen(), mm.filtering)
}
m, _ = pressKey(m, tea.KeyEsc)
if m.(Model).filtering {
t.Error("second esc must close the filter")
}
}