gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

flag.go (3732B)


      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package objabi
      6 
      7 import (
      8 	"flag"
      9 	"fmt"
     10 	"io"
     11 	"io/ioutil"
     12 	"log"
     13 	"os"
     14 	"strconv"
     15 	"strings"
     16 )
     17 
     18 func Flagcount(name, usage string, val *int) {
     19 	flag.Var((*count)(val), name, usage)
     20 }
     21 
     22 func Flagfn1(name, usage string, f func(string)) {
     23 	flag.Var(fn1(f), name, usage)
     24 }
     25 
     26 func Flagprint(w io.Writer) {
     27 	flag.CommandLine.SetOutput(w)
     28 	flag.PrintDefaults()
     29 }
     30 
     31 func Flagparse(usage func()) {
     32 	flag.Usage = usage
     33 	os.Args = expandArgs(os.Args)
     34 	flag.Parse()
     35 }
     36 
     37 // expandArgs expands "response files" arguments in the provided slice.
     38 //
     39 // A "response file" argument starts with '@' and the rest of that
     40 // argument is a filename with CR-or-CRLF-separated arguments. Each
     41 // argument in the named files can also contain response file
     42 // arguments. See Issue 18468.
     43 //
     44 // The returned slice 'out' aliases 'in' iff the input did not contain
     45 // any response file arguments.
     46 //
     47 // TODO: handle relative paths of recursive expansions in different directories?
     48 // Is there a spec for this? Are relative paths allowed?
     49 func expandArgs(in []string) (out []string) {
     50 	// out is nil until we see a "@" argument.
     51 	for i, s := range in {
     52 		if strings.HasPrefix(s, "@") {
     53 			if out == nil {
     54 				out = make([]string, 0, len(in)*2)
     55 				out = append(out, in[:i]...)
     56 			}
     57 			slurp, err := ioutil.ReadFile(s[1:])
     58 			if err != nil {
     59 				log.Fatal(err)
     60 			}
     61 			args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n")
     62 			out = append(out, expandArgs(args)...)
     63 		} else if out != nil {
     64 			out = append(out, s)
     65 		}
     66 	}
     67 	if out == nil {
     68 		return in
     69 	}
     70 	return
     71 }
     72 
     73 func AddVersionFlag() {
     74 	flag.Var(versionFlag{}, "V", "print version and exit")
     75 }
     76 
     77 var buildID string // filled in by linker
     78 
     79 type versionFlag struct{}
     80 
     81 func (versionFlag) IsBoolFlag() bool { return true }
     82 func (versionFlag) Get() interface{} { return nil }
     83 func (versionFlag) String() string   { return "" }
     84 func (versionFlag) Set(s string) error {
     85 	name := os.Args[0]
     86 	name = name[strings.LastIndex(name, `/`)+1:]
     87 	name = name[strings.LastIndex(name, `\`)+1:]
     88 	name = strings.TrimSuffix(name, ".exe")
     89 
     90 	// If there's an active experiment, include that,
     91 	// to distinguish go1.10.2 with an experiment
     92 	// from go1.10.2 without an experiment.
     93 	p := Expstring()
     94 	if p == DefaultExpstring() {
     95 		p = ""
     96 	}
     97 	sep := ""
     98 	if p != "" {
     99 		sep = " "
    100 	}
    101 
    102 	// The go command invokes -V=full to get a unique identifier
    103 	// for this tool. It is assumed that the release version is sufficient
    104 	// for releases, but during development we include the full
    105 	// build ID of the binary, so that if the compiler is changed and
    106 	// rebuilt, we notice and rebuild all packages.
    107 	if s == "full" {
    108 		if strings.HasPrefix(Version, "devel") {
    109 			p += " buildID=" + buildID
    110 		}
    111 	}
    112 
    113 	fmt.Printf("%s version %s%s%s\n", name, Version, sep, p)
    114 	os.Exit(0)
    115 	return nil
    116 }
    117 
    118 // count is a flag.Value that is like a flag.Bool and a flag.Int.
    119 // If used as -name, it increments the count, but -name=x sets the count.
    120 // Used for verbose flag -v.
    121 type count int
    122 
    123 func (c *count) String() string {
    124 	return fmt.Sprint(int(*c))
    125 }
    126 
    127 func (c *count) Set(s string) error {
    128 	switch s {
    129 	case "true":
    130 		*c++
    131 	case "false":
    132 		*c = 0
    133 	default:
    134 		n, err := strconv.Atoi(s)
    135 		if err != nil {
    136 			return fmt.Errorf("invalid count %q", s)
    137 		}
    138 		*c = count(n)
    139 	}
    140 	return nil
    141 }
    142 
    143 func (c *count) Get() interface{} {
    144 	return int(*c)
    145 }
    146 
    147 func (c *count) IsBoolFlag() bool {
    148 	return true
    149 }
    150 
    151 func (c *count) IsCountFlag() bool {
    152 	return true
    153 }
    154 
    155 type fn1 func(string)
    156 
    157 func (f fn1) Set(s string) error {
    158 	f(s)
    159 	return nil
    160 }
    161 
    162 func (f fn1) String() string { return "" }