From 5249ee67093599862579a13c6a0ec4f91573a4cf Mon Sep 17 00:00:00 2001 From: David Dworken Date: Sun, 27 Nov 2022 08:54:34 -0800 Subject: [PATCH] Add better handling for invalid searches in the TUI + better error messages in a couple other places to improve #40 --- client/client_test.go | 16 ++++++++++ .../lib/goldens/TestTui-InitialInvalidSearch | 30 +++++++++++++++++++ client/lib/goldens/TestTui-InvalidSearch | 29 ++++++++++++++++++ client/lib/lib.go | 4 +-- client/lib/tui.go | 19 +++++++----- 5 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 client/lib/goldens/TestTui-InitialInvalidSearch create mode 100644 client/lib/goldens/TestTui-InvalidSearch diff --git a/client/client_test.go b/client/client_test.go index ca53c20..686c7f8 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1840,6 +1840,22 @@ func TestTui(t *testing.T) { t.Fatalf("hishtory export mismatch (-expected +got):\n%s", diff) } + // Check the output when the initial search is invalid + out = captureTerminalOutput(t, tester, []string{ + "hishtory SPACE tquery SPACE foo: ENTER", + "ls", + }) + out = strings.TrimSpace(strings.Split(out, "hishtory tquery")[1]) + compareGoldens(t, out, "TestTui-InitialInvalidSearch") + + // Check the output when the initial search is invalid + out = captureTerminalOutput(t, tester, []string{ + "hishtory SPACE tquery ENTER", + "ls:", + }) + out = strings.TrimSpace(strings.Split(out, "hishtory tquery")[1]) + compareGoldens(t, out, "TestTui-InvalidSearch") + // Check the output when the size is adjusted out = captureTerminalOutputWithShellNameAndDimensions(t, tester, tester.ShellName(), 100, 20, []string{ "hishtory SPACE tquery ENTER", diff --git a/client/lib/goldens/TestTui-InitialInvalidSearch b/client/lib/goldens/TestTui-InitialInvalidSearch new file mode 100644 index 0000000..da0f133 --- /dev/null +++ b/client/lib/goldens/TestTui-InitialInvalidSearch @@ -0,0 +1,30 @@ +foo: + + + +Search Query: > ls + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Hostname CWD Timestamp Runtime Exit Code Command │ +│────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ localhost /tmp/ Oct 17 2022 21:43:16 PDT 3s 2 ls ~/ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file diff --git a/client/lib/goldens/TestTui-InvalidSearch b/client/lib/goldens/TestTui-InvalidSearch new file mode 100644 index 0000000..cfc6358 --- /dev/null +++ b/client/lib/goldens/TestTui-InvalidSearch @@ -0,0 +1,29 @@ +Warning: failed to search: search query contains unknown search atom 'ls' that doesn't match any column names + + +Search Query: > ls: + +┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ Hostname CWD Timestamp Runtime Exit Code Command │ +│────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ localhost /tmp/ Oct 17 2022 21:43:16 PDT 3s 2 ls ~/ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file diff --git a/client/lib/lib.go b/client/lib/lib.go index 655d9c2..9511b45 100644 --- a/client/lib/lib.go +++ b/client/lib/lib.go @@ -495,7 +495,7 @@ func IsEnabled(ctx *context.Context) (bool, error) { func CheckFatalError(err error) { if err != nil { _, filename, line, _ := runtime.Caller(1) - log.Fatalf("hishtory fatal error at %s:%d: %v", filename, line, err) + log.Fatalf("hishtory v0.%s fatal error at %s:%d: %v", Version, filename, line, err) } } @@ -1199,7 +1199,7 @@ func parseAtomizedToken(ctx *context.Context, token string) (string, interface{} } } if !isCustomColumn { - return "", nil, nil, fmt.Errorf("search query contains unknown search atom %s", field) + return "", nil, nil, fmt.Errorf("search query contains unknown search atom '%s' that doesn't match any column names", field) } // Build the where clause for the custom column return "EXISTS (SELECT 1 FROM json_each(custom_columns) WHERE json_extract(value, '$.name') = ? and instr(json_extract(value, '$.value'), ?) > 0)", field, val, nil diff --git a/client/lib/tui.go b/client/lib/tui.go index c79762b..408ef90 100644 --- a/client/lib/tui.go +++ b/client/lib/tui.go @@ -57,7 +57,7 @@ type model struct { lastQuery string // Unrecoverable error. - err error + fatalErr error // An error while searching. Recoverable and displayed as a warning message. searchErr error // Whether the device is offline. If so, a warning will be displayed. @@ -98,17 +98,15 @@ func runQueryAndUpdateTable(m model, updateTable bool) model { m.runQuery = &m.lastQuery } rows, numEntries, err := getRows(m.ctx, hctx.GetConf(m.ctx).DisplayedColumns, *m.runQuery, PADDED_NUM_ENTRIES) + m.searchErr = err if err != nil { - m.searchErr = err return m - } else { - m.searchErr = nil } m.numEntries = numEntries if updateTable { t, err := makeTable(m.ctx, rows) if err != nil { - m.err = err + m.fatalErr = err return m } m.table = t @@ -154,7 +152,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m = runQueryAndUpdateTable(m, true) return m, nil case errMsg: - m.err = msg + m.fatalErr = msg return m, nil case offlineMsg: m.isOffline = true @@ -178,8 +176,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m model) View() string { - if m.err != nil { - return fmt.Sprintf("An unrecoverable error occured: %v\n", m.err) + if m.fatalErr != nil { + return fmt.Sprintf("An unrecoverable error occured: %v\n", m.fatalErr) } if m.selected { indexOfCommand := -1 @@ -412,6 +410,11 @@ func TuiQuery(ctx *context.Context, initialQuery string) error { lipgloss.SetColorProfile(termenv.ANSI) rows, numEntries, err := getRows(ctx, hctx.GetConf(ctx).DisplayedColumns, initialQuery, PADDED_NUM_ENTRIES) if err != nil { + if initialQuery != "" { + // initialQuery is likely invalid in some way, let's just drop it + return TuiQuery(ctx, "") + } + // Something else has gone wrong, crash return err } t, err := makeTable(ctx, rows)