From 688811533af55fbac74972b17549326c7bb72d2f Mon Sep 17 00:00:00 2001 From: nobe4 Date: Wed, 2 Oct 2024 13:34:45 +0200 Subject: [PATCH] feat(actions): allow passing string parameters to actions This prepares later work for #187. Passing parameter will enable additional customization in the REPL and later in the config as well. Only the `Debug` action currently uses this new parameter, to confirm it's receiving it correctly. Also have to do some workaround a bubble limitation, see https://github.com/charmbracelet/bubbles/pull/630 --- internal/actions/actions.go | 2 +- internal/actions/debug/debug.go | 5 ++-- internal/actions/done/done.go | 2 +- internal/actions/hide/hide.go | 2 +- internal/actions/open/open.go | 2 +- internal/actions/pass/pass.go | 2 +- internal/actions/print/print.go | 2 +- internal/actions/read/read.go | 2 +- internal/manager/manager.go | 2 +- internal/repl/command.go | 45 ++++++++++++++++++++++++++++----- internal/repl/handlers.go | 2 +- internal/repl/repl.go | 6 ++--- 12 files changed, 53 insertions(+), 21 deletions(-) diff --git a/internal/actions/actions.go b/internal/actions/actions.go index 69fbd39..d2c2638 100644 --- a/internal/actions/actions.go +++ b/internal/actions/actions.go @@ -29,5 +29,5 @@ func Map(client *gh.Client) ActionsMap { } type Runner interface { - Run(*notifications.Notification, io.Writer) error + Run(*notifications.Notification, []string, io.Writer) error } diff --git a/internal/actions/debug/debug.go b/internal/actions/debug/debug.go index a531abe..1c05600 100644 --- a/internal/actions/debug/debug.go +++ b/internal/actions/debug/debug.go @@ -6,6 +6,7 @@ package debug import ( "fmt" "io" + "strings" "github.com/nobe4/gh-not/internal/colors" "github.com/nobe4/gh-not/internal/notifications" @@ -13,8 +14,8 @@ import ( type Runner struct{} -func (_ *Runner) Run(n *notifications.Notification, w io.Writer) error { - fmt.Fprint(w, colors.Yellow("DEBUG ")+n.String()) +func (_ *Runner) Run(n *notifications.Notification, args []string, w io.Writer) error { + fmt.Fprint(w, colors.Yellow("DEBUG ")+n.String()+" "+strings.Join(args, ", ")) return nil } diff --git a/internal/actions/done/done.go b/internal/actions/done/done.go index 479548e..7e6a240 100644 --- a/internal/actions/done/done.go +++ b/internal/actions/done/done.go @@ -21,7 +21,7 @@ type Runner struct { Client *gh.Client } -func (a *Runner) Run(n *notifications.Notification, w io.Writer) error { +func (a *Runner) Run(n *notifications.Notification, _ []string, w io.Writer) error { slog.Debug("marking notification as done", "notification", n) n.Meta.Done = true diff --git a/internal/actions/hide/hide.go b/internal/actions/hide/hide.go index c39e67c..1982647 100644 --- a/internal/actions/hide/hide.go +++ b/internal/actions/hide/hide.go @@ -15,7 +15,7 @@ import ( type Runner struct{} -func (_ *Runner) Run(n *notifications.Notification, w io.Writer) error { +func (_ *Runner) Run(n *notifications.Notification, _ []string, w io.Writer) error { slog.Debug("marking notification as hidden", "notification", n.Id) n.Meta.Hidden = true diff --git a/internal/actions/open/open.go b/internal/actions/open/open.go index c55b231..baa3b7f 100644 --- a/internal/actions/open/open.go +++ b/internal/actions/open/open.go @@ -18,7 +18,7 @@ type Runner struct { Client *gh.Client } -func (a *Runner) Run(n *notifications.Notification, w io.Writer) error { +func (a *Runner) Run(n *notifications.Notification, _ []string, w io.Writer) error { slog.Debug("open notification in browser", "notification", n) browser := browser.New("", w, w) diff --git a/internal/actions/pass/pass.go b/internal/actions/pass/pass.go index 6909b91..f1d2310 100644 --- a/internal/actions/pass/pass.go +++ b/internal/actions/pass/pass.go @@ -11,6 +11,6 @@ import ( type Runner struct{} -func (_ *Runner) Run(n *notifications.Notification, _ io.Writer) error { +func (_ *Runner) Run(n *notifications.Notification, _ []string, _ io.Writer) error { return nil } diff --git a/internal/actions/print/print.go b/internal/actions/print/print.go index ca454ba..63547b7 100644 --- a/internal/actions/print/print.go +++ b/internal/actions/print/print.go @@ -12,7 +12,7 @@ import ( type Runner struct{} -func (_ *Runner) Run(n *notifications.Notification, w io.Writer) error { +func (_ *Runner) Run(n *notifications.Notification, _ []string, w io.Writer) error { if !n.Meta.Hidden { fmt.Fprint(w, n.String()) } diff --git a/internal/actions/read/read.go b/internal/actions/read/read.go index 4b75f31..e88f425 100644 --- a/internal/actions/read/read.go +++ b/internal/actions/read/read.go @@ -19,7 +19,7 @@ type Runner struct { Client *gh.Client } -func (a *Runner) Run(n *notifications.Notification, w io.Writer) error { +func (a *Runner) Run(n *notifications.Notification, _ []string, w io.Writer) error { _, err := a.Client.API.Request(http.MethodPatch, n.URL, nil) // go-gh currently fails to handle HTTP-205 correctly, however it's possible diff --git a/internal/manager/manager.go b/internal/manager/manager.go index b66c3a8..ec443bb 100644 --- a/internal/manager/manager.go +++ b/internal/manager/manager.go @@ -128,7 +128,7 @@ func (m *Manager) Apply() error { continue } - if err := runner.Run(notification, os.Stdout); err != nil { + if err := runner.Run(notification, nil, os.Stdout); err != nil { slog.Error("action failed", "action", rule.Action, "err", err) } fmt.Fprintln(os.Stdout, "") diff --git a/internal/repl/command.go b/internal/repl/command.go index 489d23a..913861d 100644 --- a/internal/repl/command.go +++ b/internal/repl/command.go @@ -6,18 +6,45 @@ import ( "strings" tea "github.com/charmbracelet/bubbletea" + "github.com/nobe4/gh-not/internal/actions" ) +type Run struct { + Runner actions.Runner + Args []string +} + +func (m model) commandAndArgs(value, suggestion string) (string, []string) { + if value == suggestion { + return value, nil + } + + values := strings.Split(value, " ") + command, args := values[0], values[1:] + + // Manually get the new suggestion + m.command.SetValue(command) + // Workaround until https://github.com/charmbracelet/bubbles/pull/630 is + // merged. + m.command.SetSuggestions(m.command.AvailableSuggestions()) + command = m.command.CurrentSuggestion() + + return command, args +} + func (m model) acceptCommand() (tea.Model, tea.Cmd) { - command := m.command.CurrentSuggestion() + command, args := m.commandAndArgs( + m.command.Value(), + m.command.CurrentSuggestion(), + ) - slog.Debug("acceptCommand", "command", command) + slog.Debug("acceptCommand", "command", command, "args", args) m.command.SetValue("") m.command.Blur() m.showResult = true - return m, m.applyCommand(command) + return m, m.applyCommand(command, args) } func (m model) cancelCommand() (tea.Model, tea.Cmd) { @@ -32,9 +59,10 @@ func (m model) cancelCommand() (tea.Model, tea.Cmd) { type ApplyCommandMsg struct { Items []item Command string + Args []string } -func (m model) applyCommand(command string) tea.Cmd { +func (m model) applyCommand(command string, args []string) tea.Cmd { return func() tea.Msg { slog.Debug("applyCommand", "command", command) @@ -46,7 +74,7 @@ func (m model) applyCommand(command string) tea.Cmd { } } - return ApplyCommandMsg{Items: selected, Command: command} + return ApplyCommandMsg{Items: selected, Command: command, Args: args} } } @@ -59,7 +87,10 @@ func (msg ApplyCommandMsg) apply(m model) (tea.Model, tea.Cmd) { } m.resultStrings = []string{} - m.currentRunner = runner + m.currentRun = Run{ + Runner: runner, + Args: msg.Args, + } m.processQueue = msg.Items return m, tea.Sequence(m.renderResult(nil), m.applyNext()) @@ -93,7 +124,7 @@ func (m model) applyNext() tea.Cmd { message := "" out := &strings.Builder{} - if err := m.currentRunner.Run(current.notification, out); err != nil { + if err := m.currentRun.Runner.Run(current.notification, m.currentRun.Args, out); err != nil { message = fmt.Sprintf("Error for '%s': %s", current.notification.Subject.Title, err.Error()) } else { message = out.String() diff --git a/internal/repl/handlers.go b/internal/repl/handlers.go index 2463f78..b2dcea8 100644 --- a/internal/repl/handlers.go +++ b/internal/repl/handlers.go @@ -108,7 +108,7 @@ func (m *model) handleBrowsing(msg tea.KeyMsg) (tea.Model, tea.Cmd) { case key.Matches(msg, m.keymap.Open): current, ok := m.list.SelectedItem().(item) if ok { - m.actions["open"].Run(current.notification, os.Stderr) + m.actions["open"].Run(current.notification, nil, os.Stderr) } case key.Matches(msg, m.keymap.CommandMode): diff --git a/internal/repl/repl.go b/internal/repl/repl.go index c52b004..ce84d2d 100644 --- a/internal/repl/repl.go +++ b/internal/repl/repl.go @@ -13,9 +13,9 @@ import ( ) type model struct { - keymap Keymap - actions actions.ActionsMap - currentRunner actions.Runner + keymap Keymap + actions actions.ActionsMap + currentRun Run showHelp bool list list.Model