github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/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/ungtb10d/cli/v2/internal/config" 12 "github.com/ungtb10d/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 := cfg.Aliases() 27 28 expansion, getErr := aliases.Get(args[1]) 29 if getErr != nil { 30 return 31 } 32 33 if strings.HasPrefix(expansion, "!") { 34 isShell = true 35 if findShFunc == nil { 36 findShFunc = findSh 37 } 38 shPath, shErr := findShFunc() 39 if shErr != nil { 40 err = shErr 41 return 42 } 43 44 expanded = []string{shPath, "-c", expansion[1:]} 45 46 if len(args[2:]) > 0 { 47 expanded = append(expanded, "--") 48 expanded = append(expanded, args[2:]...) 49 } 50 51 return 52 } 53 54 extraArgs := []string{} 55 for i, a := range args[2:] { 56 if !strings.Contains(expansion, "$") { 57 extraArgs = append(extraArgs, a) 58 } else { 59 expansion = strings.ReplaceAll(expansion, fmt.Sprintf("$%d", i+1), a) 60 } 61 } 62 lingeringRE := regexp.MustCompile(`\$\d`) 63 if lingeringRE.MatchString(expansion) { 64 err = fmt.Errorf("not enough arguments for alias: %s", expansion) 65 return 66 } 67 68 var newArgs []string 69 newArgs, err = shlex.Split(expansion) 70 if err != nil { 71 return 72 } 73 74 expanded = append(newArgs, extraArgs...) 75 return 76 } 77 78 func findSh() (string, error) { 79 shPath, err := findsh.Find() 80 if err != nil { 81 if errors.Is(err, exec.ErrNotFound) { 82 if runtime.GOOS == "windows" { 83 return "", errors.New("unable to locate sh to execute the shell alias with. The sh.exe interpreter is typically distributed with Git for Windows.") 84 } 85 return "", errors.New("unable to locate sh to execute shell alias with") 86 } 87 return "", err 88 } 89 return shPath, nil 90 }