on main help sign in
refactor(tui): move command loading to uicmd package
commit7918c90ed0587dc67a178f6bd7884b6899387a63 authorAyman Bagabas <ayman.bagabas@gmail.com> dateMon 15 Dec 2025, 17:19 (1 year ago) parent69d3ac9
3 files changed+46−25
internal/tui/components/dialogs/commands/arguments.go+3−12 internal/tui/components/dialogs/commands/commands.go+9−10 internal/tui/components/dialogs/commands/loader.go → internal/uicmd/uicmd.go+34−3
internal/tui/components/dialogs/commands/arguments.go+3−12
@@ -11,6 +11,7 @@ import (
1111 "github.com/charmbracelet/crush/internal/tui/components/dialogs"
1212 "github.com/charmbracelet/crush/internal/tui/styles"
1313 "github.com/charmbracelet/crush/internal/tui/util"
14+ "github.com/charmbracelet/crush/internal/uicmd"
1415)
1516
1617const (
@@ -18,20 +19,10 @@ const (
1819)
1920
2021// ShowArgumentsDialogMsg is a message that is sent to show the arguments dialog.
21−type ShowArgumentsDialogMsg struct {
22− CommandID string
23− Description string
24− ArgNames []string
25− OnSubmit func(args map[string]string) tea.Cmd
26−}
22+type ShowArgumentsDialogMsg = uicmd.ShowArgumentsDialogMsg
2723
2824// CloseArgumentsDialogMsg is a message that is sent when the arguments dialog is closed.
29−type CloseArgumentsDialogMsg struct {
30− Submit bool
31− CommandID string
32− Content string
33− Args map[string]string
34−}
25+type CloseArgumentsDialogMsg = uicmd.CloseArgumentsDialogMsg
3526
3627// CommandArgumentsDialog represents the commands dialog.
3728type CommandArgumentsDialog interface {
internal/tui/components/dialogs/commands/commands.go+9−10
@@ -23,6 +23,7 @@ import (
2323 "github.com/charmbracelet/crush/internal/tui/exp/list"
2424 "github.com/charmbracelet/crush/internal/tui/styles"
2525 "github.com/charmbracelet/crush/internal/tui/util"
26+ "github.com/charmbracelet/crush/internal/uicmd"
2627)
2728
2829const (
@@ -44,13 +45,11 @@ const (
4445type listModel = list.FilterableList[list.CompletionItem[Command]]
4546
4647// Command represents a command that can be executed
47−type Command struct {
48− ID string
49− Title string
50− Description string
51− Shortcut string // Optional shortcut for the command
52− Handler func(cmd Command) tea.Cmd
53−}
48+type (
49+ Command = uicmd.Command
50+ CommandRunCustomMsg = uicmd.CommandRunCustomMsg
51+ ShowMCPPromptArgumentsDialogMsg = uicmd.ShowMCPPromptArgumentsDialogMsg
52+)
5453
5554// CommandsDialog represents the commands dialog.
5655type CommandsDialog interface {
@@ -121,12 +120,12 @@ func NewCommandDialog(sessionID string) CommandsDialog {
121120}
122121
123122func (c *commandDialogCmp) Init() tea.Cmd {
124− commands, err := LoadCustomCommands()
123+ commands, err := uicmd.LoadCustomCommands()
125124 if err != nil {
126125 return util.ReportError(err)
127126 }
128127 c.userCommands = commands
129− c.mcpPrompts.SetSlice(loadMCPPrompts())
128+ c.mcpPrompts.SetSlice(uicmd.LoadMCPPrompts())
130129 return c.setCommandType(c.selected)
131130}
132131
@@ -142,7 +141,7 @@ func (c *commandDialogCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
142141 case pubsub.Event[mcp.Event]:
143142 // Reload MCP prompts when MCP state changes
144143 if msg.Type == pubsub.UpdatedEvent {
145− c.mcpPrompts.SetSlice(loadMCPPrompts())
144+ c.mcpPrompts.SetSlice(uicmd.LoadMCPPrompts())
146145 // If we're currently viewing MCP prompts, refresh the list
147146 if c.selected == MCPPrompts {
148147 return c, c.setCommandType(MCPPrompts)
internal/tui/components/dialogs/commands/loader.go → internal/uicmd/uicmd.gorenamed+34−3
@@ -1,4 +1,7 @@
1−package commands
1+// Package uicmd provides functionality to load and handle custom commands
2+// from markdown files and MCP prompts.
3+// TODO: Move this into internal/ui after refactoring.
4+package uicmd
25
36import (
47 "cmp"
@@ -18,6 +21,31 @@ import (
1821 "github.com/charmbracelet/crush/internal/tui/util"
1922)
2023
24+// Command represents a command that can be executed
25+type Command struct {
26+ ID string
27+ Title string
28+ Description string
29+ Shortcut string // Optional shortcut for the command
30+ Handler func(cmd Command) tea.Cmd
31+}
32+
33+// ShowArgumentsDialogMsg is a message that is sent to show the arguments dialog.
34+type ShowArgumentsDialogMsg struct {
35+ CommandID string
36+ Description string
37+ ArgNames []string
38+ OnSubmit func(args map[string]string) tea.Cmd
39+}
40+
41+// CloseArgumentsDialogMsg is a message that is sent when the arguments dialog is closed.
42+type CloseArgumentsDialogMsg struct {
43+ Submit bool
44+ CommandID string
45+ Content string
46+ Args map[string]string
47+}
48+
2149const (
2250 userCommandPrefix = "user:"
2351 projectCommandPrefix = "project:"
@@ -35,7 +63,10 @@ type commandSource struct {
3563}
3664
3765func LoadCustomCommands() ([]Command, error) {
38− cfg := config.Get()
66+ return LoadCustomCommandsFromConfig(config.Get())
67+}
68+
69+func LoadCustomCommandsFromConfig(cfg *config.Config) ([]Command, error) {
3970 if cfg == nil {
4071 return nil, fmt.Errorf("config not loaded")
4172 }
@@ -221,7 +252,7 @@ type CommandRunCustomMsg struct {
221252 Content string
222253}
223254
224−func loadMCPPrompts() []Command {
255+func LoadMCPPrompts() []Command {
225256 var commands []Command
226257 for mcpName, prompts := range mcp.Prompts() {
227258 for _, prompt := range prompts {