From 08cd1a61d34106e36862b64d478c997775c2e4f1 Mon Sep 17 00:00:00 2001 From: Daniel Lewan Date: Fri, 12 Nov 2021 12:54:01 +0100 Subject: [PATCH] add git like subcommand deferring mechanism This commit implements a simple mechanism of deferring unknown subcommands to other executables in $PATH. When users executes `kks foo` kks will try to run `kks-foo` command. --- README.md | 6 ++++++ cmd/external.go | 27 +++++++++++++++++++++++++++ cmd/root.go | 5 ++++- main.go | 8 +++++++- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 cmd/external.go diff --git a/README.md b/README.md index ff2dea3..a43a1a3 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,12 @@ ENVIRONMENT VARIABLES Use "kks -h" for command usage. ``` +### Unknown command + +When unknown command is run, `kks` will try to find an executable named +`kks-` in `$PATH`. If the executable is found, `kks` will run it +with all arguments that were provided to the unknown command. + ## Configuration `kks` can be configured through environment variables. diff --git a/cmd/external.go b/cmd/external.go new file mode 100644 index 0000000..237a2e1 --- /dev/null +++ b/cmd/external.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "syscall" +) + +func External(args []string, original error) error { + if len(args) == 0 { + return original + } + + thisExecutable := filepath.Base(os.Args[0]) + path, err := exec.LookPath(fmt.Sprintf("%s-%s", thisExecutable, args[0])) + if err != nil { + // no such executable - return original error + return original + } + if len(args) < 1 { + args = args[1:] + } + + return syscall.Exec(path, args, os.Environ()) +} diff --git a/cmd/root.go b/cmd/root.go index b04146a..2c77bf4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,6 +2,7 @@ package cmd import ( _ "embed" + "errors" "fmt" "os" ) @@ -9,6 +10,8 @@ import ( //go:embed embed/help var helpTxt string +var UnknownSubcommand = errors.New("unknown subcommand") + func Root(args []string) error { if len(args) < 1 || args[0] == "-h" || args[0] == "--help" { printHelp() @@ -39,7 +42,7 @@ func Root(args []string) error { } } - return fmt.Errorf("unknown subcommand: %s", subcommand) + return fmt.Errorf("can't run %s: %w", subcommand, UnknownSubcommand) } func containsString(s []string, e string) bool { diff --git a/main.go b/main.go index 55df9b7..a7e26c9 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "log" "os" @@ -18,7 +19,12 @@ func main() { os.Exit(0) } - if err := cmd.Root(os.Args[1:]); err != nil { + err := cmd.Root(os.Args[1:]) + + if err != nil && errors.Is(err, cmd.UnknownSubcommand) { + err = cmd.External(os.Args[1:], err) + } + if err != nil { log.Fatal(err) } }