github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/utils/customflags.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 package utils 18 19 import ( 20 "flag" 21 "fmt" 22 "os" 23 "os/user" 24 "path" 25 "strings" 26 ) 27 28 // Custom type which is registered in the flags library which cli uses for 29 // argument parsing. This allows us to expand Value to an absolute path when 30 // the argument is parsed 31 type DirectoryString struct { 32 Value string 33 } 34 35 func (self *DirectoryString) String() string { 36 return self.Value 37 } 38 39 func (self *DirectoryString) Set(value string) error { 40 self.Value = expandPath(value) 41 return nil 42 } 43 44 // Custom cli.Flag type which expand the received string to an absolute path. 45 // e.g. ~/.atheios -> /home/username/.atheios 46 type DirectoryFlag struct { 47 Name string 48 Value DirectoryString 49 Usage string 50 EnvVar string 51 } 52 53 func (self DirectoryFlag) String() string { 54 fmtString := "%s %v\t%v" 55 if len(self.Value.Value) > 0 { 56 fmtString = "%s \"%v\"\t%v" 57 } 58 return withEnvHint(self.EnvVar, fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage)) 59 } 60 61 func eachName(longName string, fn func(string)) { 62 parts := strings.Split(longName, ",") 63 for _, name := range parts { 64 name = strings.Trim(name, " ") 65 fn(name) 66 } 67 } 68 69 // called by cli library, grabs variable from environment (if in env) 70 // and adds variable to flag set for parsing. 71 func (self DirectoryFlag) Apply(set *flag.FlagSet) { 72 if self.EnvVar != "" { 73 for _, envVar := range strings.Split(self.EnvVar, ",") { 74 envVar = strings.TrimSpace(envVar) 75 if envVal := os.Getenv(envVar); envVal != "" { 76 self.Value.Value = envVal 77 break 78 } 79 } 80 } 81 82 eachName(self.Name, func(name string) { 83 set.Var(&self.Value, self.Name, self.Usage) 84 }) 85 } 86 87 func prefixFor(name string) (prefix string) { 88 if len(name) == 1 { 89 prefix = "-" 90 } else { 91 prefix = "--" 92 } 93 94 return 95 } 96 97 func prefixedNames(fullName string) (prefixed string) { 98 parts := strings.Split(fullName, ",") 99 for i, name := range parts { 100 name = strings.Trim(name, " ") 101 prefixed += prefixFor(name) + name 102 if i < len(parts)-1 { 103 prefixed += ", " 104 } 105 } 106 return 107 } 108 109 func withEnvHint(envVar, str string) string { 110 envText := "" 111 if envVar != "" { 112 envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $")) 113 } 114 return str + envText 115 } 116 117 func (self DirectoryFlag) GetName() string { 118 return self.Name 119 } 120 121 func (self *DirectoryFlag) Set(value string) { 122 self.Value.Value = value 123 } 124 125 // Expands a file path 126 // 1. replace tilde with users home dir 127 // 2. expands embedded environment variables 128 // 3. cleans the path, e.g. /a/b/../c -> /a/c 129 // Note, it has limitations, e.g. ~someuser/tmp will not be expanded 130 func expandPath(p string) string { 131 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 132 if home := homeDir(); home != "" { 133 p = home + p[1:] 134 } 135 } 136 return path.Clean(os.ExpandEnv(p)) 137 } 138 139 func homeDir() string { 140 if home := os.Getenv("HOME"); home != "" { 141 return home 142 } 143 if usr, err := user.Current(); err == nil { 144 return usr.HomeDir 145 } 146 return "" 147 }