Advertise the rule screens in the key help
The bottom help still described 4 as "rules" from before the rules list existed, and never mentioned 5 at all, so the new screen was unreachable unless you already knew about it. The transactions line had also outgrown the window: at 137 characters it ran past the edge of a normal terminal and "q quit" was simply gone. Help now wraps to the window width instead of being cut off, and that line is shorter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@ const usage = `money - statement-driven personal finance tracker
|
|||||||
usage: money [--root DIR] <command> [flags]
|
usage: money [--root DIR] <command> [flags]
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
tui browse and tag transactions (default)
|
tui browse and tag transactions, build and prune rules (default)
|
||||||
import extract transactions from every statement into the index
|
import extract transactions from every statement into the index
|
||||||
retag re-apply rules.toml to everything already imported
|
retag re-apply rules.toml to everything already imported
|
||||||
ls list transactions
|
ls list transactions
|
||||||
|
|||||||
+12
-5
@@ -1111,7 +1111,14 @@ func (m *Model) View() string {
|
|||||||
b.WriteString(statusStyle.Render(m.status))
|
b.WriteString(statusStyle.Render(m.status))
|
||||||
}
|
}
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render(m.help()))
|
// Wrap the key list rather than letting the terminal cut it off: the keys
|
||||||
|
// at the end are as important as the ones at the start, and "q quit" was
|
||||||
|
// the first casualty on a narrow window.
|
||||||
|
help := helpStyle
|
||||||
|
if m.width > 0 {
|
||||||
|
help = help.Width(m.width)
|
||||||
|
}
|
||||||
|
b.WriteString(help.Render(m.help()))
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,17 +1259,17 @@ func (m *Model) help() string {
|
|||||||
}
|
}
|
||||||
switch m.view {
|
switch m.view {
|
||||||
case viewAccounts:
|
case viewAccounts:
|
||||||
return "enter open · 2 transactions · 3 report · 4 rules · i import · r retag · q quit"
|
return "enter open · 2 transactions · 3 report · 4 new rule · 5 rules · i import · r retag · q quit"
|
||||||
case viewRules:
|
case viewRules:
|
||||||
return "tab/↑↓ field · pgup/pgdn scroll list · enter save rule · esc back · ctrl+c quit"
|
return "tab/↑↓ field · pgup/pgdn scroll list · enter save rule · esc back · ctrl+c quit"
|
||||||
case viewRuleList:
|
case viewRuleList:
|
||||||
if m.confirm != confirmNone {
|
if m.confirm != confirmNone {
|
||||||
return "y confirm · any other key cancels"
|
return "y confirm · any other key cancels"
|
||||||
}
|
}
|
||||||
return "d delete rule · p prune all unused · r refresh counts · 4 rule builder · esc back · q quit"
|
return "d delete rule · p prune all unused · r refresh counts · 4 new rule · 1 accounts · esc back · q quit"
|
||||||
case viewReport:
|
case viewReport:
|
||||||
return "1 accounts · 2 transactions · 4 rules · u untagged · a all accounts · q quit"
|
return "1 accounts · 2 transactions · 4 new rule · 5 rules · u untagged · a all accounts · q quit"
|
||||||
default:
|
default:
|
||||||
return "t tag · x transfer · c clear · / search · u untagged · a all · i import · r retag · 4 rules · 1 accounts · 3 report · q quit"
|
return "t tag · x transfer · c clear · / search · u untagged · a all · i import · r retag · 4 new rule · 5 rules · q quit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -840,6 +840,55 @@ func TestRuleListPruneWithNothingToDo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every screen must advertise how to reach the others and how to quit. These
|
||||||
|
// lines drift as screens are added, and a line that outgrows the terminal
|
||||||
|
// loses its tail silently.
|
||||||
|
func TestHelpLinesMentionEveryScreen(t *testing.T) {
|
||||||
|
m, _ := newTestModel(t)
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
key string
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{"accounts", "1", []string{"4 new rule", "5 rules", "q quit"}},
|
||||||
|
{"transactions", "2", []string{"4 new rule", "5 rules", "q quit"}},
|
||||||
|
{"report", "3", []string{"4 new rule", "5 rules", "q quit"}},
|
||||||
|
{"rules", "5", []string{"d delete rule", "p prune all unused", "4 new rule", "q quit"}},
|
||||||
|
} {
|
||||||
|
key(t, m, tc.key)
|
||||||
|
help := m.help()
|
||||||
|
for _, want := range tc.want {
|
||||||
|
if !strings.Contains(help, want) {
|
||||||
|
t.Errorf("%s help = %q, missing %q", tc.name, help, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rule builder is a form, so it advertises its own keys instead.
|
||||||
|
key(t, m, "4")
|
||||||
|
if help := m.help(); !strings.Contains(help, "enter save rule") || !strings.Contains(help, "esc back") {
|
||||||
|
t.Errorf("rule builder help = %q", help)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A help line longer than the window must wrap, not be cut off.
|
||||||
|
func TestHelpWrapsOnNarrowTerminals(t *testing.T) {
|
||||||
|
m, _ := newTestModel(t)
|
||||||
|
key(t, m, "2")
|
||||||
|
m.Update(tea.WindowSizeMsg{Width: 90, Height: 30})
|
||||||
|
|
||||||
|
view := m.View()
|
||||||
|
if !strings.Contains(view, "q quit") {
|
||||||
|
t.Errorf("the end of the help line was lost at 90 columns:\n%s", view)
|
||||||
|
}
|
||||||
|
for _, line := range strings.Split(view, "\n") {
|
||||||
|
if len([]rune(line)) > 90 {
|
||||||
|
t.Errorf("line is %d columns wide, wider than the window:\n%q", len([]rune(line)), line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// newEmptyModel builds a model over an index with nothing in it.
|
// newEmptyModel builds a model over an index with nothing in it.
|
||||||
func newEmptyModel(t *testing.T, accounts []*config.Account) *Model {
|
func newEmptyModel(t *testing.T, accounts []*config.Account) *Model {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|||||||
Reference in New Issue
Block a user