github.com/aquanetwork/aquachain@v1.7.8/cmd/aquachain/usage.go (about) 1 // Copyright 2015 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 "gitlab.com/aquachain/aquachain/cmd/utils" 28 "gitlab.com/aquachain/aquachain/internal/debug" 29 "gopkg.in/urfave/cli.v1" 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 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 configFileFlag, 79 utils.DataDirFlag, 80 utils.KeyStoreDirFlag, 81 utils.UseUSBFlag, 82 utils.NetworkIdFlag, 83 utils.TestnetFlag, 84 utils.Testnet2Flag, 85 utils.SyncModeFlag, 86 utils.GCModeFlag, 87 utils.AquaStatsURLFlag, 88 utils.IdentityFlag, 89 }, 90 }, 91 {Name: "DEVELOPER CHAIN", 92 Flags: []cli.Flag{ 93 utils.DeveloperFlag, 94 utils.DeveloperPeriodFlag, 95 }, 96 }, 97 { 98 Name: "AQUAHASH", 99 Flags: []cli.Flag{ 100 utils.AquahashCacheDirFlag, 101 utils.AquahashCachesInMemoryFlag, 102 utils.AquahashCachesOnDiskFlag, 103 utils.AquahashDatasetDirFlag, 104 utils.AquahashDatasetsInMemoryFlag, 105 utils.AquahashDatasetsOnDiskFlag, 106 }, 107 }, 108 { 109 Name: "TRANSACTION POOL", 110 Flags: []cli.Flag{ 111 utils.TxPoolNoLocalsFlag, 112 utils.TxPoolJournalFlag, 113 utils.TxPoolRejournalFlag, 114 utils.TxPoolPriceLimitFlag, 115 utils.TxPoolPriceBumpFlag, 116 utils.TxPoolAccountSlotsFlag, 117 utils.TxPoolGlobalSlotsFlag, 118 utils.TxPoolAccountQueueFlag, 119 utils.TxPoolGlobalQueueFlag, 120 utils.TxPoolLifetimeFlag, 121 }, 122 }, 123 { 124 Name: "PERFORMANCE TUNING", 125 Flags: []cli.Flag{ 126 utils.CacheFlag, 127 utils.CacheDatabaseFlag, 128 utils.CacheGCFlag, 129 utils.TrieCacheGenFlag, 130 }, 131 }, 132 { 133 Name: "ACCOUNT", 134 Flags: []cli.Flag{ 135 utils.UnlockedAccountFlag, 136 utils.PasswordFileFlag, 137 }, 138 }, 139 { 140 Name: "API AND CONSOLE", 141 Flags: []cli.Flag{ 142 utils.RPCEnabledFlag, 143 utils.RPCListenAddrFlag, 144 utils.RPCPortFlag, 145 utils.RPCApiFlag, 146 utils.WSEnabledFlag, 147 utils.WSListenAddrFlag, 148 utils.WSPortFlag, 149 utils.WSApiFlag, 150 utils.WSAllowedOriginsFlag, 151 utils.IPCDisabledFlag, 152 utils.IPCPathFlag, 153 utils.RPCCORSDomainFlag, 154 utils.RPCVirtualHostsFlag, 155 utils.JSpathFlag, 156 utils.ExecFlag, 157 utils.PreloadJSFlag, 158 }, 159 }, 160 { 161 Name: "NETWORKING", 162 Flags: []cli.Flag{ 163 utils.BootnodesFlag, 164 utils.BootnodesV4Flag, 165 utils.BootnodesV5Flag, 166 utils.ListenPortFlag, 167 utils.MaxPeersFlag, 168 utils.MaxPendingPeersFlag, 169 utils.NATFlag, 170 utils.NoDiscoverFlag, 171 utils.OfflineFlag, 172 utils.DiscoveryV5Flag, 173 utils.NetrestrictFlag, 174 utils.NodeKeyFileFlag, 175 utils.NodeKeyHexFlag, 176 }, 177 }, 178 { 179 Name: "MINER", 180 Flags: []cli.Flag{ 181 utils.MiningEnabledFlag, 182 utils.MinerThreadsFlag, 183 utils.AquabaseFlag, 184 utils.TargetGasLimitFlag, 185 utils.GasPriceFlag, 186 utils.ExtraDataFlag, 187 }, 188 }, 189 { 190 Name: "GAS PRICE ORACLE", 191 Flags: []cli.Flag{ 192 utils.GpoBlocksFlag, 193 utils.GpoPercentileFlag, 194 }, 195 }, 196 { 197 Name: "VIRTUAL MACHINE", 198 Flags: []cli.Flag{ 199 utils.VMEnableDebugFlag, 200 }, 201 }, 202 { 203 Name: "LOGGING AND DEBUGGING", 204 Flags: append([]cli.Flag{ 205 utils.MetricsEnabledFlag, 206 utils.FakePoWFlag, 207 utils.NoCompactionFlag, 208 }, debug.Flags...), 209 }, 210 { 211 Name: "WHISPER (EXPERIMENTAL)", 212 Flags: whisperFlags, 213 }, 214 { 215 Name: "DEPRECATED", 216 }, 217 { 218 Name: "MISC", 219 Flags: []cli.Flag{utils.FastSyncFlag}, 220 }, 221 } 222 223 // byCategory sorts an array of flagGroup by Name in the order 224 // defined in AppHelpFlagGroups. 225 type byCategory []flagGroup 226 227 func (a byCategory) Len() int { return len(a) } 228 func (a byCategory) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 229 func (a byCategory) Less(i, j int) bool { 230 iCat, jCat := a[i].Name, a[j].Name 231 iIdx, jIdx := len(AppHelpFlagGroups), len(AppHelpFlagGroups) // ensure non categorized flags come last 232 233 for i, group := range AppHelpFlagGroups { 234 if iCat == group.Name { 235 iIdx = i 236 } 237 if jCat == group.Name { 238 jIdx = i 239 } 240 } 241 242 return iIdx < jIdx 243 } 244 245 func flagCategory(flag cli.Flag) string { 246 for _, category := range AppHelpFlagGroups { 247 for _, flg := range category.Flags { 248 if flg.GetName() == flag.GetName() { 249 return category.Name 250 } 251 } 252 } 253 return "MISC" 254 } 255 256 func init() { 257 // Override the default app help template 258 cli.AppHelpTemplate = AppHelpTemplate 259 260 // Define a one shot struct to pass to the usage template 261 type helpData struct { 262 App interface{} 263 FlagGroups []flagGroup 264 } 265 266 // Override the default app help printer, but only for the global app help 267 originalHelpPrinter := cli.HelpPrinter 268 cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { 269 if tmpl == AppHelpTemplate { 270 // Iterate over all the flags and add any uncategorized ones 271 categorized := make(map[string]struct{}) 272 for _, group := range AppHelpFlagGroups { 273 for _, flag := range group.Flags { 274 categorized[flag.String()] = struct{}{} 275 } 276 } 277 uncategorized := []cli.Flag{} 278 for _, flag := range data.(*cli.App).Flags { 279 if _, ok := categorized[flag.String()]; !ok { 280 if strings.HasPrefix(flag.GetName(), "dashboard") { 281 continue 282 } 283 uncategorized = append(uncategorized, flag) 284 } 285 } 286 if len(uncategorized) > 0 { 287 // Append all ungategorized options to the misc group 288 miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) 289 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) 290 291 // Make sure they are removed afterwards 292 defer func() { 293 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] 294 }() 295 } 296 // Render out custom usage screen 297 originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups}) 298 } else if tmpl == utils.CommandHelpTemplate { 299 // Iterate over all command specific flags and categorize them 300 categorized := make(map[string][]cli.Flag) 301 for _, flag := range data.(cli.Command).Flags { 302 if _, ok := categorized[flag.String()]; !ok { 303 categorized[flagCategory(flag)] = append(categorized[flagCategory(flag)], flag) 304 } 305 } 306 307 // sort to get a stable ordering 308 sorted := make([]flagGroup, 0, len(categorized)) 309 for cat, flgs := range categorized { 310 sorted = append(sorted, flagGroup{cat, flgs}) 311 } 312 sort.Sort(byCategory(sorted)) 313 314 // add sorted array to data and render with default printer 315 originalHelpPrinter(w, tmpl, map[string]interface{}{ 316 "cmd": data, 317 "categorizedFlags": sorted, 318 }) 319 } else { 320 originalHelpPrinter(w, tmpl, data) 321 } 322 } 323 }