diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-23 22:43:59 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-23 22:43:59 +0200 |
| commit | b14a1ccfbf60b0866911788176491af5907702eb (patch) | |
| tree | eccb1293b62e3ccb8d7e24f9a6170e5c2141bc3b /internal/cli | |
| parent | 13272b89c8e343f53f0633fd057d7a0054113524 (diff) | |
Release v0.5.2v0.5.2
Diffstat (limited to 'internal/cli')
| -rw-r--r-- | internal/cli/cli.go | 36 | ||||
| -rw-r--r-- | internal/cli/cli_test.go | 35 |
2 files changed, 67 insertions, 4 deletions
diff --git a/internal/cli/cli.go b/internal/cli/cli.go index ef00010..7152496 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -156,6 +156,7 @@ func (c *CLI) run(ctx context.Context, argv []string) int { // c.lastResult is updated by dispatch and accessible between iterations. func (c *CLI) shellLoop(ctx context.Context) int { ec := 0 + logMsg("Interactive mode (vi keys): Ctrl-] for normal mode, i for insert | Enter fuzzy picker | ctrl-t/y/o/e (or alt-t/y/o/e) in picker") for { line, err := c.sh.ReadLine(ctx) @@ -170,12 +171,16 @@ func (c *CLI) shellLoop(ctx context.Context) int { argv := strings.Fields(line) if len(argv) == 0 { - // Empty input — run fzf picker just as the Ruby nil branch does. - result, fzfErr := c.st.Fzf(ctx) + // Empty input — run fzf picker. + result, fzfErr := c.st.FzfInteractive(ctx) if fzfErr != nil { warn(fzfErr.Error()) - } else if result != "" { - c.lastResult = result + continue + } + if result.Description != "" { + c.lastResult = result.Description + logMsg(fmt.Sprintf("Picked: %s", result.Description)) + ec = c.dispatchPickerAction(ctx, result) } continue } @@ -198,6 +203,29 @@ func (c *CLI) shellLoop(ctx context.Context) int { return ec } +func pickerActionArgv(action store.PickerAction, description string) []string { + switch action { + case store.PickerCat: + return []string{"cat", description} + case store.PickerPaste: + return []string{"paste", description} + case store.PickerOpen: + return []string{"open", description} + case store.PickerEdit: + return []string{"edit", description} + default: + return nil + } +} + +func (c *CLI) dispatchPickerAction(ctx context.Context, result store.PickerResult) int { + argv := pickerActionArgv(result.Action, result.Description) + if len(argv) == 0 { + return 0 + } + return c.dispatch(ctx, argv) +} + // dispatch routes a parsed argv slice to the appropriate handler. // It returns an exit code and updates c.lastResult when a non-empty result // is produced. The function is split into helpers to keep each branch under diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 250601c..2ad52db 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -364,6 +364,41 @@ func TestMakeActionFn_nil(t *testing.T) { } } +// ---- pickerActionArgv ------------------------------------------------------- + +// TestPickerActionArgv verifies the direct mapping from picker action keys to +// CLI argv commands used by interactive empty-line fzf selection. +func TestPickerActionArgv(t *testing.T) { + desc := "docs/secret.txt" + + cases := []struct { + name string + action store.PickerAction + want []string + }{ + {name: "select", action: store.PickerSelect, want: nil}, + {name: "cat", action: store.PickerCat, want: []string{"cat", desc}}, + {name: "paste", action: store.PickerPaste, want: []string{"paste", desc}}, + {name: "open", action: store.PickerOpen, want: []string{"open", desc}}, + {name: "edit", action: store.PickerEdit, want: []string{"edit", desc}}, + {name: "unknown", action: store.PickerAction("weird"), want: nil}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got := pickerActionArgv(tc.action, desc) + if len(got) != len(tc.want) { + t.Fatalf("pickerActionArgv(%q) len = %d; want %d (%v)", tc.action, len(got), len(tc.want), got) + } + for i := range got { + if got[i] != tc.want[i] { + t.Fatalf("pickerActionArgv(%q)[%d] = %q; want %q", tc.action, i, got[i], tc.want[i]) + } + } + }) + } +} + // ---- remaining dispatchSearch branches -------------------------------------- // TestDispatch_searchActions exercises all SearchActions entries on an empty |
