Skip to content

Commit

Permalink
Merge pull request #1851 from rsteube/env-custom
Browse files Browse the repository at this point in the history
env: support custom variables
  • Loading branch information
rsteube authored Sep 20, 2023
2 parents 18a06dd + 29bffd9 commit 3cf3dbf
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 21 deletions.
161 changes: 161 additions & 0 deletions docs/src/environment-custom.cast

Large diffs are not rendered by default.

17 changes: 15 additions & 2 deletions docs/src/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ For other shells custom functions are added.
![](./environment.cast)

## Custom definitions
## Custom variables

*TODO:* define using `~/.config/carapace/env.yaml`
Custom variables can be defined in `~/.config/carapace/env.yaml`

```yaml
names:
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"]
```
![](./environment-custom.cast)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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.10.5
github.com/rsteube/carapace-spec v0.10.6
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
golang.org/x/mod v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ 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.10.5 h1:ZA62YgYpm/0y6TsbGWqpqpw5Xkq6CkfnW0fz4K9ozxw=
github.com/rsteube/carapace-spec v0.10.5/go.mod h1:g6sfFykdrYbK3PEIc0rFrFFffPMsoGFSTTp6uaZEB0c=
github.com/rsteube/carapace-spec v0.10.6 h1:vlM/tLSQdNdXlXbXk5j6eI6r6jb0n4eeLPYev+mIjhQ=
github.com/rsteube/carapace-spec v0.10.6/go.mod h1:tZIZjpCdeb8WClSdHDf95FN1LB168CrFD1ImROUZnds=
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=
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,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",
},
Values: map[string]carapace.Action{
Completion: 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",
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/carapace.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func init() {
"CARAPACE_SANDBOX": "mock context for sandbox tests",
"CARAPACE_ZSH_HASH_DIRS": "zsh hash directories",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"CARAPACE_COVERDIR": carapace.ActionDirectories(),
"CARAPACE_ENV": carapace.ActionValues("0", "1"),
"CARAPACE_HIDDEN": carapace.ActionValues("0", "1"),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/cargo.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func init() {
"CARGO_TERM_QUIET": "Quiet mode, see term.quiet",
"CARGO_TERM_VERBOSE": "The default terminal verbosity, see term.verbose",
},
Values: map[string]carapace.Action{
Completion: 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(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func init() {
"HTTPS_PROXY": "https proxy server",
"PATH": "A list of directories to be searched when executing commands",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"PATH": carapace.ActionDirectories().List(string(_os.PathListSeparator)).NoSpace(),
},
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/common_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func init() {
"TERM": "The current terminal emulation",
"MAIL": "Location of where the current user’s mail is stored",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"HOME": carapace.ActionDirectories(),
"LANG": os.ActionLanguages(),
"LOGNAME": os.ActionUsers(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func init() {
"DOCKER_TLS_VERIFY": "When set Docker uses TLS and verifies the remote",
"BUILDKIT_PROGRESS": "Set type of progress output",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"DOCKER_CERT_PATH": carapace.ActionDirectories(),
"DOCKER_CONFIG": carapace.ActionFiles(),
"DOCKER_HIDE_LEGACY_COMMANDS": carapace.ActionStyledValuesDescribed(
Expand Down
82 changes: 78 additions & 4 deletions pkg/actions/env/env.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
package env

import (
"os"
"os/exec"

"github.com/rsteube/carapace"
spec "github.com/rsteube/carapace-spec"
"github.com/rsteube/carapace/pkg/xdg"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)

type variables struct {
Condition func(c carapace.Context) bool
Names map[string]string
Values map[string]carapace.Action
Condition func(c carapace.Context) bool
Names map[string]string
Completion map[string]carapace.Action
}

func (v *variables) UnmarshalYAML(unmarshal func(interface{}) error) error {
var env struct {
Names map[string]string
Completion map[string][]string
}
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{})
}
return nil
}

func checkPath(s string) func(c carapace.Context) bool {
Expand All @@ -22,6 +43,13 @@ func checkPath(s string) func(c carapace.Context) bool {
var knownVariables = map[string]variables{}

func ActionKnownEnvironmentVariables() carapace.Action {
return carapace.Batch(
actionKnownEnvironmentVariables(),
actionCustomEnvironmentVariables(),
).ToA()
}

func actionKnownEnvironmentVariables() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
vals := make([]string, 0)
for _, v := range knownVariables {
Expand All @@ -39,11 +67,57 @@ func ActionKnownEnvironmentVariables() carapace.Action {

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
}
}

for _, v := range knownVariables {
if action, ok := v.Values[s]; ok {
if action, ok := v.Completion[s]; ok {
return action
}
}
return carapace.ActionFiles()
})
}

func actionCustomEnvironmentVariables() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
v, err := loadCustomVariables()
if err != nil {
return carapace.ActionMessage(err.Error())
}

vals := make([]string, 0)
for name, description := range v.Names {
vals = append(vals, name, description)
}
return carapace.ActionValuesDescribed(vals...)
}).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")
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
return &variables{
Names: map[string]string{},
Completion: make(map[string]carapace.Action),
}, nil
}

var v variables
if err := yaml.Unmarshal(content, &v); err != nil {
return nil, err
}

return &v, nil
}
2 changes: 1 addition & 1 deletion pkg/actions/env/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "testing"

func TestKnownVariables(t *testing.T) {
for k, v := range knownVariables {
for name := range v.Values {
for name := range v.Completion {
if _, ok := v.Names[name]; !ok {
t.Errorf("variables %#v is unknown in %#v", name, k)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/gh.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,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",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"GH_REPO": gh.ActionOwnerRepositories(gh.HostOpts{}),
"GH_EDITOR": bridge.ActionCarapaceBin().Split(),
"GH_BROWSER": bridge.ActionCarapaceBin().Split(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func init() {
"GIT_TRACE_SETUP": "shows information about what Git is discovering about the repository and environment it’s interacting with",
"GIT_WORK_TREE": "is the location of the root of the working directory for a non-bare repository",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
// TODO complete more variables
"GIT_ALTERNATE_OBJECT_DIRECTORIES": carapace.ActionDirectories().MultiParts(":"),
"GIT_ASKPASS": git.ActionConfigValues("core.askpass"),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/golang.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,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",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
// TODO more flags
"AR": bridge.ActionCarapaceBin().Split(),
"CC": bridge.ActionCarapaceBin().Split(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/nocolor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func init() {
Names: map[string]string{
"NO_COLOR": "disable colors in supported commands",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"NO_COLOR": carapace.ActionStyledValuesDescribed(
"0", "show colors", style.Carapace.KeywordNegative,
"1", "do not show colors", style.Carapace.KeywordPositive,
Expand Down
2 changes: 1 addition & 1 deletion pkg/actions/env/xdg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
Values: map[string]carapace.Action{
Completion: map[string]carapace.Action{
"XDG_DATA_HOME": carapace.ActionDirectories(),
"XDG_CONFIG_HOME": carapace.ActionDirectories(),
"XDG_STATE_HOME": carapace.ActionDirectories(),
Expand Down

0 comments on commit 3cf3dbf

Please sign in to comment.