github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/main/commands/base/execute.go (about)

     1  package base
     2  
     3  import (
     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
    16  func Execute() {
    17  	flag.Usage = func() {
    18  		PrintUsage(os.Stderr, RootCommand)
    19  	}
    20  	flag.Parse()
    21  	args := flag.Args()
    22  	if len(args) < 1 {
    23  		PrintUsage(os.Stderr, RootCommand)
    24  		return
    25  	}
    26  	cmdName := args[0] // for error messages
    27  	if args[0] == "help" {
    28  		Help(os.Stdout, args[1:])
    29  		return
    30  	}
    31  
    32  BigCmdLoop:
    33  	for bigCmd := RootCommand; ; {
    34  		for _, cmd := range bigCmd.Commands {
    35  			if cmd.Name() != args[0] {
    36  				continue
    37  			}
    38  			if len(cmd.Commands) > 0 {
    39  				// test sub commands
    40  				bigCmd = cmd
    41  				args = args[1:]
    42  				if len(args) == 0 {
    43  					PrintUsage(os.Stderr, bigCmd)
    44  					SetExitStatus(2)
    45  					Exit()
    46  				}
    47  				if args[0] == "help" {
    48  					// Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'.
    49  					Help(os.Stdout, append(strings.Split(cmdName, " "), args[1:]...))
    50  					return
    51  				}
    52  				cmdName += " " + args[0]
    53  				continue BigCmdLoop
    54  			}
    55  			if !cmd.Runnable() {
    56  				continue
    57  			}
    58  			cmd.Flag.Usage = func() { cmd.Usage() }
    59  			if cmd.CustomFlags {
    60  				args = args[1:]
    61  			} else {
    62  				cmd.Flag.Parse(args[1:])
    63  				args = cmd.Flag.Args()
    64  			}
    65  
    66  			buildCommandText(cmd)
    67  			cmd.Run(cmd, args)
    68  			Exit()
    69  			return
    70  		}
    71  		helpArg := ""
    72  		if i := strings.LastIndex(cmdName, " "); i >= 0 {
    73  			helpArg = " " + cmdName[:i]
    74  		}
    75  		fmt.Fprintf(os.Stderr, "%s %s: unknown command\nRun '%s help%s' for usage.\n", CommandEnv.Exec, cmdName, CommandEnv.Exec, helpArg)
    76  		SetExitStatus(2)
    77  		Exit()
    78  	}
    79  }
    80  
    81  // SortCommands sorts the first level sub commands
    82  func SortCommands() {
    83  	sort.Slice(RootCommand.Commands, func(i, j int) bool {
    84  		return SortLessFunc(RootCommand.Commands[i], RootCommand.Commands[j])
    85  	})
    86  }
    87  
    88  // SortLessFunc used for sort commands list, can be override from outside
    89  var SortLessFunc = func(i, j *Command) bool {
    90  	return i.Name() < j.Name()
    91  }