env: conditions

This commit is contained in:
rsteube 2023-09-21 13:52:19 +02:00
parent 3ce9b6f114
commit 295221d889
35 changed files with 750 additions and 124 deletions

3
.gitignore vendored
View File

@ -5,7 +5,6 @@ cmd/carapace/cmd/completers/description.go
cmd/carapace/cmd/completers.go
cmd/carapace/cmd/completers/name.go
cmd/carapace/cmd/completers_release.go
cmd/carapace/cmd/macros.go
cmd/carapace/cmd/shim/*.exe
cmd/carapace-fmt/carapace-fmt
cmd/carapace-generate/carapace-generate
@ -18,3 +17,5 @@ completers_release
dist
docs/book
out.gif
pkg/actions/actions_generated.go
pkg/conditions/conditions_generated.go

View File

@ -18,6 +18,7 @@ import (
func main() {
macros()
conditions()
names, descriptions := readCompleters()
@ -269,23 +270,104 @@ func macros() {
}
sort.Strings(sortedDescriptions)
content := fmt.Sprintf(`package cmd
content := fmt.Sprintf(`package actions
import (
%v
spec "github.com/rsteube/carapace-spec"
)
var macros = map[string]spec.Macro{
func init() {
MacroMap = map[string]spec.Macro{
%v
}
}
var macroDescriptions = map[string]string {
MacroDescriptions = map[string]string {
%v
}
}
`, strings.Join(sortedImports, "\n"), strings.Join(macros, "\n"), strings.Join(sortedDescriptions, "\n"))
os.WriteFile(root+"/cmd/carapace/cmd/macros.go", []byte(content), 0644)
execabs.Command("go", "fmt", root+"/cmd/carapace/cmd/macros.go").Run()
os.WriteFile(root+"/pkg/actions/actions_generated.go", []byte(content), 0644)
execabs.Command("go", "fmt", root+"/pkg/actions/actions_generated.go").Run()
}
func conditions() {
root, err := rootDir()
if err != nil {
panic(err.Error)
}
macros := make([]string, 0)
descriptions := make(map[string]string, 0)
r := regexp.MustCompile(`^func Condition(?P<name>[^(]+)\((?P<arg>[^(]*)\) condition.Condition {$`)
filepath.WalkDir(root+"/pkg/conditions", func(path string, d fs.DirEntry, err error) error { // TODO walkdir not necessary
path = filepath.ToSlash(path)
if !d.IsDir() && strings.HasSuffix(path, ".go") {
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if t := scanner.Text(); strings.HasPrefix(t, "func Condition") {
if r.MatchString(t) {
matches := r.FindStringSubmatch(t)
_func := fmt.Sprintf("Condition%v", matches[1])
if arg := matches[2]; strings.Contains(arg, ",") {
macros = append(macros, "// TODO unsupported signature: "+t)
continue
} else if arg == "" {
macros = append(macros, fmt.Sprintf(`"%v": condition.MacroN(%v),`, matches[1], _func))
} else if strings.Contains(arg, "...") {
macros = append(macros, fmt.Sprintf(`"%v": condition.MacroV(%v),`, matches[1], _func))
} else {
macros = append(macros, fmt.Sprintf(`"%v": condition.MacroI(%v),`, matches[1], _func))
}
}
} else if strings.HasPrefix(t, "// Condition") {
if splitted := strings.SplitN(strings.TrimPrefix(t, "// Condition"), " ", 2); len(splitted) > 1 {
descriptions[splitted[0]] = splitted[1]
}
}
}
}
return nil
})
sortedDescriptions := make([]string, 0)
for key, value := range descriptions {
sortedDescriptions = append(sortedDescriptions, fmt.Sprintf(`%#v: %#v,`, key, value))
}
sort.Strings(sortedDescriptions)
content := fmt.Sprintf(`package conditions
import (
"github.com/rsteube/carapace-bin/internal/condition"
"github.com/rsteube/carapace-spec/pkg/macro"
)
func init() {
MacroMap = macro.MacroMap[condition.Macro]{
%v
}
MacroDescriptions = map[string]string {
%v
}
}
`, strings.Join(macros, "\n"), strings.Join(sortedDescriptions, "\n"))
os.WriteFile(root+"/pkg/conditions/conditions_generated.go", []byte(content), 0644)
execabs.Command("go", "fmt", root+"/pkg/conditions/conditions_generated.go").Run()
}

View File

@ -17,6 +17,8 @@ import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/cmd/carapace/cmd/completers"
"github.com/rsteube/carapace-bin/cmd/carapace/cmd/shim"
"github.com/rsteube/carapace-bin/pkg/actions"
"github.com/rsteube/carapace-bin/pkg/conditions"
spec "github.com/rsteube/carapace-spec"
"github.com/rsteube/carapace/pkg/ps"
"github.com/rsteube/carapace/pkg/style"
@ -63,6 +65,12 @@ var rootCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
// since flag parsing is disabled do this manually
switch args[0] {
case "--conditions":
if len(args) > 1 {
//printCondition(args[1]) // TODO
} else {
printConditions() // TODO
}
case "--macros":
if len(args) > 1 {
printMacro(args[1])
@ -121,27 +129,42 @@ var rootCmd = &cobra.Command{
fmt.Fprintln(cmd.ErrOrStderr(), err.Error())
}
}
completers := completers.Names()
if os.Getenv("CARAPACE_ENV") == "0" {
filtered := make([]string, 0, len(completers))
for _, name := range completers {
switch name {
case "get-env", "set-env", "unset-env":
default:
filtered = append(filtered, name)
}
}
completers = filtered
}
switch shell {
case "bash":
fmt.Fprintln(cmd.OutOrStdout(), bash_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), bash_lazy(completers))
case "bash-ble":
fmt.Fprintln(cmd.OutOrStdout(), bash_ble_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), bash_ble_lazy(completers))
case "elvish":
fmt.Fprintln(cmd.OutOrStdout(), elvish_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), elvish_lazy(completers))
case "fish":
fmt.Fprintln(cmd.OutOrStdout(), fish_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), fish_lazy(completers))
case "nushell":
fmt.Fprintln(cmd.OutOrStdout(), nushell_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), nushell_lazy(completers))
case "oil":
fmt.Fprintln(cmd.OutOrStdout(), oil_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), oil_lazy(completers))
case "powershell":
fmt.Fprintln(cmd.OutOrStdout(), powershell_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), powershell_lazy(completers))
case "tcsh":
fmt.Fprintln(cmd.OutOrStdout(), tcsh_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), tcsh_lazy(completers))
case "xonsh":
fmt.Fprintln(cmd.OutOrStdout(), xonsh_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), xonsh_lazy(completers))
case "zsh":
fmt.Fprintln(cmd.OutOrStdout(), zsh_lazy(completers.Names()))
fmt.Fprintln(cmd.OutOrStdout(), zsh_lazy(completers))
default:
fmt.Fprintln(os.Stderr, "could not determine shell")
}
@ -286,10 +309,10 @@ func printCompletersJson() {
}
}
func printMacros() {
func printConditions() {
maxlen := 0
names := make([]string, 0)
for name := range macros {
for name := range conditions.MacroMap {
names = append(names, name)
if len := len(name); len > maxlen {
maxlen = len
@ -298,12 +321,28 @@ func printMacros() {
sort.Strings(names)
for _, name := range names {
fmt.Printf("%-"+strconv.Itoa(maxlen)+"v %v\n", name, macroDescriptions[name])
fmt.Printf("%-"+strconv.Itoa(maxlen)+"v %v\n", name, conditions.MacroDescriptions[name])
}
}
func printMacros() {
maxlen := 0
names := make([]string, 0)
for name := range actions.MacroMap {
names = append(names, name)
if len := len(name); len > maxlen {
maxlen = len
}
}
sort.Strings(names)
for _, name := range names {
fmt.Printf("%-"+strconv.Itoa(maxlen)+"v %v\n", name, actions.MacroDescriptions[name])
}
}
func printMacro(name string) {
if m, ok := macros[name]; ok {
if m, ok := actions.MacroMap[name]; ok {
path := strings.Replace(name, ".", "/", -1)
signature := ""
if s := m.Signature(); s != "" {
@ -313,7 +352,7 @@ func printMacro(name string) {
fmt.Printf(`signature: $_%v%v
description: %v
reference: https://pkg.go.dev/github.com/rsteube/carapace-bin/pkg/actions/%v#Action%v
`, name, signature, macroDescriptions[name], filepath.Dir(path), filepath.Base(path))
`, name, signature, actions.MacroDescriptions[name], filepath.Dir(path), filepath.Base(path))
}
}
@ -406,7 +445,7 @@ func init() {
rootCmd.Flags().String("scrape", "", "scrape spec to go code")
rootCmd.Flags().String("style", "", "set style")
for m, f := range macros {
for m, f := range actions.MacroMap {
spec.AddMacro(m, f)
}
}

View File

@ -0,0 +1 @@
# carapace-fmt

View File

@ -0,0 +1 @@
# carapace-generate

View File

@ -0,0 +1 @@
# carapace-lint

View File

@ -0,0 +1 @@
# carapace-parse

View File

@ -0,0 +1,75 @@
{"version": 2, "width": 108, "height": 24, "timestamp": 1695398869, "env": {"SHELL": "elvish", "TERM": "tmux-256color"}}
[0.092246, "o", "\u001b[?7h\u001b[7m⏎\u001b[m \r \r\u001b[?7l\u001b[?2004h"]
[0.092819, "o", "\u001b[?25l\r???> ???> \r\u001b[5C\u001b[?25h\u001b[?25l\r\u001b[5C\u001b[K\r\u001b[5C\u001b[?25h"]
[0.111124, "o", "\u001b[?25l\r\r\u001b[5C\u001b[?25h"]
[0.111245, "o", "\u001b[?25l\r\u001b[K\r\n\u001b[0;1;36mcarapace-bin\u001b[0;m on \u001b[0;1;35m env-condition\u001b[0;m via \u001b[0;1;36m🐹 v1.21.1 \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m\u001b[0;m \r\u001b[6C\u001b[?25h"]
[0.681095, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31ms\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[0.681623, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[0.716204, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[0.768028, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31me\u001b[0;m\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"]
[0.867447, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mset\u001b[0;m\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"]
[0.96114, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;31mset-\u001b[0;m\r\u001b[10C\u001b[?25h"]
[0.961535, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[0.962133, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[1.076815, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10C\u001b[0;31me\u001b[0;m\r\u001b[11C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"]
[1.172287, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[11C\u001b[0;31mn\u001b[0;m\r\u001b[12C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[12C\u001b[?25h"]
[1.291771, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mset-env\u001b[0;m\r\u001b[13C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[13C\u001b[?25h"]
[1.383674, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[13C \r\u001b[14C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h"]
[1.722694, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14C\u001b[0;4mAR \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mAR\u001b[0;2;7m (The command to use to manipulate library archives when building with the gccg...)\u001b[0;m \u001b[0;34mDOCKER_HIDE_LEGACY_CO\r\nASCIINEMA_REC\u001b[0;2m (1) \u001b[0;m \u001b[0;34mEDITOR\u001b[0;2m (/usr/bin/heli\r\n\u001b[0;mAWS_ FC\u001b[0;2m (The command to us\r\n\u001b[0;mBUILDKIT_ GCCGO\u001b[0;2m (The gccgo comm\r\n\u001b[0;mCARAPACE_ GCCGOTOOLDIR\u001b[0;2m (If set,\r\n\u001b[0;34mCARAPACE_MATCH\u001b[0;2m (1) \u001b[0;m GH_ \r\nCARGO_ GIT_ \r\nCC\u001b[0;2m (The command to use to compile C code) \u001b[0;m GO111MODULE\u001b[0;2m (Controls\r\n\u001b[0;mCGO_ GO386\u001b[0;2m (For GOARCH=386\r\n\u001b[0;34mCLOUDSDK_PYTHON\u001b[0;2m (/usr/bin/python) \u001b[0;m GOAMD64\u001b[0;2m (For GOARCH=a\r\n\u001b[0;34mCLOUDSDK_PYTHON_ARGS\u001b[0;2m (-S) \u001b[0;m GOARCH\u001b[0;2m (The architect\r\n\u001b[0;34mCLOUDSDK_ROOT_DIR\u001b[0;2m (/opt/google-cloud-cli) \u001b[0;m GOARM\u001b[0;2m (For GOARCH=arm\r\n\u001b[0;34mCOLORTERM\u001b[0;2m (truecolor) \u001b[0;m GOBIN\u001b[0;2m (The directory \r\n\u001b[0;mCUSTOM_ GOCACHE\u001b[0;2m (The director\r\n\u001b[0;mCXX\u001b[0;2m (The command to use to compile C++ code) \u001b[0;m GOCOVERDIR\u001b[0;2m (Directory\r\n\u001b[0;34mDBUS_SESSION_BUS_ADDRESS\u001b[0;2m (unix:path=/run/user/1000/bus) \u001b[0;m GODEBUG\u001b[0;2m (Enable vario\r\n\u001b[0;34mDEBUGINFOD_URLS\u001b[0;2m (https://debuginfod.archlinux.org) \u001b[0;m GOENV\u001b[0;2m (The location o\r\n\u001b[0;34mDISPLAY\u001b[0;2m (:0) \u001b[0;m GOEXE\u001b[0;2m (The executable\r\n\u001b[0;mDOCKER_ GOEXPERIMENT\u001b[0;2m (Comma-s\r\n\u001b[0;7;35m \u001b[0;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0;m\u001b[20A\r\u001b[22C\u001b[?25h"]
[2.049261, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\u001b[22Cc\r\n\u001b[87C\u001b[KGO111MODULE\u001b[0;2m (Controls\r\n\u001b[87C\u001b[0;m\u001b[KGO386\u001b[0;2m (For GOARCH=386\r\n\u001b[0;m\u001b[KCARAPACE_ GOAMD64\u001b[0;2m (For GOARCH=a\r\n\u001b[0;m\u001b[K\u001b[0;34mCARAPACE_MATCH\u001b[0;2m (1) \u001b[0;m GOARCH\u001b[0;2m (The architect\r\n\u001b[3C\u001b[0;m\u001b[KGO_ GOARM\u001b[0;2m (For GOARCH=arm\r\n\u001b[0;m\u001b[KCC\u001b[0;2m (The command to use to compile C code) \u001b[0;m GOBIN\u001b[0;2m (The directory \r\n\u001b[1C\u001b[0;m\u001b[KGO_ GOCACHE\u001b[0;2m (The director\r\n\u001b[0;m\u001b[K\u001b[0;34mCLOUDSDK_PYTHON\u001b[0;2m (/usr/bin/python) \u001b[0;m GOCOVERDIR\u001b[0;2m (Directory\r\n\u001b[0;m\u001b[K\u001b[0;34mCLOUDSDK_PYTHON_ARGS\u001b[0;2m (-S) \u001b[0;m GODEBUG\u001b[0;2m (Enable vario\r\n\u001b[9C\u001b[0;m\u001b[K\u001b[0;34mROOT_DIR\u001b[0;2m (/opt/google-cloud-cli) \u001b[0;m GOENV\u001b[0;2m (The location o\r\n\u001b[1C\u001b[0;m\u001b[K\u001b[0;34mOLORTERM\u001b[0;2m (truecolor) \u001b[0;m GOEXE\u001b[0;2m (The executable\r\n\u001b[0;m\u001b[KCUSTOM_ GOEXPERIMENT\u001b[0;2m (Comma-s\r\n\u001b[0;m\u001b[KCXX\u001b[0;2m (The command to use to compile C++ code) \u001b[0;m GOFLAGS\u001b[0;2m (A space-sepa\r\n\u001b[0;m\u001b[K\u001b[0;34mDEBUGINFOD_URLS\u001b[0;2m (https://debuginfod.archlinux.org) \u001b[0;m GOGCCFLAGS\u001b[0;2m (A space-s\r\n\u001b[0;m\u001b[KDOCKER_ GOHOSTARCH\u001b[0;2m (The archi\r\n\u001b[1C\u001b[0;m\u001b[K\u001b[0;34mOCKER_HIDE_LEGACY_COMMANDS\u001b[0;2m (1) \u001b[0;m GOHOSTOS\u001b[0;2m (The operati\r\n\u001b[0;m\u001b[KFC\u001b[0;2m (The command to use to compile Fortran code) \u001b[0;m GOINSECURE\u001b[0;2m (Comma-sep\r\n\u001b[0;m\u001b[KGCCGO\u001b[0;2m (The gccgo command to run for 'go build -compiler=gccgo') \u001b[0;m GOMIPS\u001b[0;2m (For GOARCH=mi\r\n\u001b[0;m\u001b[KGCCGOTOOLDIR\u001b[0;2m (If set, where to find gccgo tools, such as cgo) \u001b[0;m GOMIPS64\u001b[0;2m (For GOARCH=\r\n\u001b[32C\u001b[0;m\u001b[K\u001b[0;7;35m \u001b[0;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0;m\u001b[20A\r\u001b[23C\u001b[?25h"]
[2.050627, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[20A\r\u001b[23C\u001b[?25h"]
[2.055688, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[20A\r\u001b[23C\u001b[?25h"]
[2.126031, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[14C\u001b[K\u001b[0;4mCUSTOM_\r\n\u001b[23C\u001b[0;mu\r\n\u001b[K\u001b[0;7mCUSTOM_ \r\n\u001b[0;m\u001b[KGOEXE\u001b[0;2m (The executable file name suffix (\".exe\" on Windows, \"\" on other systems))\r\n\u001b[0;m\u001b[KGOINSECURE\u001b[0;2m (Comma-separated list of glob patterns) \r\n\u001b[0;m\u001b[K\u001b[0;34mPWD\u001b[0;2m (/home/rsteube/Documents/development/github/carapace-bin) \r\n\u001b[0;m\u001b[K\u001b[0;34mXCURSOR_SIZE\u001b[0;2m (24) \r\n\u001b[0;m\u001b[K\u001b[0;34mXDG_CURRENT_DESKTOP\u001b[0;2m (sway) \u001b[0;m\r\n\u001b[J\u001b[A\u001b[6A\r\u001b[24C\u001b[?25h"]
[2.260879, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\u001b[24Cs\r\n\u001b[7C\u001b[K\r\n\u001b[J\u001b[A\u001b[1A\r\u001b[25C\u001b[?25h"]
[2.731591, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[14C\u001b[KCUSTOM_\r\n\u001b[J\u001b[A\r\u001b[21C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[21C\u001b[?25h"]
[2.731749, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[21C\u001b[?25h"]
[2.976598, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14C\u001b[K\u001b[0;4mCUSTOM_CONDITION \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mCUSTOM_CONDITION\u001b[0;2;7m (condition example) \u001b[0;m CUSTOM_MACRO\u001b[0;2m (macro example)\r\n\u001b[0;mCUSTOM_EXAMPLE\u001b[0;2m (example environment variable)\u001b[0;m\u001b[2A\r\u001b[22C\u001b[?25h"]
[2.976935, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\r\n\u001b[2A\r\u001b[22C\u001b[?25h"]
[2.977079, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\r\n\r\n\u001b[2A\r\u001b[22C\u001b[?25h"]
[3.647594, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[14C\u001b[KCUSTOM_CONDITION \r\n\u001b[J\u001b[A\r\u001b[31C\u001b[?25h"]
[3.966445, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[31C\u001b[0;4mgit \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mgit\u001b[0;m repo within\u001b[1A\r\u001b[22C\u001b[?25h"]
[6.040677, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[31C\u001b[K\r\n\u001b[J\u001b[A\r\u001b[31C\u001b[?25h"]
[6.273995, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[6.274588, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[6.30132, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[6.301403, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[6.846963, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31mc\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[6.900399, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mcd\u001b[0;m\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"]
[6.963468, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[8C \r\u001b[9C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"]
[7.115758, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[9C/\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[7.245796, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10Ct\r\u001b[11C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"]
[7.337438, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[11Cm\r\u001b[12C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[12C\u001b[?25h"]
[7.441723, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[12Cp/\r\u001b[14C\u001b[?25h"]
[7.863996, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\u001b[?25h\u001b[?7h\u001b[?2004l\r"]
[7.924335, "o", "\u001b[?7h\u001b[7m⏎\u001b[m \r \r\u001b[?7l\u001b[?2004h"]
[7.92561, "o", "\u001b[?25l\r\r\n\u001b[0;1;36mcarapace-bin\u001b[0;m on \u001b[0;1;35m env-condition\u001b[0;m via \u001b[0;1;36m🐹 v1.21.1 \r\n\u001b[0;1;37mesh\u001b[0;m \u001b[0;1;32m\u001b[0;m \r\u001b[6C\u001b[?25h"]
[7.927035, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[7.942635, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[7.942696, "o", "\u001b[?25l\u001b[2A\r\r\n\u001b[K\u001b[0;1;36m/tmp\u001b[0;m \r\n\r\u001b[6C\u001b[?25h"]
[8.317012, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31ms\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[8.32724, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[8.327358, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[8.374677, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31me\u001b[0;m\r\u001b[8C\u001b[?25h"]
[8.456446, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mset\u001b[0;m\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"]
[8.539056, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;31mset-\u001b[0;m\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[8.645899, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[10C\u001b[0;31me\u001b[0;m\r\u001b[11C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[11C\u001b[?25h"]
[8.780566, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[11C\u001b[0;31mn\u001b[0;m\r\u001b[12C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[12C\u001b[?25h"]
[8.881374, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mset-env\u001b[0;m\r\u001b[13C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[13C\u001b[?25h"]
[8.989185, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[13C \r\u001b[14C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[14C\u001b[?25h"]
[9.710983, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14C\u001b[0;4mAR \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mAR\u001b[0;2;7m (The command to use to manipulate library archives when building with the gccg...)\u001b[0;m \u001b[0;34mDOCKER_HIDE_LEGACY_CO\r\nASCIINEMA_REC\u001b[0;2m (1) \u001b[0;m \u001b[0;34mEDITOR\u001b[0;2m (/usr/bin/heli\r\n\u001b[0;mAWS_ FC\u001b[0;2m (The command to us\r\n\u001b[0;mBUILDKIT_ GCCGO\u001b[0;2m (The gccgo comm\r\n\u001b[0;mCARAPACE_ GCCGOTOOLDIR\u001b[0;2m (If set,\r\n\u001b[0;34mCARAPACE_MATCH\u001b[0;2m (1) \u001b[0;m GH_ \r\nCARGO_ GIT_ \r\nCC\u001b[0;2m (The command to use to compile C code) \u001b[0;m GO111MODULE\u001b[0;2m (Controls\r\n\u001b[0;mCGO_ GO386\u001b[0;2m (For GOARCH=386\r\n\u001b[0;34mCLOUDSDK_PYTHON\u001b[0;2m (/usr/bin/python) \u001b[0;m GOAMD64\u001b[0;2m (For GOARCH=a\r\n\u001b[0;34mCLOUDSDK_PYTHON_ARGS\u001b[0;2m (-S) \u001b[0;m GOARCH\u001b[0;2m (The architect\r\n\u001b[0;34mCLOUDSDK_ROOT_DIR\u001b[0;2m (/opt/google-cloud-cli) \u001b[0;m GOARM\u001b[0;2m (For GOARCH=arm\r\n\u001b[0;34mCOLORTERM\u001b[0;2m (truecolor) \u001b[0;m GOBIN\u001b[0;2m (The directory \r\n\u001b[0;mCUSTOM_ GOCACHE\u001b[0;2m (The director\r\n\u001b[0;mCXX\u001b[0;2m (The command to use to compile C++ code) \u001b[0;m GOCOVERDIR\u001b[0;2m (Directory\r\n\u001b[0;34mDBUS_SESSION_BUS_ADDRESS\u001b[0;2m (unix:path=/run/user/1000/bus) \u001b[0;m GODEBUG\u001b[0;2m (Enable vario\r\n\u001b[0;34mDEBUGINFOD_URLS\u001b[0;2m (https://debuginfod.archlinux.org) \u001b[0;m GOENV\u001b[0;2m (The location o\r\n\u001b[0;34mDISPLAY\u001b[0;2m (:0) \u001b[0;m GOEXE\u001b[0;2m (The executable\r\n\u001b[0;mDOCKER_ GOEXPERIMENT\u001b[0;2m (Comma-s\r\n\u001b[0;7;35m \u001b[0;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0;m\u001b[20A\r\u001b[22C\u001b[?25h"]
[10.310527, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\u001b[22Cc\r\n\u001b[87C\u001b[KGO111MODULE\u001b[0;2m (Controls\r\n\u001b[87C\u001b[0;m\u001b[KGO386\u001b[0;2m (For GOARCH=386\r\n\u001b[0;m\u001b[KCARAPACE_ GOAMD64\u001b[0;2m (For GOARCH=a\r\n\u001b[0;m\u001b[K\u001b[0;34mCARAPACE_MATCH\u001b[0;2m (1) \u001b[0;m GOARCH\u001b[0;2m (The architect\r\n\u001b[3C\u001b[0;m\u001b[KGO_ GOARM\u001b[0;2m (For GOARCH=arm\r\n\u001b[0;m\u001b[KCC\u001b[0;2m (The command to use to compile C code) \u001b[0;m GOBIN\u001b[0;2m (The directory \r\n\u001b[1C\u001b[0;m\u001b[KGO_ GOCACHE\u001b[0;2m (The director\r\n\u001b[0;m\u001b[K\u001b[0;34mCLOUDSDK_PYTHON\u001b[0;2m (/usr/bin/python) \u001b[0;m GOCOVERDIR\u001b[0;2m (Directory\r\n\u001b[0;m\u001b[K\u001b[0;34mCLOUDSDK_PYTHON_ARGS\u001b[0;2m (-S) \u001b[0;m GODEBUG\u001b[0;2m (Enable vario\r\n\u001b[9C\u001b[0;m\u001b[K\u001b[0;34mROOT_DIR\u001b[0;2m (/opt/google-cloud-cli) \u001b[0;m GOENV\u001b[0;2m (The location o\r\n\u001b[1C\u001b[0;m\u001b[K\u001b[0;34mOLORTERM\u001b[0;2m (truecolor) \u001b[0;m GOEXE\u001b[0;2m (The executable\r\n\u001b[0;m\u001b[KCUSTOM_ GOEXPERIMENT\u001b[0;2m (Comma-s\r\n\u001b[0;m\u001b[KCXX\u001b[0;2m (The command to use to compile C++ code) \u001b[0;m GOFLAGS\u001b[0;2m (A space-sepa\r\n\u001b[0;m\u001b[K\u001b[0;34mDEBUGINFOD_URLS\u001b[0;2m (https://debuginfod.archlinux.org) \u001b[0;m GOGCCFLAGS\u001b[0;2m (A space-s\r\n\u001b[0;m\u001b[KDOCKER_ GOHOSTARCH\u001b[0;2m (The archi\r\n\u001b[1C\u001b[0;m\u001b[K\u001b[0;34mOCKER_HIDE_LEGACY_COMMANDS\u001b[0;2m (1) \u001b[0;m GOHOSTOS\u001b[0;2m (The operati\r\n\u001b[0;m\u001b[KFC\u001b[0;2m (The command to use to compile Fortran code) \u001b[0;m GOINSECURE\u001b[0;2m (Comma-sep\r\n\u001b[0;m\u001b[KGCCGO\u001b[0;2m (The gccgo command to run for 'go build -compiler=gccgo') \u001b[0;m GOMIPS\u001b[0;2m (For GOARCH=mi\r\n\u001b[0;m\u001b[KGCCGOTOOLDIR\u001b[0;2m (If set, where to find gccgo tools, such as cgo) \u001b[0;m GOMIPS64\u001b[0;2m (For GOARCH=\r\n\u001b[32C\u001b[0;m\u001b[K\u001b[0;7;35m \u001b[0;35m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0;m\u001b[20A\r\u001b[23C\u001b[?25h"]
[10.403602, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[14C\u001b[K\u001b[0;4mCUSTOM_\r\n\u001b[23C\u001b[0;mu\r\n\u001b[K\u001b[0;7mCUSTOM_ \r\n\u001b[0;m\u001b[KGOEXE\u001b[0;2m (The executable file name suffix (\".exe\" on Windows, \"\" on other systems))\r\n\u001b[0;m\u001b[KGOINSECURE\u001b[0;2m (Comma-separated list of glob patterns) \r\n\u001b[0;m\u001b[K\u001b[0;34mXCURSOR_SIZE\u001b[0;2m (24) \r\n\u001b[0;m\u001b[K\u001b[0;34mXDG_CURRENT_DESKTOP\u001b[0;2m (sway) \u001b[0;m\r\n\u001b[J\u001b[A\u001b[5A\r\u001b[24C\u001b[?25h"]
[10.465209, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\r\n\u001b[24Cs\r\n\u001b[7C\u001b[K\r\n\u001b[J\u001b[A\u001b[1A\r\u001b[25C\u001b[?25h"]
[10.972623, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[14C\u001b[KCUSTOM_\r\n\u001b[J\u001b[A\r\u001b[21C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[21C\u001b[?25h"]
[11.243591, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[14C\u001b[K\u001b[0;4mCUSTOM_EXAMPLE \r\n\u001b[0;1;37;45m COMPLETING argument \u001b[0;m \r\n\u001b[0;7mCUSTOM_EXAMPLE\u001b[0;2;7m (example environment variable)\u001b[0;m CUSTOM_MACRO\u001b[0;2m (macro example)\u001b[0;m\u001b[1A\r\u001b[22C\u001b[?25h"]
[14.872308, "o", "\u001b[?25l\u001b[3A\r\r\n\r\n\u001b[6C\u001b[K\r\n\u001b[J\u001b[A\r\u001b[6C\u001b[?25h"]
[14.872715, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[14.873279, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[14.87414, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[14.874521, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[14.891848, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[6C\u001b[?25h"]
[15.118188, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[0;31me\u001b[0;m\r\u001b[7C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[7C\u001b[?25h"]
[15.317512, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[7C\u001b[0;31mx\u001b[0;m\r\u001b[8C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[8C\u001b[?25h"]
[15.46072, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[8C\u001b[0;31mi\u001b[0;m\r\u001b[9C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[9C\u001b[?25h"]
[15.571217, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\u001b[6C\u001b[K\u001b[0;32mexit\u001b[0;m\r\u001b[10C\u001b[?25h\u001b[?25l\u001b[2A\r\r\n\r\n\r\u001b[10C\u001b[?25h"]
[15.687253, "o", "\u001b[?25l\u001b[2A\r\r\n\r\n\r\n\r\u001b[?25h\u001b[?7h\u001b[?2004l\r"]

View File

@ -7,24 +7,39 @@ Complex environment variable completion is provided with `get-env`, `set-env` an
In `elvish` the completion is simply overridden.
For other shells custom functions are added.
> Setting the environment variable `CARAPACE_ENV` to `0`
> before sourcing `carapace _carapace` disables this behaviour.
> Setting `CARAPACE_ENV=0` before sourcing `carapace _carapace` disables this behaviour.
![](./environment.cast)
## Custom variables
Custom variables can be defined in `~/.config/carapace/env.yaml`
Custom variables can be defined in `~/.config/carapace/variables/{group}.yaml`
```yaml
names:
variables:
CUSTOM_EXAMPLE: example environment variable
CUSTOM_MACRO: macro example
HTTPS_PROXY: override existing variable
completion:
CUSTOM_EXAMPLE: ["0\tdisabled\tred", "1\tenabled\tgreen"]
CUSTOM_MACRO: ["$_tools.gh.Labels({owner: rsteube, name: carapace}) ||| $uniquelist(,)"]
HTTPS_PROXY: ["https://localhost:8443\tdevelopment", "https://proxy.company:443\tproduction"]
variable:
CUSTOM_EXAMPLE: ["0\tdisabled\tred", "1\tenabled\tgreen"]
CUSTOM_MACRO: ["$_tools.gh.Labels({owner: rsteube, name: carapace}) ||| $uniquelist(,)"]
HTTPS_PROXY: ["https://localhost:8443\tdevelopment", "https://proxy.company:443\tproduction"]
```
![](./environment-custom.cast)
It is also possible to define conditions.
```yaml
condition: ["$Parent([.git])"]
variables:
CUSTOM_CONDITION: condition example
completion:
variable:
CUSTOM_CONDITION: ["within", "git", "repo"]
```
![](./environment-condition.cast)
> TODO document conditions

10
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/rsteube/carapace v0.43.5
github.com/rsteube/carapace-bridge v0.1.4
github.com/rsteube/carapace-shlex v0.0.4
github.com/rsteube/carapace-spec v0.11.0
github.com/rsteube/carapace-spec v0.11.1
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
golang.org/x/mod v0.12.0
@ -16,10 +16,12 @@ require (
)
require (
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/invopop/jsonschema v0.8.0 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/invopop/jsonschema v0.9.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
)
replace github.com/spf13/pflag => github.com/rsteube/carapace-pflag v0.2.0

30
go.sum
View File

@ -1,12 +1,17 @@
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/jsonschema v0.8.0 h1:9Vblm5uNqURXUSaX0QUYcI/Hcu5rrvOz5MbpWgw0VkM=
github.com/invopop/jsonschema v0.8.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
github.com/invopop/jsonschema v0.9.0 h1:m1Fe5PN4X9V7P1TCF+pA8Xly3Vj3pY905klC++8oOpM=
github.com/invopop/jsonschema v0.9.0/go.mod h1:uMhbTEOXoPcOKzdYRfk914W6UTGA/cVcgEQxXh1MJ7g=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -20,21 +25,20 @@ github.com/rsteube/carapace-pflag v0.2.0 h1:EYqFO9Haib3NDCPqKu0VxOGi9YQBkXk1IzlH
github.com/rsteube/carapace-pflag v0.2.0/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/rsteube/carapace-shlex v0.0.4 h1:3GVn8PaM2RCxPTAiwVy9vDQI8Mi7DqrbdpDgf5ZzQmY=
github.com/rsteube/carapace-shlex v0.0.4/go.mod h1:zPw1dOFwvLPKStUy9g2BYKanI6bsQMATzDMYQQybo3o=
github.com/rsteube/carapace-spec v0.11.0 h1:SMMivfa2OXK/pTtJrx2fqqLgJgh2EuF/uchcLaH/6AM=
github.com/rsteube/carapace-spec v0.11.0/go.mod h1:tZIZjpCdeb8WClSdHDf95FN1LB168CrFD1ImROUZnds=
github.com/rsteube/carapace-spec v0.11.1 h1:LUNFbGOucWj4C74JMLvPuqKDFNGFGMHunWyiUfTM0BU=
github.com/rsteube/carapace-spec v0.11.1/go.mod h1:1rjCeoupGdnfPaMMfYr7PQDDHk8G8HeL9sSdyHO5UHU=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,19 @@
package condition
import (
"github.com/rsteube/carapace"
)
type Condition func(c carapace.Context) bool
// Of combines different conditions.
func Of(conditions ...Condition) Condition {
return func(c carapace.Context) bool {
for _, condition := range conditions {
if !condition(c) {
return false
}
}
return true
}
}

View File

@ -0,0 +1,49 @@
package condition
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-spec/pkg/macro"
)
type Macro struct {
macro macro.Macro[Condition]
}
func (m Macro) Parse(s string) Condition {
return func(c carapace.Context) bool {
b, err := m.macro.Parse(s)
if err != nil {
return false
}
return (*b)(c)
}
}
func (m Macro) Signature() string { return m.macro.Signature() }
func MacroI[A any](f func(arg A) Condition) Macro {
return Macro{
macro: macro.MacroI[A, Condition](func(arg A) (*Condition, error) {
a := f(arg)
return &a, nil
}),
}
}
func MacroN(f func() Condition) Macro {
return Macro{
macro: macro.MacroN[Condition](func() (*Condition, error) {
a := f()
return &a, nil
}),
}
}
func MacroV[A any](f func(args ...A) Condition) Macro {
return Macro{
macro: macro.MacroV[A, Condition](func(args ...A) (*Condition, error) {
a := f(args...)
return &a, nil
}),
}
}

11
pkg/actions/actions.go Normal file
View File

@ -0,0 +1,11 @@
package actions
import (
spec "github.com/rsteube/carapace-spec"
"github.com/rsteube/carapace-spec/pkg/macro"
)
var (
MacroMap = make(macro.MacroMap[spec.Macro])
MacroDescriptions = make(map[string]string)
)

View File

@ -5,6 +5,7 @@ import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/aws"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace-bridge/pkg/actions/bridge"
"github.com/rsteube/carapace/pkg/style"
)
@ -12,8 +13,8 @@ import (
func init() {
_bool := carapace.ActionValues("true", "false").StyleF(style.ForKeyword)
knownVariables["aws"] = variables{
Condition: checkPath("aws"),
Names: map[string]string{
Condition: conditions.ConditionPath("aws"),
Variables: map[string]string{
"AWS_ACCESS_KEY_ID": "Specifies an AWS access key associated with an IAM account",
"AWS_CA_BUNDLE": "Specifies the path to a certificate bundle to use for HTTPS certificate validation",
"AWS_CLI_AUTO_PROMPT": "Enables the auto-prompt for the AWS CLI version 2",
@ -40,7 +41,7 @@ func init() {
"AWS_USE_FIPS_ENDPOINT": "Federal Information Processing Standard (FIPS) endoint",
"AWS_WEB_IDENTITY_TOKEN_FILE": "Specifies the path to a file that contains an OAuth 2.0 access token",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"AWS_CA_BUNDLE": carapace.ActionFiles(),
"AWS_CLI_AUTO_PROMPT": carapace.ActionValuesDescribed(
"on", "full auto-prompt mode each time you attempt to run an aws command",

View File

@ -8,7 +8,7 @@ import (
func init() {
_bool := carapace.ActionValuesDescribed("0", "disabled", "1", "enabled").StyleF(style.ForKeyword)
knownVariables["carapace"] = variables{
Names: map[string]string{
Variables: map[string]string{
"CARAPACE_COVERDIR": "coverage directory for sandbox tests",
"CARAPACE_ENV": "register get-env, set-env and unset-env",
"CARAPACE_HIDDEN": "show hidden commands/flags",
@ -18,7 +18,7 @@ func init() {
"CARAPACE_SANDBOX": "mock context for sandbox tests",
"CARAPACE_ZSH_HASH_DIRS": "zsh hash directories",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"CARAPACE_COVERDIR": carapace.ActionDirectories(),
"CARAPACE_ENV": _bool,
"CARAPACE_HIDDEN": _bool,

View File

@ -2,12 +2,14 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/net/http"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
_bool := carapace.ActionValues("true", "false").StyleF(style.ForKeyword)
knownVariables["cargo"] = variables{
Names: map[string]string{
Variables: map[string]string{
"CARGO_BIN_NAME": "The name of the binary that is currently being compiled",
"CARGO_BUILD_DEP_INFO_BASEDIR": "Dep-info relative directory, see build.dep-info-basedir",
"CARGO_BUILD_INCREMENTAL": "Incremental compilation, see build.incremental",
@ -80,7 +82,7 @@ func init() {
"CARGO_TERM_QUIET": "Quiet mode, see term.quiet",
"CARGO_TERM_VERBOSE": "The default terminal verbosity, see term.verbose",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"CARGO_BUILD_DEP_INFO_BASEDIR": carapace.ActionDirectories(),
"CARGO_LOG": carapace.ActionValues("debug", "info", "warn", "error", "trace").StyleF(style.ForLogLevel),
"CARGO_HOME": carapace.ActionDirectories(),
@ -89,7 +91,11 @@ func init() {
"0", "force disabled,", style.Red,
"1", "force enabled", style.Green,
),
"CARGO_CARGO_NEW_VCS": carapace.ActionValues("git", "hg", "pijul", "fossil", "none"),
"CARGO_CARGO_NEW_VCS": carapace.ActionValues("git", "hg", "pijul", "fossil", "none"),
"CARGO_HTTP_USER_AGENT": http.ActionUserAgents(),
"CARGO_TERM_COLOR": carapace.ActionValues("auto", "always", "never").StyleF(style.ForKeyword),
"CARGO_TERM_QUIET": _bool,
"CARGO_TERM_VERBOSE": _bool,
// TODO more completions
},
}

View File

@ -9,7 +9,7 @@ import (
func init() {
knownVariables["common"] = variables{
Names: map[string]string{
Variables: map[string]string{
"BROWSER": "the browser to use",
"EDITOR": "the editor to use",
"HTTP_PROXY": "http proxy server",
@ -18,7 +18,7 @@ func init() {
"PAGER": "the pager to use",
"PATH": "A list of directories to be searched when executing commands",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"BROWSER": bridge.ActionCarapaceBin().Split(),
"EDITOR": bridge.ActionCarapaceBin().Split(),
"PAGER": bridge.ActionCarapaceBin().Split(),

View File

@ -7,7 +7,7 @@ import (
func init() {
knownVariables["common_unix"] = variables{
Names: map[string]string{
Variables: map[string]string{
"USER": "The current logged in user",
"HOME": "The home directory of the current user",
"EDITOR": "The default file editor to be used",
@ -17,7 +17,7 @@ func init() {
"TERM": "The current terminal emulation",
"MAIL": "Location of where the current users mail is stored",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"HOME": carapace.ActionDirectories(),
"LANG": os.ActionLanguages(),
"LOGNAME": os.ActionUsers(),

View File

@ -2,13 +2,14 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
knownVariables["docker"] = variables{
Condition: checkPath("docker"),
Names: map[string]string{
Condition: conditions.ConditionPath("docker"),
Variables: map[string]string{
"DOCKER_API_VERSION": "Override the negotiated API version to use for debugging",
"DOCKER_CERT_PATH": "Location of your authentication keys",
"DOCKER_CONFIG": "The location of your client configuration files",
@ -21,7 +22,7 @@ func init() {
"DOCKER_TLS_VERIFY": "When set Docker uses TLS and verifies the remote",
"BUILDKIT_PROGRESS": "Set type of progress output",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"DOCKER_CERT_PATH": carapace.ActionDirectories(),
"DOCKER_CONFIG": carapace.ActionFiles(),
"DOCKER_HIDE_LEGACY_COMMANDS": carapace.ActionStyledValuesDescribed(

141
pkg/actions/env/env.go vendored
View File

@ -2,9 +2,11 @@ package env
import (
"os"
"os/exec"
"strings"
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/internal/condition"
"github.com/rsteube/carapace-bin/pkg/conditions"
spec "github.com/rsteube/carapace-spec"
"github.com/rsteube/carapace/pkg/xdg"
"github.com/spf13/cobra"
@ -12,34 +14,43 @@ import (
)
type variables struct {
Condition func(c carapace.Context) bool
Names map[string]string
Completion map[string]carapace.Action
Condition condition.Condition
Variables map[string]string
VariableCompletion map[string]carapace.Action
// PlaceholderCompletion map[string]carapace.Action // TODO
}
func (v *variables) UnmarshalYAML(unmarshal func(interface{}) error) error {
var env struct {
Names map[string]string
Completion map[string][]string
Condition []string
Variables map[string]string
Completion struct {
Variable map[string][]string
// Placeholder map[string][]string // TODO
}
}
if err := unmarshal(&env); err != nil {
return err
}
v.Names = env.Names
v.Completion = make(map[string]carapace.Action)
for name, completion := range env.Completion {
v.Completion[name] = spec.NewAction(completion).Parse(&cobra.Command{})
conds := make([]condition.Condition, 0)
for _, c := range env.Condition {
m, err := conditions.MacroMap.Lookup(c)
if err != nil {
return err
}
conds = append(conds, m.Parse(c))
}
v.Condition = condition.Of(conds...)
v.Variables = env.Variables
v.VariableCompletion = make(map[string]carapace.Action)
for name, completion := range env.Completion.Variable {
v.VariableCompletion[name] = spec.NewAction(completion).Parse(&cobra.Command{})
}
return nil
}
func checkPath(s string) func(c carapace.Context) bool {
return func(c carapace.Context) bool {
_, err := exec.LookPath(s) // TODO copy function to carapace as this needs to use carapace.Context$Env
return err == nil
}
}
var knownVariables = map[string]variables{}
// ActionKnownEnvironmentVariables completes known environment variables
@ -61,7 +72,7 @@ func actionKnownEnvironmentVariables() carapace.Action {
continue
}
for name, description := range v.Names {
for name, description := range v.Variables {
vals = append(vals, name, description)
}
}
@ -72,50 +83,100 @@ func actionKnownEnvironmentVariables() carapace.Action {
// ActionEnvironmentVariableValues completes values for given environment variable
func ActionEnvironmentVariableValues(s string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
if custom, err := loadCustomVariables(); err == nil {
if action, ok := custom.Completion[s]; ok {
return action
dir, err := xdg.UserConfigDir()
if err != nil {
return carapace.ActionMessage(err.Error())
}
entries, err := os.ReadDir(dir + "/carapace/variables")
if err != nil {
return carapace.ActionMessage(err.Error()) // TODO ignore if not exists
}
found := false
batch := carapace.Batch()
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".yaml") {
file := dir + "/carapace/variables/" + entry.Name()
batch = append(batch, carapace.ActionCallback(func(c carapace.Context) carapace.Action {
custom, err := loadCustomVariables(file)
if err != nil {
return carapace.ActionMessage(err.Error())
}
if custom.Condition == nil || custom.Condition(c) {
if action, ok := custom.VariableCompletion[s]; ok {
found = true
return action
}
}
for _, v := range knownVariables {
if action, ok := v.VariableCompletion[s]; ok {
found = true
return action
}
}
return carapace.ActionValues()
}))
}
}
for _, v := range knownVariables {
if action, ok := v.Completion[s]; ok {
return action
}
if a := batch.Invoke(c).Merge().ToA(); found {
return a
}
return carapace.ActionFiles()
return carapace.ActionFiles() // fallback
})
}
func actionCustomEnvironmentVariables() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
v, err := loadCustomVariables()
dir, err := xdg.UserConfigDir()
if err != nil {
return carapace.ActionMessage(err.Error())
}
vals := make([]string, 0)
for name, description := range v.Names {
vals = append(vals, name, description)
entries, err := os.ReadDir(dir + "/carapace/variables")
if err != nil {
return carapace.ActionMessage(err.Error()) // TODO ignore if not exists
}
return carapace.ActionValuesDescribed(vals...)
batch := carapace.Batch()
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".yaml") {
file := dir + "/carapace/variables/" + entry.Name()
batch = append(batch, carapace.ActionCallback(func(c carapace.Context) carapace.Action {
custom, err := loadCustomVariables(file)
if err != nil {
return carapace.ActionMessage(err.Error())
}
if custom.Condition != nil && !custom.Condition(c) {
return carapace.ActionValues() // skip when condition failed
}
vals := make([]string, 0)
for name, description := range custom.Variables {
vals = append(vals, name, description)
}
return carapace.ActionValuesDescribed(vals...)
}))
}
}
return batch.ToA()
}).Tag("custom environment variables")
}
func loadCustomVariables() (*variables, error) {
dir, err := xdg.UserConfigDir()
if err != nil {
return nil, err
}
content, err := os.ReadFile(dir + "/carapace/env.yaml")
func loadCustomVariables(file string) (*variables, error) {
content, err := os.ReadFile(file)
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
return &variables{
Names: map[string]string{},
Completion: make(map[string]carapace.Action),
Variables: map[string]string{},
VariableCompletion: make(map[string]carapace.Action),
}, nil
}

View File

@ -4,8 +4,8 @@ import "testing"
func TestKnownVariables(t *testing.T) {
for k, v := range knownVariables {
for name := range v.Completion {
if _, ok := v.Names[name]; !ok {
for name := range v.VariableCompletion {
if _, ok := v.Variables[name]; !ok {
t.Errorf("variables %#v is unknown in %#v", name, k)
}
}

View File

@ -3,13 +3,14 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/gh"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace-bridge/pkg/actions/bridge"
)
func init() {
knownVariables["gh"] = variables{
Condition: checkPath("gh"),
Names: map[string]string{
Condition: conditions.ConditionPath("gh"),
Variables: map[string]string{
"GH_TOKEN": "an authentication token for github.com API requests",
"GH_ENTERPRISE_TOKEN": "an authentication token for API requests to GitHub Enterprise",
"GH_HOST": "specify the GitHub hostname",
@ -24,7 +25,7 @@ func init() {
"GH_PROMPT_DISABLED": "set to any value to disable interactive prompting in the terminal",
"GH_PATH": "set the path to the gh executable",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"GH_REPO": gh.ActionOwnerRepositories(gh.HostOpts{}),
"GH_EDITOR": bridge.ActionCarapaceBin().Split(),
"GH_BROWSER": bridge.ActionCarapaceBin().Split(),

View File

@ -5,6 +5,7 @@ import (
"github.com/rsteube/carapace-bin/pkg/actions/net/http"
"github.com/rsteube/carapace-bin/pkg/actions/time"
"github.com/rsteube/carapace-bin/pkg/actions/tools/git"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace/pkg/style"
"github.com/spf13/cobra"
)
@ -12,8 +13,8 @@ import (
func init() {
_bool := carapace.ActionValues("true", "false").StyleF(style.ForKeyword)
knownVariables["git"] = variables{
Condition: checkPath("git"),
Names: map[string]string{
Condition: conditions.ConditionPath("git"),
Variables: map[string]string{
"GIT_ALTERNATE_OBJECT_DIRECTORIES": "is a colon-separated list which tells Git where to check for objects",
"GIT_ASKPASS": "is an override for the core.askpass configuration value",
"GIT_AUTHOR_DATE": "is the timestamp used for the “author” field",
@ -53,7 +54,7 @@ func init() {
"GIT_TRACE_SETUP": "shows information about what Git is discovering about the repository and environment its interacting with",
"GIT_WORK_TREE": "is the location of the root of the working directory for a non-bare repository",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
// TODO complete more variables
"GIT_ALTERNATE_OBJECT_DIRECTORIES": carapace.ActionDirectories().MultiParts(":"),
"GIT_ASKPASS": git.ActionConfigValues("core.askpass"),

View File

@ -3,13 +3,15 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/golang"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace-bridge/pkg/actions/bridge"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
knownVariables["golang"] = variables{
Names: map[string]string{
Condition: conditions.ConditionPath("go"),
Variables: map[string]string{
"AR": "The command to use to manipulate library archives when building with the gccgo compiler",
"CC": "The command to use to compile C code",
"CGO_CFFLAGS_ALLOW": "Like CGO_CFLAGS_ALLOW but for the Fortran compiler",
@ -73,7 +75,7 @@ func init() {
"GOWORK": "In module aware mode, use the given go.work file as a workspace file",
"PKG_CONFIG": "Path to pkg-config tool",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
// TODO more flags
"AR": bridge.ActionCarapaceBin().Split(),
"CC": bridge.ActionCarapaceBin().Split(),

View File

@ -7,10 +7,10 @@ import (
func init() {
knownVariables["nocolor"] = variables{
Names: map[string]string{
Variables: map[string]string{
"NO_COLOR": "disable colors in supported commands",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"NO_COLOR": carapace.ActionStyledValuesDescribed(
"0", "show colors", style.Carapace.KeywordNegative,
"1", "do not show colors", style.Carapace.KeywordPositive,

View File

@ -2,14 +2,15 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
_bool := carapace.ActionValuesDescribed("0", "disabled", "1", "enabled").StyleF(style.ForKeyword)
knownVariables["node"] = variables{
Condition: checkPath("node"),
Names: map[string]string{
Condition: conditions.ConditionPath("node"),
Variables: map[string]string{
"NODE_DEBUG": "Comma-separated list of core modules that should print debug information",
"NODE_DEBUG_NATIVE": "Comma-separated list of C++ core modules that should print debug information",
"NODE_DISABLE_COLORS": "When set to 1, colors will not be used in the REPL",
@ -27,7 +28,7 @@ func init() {
"NODE_TLS_REJECT_UNAUTHORIZED": "When set to 0, TLS certificate validation is disabled",
"NODE_V8_COVERAGE": "When set, Node.js writes JavaScript code coverage information to dir",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
// TODO more completions
"NODE_DISABLE_COLORS": _bool,
"NODE_NO_WARNINGS": _bool,

View File

@ -2,20 +2,21 @@ package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/conditions"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
_bool := carapace.ActionValuesDescribed("0", "disabled", "1", "enabled").StyleF(style.ForKeyword)
knownVariables["rust"] = variables{
Condition: checkPath("rustc"),
Names: map[string]string{
Condition: conditions.ConditionPath("rustc"),
Variables: map[string]string{
"RUST_TEST_THREADS": "The test framework Rust provides executes tests in parallel",
"RUST_TEST_NOCAPTURE": "Synonym for the --nocapture flag",
"RUST_MIN_STACK": "Sets the minimum stack size for new threads",
"RUST_BACKTRACE": "Produces a backtrace in the output of a program which panics",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"RUST_TEST_THREADS": carapace.ActionValues(),
"RUST_TEST_NOCAPTURE": _bool,
"RUST_MIN_STACK": carapace.ActionValues(),

View File

@ -7,7 +7,7 @@ import (
func init() {
knownVariables["starship"] = variables{
Names: map[string]string{
Variables: map[string]string{
"STARSHIP_CACHE": "cache location",
"STARSHIP_CONFIG": "config location",
"STARSHIP_LOG": "log level",
@ -15,7 +15,7 @@ func init() {
"STARSHIP_SESSION_KEY": "session key",
"STARSHIP_SHELL": "shell",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"STARSHIP_CACHE": carapace.ActionDirectories(),
"STARSHIP_CONFIG": carapace.ActionFiles(),
"STARSHIP_LOG": carapace.ActionValues("debug", "error", "info", "trace", "warn").StyleF(style.ForLogLevel),

88
pkg/actions/env/terraform.go vendored Normal file
View File

@ -0,0 +1,88 @@
package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/terraform"
"github.com/rsteube/carapace-bridge/pkg/actions/bridge"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
_bool := carapace.ActionValues("true", "false").StyleF(style.ForKeyword)
knownVariables["terraform"] = variables{
Variables: map[string]string{
"TF_LOG": "Enables detailed logs to appear on stderr which is useful for debugging",
"TF_LOG_PATH": "This specifies where the log should persist its output to",
"TF_INPUT": "If set to \"false\" or \"0\", causes terraform commands to behave as if the -input=false flag was specified",
"TF_CLI_ARGS": "Additional cli arguments",
"TF_CLI_ARGS_init": "Additional cli arguments to init",
"TF_CLI_ARGS_validate": "Additional cli arguments to validate",
"TF_CLI_ARGS_plan": "Additional cli arguments to plan",
"TF_CLI_ARGS_apply": "Additional cli arguments to apply",
"TF_CLI_ARGS_destroy": "Additional cli arguments to destroy",
"TF_CLI_ARGS_console": "Additional cli arguments to console",
"TF_CLI_ARGS_fmt": "Additional cli arguments to fmt",
"TF_CLI_ARGS_force-unlock": "Additional cli arguments to force-unlock",
"TF_CLI_ARGS_get": "Additional cli arguments to get",
"TF_CLI_ARGS_graph": "Additional cli arguments to graph",
"TF_CLI_ARGS_import": "Additional cli arguments to import",
"TF_CLI_ARGS_login": "Additional cli arguments to login",
"TF_CLI_ARGS_logout": "Additional cli arguments to logout",
"TF_CLI_ARGS_metadata": "Additional cli arguments to metadata",
"TF_CLI_ARGS_output": "Additional cli arguments to output",
"TF_CLI_ARGS_providers": "Additional cli arguments to providers",
"TF_CLI_ARGS_refresh": "Additional cli arguments to refresh",
"TF_CLI_ARGS_show": "Additional cli arguments to show",
"TF_CLI_ARGS_state": "Additional cli arguments to state",
"TF_CLI_ARGS_taint": "Additional cli arguments to taint",
"TF_CLI_ARGS_test": "Additional cli arguments to test",
"TF_CLI_ARGS_untaint": "Additional cli arguments to untaint",
"TF_CLI_ARGS_version": "Additional cli arguments to version",
"TF_CLI_ARGS_workspace": "Additional cli arguments to workspace",
"TF_DATA_DIR": "Changes the location where Terraform keeps its per-working-directory data",
"TF_WORKSPACE": "Selects the workspace",
"TF_IN_AUTOMATION": "Adjusts its output to avoid suggesting specific commands to run next",
"TF_REGISTRY_DISCOVERY_RETRY": "Max number of request retries the remote registry client will attempt",
"TF_REGISTRY_CLIENT_TIMEOUT": "Client timeout for requests ",
"TF_CLI_CONFIG_FILE": "Location of the Terraform CLI configuration file",
"TF_PLUGIN_CACHE_DIR": "Plugin cache directory",
"TF_IGNORE": "When set to \"trace\", Terraform will output debug messages to display ignored files and folder",
},
VariableCompletion: map[string]carapace.Action{
"TF_LOG": _bool,
"TF_LOG_PATH": carapace.ActionValues(),
"TF_INPUT": carapace.ActionFiles(),
"TF_CLI_ARGS": bridge.ActionCarapaceBin("terraform").Split(),
"TF_CLI_ARGS_init": bridge.ActionCarapaceBin("terraform", "init").Split(),
"TF_CLI_ARGS_validate": bridge.ActionCarapaceBin("terraform", "validate").Split(),
"TF_CLI_ARGS_plan": bridge.ActionCarapaceBin("terraform", "plan").Split(),
"TF_CLI_ARGS_apply": bridge.ActionCarapaceBin("terraform", "apply").Split(),
"TF_CLI_ARGS_destroy": bridge.ActionCarapaceBin("terraform", "destroy").Split(),
"TF_CLI_ARGS_console": bridge.ActionCarapaceBin("terraform", "console").Split(),
"TF_CLI_ARGS_fmt": bridge.ActionCarapaceBin("terraform", "fmt").Split(),
"TF_CLI_ARGS_force-unlock": bridge.ActionCarapaceBin("terraform", "force-unlock").Split(),
"TF_CLI_ARGS_get": bridge.ActionCarapaceBin("terraform", "get").Split(),
"TF_CLI_ARGS_graph": bridge.ActionCarapaceBin("terraform", "graph").Split(),
"TF_CLI_ARGS_import": bridge.ActionCarapaceBin("terraform", "import").Split(),
"TF_CLI_ARGS_login": bridge.ActionCarapaceBin("terraform", "login").Split(),
"TF_CLI_ARGS_logout": bridge.ActionCarapaceBin("terraform", "logout").Split(),
"TF_CLI_ARGS_metadata": bridge.ActionCarapaceBin("terraform", "metadata").Split(),
"TF_CLI_ARGS_output": bridge.ActionCarapaceBin("terraform", "output").Split(),
"TF_CLI_ARGS_providers": bridge.ActionCarapaceBin("terraform", "providers").Split(),
"TF_CLI_ARGS_refresh": bridge.ActionCarapaceBin("terraform", "refresh").Split(),
"TF_CLI_ARGS_show": bridge.ActionCarapaceBin("terraform", "show").Split(),
"TF_CLI_ARGS_state": bridge.ActionCarapaceBin("terraform", "state").Split(),
"TF_CLI_ARGS_taint": bridge.ActionCarapaceBin("terraform", "taint").Split(),
"TF_CLI_ARGS_test": bridge.ActionCarapaceBin("terraform", "test").Split(),
"TF_CLI_ARGS_untaint": bridge.ActionCarapaceBin("terraform", "untaint").Split(),
"TF_CLI_ARGS_version": bridge.ActionCarapaceBin("terraform", "version").Split(),
"TF_CLI_ARGS_workspace": bridge.ActionCarapaceBin("terraform", "workspace").Split(),
"TF_DATA_DIR": carapace.ActionDirectories(),
"TF_WORKSPACE": terraform.ActionWorkspaces(),
"TF_IN_AUTOMATION": _bool,
"TF_CLI_CONFIG_FILE": carapace.ActionFiles(),
"TF_PLUGIN_CACHE_DIR": carapace.ActionDirectories(),
"TF_IGNORE": carapace.ActionValues("trace").StyleF(style.ForLogLevel),
},
}
}

88
pkg/actions/env/tofu.go vendored Normal file
View File

@ -0,0 +1,88 @@
package env
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/tofu"
"github.com/rsteube/carapace-bridge/pkg/actions/bridge"
"github.com/rsteube/carapace/pkg/style"
)
func init() {
_bool := carapace.ActionValues("true", "false").StyleF(style.ForKeyword)
knownVariables["tofu"] = variables{
Variables: map[string]string{
"TF_LOG": "Enables detailed logs to appear on stderr which is useful for debugging",
"TF_LOG_PATH": "This specifies where the log should persist its output to",
"TF_INPUT": "If set to \"false\" or \"0\", causes tofu commands to behave as if the -input=false flag was specified",
"TF_CLI_ARGS": "Additional cli arguments",
"TF_CLI_ARGS_init": "Additional cli arguments to init",
"TF_CLI_ARGS_validate": "Additional cli arguments to validate",
"TF_CLI_ARGS_plan": "Additional cli arguments to plan",
"TF_CLI_ARGS_apply": "Additional cli arguments to apply",
"TF_CLI_ARGS_destroy": "Additional cli arguments to destroy",
"TF_CLI_ARGS_console": "Additional cli arguments to console",
"TF_CLI_ARGS_fmt": "Additional cli arguments to fmt",
"TF_CLI_ARGS_force-unlock": "Additional cli arguments to force-unlock",
"TF_CLI_ARGS_get": "Additional cli arguments to get",
"TF_CLI_ARGS_graph": "Additional cli arguments to graph",
"TF_CLI_ARGS_import": "Additional cli arguments to import",
"TF_CLI_ARGS_login": "Additional cli arguments to login",
"TF_CLI_ARGS_logout": "Additional cli arguments to logout",
"TF_CLI_ARGS_metadata": "Additional cli arguments to metadata",
"TF_CLI_ARGS_output": "Additional cli arguments to output",
"TF_CLI_ARGS_providers": "Additional cli arguments to providers",
"TF_CLI_ARGS_refresh": "Additional cli arguments to refresh",
"TF_CLI_ARGS_show": "Additional cli arguments to show",
"TF_CLI_ARGS_state": "Additional cli arguments to state",
"TF_CLI_ARGS_taint": "Additional cli arguments to taint",
"TF_CLI_ARGS_test": "Additional cli arguments to test",
"TF_CLI_ARGS_untaint": "Additional cli arguments to untaint",
"TF_CLI_ARGS_version": "Additional cli arguments to version",
"TF_CLI_ARGS_workspace": "Additional cli arguments to workspace",
"TF_DATA_DIR": "Changes the location where tofu keeps its per-working-directory data",
"TF_WORKSPACE": "Selects the workspace",
"TF_IN_AUTOMATION": "Adjusts its output to avoid suggesting specific commands to run next",
"TF_REGISTRY_DISCOVERY_RETRY": "Max number of request retries the remote registry client will attempt",
"TF_REGISTRY_CLIENT_TIMEOUT": "Client timeout for requests ",
"TF_CLI_CONFIG_FILE": "Location of the tofu CLI configuration file",
"TF_PLUGIN_CACHE_DIR": "Plugin cache directory",
"TF_IGNORE": "When set to \"trace\", tofu will output debug messages to display ignored files and folder",
},
VariableCompletion: map[string]carapace.Action{
"TF_LOG": _bool,
"TF_LOG_PATH": carapace.ActionValues(),
"TF_INPUT": carapace.ActionFiles(),
"TF_CLI_ARGS": bridge.ActionCarapaceBin("tofu").Split(),
"TF_CLI_ARGS_init": bridge.ActionCarapaceBin("tofu", "init").Split(),
"TF_CLI_ARGS_validate": bridge.ActionCarapaceBin("tofu", "validate").Split(),
"TF_CLI_ARGS_plan": bridge.ActionCarapaceBin("tofu", "plan").Split(),
"TF_CLI_ARGS_apply": bridge.ActionCarapaceBin("tofu", "apply").Split(),
"TF_CLI_ARGS_destroy": bridge.ActionCarapaceBin("tofu", "destroy").Split(),
"TF_CLI_ARGS_console": bridge.ActionCarapaceBin("tofu", "console").Split(),
"TF_CLI_ARGS_fmt": bridge.ActionCarapaceBin("tofu", "fmt").Split(),
"TF_CLI_ARGS_force-unlock": bridge.ActionCarapaceBin("tofu", "force-unlock").Split(),
"TF_CLI_ARGS_get": bridge.ActionCarapaceBin("tofu", "get").Split(),
"TF_CLI_ARGS_graph": bridge.ActionCarapaceBin("tofu", "graph").Split(),
"TF_CLI_ARGS_import": bridge.ActionCarapaceBin("tofu", "import").Split(),
"TF_CLI_ARGS_login": bridge.ActionCarapaceBin("tofu", "login").Split(),
"TF_CLI_ARGS_logout": bridge.ActionCarapaceBin("tofu", "logout").Split(),
"TF_CLI_ARGS_metadata": bridge.ActionCarapaceBin("tofu", "metadata").Split(),
"TF_CLI_ARGS_output": bridge.ActionCarapaceBin("tofu", "output").Split(),
"TF_CLI_ARGS_providers": bridge.ActionCarapaceBin("tofu", "providers").Split(),
"TF_CLI_ARGS_refresh": bridge.ActionCarapaceBin("tofu", "refresh").Split(),
"TF_CLI_ARGS_show": bridge.ActionCarapaceBin("tofu", "show").Split(),
"TF_CLI_ARGS_state": bridge.ActionCarapaceBin("tofu", "state").Split(),
"TF_CLI_ARGS_taint": bridge.ActionCarapaceBin("tofu", "taint").Split(),
"TF_CLI_ARGS_test": bridge.ActionCarapaceBin("tofu", "test").Split(),
"TF_CLI_ARGS_untaint": bridge.ActionCarapaceBin("tofu", "untaint").Split(),
"TF_CLI_ARGS_version": bridge.ActionCarapaceBin("tofu", "version").Split(),
"TF_CLI_ARGS_workspace": bridge.ActionCarapaceBin("tofu", "workspace").Split(),
"TF_DATA_DIR": carapace.ActionDirectories(),
"TF_WORKSPACE": tofu.ActionWorkspaces(),
"TF_IN_AUTOMATION": _bool,
"TF_CLI_CONFIG_FILE": carapace.ActionFiles(),
"TF_PLUGIN_CACHE_DIR": carapace.ActionDirectories(),
"TF_IGNORE": carapace.ActionValues("trace").StyleF(style.ForLogLevel),
},
}
}

View File

@ -6,7 +6,7 @@ import (
func init() {
knownVariables["xdg"] = variables{
Names: map[string]string{
Variables: map[string]string{
"XDG_DATA_HOME": "base directory relative to which user-specific data files should be stored",
"XDG_CONFIG_HOME": "base directory relative to which user-specific configuration files should be stored",
"XDG_STATE_HOME": "base directory relative to which user-specific state files should be stored",
@ -15,7 +15,7 @@ func init() {
"XDG_CACHE_HOME": "base directory relative to which user-specific non-essential data files should be stored",
"XDG_RUNTIME_DIR": "base directory relative to which user-specific non-essential runtime files should be stored",
},
Completion: map[string]carapace.Action{
VariableCompletion: map[string]carapace.Action{
"XDG_DATA_HOME": carapace.ActionDirectories(),
"XDG_CONFIG_HOME": carapace.ActionDirectories(),
"XDG_STATE_HOME": carapace.ActionDirectories(),

View File

@ -0,0 +1,11 @@
package conditions
import (
"github.com/rsteube/carapace-bin/internal/condition"
"github.com/rsteube/carapace-spec/pkg/macro"
)
var (
MacroMap = make(macro.MacroMap[condition.Macro])
MacroDescriptions = make(map[string]string)
)

18
pkg/conditions/fs.go Normal file
View File

@ -0,0 +1,18 @@
package conditions
import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/internal/condition"
"github.com/rsteube/carapace/pkg/traverse"
)
// ConditionParent checks if any parent directory contains one of the given file/directory
//
// ConditionParent(".git")
// ConditionParent("go.mod", "go.sum")
func ConditionParent(s ...string) condition.Condition {
return func(c carapace.Context) bool {
_, err := traverse.Parent(s...)(carapace.NewContext())
return err == nil
}
}

45
pkg/conditions/os.go Normal file
View File

@ -0,0 +1,45 @@
package conditions
import (
"os/exec"
"runtime"
"slices"
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/internal/condition"
)
// ConditionArch checks if the given names contain current `runtime.GOARCH`
//
// ConditionArch("amd64")
// ConditionArch("arm", "arm64")
func ConditionArch(s ...string) condition.Condition {
return func(c carapace.Context) bool {
return slices.Contains(s, runtime.GOARCH)
}
}
// ConditionOs checks if the given names contain current `runtime.GOOS`
//
// ConditionOs("windows")
// ConditionOs("darwin", "linux")
func ConditionOs(s ...string) condition.Condition {
return func(c carapace.Context) bool {
return slices.Contains(s, runtime.GOOS)
}
}
// ConditionPath checks if any of the given executables are in PATH
//
// ConditionPath("git")
// ConditionPath("carapace", "go")
func ConditionPath(s ...string) condition.Condition {
return func(c carapace.Context) bool {
for _, file := range s {
if _, err := exec.LookPath(file); err == nil {
return true
}
}
return false
}
}