github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/utils/customflags.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:31</date> 10 //</624342606838501376> 11 12 13 package utils 14 15 import ( 16 "encoding" 17 "errors" 18 "flag" 19 "fmt" 20 "math/big" 21 "os" 22 "os/user" 23 "path" 24 "strings" 25 26 "github.com/ethereum/go-ethereum/common/math" 27 "gopkg.in/urfave/cli.v1" 28 ) 29 30 // 31 //参数分析。这允许我们将值扩展到绝对路径,当 32 // 33 type DirectoryString struct { 34 Value string 35 } 36 37 func (self *DirectoryString) String() string { 38 return self.Value 39 } 40 41 func (self *DirectoryString) Set(value string) error { 42 self.Value = expandPath(value) 43 return nil 44 } 45 46 //将接收到的字符串扩展为绝对路径的自定义cli.flag类型。 47 // 48 type DirectoryFlag struct { 49 Name string 50 Value DirectoryString 51 Usage string 52 } 53 54 func (self DirectoryFlag) String() string { 55 fmtString := "%s %v\t%v" 56 if len(self.Value.Value) > 0 { 57 fmtString = "%s \"%v\"\t%v" 58 } 59 return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) 60 } 61 62 func eachName(longName string, fn func(string)) { 63 parts := strings.Split(longName, ",") 64 for _, name := range parts { 65 name = strings.Trim(name, " ") 66 fn(name) 67 } 68 } 69 70 //由cli库调用,从环境中获取变量(如果在env中) 71 // 72 func (self DirectoryFlag) Apply(set *flag.FlagSet) { 73 eachName(self.Name, func(name string) { 74 set.Var(&self.Value, self.Name, self.Usage) 75 }) 76 } 77 78 type TextMarshaler interface { 79 encoding.TextMarshaler 80 encoding.TextUnmarshaler 81 } 82 83 //textmarshal将textmarshaler转换为flag.value 84 type textMarshalerVal struct { 85 v TextMarshaler 86 } 87 88 func (v textMarshalerVal) String() string { 89 if v.v == nil { 90 return "" 91 } 92 text, _ := v.v.MarshalText() 93 return string(text) 94 } 95 96 func (v textMarshalerVal) Set(s string) error { 97 return v.v.UnmarshalText([]byte(s)) 98 } 99 100 // 101 type TextMarshalerFlag struct { 102 Name string 103 Value TextMarshaler 104 Usage string 105 } 106 107 func (f TextMarshalerFlag) GetName() string { 108 return f.Name 109 } 110 111 func (f TextMarshalerFlag) String() string { 112 return fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage) 113 } 114 115 func (f TextMarshalerFlag) Apply(set *flag.FlagSet) { 116 eachName(f.Name, func(name string) { 117 set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage) 118 }) 119 } 120 121 // 122 func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler { 123 val := ctx.GlobalGeneric(name) 124 if val == nil { 125 return nil 126 } 127 return val.(textMarshalerVal).v 128 } 129 130 // 131 // 132 type BigFlag struct { 133 Name string 134 Value *big.Int 135 Usage string 136 } 137 138 //big value将*big.int转换为flag.value 139 type bigValue big.Int 140 141 func (b *bigValue) String() string { 142 if b == nil { 143 return "" 144 } 145 return (*big.Int)(b).String() 146 } 147 148 func (b *bigValue) Set(s string) error { 149 int, ok := math.ParseBig256(s) 150 if !ok { 151 return errors.New("invalid integer syntax") 152 } 153 *b = (bigValue)(*int) 154 return nil 155 } 156 157 func (f BigFlag) GetName() string { 158 return f.Name 159 } 160 161 func (f BigFlag) String() string { 162 fmtString := "%s %v\t%v" 163 if f.Value != nil { 164 fmtString = "%s \"%v\"\t%v" 165 } 166 return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) 167 } 168 169 func (f BigFlag) Apply(set *flag.FlagSet) { 170 eachName(f.Name, func(name string) { 171 set.Var((*bigValue)(f.Value), f.Name, f.Usage) 172 }) 173 } 174 175 //GlobalBigFlag从全局标志集返回BigFlag的值。 176 func GlobalBig(ctx *cli.Context, name string) *big.Int { 177 val := ctx.GlobalGeneric(name) 178 if val == nil { 179 return nil 180 } 181 return (*big.Int)(val.(*bigValue)) 182 } 183 184 func prefixFor(name string) (prefix string) { 185 if len(name) == 1 { 186 prefix = "-" 187 } else { 188 prefix = "--" 189 } 190 191 return 192 } 193 194 func prefixedNames(fullName string) (prefixed string) { 195 parts := strings.Split(fullName, ",") 196 for i, name := range parts { 197 name = strings.Trim(name, " ") 198 prefixed += prefixFor(name) + name 199 if i < len(parts)-1 { 200 prefixed += ", " 201 } 202 } 203 return 204 } 205 206 func (self DirectoryFlag) GetName() string { 207 return self.Name 208 } 209 210 func (self *DirectoryFlag) Set(value string) { 211 self.Value.Value = value 212 } 213 214 //展开文件路径 215 //1。用用户主目录替换tilde 216 //2。扩展嵌入的环境变量 217 //三。清理路径,例如/a/b/。/c->/a/c 218 //注意,它有局限性,例如~someuser/tmp将不会扩展 219 func expandPath(p string) string { 220 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 221 if home := homeDir(); home != "" { 222 p = home + p[1:] 223 } 224 } 225 return path.Clean(os.ExpandEnv(p)) 226 } 227 228 func homeDir() string { 229 if home := os.Getenv("HOME"); home != "" { 230 return home 231 } 232 if usr, err := user.Current(); err == nil { 233 return usr.HomeDir 234 } 235 return "" 236 } 237