github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/alias/expand/expand.go (about) 1 package expand 2 3 import ( 4 "errors" 5 "fmt" 6 "os/exec" 7 "regexp" 8 "runtime" 9 "strings" 10 11 "github.com/andrewhsu/cli/v2/internal/config" 12 "github.com/andrewhsu/cli/v2/pkg/findsh" 13 "github.com/google/shlex" 14 ) 15 16 // ExpandAlias processes argv to see if it should be rewritten according to a user's aliases. The 17 // second return value indicates whether the alias should be executed in a new shell process instead 18 // of running gh itself. 19 func ExpandAlias(cfg config.Config, args []string, findShFunc func() (string, error)) (expanded []string, isShell bool, err error) { 20 if len(args) < 2 { 21 // the command is lacking a subcommand 22 return 23 } 24 expanded = args[1:] 25 26 aliases, err := cfg.Aliases() 27 if err != nil { 28 return 29 } 30 31 expansion, ok := aliases.Get(args[1]) 32 if !ok { 33 return 34 } 35 36 if strings.HasPrefix(expansion, "!") { 37 isShell = true 38 if findShFunc == nil { 39 findShFunc = findSh 40 } 41 shPath, shErr := findShFunc() 42 if shErr != nil { 43 err = shErr 44 return 45 } 46 47 expanded = []string{shPath, "-c", expansion[1:]} 48 49 if len(args[2:]) > 0 { 50 expanded = append(expanded, "--") 51 expanded = append(expanded, args[2:]...) 52 } 53 54 return 55 } 56 57 extraArgs := []string{} 58 for i, a := range args[2:] { 59 if !strings.Contains(expansion, "$") { 60 extraArgs = append(extraArgs, a) 61 } else { 62 expansion = strings.ReplaceAll(expansion, fmt.Sprintf("$%d", i+1), a) 63 } 64 } 65 lingeringRE := regexp.MustCompile(`\$\d`) 66 if lingeringRE.MatchString(expansion) { 67 err = fmt.Errorf("not enough arguments for alias: %s", expansion) 68 return 69 } 70 71 var newArgs []string 72 newArgs, err = shlex.Split(expansion) 73 if err != nil { 74 return 75 } 76 77 expanded = append(newArgs, extraArgs...) 78 return 79 } 80 81 func findSh() (string, error) { 82 shPath, err := findsh.Find() 83 if err != nil { 84 if errors.Is(err, exec.ErrNotFound) { 85 if runtime.GOOS == "windows" { 86 return "", errors.New("unable to locate sh to execute the shell alias with. The sh.exe interpreter is typically distributed with Git for Windows.") 87 } 88 return "", errors.New("unable to locate sh to execute shell alias with") 89 } 90 return "", err 91 } 92 return shPath, nil 93 }