Hilbish/readline/completers/env.go

125 lines
3.3 KiB
Go

package completers
import (
"os"
"strings"
"github.com/maxlandon/readline"
)
// completeEnvironmentVariables - Returns all environment variables as suggestions
func completeEnvironmentVariables(lastWord string) (last string, completions []*readline.CompletionGroup) {
// Check if last input is made of several different variables
allVars := strings.Split(lastWord, "/")
lastVar := allVars[len(allVars)-1]
var evaluated = map[string]string{}
grp := &readline.CompletionGroup{
Name: "console OS environment",
MaxLength: 5, // Should be plenty enough
DisplayType: readline.TabDisplayGrid,
TrimSlash: true, // Some variables can be paths
}
for k, v := range clientEnv {
if strings.HasPrefix("$"+k, lastVar) {
grp.Suggestions = append(grp.Suggestions, "$"+k+"/")
evaluated[k] = v
}
}
completions = append(completions, grp)
return lastVar, completions
}
// clientEnv - Contains all OS environment variables, client-side.
// This is used for things like downloading/uploading files from localhost, etc.,
// therefore we need completion and parsing stuff, sometimes.
var clientEnv = map[string]string{}
// ParseEnvironmentVariables - Parses a line of input and replace detected environment variables with their values.
func ParseEnvironmentVariables(args []string) (processed []string, err error) {
for _, arg := range args {
// Anywhere a $ is assigned means there is an env variable
if strings.Contains(arg, "$") || strings.Contains(arg, "~") {
//Split in case env is embedded in path
envArgs := strings.Split(arg, "/")
// If its not a path
if len(envArgs) == 1 {
processed = append(processed, handleCuratedVar(arg))
}
// If len of the env var split is > 1, its a path
if len(envArgs) > 1 {
processed = append(processed, handleEmbeddedVar(arg))
}
} else if arg != "" && arg != " " {
// Else, if arg is not an environment variable, return it as is
processed = append(processed, arg)
}
}
return
}
// handleCuratedVar - Replace an environment variable alone and without any undesired characters attached
func handleCuratedVar(arg string) (value string) {
if strings.HasPrefix(arg, "$") && arg != "" && arg != "$" {
envVar := strings.TrimPrefix(arg, "$")
val, ok := clientEnv[envVar]
if !ok {
return envVar
}
return val
}
if arg != "" && arg == "~" {
return clientEnv["HOME"]
}
return arg
}
// handleEmbeddedVar - Replace an environment variable that is in the middle of a path, or other one-string combination
func handleEmbeddedVar(arg string) (value string) {
envArgs := strings.Split(arg, "/")
var path []string
for _, arg := range envArgs {
if strings.HasPrefix(arg, "$") && arg != "" && arg != "$" {
envVar := strings.TrimPrefix(arg, "$")
val, ok := clientEnv[envVar]
if !ok {
// Err will be caught when command is ran anyway, or completion will stop...
path = append(path, arg)
}
path = append(path, val)
} else if arg != "" && arg == "~" {
path = append(path, clientEnv["HOME"])
} else if arg != " " && arg != "" {
path = append(path, arg)
}
}
return strings.Join(path, "/")
}
// loadClientEnv - Loads all user environment variables
func loadClientEnv() error {
env := os.Environ()
for _, kv := range env {
key := strings.Split(kv, "=")[0]
value := strings.Split(kv, "=")[1]
clientEnv[key] = value
}
return nil
}