gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/cmd/attacher/usage.go (about) 1 // Copyright 2019 The aquachain Authors 2 // This file is part of aquachain. 3 // 4 // aquachain is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // aquachain 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with aquachain. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the aquachain command usage template and generator. 18 19 package main 20 21 import ( 22 "io" 23 "sort" 24 25 "strings" 26 27 "github.com/urfave/cli" 28 "gitlab.com/aquachain/aquachain/cmd/utils" 29 "gitlab.com/aquachain/aquachain/internal/debug" 30 ) 31 32 const logo = ` _ _ 33 __ _ __ _ _ _ __ _ ___| |__ __ _(_)_ __ 34 / _ '|/ _' | | | |/ _' |/ __| '_ \ / _' | | '_ \ 35 | (_| | (_| | |_| | (_| | (__| | | | (_| | | | | | 36 \__,_|\__, |\__,_|\__,_|\___|_| |_|\__,_|_|_| |_| 37 |_|` + "Update Often! https://gitlab.com/aquachain/aquachain\n\n" 38 39 // AppHelpTemplate is the test template for the default, global app help topic. 40 var AppHelpTemplate = logo + `NAME: 41 {{.App.Name}} - {{.App.Usage}} 42 43 Copyright 2018-2019 The aquachain authors 44 Copyright 2013-2018 The go-ethereum authors 45 46 USAGE: 47 {{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}} 48 {{if .App.Version}} 49 VERSION: 50 {{.App.Version}} 51 {{end}}{{if len .App.Authors}} 52 AUTHOR(S): 53 {{range .App.Authors}}{{ . }}{{end}} 54 {{end}}{{if .App.Commands}} 55 COMMANDS: 56 {{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} 57 {{end}}{{end}}{{if .FlagGroups}} 58 {{range .FlagGroups}}{{.Name}} OPTIONS: 59 {{range .Flags}}{{.}} 60 {{end}} 61 {{end}}{{end}}{{if .App.Copyright }} 62 COPYRIGHT: 63 {{.App.Copyright}} 64 {{end}} 65 ` 66 67 // flagGroup is a collection of flags belonging to a single topic. 68 type flagGroup struct { 69 Name string 70 Flags []cli.Flag 71 } 72 73 // AppHelpFlagGroups is the application flags, grouped by functionality. 74 var AppHelpFlagGroups = []flagGroup{ 75 { 76 Name: "Aquachain", 77 Flags: []cli.Flag{ 78 utils.NetworkIdFlag, 79 utils.IdentityFlag, 80 }, 81 }, 82 { 83 Name: "API AND CONSOLE", 84 Flags: []cli.Flag{ 85 utils.IPCPathFlag, 86 utils.JSpathFlag, 87 utils.ExecFlag, 88 utils.PreloadJSFlag, 89 }, 90 }, 91 { 92 Name: "LOGGING AND DEBUGGING", 93 Flags: append([]cli.Flag{ 94 utils.MetricsEnabledFlag, 95 utils.NoCompactionFlag, 96 }, debug.Flags...), 97 }, 98 { 99 Name: "MISC", 100 Flags: []cli.Flag{utils.FastSyncFlag}, 101 }, 102 } 103 104 // byCategory sorts an array of flagGroup by Name in the order 105 // defined in AppHelpFlagGroups. 106 type byCategory []flagGroup 107 108 func (a byCategory) Len() int { return len(a) } 109 func (a byCategory) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 110 func (a byCategory) Less(i, j int) bool { 111 iCat, jCat := a[i].Name, a[j].Name 112 iIdx, jIdx := len(AppHelpFlagGroups), len(AppHelpFlagGroups) // ensure non categorized flags come last 113 114 for i, group := range AppHelpFlagGroups { 115 if iCat == group.Name { 116 iIdx = i 117 } 118 if jCat == group.Name { 119 jIdx = i 120 } 121 } 122 123 return iIdx < jIdx 124 } 125 126 func flagCategory(flag cli.Flag) string { 127 for _, category := range AppHelpFlagGroups { 128 for _, flg := range category.Flags { 129 if flg.GetName() == flag.GetName() { 130 return category.Name 131 } 132 } 133 } 134 return "MISC" 135 } 136 137 func init() { 138 // Override the default app help template 139 cli.AppHelpTemplate = AppHelpTemplate 140 141 // Define a one shot struct to pass to the usage template 142 type helpData struct { 143 App interface{} 144 FlagGroups []flagGroup 145 } 146 147 // Override the default app help printer, but only for the global app help 148 originalHelpPrinter := cli.HelpPrinter 149 cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { 150 if tmpl == AppHelpTemplate { 151 // Iterate over all the flags and add any uncategorized ones 152 categorized := make(map[string]struct{}) 153 for _, group := range AppHelpFlagGroups { 154 for _, flag := range group.Flags { 155 categorized[flag.String()] = struct{}{} 156 } 157 } 158 uncategorized := []cli.Flag{} 159 for _, flag := range data.(*cli.App).Flags { 160 if _, ok := categorized[flag.String()]; !ok { 161 if strings.HasPrefix(flag.GetName(), "dashboard") { 162 continue 163 } 164 uncategorized = append(uncategorized, flag) 165 } 166 } 167 if len(uncategorized) > 0 { 168 // Append all ungategorized options to the misc group 169 miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) 170 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) 171 172 // Make sure they are removed afterwards 173 defer func() { 174 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] 175 }() 176 } 177 // Render out custom usage screen 178 originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups}) 179 } else if tmpl == utils.CommandHelpTemplate { 180 // Iterate over all command specific flags and categorize them 181 categorized := make(map[string][]cli.Flag) 182 for _, flag := range data.(cli.Command).Flags { 183 if _, ok := categorized[flag.String()]; !ok { 184 categorized[flagCategory(flag)] = append(categorized[flagCategory(flag)], flag) 185 } 186 } 187 188 // sort to get a stable ordering 189 sorted := make([]flagGroup, 0, len(categorized)) 190 for cat, flgs := range categorized { 191 sorted = append(sorted, flagGroup{cat, flgs}) 192 } 193 sort.Sort(byCategory(sorted)) 194 195 // add sorted array to data and render with default printer 196 originalHelpPrinter(w, tmpl, map[string]interface{}{ 197 "cmd": data, 198 "categorizedFlags": sorted, 199 }) 200 } else { 201 originalHelpPrinter(w, tmpl, data) 202 } 203 } 204 }