commands/alias/set/alias_set.go (120 lines of code) (raw):

package set import ( "fmt" "strings" "gitlab.com/gitlab-org/cli/pkg/iostreams" "gitlab.com/gitlab-org/cli/commands/cmdutils" "github.com/MakeNowJust/heredoc/v2" "github.com/google/shlex" "github.com/spf13/cobra" "gitlab.com/gitlab-org/cli/internal/config" ) type SetOptions struct { Config func() (config.Config, error) Name string Expansion string IsShell bool RootCmd *cobra.Command IO *iostreams.IOStreams } func NewCmdSet(f *cmdutils.Factory, runF func(*SetOptions) error) *cobra.Command { opts := &SetOptions{ Config: f.Config, } aliasSetCmd := &cobra.Command{ Use: "set <alias name> '<command>' [flags]", Short: `Set an alias for a longer command.`, Long: heredoc.Doc(` Declare a word as an alias for a longer command. Your expansion might include arguments and flags. If your expansion includes positional placeholders such as '$1' or '$2', any extra arguments that follow the invocation of an alias are inserted appropriately. Specify '--shell' in your alias to run it through 'sh', a shell converter. Shell conversion enables you to compose commands with "|" or redirect with ">", with these caveats: - Any extra arguments following the alias are not passed to the expanded expression arguments by default. - You must explicitly accept the arguments using '$1', '$2', and so on. - Use '$@' to accept all arguments. For Windows users only: - On Windows, shell aliases are executed with 'sh' as installed by Git For Windows. If you installed Git in some other way in Windows, shell aliases might not work for you. - Always use quotation marks when defining a command, as in the examples. `), Example: heredoc.Doc(` $ glab alias set mrv 'mr view' $ glab mrv -w 123 > glab mr view -w 123 $ glab alias set createissue 'glab create issue --title "$1"' $ glab createissue "My Issue" --description "Something is broken." > glab create issue --title "My Issue" --description "Something is broken." $ glab alias set --shell igrep 'glab issue list --assignee="$1" | grep $2' $ glab igrep user foo > glab issue list --assignee="user" | grep "foo" `), Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { opts.RootCmd = cmd.Root() opts.Name = args[0] opts.Expansion = args[1] opts.IO = f.IO if runF != nil { return runF(opts) } return setRun(cmd, opts) }, } aliasSetCmd.Flags().BoolVarP(&opts.IsShell, "shell", "s", false, "Declare an alias to be passed through a shell interpreter.") return aliasSetCmd } func setRun(cmd *cobra.Command, opts *SetOptions) error { c := opts.IO.Color() cfg, err := opts.Config() if err != nil { return err } aliasCfg, err := cfg.Aliases() if err != nil { return err } if opts.IO.IsaTTY && opts.IO.IsErrTTY { fmt.Fprintf(opts.IO.StdErr, "- Adding alias for %s: %s.\n", c.Bold(opts.Name), c.Bold(opts.Expansion)) } expansion := opts.Expansion isShell := opts.IsShell if isShell && !strings.HasPrefix(expansion, "!") { expansion = "!" + expansion } isShell = strings.HasPrefix(expansion, "!") if validCommand(opts.RootCmd, opts.Name) { return fmt.Errorf("could not create alias: %q is already a glab command.", opts.Name) } if !isShell && !validCommand(opts.RootCmd, expansion) { return fmt.Errorf("could not create alias: %s does not correspond to a glab command.", expansion) } successMsg := fmt.Sprintf("%s Added alias.", c.Green("✓")) if oldExpansion, ok := aliasCfg.Get(opts.Name); ok { successMsg = fmt.Sprintf("%s Changed alias %s from %s to %s.", c.Green("✓"), c.Bold(opts.Name), c.Bold(oldExpansion), c.Bold(expansion), ) } err = aliasCfg.Set(opts.Name, expansion) if err != nil { return fmt.Errorf("could not create alias: %s", err) } fmt.Fprintln(opts.IO.StdErr, successMsg) return nil } func validCommand(rootCmd *cobra.Command, expansion string) bool { split, err := shlex.Split(expansion) if err != nil { return false } cmd, _, err := rootCmd.Traverse(split) return err == nil && cmd != rootCmd }