Skip to content

Commit

Permalink
expose custom macros
Browse files Browse the repository at this point in the history
  • Loading branch information
rsteube committed Oct 25, 2023
1 parent 2f027fc commit 86ad1ac
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 5 deletions.
45 changes: 41 additions & 4 deletions action.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package spec
import (
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
Expand Down Expand Up @@ -47,14 +48,50 @@ func (value) JSONSchema() *jsonschema.Schema {
}
}

func executable() string {
s, err := os.Executable()
if err != nil {
panic(err.Error()) // TODO handle error, eval symlink, how to handle "go test"
}

return filepath.Base(s)
}

// ActionMacro completes given macro
func ActionMacro(s string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
m, err := macros.Lookup(s)
if err != nil {
return carapace.ActionMessage(err.Error())
r := regexp.MustCompile(`^\$(?P<macro>[^(]*)(\((?P<arg>.*)\))?$`)
matches := r.FindStringSubmatch(s)
if matches == nil {
return carapace.ActionMessage("malformed macro: %#v", s)
}
if strings.HasPrefix(matches[1], "_") && !strings.HasPrefix(matches[1], "_.") {
return carapace.ActionMessage(`"$_" deprecated: replace %#v with %#v`, "$"+matches[1], "$carapace."+strings.TrimPrefix(matches[1], "_"))
}
prefix := fmt.Sprintf("$%v.", executable())

switch {
case !strings.HasPrefix(matches[1], "_.") && strings.Contains(matches[1], ".") && !strings.HasPrefix(s, prefix):
splitted := strings.SplitN(strings.TrimPrefix(s, "$"), ".", 2)
args := []string{"_carapace", "macro"}
args = append(args, splitted[1])
args = append(args, c.Args...)
args = append(args, c.Value)
carapace.LOG.Printf("%#v", args)
return carapace.ActionExecCommand(splitted[0], args...)(func(output []byte) carapace.Action {
return carapace.ActionImport(output)
})

default:
if strings.HasPrefix(s, prefix) {
s = "$_." + strings.TrimPrefix(s, prefix)
}
m, err := macros.Lookup(s)
if err != nil {
return carapace.ActionMessage(err.Error())
}
return m.Parse(s)
}
return m.Parse(s)
})
}

Expand Down
4 changes: 4 additions & 0 deletions cmd/carapace-spec/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ func init() {
default:
cmd.Flags().Parse(args[:1]) // TODO unnecessary
}

})

spec.AddMacro("Spec", spec.MacroI(spec.ActionSpec))
spec.Register(rootCmd)
}

func bridgeCompletion(cmd *cobra.Command, spec string, args ...string) {
Expand Down
2 changes: 1 addition & 1 deletion macro.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func addCoreMacro(s string, m Macro) {

// AddMacro adds a custom macro
func AddMacro(s string, m Macro) {
macros["_"+s] = m
macros["_."+s] = m
}

func MacroN(f func() carapace.Action) Macro {
Expand Down
80 changes: 80 additions & 0 deletions register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package spec

import (
"fmt"
"sort"
"strings"

"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

func Register(cmd *cobra.Command) {
carapace.Gen(cmd)

carapaceCmd, _, err := cmd.Find([]string{"_carapace"})
if err != nil {
panic(err.Error()) // TODO handle err
}

macroCmd := &cobra.Command{
Use: "macro",
RunE: func(cmd *cobra.Command, args []string) error {
switch len(args) {
case 0:
keys := make([]string, 0, len(macros))
for k := range macros {
keys = append(keys, k)
}
sort.Strings(keys)

for _, key := range keys {
if strings.HasPrefix(key, "_") {
fmt.Fprintln(cmd.OutOrStdout(), strings.TrimPrefix(key, "_"))
}
}
case 1:
m, ok := macros["_."+args[0]]
if !ok {
return fmt.Errorf("unknown macro: %v", args[0])
}
fmt.Fprintln(cmd.OutOrStdout(), m.Signature())
default:
mCmd := &cobra.Command{
DisableFlagParsing: true,
}
carapace.Gen(mCmd).Standalone()
carapace.Gen(mCmd).PositionalAnyCompletion(
ActionMacro("$_." + args[0]),
)
carapace.LOG.Printf("%#v", args)
mCmd.SetArgs(append([]string{"_carapace", "export", ""}, args[1:]...))
mCmd.SetOut(cmd.OutOrStdout())
mCmd.SetErr(cmd.ErrOrStderr())
return mCmd.Execute()
}
return nil
},
DisableFlagParsing: true,
}

carapaceCmd.AddCommand(macroCmd) // TODO this currently does not work when bridged using a spec

carapace.Gen(macroCmd).PositionalCompletion(
carapace.ActionCallback(func(c carapace.Context) carapace.Action {
vals := make([]string, 0, len(macros))
for key := range macros {
if strings.HasPrefix(key, "_.") {
vals = append(vals, strings.TrimPrefix(key, "_."))
}
}
return carapace.ActionValues(vals...).MultiParts(".")
}),
)

carapace.Gen(macroCmd).PositionalAnyCompletion(
carapace.ActionCallback(func(c carapace.Context) carapace.Action {
return ActionMacro("$_." + c.Args[0]).Shift(1)
}),
)
}

0 comments on commit 86ad1ac

Please sign in to comment.