diff --git a/client.go b/client.go index f64d752..b81b799 100644 --- a/client.go +++ b/client.go @@ -16,6 +16,7 @@ type KVSClient struct { httpClient *http.Client profiles map[string]Profile activeProfile string + variables map[string]string // Shell variables for scripting } // NewKVSClient creates a new KVS client instance @@ -25,7 +26,8 @@ func NewKVSClient(baseURL string) *KVSClient { httpClient: &http.Client{ Timeout: 30 * time.Second, }, - profiles: make(map[string]Profile), + profiles: make(map[string]Profile), + variables: make(map[string]string), } } diff --git a/cmd_system.go b/cmd_system.go index dc0111b..60132ca 100644 --- a/cmd_system.go +++ b/cmd_system.go @@ -67,6 +67,13 @@ Export/Import: --skip-existing - Skip existing keys (default) --overwrite - Overwrite existing keys +Shell Scripting: + set - Set shell variable + unset - Remove shell variable + vars - List all variables + Variables: $VAR or ${VAR} + Environment: $ENV:VARNAME + Batch Operations: batch - Execute commands from file source - Alias for batch diff --git a/cmd_variables.go b/cmd_variables.go new file mode 100644 index 0000000..76257ac --- /dev/null +++ b/cmd_variables.go @@ -0,0 +1,84 @@ +package main + +import ( + "fmt" + "os" + "regexp" + "strings" +) + +// handleSet sets a shell variable +func (c *KVSClient) handleSet(args []string) { + if len(args) < 2 { + fmt.Println(red("Usage: set ")) + fmt.Println("Example: set USER_ID abc-123") + return + } + + name := args[0] + value := strings.Join(args[1:], " ") + + c.variables[name] = value + fmt.Printf(green("Set:")+" %s = %s\n", name, value) +} + +// handleUnset removes a shell variable +func (c *KVSClient) handleUnset(args []string) { + if len(args) < 1 { + fmt.Println(red("Usage: unset ")) + return + } + + name := args[0] + if _, exists := c.variables[name]; exists { + delete(c.variables, name) + fmt.Println(green("Unset:"), name) + } else { + fmt.Println(yellow("Variable not set:"), name) + } +} + +// handleVars lists all shell variables +func (c *KVSClient) handleVars(args []string) { + if len(c.variables) == 0 { + fmt.Println(yellow("No variables set")) + return + } + + fmt.Println(cyan("Shell Variables:")) + for name, value := range c.variables { + fmt.Printf(" %s = %s\n", name, value) + } +} + +// expandVariables performs variable substitution on a string +// Supports: +// - $VAR or ${VAR} for shell variables +// - $ENV:VAR for environment variables +func (c *KVSClient) expandVariables(input string) string { + // Pattern for $VAR or ${VAR} + varPattern := regexp.MustCompile(`\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?`) + + // Pattern for $ENV:VAR + envPattern := regexp.MustCompile(`\$ENV:([A-Za-z_][A-Za-z0-9_]*)`) + + // First, replace environment variables + result := envPattern.ReplaceAllStringFunc(input, func(match string) string { + varName := envPattern.FindStringSubmatch(match)[1] + if value, exists := os.LookupEnv(varName); exists { + return value + } + return match // Leave unchanged if not found + }) + + // Then, replace shell variables + result = varPattern.ReplaceAllStringFunc(result, func(match string) string { + varName := varPattern.FindStringSubmatch(match)[1] + if value, exists := c.variables[varName]; exists { + return value + } + return match // Leave unchanged if not found + }) + + return result +} diff --git a/main.go b/main.go index ba6a498..508c90d 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,9 @@ import ( // executeCommand executes a single command line func (c *KVSClient) executeCommand(line string) bool { + // Expand variables in the line + line = c.expandVariables(line) + parts := parseCommand(line) if len(parts) == 0 { return true @@ -66,6 +69,12 @@ func (c *KVSClient) executeCommand(line string) bool { c.handleImport(args) case "export-list": c.handleExportList(args) + case "set": + c.handleSet(args) + case "unset": + c.handleUnset(args) + case "vars": + c.handleVars(args) case "batch", "source": c.handleBatch(args, c.executeCommand) default: diff --git a/utils.go b/utils.go index cfbed9c..62c5c50 100644 --- a/utils.go +++ b/utils.go @@ -130,6 +130,9 @@ var completer = readline.NewPrefixCompleter( readline.PcItem("export"), readline.PcItem("import"), readline.PcItem("export-list"), + readline.PcItem("set"), + readline.PcItem("unset"), + readline.PcItem("vars"), readline.PcItem("batch"), readline.PcItem("source"), readline.PcItem("help"),