feat(recipe): add --param flag support and improve project root detection
- Introduce --param/-p flag to pass key=value parameters to recipes, parsed into a map with basic bool handling. - Expand findProjectRoot to detect more project types (e.g., .gitignore, pyproject.toml, CMakeLists.txt). - Clean up comments and minor refactoring in recipe resolution logic.
This commit is contained in:
parent
18bbb67789
commit
95deb65f06
@ -25,7 +25,10 @@ var runCmd = &cobra.Command{
|
|||||||
RunE: runRecipe,
|
RunE: runRecipe,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var paramFlags []string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
runCmd.Flags().StringSliceVarP(¶mFlags, "param", "p", nil, "key=value parameters for the recipe (can be repeated)")
|
||||||
recipeCmd.AddCommand(runCmd)
|
recipeCmd.AddCommand(runCmd)
|
||||||
rootCmd.AddCommand(recipeCmd)
|
rootCmd.AddCommand(recipeCmd)
|
||||||
}
|
}
|
||||||
@ -38,15 +41,28 @@ func runRecipe(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add --param support later; for now YAML defaults work
|
// Parse --param key=value into map
|
||||||
params := make(map[string]any)
|
params := make(map[string]any)
|
||||||
|
for _, p := range paramFlags {
|
||||||
|
if kv := strings.SplitN(p, "=", 2); len(kv) == 2 {
|
||||||
|
key := strings.TrimSpace(kv[0])
|
||||||
|
value := strings.TrimSpace(kv[1])
|
||||||
|
// simple bool detection
|
||||||
|
if value == "true" {
|
||||||
|
params[key] = true
|
||||||
|
} else if value == "false" {
|
||||||
|
params[key] = false
|
||||||
|
} else {
|
||||||
|
params[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r, err := recipe.Load(recipePath, params)
|
r, err := recipe.Load(recipePath, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load recipe: %w", err)
|
return fmt.Errorf("failed to load recipe: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// respect -m/--model flag + config exactly like every other command
|
|
||||||
flagModel, _ := cmd.Flags().GetString("model")
|
flagModel, _ := cmd.Flags().GetString("model")
|
||||||
model := config.GetModel("recipe", flagModel)
|
model := config.GetModel("recipe", flagModel)
|
||||||
|
|
||||||
@ -56,9 +72,8 @@ func runRecipe(cmd *cobra.Command, args []string) error {
|
|||||||
return runner.Run()
|
return runner.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveRecipePath implements exactly the rules you specified
|
// resolveRecipePath and findProjectRoot stay exactly as you already have them
|
||||||
func resolveRecipePath(nameOrPath string) (string, error) {
|
func resolveRecipePath(nameOrPath string) (string, error) {
|
||||||
// explicit path wins immediately
|
|
||||||
if strings.Contains(nameOrPath, "/") || strings.HasSuffix(nameOrPath, ".md") {
|
if strings.Contains(nameOrPath, "/") || strings.HasSuffix(nameOrPath, ".md") {
|
||||||
if _, err := os.Stat(nameOrPath); err == nil {
|
if _, err := os.Stat(nameOrPath); err == nil {
|
||||||
return nameOrPath, nil
|
return nameOrPath, nil
|
||||||
@ -66,12 +81,10 @@ func resolveRecipePath(nameOrPath string) (string, error) {
|
|||||||
return "", fmt.Errorf("recipe file not found: %s", nameOrPath)
|
return "", fmt.Errorf("recipe file not found: %s", nameOrPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalise to .md
|
|
||||||
if !strings.HasSuffix(nameOrPath, ".md") {
|
if !strings.HasSuffix(nameOrPath, ".md") {
|
||||||
nameOrPath += ".md"
|
nameOrPath += ".md"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Project-local first (primary source of truth)
|
|
||||||
projectRoot, err := findProjectRoot()
|
projectRoot, err := findProjectRoot()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
local := filepath.Join(projectRoot, ".grokkit", "recipes", nameOrPath)
|
local := filepath.Join(projectRoot, ".grokkit", "recipes", nameOrPath)
|
||||||
@ -80,7 +93,6 @@ func resolveRecipePath(nameOrPath string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Global XDG fallback with confirmation
|
|
||||||
global := filepath.Join(os.Getenv("HOME"), ".local", "share", "grokkit", "recipes", nameOrPath)
|
global := filepath.Join(os.Getenv("HOME"), ".local", "share", "grokkit", "recipes", nameOrPath)
|
||||||
if _, err := os.Stat(global); err == nil {
|
if _, err := os.Stat(global); err == nil {
|
||||||
fmt.Printf("Recipe %q not found in project.\nFound globally at %s\nUse this one? [y/N] ", nameOrPath, global)
|
fmt.Printf("Recipe %q not found in project.\nFound globally at %s\nUse this one? [y/N] ", nameOrPath, global)
|
||||||
@ -97,7 +109,6 @@ func resolveRecipePath(nameOrPath string) (string, error) {
|
|||||||
return "", fmt.Errorf("recipe %q not found in project or global store", nameOrPath)
|
return "", fmt.Errorf("recipe %q not found in project or global store", nameOrPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tiny helper used by almost every command already
|
|
||||||
func findProjectRoot() (string, error) {
|
func findProjectRoot() (string, error) {
|
||||||
dir, err := os.Getwd()
|
dir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,10 +118,19 @@ func findProjectRoot() (string, error) {
|
|||||||
if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
|
if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
|
||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
if _, err := os.Stat(filepath.Join(dir, ".grokkit")); err == nil {
|
||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(filepath.Join(dir, ".grokkit")); err == nil {
|
if _, err := os.Stat(filepath.Join(dir, ".gitignore")); err == nil {
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "pyproject.toml")); err == nil {
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "CmakeLists.txt")); err == nil {
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
parent := filepath.Dir(dir)
|
parent := filepath.Dir(dir)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user