mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-14 03:30:26 +00:00
feat(ui): populate input instead of auto-submitting prompts with args
- Add HasArgPlaceholders() method to PromptTemplate to detect , $@, $ARGUMENTS, etc. placeholders in template content - Add HasArgs field to SlashCommand struct - Set HasArgs when registering prompt templates as slash commands - In fuzzy finder Enter handler, populate input with command + trailing space when HasArgs is true, letting the user type arguments naturally - Fix potential index bug by capturing selectedCmd before resetting index
This commit is contained in:
@@ -266,6 +266,12 @@ func joinArgsRange(args []string, start, length int) string {
|
||||
return strings.Join(args[start:end], " ")
|
||||
}
|
||||
|
||||
// HasArgPlaceholders reports whether the template content contains any
|
||||
// argument placeholders ($1, $@, $ARGUMENTS, ${@:...}, etc.).
|
||||
func (t *PromptTemplate) HasArgPlaceholders() bool {
|
||||
return argPlaceholder.MatchString(t.Content)
|
||||
}
|
||||
|
||||
// Expand substitutes arguments into the template content and returns the result.
|
||||
// It first parses args from the input string, then substitutes them into the template.
|
||||
func (t *PromptTemplate) Expand(argsInput string) string {
|
||||
|
||||
@@ -213,3 +213,31 @@ func TestPromptTemplateExpand(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasArgPlaceholders(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
want bool
|
||||
}{
|
||||
{"no placeholders", "Just a plain prompt with no args", false},
|
||||
{"$1 placeholder", "Create a $1 component", true},
|
||||
{"$@ placeholder", "Run with args: $@", true},
|
||||
{"$ARGUMENTS placeholder", "Features: $ARGUMENTS", true},
|
||||
{"${1} placeholder", "Name: ${1}", true},
|
||||
{"${ARGUMENTS} placeholder", "All: ${ARGUMENTS}", true},
|
||||
{"${@:1} placeholder", "Rest: ${@:1}", true},
|
||||
{"${@:1:2} placeholder", "Slice: ${@:1:2}", true},
|
||||
{"dollar in text", "Cost is one hundred dollars", false},
|
||||
{"empty content", "", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tpl := &PromptTemplate{Content: tt.content}
|
||||
if got := tpl.HasArgPlaceholders(); got != tt.want {
|
||||
t.Errorf("HasArgPlaceholders() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ type SlashCommand struct {
|
||||
Aliases []string
|
||||
Category string // e.g., "Navigation", "System", "Info"
|
||||
Complete func(prefix string) []string // optional argument tab-completion
|
||||
HasArgs bool // true when the command expects arguments (e.g. prompt templates with placeholders)
|
||||
}
|
||||
|
||||
// SlashCommands provides the global registry of all available slash commands
|
||||
|
||||
+12
-3
@@ -285,16 +285,25 @@ func (s *InputComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
s.textarea.CursorEnd()
|
||||
return s, nil
|
||||
}
|
||||
selectedCmd := s.filtered[s.selected].Command
|
||||
// Populate textarea with selected item and submit on next tick.
|
||||
if s.argMode {
|
||||
s.textarea.SetValue(s.argCommand + " " + s.filtered[s.selected].Command.Name)
|
||||
s.textarea.SetValue(s.argCommand + " " + selectedCmd.Name)
|
||||
} else {
|
||||
s.textarea.SetValue(s.filtered[s.selected].Command.Name)
|
||||
s.textarea.SetValue(selectedCmd.Name)
|
||||
}
|
||||
s.textarea.CursorEnd()
|
||||
s.showPopup = false
|
||||
s.selected = 0
|
||||
s.submitNext = true
|
||||
// If the selected command expects arguments, populate
|
||||
// the input with the command + trailing space so the
|
||||
// user can type args, instead of auto-submitting.
|
||||
if !s.argMode && selectedCmd.HasArgs {
|
||||
s.textarea.SetValue(selectedCmd.Name + " ")
|
||||
s.textarea.CursorEnd()
|
||||
} else {
|
||||
s.submitNext = true
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
return s, nil
|
||||
|
||||
@@ -827,6 +827,7 @@ func NewAppModel(appCtrl AppController, opts AppModelOptions) *AppModel {
|
||||
Name: "/" + tpl.Name,
|
||||
Description: tpl.Description,
|
||||
Category: "Prompts",
|
||||
HasArgs: tpl.HasArgPlaceholders(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2932,6 +2933,7 @@ func (m *AppModel) refreshPromptTemplates() {
|
||||
Name: "/" + tpl.Name,
|
||||
Description: tpl.Description,
|
||||
Category: "Prompts",
|
||||
HasArgs: tpl.HasArgPlaceholders(),
|
||||
})
|
||||
}
|
||||
ic.commands = kept
|
||||
|
||||
Reference in New Issue
Block a user