1package base
2
3import (
4	"flag"
5	"fmt"
6	"os"
7	"sort"
8	"strings"
9)
10
11// Copyright 2011 The Go Authors. All rights reserved.
12// Use of this source code is governed by a BSD-style
13// copied from "github.com/golang/go/main.go"
14
15// Execute excute the commands
16func Execute() {
17	flag.Parse()
18	args := flag.Args()
19	if len(args) < 1 {
20		PrintUsage(os.Stderr, RootCommand)
21		return
22	}
23	cmdName := args[0] // for error messages
24	if args[0] == "help" {
25		Help(os.Stdout, args[1:])
26		return
27	}
28
29BigCmdLoop:
30	for bigCmd := RootCommand; ; {
31		for _, cmd := range bigCmd.Commands {
32			if cmd.Name() != args[0] {
33				continue
34			}
35			if len(cmd.Commands) > 0 {
36				// test sub commands
37				bigCmd = cmd
38				args = args[1:]
39				if len(args) == 0 {
40					PrintUsage(os.Stderr, bigCmd)
41					SetExitStatus(2)
42					Exit()
43				}
44				if args[0] == "help" {
45					// Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'.
46					Help(os.Stdout, append(strings.Split(cmdName, " "), args[1:]...))
47					return
48				}
49				cmdName += " " + args[0]
50				continue BigCmdLoop
51			}
52			if !cmd.Runnable() {
53				continue
54			}
55			cmd.Flag.Usage = func() { cmd.Usage() }
56			if cmd.CustomFlags {
57				args = args[1:]
58			} else {
59				cmd.Flag.Parse(args[1:])
60				args = cmd.Flag.Args()
61			}
62
63			buildCommandText(cmd)
64			cmd.Run(cmd, args)
65			Exit()
66			return
67		}
68		helpArg := ""
69		if i := strings.LastIndex(cmdName, " "); i >= 0 {
70			helpArg = " " + cmdName[:i]
71		}
72		fmt.Fprintf(os.Stderr, "%s %s: unknown command\nRun '%s help%s' for usage.\n", CommandEnv.Exec, cmdName, CommandEnv.Exec, helpArg)
73		SetExitStatus(2)
74		Exit()
75	}
76}
77
78// Sort sorts the commands
79func Sort() {
80	sort.Slice(RootCommand.Commands, func(i, j int) bool {
81		return SortLessFunc(RootCommand.Commands[i], RootCommand.Commands[j])
82	})
83}
84
85// SortLessFunc used for sort commands list, can be override from outside
86var SortLessFunc = func(i, j *Command) bool {
87	return i.Name() < j.Name()
88}
89