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  }