Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion cmd/gh/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"net"
"os"
"os/exec"
"path"
"strings"

Expand Down Expand Up @@ -40,11 +41,26 @@ func main() {
cmd, _, err := command.RootCmd.Traverse(expandedArgs)
if err != nil || cmd == command.RootCmd {
originalArgs := expandedArgs
expandedArgs, err = command.ExpandAlias(os.Args)
expandedArgs, isShell, err := command.ExpandAlias(os.Args)
if err != nil {
fmt.Fprintf(stderr, "failed to process aliases: %s\n", err)
os.Exit(2)
}

if isShell {
err = command.ExecuteShellAlias(expandedArgs)
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
os.Exit(ee.ExitCode())
}

fmt.Fprintf(stderr, "failed to run external command: %s", err)
os.Exit(3)
}

os.Exit(0)
}

if hasDebug {
fmt.Fprintf(stderr, "%v -> %v\n", originalArgs, expandedArgs)
}
Expand Down
89 changes: 50 additions & 39 deletions command/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,39 @@ func init() {
aliasCmd.AddCommand(aliasSetCmd)
aliasCmd.AddCommand(aliasListCmd)
aliasCmd.AddCommand(aliasDeleteCmd)

aliasSetCmd.Flags().BoolP("shell", "s", false, "Declare an alias to be passed through a shell interpreter")
}

var aliasCmd = &cobra.Command{
Use: "alias",
Short: "Create shortcuts for gh commands",
Short: "Create command shortcuts",
Long: heredoc.Doc(`
Aliases can be used to make shortcuts for gh commands or to compose multiple commands.

Run "gh help alias set" to learn more.
`),
}

var aliasSetCmd = &cobra.Command{
Use: "set <alias> <expansion>",
Short: "Create a shortcut for a gh command",
Long: `Declare a word as a command alias that will expand to the specified command.
Long: heredoc.Doc(`
Declare a word as a command alias that will expand to the specified command(s).

The expansion may specify additional arguments and flags. If the expansion
includes positional placeholders such as '$1', '$2', etc., any extra arguments
that follow the invocation of an alias will be inserted appropriately.

If '--shell' is specified, the alias will be run through a shell interpreter (sh). This allows you
to compose commands with "|" or redirect with ">". Note that extra arguments following the alias
will not be automatically passed to the expanded expression. To have a shell alias receive
arguments, you must explicitly accept them using "$1", "$2", etc., or "$@" to accept all of them.

Platform note: on Windows, shell aliases are executed via "sh" as installed by Git For Windows. If
you have installed git on Windows in some other way, shell aliases may not work for you.

The expansion may specify additional arguments and flags. If the expansion
includes positional placeholders such as '$1', '$2', etc., any extra arguments
that follow the invocation of an alias will be inserted appropriately.`,
Quotes must always be used when defining a command as in the examples.`),
Example: heredoc.Doc(`
$ gh alias set pv 'pr view'
$ gh pv -w 123
Expand All @@ -41,13 +59,12 @@ that follow the invocation of an alias will be inserted appropriately.`,
$ gh alias set epicsBy 'issue list --author="$1" --label="epic"'
$ gh epicsBy vilmibm
#=> gh issue list --author="vilmibm" --label="epic"
`),
Args: cobra.MinimumNArgs(2),
RunE: aliasSet,

// NB: this allows a user to eschew quotes when specifying an alias expansion. We'll have to
// revisit it if we ever want to add flags to alias set but we have no current plans for that.
DisableFlagParsing: true,
$ gh alias set --shell igrep 'gh issue list --label="$1" | grep $2'
$ gh igrep epic foo
#=> gh issue list --label="epic" | grep "foo"`),
Args: cobra.ExactArgs(2),
RunE: aliasSet,
}

func aliasSet(cmd *cobra.Command, args []string) error {
Expand All @@ -63,19 +80,26 @@ func aliasSet(cmd *cobra.Command, args []string) error {
}

alias := args[0]
expansion := processArgs(args[1:])

expansionStr := strings.Join(expansion, " ")
expansion := args[1]

out := colorableOut(cmd)
fmt.Fprintf(out, "- Adding alias for %s: %s\n", utils.Bold(alias), utils.Bold(expansionStr))
fmt.Fprintf(out, "- Adding alias for %s: %s\n", utils.Bold(alias), utils.Bold(expansion))

shell, err := cmd.Flags().GetBool("shell")
if err != nil {
return err
}
if shell && !strings.HasPrefix(expansion, "!") {
expansion = "!" + expansion
}
isExternal := strings.HasPrefix(expansion, "!")

if validCommand([]string{alias}) {
if validCommand(alias) {
return fmt.Errorf("could not create alias: %q is already a gh command", alias)
}

if !validCommand(expansion) {
return fmt.Errorf("could not create alias: %s does not correspond to a gh command", utils.Bold(expansionStr))
if !isExternal && !validCommand(expansion) {
return fmt.Errorf("could not create alias: %s does not correspond to a gh command", expansion)
}

successMsg := fmt.Sprintf("%s Added alias.", utils.Green("✓"))
Expand All @@ -86,11 +110,11 @@ func aliasSet(cmd *cobra.Command, args []string) error {
utils.Green("✓"),
utils.Bold(alias),
utils.Bold(oldExpansion),
utils.Bold(expansionStr),
utils.Bold(expansion),
)
}

err = aliasCfg.Add(alias, expansionStr)
err = aliasCfg.Add(alias, expansion)
if err != nil {
return fmt.Errorf("could not create alias: %s", err)
}
Expand All @@ -100,26 +124,13 @@ func aliasSet(cmd *cobra.Command, args []string) error {
return nil
}

func validCommand(expansion []string) bool {
cmd, _, err := RootCmd.Traverse(expansion)
return err == nil && cmd != RootCmd
}

func processArgs(args []string) []string {
if len(args) == 1 {
split, _ := shlex.Split(args[0])
return split
}

newArgs := []string{}
for _, a := range args {
if !strings.HasPrefix(a, "-") && strings.Contains(a, " ") {
a = fmt.Sprintf("%q", a)
}
newArgs = append(newArgs, a)
func validCommand(expansion string) bool {
split, err := shlex.Split(expansion)
if err != nil {
return false
}

return newArgs
cmd, _, err := RootCmd.Traverse(split)
return err == nil && cmd != RootCmd
}

var aliasListCmd = &cobra.Command{
Expand Down
Loading