diff --git a/autocomplete/orchestra b/autocomplete/orchestra index 7eb6b81..2233590 100644 --- a/autocomplete/orchestra +++ b/autocomplete/orchestra @@ -1,13 +1,65 @@ -#! /bin/bash +#!/bin/bash -_cli_bash_autocomplete() { - local cur prev opts base +_orchestra_find_projectdir() { + filename="orchestra.yml" + current_dir=$(pwd) + while [ "$current_dir" != "/" ]; do + if [ -f "$current_dir/$filename" ]; then + echo "${current_dir}" + break + fi + current_dir=$(dirname "$current_dir") + done +} + +_orchestra_targets_autcomplete() { + projdir=$(_orchestra_find_projectdir) + svcs=$(cd "${projdir}" 2>/dev/null && ls -d -- **/service.* 2>/dev/null) + stacks=$(echo "${svcs}" | cut -d/ -f-1 | sort -u) + echo "${stacks} ${svcs}" +} + +_orchestra_bash_autocomplete() { + local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 + opts="build export install logs ps restart start stop test help" + targets=$(_orchestra_targets_autcomplete) + case "${COMP_WORDS[1]}" in + build|install|logs|ps|stop) + COMPREPLY=( $(compgen -W "${targets}" -- ${cur}) ) + return 0 + ;; + test) + if [[ "${prev}" == "test" || "${prev}" =~ --* ]]; then + COMPREPLY=( $(compgen -W "--verbose --race" -- ${cur}) ) + fi + COMPREPLY+=( $(compgen -W "${targets}" -- ${cur}) ) + return 0 + ;; + start|restart) + if [[ "${prev}" == "start" || "${prev}" == "restart" ]]; then + COMPREPLY=( $(compgen -W "--logs --attach" -- ${cur}) ) + fi + COMPREPLY+=( $(compgen -W "${targets}" -- ${cur}) ) + return 0 + ;; + *) + if [[ "${prev}" == "orchestra" ]]; then + COMPREPLY=( $(compgen -W "--help --version --config" -- ${cur}) ) + fi + if [[ "${prev}" == "--help" || "${prev}" == "--version" ]]; then + return 0 + fi + if [[ "${prev}" == "--config" ]]; then + COMPREPLY=( $(compgen -f -- ${cur}) ) + return 0 + fi + COMPREPLY+=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; + esac } -complete -F _cli_bash_autocomplete orchestra +complete -F _orchestra_bash_autocomplete orchestra diff --git a/commands/build.go b/commands/build.go index e2856b7..805ce2b 100644 --- a/commands/build.go +++ b/commands/build.go @@ -14,10 +14,9 @@ import ( ) var BuildCommand = &cli.Command{ - Name: "build", - Usage: "Build service(s)", - Action: BeforeAfterWrapper(BuildAction), - BashComplete: ServicesBashComplete, + Name: "build", + Usage: "Build service(s)", + Action: BeforeAfterWrapper(BuildAction), } func BuildAction(c *cli.Context) error { diff --git a/commands/export.go b/commands/export.go index 6473ec1..6504a47 100644 --- a/commands/export.go +++ b/commands/export.go @@ -10,10 +10,9 @@ import ( ) var ExportCommand = &cli.Command{ - Name: "export", - Usage: "Export those *#%&! env vars ", - Action: BeforeAfterWrapper(ExportAction), - BashComplete: ServicesBashComplete, + Name: "export", + Usage: "Export those *#%&! env vars ", + Action: BeforeAfterWrapper(ExportAction), } func ExportAction(c *cli.Context) error { diff --git a/commands/install.go b/commands/install.go index e7f979e..85f19cd 100644 --- a/commands/install.go +++ b/commands/install.go @@ -14,10 +14,10 @@ import ( ) var InstallCommand = &cli.Command{ - Name: "install", - Usage: "Installs all the services", - Action: BeforeAfterWrapper(InstallAction), - BashComplete: ServicesBashComplete} + Name: "install", + Usage: "Installs all the services", + Action: BeforeAfterWrapper(InstallAction), +} // InstallAction installs all the services (or the specified ones) func InstallAction(c *cli.Context) error { diff --git a/commands/logs.go b/commands/logs.go index 0417060..c4e37bf 100644 --- a/commands/logs.go +++ b/commands/logs.go @@ -14,10 +14,9 @@ import ( ) var LogsCommand = &cli.Command{ - Name: "logs", - Usage: "Aggregate services logs", - Action: BeforeAfterWrapper(LogsAction), - BashComplete: ServicesBashComplete, + Name: "logs", + Usage: "Aggregate services logs", + Action: BeforeAfterWrapper(LogsAction), } var logReceiver chan string diff --git a/commands/restart.go b/commands/restart.go index 58bdc40..8be1161 100644 --- a/commands/restart.go +++ b/commands/restart.go @@ -11,10 +11,9 @@ import ( ) var RestartCommand = &cli.Command{ - Name: "restart", - Usage: "Restarts all the services", - Action: BeforeAfterWrapper(RestartAction), - BashComplete: ServicesBashComplete, + Name: "restart", + Usage: "Restarts all the services", + Action: BeforeAfterWrapper(RestartAction), Flags: []cli.Flag{ &cli.BoolFlag{ Name: "attach, a", diff --git a/commands/start.go b/commands/start.go index adcf9d1..60d6486 100644 --- a/commands/start.go +++ b/commands/start.go @@ -17,10 +17,9 @@ import ( ) var StartCommand = &cli.Command{ - Name: "start", - Usage: "Starts all the services", - Action: BeforeAfterWrapper(StartAction), - BashComplete: ServicesBashComplete, + Name: "start", + Usage: "Starts all the services", + Action: BeforeAfterWrapper(StartAction), Flags: []cli.Flag{ &cli.BoolFlag{ Name: "attach, a", diff --git a/commands/stop.go b/commands/stop.go index e0844bb..3004b88 100644 --- a/commands/stop.go +++ b/commands/stop.go @@ -11,10 +11,10 @@ import ( ) var StopCommand = &cli.Command{ - Name: "stop", - Usage: "Stops all the services", - Action: BeforeAfterWrapper(StopAction), - BashComplete: ServicesBashComplete, + Name: "stop", + Usage: "Stops all the services", + Action: BeforeAfterWrapper(StopAction), + Args: true, } // StopAction stops all the services (or the specified ones) diff --git a/commands/test.go b/commands/test.go index 6fb7569..8557a4e 100644 --- a/commands/test.go +++ b/commands/test.go @@ -13,10 +13,9 @@ import ( ) var TestCommand = &cli.Command{ - Name: "test", - Usage: "Runs go test ./... for every service", - Action: BeforeAfterWrapper(TestAction), - BashComplete: ServicesBashComplete, + Name: "test", + Usage: "Runs go test ./... for every service", + Action: BeforeAfterWrapper(TestAction), Flags: []cli.Flag{ &cli.BoolFlag{ Name: "verbose, v", diff --git a/commands/utils.go b/commands/utils.go index 5cb36ea..94fa422 100644 --- a/commands/utils.go +++ b/commands/utils.go @@ -1,9 +1,9 @@ package commands import ( - "fmt" "math" "os" + "path/filepath" "strings" log "github.com/cihub/seelog" @@ -21,17 +21,28 @@ const niceness = "1" func FilterServices(c *cli.Context) map[string]*services.Service { excludeMode := 0 args := c.Args().Slice() + included := make(map[string]bool) + for _, s := range args { name := s if strings.HasPrefix(s, "~") { name = strings.Replace(s, "~", "", 1) } + // Remove trailing slash to help with file autocomplete + name = strings.TrimRight(name, "/") + // Alias `.` to the current service if it exists + if name == "." { + cwd, _ := os.Getwd() + name, _ = filepath.Rel(services.ProjectPath, cwd) + } + // Check if arg match a service or a stack if _, ok := services.Registry[name]; ok { if strings.HasPrefix(s, "~") { excludeMode += 1 delete(services.Registry, name) } else { excludeMode -= 1 + included[name] = true } } else if stack, ok := services.StackRegistry[name]; ok { if strings.HasPrefix(s, "~") { @@ -42,9 +53,12 @@ func FilterServices(c *cli.Context) map[string]*services.Service { delete(services.StackRegistry, name) } else { excludeMode -= 1 + for _, svc := range stack { + included[svc.Name] = true + } } } else { - _ = log.Errorf("Service or stack %s not found", s) + _ = log.Errorf("Service or stack %s not found", name) return nil } } @@ -53,18 +67,8 @@ func FilterServices(c *cli.Context) map[string]*services.Service { os.Exit(1) } if excludeMode < 0 { - for name, svc := range services.Registry { - included := false - for _, s := range args { - if name == s { - included = true - break - } - if svc.Stack == s { - included = true - } - } - if !included { + for name := range services.Registry { + if !included[name] { delete(services.Registry, name) } } @@ -72,16 +76,6 @@ func FilterServices(c *cli.Context) map[string]*services.Service { return services.Registry } -func ServicesBashComplete(c *cli.Context) { - for stack := range services.StackRegistry { - fmt.Println(stack) - } - for name := range services.Registry { - fmt.Println(name) - fmt.Println("~" + name) - } -} - func BeforeAfterWrapper(f func(c *cli.Context) error) func(c *cli.Context) error { return func(c *cli.Context) error { err := config.GetBeforeFunc()(c) diff --git a/main.go b/main.go index 911d42b..66a34eb 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,6 @@ func main() { app = cli.NewApp() app.Name = "Orchestra" app.Usage = "Orchestrate Go Services (Tifo)" - app.EnableBashCompletion = true app.Commands = []*cli.Command{ commands.BuildCommand, commands.ExportCommand,