github.com/tuotoo/go-ethereum@v1.7.4-0.20171121184211-049797d40a24/cmd/geth/usage.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum 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 // go-ethereum 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 go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the geth command usage template and generator. 18 19 package main 20 21 import ( 22 "io" 23 "sort" 24 25 "github.com/ethereum/go-ethereum/cmd/utils" 26 "github.com/ethereum/go-ethereum/internal/debug" 27 "gopkg.in/urfave/cli.v1" 28 "strings" 29 ) 30 31 // AppHelpTemplate is the test template for the default, global app help topic. 32 var AppHelpTemplate = `NAME: 33 {{.App.Name}} - {{.App.Usage}} 34 35 Copyright 2013-2017 The go-ethereum Authors 36 37 USAGE: 38 {{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}} 39 {{if .App.Version}} 40 VERSION: 41 {{.App.Version}} 42 {{end}}{{if len .App.Authors}} 43 AUTHOR(S): 44 {{range .App.Authors}}{{ . }}{{end}} 45 {{end}}{{if .App.Commands}} 46 COMMANDS: 47 {{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} 48 {{end}}{{end}}{{if .FlagGroups}} 49 {{range .FlagGroups}}{{.Name}} OPTIONS: 50 {{range .Flags}}{{.}} 51 {{end}} 52 {{end}}{{end}}{{if .App.Copyright }} 53 COPYRIGHT: 54 {{.App.Copyright}} 55 {{end}} 56 ` 57 58 // flagGroup is a collection of flags belonging to a single topic. 59 type flagGroup struct { 60 Name string 61 Flags []cli.Flag 62 } 63 64 // AppHelpFlagGroups is the application flags, grouped by functionality. 65 var AppHelpFlagGroups = []flagGroup{ 66 { 67 Name: "ETHEREUM", 68 Flags: []cli.Flag{ 69 configFileFlag, 70 utils.DataDirFlag, 71 utils.KeyStoreDirFlag, 72 utils.NoUSBFlag, 73 utils.NetworkIdFlag, 74 utils.TestnetFlag, 75 utils.RinkebyFlag, 76 utils.SyncModeFlag, 77 utils.EthStatsURLFlag, 78 utils.IdentityFlag, 79 utils.LightServFlag, 80 utils.LightPeersFlag, 81 utils.LightKDFFlag, 82 }, 83 }, 84 {Name: "DEVELOPER CHAIN", 85 Flags: []cli.Flag{ 86 utils.DeveloperFlag, 87 utils.DeveloperPeriodFlag, 88 }, 89 }, 90 { 91 Name: "ETHASH", 92 Flags: []cli.Flag{ 93 utils.EthashCacheDirFlag, 94 utils.EthashCachesInMemoryFlag, 95 utils.EthashCachesOnDiskFlag, 96 utils.EthashDatasetDirFlag, 97 utils.EthashDatasetsInMemoryFlag, 98 utils.EthashDatasetsOnDiskFlag, 99 }, 100 }, 101 //{ 102 // Name: "DASHBOARD", 103 // Flags: []cli.Flag{ 104 // utils.DashboardEnabledFlag, 105 // utils.DashboardAddrFlag, 106 // utils.DashboardPortFlag, 107 // utils.DashboardRefreshFlag, 108 // utils.DashboardAssetsFlag, 109 // }, 110 //}, 111 { 112 Name: "TRANSACTION POOL", 113 Flags: []cli.Flag{ 114 utils.TxPoolNoLocalsFlag, 115 utils.TxPoolJournalFlag, 116 utils.TxPoolRejournalFlag, 117 utils.TxPoolPriceLimitFlag, 118 utils.TxPoolPriceBumpFlag, 119 utils.TxPoolAccountSlotsFlag, 120 utils.TxPoolGlobalSlotsFlag, 121 utils.TxPoolAccountQueueFlag, 122 utils.TxPoolGlobalQueueFlag, 123 utils.TxPoolLifetimeFlag, 124 }, 125 }, 126 { 127 Name: "PERFORMANCE TUNING", 128 Flags: []cli.Flag{ 129 utils.CacheFlag, 130 utils.TrieCacheGenFlag, 131 }, 132 }, 133 { 134 Name: "ACCOUNT", 135 Flags: []cli.Flag{ 136 utils.UnlockedAccountFlag, 137 utils.PasswordFileFlag, 138 }, 139 }, 140 { 141 Name: "API AND CONSOLE", 142 Flags: []cli.Flag{ 143 utils.RPCEnabledFlag, 144 utils.RPCListenAddrFlag, 145 utils.RPCPortFlag, 146 utils.RPCApiFlag, 147 utils.WSEnabledFlag, 148 utils.WSListenAddrFlag, 149 utils.WSPortFlag, 150 utils.WSApiFlag, 151 utils.WSAllowedOriginsFlag, 152 utils.IPCDisabledFlag, 153 utils.IPCPathFlag, 154 utils.RPCCORSDomainFlag, 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.DiscoveryV5Flag, 172 utils.NetrestrictFlag, 173 utils.NodeKeyFileFlag, 174 utils.NodeKeyHexFlag, 175 }, 176 }, 177 { 178 Name: "MINER", 179 Flags: []cli.Flag{ 180 utils.MiningEnabledFlag, 181 utils.MinerThreadsFlag, 182 utils.EtherbaseFlag, 183 utils.TargetGasLimitFlag, 184 utils.GasPriceFlag, 185 utils.ExtraDataFlag, 186 }, 187 }, 188 { 189 Name: "GAS PRICE ORACLE", 190 Flags: []cli.Flag{ 191 utils.GpoBlocksFlag, 192 utils.GpoPercentileFlag, 193 }, 194 }, 195 { 196 Name: "VIRTUAL MACHINE", 197 Flags: []cli.Flag{ 198 utils.VMEnableDebugFlag, 199 }, 200 }, 201 { 202 Name: "LOGGING AND DEBUGGING", 203 Flags: append([]cli.Flag{ 204 utils.MetricsEnabledFlag, 205 utils.FakePoWFlag, 206 utils.NoCompactionFlag, 207 }, debug.Flags...), 208 }, 209 { 210 Name: "WHISPER (EXPERIMENTAL)", 211 Flags: whisperFlags, 212 }, 213 { 214 Name: "DEPRECATED", 215 Flags: []cli.Flag{ 216 utils.FastSyncFlag, 217 utils.LightModeFlag, 218 }, 219 }, 220 { 221 Name: "MISC", 222 }, 223 } 224 225 // byCategory sorts an array of flagGroup by Name in the order 226 // defined in AppHelpFlagGroups. 227 type byCategory []flagGroup 228 229 func (a byCategory) Len() int { return len(a) } 230 func (a byCategory) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 231 func (a byCategory) Less(i, j int) bool { 232 iCat, jCat := a[i].Name, a[j].Name 233 iIdx, jIdx := len(AppHelpFlagGroups), len(AppHelpFlagGroups) // ensure non categorized flags come last 234 235 for i, group := range AppHelpFlagGroups { 236 if iCat == group.Name { 237 iIdx = i 238 } 239 if jCat == group.Name { 240 jIdx = i 241 } 242 } 243 244 return iIdx < jIdx 245 } 246 247 func flagCategory(flag cli.Flag) string { 248 for _, category := range AppHelpFlagGroups { 249 for _, flg := range category.Flags { 250 if flg.GetName() == flag.GetName() { 251 return category.Name 252 } 253 } 254 } 255 return "MISC" 256 } 257 258 func init() { 259 // Override the default app help template 260 cli.AppHelpTemplate = AppHelpTemplate 261 262 // Define a one shot struct to pass to the usage template 263 type helpData struct { 264 App interface{} 265 FlagGroups []flagGroup 266 } 267 268 // Override the default app help printer, but only for the global app help 269 originalHelpPrinter := cli.HelpPrinter 270 cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { 271 if tmpl == AppHelpTemplate { 272 // Iterate over all the flags and add any uncategorized ones 273 categorized := make(map[string]struct{}) 274 for _, group := range AppHelpFlagGroups { 275 for _, flag := range group.Flags { 276 categorized[flag.String()] = struct{}{} 277 } 278 } 279 uncategorized := []cli.Flag{} 280 for _, flag := range data.(*cli.App).Flags { 281 if _, ok := categorized[flag.String()]; !ok { 282 if strings.HasPrefix(flag.GetName(), "dashboard") { 283 continue 284 } 285 uncategorized = append(uncategorized, flag) 286 } 287 } 288 if len(uncategorized) > 0 { 289 // Append all ungategorized options to the misc group 290 miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) 291 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) 292 293 // Make sure they are removed afterwards 294 defer func() { 295 AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] 296 }() 297 } 298 // Render out custom usage screen 299 originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups}) 300 } else if tmpl == utils.CommandHelpTemplate { 301 // Iterate over all command specific flags and categorize them 302 categorized := make(map[string][]cli.Flag) 303 for _, flag := range data.(cli.Command).Flags { 304 if _, ok := categorized[flag.String()]; !ok { 305 categorized[flagCategory(flag)] = append(categorized[flagCategory(flag)], flag) 306 } 307 } 308 309 // sort to get a stable ordering 310 sorted := make([]flagGroup, 0, len(categorized)) 311 for cat, flgs := range categorized { 312 sorted = append(sorted, flagGroup{cat, flgs}) 313 } 314 sort.Sort(byCategory(sorted)) 315 316 // add sorted array to data and render with default printer 317 originalHelpPrinter(w, tmpl, map[string]interface{}{ 318 "cmd": data, 319 "categorizedFlags": sorted, 320 }) 321 } else { 322 originalHelpPrinter(w, tmpl, data) 323 } 324 } 325 }