diff --git a/cli/autocomplete.go b/cli/autocomplete.go new file mode 100644 index 00000000..08af3436 --- /dev/null +++ b/cli/autocomplete.go @@ -0,0 +1,121 @@ +package cli + +import ( + "errors" + "fmt" + "io" + "net/http" + "os" + "path" + + "coopcloud.tech/abra/cli/internal" + "coopcloud.tech/abra/pkg/config" + "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" +) + +// downloadFile downloads a file brah +func downloadFile(filepath string, url string) (err error) { + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("bad status: %s", resp.Status) + } + + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + + return nil +} + +// AutoCompleteCommand helps people set up auto-complete in their shells +var AutoCompleteCommand = &cli.Command{ + Name: "autocomplete", + Usage: "Help set up shell autocompletion", + Aliases: []string{"ac"}, + Description: ` +This command helps set up autocompletion in your shell by downloading the +relevant autocompletion files and laying out what additional information must +be loaded. + +Example: + + abra autocomplete bash + +Supported shells are as follows: + + fish + zsh + bash +`, + ArgsUsage: "", + Action: func(c *cli.Context) error { + shellType := c.Args().First() + + if shellType == "" { + internal.ShowSubcommandHelpAndError(c, errors.New("no shell provided")) + } + + supportedShells := map[string]bool{ + "bash": true, + "zsh": true, + "fish": true, + } + + if _, ok := supportedShells[shellType]; !ok { + logrus.Fatalf("%s is not a supported shell right now, sorry", shellType) + } + + if shellType == "fish" { + shellType = "zsh" // handled the same on the autocompletion side + } + + autocompletionDir := path.Join(config.ABRA_DIR, "autocompletion") + if err := os.Mkdir(autocompletionDir, 0755); err != nil { + if !os.IsExist(err) { + logrus.Fatal(err) + } + logrus.Debugf("'%s' already created, moving on...", autocompletionDir) + } + + autocompletionFile := path.Join(config.ABRA_DIR, "autocompletion", shellType) + if _, err := os.Stat(autocompletionFile); err != nil && os.IsNotExist(err) { + url := fmt.Sprintf("https://git.coopcloud.tech/coop-cloud/abra/raw/branch/main/scripts/autocomplete/%s", shellType) + logrus.Infof("fetching %s", url) + if err := downloadFile(autocompletionFile, url); err != nil { + logrus.Fatal(err) + } + } + + switch shellType { + case "bash": + fmt.Println(fmt.Sprintf(` +# Run the following commands to install autocompletion +sudo mkdir /etc/bash/completion.d/ +sudo cp %s /etc/bash_completion.d/abra +source "/etc/bash/completion.d/abra +`, autocompletionFile)) + case "zsh": + fmt.Println(fmt.Sprintf(` +# Run the following commands to install autocompletion +sudo mkdir /etc/zsh/completion.d/ +sudo cp %s /etc/zsh/completion.d/abra +echo "PROG=abra\n_CLI_ZSH_AUTOCOMPLETE_HACK=1\nsource /etc/zsh/completion.d/abra" >> ~/.zshrc +`, autocompletionFile)) + } + + return nil + }, +} diff --git a/cli/cli.go b/cli/cli.go index 6b138933..1d2aa7e8 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -62,6 +62,7 @@ func newAbraApp(version, commit string) *cli.App { catalogue.CatalogueCommand, record.RecordCommand, UpgradeCommand, + AutoCompleteCommand, }, Flags: []cli.Flag{ VerboseFlag,