diff --git a/completers/dagger_completer/cmd/call.go b/completers/dagger_completer/cmd/call.go
index 21100e4843..c47b4f83a0 100644
--- a/completers/dagger_completer/cmd/call.go
+++ b/completers/dagger_completer/cmd/call.go
@@ -15,6 +15,7 @@ var callCmd = &cobra.Command{
func init() {
carapace.Gen(callCmd).Standalone()
+ callCmd.Flags().SetInterspersed(false)
callCmd.PersistentFlags().Bool("focus", false, "Only show output for focused commands")
callCmd.PersistentFlags().Bool("json", false, "Present result as JSON")
diff --git a/completers/dagger_completer/cmd/functions.go b/completers/dagger_completer/cmd/functions.go
index d4f114d085..09a5d58759 100644
--- a/completers/dagger_completer/cmd/functions.go
+++ b/completers/dagger_completer/cmd/functions.go
@@ -17,6 +17,7 @@ func init() {
carapace.Gen(functionsCmd).Standalone()
functionsCmd.PersistentFlags().Bool("focus", false, "Only show output for focused commands")
+ functionsCmd.PersistentFlags().Bool("json", false, "Output as json")
functionsCmd.PersistentFlags().StringP("mod", "m", "", "Path to dagger.json config file for the module or a directory containing that file. Either local path (e.g. \"/path/to/some/dir\") or a github repo (e.g. \"github.com/dagger/dagger/path/to/some/subdir\")")
rootCmd.AddCommand(functionsCmd)
diff --git a/completers/dagger_completer/cmd/run.go b/completers/dagger_completer/cmd/run.go
index 54ee2e7935..1d21721f52 100644
--- a/completers/dagger_completer/cmd/run.go
+++ b/completers/dagger_completer/cmd/run.go
@@ -2,6 +2,7 @@ package cmd
import (
"github.com/rsteube/carapace"
+ "github.com/rsteube/carapace-bridge/pkg/actions/bridge"
"github.com/spf13/cobra"
)
@@ -15,8 +16,13 @@ var runCmd = &cobra.Command{
func init() {
carapace.Gen(runCmd).Standalone()
+ runCmd.Flags().SetInterspersed(false)
runCmd.Flags().String("cleanup-timeout", "", "max duration to wait between SIGTERM and SIGKILL on interrupt")
runCmd.Flags().Bool("focus", false, "Only show output for focused commands.")
rootCmd.AddCommand(runCmd)
+
+ carapace.Gen(runCmd).PositionalAnyCompletion(
+ bridge.ActionCarapaceBin(),
+ )
}
diff --git a/pkg/actions/tools/dagger/function.go b/pkg/actions/tools/dagger/function.go
index 6fc38d322a..9d97e12df8 100644
--- a/pkg/actions/tools/dagger/function.go
+++ b/pkg/actions/tools/dagger/function.go
@@ -1,27 +1,134 @@
package dagger
import (
- "regexp"
- "strings"
+ "encoding/json"
+ "os"
+ "time"
+ "unicode"
"github.com/rsteube/carapace"
+ "github.com/rsteube/carapace/pkg/cache"
+ "github.com/rsteube/carapace/pkg/cache/key"
+ "github.com/spf13/cobra"
)
-// ActionFunctions completes functions
+type function struct {
+ Name string `json:"Name"`
+ Description string `json:"Description"`
+ Args []struct {
+ Name string `json:"Name"`
+ Description string `json:"Description"`
+ TypeDef struct {
+ Kind string `json:"Kind"`
+ Optional bool `json:"Optional"`
+ AsObject *struct {
+ Name string `json:"Name"`
+ Functions any `json:"Functions"`
+ Fields any `json:"Fields"`
+ Constructor any `json:"Constructor"`
+ SourceModuleName string `json:"SourceModuleName"`
+ } `json:"AsObject"`
+ AsInterface any `json:"AsInterface"`
+ AsInput any `json:"AsInput"`
+ AsList any `json:"AsList"`
+ } `json:"TypeDef"`
+ DefaultValue string `json:"DefaultValue"`
+ } `json:"Args"`
+}
+
+type daggerFile struct {
+ Name string
+ Sdk string
+ Source string
+}
+
+// ActionFunctions completes functions and their arguments
//
-// container-echo (dagger call container-echo --string-arg yo stdout)
// grep-dir (dagger call grep-dir --directory-arg . --pattern GrepDir)
+// --directory-arg
func ActionFunctions() carapace.Action {
- return carapace.ActionExecCommand("dagger", "functions", "--silent")(func(output []byte) carapace.Action {
- lines := strings.Split(string(output), "\n")
- r := regexp.MustCompile(`^(?P[^ ]+) +example usage: "(?P.*)"$`)
-
- vals := make([]string, 0)
- for _, line := range lines[1:] {
- if matches := r.FindStringSubmatch(line); matches != nil {
- vals = append(vals, matches[1], matches[2])
+ return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
+ content, err := os.ReadFile("dagger.json")
+ if err != nil {
+ return carapace.ActionMessage(err.Error())
+ }
+
+ var d daggerFile
+ if err := json.Unmarshal(content, &d); err != nil {
+ return carapace.ActionMessage(err.Error())
+ }
+
+ output, err := cache.Cache(24*time.Hour, key.FolderStats(d.Source))(func() ([]byte, error) {
+ return c.Command("dagger", "functions", "--json").Output()
+ })
+ if err != nil {
+ return carapace.ActionMessage(err.Error())
+ }
+
+ var functions []function
+ if err := json.Unmarshal(output, &functions); err != nil {
+ return carapace.ActionMessage(err.Error())
+ }
+
+ cmd := &cobra.Command{}
+ carapace.Gen(cmd).Standalone()
+ for _, f := range functions {
+ f.Name = toKebab(f.Name)
+ subCmd := &cobra.Command{
+ Use: f.Name,
+ Short: f.Description,
+ Run: func(cmd *cobra.Command, args []string) {},
}
+ carapace.Gen(subCmd).Standalone()
+
+ for _, arg := range f.Args {
+ arg.Name = toKebab(arg.Name)
+
+ // TODO transform camelcase to kebab
+ switch arg.TypeDef.Kind { // TODO more types
+ case "STRING_KIND", "OBJECT_KIND":
+ subCmd.Flags().String(arg.Name, arg.DefaultValue, arg.Description)
+ default:
+ return carapace.ActionMessage("unknown kind %s", arg.TypeDef.Kind)
+ }
+
+ if arg.TypeDef.Optional {
+ subCmd.Flag(arg.Name).NoOptDefVal = " "
+ }
+
+ localArg := arg
+ carapace.Gen(subCmd).FlagCompletion(carapace.ActionMap{
+ arg.Name: carapace.ActionCallback(func(c carapace.Context) carapace.Action {
+ if localArg.TypeDef.AsObject == nil {
+ return carapace.ActionValues()
+ }
+
+ switch localArg.TypeDef.AsObject.Name { // TODO more
+ case "Directory":
+ return carapace.ActionDirectories()
+ case "File":
+ return carapace.ActionFiles()
+ default:
+ return carapace.ActionValues()
+ }
+ }),
+ })
+ }
+
+ cmd.AddCommand(subCmd)
}
- return carapace.ActionValuesDescribed(vals...)
+
+ return carapace.ActionExecute(cmd)
})
}
+
+func toKebab(s string) string {
+ runes := make([]rune, 0)
+ for _, r := range []rune(s) {
+ if unicode.IsUpper(r) {
+ runes = append(runes, '-')
+ }
+ runes = append(runes, unicode.ToLower(r))
+ }
+ return string(runes)
+}