github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/utils/customflags.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2015 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package utils 26 27 import ( 28 "encoding" 29 "errors" 30 "flag" 31 "fmt" 32 "math/big" 33 "os" 34 "os/user" 35 "path" 36 "strings" 37 38 "github.com/ethereum/go-ethereum/common/math" 39 "gopkg.in/urfave/cli.v1" 40 ) 41 42 // 43 //参数分析。这允许我们将值扩展到绝对路径,当 44 // 45 type DirectoryString struct { 46 Value string 47 } 48 49 func (self *DirectoryString) String() string { 50 return self.Value 51 } 52 53 func (self *DirectoryString) Set(value string) error { 54 self.Value = expandPath(value) 55 return nil 56 } 57 58 //将接收到的字符串扩展为绝对路径的自定义cli.flag类型。 59 // 60 type DirectoryFlag struct { 61 Name string 62 Value DirectoryString 63 Usage string 64 } 65 66 func (self DirectoryFlag) String() string { 67 fmtString := "%s %v\t%v" 68 if len(self.Value.Value) > 0 { 69 fmtString = "%s \"%v\"\t%v" 70 } 71 return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) 72 } 73 74 func eachName(longName string, fn func(string)) { 75 parts := strings.Split(longName, ",") 76 for _, name := range parts { 77 name = strings.Trim(name, " ") 78 fn(name) 79 } 80 } 81 82 //由cli库调用,从环境中获取变量(如果在env中) 83 // 84 func (self DirectoryFlag) Apply(set *flag.FlagSet) { 85 eachName(self.Name, func(name string) { 86 set.Var(&self.Value, self.Name, self.Usage) 87 }) 88 } 89 90 type TextMarshaler interface { 91 encoding.TextMarshaler 92 encoding.TextUnmarshaler 93 } 94 95 //textmarshal将textmarshaler转换为flag.value 96 type textMarshalerVal struct { 97 v TextMarshaler 98 } 99 100 func (v textMarshalerVal) String() string { 101 if v.v == nil { 102 return "" 103 } 104 text, _ := v.v.MarshalText() 105 return string(text) 106 } 107 108 func (v textMarshalerVal) Set(s string) error { 109 return v.v.UnmarshalText([]byte(s)) 110 } 111 112 // 113 type TextMarshalerFlag struct { 114 Name string 115 Value TextMarshaler 116 Usage string 117 } 118 119 func (f TextMarshalerFlag) GetName() string { 120 return f.Name 121 } 122 123 func (f TextMarshalerFlag) String() string { 124 return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage) 125 } 126 127 func (f TextMarshalerFlag) Apply(set *flag.FlagSet) { 128 eachName(f.Name, func(name string) { 129 set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) 130 }) 131 } 132 133 // 134 func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { 135 val := ctx.GlobalGeneric(name) 136 if val == nil { 137 return nil 138 } 139 return val.(textMarshalerVal).v 140 } 141 142 // 143 // 144 type BigFlag struct { 145 Name string 146 Value *big.Int 147 Usage string 148 } 149 150 //big value将*big.int转换为flag.value 151 type bigValue big.Int 152 153 func (b *bigValue) String() string { 154 if b == nil { 155 return "" 156 } 157 return (*big.Int)(b).String() 158 } 159 160 func (b *bigValue) Set(s string) error { 161 int, ok := math.ParseBig256(s) 162 if !ok { 163 return errors.New("invalid integer syntax") 164 } 165 *b = (bigValue)(*int) 166 return nil 167 } 168 169 func (f BigFlag) GetName() string { 170 return f.Name 171 } 172 173 func (f BigFlag) String() string { 174 fmtString := "%s %v\t%v" 175 if f.Value != nil { 176 fmtString = "%s \"%v\"\t%v" 177 } 178 return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) 179 } 180 181 func (f BigFlag) Apply(set *flag.FlagSet) { 182 eachName(f.Name, func(name string) { 183 set.Var((*bigValue)(f.Value), f.Name, f.Usage) 184 }) 185 } 186 187 //GlobalBigFlag从全局标志集返回BigFlag的值。 188 func GlobalBig(ctx *cli.Context, name string) *big.Int { 189 val := ctx.GlobalGeneric(name) 190 if val == nil { 191 return nil 192 } 193 return (*big.Int)(val.(*bigValue)) 194 } 195 196 func prefixFor(name string) (prefix string) { 197 if len(name) == 1 { 198 prefix = "-" 199 } else { 200 prefix = "--" 201 } 202 203 return 204 } 205 206 func prefixedNames(fullName string) (prefixed string) { 207 parts := strings.Split(fullName, ",") 208 for i, name := range parts { 209 name = strings.Trim(name, " ") 210 prefixed += prefixFor(name) + name 211 if i < len(parts)-1 { 212 prefixed += ", " 213 } 214 } 215 return 216 } 217 218 func (self DirectoryFlag) GetName() string { 219 return self.Name 220 } 221 222 func (self *DirectoryFlag) Set(value string) { 223 self.Value.Value = value 224 } 225 226 //展开文件路径 227 //1。用用户主目录替换tilde 228 //2。扩展嵌入的环境变量 229 //三。清理路径,例如/a/b/。/c->/a/c 230 //注意,它有局限性,例如~someuser/tmp将不会扩展 231 func expandPath(p string) string { 232 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 233 if home := homeDir(); home != "" { 234 p = home + p[1:] 235 } 236 } 237 return path.Clean(os.ExpandEnv(p)) 238 } 239 240 func homeDir() string { 241 if home := os.Getenv("HOME"); home != "" { 242 return home 243 } 244 if usr, err := user.Current(); err == nil { 245 return usr.HomeDir 246 } 247 return "" 248 }