Skip to content

Commit

Permalink
Merge pull request #30 from rsteube/macros
Browse files Browse the repository at this point in the history
macros
  • Loading branch information
rsteube authored May 5, 2022
2 parents ede71e0 + 798caac commit 4845591
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 60 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18

- name: Build
run: go build -v ./...
Expand All @@ -34,7 +34,7 @@ jobs:
run: '[ "$(gofmt -d -s . | tee -a /dev/stderr)" = "" ]'

- name: "staticcheck"
run: go install honnef.co/go/tools/cmd/staticcheck@2021.1.1 && staticcheck ./...
run: go install honnef.co/go/tools/cmd/staticcheck@latest && staticcheck ./...

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
cmd/carapace-spec/carapace-spec
dist
docs/book
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/rsteube/carapace-spec

go 1.17
go 1.18

replace github.com/spf13/pflag => github.com/cornfeedhobo/pflag v1.1.0

Expand Down
65 changes: 61 additions & 4 deletions macro.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,66 @@
package spec

import "github.com/rsteube/carapace"
import (
"fmt"
"reflect"
"regexp"

var macros = make(map[string]func(string) carapace.Action)
"github.com/rsteube/carapace"
"gopkg.in/yaml.v3"
)

func AddMacro(s string, f func(string) carapace.Action) {
macros[s] = f
type Macro func(string) carapace.Action

var macros = make(map[string]Macro)

func addCoreMacro(s string, m Macro) {
macros[s] = m
}

func AddMacro(s string, m Macro) {
macros["_"+s] = m
}

func parseMacro(s string) carapace.Action {
r := regexp.MustCompile(`^\$(?P<macro>[^(]*)(\((?P<arg>.*)\))?$`)
if !r.MatchString(s) {
return carapace.ActionMessage(fmt.Sprintf("malformed macro: '%v'", s))
}

matches := findNamedMatches(r, s)
if m, ok := macros[matches["macro"]]; !ok {
return carapace.ActionMessage(fmt.Sprintf("unknown macro: '%v'", s))
} else {
return m(matches["arg"])
}
}

func MacroN(f func() carapace.Action) Macro {
return func(s string) carapace.Action {
return f()
}
}

func MacroI[T any](f func(t T) carapace.Action) Macro {
return func(s string) carapace.Action {
var t T
if err := yaml.Unmarshal([]byte(s), &t); err != nil {
return carapace.ActionMessage(err.Error())
}
return f(t)
}
}

func MacroVarI[T any](f func(s ...T) carapace.Action) Macro {
return func(s string) carapace.Action {
if s == "" {
return f()
}

var t []T
if err := yaml.Unmarshal([]byte(s), &t); err != nil {
return carapace.ActionMessage(fmt.Sprintf("malformed macro arg: '%v', expected '%v'", s, reflect.TypeOf(t)))
}
return f(t...)
}
}
92 changes: 39 additions & 53 deletions spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,66 +73,52 @@ func (c *Command) ToCobra() *cobra.Command {

func parseAction(cmd *cobra.Command, arr []string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
rMacro := regexp.MustCompile(`^\$(?P<macro>[^(]*)(\((?P<arg>.*)\))?$`)
listDelimiter := ""
nospace := false

// TODO don't alter the map each time, solve this differently
addCoreMacro("list", func(s string) carapace.Action {
listDelimiter = s
return carapace.ActionValues()
})
addCoreMacro("nospace", func(s string) carapace.Action {
nospace = true
return carapace.ActionValues()
})
addCoreMacro("files", MacroVarI(carapace.ActionFiles))
addCoreMacro("directories", MacroN(carapace.ActionDirectories))
addCoreMacro("", func(s string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
for index, arg := range c.Args {
c.Setenv(fmt.Sprintf("CARAPACE_ARG%v", index), arg)
}
for index, arg := range c.Parts {
c.Setenv(fmt.Sprintf("CARAPACE_PART%v", index), arg)
}
c.Setenv("CARAPACE_CALLBACK", c.CallbackValue)

cmd.Flags().Visit(func(f *pflag.Flag) {
c.Setenv(fmt.Sprintf("CARAPACE_FLAG_%v", strings.ToUpper(f.Name)), f.Value.String())
})

return carapace.ActionExecCommand("sh", "-c", s)(func(output []byte) carapace.Action {
lines := strings.Split(string(output), "\n")
vals := make([]string, 0)
for _, line := range lines {
if line != "" {
vals = append(vals, parseValue(line)...)
}
}
return carapace.ActionStyledValuesDescribed(vals...)
}).Invoke(c).ToA()
})
})

batch := carapace.Batch()
vals := make([]string, 0)
for _, elem := range arr {
if strings.HasPrefix(elem, "$") { // macro
match := findNamedMatches(rMacro, elem) // TODO check if matches
macro := match["macro"]
arg := match["arg"]

if strings.HasPrefix(macro, "_") { // custom macro
if f := macros[strings.TrimPrefix(macro, "_")]; f != nil {
batch = append(batch, carapace.ActionCallback(func(c carapace.Context) carapace.Action { return f(arg) }))
continue
}
return carapace.ActionMessage(fmt.Sprintf("unknown custom macro: '%v'", elem))
}

switch macro {
case "nospace":
nospace = true
case "list":
listDelimiter = arg
case "directories":
return carapace.ActionDirectories()
case "files":
if arg != "" {
batch = append(batch, carapace.ActionFiles(strings.Fields(arg)...))
}
batch = append(batch, carapace.ActionFiles())
case "":
batch = append(batch, carapace.ActionCallback(func(c carapace.Context) carapace.Action {
for index, arg := range c.Args {
c.Setenv(fmt.Sprintf("CARAPACE_ARG%v", index), arg)
}
for index, arg := range c.Parts {
c.Setenv(fmt.Sprintf("CARAPACE_PART%v", index), arg)
}
c.Setenv("CARAPACE_CALLBACK", c.CallbackValue)

cmd.Flags().Visit(func(f *pflag.Flag) {
c.Setenv(fmt.Sprintf("CARAPACE_FLAG_%v", strings.ToUpper(f.Name)), f.Value.String())
})

return carapace.ActionExecCommand("sh", "-c", arg)(func(output []byte) carapace.Action {
lines := strings.Split(string(output), "\n")
vals := make([]string, 0)
for _, line := range lines {
if line != "" {
vals = append(vals, parseValue(line)...)
}
}
return carapace.ActionStyledValuesDescribed(vals...)
}).Invoke(c).ToA()
}))
default:
batch = append(batch, carapace.ActionMessage(fmt.Sprintf("malformed macro: '%v'", elem)))
}
batch = append(batch, parseMacro(elem))
} else {
vals = append(vals, parseValue(elem)...)
}
Expand Down

0 comments on commit 4845591

Please sign in to comment.