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  }