github.com/minio/console@v1.4.1/cmd/console/main.go (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2021 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  //
    17  
    18  package main
    19  
    20  import (
    21  	"os"
    22  	"path/filepath"
    23  	"sort"
    24  	"time"
    25  
    26  	"github.com/minio/cli"
    27  	"github.com/minio/console/pkg"
    28  	"github.com/minio/pkg/v3/console"
    29  	"github.com/minio/pkg/v3/trie"
    30  	"github.com/minio/pkg/v3/words"
    31  )
    32  
    33  // Help template for Console.
    34  var consoleHelpTemplate = `NAME:
    35   {{.Name}} - {{.Usage}}
    36  
    37  DESCRIPTION:
    38   {{.Description}}
    39  
    40  USAGE:
    41   {{.HelpName}} {{if .VisibleFlags}}[FLAGS] {{end}}COMMAND{{if .VisibleFlags}}{{end}} [ARGS...]
    42  
    43  COMMANDS:
    44   {{range .VisibleCommands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
    45   {{end}}{{if .VisibleFlags}}
    46  FLAGS:
    47   {{range .VisibleFlags}}{{.}}
    48   {{end}}{{end}}
    49  VERSION:
    50   {{.Version}}
    51  `
    52  
    53  func newApp(name string) *cli.App {
    54  	// Collection of console commands currently supported are.
    55  	var commands []cli.Command
    56  
    57  	// Collection of console commands currently supported in a trie tree.
    58  	commandsTree := trie.NewTrie()
    59  
    60  	// registerCommand registers a cli command.
    61  	registerCommand := func(command cli.Command) {
    62  		commands = append(commands, command)
    63  		commandsTree.Insert(command.Name)
    64  	}
    65  
    66  	// register commands
    67  	for _, cmd := range appCmds {
    68  		registerCommand(cmd)
    69  	}
    70  
    71  	findClosestCommands := func(command string) []string {
    72  		var closestCommands []string
    73  		closestCommands = append(closestCommands, commandsTree.PrefixMatch(command)...)
    74  
    75  		sort.Strings(closestCommands)
    76  		// Suggest other close commands - allow missed, wrongly added and
    77  		// even transposed characters
    78  		for _, value := range commandsTree.Walk(commandsTree.Root()) {
    79  			if sort.SearchStrings(closestCommands, value) < len(closestCommands) {
    80  				continue
    81  			}
    82  			// 2 is arbitrary and represents the max
    83  			// allowed number of typed errors
    84  			if words.DamerauLevenshteinDistance(command, value) < 2 {
    85  				closestCommands = append(closestCommands, value)
    86  			}
    87  		}
    88  
    89  		return closestCommands
    90  	}
    91  
    92  	cli.HelpFlag = cli.BoolFlag{
    93  		Name:  "help, h",
    94  		Usage: "show help",
    95  	}
    96  
    97  	app := cli.NewApp()
    98  	app.Name = name
    99  	app.Version = pkg.Version + " - " + pkg.ShortCommitID
   100  	app.Author = "MinIO, Inc."
   101  	app.Usage = "MinIO Console Server"
   102  	app.Description = `MinIO Console Server`
   103  	app.Copyright = "(c) 2021 MinIO, Inc."
   104  	app.Compiled, _ = time.Parse(time.RFC3339, pkg.ReleaseTime)
   105  	app.Commands = commands
   106  	app.HideHelpCommand = true // Hide `help, h` command, we already have `minio --help`.
   107  	app.CustomAppHelpTemplate = consoleHelpTemplate
   108  	app.CommandNotFound = func(_ *cli.Context, command string) {
   109  		console.Printf("‘%s’ is not a console sub-command. See ‘console --help’.\n", command)
   110  		closestCommands := findClosestCommands(command)
   111  		if len(closestCommands) > 0 {
   112  			console.Println()
   113  			console.Println("Did you mean one of these?")
   114  			for _, cmd := range closestCommands {
   115  				console.Printf("\t‘%s’\n", cmd)
   116  			}
   117  		}
   118  
   119  		os.Exit(1)
   120  	}
   121  
   122  	return app
   123  }
   124  
   125  func main() {
   126  	args := os.Args
   127  	// Set the orchestrator app name.
   128  	appName := filepath.Base(args[0])
   129  	// Run the app - exit on error.
   130  	if err := newApp(appName).Run(args); err != nil {
   131  		os.Exit(1)
   132  	}
   133  }