github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/util/options/options.go (about) 1 // Copyright (c) 2015, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package options works in concert with flag, adding prettier printing of 16 // options. 17 package options 18 19 import ( 20 "flag" 21 "fmt" 22 "io" 23 "strings" 24 "text/tabwriter" 25 "time" 26 27 _ "github.com/golang/glog" 28 ) 29 30 // Option is like flag.Flag, but supports prettier printing. 31 type Option struct { 32 // Name for this flag, e.g. "pass" 33 Name string 34 35 // Default value, e.g. "BogusPassword" 36 Default interface{} 37 38 // Placeholder description of the argument e.g. "<password>" 39 Prototype string 40 41 // Help message, e.g. "Password for decryption" 42 Help string 43 44 // Relevance is a comma-separated list of words, used to group the flags 45 // into categories. 46 Relevance string 47 } 48 49 // Category describes a group of related command-line flags. 50 type Category struct { 51 52 // Name for this group of flags. 53 Name string 54 55 // Description for this group of flags. 56 Description string 57 } 58 59 var ( 60 // Options is like flag.CommandLine, the current set of options. It is not kept 61 // in lexicographical order. Initially, it will contain (at least) all the flags 62 // from golang/glog. 63 Options = []Option{} 64 65 // String maps from name to value for string options added with Add. 66 String = make(map[string]*string) 67 68 // Bool maps from name to value for boolean options added with Add. 69 Bool = make(map[string]*bool) 70 71 // Int maps from name to value for int options added with Add. 72 Int = make(map[string]*int) 73 74 // Duration maps from name to value for time.Duration options added with 75 // Add. 76 Duration = make(map[string]*time.Duration) 77 ) 78 79 func init() { 80 // Add to options all existing flags, which presumably come from golang/glog 81 // since we import that package. 82 flag.VisitAll(func(f *flag.Flag) { 83 defval := f.Value.(flag.Getter).Get() 84 option := Option{f.Name, defval, "", f.Usage, "logging"} 85 switch defval.(type) { 86 case int: 87 option.Prototype = "<n>" 88 case bool: 89 option.Prototype = "" 90 default: 91 option.Prototype = "<arg>" 92 } 93 Options = append(Options, option) 94 }) 95 } 96 97 // Add adds one or more options to Options, to the flag package's list, and to 98 // the approprate map (either String, Bool, Int, or Duration). 99 func Add(option ...Option) { 100 Options = append(Options, option...) 101 for _, o := range option { 102 switch defval := o.Default.(type) { 103 case string: 104 String[o.Name] = flag.String(o.Name, defval, o.Help) 105 case bool: 106 Bool[o.Name] = flag.Bool(o.Name, defval, o.Help) 107 case int: 108 Int[o.Name] = flag.Int(o.Name, defval, o.Help) 109 case time.Duration: 110 Duration[o.Name] = flag.Duration(o.Name, defval, o.Help) 111 default: 112 panic(fmt.Sprintf("Option type not yet supported: %T", o.Default)) 113 } 114 } 115 } 116 117 // ShowRelevant pretty-prints all options relevant to one or more categories. 118 func ShowRelevant(out io.Writer, category ...Category) { 119 w, ok := out.(*tabwriter.Writer) 120 if !ok { 121 w = new(tabwriter.Writer) 122 w.Init(out, 4, 0, 2, ' ', 0) 123 } 124 for i, c := range category { 125 if i != 0 { 126 fmt.Fprintf(w, "\t\n") 127 } 128 fmt.Fprintf(w, "%s:\n", c.Description) 129 Show(w, c.Name) 130 } 131 if !ok { 132 w.Flush() 133 } 134 } 135 136 // Show pretty-prints all options. If a category is given, only those are shown. 137 func Show(out io.Writer, category string) { 138 w, ok := out.(*tabwriter.Writer) 139 if !ok { 140 w = new(tabwriter.Writer) 141 w.Init(out, 4, 0, 2, ' ', 0) 142 } 143 for _, opt := range Options { 144 for _, r := range strings.Split(opt.Relevance, ",") { 145 if category == "" || category == r { 146 // -name <prototype> help 147 // (default is <default>) 148 fmt.Fprintf(w, " -%s %s\t %s\n", opt.Name, opt.Prototype, opt.Help) 149 if opt.Default != "" && opt.Default != false && opt.Default != nil { 150 fmt.Fprintf(w, " \t (default is %v)\n", opt.Default) 151 } 152 } 153 } 154 } 155 if !ok { 156 w.Flush() 157 } 158 } 159 160 // Show pretty-prints all options. 161 func ShowAll(out io.Writer) { 162 Show(out, "") 163 }