1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
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
}
|