├── .gitignore ├── .travis.yml ├── Dockerfile ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ ├── github.com │ ├── codegangsta │ │ └── cli │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── app.go │ │ │ ├── app_test.go │ │ │ ├── autocomplete │ │ │ ├── bash_autocomplete │ │ │ └── zsh_autocomplete │ │ │ ├── cli.go │ │ │ ├── cli_test.go │ │ │ ├── command.go │ │ │ ├── command_test.go │ │ │ ├── context.go │ │ │ ├── context_test.go │ │ │ ├── flag.go │ │ │ ├── flag_test.go │ │ │ ├── help.go │ │ │ └── helpers_test.go │ ├── fatih │ │ └── color │ │ │ ├── .travis.yml │ │ │ ├── LICENSE.md │ │ │ ├── README.md │ │ │ ├── color.go │ │ │ ├── color_test.go │ │ │ └── doc.go │ ├── mitchellh │ │ └── go-homedir │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── homedir.go │ │ │ └── homedir_test.go │ └── shiena │ │ └── ansicolor │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ansicolor.go │ │ ├── ansicolor │ │ └── main.go │ │ ├── ansicolor_ansi.go │ │ ├── ansicolor_windows.go │ │ ├── ansicolor_windows_test.go │ │ ├── example_test.go │ │ └── export_test.go │ └── gopkg.in │ └── yaml.v2 │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── decode_test.go │ ├── emitterc.go │ ├── encode.go │ ├── encode_test.go │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── suite_test.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go ├── LICENSE ├── Makefile ├── README.md ├── VERSION ├── app ├── app.go ├── config.go └── config_test.go ├── build └── ci.sh ├── cig.go ├── docker-compose.yml ├── install.sh ├── output └── output.go ├── repo └── repo.go └── test └── fixtures ├── invalid └── .cig.yaml └── valid └── .cig.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | cig_* 26 | .cig.yaml 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | script: 3 | - ./build/ci.sh 4 | deploy: 5 | provider: releases 6 | api_key: 7 | secure: doUo3FJLvbkPrwadQKp6EqwU2D7/yhAdXmDXhBBEFC8uIoo99C1CN/97ajkTf7GW53ZUOACTsAPaEiE2d3MVBheFN4Rza+8QXqHXOOoLl/7NjP/Tm/BYFlIqFuYgGbDy3HPU2cAqSwwXPKhMByZ1ydsw7bazQfH3KuXTcTLs6to= 8 | file: 9 | - cig_darwin_x86_64 10 | - cig_linux_x86_64 11 | - cig_windows_x86_64.exe 12 | skip_cleanup: true 13 | on: 14 | tags: true 15 | notifications: 16 | email: 17 | recipients: 18 | - stevenmajack@gmail.com 19 | on_failure: change 20 | on_success: never 21 | 22 | 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.4.2 2 | MAINTAINER Steven Jack 3 | 4 | RUN apt-get update && apt-get install git -yq 5 | 6 | RUN go get github.com/mitchellh/gox 7 | RUN gox -build-toolchain 8 | 9 | WORKDIR /go 10 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/stevenjack/cig", 3 | "GoVersion": "go1.4", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/codegangsta/cli", 7 | "Comment": "1.2.0-95-g9b2bd2b", 8 | "Rev": "9b2bd2b3489748d4d0a204fa4eb2ee9e89e0ebc6" 9 | }, 10 | { 11 | "ImportPath": "github.com/fatih/color", 12 | "Rev": "f952d5afece9417e6240c2b649c1ef84bc3b6299" 13 | }, 14 | { 15 | "ImportPath": "github.com/mitchellh/go-homedir", 16 | "Rev": "1f6da4a72e57d4e7edd4a7295a585e0a3999a2d4" 17 | }, 18 | { 19 | "ImportPath": "github.com/shiena/ansicolor", 20 | "Rev": "8368d3b31cf6f2c2464c7a91675342c9a0ac6658" 21 | }, 22 | { 23 | "ImportPath": "gopkg.in/yaml.v2", 24 | "Rev": "d466437aa4adc35830964cffc5b5f262c63ddcb4" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 1.1 3 | 4 | script: 5 | - go vet ./... 6 | - go test -v ./... 7 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Jeremy Saenz 2 | All Rights Reserved. 3 | 4 | MIT LICENSE 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/codegangsta/cli.png?branch=master)](https://travis-ci.org/codegangsta/cli) 2 | 3 | # cli.go 4 | cli.go is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way. 5 | 6 | You can view the API docs here: 7 | http://godoc.org/github.com/codegangsta/cli 8 | 9 | ## Overview 10 | Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app. 11 | 12 | **This is where cli.go comes into play.** cli.go makes command line programming fun, organized, and expressive! 13 | 14 | ## Installation 15 | Make sure you have a working Go environment (go 1.1 is *required*). [See the install instructions](http://golang.org/doc/install.html). 16 | 17 | To install `cli.go`, simply run: 18 | ``` 19 | $ go get github.com/codegangsta/cli 20 | ``` 21 | 22 | Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands can be easily used: 23 | ``` 24 | export PATH=$PATH:$GOPATH/bin 25 | ``` 26 | 27 | ## Getting Started 28 | One of the philosophies behind cli.go is that an API should be playful and full of discovery. So a cli.go app can be as little as one line of code in `main()`. 29 | 30 | ``` go 31 | package main 32 | 33 | import ( 34 | "os" 35 | "github.com/codegangsta/cli" 36 | ) 37 | 38 | func main() { 39 | cli.NewApp().Run(os.Args) 40 | } 41 | ``` 42 | 43 | This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation: 44 | 45 | ``` go 46 | package main 47 | 48 | import ( 49 | "os" 50 | "github.com/codegangsta/cli" 51 | ) 52 | 53 | func main() { 54 | app := cli.NewApp() 55 | app.Name = "boom" 56 | app.Usage = "make an explosive entrance" 57 | app.Action = func(c *cli.Context) { 58 | println("boom! I say!") 59 | } 60 | 61 | app.Run(os.Args) 62 | } 63 | ``` 64 | 65 | Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below. 66 | 67 | ## Example 68 | 69 | Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness! 70 | 71 | Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it: 72 | 73 | ``` go 74 | package main 75 | 76 | import ( 77 | "os" 78 | "github.com/codegangsta/cli" 79 | ) 80 | 81 | func main() { 82 | app := cli.NewApp() 83 | app.Name = "greet" 84 | app.Usage = "fight the loneliness!" 85 | app.Action = func(c *cli.Context) { 86 | println("Hello friend!") 87 | } 88 | 89 | app.Run(os.Args) 90 | } 91 | ``` 92 | 93 | Install our command to the `$GOPATH/bin` directory: 94 | 95 | ``` 96 | $ go install 97 | ``` 98 | 99 | Finally run our new command: 100 | 101 | ``` 102 | $ greet 103 | Hello friend! 104 | ``` 105 | 106 | cli.go also generates some bitchass help text: 107 | ``` 108 | $ greet help 109 | NAME: 110 | greet - fight the loneliness! 111 | 112 | USAGE: 113 | greet [global options] command [command options] [arguments...] 114 | 115 | VERSION: 116 | 0.0.0 117 | 118 | COMMANDS: 119 | help, h Shows a list of commands or help for one command 120 | 121 | GLOBAL OPTIONS 122 | --version Shows version information 123 | ``` 124 | 125 | ### Arguments 126 | You can lookup arguments by calling the `Args` function on `cli.Context`. 127 | 128 | ``` go 129 | ... 130 | app.Action = func(c *cli.Context) { 131 | println("Hello", c.Args()[0]) 132 | } 133 | ... 134 | ``` 135 | 136 | ### Flags 137 | Setting and querying flags is simple. 138 | ``` go 139 | ... 140 | app.Flags = []cli.Flag { 141 | cli.StringFlag{ 142 | Name: "lang", 143 | Value: "english", 144 | Usage: "language for the greeting", 145 | }, 146 | } 147 | app.Action = func(c *cli.Context) { 148 | name := "someone" 149 | if len(c.Args()) > 0 { 150 | name = c.Args()[0] 151 | } 152 | if c.String("lang") == "spanish" { 153 | println("Hola", name) 154 | } else { 155 | println("Hello", name) 156 | } 157 | } 158 | ... 159 | ``` 160 | 161 | #### Alternate Names 162 | 163 | You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g. 164 | 165 | ``` go 166 | app.Flags = []cli.Flag { 167 | cli.StringFlag{ 168 | Name: "lang, l", 169 | Value: "english", 170 | Usage: "language for the greeting", 171 | }, 172 | } 173 | ``` 174 | 175 | That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error. 176 | 177 | #### Values from the Environment 178 | 179 | You can also have the default value set from the environment via `EnvVar`. e.g. 180 | 181 | ``` go 182 | app.Flags = []cli.Flag { 183 | cli.StringFlag{ 184 | Name: "lang, l", 185 | Value: "english", 186 | Usage: "language for the greeting", 187 | EnvVar: "APP_LANG", 188 | }, 189 | } 190 | ``` 191 | 192 | The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default. 193 | 194 | ``` go 195 | app.Flags = []cli.Flag { 196 | cli.StringFlag{ 197 | Name: "lang, l", 198 | Value: "english", 199 | Usage: "language for the greeting", 200 | EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG", 201 | }, 202 | } 203 | ``` 204 | 205 | ### Subcommands 206 | 207 | Subcommands can be defined for a more git-like command line app. 208 | ```go 209 | ... 210 | app.Commands = []cli.Command{ 211 | { 212 | Name: "add", 213 | Aliases: []string{"a"}, 214 | Usage: "add a task to the list", 215 | Action: func(c *cli.Context) { 216 | println("added task: ", c.Args().First()) 217 | }, 218 | }, 219 | { 220 | Name: "complete", 221 | Aliases: []string{"c"}, 222 | Usage: "complete a task on the list", 223 | Action: func(c *cli.Context) { 224 | println("completed task: ", c.Args().First()) 225 | }, 226 | }, 227 | { 228 | Name: "template", 229 | Aliases: []string{"r"}, 230 | Usage: "options for task templates", 231 | Subcommands: []cli.Command{ 232 | { 233 | Name: "add", 234 | Usage: "add a new template", 235 | Action: func(c *cli.Context) { 236 | println("new task template: ", c.Args().First()) 237 | }, 238 | }, 239 | { 240 | Name: "remove", 241 | Usage: "remove an existing template", 242 | Action: func(c *cli.Context) { 243 | println("removed task template: ", c.Args().First()) 244 | }, 245 | }, 246 | }, 247 | }, 248 | } 249 | ... 250 | ``` 251 | 252 | ### Bash Completion 253 | 254 | You can enable completion commands by setting the `EnableBashCompletion` 255 | flag on the `App` object. By default, this setting will only auto-complete to 256 | show an app's subcommands, but you can write your own completion methods for 257 | the App or its subcommands. 258 | ```go 259 | ... 260 | var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"} 261 | app := cli.NewApp() 262 | app.EnableBashCompletion = true 263 | app.Commands = []cli.Command{ 264 | { 265 | Name: "complete", 266 | Aliases: []string{"c"}, 267 | Usage: "complete a task on the list", 268 | Action: func(c *cli.Context) { 269 | println("completed task: ", c.Args().First()) 270 | }, 271 | BashComplete: func(c *cli.Context) { 272 | // This will complete if no args are passed 273 | if len(c.Args()) > 0 { 274 | return 275 | } 276 | for _, t := range tasks { 277 | fmt.Println(t) 278 | } 279 | }, 280 | } 281 | } 282 | ... 283 | ``` 284 | 285 | #### To Enable 286 | 287 | Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while 288 | setting the `PROG` variable to the name of your program: 289 | 290 | `PROG=myprogram source /.../cli/autocomplete/bash_autocomplete` 291 | 292 | 293 | ## Contribution Guidelines 294 | Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch. 295 | 296 | If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together. 297 | 298 | If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out. 299 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/app.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | "strings" 9 | "text/tabwriter" 10 | "text/template" 11 | "time" 12 | ) 13 | 14 | // App is the main structure of a cli application. It is recomended that 15 | // and app be created with the cli.NewApp() function 16 | type App struct { 17 | // The name of the program. Defaults to os.Args[0] 18 | Name string 19 | // Description of the program. 20 | Usage string 21 | // Version of the program 22 | Version string 23 | // List of commands to execute 24 | Commands []Command 25 | // List of flags to parse 26 | Flags []Flag 27 | // Boolean to enable bash completion commands 28 | EnableBashCompletion bool 29 | // Boolean to hide built-in help command 30 | HideHelp bool 31 | // Boolean to hide built-in version flag 32 | HideVersion bool 33 | // An action to execute when the bash-completion flag is set 34 | BashComplete func(context *Context) 35 | // An action to execute before any subcommands are run, but after the context is ready 36 | // If a non-nil error is returned, no subcommands are run 37 | Before func(context *Context) error 38 | // An action to execute after any subcommands are run, but after the subcommand has finished 39 | // It is run even if Action() panics 40 | After func(context *Context) error 41 | // The action to execute when no subcommands are specified 42 | Action func(context *Context) 43 | // Execute this function if the proper command cannot be found 44 | CommandNotFound func(context *Context, command string) 45 | // Compilation date 46 | Compiled time.Time 47 | // List of all authors who contributed 48 | Authors []Author 49 | // Name of Author (Note: Use App.Authors, this is deprecated) 50 | Author string 51 | // Email of Author (Note: Use App.Authors, this is deprecated) 52 | Email string 53 | // Writer writer to write output to 54 | Writer io.Writer 55 | } 56 | 57 | // Tries to find out when this binary was compiled. 58 | // Returns the current time if it fails to find it. 59 | func compileTime() time.Time { 60 | info, err := os.Stat(os.Args[0]) 61 | if err != nil { 62 | return time.Now() 63 | } 64 | return info.ModTime() 65 | } 66 | 67 | // Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action. 68 | func NewApp() *App { 69 | return &App{ 70 | Name: os.Args[0], 71 | Usage: "A new cli application", 72 | Version: "0.0.0", 73 | BashComplete: DefaultAppComplete, 74 | Action: helpCommand.Action, 75 | Compiled: compileTime(), 76 | Writer: os.Stdout, 77 | } 78 | } 79 | 80 | // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination 81 | func (a *App) Run(arguments []string) (err error) { 82 | if a.Author != "" || a.Email != "" { 83 | a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) 84 | } 85 | 86 | if HelpPrinter == nil { 87 | defer func() { 88 | HelpPrinter = nil 89 | }() 90 | 91 | HelpPrinter = func(templ string, data interface{}) { 92 | funcMap := template.FuncMap{ 93 | "join": strings.Join, 94 | } 95 | 96 | w := tabwriter.NewWriter(a.Writer, 0, 8, 1, '\t', 0) 97 | t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) 98 | err := t.Execute(w, data) 99 | if err != nil { 100 | panic(err) 101 | } 102 | w.Flush() 103 | } 104 | } 105 | 106 | // append help to commands 107 | if a.Command(helpCommand.Name) == nil && !a.HideHelp { 108 | a.Commands = append(a.Commands, helpCommand) 109 | if (HelpFlag != BoolFlag{}) { 110 | a.appendFlag(HelpFlag) 111 | } 112 | } 113 | 114 | //append version/help flags 115 | if a.EnableBashCompletion { 116 | a.appendFlag(BashCompletionFlag) 117 | } 118 | 119 | if !a.HideVersion { 120 | a.appendFlag(VersionFlag) 121 | } 122 | 123 | // parse flags 124 | set := flagSet(a.Name, a.Flags) 125 | set.SetOutput(ioutil.Discard) 126 | err = set.Parse(arguments[1:]) 127 | nerr := normalizeFlags(a.Flags, set) 128 | if nerr != nil { 129 | fmt.Fprintln(a.Writer, nerr) 130 | context := NewContext(a, set, set) 131 | ShowAppHelp(context) 132 | fmt.Fprintln(a.Writer) 133 | return nerr 134 | } 135 | context := NewContext(a, set, set) 136 | 137 | if err != nil { 138 | fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") 139 | ShowAppHelp(context) 140 | fmt.Fprintln(a.Writer) 141 | return err 142 | } 143 | 144 | if checkCompletions(context) { 145 | return nil 146 | } 147 | 148 | if checkHelp(context) { 149 | return nil 150 | } 151 | 152 | if checkVersion(context) { 153 | return nil 154 | } 155 | 156 | if a.After != nil { 157 | defer func() { 158 | // err is always nil here. 159 | // There is a check to see if it is non-nil 160 | // just few lines before. 161 | err = a.After(context) 162 | }() 163 | } 164 | 165 | if a.Before != nil { 166 | err := a.Before(context) 167 | if err != nil { 168 | return err 169 | } 170 | } 171 | 172 | args := context.Args() 173 | if args.Present() { 174 | name := args.First() 175 | c := a.Command(name) 176 | if c != nil { 177 | return c.Run(context) 178 | } 179 | } 180 | 181 | // Run default Action 182 | a.Action(context) 183 | return nil 184 | } 185 | 186 | // Another entry point to the cli app, takes care of passing arguments and error handling 187 | func (a *App) RunAndExitOnError() { 188 | if err := a.Run(os.Args); err != nil { 189 | fmt.Fprintln(os.Stderr, err) 190 | os.Exit(1) 191 | } 192 | } 193 | 194 | // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags 195 | func (a *App) RunAsSubcommand(ctx *Context) (err error) { 196 | // append help to commands 197 | if len(a.Commands) > 0 { 198 | if a.Command(helpCommand.Name) == nil && !a.HideHelp { 199 | a.Commands = append(a.Commands, helpCommand) 200 | if (HelpFlag != BoolFlag{}) { 201 | a.appendFlag(HelpFlag) 202 | } 203 | } 204 | } 205 | 206 | // append flags 207 | if a.EnableBashCompletion { 208 | a.appendFlag(BashCompletionFlag) 209 | } 210 | 211 | // parse flags 212 | set := flagSet(a.Name, a.Flags) 213 | set.SetOutput(ioutil.Discard) 214 | err = set.Parse(ctx.Args().Tail()) 215 | nerr := normalizeFlags(a.Flags, set) 216 | context := NewContext(a, set, ctx.globalSet) 217 | 218 | if nerr != nil { 219 | fmt.Fprintln(a.Writer, nerr) 220 | if len(a.Commands) > 0 { 221 | ShowSubcommandHelp(context) 222 | } else { 223 | ShowCommandHelp(ctx, context.Args().First()) 224 | } 225 | fmt.Fprintln(a.Writer) 226 | return nerr 227 | } 228 | 229 | if err != nil { 230 | fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") 231 | ShowSubcommandHelp(context) 232 | return err 233 | } 234 | 235 | if checkCompletions(context) { 236 | return nil 237 | } 238 | 239 | if len(a.Commands) > 0 { 240 | if checkSubcommandHelp(context) { 241 | return nil 242 | } 243 | } else { 244 | if checkCommandHelp(ctx, context.Args().First()) { 245 | return nil 246 | } 247 | } 248 | 249 | if a.After != nil { 250 | defer func() { 251 | // err is always nil here. 252 | // There is a check to see if it is non-nil 253 | // just few lines before. 254 | err = a.After(context) 255 | }() 256 | } 257 | 258 | if a.Before != nil { 259 | err := a.Before(context) 260 | if err != nil { 261 | return err 262 | } 263 | } 264 | 265 | args := context.Args() 266 | if args.Present() { 267 | name := args.First() 268 | c := a.Command(name) 269 | if c != nil { 270 | return c.Run(context) 271 | } 272 | } 273 | 274 | // Run default Action 275 | a.Action(context) 276 | 277 | return nil 278 | } 279 | 280 | // Returns the named command on App. Returns nil if the command does not exist 281 | func (a *App) Command(name string) *Command { 282 | for _, c := range a.Commands { 283 | if c.HasName(name) { 284 | return &c 285 | } 286 | } 287 | 288 | return nil 289 | } 290 | 291 | func (a *App) hasFlag(flag Flag) bool { 292 | for _, f := range a.Flags { 293 | if flag == f { 294 | return true 295 | } 296 | } 297 | 298 | return false 299 | } 300 | 301 | func (a *App) appendFlag(flag Flag) { 302 | if !a.hasFlag(flag) { 303 | a.Flags = append(a.Flags, flag) 304 | } 305 | } 306 | 307 | // Author represents someone who has contributed to a cli project. 308 | type Author struct { 309 | Name string // The Authors name 310 | Email string // The Authors email 311 | } 312 | 313 | // String makes Author comply to the Stringer interface, to allow an easy print in the templating process 314 | func (a Author) String() string { 315 | e := "" 316 | if a.Email != "" { 317 | e = "<" + a.Email + "> " 318 | } 319 | 320 | return fmt.Sprintf("%v %v", a.Name, e) 321 | } 322 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | _cli_bash_autocomplete() { 4 | local cur prev opts base 5 | COMPREPLY=() 6 | cur="${COMP_WORDS[COMP_CWORD]}" 7 | prev="${COMP_WORDS[COMP_CWORD-1]}" 8 | opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) 9 | COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) 10 | return 0 11 | } 12 | 13 | complete -F _cli_bash_autocomplete $PROG -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/autocomplete/zsh_autocomplete: -------------------------------------------------------------------------------- 1 | autoload -U compinit && compinit 2 | autoload -U bashcompinit && bashcompinit 3 | 4 | script_dir=$(dirname $0) 5 | source ${script_dir}/bash_autocomplete 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/cli.go: -------------------------------------------------------------------------------- 1 | // Package cli provides a minimal framework for creating and organizing command line 2 | // Go applications. cli is designed to be easy to understand and write, the most simple 3 | // cli application can be written as follows: 4 | // func main() { 5 | // cli.NewApp().Run(os.Args) 6 | // } 7 | // 8 | // Of course this application does not do much, so let's make this an actual application: 9 | // func main() { 10 | // app := cli.NewApp() 11 | // app.Name = "greet" 12 | // app.Usage = "say a greeting" 13 | // app.Action = func(c *cli.Context) { 14 | // println("Greetings") 15 | // } 16 | // 17 | // app.Run(os.Args) 18 | // } 19 | package cli 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go: -------------------------------------------------------------------------------- 1 | package cli_test 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/codegangsta/cli" 7 | ) 8 | 9 | func Example() { 10 | app := cli.NewApp() 11 | app.Name = "todo" 12 | app.Usage = "task list on the command line" 13 | app.Commands = []cli.Command{ 14 | { 15 | Name: "add", 16 | Aliases: []string{"a"}, 17 | Usage: "add a task to the list", 18 | Action: func(c *cli.Context) { 19 | println("added task: ", c.Args().First()) 20 | }, 21 | }, 22 | { 23 | Name: "complete", 24 | Aliases: []string{"c"}, 25 | Usage: "complete a task on the list", 26 | Action: func(c *cli.Context) { 27 | println("completed task: ", c.Args().First()) 28 | }, 29 | }, 30 | } 31 | 32 | app.Run(os.Args) 33 | } 34 | 35 | func ExampleSubcommand() { 36 | app := cli.NewApp() 37 | app.Name = "say" 38 | app.Commands = []cli.Command{ 39 | { 40 | Name: "hello", 41 | Aliases: []string{"hi"}, 42 | Usage: "use it to see a description", 43 | Description: "This is how we describe hello the function", 44 | Subcommands: []cli.Command{ 45 | { 46 | Name: "english", 47 | Aliases: []string{"en"}, 48 | Usage: "sends a greeting in english", 49 | Description: "greets someone in english", 50 | Flags: []cli.Flag{ 51 | cli.StringFlag{ 52 | Name: "name", 53 | Value: "Bob", 54 | Usage: "Name of the person to greet", 55 | }, 56 | }, 57 | Action: func(c *cli.Context) { 58 | println("Hello, ", c.String("name")) 59 | }, 60 | }, { 61 | Name: "spanish", 62 | Aliases: []string{"sp"}, 63 | Usage: "sends a greeting in spanish", 64 | Flags: []cli.Flag{ 65 | cli.StringFlag{ 66 | Name: "surname", 67 | Value: "Jones", 68 | Usage: "Surname of the person to greet", 69 | }, 70 | }, 71 | Action: func(c *cli.Context) { 72 | println("Hola, ", c.String("surname")) 73 | }, 74 | }, { 75 | Name: "french", 76 | Aliases: []string{"fr"}, 77 | Usage: "sends a greeting in french", 78 | Flags: []cli.Flag{ 79 | cli.StringFlag{ 80 | Name: "nickname", 81 | Value: "Stevie", 82 | Usage: "Nickname of the person to greet", 83 | }, 84 | }, 85 | Action: func(c *cli.Context) { 86 | println("Bonjour, ", c.String("nickname")) 87 | }, 88 | }, 89 | }, 90 | }, { 91 | Name: "bye", 92 | Usage: "says goodbye", 93 | Action: func(c *cli.Context) { 94 | println("bye") 95 | }, 96 | }, 97 | } 98 | 99 | app.Run(os.Args) 100 | } 101 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/command.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "strings" 7 | ) 8 | 9 | // Command is a subcommand for a cli.App. 10 | type Command struct { 11 | // The name of the command 12 | Name string 13 | // short name of the command. Typically one character (deprecated, use `Aliases`) 14 | ShortName string 15 | // A list of aliases for the command 16 | Aliases []string 17 | // A short description of the usage of this command 18 | Usage string 19 | // A longer explanation of how the command works 20 | Description string 21 | // The function to call when checking for bash command completions 22 | BashComplete func(context *Context) 23 | // An action to execute before any sub-subcommands are run, but after the context is ready 24 | // If a non-nil error is returned, no sub-subcommands are run 25 | Before func(context *Context) error 26 | // An action to execute after any subcommands are run, but after the subcommand has finished 27 | // It is run even if Action() panics 28 | After func(context *Context) error 29 | // The function to call when this command is invoked 30 | Action func(context *Context) 31 | // List of child commands 32 | Subcommands []Command 33 | // List of flags to parse 34 | Flags []Flag 35 | // Treat all flags as normal arguments if true 36 | SkipFlagParsing bool 37 | // Boolean to hide built-in help command 38 | HideHelp bool 39 | } 40 | 41 | // Invokes the command given the context, parses ctx.Args() to generate command-specific flags 42 | func (c Command) Run(ctx *Context) error { 43 | 44 | if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { 45 | return c.startApp(ctx) 46 | } 47 | 48 | if !c.HideHelp && (HelpFlag != BoolFlag{}) { 49 | // append help to flags 50 | c.Flags = append( 51 | c.Flags, 52 | HelpFlag, 53 | ) 54 | } 55 | 56 | if ctx.App.EnableBashCompletion { 57 | c.Flags = append(c.Flags, BashCompletionFlag) 58 | } 59 | 60 | set := flagSet(c.Name, c.Flags) 61 | set.SetOutput(ioutil.Discard) 62 | 63 | firstFlagIndex := -1 64 | terminatorIndex := -1 65 | for index, arg := range ctx.Args() { 66 | if arg == "--" { 67 | terminatorIndex = index 68 | break 69 | } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 { 70 | firstFlagIndex = index 71 | } 72 | } 73 | 74 | var err error 75 | if firstFlagIndex > -1 && !c.SkipFlagParsing { 76 | args := ctx.Args() 77 | regularArgs := make([]string, len(args[1:firstFlagIndex])) 78 | copy(regularArgs, args[1:firstFlagIndex]) 79 | 80 | var flagArgs []string 81 | if terminatorIndex > -1 { 82 | flagArgs = args[firstFlagIndex:terminatorIndex] 83 | regularArgs = append(regularArgs, args[terminatorIndex:]...) 84 | } else { 85 | flagArgs = args[firstFlagIndex:] 86 | } 87 | 88 | err = set.Parse(append(flagArgs, regularArgs...)) 89 | } else { 90 | err = set.Parse(ctx.Args().Tail()) 91 | } 92 | 93 | if err != nil { 94 | fmt.Fprint(ctx.App.Writer, "Incorrect Usage.\n\n") 95 | ShowCommandHelp(ctx, c.Name) 96 | fmt.Fprintln(ctx.App.Writer) 97 | return err 98 | } 99 | 100 | nerr := normalizeFlags(c.Flags, set) 101 | if nerr != nil { 102 | fmt.Fprintln(ctx.App.Writer, nerr) 103 | fmt.Fprintln(ctx.App.Writer) 104 | ShowCommandHelp(ctx, c.Name) 105 | fmt.Fprintln(ctx.App.Writer) 106 | return nerr 107 | } 108 | context := NewContext(ctx.App, set, ctx.globalSet) 109 | 110 | if checkCommandCompletions(context, c.Name) { 111 | return nil 112 | } 113 | 114 | if checkCommandHelp(context, c.Name) { 115 | return nil 116 | } 117 | context.Command = c 118 | c.Action(context) 119 | return nil 120 | } 121 | 122 | func (c Command) Names() []string { 123 | names := []string{c.Name} 124 | 125 | if c.ShortName != "" { 126 | names = append(names, c.ShortName) 127 | } 128 | 129 | return append(names, c.Aliases...) 130 | } 131 | 132 | // Returns true if Command.Name or Command.ShortName matches given name 133 | func (c Command) HasName(name string) bool { 134 | for _, n := range c.Names() { 135 | if n == name { 136 | return true 137 | } 138 | } 139 | return false 140 | } 141 | 142 | func (c Command) startApp(ctx *Context) error { 143 | app := NewApp() 144 | 145 | // set the name and usage 146 | app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) 147 | if c.Description != "" { 148 | app.Usage = c.Description 149 | } else { 150 | app.Usage = c.Usage 151 | } 152 | 153 | // set CommandNotFound 154 | app.CommandNotFound = ctx.App.CommandNotFound 155 | 156 | // set the flags and commands 157 | app.Commands = c.Subcommands 158 | app.Flags = c.Flags 159 | app.HideHelp = c.HideHelp 160 | 161 | // bash completion 162 | app.EnableBashCompletion = ctx.App.EnableBashCompletion 163 | if c.BashComplete != nil { 164 | app.BashComplete = c.BashComplete 165 | } 166 | 167 | // set the actions 168 | app.Before = c.Before 169 | app.After = c.After 170 | if c.Action != nil { 171 | app.Action = c.Action 172 | } else { 173 | app.Action = helpSubcommand.Action 174 | } 175 | 176 | return app.RunAsSubcommand(ctx) 177 | } 178 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go: -------------------------------------------------------------------------------- 1 | package cli_test 2 | 3 | import ( 4 | "flag" 5 | "testing" 6 | 7 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/codegangsta/cli" 8 | ) 9 | 10 | func TestCommandDoNotIgnoreFlags(t *testing.T) { 11 | app := cli.NewApp() 12 | set := flag.NewFlagSet("test", 0) 13 | test := []string{"blah", "blah", "-break"} 14 | set.Parse(test) 15 | 16 | c := cli.NewContext(app, set, set) 17 | 18 | command := cli.Command{ 19 | Name: "test-cmd", 20 | Aliases: []string{"tc"}, 21 | Usage: "this is for testing", 22 | Description: "testing", 23 | Action: func(_ *cli.Context) {}, 24 | } 25 | err := command.Run(c) 26 | 27 | expect(t, err.Error(), "flag provided but not defined: -break") 28 | } 29 | 30 | func TestCommandIgnoreFlags(t *testing.T) { 31 | app := cli.NewApp() 32 | set := flag.NewFlagSet("test", 0) 33 | test := []string{"blah", "blah"} 34 | set.Parse(test) 35 | 36 | c := cli.NewContext(app, set, set) 37 | 38 | command := cli.Command{ 39 | Name: "test-cmd", 40 | Aliases: []string{"tc"}, 41 | Usage: "this is for testing", 42 | Description: "testing", 43 | Action: func(_ *cli.Context) {}, 44 | SkipFlagParsing: true, 45 | } 46 | err := command.Run(c) 47 | 48 | expect(t, err, nil) 49 | } 50 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/context.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | // Context is a type that is passed through to 12 | // each Handler action in a cli application. Context 13 | // can be used to retrieve context-specific Args and 14 | // parsed command-line options. 15 | type Context struct { 16 | App *App 17 | Command Command 18 | flagSet *flag.FlagSet 19 | globalSet *flag.FlagSet 20 | setFlags map[string]bool 21 | globalSetFlags map[string]bool 22 | } 23 | 24 | // Creates a new context. For use in when invoking an App or Command action. 25 | func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context { 26 | return &Context{App: app, flagSet: set, globalSet: globalSet} 27 | } 28 | 29 | // Looks up the value of a local int flag, returns 0 if no int flag exists 30 | func (c *Context) Int(name string) int { 31 | return lookupInt(name, c.flagSet) 32 | } 33 | 34 | // Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists 35 | func (c *Context) Duration(name string) time.Duration { 36 | return lookupDuration(name, c.flagSet) 37 | } 38 | 39 | // Looks up the value of a local float64 flag, returns 0 if no float64 flag exists 40 | func (c *Context) Float64(name string) float64 { 41 | return lookupFloat64(name, c.flagSet) 42 | } 43 | 44 | // Looks up the value of a local bool flag, returns false if no bool flag exists 45 | func (c *Context) Bool(name string) bool { 46 | return lookupBool(name, c.flagSet) 47 | } 48 | 49 | // Looks up the value of a local boolT flag, returns false if no bool flag exists 50 | func (c *Context) BoolT(name string) bool { 51 | return lookupBoolT(name, c.flagSet) 52 | } 53 | 54 | // Looks up the value of a local string flag, returns "" if no string flag exists 55 | func (c *Context) String(name string) string { 56 | return lookupString(name, c.flagSet) 57 | } 58 | 59 | // Looks up the value of a local string slice flag, returns nil if no string slice flag exists 60 | func (c *Context) StringSlice(name string) []string { 61 | return lookupStringSlice(name, c.flagSet) 62 | } 63 | 64 | // Looks up the value of a local int slice flag, returns nil if no int slice flag exists 65 | func (c *Context) IntSlice(name string) []int { 66 | return lookupIntSlice(name, c.flagSet) 67 | } 68 | 69 | // Looks up the value of a local generic flag, returns nil if no generic flag exists 70 | func (c *Context) Generic(name string) interface{} { 71 | return lookupGeneric(name, c.flagSet) 72 | } 73 | 74 | // Looks up the value of a global int flag, returns 0 if no int flag exists 75 | func (c *Context) GlobalInt(name string) int { 76 | return lookupInt(name, c.globalSet) 77 | } 78 | 79 | // Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists 80 | func (c *Context) GlobalDuration(name string) time.Duration { 81 | return lookupDuration(name, c.globalSet) 82 | } 83 | 84 | // Looks up the value of a global bool flag, returns false if no bool flag exists 85 | func (c *Context) GlobalBool(name string) bool { 86 | return lookupBool(name, c.globalSet) 87 | } 88 | 89 | // Looks up the value of a global string flag, returns "" if no string flag exists 90 | func (c *Context) GlobalString(name string) string { 91 | return lookupString(name, c.globalSet) 92 | } 93 | 94 | // Looks up the value of a global string slice flag, returns nil if no string slice flag exists 95 | func (c *Context) GlobalStringSlice(name string) []string { 96 | return lookupStringSlice(name, c.globalSet) 97 | } 98 | 99 | // Looks up the value of a global int slice flag, returns nil if no int slice flag exists 100 | func (c *Context) GlobalIntSlice(name string) []int { 101 | return lookupIntSlice(name, c.globalSet) 102 | } 103 | 104 | // Looks up the value of a global generic flag, returns nil if no generic flag exists 105 | func (c *Context) GlobalGeneric(name string) interface{} { 106 | return lookupGeneric(name, c.globalSet) 107 | } 108 | 109 | // Returns the number of flags set 110 | func (c *Context) NumFlags() int { 111 | return c.flagSet.NFlag() 112 | } 113 | 114 | // Determines if the flag was actually set 115 | func (c *Context) IsSet(name string) bool { 116 | if c.setFlags == nil { 117 | c.setFlags = make(map[string]bool) 118 | c.flagSet.Visit(func(f *flag.Flag) { 119 | c.setFlags[f.Name] = true 120 | }) 121 | } 122 | return c.setFlags[name] == true 123 | } 124 | 125 | // Determines if the global flag was actually set 126 | func (c *Context) GlobalIsSet(name string) bool { 127 | if c.globalSetFlags == nil { 128 | c.globalSetFlags = make(map[string]bool) 129 | c.globalSet.Visit(func(f *flag.Flag) { 130 | c.globalSetFlags[f.Name] = true 131 | }) 132 | } 133 | return c.globalSetFlags[name] == true 134 | } 135 | 136 | // Returns a slice of flag names used in this context. 137 | func (c *Context) FlagNames() (names []string) { 138 | for _, flag := range c.Command.Flags { 139 | name := strings.Split(flag.getName(), ",")[0] 140 | if name == "help" { 141 | continue 142 | } 143 | names = append(names, name) 144 | } 145 | return 146 | } 147 | 148 | // Returns a slice of global flag names used by the app. 149 | func (c *Context) GlobalFlagNames() (names []string) { 150 | for _, flag := range c.App.Flags { 151 | name := strings.Split(flag.getName(), ",")[0] 152 | if name == "help" || name == "version" { 153 | continue 154 | } 155 | names = append(names, name) 156 | } 157 | return 158 | } 159 | 160 | type Args []string 161 | 162 | // Returns the command line arguments associated with the context. 163 | func (c *Context) Args() Args { 164 | args := Args(c.flagSet.Args()) 165 | return args 166 | } 167 | 168 | // Returns the nth argument, or else a blank string 169 | func (a Args) Get(n int) string { 170 | if len(a) > n { 171 | return a[n] 172 | } 173 | return "" 174 | } 175 | 176 | // Returns the first argument, or else a blank string 177 | func (a Args) First() string { 178 | return a.Get(0) 179 | } 180 | 181 | // Return the rest of the arguments (not the first one) 182 | // or else an empty string slice 183 | func (a Args) Tail() []string { 184 | if len(a) >= 2 { 185 | return []string(a)[1:] 186 | } 187 | return []string{} 188 | } 189 | 190 | // Checks if there are any arguments present 191 | func (a Args) Present() bool { 192 | return len(a) != 0 193 | } 194 | 195 | // Swaps arguments at the given indexes 196 | func (a Args) Swap(from, to int) error { 197 | if from >= len(a) || to >= len(a) { 198 | return errors.New("index out of range") 199 | } 200 | a[from], a[to] = a[to], a[from] 201 | return nil 202 | } 203 | 204 | func lookupInt(name string, set *flag.FlagSet) int { 205 | f := set.Lookup(name) 206 | if f != nil { 207 | val, err := strconv.Atoi(f.Value.String()) 208 | if err != nil { 209 | return 0 210 | } 211 | return val 212 | } 213 | 214 | return 0 215 | } 216 | 217 | func lookupDuration(name string, set *flag.FlagSet) time.Duration { 218 | f := set.Lookup(name) 219 | if f != nil { 220 | val, err := time.ParseDuration(f.Value.String()) 221 | if err == nil { 222 | return val 223 | } 224 | } 225 | 226 | return 0 227 | } 228 | 229 | func lookupFloat64(name string, set *flag.FlagSet) float64 { 230 | f := set.Lookup(name) 231 | if f != nil { 232 | val, err := strconv.ParseFloat(f.Value.String(), 64) 233 | if err != nil { 234 | return 0 235 | } 236 | return val 237 | } 238 | 239 | return 0 240 | } 241 | 242 | func lookupString(name string, set *flag.FlagSet) string { 243 | f := set.Lookup(name) 244 | if f != nil { 245 | return f.Value.String() 246 | } 247 | 248 | return "" 249 | } 250 | 251 | func lookupStringSlice(name string, set *flag.FlagSet) []string { 252 | f := set.Lookup(name) 253 | if f != nil { 254 | return (f.Value.(*StringSlice)).Value() 255 | 256 | } 257 | 258 | return nil 259 | } 260 | 261 | func lookupIntSlice(name string, set *flag.FlagSet) []int { 262 | f := set.Lookup(name) 263 | if f != nil { 264 | return (f.Value.(*IntSlice)).Value() 265 | 266 | } 267 | 268 | return nil 269 | } 270 | 271 | func lookupGeneric(name string, set *flag.FlagSet) interface{} { 272 | f := set.Lookup(name) 273 | if f != nil { 274 | return f.Value 275 | } 276 | return nil 277 | } 278 | 279 | func lookupBool(name string, set *flag.FlagSet) bool { 280 | f := set.Lookup(name) 281 | if f != nil { 282 | val, err := strconv.ParseBool(f.Value.String()) 283 | if err != nil { 284 | return false 285 | } 286 | return val 287 | } 288 | 289 | return false 290 | } 291 | 292 | func lookupBoolT(name string, set *flag.FlagSet) bool { 293 | f := set.Lookup(name) 294 | if f != nil { 295 | val, err := strconv.ParseBool(f.Value.String()) 296 | if err != nil { 297 | return true 298 | } 299 | return val 300 | } 301 | 302 | return false 303 | } 304 | 305 | func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { 306 | switch ff.Value.(type) { 307 | case *StringSlice: 308 | default: 309 | set.Set(name, ff.Value.String()) 310 | } 311 | } 312 | 313 | func normalizeFlags(flags []Flag, set *flag.FlagSet) error { 314 | visited := make(map[string]bool) 315 | set.Visit(func(f *flag.Flag) { 316 | visited[f.Name] = true 317 | }) 318 | for _, f := range flags { 319 | parts := strings.Split(f.getName(), ",") 320 | if len(parts) == 1 { 321 | continue 322 | } 323 | var ff *flag.Flag 324 | for _, name := range parts { 325 | name = strings.Trim(name, " ") 326 | if visited[name] { 327 | if ff != nil { 328 | return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) 329 | } 330 | ff = set.Lookup(name) 331 | } 332 | } 333 | if ff == nil { 334 | continue 335 | } 336 | for _, name := range parts { 337 | name = strings.Trim(name, " ") 338 | if !visited[name] { 339 | copyFlag(name, ff, set) 340 | } 341 | } 342 | } 343 | return nil 344 | } 345 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go: -------------------------------------------------------------------------------- 1 | package cli_test 2 | 3 | import ( 4 | "flag" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/codegangsta/cli" 9 | ) 10 | 11 | func TestNewContext(t *testing.T) { 12 | set := flag.NewFlagSet("test", 0) 13 | set.Int("myflag", 12, "doc") 14 | globalSet := flag.NewFlagSet("test", 0) 15 | globalSet.Int("myflag", 42, "doc") 16 | command := cli.Command{Name: "mycommand"} 17 | c := cli.NewContext(nil, set, globalSet) 18 | c.Command = command 19 | expect(t, c.Int("myflag"), 12) 20 | expect(t, c.GlobalInt("myflag"), 42) 21 | expect(t, c.Command.Name, "mycommand") 22 | } 23 | 24 | func TestContext_Int(t *testing.T) { 25 | set := flag.NewFlagSet("test", 0) 26 | set.Int("myflag", 12, "doc") 27 | c := cli.NewContext(nil, set, set) 28 | expect(t, c.Int("myflag"), 12) 29 | } 30 | 31 | func TestContext_Duration(t *testing.T) { 32 | set := flag.NewFlagSet("test", 0) 33 | set.Duration("myflag", time.Duration(12*time.Second), "doc") 34 | c := cli.NewContext(nil, set, set) 35 | expect(t, c.Duration("myflag"), time.Duration(12*time.Second)) 36 | } 37 | 38 | func TestContext_String(t *testing.T) { 39 | set := flag.NewFlagSet("test", 0) 40 | set.String("myflag", "hello world", "doc") 41 | c := cli.NewContext(nil, set, set) 42 | expect(t, c.String("myflag"), "hello world") 43 | } 44 | 45 | func TestContext_Bool(t *testing.T) { 46 | set := flag.NewFlagSet("test", 0) 47 | set.Bool("myflag", false, "doc") 48 | c := cli.NewContext(nil, set, set) 49 | expect(t, c.Bool("myflag"), false) 50 | } 51 | 52 | func TestContext_BoolT(t *testing.T) { 53 | set := flag.NewFlagSet("test", 0) 54 | set.Bool("myflag", true, "doc") 55 | c := cli.NewContext(nil, set, set) 56 | expect(t, c.BoolT("myflag"), true) 57 | } 58 | 59 | func TestContext_Args(t *testing.T) { 60 | set := flag.NewFlagSet("test", 0) 61 | set.Bool("myflag", false, "doc") 62 | c := cli.NewContext(nil, set, set) 63 | set.Parse([]string{"--myflag", "bat", "baz"}) 64 | expect(t, len(c.Args()), 2) 65 | expect(t, c.Bool("myflag"), true) 66 | } 67 | 68 | func TestContext_IsSet(t *testing.T) { 69 | set := flag.NewFlagSet("test", 0) 70 | set.Bool("myflag", false, "doc") 71 | set.String("otherflag", "hello world", "doc") 72 | globalSet := flag.NewFlagSet("test", 0) 73 | globalSet.Bool("myflagGlobal", true, "doc") 74 | c := cli.NewContext(nil, set, globalSet) 75 | set.Parse([]string{"--myflag", "bat", "baz"}) 76 | globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) 77 | expect(t, c.IsSet("myflag"), true) 78 | expect(t, c.IsSet("otherflag"), false) 79 | expect(t, c.IsSet("bogusflag"), false) 80 | expect(t, c.IsSet("myflagGlobal"), false) 81 | } 82 | 83 | func TestContext_GlobalIsSet(t *testing.T) { 84 | set := flag.NewFlagSet("test", 0) 85 | set.Bool("myflag", false, "doc") 86 | set.String("otherflag", "hello world", "doc") 87 | globalSet := flag.NewFlagSet("test", 0) 88 | globalSet.Bool("myflagGlobal", true, "doc") 89 | globalSet.Bool("myflagGlobalUnset", true, "doc") 90 | c := cli.NewContext(nil, set, globalSet) 91 | set.Parse([]string{"--myflag", "bat", "baz"}) 92 | globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) 93 | expect(t, c.GlobalIsSet("myflag"), false) 94 | expect(t, c.GlobalIsSet("otherflag"), false) 95 | expect(t, c.GlobalIsSet("bogusflag"), false) 96 | expect(t, c.GlobalIsSet("myflagGlobal"), true) 97 | expect(t, c.GlobalIsSet("myflagGlobalUnset"), false) 98 | expect(t, c.GlobalIsSet("bogusGlobal"), false) 99 | } 100 | 101 | func TestContext_NumFlags(t *testing.T) { 102 | set := flag.NewFlagSet("test", 0) 103 | set.Bool("myflag", false, "doc") 104 | set.String("otherflag", "hello world", "doc") 105 | globalSet := flag.NewFlagSet("test", 0) 106 | globalSet.Bool("myflagGlobal", true, "doc") 107 | c := cli.NewContext(nil, set, globalSet) 108 | set.Parse([]string{"--myflag", "--otherflag=foo"}) 109 | globalSet.Parse([]string{"--myflagGlobal"}) 110 | expect(t, c.NumFlags(), 2) 111 | } 112 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/help.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import "fmt" 4 | 5 | // The text template for the Default help topic. 6 | // cli.go uses text/template to render templates. You can 7 | // render custom help text by setting this variable. 8 | var AppHelpTemplate = `NAME: 9 | {{.Name}} - {{.Usage}} 10 | 11 | USAGE: 12 | {{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 13 | 14 | VERSION: 15 | {{.Version}} 16 | 17 | AUTHOR(S): 18 | {{range .Authors}}{{ . }} 19 | {{end}} 20 | COMMANDS: 21 | {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} 22 | {{end}}{{if .Flags}} 23 | GLOBAL OPTIONS: 24 | {{range .Flags}}{{.}} 25 | {{end}}{{end}} 26 | ` 27 | 28 | // The text template for the command help topic. 29 | // cli.go uses text/template to render templates. You can 30 | // render custom help text by setting this variable. 31 | var CommandHelpTemplate = `NAME: 32 | {{.Name}} - {{.Usage}} 33 | 34 | USAGE: 35 | command {{.Name}}{{if .Flags}} [command options]{{end}} [arguments...]{{if .Description}} 36 | 37 | DESCRIPTION: 38 | {{.Description}}{{end}}{{if .Flags}} 39 | 40 | OPTIONS: 41 | {{range .Flags}}{{.}} 42 | {{end}}{{ end }} 43 | ` 44 | 45 | // The text template for the subcommand help topic. 46 | // cli.go uses text/template to render templates. You can 47 | // render custom help text by setting this variable. 48 | var SubcommandHelpTemplate = `NAME: 49 | {{.Name}} - {{.Usage}} 50 | 51 | USAGE: 52 | {{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...] 53 | 54 | COMMANDS: 55 | {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} 56 | {{end}}{{if .Flags}} 57 | OPTIONS: 58 | {{range .Flags}}{{.}} 59 | {{end}}{{end}} 60 | ` 61 | 62 | var helpCommand = Command{ 63 | Name: "help", 64 | Aliases: []string{"h"}, 65 | Usage: "Shows a list of commands or help for one command", 66 | Action: func(c *Context) { 67 | args := c.Args() 68 | if args.Present() { 69 | ShowCommandHelp(c, args.First()) 70 | } else { 71 | ShowAppHelp(c) 72 | } 73 | }, 74 | } 75 | 76 | var helpSubcommand = Command{ 77 | Name: "help", 78 | Aliases: []string{"h"}, 79 | Usage: "Shows a list of commands or help for one command", 80 | Action: func(c *Context) { 81 | args := c.Args() 82 | if args.Present() { 83 | ShowCommandHelp(c, args.First()) 84 | } else { 85 | ShowSubcommandHelp(c) 86 | } 87 | }, 88 | } 89 | 90 | // Prints help for the App 91 | type helpPrinter func(templ string, data interface{}) 92 | 93 | var HelpPrinter helpPrinter = nil 94 | 95 | // Prints version for the App 96 | var VersionPrinter = printVersion 97 | 98 | func ShowAppHelp(c *Context) { 99 | HelpPrinter(AppHelpTemplate, c.App) 100 | } 101 | 102 | // Prints the list of subcommands as the default app completion method 103 | func DefaultAppComplete(c *Context) { 104 | for _, command := range c.App.Commands { 105 | for _, name := range command.Names() { 106 | fmt.Fprintln(c.App.Writer, name) 107 | } 108 | } 109 | } 110 | 111 | // Prints help for the given command 112 | func ShowCommandHelp(c *Context, command string) { 113 | // show the subcommand help for a command with subcommands 114 | if command == "" { 115 | HelpPrinter(SubcommandHelpTemplate, c.App) 116 | return 117 | } 118 | 119 | for _, c := range c.App.Commands { 120 | if c.HasName(command) { 121 | HelpPrinter(CommandHelpTemplate, c) 122 | return 123 | } 124 | } 125 | 126 | if c.App.CommandNotFound != nil { 127 | c.App.CommandNotFound(c, command) 128 | } else { 129 | fmt.Fprintf(c.App.Writer, "No help topic for '%v'\n", command) 130 | } 131 | } 132 | 133 | // Prints help for the given subcommand 134 | func ShowSubcommandHelp(c *Context) { 135 | ShowCommandHelp(c, c.Command.Name) 136 | } 137 | 138 | // Prints the version number of the App 139 | func ShowVersion(c *Context) { 140 | VersionPrinter(c) 141 | } 142 | 143 | func printVersion(c *Context) { 144 | fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) 145 | } 146 | 147 | // Prints the lists of commands within a given context 148 | func ShowCompletions(c *Context) { 149 | a := c.App 150 | if a != nil && a.BashComplete != nil { 151 | a.BashComplete(c) 152 | } 153 | } 154 | 155 | // Prints the custom completions for a given command 156 | func ShowCommandCompletions(ctx *Context, command string) { 157 | c := ctx.App.Command(command) 158 | if c != nil && c.BashComplete != nil { 159 | c.BashComplete(ctx) 160 | } 161 | } 162 | 163 | func checkVersion(c *Context) bool { 164 | if c.GlobalBool("version") { 165 | ShowVersion(c) 166 | return true 167 | } 168 | 169 | return false 170 | } 171 | 172 | func checkHelp(c *Context) bool { 173 | if c.GlobalBool("h") || c.GlobalBool("help") { 174 | ShowAppHelp(c) 175 | return true 176 | } 177 | 178 | return false 179 | } 180 | 181 | func checkCommandHelp(c *Context, name string) bool { 182 | if c.Bool("h") || c.Bool("help") { 183 | ShowCommandHelp(c, name) 184 | return true 185 | } 186 | 187 | return false 188 | } 189 | 190 | func checkSubcommandHelp(c *Context) bool { 191 | if c.GlobalBool("h") || c.GlobalBool("help") { 192 | ShowSubcommandHelp(c) 193 | return true 194 | } 195 | 196 | return false 197 | } 198 | 199 | func checkCompletions(c *Context) bool { 200 | if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion { 201 | ShowCompletions(c) 202 | return true 203 | } 204 | 205 | return false 206 | } 207 | 208 | func checkCommandCompletions(c *Context, name string) bool { 209 | if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { 210 | ShowCommandCompletions(c, name) 211 | return true 212 | } 213 | 214 | return false 215 | } 216 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/cli/helpers_test.go: -------------------------------------------------------------------------------- 1 | package cli_test 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | /* Test Helpers */ 9 | func expect(t *testing.T, a interface{}, b interface{}) { 10 | if a != b { 11 | t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) 12 | } 13 | } 14 | 15 | func refute(t *testing.T, a interface{}, b interface{}) { 16 | if a == b { 17 | t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 1.3 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Fatih Arslan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/README.md: -------------------------------------------------------------------------------- 1 | # Color [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/color) [![Build Status](http://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color) 2 | 3 | 4 | 5 | Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you. 6 | 7 | 8 | 9 | ![Color](http://i.imgur.com/c1JI0lA.png) 10 | 11 | 12 | ## Install 13 | 14 | ```bash 15 | go get github.com/fatih/color 16 | ``` 17 | 18 | ## Examples 19 | 20 | ### Standard colors 21 | 22 | ```go 23 | // Print with default helper functions 24 | color.Cyan("Prints text in cyan.") 25 | 26 | // A newline will be appended automatically 27 | color.Blue("Prints %s in blue.", "text") 28 | 29 | // These are using the default foreground colors 30 | color.Red("We have red") 31 | color.Magenta("And many others ..") 32 | 33 | ``` 34 | 35 | ### Mix and reuse colors 36 | 37 | ```go 38 | // Create a new color object 39 | c := color.New(color.FgCyan).Add(color.Underline) 40 | c.Println("Prints cyan text with an underline.") 41 | 42 | // Or just add them to New() 43 | d := color.New(color.FgCyan, color.Bold) 44 | d.Printf("This prints bold cyan %s\n", "too!.") 45 | 46 | // Mix up foreground and background colors, create new mixes! 47 | red := color.New(color.FgRed) 48 | 49 | boldRed := red.Add(color.Bold) 50 | boldRed.Println("This will print text in bold red.") 51 | 52 | whiteBackground := red.Add(color.BgWhite) 53 | whiteBackground.Println("Red text with white background.") 54 | ``` 55 | 56 | ### Custom print functions (PrintFunc) 57 | 58 | ```go 59 | // Create a custom print function for convenience 60 | red := color.New(color.FgRed).PrintfFunc() 61 | red("Warning") 62 | red("Error: %s", err) 63 | 64 | // Mix up multiple attributes 65 | notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() 66 | notice("Don't forget this...") 67 | ``` 68 | 69 | ### Insert into noncolor strings (SprintFunc) 70 | 71 | ```go 72 | // Create SprintXxx functions to mix strings with other non-colorized strings: 73 | yellow := color.New(color.FgYellow).SprintFunc() 74 | red := color.New(color.FgRed).SprintFunc() 75 | fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) 76 | 77 | info := color.New(color.FgWhite, color.BgGreen).SprintFunc() 78 | fmt.Printf("This %s rocks!\n", info("package")) 79 | 80 | // Use helper functions 81 | fmt.Printf("This", color.RedString("warning"), "should be not neglected.") 82 | fmt.Printf(color.GreenString("Info:"), "an important message." ) 83 | 84 | // Windows supported too! Just don't forget to change the output to color.Output 85 | fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) 86 | ``` 87 | 88 | ### Plug into existing code 89 | 90 | ```go 91 | // Use handy standard colors 92 | color.Set(color.FgYellow) 93 | 94 | fmt.Println("Existing text will now be in yellow") 95 | fmt.Printf("This one %s\n", "too") 96 | 97 | color.Unset() // Don't forget to unset 98 | 99 | // You can mix up parameters 100 | color.Set(color.FgMagenta, color.Bold) 101 | defer color.Unset() // Use it in your function 102 | 103 | fmt.Println("All text will now be bold magenta.") 104 | ``` 105 | 106 | ## Todo 107 | 108 | * Save/Return previous values 109 | * Evaluate fmt.Formatter interface 110 | 111 | 112 | ## Credits 113 | 114 | * [Fatih Arslan](https://github.com/fatih) 115 | * Windows support via @shiena: [ansicolor](https://github.com/shiena/ansicolor) 116 | 117 | ## License 118 | 119 | The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details 120 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/color.go: -------------------------------------------------------------------------------- 1 | package color 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 11 | ) 12 | 13 | // Color defines a custom color object which is defined by SGR parameters. 14 | type Color struct { 15 | params []Attribute 16 | } 17 | 18 | // Attribute defines a single SGR Code 19 | type Attribute int 20 | 21 | const escape = "\x1b" 22 | 23 | // Base attributes 24 | const ( 25 | Reset Attribute = iota 26 | Bold 27 | Faint 28 | Italic 29 | Underline 30 | BlinkSlow 31 | BlinkRapid 32 | ReverseVideo 33 | Concealed 34 | CrossedOut 35 | ) 36 | 37 | // Foreground text colors 38 | const ( 39 | FgBlack Attribute = iota + 30 40 | FgRed 41 | FgGreen 42 | FgYellow 43 | FgBlue 44 | FgMagenta 45 | FgCyan 46 | FgWhite 47 | ) 48 | 49 | // Background text colors 50 | const ( 51 | BgBlack Attribute = iota + 40 52 | BgRed 53 | BgGreen 54 | BgYellow 55 | BgBlue 56 | BgMagenta 57 | BgCyan 58 | BgWhite 59 | ) 60 | 61 | // New returns a newly created color object. 62 | func New(value ...Attribute) *Color { 63 | c := &Color{params: make([]Attribute, 0)} 64 | c.Add(value...) 65 | return c 66 | } 67 | 68 | // Set sets the given parameters immediately. It will change the color of 69 | // output with the given SGR parameters until color.Unset() is called. 70 | func Set(p ...Attribute) *Color { 71 | c := New(p...) 72 | c.Set() 73 | return c 74 | } 75 | 76 | // Unset resets all escape attributes and clears the output. Usually should 77 | // be called after Set(). 78 | func Unset() { 79 | fmt.Fprintf(Output, "%s[%dm", escape, Reset) 80 | } 81 | 82 | // Add is used to chain SGR parameters. Use as many as parameters to combine 83 | // and create custom color objects. Example: Add(color.FgRed, color.Underline). 84 | func (c *Color) Add(value ...Attribute) *Color { 85 | c.params = append(c.params, value...) 86 | return c 87 | } 88 | 89 | func (c *Color) prepend(value Attribute) { 90 | c.params = append(c.params, 0) 91 | copy(c.params[1:], c.params[0:]) 92 | c.params[0] = value 93 | } 94 | 95 | // Output defines the standard output of the print functions. By default 96 | // os.Stdout is used. 97 | var Output io.Writer = ansicolor.NewAnsiColorWriter(os.Stdout) 98 | 99 | // Print formats using the default formats for its operands and writes to 100 | // standard output. Spaces are added between operands when neither is a 101 | // string. It returns the number of bytes written and any write error 102 | // encountered. This is the standard fmt.Print() method wrapped with the given 103 | // color. 104 | func (c *Color) Print(a ...interface{}) (n int, err error) { 105 | c.Set() 106 | defer Unset() 107 | 108 | return fmt.Fprint(Output, a...) 109 | } 110 | 111 | // Printf formats according to a format specifier and writes to standard output. 112 | // It returns the number of bytes written and any write error encountered. 113 | // This is the standard fmt.Printf() method wrapped with the given color. 114 | func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { 115 | c.Set() 116 | defer Unset() 117 | 118 | return fmt.Fprintf(Output, format, a...) 119 | } 120 | 121 | // Println formats using the default formats for its operands and writes to 122 | // standard output. Spaces are always added between operands and a newline is 123 | // appended. It returns the number of bytes written and any write error 124 | // encountered. This is the standard fmt.Print() method wrapped with the given 125 | // color. 126 | func (c *Color) Println(a ...interface{}) (n int, err error) { 127 | c.Set() 128 | defer Unset() 129 | 130 | return fmt.Fprintln(Output, a...) 131 | } 132 | 133 | // PrintFunc returns a new function that prints the passed arguments as 134 | // colorized with color.Print(). 135 | func (c *Color) PrintFunc() func(a ...interface{}) { 136 | return func(a ...interface{}) { c.Print(a...) } 137 | } 138 | 139 | // PrintfFunc returns a new function that prints the passed arguments as 140 | // colorized with color.Printf(). 141 | func (c *Color) PrintfFunc() func(format string, a ...interface{}) { 142 | return func(format string, a ...interface{}) { c.Printf(format, a...) } 143 | } 144 | 145 | // PrintlnFunc returns a new function that prints the passed arguments as 146 | // colorized with color.Println(). 147 | func (c *Color) PrintlnFunc() func(a ...interface{}) { 148 | return func(a ...interface{}) { c.Println(a...) } 149 | } 150 | 151 | // SprintFunc returns a new function that returns colorized strings for the 152 | // given arguments with fmt.Sprint(). Useful to put into or mix into other 153 | // string. Windows users should use this in conjuction with color.Output, example: 154 | // 155 | // put := New(FgYellow).SprintFunc() 156 | // fmt.Ffprintf(color.Output, "This is a %s", put("warning")) 157 | func (c *Color) SprintFunc() func(a ...interface{}) string { 158 | return func(a ...interface{}) string { 159 | return c.wrap(fmt.Sprint(a...)) 160 | } 161 | } 162 | 163 | // SprintfFunc returns a new function that returns colorized strings for the 164 | // given arguments with fmt.Sprintf(). Useful to put into or mix into other 165 | // string. Windows users should use this in conjuction with color.Output. 166 | func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { 167 | return func(format string, a ...interface{}) string { 168 | return c.wrap(fmt.Sprintf(format, a...)) 169 | } 170 | } 171 | 172 | // SprintlnFunc returns a new function that returns colorized strings for the 173 | // given arguments with fmt.Sprintln(). Useful to put into or mix into other 174 | // string. Windows users should use this in conjuction with color.Output. 175 | func (c *Color) SprintlnFunc() func(a ...interface{}) string { 176 | return func(a ...interface{}) string { 177 | return c.wrap(fmt.Sprintln(a...)) 178 | } 179 | } 180 | 181 | // sequence returns a formated SGR sequence to be plugged into a "\x1b[...m" 182 | // an example output might be: "1;36" -> bold cyan 183 | func (c *Color) sequence() string { 184 | format := make([]string, len(c.params)) 185 | for i, v := range c.params { 186 | format[i] = strconv.Itoa(int(v)) 187 | } 188 | 189 | return strings.Join(format, ";") 190 | } 191 | 192 | func (c *Color) wrap(s string) string { return c.format() + s + c.unformat() } 193 | 194 | func (c *Color) format() string { return fmt.Sprintf("%s[%sm", escape, c.sequence()) } 195 | 196 | func (c *Color) unformat() string { return fmt.Sprintf("%s[%dm", escape, Reset) } 197 | 198 | // Set sets the SGR sequence. 199 | func (c *Color) Set() *Color { 200 | fmt.Fprintf(Output, c.format()) 201 | return c 202 | } 203 | 204 | // Black is an convenient helper function to print with black foreground. A 205 | // newline is appended to format by default. 206 | func Black(format string, a ...interface{}) { printColor(format, FgBlack, a...) } 207 | 208 | // Red is an convenient helper function to print with red foreground. A 209 | // newline is appended to format by default. 210 | func Red(format string, a ...interface{}) { printColor(format, FgRed, a...) } 211 | 212 | // Green is an convenient helper function to print with green foreground. A 213 | // newline is appended to format by default. 214 | func Green(format string, a ...interface{}) { printColor(format, FgGreen, a...) } 215 | 216 | // Yellow is an convenient helper function to print with yellow foreground. 217 | // A newline is appended to format by default. 218 | func Yellow(format string, a ...interface{}) { printColor(format, FgYellow, a...) } 219 | 220 | // Blue is an convenient helper function to print with blue foreground. A 221 | // newline is appended to format by default. 222 | func Blue(format string, a ...interface{}) { printColor(format, FgBlue, a...) } 223 | 224 | // Magenta is an convenient helper function to print with magenta foreground. 225 | // A newline is appended to format by default. 226 | func Magenta(format string, a ...interface{}) { printColor(format, FgMagenta, a...) } 227 | 228 | // Cyan is an convenient helper function to print with cyan foreground. A 229 | // newline is appended to format by default. 230 | func Cyan(format string, a ...interface{}) { printColor(format, FgCyan, a...) } 231 | 232 | // White is an convenient helper function to print with white foreground. A 233 | // newline is appended to format by default. 234 | func White(format string, a ...interface{}) { printColor(format, FgWhite, a...) } 235 | 236 | func printColor(format string, p Attribute, a ...interface{}) { 237 | if !strings.HasSuffix(format, "\n") { 238 | format += "\n" 239 | } 240 | 241 | c := &Color{params: []Attribute{p}} 242 | c.Printf(format, a...) 243 | } 244 | 245 | // BlackString is an convenient helper function to return a string with black 246 | // foreground. 247 | func BlackString(format string, a ...interface{}) string { 248 | return New(FgBlack).SprintfFunc()(format, a...) 249 | } 250 | 251 | // RedString is an convenient helper function to return a string with red 252 | // foreground. 253 | func RedString(format string, a ...interface{}) string { 254 | return New(FgRed).SprintfFunc()(format, a...) 255 | } 256 | 257 | // GreenString is an convenient helper function to return a string with green 258 | // foreground. 259 | func GreenString(format string, a ...interface{}) string { 260 | return New(FgGreen).SprintfFunc()(format, a...) 261 | } 262 | 263 | // YellowString is an convenient helper function to return a string with yellow 264 | // foreground. 265 | func YellowString(format string, a ...interface{}) string { 266 | return New(FgYellow).SprintfFunc()(format, a...) 267 | } 268 | 269 | // BlueString is an convenient helper function to return a string with blue 270 | // foreground. 271 | func BlueString(format string, a ...interface{}) string { 272 | return New(FgBlue).SprintfFunc()(format, a...) 273 | } 274 | 275 | // MagentaString is an convenient helper function to return a string with magenta 276 | // foreground. 277 | func MagentaString(format string, a ...interface{}) string { 278 | return New(FgMagenta).SprintfFunc()(format, a...) 279 | } 280 | 281 | // CyanString is an convenient helper function to return a string with cyan 282 | // foreground. 283 | func CyanString(format string, a ...interface{}) string { 284 | return New(FgCyan).SprintfFunc()(format, a...) 285 | } 286 | 287 | // WhiteString is an convenient helper function to return a string with white 288 | // foreground. 289 | func WhiteString(format string, a ...interface{}) string { 290 | return New(FgWhite).SprintfFunc()(format, a...) 291 | } 292 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/color_test.go: -------------------------------------------------------------------------------- 1 | package color 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "testing" 8 | 9 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 10 | ) 11 | 12 | // Testing colors is kinda different. First we test for given colors and their 13 | // escaped formatted results. Next we create some visual tests to be tested. 14 | // Each visual test includes the color name to be compared. 15 | func TestColor(t *testing.T) { 16 | rb := new(bytes.Buffer) 17 | Output = rb 18 | 19 | testColors := []struct { 20 | text string 21 | code Attribute 22 | }{ 23 | {text: "black", code: FgBlack}, 24 | {text: "red", code: FgRed}, 25 | {text: "green", code: FgGreen}, 26 | {text: "yellow", code: FgYellow}, 27 | {text: "blue", code: FgBlue}, 28 | {text: "magent", code: FgMagenta}, 29 | {text: "cyan", code: FgCyan}, 30 | {text: "white", code: FgWhite}, 31 | } 32 | 33 | for _, c := range testColors { 34 | New(c.code).Print(c.text) 35 | 36 | line, _ := rb.ReadString('\n') 37 | scannedLine := fmt.Sprintf("%q", line) 38 | colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text) 39 | escapedForm := fmt.Sprintf("%q", colored) 40 | 41 | fmt.Printf("%s\t: %s\n", c.text, line) 42 | 43 | if scannedLine != escapedForm { 44 | t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine) 45 | } 46 | } 47 | 48 | // First Visual Test 49 | fmt.Println("") 50 | Output = ansicolor.NewAnsiColorWriter(os.Stdout) 51 | 52 | New(FgRed).Printf("red\t") 53 | New(BgRed).Print(" ") 54 | New(FgRed, Bold).Println(" red") 55 | 56 | New(FgGreen).Printf("green\t") 57 | New(BgGreen).Print(" ") 58 | New(FgGreen, Bold).Println(" green") 59 | 60 | New(FgYellow).Printf("yellow\t") 61 | New(BgYellow).Print(" ") 62 | New(FgYellow, Bold).Println(" yellow") 63 | 64 | New(FgBlue).Printf("blue\t") 65 | New(BgBlue).Print(" ") 66 | New(FgBlue, Bold).Println(" blue") 67 | 68 | New(FgMagenta).Printf("magenta\t") 69 | New(BgMagenta).Print(" ") 70 | New(FgMagenta, Bold).Println(" magenta") 71 | 72 | New(FgCyan).Printf("cyan\t") 73 | New(BgCyan).Print(" ") 74 | New(FgCyan, Bold).Println(" cyan") 75 | 76 | New(FgWhite).Printf("white\t") 77 | New(BgWhite).Print(" ") 78 | New(FgWhite, Bold).Println(" white") 79 | fmt.Println("") 80 | 81 | // Second Visual test 82 | Black("black") 83 | Red("red") 84 | Green("green") 85 | Yellow("yellow") 86 | Blue("blue") 87 | Magenta("magenta") 88 | Cyan("cyan") 89 | White("white") 90 | 91 | // Third visual test 92 | fmt.Println() 93 | Set(FgBlue) 94 | fmt.Println("is this blue?") 95 | Unset() 96 | 97 | Set(FgMagenta) 98 | fmt.Println("and this magenta?") 99 | Unset() 100 | 101 | // Fourth Visual test 102 | fmt.Println() 103 | blue := New(FgBlue).PrintlnFunc() 104 | blue("blue text with custom print func") 105 | 106 | red := New(FgRed).PrintfFunc() 107 | red("red text with a printf func: %d\n", 123) 108 | 109 | put := New(FgYellow).SprintFunc() 110 | warn := New(FgRed).SprintFunc() 111 | 112 | fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error")) 113 | 114 | info := New(FgWhite, BgGreen).SprintFunc() 115 | fmt.Fprintf(Output, "this %s rocks!\n", info("package")) 116 | 117 | // Fifth Visual Test 118 | fmt.Println() 119 | 120 | fmt.Fprintln(Output, BlackString("black")) 121 | fmt.Fprintln(Output, RedString("red")) 122 | fmt.Fprintln(Output, GreenString("green")) 123 | fmt.Fprintln(Output, YellowString("yellow")) 124 | fmt.Fprintln(Output, BlueString("blue")) 125 | fmt.Fprintln(Output, MagentaString("magenta")) 126 | fmt.Fprintln(Output, CyanString("cyan")) 127 | fmt.Fprintln(Output, WhiteString("white")) 128 | 129 | } 130 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/fatih/color/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package color is an ANSI color package to output colorized or SGR defined 3 | output to the standard output. The API can be used in several way, pick one 4 | that suits you. 5 | 6 | Use simple and default helper functions with predefined foreground colors: 7 | 8 | color.Cyan("Prints text in cyan.") 9 | 10 | // a newline will be appended automatically 11 | color.Blue("Prints %s in blue.", "text") 12 | 13 | // More default foreground colors.. 14 | color.Red("We have red") 15 | color.Yellow("Yellow color too!") 16 | color.Magenta("And many others ..") 17 | 18 | However there are times where custom color mixes are required. Below are some 19 | examples to create custom color objects and use the print functions of each 20 | separate color object. 21 | 22 | // Create a new color object 23 | c := color.New(color.FgCyan).Add(color.Underline) 24 | c.Println("Prints cyan text with an underline.") 25 | 26 | // Or just add them to New() 27 | d := color.New(color.FgCyan, color.Bold) 28 | d.Printf("This prints bold cyan %s\n", "too!.") 29 | 30 | 31 | // Mix up foreground and background colors, create new mixes! 32 | red := color.New(color.FgRed) 33 | 34 | boldRed := red.Add(color.Bold) 35 | boldRed.Println("This will print text in bold red.") 36 | 37 | whiteBackground := red.Add(color.BgWhite) 38 | whiteBackground.Println("Red text with White background.") 39 | 40 | 41 | You can create PrintXxx functions to simplify even more: 42 | 43 | // Create a custom print function for convenient 44 | red := color.New(color.FgRed).PrintfFunc() 45 | red("warning") 46 | red("error: %s", err) 47 | 48 | // Mix up multiple attributes 49 | notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() 50 | notice("don't forget this...") 51 | 52 | 53 | Or create SprintXxx functions to mix strings with other non-colorized strings: 54 | 55 | yellow := New(FgYellow).SprintFunc() 56 | red := New(FgRed).SprintFunc() 57 | 58 | fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error")) 59 | 60 | info := New(FgWhite, BgGreen).SprintFunc() 61 | fmt.Printf("this %s rocks!\n", info("package")) 62 | 63 | Windows support is enabled by default. All Print functions works as intended. 64 | However only for color.SprintXXX functions, user should use fmt.FprintXXX and 65 | set the output to color.Output: 66 | 67 | fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) 68 | 69 | info := New(FgWhite, BgGreen).SprintFunc() 70 | fmt.Fprintf(color.Output, "this %s rocks!\n", info("package")) 71 | 72 | 73 | Using with existing code is possible. Just use the Set() method to set the 74 | standard output to the given parameters. That way a rewrite of an existing 75 | code is not required. 76 | 77 | // Use handy standard colors. 78 | color.Set(color.FgYellow) 79 | 80 | fmt.Println("Existing text will be now in Yellow") 81 | fmt.Printf("This one %s\n", "too") 82 | 83 | color.Unset() // don't forget to unset 84 | 85 | // You can mix up parameters 86 | color.Set(color.FgMagenta, color.Bold) 87 | defer color.Unset() // use it in your function 88 | 89 | fmt.Println("All text will be now bold magenta.") 90 | */ 91 | package color 92 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mitchellh/go-homedir/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mitchellh/go-homedir/README.md: -------------------------------------------------------------------------------- 1 | # go-homedir 2 | 3 | This is a Go library for detecting the user's home directory without 4 | the use of cgo, so the library can be used in cross-compilation environments. 5 | 6 | Usage is incredibly simple, just call `homedir.Dir()` to get the home directory 7 | for a user, and `homedir.Expand()` to expand the `~` in a path to the home 8 | directory. 9 | 10 | **Why not just use `os/user`?** The built-in `os/user` package requires 11 | cgo on Darwin systems. This means that any Go code that uses that package 12 | cannot cross compile. But 99% of the time the use for `os/user` is just to 13 | retrieve the home directory, which we can do for the current user without 14 | cgo. This library does that, enabling cross-compilation. 15 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mitchellh/go-homedir/homedir.go: -------------------------------------------------------------------------------- 1 | package homedir 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "os" 7 | "os/exec" 8 | "path/filepath" 9 | "runtime" 10 | "strings" 11 | ) 12 | 13 | // Dir returns the home directory for the executing user. 14 | // 15 | // This uses an OS-specific method for discovering the home directory. 16 | // An error is returned if a home directory cannot be detected. 17 | func Dir() (string, error) { 18 | if runtime.GOOS == "windows" { 19 | return dirWindows() 20 | } 21 | 22 | // Unix-like system, so just assume Unix 23 | return dirUnix() 24 | } 25 | 26 | // Expand expands the path to include the home directory if the path 27 | // is prefixed with `~`. If it isn't prefixed with `~`, the path is 28 | // returned as-is. 29 | func Expand(path string) (string, error) { 30 | if len(path) == 0 { 31 | return path, nil 32 | } 33 | 34 | if path[0] != '~' { 35 | return path, nil 36 | } 37 | 38 | if len(path) > 1 && path[1] != '/' && path[1] != '\\' { 39 | return "", errors.New("cannot expand user-specific home dir") 40 | } 41 | 42 | dir, err := Dir() 43 | if err != nil { 44 | return "", err 45 | } 46 | 47 | return filepath.Join(dir, path[1:]), nil 48 | } 49 | 50 | func dirUnix() (string, error) { 51 | // First prefer the HOME environmental variable 52 | if home := os.Getenv("HOME"); home != "" { 53 | return home, nil 54 | } 55 | 56 | // If that fails, try the shell 57 | var stdout bytes.Buffer 58 | cmd := exec.Command("sh", "-c", "eval echo ~$USER") 59 | cmd.Stdout = &stdout 60 | if err := cmd.Run(); err != nil { 61 | return "", err 62 | } 63 | 64 | result := strings.TrimSpace(stdout.String()) 65 | if result == "" { 66 | return "", errors.New("blank output when reading home directory") 67 | } 68 | 69 | return result, nil 70 | } 71 | 72 | func dirWindows() (string, error) { 73 | drive := os.Getenv("HOMEDRIVE") 74 | path := os.Getenv("HOMEPATH") 75 | home := drive + path 76 | if drive == "" || path == "" { 77 | home = os.Getenv("USERPROFILE") 78 | } 79 | if home == "" { 80 | return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") 81 | } 82 | 83 | return home, nil 84 | } 85 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mitchellh/go-homedir/homedir_test.go: -------------------------------------------------------------------------------- 1 | package homedir 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/user" 7 | "testing" 8 | ) 9 | 10 | func patchEnv(key, value string) func() { 11 | bck := os.Getenv(key) 12 | deferFunc := func() { 13 | os.Setenv(key, bck) 14 | } 15 | 16 | os.Setenv(key, value) 17 | return deferFunc 18 | } 19 | 20 | func TestDir(t *testing.T) { 21 | u, err := user.Current() 22 | if err != nil { 23 | t.Fatalf("err: %s", err) 24 | } 25 | 26 | dir, err := Dir() 27 | if err != nil { 28 | t.Fatalf("err: %s", err) 29 | } 30 | 31 | if u.HomeDir != dir { 32 | t.Fatalf("%#v != %#v", u.HomeDir, dir) 33 | } 34 | } 35 | 36 | func TestExpand(t *testing.T) { 37 | u, err := user.Current() 38 | if err != nil { 39 | t.Fatalf("err: %s", err) 40 | } 41 | 42 | cases := []struct { 43 | Input string 44 | Output string 45 | Err bool 46 | }{ 47 | { 48 | "/foo", 49 | "/foo", 50 | false, 51 | }, 52 | 53 | { 54 | "~/foo", 55 | fmt.Sprintf("%s/foo", u.HomeDir), 56 | false, 57 | }, 58 | 59 | { 60 | "", 61 | "", 62 | false, 63 | }, 64 | 65 | { 66 | "~", 67 | u.HomeDir, 68 | false, 69 | }, 70 | 71 | { 72 | "~foo/foo", 73 | "", 74 | true, 75 | }, 76 | } 77 | 78 | for _, tc := range cases { 79 | actual, err := Expand(tc.Input) 80 | if (err != nil) != tc.Err { 81 | t.Fatalf("Input: %#v\n\nErr: %s", tc.Input, err) 82 | } 83 | 84 | if actual != tc.Output { 85 | t.Fatalf("Input: %#v\n\nOutput: %#v", tc.Input, actual) 86 | } 87 | } 88 | 89 | defer patchEnv("HOME", "/custom/path/")() 90 | expected := "/custom/path/foo/bar" 91 | actual, err := Expand("~/foo/bar") 92 | 93 | if err != nil { 94 | t.Errorf("No error is expected, got: %v", err) 95 | } else if actual != "/custom/path/foo/bar" { 96 | t.Errorf("Expected: %v; actual: %v", expected, actual) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### Go ### 4 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 5 | *.o 6 | *.a 7 | *.so 8 | 9 | # Folders 10 | _obj 11 | _test 12 | 13 | # Architecture specific extensions/prefixes 14 | *.[568vq] 15 | [568vq].out 16 | 17 | *.cgo1.go 18 | *.cgo2.c 19 | _cgo_defun.c 20 | _cgo_gotypes.go 21 | _cgo_export.* 22 | 23 | _testmain.go 24 | 25 | *.exe 26 | *.test 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) [2014] [shiena] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/README.md: -------------------------------------------------------------------------------- 1 | # ansicolor 2 | 3 | Ansicolor library provides color console in Windows as ANSICON for Golang. 4 | 5 | ## Features 6 | 7 | |Escape sequence|Text attributes| 8 | |---------------|----| 9 | |\x1b[0m|All attributes off(color at startup)| 10 | |\x1b[1m|Bold on(enable foreground intensity)| 11 | |\x1b[4m|Underline on| 12 | |\x1b[5m|Blink on(enable background intensity)| 13 | |\x1b[21m|Bold off(disable foreground intensity)| 14 | |\x1b[24m|Underline off| 15 | |\x1b[25m|Blink off(disable background intensity)| 16 | 17 | |Escape sequence|Foreground colors| 18 | |---------------|----| 19 | |\x1b[30m|Black| 20 | |\x1b[31m|Red| 21 | |\x1b[32m|Green| 22 | |\x1b[33m|Yellow| 23 | |\x1b[34m|Blue| 24 | |\x1b[35m|Magenta| 25 | |\x1b[36m|Cyan| 26 | |\x1b[37m|White| 27 | |\x1b[39m|Default(foreground color at startup)| 28 | 29 | |Escape sequence|Background colors| 30 | |---------------|----| 31 | |\x1b[40m|Black| 32 | |\x1b[41m|Red| 33 | |\x1b[42m|Green| 34 | |\x1b[43m|Yellow| 35 | |\x1b[44m|Blue| 36 | |\x1b[45m|Magenta| 37 | |\x1b[46m|Cyan| 38 | |\x1b[47m|White| 39 | |\x1b[49m|Default(background color at startup)| 40 | 41 | ## Example 42 | 43 | ```go 44 | package main 45 | 46 | import ( 47 | "fmt" 48 | "os" 49 | 50 | "github.com/shiena/ansicolor" 51 | ) 52 | 53 | func main() { 54 | w := ansicolor.NewAnsiColorWriter(os.Stdout) 55 | text := "%sforeground %sbold%s %sbackground%s\n" 56 | fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m") 57 | fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m") 58 | fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m") 59 | fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m") 60 | fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m") 61 | fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m") 62 | fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m") 63 | } 64 | ``` 65 | 66 | ![screenshot](https://gist.githubusercontent.com/shiena/a1bada24b525314a7d5e/raw/c763aa7cda6e4fefaccf831e2617adc40b6151c7/main.png) 67 | 68 | ## See also: 69 | 70 | - https://github.com/daviddengcn/go-colortext 71 | - https://github.com/adoxa/ansicon 72 | - https://github.com/aslakhellesoy/wac 73 | - https://github.com/wsxiaoys/terminal 74 | 75 | ## Contributing 76 | 77 | 1. Fork it 78 | 2. Create your feature branch (`git checkout -b my-new-feature`) 79 | 3. Commit your changes (`git commit -am 'Add some feature'`) 80 | 4. Push to the branch (`git push origin my-new-feature`) 81 | 5. Create new Pull Request 82 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package ansicolor provides color console in Windows as ANSICON. 6 | package ansicolor 7 | 8 | import "io" 9 | 10 | // NewAnsiColorWriter creates and initializes a new ansiColorWriter 11 | // using io.Writer w as its initial contents. 12 | // In the console of Windows, which change the foreground and background 13 | // colors of the text by the escape sequence. 14 | // In the console of other systems, which writes to w all text. 15 | func NewAnsiColorWriter(w io.Writer) io.Writer { 16 | return &ansiColorWriter{w: w} 17 | } 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | 7 | The ansicolor command colors a console text by ANSI escape sequence like wac. 8 | 9 | $ go get github.com/shiena/ansicolor/ansicolor 10 | 11 | See also: 12 | https://github.com/aslakhellesoy/wac 13 | 14 | */ 15 | package main 16 | 17 | import ( 18 | "io" 19 | "os" 20 | 21 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 22 | ) 23 | 24 | func main() { 25 | w := ansicolor.NewAnsiColorWriter(os.Stdout) 26 | io.Copy(w, os.Stdin) 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package ansicolor 8 | 9 | import "io" 10 | 11 | type ansiColorWriter struct { 12 | w io.Writer 13 | } 14 | 15 | func (cw *ansiColorWriter) Write(p []byte) (int, error) { 16 | return cw.w.Write(p) 17 | } 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | package ansicolor 8 | 9 | import ( 10 | "bytes" 11 | "io" 12 | "strings" 13 | "syscall" 14 | "unsafe" 15 | ) 16 | 17 | type csiState int 18 | 19 | const ( 20 | outsideCsiCode csiState = iota 21 | firstCsiCode 22 | secondeCsiCode 23 | ) 24 | 25 | type ansiColorWriter struct { 26 | w io.Writer 27 | state csiState 28 | paramBuf bytes.Buffer 29 | } 30 | 31 | const ( 32 | firstCsiChar byte = '\x1b' 33 | secondeCsiChar byte = '[' 34 | separatorChar byte = ';' 35 | sgrCode byte = 'm' 36 | ) 37 | 38 | const ( 39 | foregroundBlue = uint16(0x0001) 40 | foregroundGreen = uint16(0x0002) 41 | foregroundRed = uint16(0x0004) 42 | foregroundIntensity = uint16(0x0008) 43 | backgroundBlue = uint16(0x0010) 44 | backgroundGreen = uint16(0x0020) 45 | backgroundRed = uint16(0x0040) 46 | backgroundIntensity = uint16(0x0080) 47 | underscore = uint16(0x8000) 48 | 49 | foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity 50 | backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity 51 | ) 52 | 53 | const ( 54 | ansiReset = "0" 55 | ansiIntensityOn = "1" 56 | ansiIntensityOff = "21" 57 | ansiUnderlineOn = "4" 58 | ansiUnderlineOff = "24" 59 | ansiBlinkOn = "5" 60 | ansiBlinkOff = "25" 61 | 62 | ansiForegroundBlack = "30" 63 | ansiForegroundRed = "31" 64 | ansiForegroundGreen = "32" 65 | ansiForegroundYellow = "33" 66 | ansiForegroundBlue = "34" 67 | ansiForegroundMagenta = "35" 68 | ansiForegroundCyan = "36" 69 | ansiForegroundWhite = "37" 70 | ansiForegroundDefault = "39" 71 | 72 | ansiBackgroundBlack = "40" 73 | ansiBackgroundRed = "41" 74 | ansiBackgroundGreen = "42" 75 | ansiBackgroundYellow = "43" 76 | ansiBackgroundBlue = "44" 77 | ansiBackgroundMagenta = "45" 78 | ansiBackgroundCyan = "46" 79 | ansiBackgroundWhite = "47" 80 | ansiBackgroundDefault = "49" 81 | ) 82 | 83 | type drawType int 84 | 85 | const ( 86 | foreground drawType = iota 87 | background 88 | ) 89 | 90 | type winColor struct { 91 | code uint16 92 | drawType drawType 93 | } 94 | 95 | var colorMap = map[string]winColor{ 96 | ansiForegroundBlack: {0, foreground}, 97 | ansiForegroundRed: {foregroundRed, foreground}, 98 | ansiForegroundGreen: {foregroundGreen, foreground}, 99 | ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground}, 100 | ansiForegroundBlue: {foregroundBlue, foreground}, 101 | ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground}, 102 | ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground}, 103 | ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, 104 | ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, 105 | 106 | ansiBackgroundBlack: {0, background}, 107 | ansiBackgroundRed: {backgroundRed, background}, 108 | ansiBackgroundGreen: {backgroundGreen, background}, 109 | ansiBackgroundYellow: {backgroundRed | backgroundGreen, background}, 110 | ansiBackgroundBlue: {backgroundBlue, background}, 111 | ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background}, 112 | ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background}, 113 | ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background}, 114 | ansiBackgroundDefault: {0, background}, 115 | } 116 | 117 | var ( 118 | kernel32 = syscall.NewLazyDLL("kernel32.dll") 119 | procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") 120 | procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") 121 | defaultAttr *textAttributes 122 | ) 123 | 124 | func init() { 125 | screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) 126 | if screenInfo != nil { 127 | colorMap[ansiForegroundDefault] = winColor{ 128 | screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue), 129 | foreground, 130 | } 131 | colorMap[ansiBackgroundDefault] = winColor{ 132 | screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue), 133 | background, 134 | } 135 | defaultAttr = convertTextAttr(screenInfo.WAttributes) 136 | } 137 | } 138 | 139 | type coord struct { 140 | X, Y int16 141 | } 142 | 143 | type smallRect struct { 144 | Left, Top, Right, Bottom int16 145 | } 146 | 147 | type consoleScreenBufferInfo struct { 148 | DwSize coord 149 | DwCursorPosition coord 150 | WAttributes uint16 151 | SrWindow smallRect 152 | DwMaximumWindowSize coord 153 | } 154 | 155 | func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo { 156 | var csbi consoleScreenBufferInfo 157 | ret, _, _ := procGetConsoleScreenBufferInfo.Call( 158 | hConsoleOutput, 159 | uintptr(unsafe.Pointer(&csbi))) 160 | if ret == 0 { 161 | return nil 162 | } 163 | return &csbi 164 | } 165 | 166 | func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool { 167 | ret, _, _ := procSetConsoleTextAttribute.Call( 168 | hConsoleOutput, 169 | uintptr(wAttributes)) 170 | return ret != 0 171 | } 172 | 173 | type textAttributes struct { 174 | foregroundColor uint16 175 | backgroundColor uint16 176 | foregroundIntensity uint16 177 | backgroundIntensity uint16 178 | underscore uint16 179 | otherAttributes uint16 180 | } 181 | 182 | func convertTextAttr(winAttr uint16) *textAttributes { 183 | fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue) 184 | bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue) 185 | fgIntensity := winAttr & foregroundIntensity 186 | bgIntensity := winAttr & backgroundIntensity 187 | underline := winAttr & underscore 188 | otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore) 189 | return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes} 190 | } 191 | 192 | func convertWinAttr(textAttr *textAttributes) uint16 { 193 | var winAttr uint16 = 0 194 | winAttr |= textAttr.foregroundColor 195 | winAttr |= textAttr.backgroundColor 196 | winAttr |= textAttr.foregroundIntensity 197 | winAttr |= textAttr.backgroundIntensity 198 | winAttr |= textAttr.underscore 199 | winAttr |= textAttr.otherAttributes 200 | return winAttr 201 | } 202 | 203 | func changeColor(param []byte) { 204 | if defaultAttr == nil { 205 | return 206 | } 207 | 208 | screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) 209 | if screenInfo == nil { 210 | return 211 | } 212 | 213 | winAttr := convertTextAttr(screenInfo.WAttributes) 214 | strParam := string(param) 215 | if len(strParam) <= 0 { 216 | strParam = "0" 217 | } 218 | csiParam := strings.Split(strParam, string(separatorChar)) 219 | for _, p := range csiParam { 220 | c, ok := colorMap[p] 221 | switch { 222 | case !ok: 223 | switch p { 224 | case ansiReset: 225 | winAttr.foregroundColor = defaultAttr.foregroundColor 226 | winAttr.backgroundColor = defaultAttr.backgroundColor 227 | winAttr.foregroundIntensity = defaultAttr.foregroundIntensity 228 | winAttr.backgroundIntensity = defaultAttr.backgroundIntensity 229 | winAttr.underscore = 0 230 | winAttr.otherAttributes = 0 231 | case ansiIntensityOn: 232 | winAttr.foregroundIntensity = foregroundIntensity 233 | case ansiIntensityOff: 234 | winAttr.foregroundIntensity = 0 235 | case ansiUnderlineOn: 236 | winAttr.underscore = underscore 237 | case ansiUnderlineOff: 238 | winAttr.underscore = 0 239 | case ansiBlinkOn: 240 | winAttr.backgroundIntensity = backgroundIntensity 241 | case ansiBlinkOff: 242 | winAttr.backgroundIntensity = 0 243 | default: 244 | // unknown code 245 | } 246 | case c.drawType == foreground: 247 | winAttr.foregroundColor = c.code 248 | case c.drawType == background: 249 | winAttr.backgroundColor = c.code 250 | } 251 | } 252 | winTextAttribute := convertWinAttr(winAttr) 253 | setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute) 254 | } 255 | 256 | func parseEscapeSequence(command byte, param []byte) { 257 | switch command { 258 | case sgrCode: 259 | changeColor(param) 260 | } 261 | } 262 | 263 | func isParameterChar(b byte) bool { 264 | return ('0' <= b && b <= '9') || b == separatorChar 265 | } 266 | 267 | func (cw *ansiColorWriter) Write(p []byte) (int, error) { 268 | r, nw, nc, first, last := 0, 0, 0, 0, 0 269 | var err error 270 | for i, ch := range p { 271 | switch cw.state { 272 | case outsideCsiCode: 273 | if ch == firstCsiChar { 274 | nc++ 275 | cw.state = firstCsiCode 276 | } 277 | case firstCsiCode: 278 | switch ch { 279 | case firstCsiChar: 280 | nc++ 281 | break 282 | case secondeCsiChar: 283 | nc++ 284 | cw.state = secondeCsiCode 285 | last = i - 1 286 | default: 287 | cw.state = outsideCsiCode 288 | } 289 | case secondeCsiCode: 290 | nc++ 291 | if isParameterChar(ch) { 292 | cw.paramBuf.WriteByte(ch) 293 | } else { 294 | nw, err = cw.w.Write(p[first:last]) 295 | r += nw 296 | if err != nil { 297 | return r, err 298 | } 299 | first = i + 1 300 | param := cw.paramBuf.Bytes() 301 | cw.paramBuf.Reset() 302 | parseEscapeSequence(ch, param) 303 | cw.state = outsideCsiCode 304 | } 305 | default: 306 | cw.state = outsideCsiCode 307 | } 308 | } 309 | 310 | if cw.state == outsideCsiCode { 311 | nw, err = cw.w.Write(p[first:len(p)]) 312 | } 313 | 314 | return r + nw + nc, err 315 | } 316 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | package ansicolor_test 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "syscall" 13 | "testing" 14 | 15 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 16 | . "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 17 | ) 18 | 19 | func TestWritePlanText(t *testing.T) { 20 | inner := bytes.NewBufferString("") 21 | w := ansicolor.NewAnsiColorWriter(inner) 22 | expected := "plain text" 23 | fmt.Fprintf(w, expected) 24 | actual := inner.String() 25 | if actual != expected { 26 | t.Errorf("Get %s, want %s", actual, expected) 27 | } 28 | } 29 | 30 | func TestWriteParseText(t *testing.T) { 31 | inner := bytes.NewBufferString("") 32 | w := ansicolor.NewAnsiColorWriter(inner) 33 | 34 | inputTail := "\x1b[0mtail text" 35 | expectedTail := "tail text" 36 | fmt.Fprintf(w, inputTail) 37 | actualTail := inner.String() 38 | inner.Reset() 39 | if actualTail != expectedTail { 40 | t.Errorf("Get %s, want %s", actualTail, expectedTail) 41 | } 42 | 43 | inputHead := "head text\x1b[0m" 44 | expectedHead := "head text" 45 | fmt.Fprintf(w, inputHead) 46 | actualHead := inner.String() 47 | inner.Reset() 48 | if actualHead != expectedHead { 49 | t.Errorf("Get %s, want %s", actualHead, expectedHead) 50 | } 51 | 52 | inputBothEnds := "both ends \x1b[0m text" 53 | expectedBothEnds := "both ends text" 54 | fmt.Fprintf(w, inputBothEnds) 55 | actualBothEnds := inner.String() 56 | inner.Reset() 57 | if actualBothEnds != expectedBothEnds { 58 | t.Errorf("Get %s, want %s", actualBothEnds, expectedBothEnds) 59 | } 60 | 61 | inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc" 62 | expectedManyEsc := "\x1b\x1b\x1b many esc" 63 | fmt.Fprintf(w, inputManyEsc) 64 | actualManyEsc := inner.String() 65 | inner.Reset() 66 | if actualManyEsc != expectedManyEsc { 67 | t.Errorf("Get %s, want %s", actualManyEsc, expectedManyEsc) 68 | } 69 | 70 | expectedSplit := "split text" 71 | for _, ch := range "split \x1b[0m text" { 72 | fmt.Fprintf(w, string(ch)) 73 | } 74 | actualSplit := inner.String() 75 | inner.Reset() 76 | if actualSplit != expectedSplit { 77 | t.Errorf("Get %s, want %s", actualSplit, expectedSplit) 78 | } 79 | } 80 | 81 | type screenNotFoundError struct { 82 | error 83 | } 84 | 85 | func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) { 86 | inner := bytes.NewBufferString("") 87 | w := ansicolor.NewAnsiColorWriter(inner) 88 | fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText) 89 | 90 | actualText = inner.String() 91 | screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout)) 92 | if screenInfo != nil { 93 | actualAttributes = screenInfo.WAttributes 94 | } else { 95 | err = &screenNotFoundError{} 96 | } 97 | return 98 | } 99 | 100 | type testParam struct { 101 | text string 102 | attributes uint16 103 | ansiColor string 104 | } 105 | 106 | func TestWriteAnsiColorText(t *testing.T) { 107 | screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout)) 108 | if screenInfo == nil { 109 | t.Fatal("Could not get ConsoleScreenBufferInfo") 110 | } 111 | defer ChangeColor(screenInfo.WAttributes) 112 | defaultFgColor := screenInfo.WAttributes & uint16(0x0007) 113 | defaultBgColor := screenInfo.WAttributes & uint16(0x0070) 114 | defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008) 115 | defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080) 116 | 117 | fgParam := []testParam{ 118 | {"foreground black ", uint16(0x0000 | 0x0000), "30"}, 119 | {"foreground red ", uint16(0x0004 | 0x0000), "31"}, 120 | {"foreground green ", uint16(0x0002 | 0x0000), "32"}, 121 | {"foreground yellow ", uint16(0x0006 | 0x0000), "33"}, 122 | {"foreground blue ", uint16(0x0001 | 0x0000), "34"}, 123 | {"foreground magenta", uint16(0x0005 | 0x0000), "35"}, 124 | {"foreground cyan ", uint16(0x0003 | 0x0000), "36"}, 125 | {"foreground white ", uint16(0x0007 | 0x0000), "37"}, 126 | {"foreground default", defaultFgColor | 0x0000, "39"}, 127 | } 128 | 129 | bgParam := []testParam{ 130 | {"background black ", uint16(0x0007 | 0x0000), "40"}, 131 | {"background red ", uint16(0x0007 | 0x0040), "41"}, 132 | {"background green ", uint16(0x0007 | 0x0020), "42"}, 133 | {"background yellow ", uint16(0x0007 | 0x0060), "43"}, 134 | {"background blue ", uint16(0x0007 | 0x0010), "44"}, 135 | {"background magenta", uint16(0x0007 | 0x0050), "45"}, 136 | {"background cyan ", uint16(0x0007 | 0x0030), "46"}, 137 | {"background white ", uint16(0x0007 | 0x0070), "47"}, 138 | {"background default", uint16(0x0007) | defaultBgColor, "49"}, 139 | } 140 | 141 | resetParam := []testParam{ 142 | {"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"}, 143 | {"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""}, 144 | } 145 | 146 | boldParam := []testParam{ 147 | {"bold on", uint16(0x0007 | 0x0008), "1"}, 148 | {"bold off", uint16(0x0007), "21"}, 149 | } 150 | 151 | underscoreParam := []testParam{ 152 | {"underscore on", uint16(0x0007 | 0x8000), "4"}, 153 | {"underscore off", uint16(0x0007), "24"}, 154 | } 155 | 156 | blinkParam := []testParam{ 157 | {"blink on", uint16(0x0007 | 0x0080), "5"}, 158 | {"blink off", uint16(0x0007), "25"}, 159 | } 160 | 161 | mixedParam := []testParam{ 162 | {"both black, bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"}, 163 | {"both red, bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"}, 164 | {"both green, bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"}, 165 | {"both yellow, bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"}, 166 | {"both blue, bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"}, 167 | {"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"}, 168 | {"both cyan, bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"}, 169 | {"both white, bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"}, 170 | {"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"}, 171 | } 172 | 173 | assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) { 174 | actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor) 175 | if actualText != expectedText { 176 | t.Errorf("Get %s, want %s", actualText, expectedText) 177 | } 178 | if err != nil { 179 | t.Fatal("Could not get ConsoleScreenBufferInfo") 180 | } 181 | if actualAttributes != expectedAttributes { 182 | t.Errorf("Text: %s, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes) 183 | } 184 | } 185 | 186 | for _, v := range fgParam { 187 | ResetColor() 188 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 189 | } 190 | 191 | for _, v := range bgParam { 192 | ChangeColor(uint16(0x0070 | 0x0007)) 193 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 194 | } 195 | 196 | for _, v := range resetParam { 197 | ChangeColor(uint16(0x0000 | 0x0070 | 0x0008)) 198 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 199 | } 200 | 201 | ResetColor() 202 | for _, v := range boldParam { 203 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 204 | } 205 | 206 | ResetColor() 207 | for _, v := range underscoreParam { 208 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 209 | } 210 | 211 | ResetColor() 212 | for _, v := range blinkParam { 213 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 214 | } 215 | 216 | for _, v := range mixedParam { 217 | ResetColor() 218 | assertTextAttribute(v.text, v.attributes, v.ansiColor) 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ansicolor_test 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | 11 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/shiena/ansicolor" 12 | ) 13 | 14 | func ExampleNewAnsiColorWriter() { 15 | w := ansicolor.NewAnsiColorWriter(os.Stdout) 16 | text := "%sforeground %sbold%s %sbackground%s\n" 17 | fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m") 18 | fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m") 19 | fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m") 20 | fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m") 21 | fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m") 22 | fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m") 23 | fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m") 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 shiena Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build windows 6 | 7 | package ansicolor 8 | 9 | import "syscall" 10 | 11 | var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo 12 | 13 | func ChangeColor(color uint16) { 14 | setConsoleTextAttribute(uintptr(syscall.Stdout), color) 15 | } 16 | 17 | func ResetColor() { 18 | ChangeColor(uint16(0x0007)) 19 | } 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2011-2014 - Canonical Inc. 3 | 4 | This software is licensed under the LGPLv3, included below. 5 | 6 | As a special exception to the GNU Lesser General Public License version 3 7 | ("LGPL3"), the copyright holders of this Library give you permission to 8 | convey to a third party a Combined Work that links statically or dynamically 9 | to this Library without providing any Minimal Corresponding Source or 10 | Minimal Application Code as set out in 4d or providing the installation 11 | information set out in section 4e, provided that you comply with the other 12 | provisions of LGPL3 and provided that you meet, for the Application the 13 | terms and conditions of the license(s) which apply to the Application. 14 | 15 | Except as stated in this special exception, the provisions of LGPL3 will 16 | continue to comply in full to this Library. If you modify this Library, you 17 | may apply this exception to your version of this Library, but you are not 18 | obliged to do so. If you do not wish to do so, delete this exception 19 | statement from your version. This exception does not (and cannot) modify any 20 | license terms which apply to the Application, with which you must still 21 | comply. 22 | 23 | 24 | GNU LESSER GENERAL PUBLIC LICENSE 25 | Version 3, 29 June 2007 26 | 27 | Copyright (C) 2007 Free Software Foundation, Inc. 28 | Everyone is permitted to copy and distribute verbatim copies 29 | of this license document, but changing it is not allowed. 30 | 31 | 32 | This version of the GNU Lesser General Public License incorporates 33 | the terms and conditions of version 3 of the GNU General Public 34 | License, supplemented by the additional permissions listed below. 35 | 36 | 0. Additional Definitions. 37 | 38 | As used herein, "this License" refers to version 3 of the GNU Lesser 39 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 40 | General Public License. 41 | 42 | "The Library" refers to a covered work governed by this License, 43 | other than an Application or a Combined Work as defined below. 44 | 45 | An "Application" is any work that makes use of an interface provided 46 | by the Library, but which is not otherwise based on the Library. 47 | Defining a subclass of a class defined by the Library is deemed a mode 48 | of using an interface provided by the Library. 49 | 50 | A "Combined Work" is a work produced by combining or linking an 51 | Application with the Library. The particular version of the Library 52 | with which the Combined Work was made is also called the "Linked 53 | Version". 54 | 55 | The "Minimal Corresponding Source" for a Combined Work means the 56 | Corresponding Source for the Combined Work, excluding any source code 57 | for portions of the Combined Work that, considered in isolation, are 58 | based on the Application, and not on the Linked Version. 59 | 60 | The "Corresponding Application Code" for a Combined Work means the 61 | object code and/or source code for the Application, including any data 62 | and utility programs needed for reproducing the Combined Work from the 63 | Application, but excluding the System Libraries of the Combined Work. 64 | 65 | 1. Exception to Section 3 of the GNU GPL. 66 | 67 | You may convey a covered work under sections 3 and 4 of this License 68 | without being bound by section 3 of the GNU GPL. 69 | 70 | 2. Conveying Modified Versions. 71 | 72 | If you modify a copy of the Library, and, in your modifications, a 73 | facility refers to a function or data to be supplied by an Application 74 | that uses the facility (other than as an argument passed when the 75 | facility is invoked), then you may convey a copy of the modified 76 | version: 77 | 78 | a) under this License, provided that you make a good faith effort to 79 | ensure that, in the event an Application does not supply the 80 | function or data, the facility still operates, and performs 81 | whatever part of its purpose remains meaningful, or 82 | 83 | b) under the GNU GPL, with none of the additional permissions of 84 | this License applicable to that copy. 85 | 86 | 3. Object Code Incorporating Material from Library Header Files. 87 | 88 | The object code form of an Application may incorporate material from 89 | a header file that is part of the Library. You may convey such object 90 | code under terms of your choice, provided that, if the incorporated 91 | material is not limited to numerical parameters, data structure 92 | layouts and accessors, or small macros, inline functions and templates 93 | (ten or fewer lines in length), you do both of the following: 94 | 95 | a) Give prominent notice with each copy of the object code that the 96 | Library is used in it and that the Library and its use are 97 | covered by this License. 98 | 99 | b) Accompany the object code with a copy of the GNU GPL and this license 100 | document. 101 | 102 | 4. Combined Works. 103 | 104 | You may convey a Combined Work under terms of your choice that, 105 | taken together, effectively do not restrict modification of the 106 | portions of the Library contained in the Combined Work and reverse 107 | engineering for debugging such modifications, if you also do each of 108 | the following: 109 | 110 | a) Give prominent notice with each copy of the Combined Work that 111 | the Library is used in it and that the Library and its use are 112 | covered by this License. 113 | 114 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 115 | document. 116 | 117 | c) For a Combined Work that displays copyright notices during 118 | execution, include the copyright notice for the Library among 119 | these notices, as well as a reference directing the user to the 120 | copies of the GNU GPL and this license document. 121 | 122 | d) Do one of the following: 123 | 124 | 0) Convey the Minimal Corresponding Source under the terms of this 125 | License, and the Corresponding Application Code in a form 126 | suitable for, and under terms that permit, the user to 127 | recombine or relink the Application with a modified version of 128 | the Linked Version to produce a modified Combined Work, in the 129 | manner specified by section 6 of the GNU GPL for conveying 130 | Corresponding Source. 131 | 132 | 1) Use a suitable shared library mechanism for linking with the 133 | Library. A suitable mechanism is one that (a) uses at run time 134 | a copy of the Library already present on the user's computer 135 | system, and (b) will operate properly with a modified version 136 | of the Library that is interface-compatible with the Linked 137 | Version. 138 | 139 | e) Provide Installation Information, but only if you would otherwise 140 | be required to provide such information under section 6 of the 141 | GNU GPL, and only to the extent that such information is 142 | necessary to install and execute a modified version of the 143 | Combined Work produced by recombining or relinking the 144 | Application with a modified version of the Linked Version. (If 145 | you use option 4d0, the Installation Information must accompany 146 | the Minimal Corresponding Source and Corresponding Application 147 | Code. If you use option 4d1, you must provide the Installation 148 | Information in the manner specified by section 6 of the GNU GPL 149 | for conveying Corresponding Source.) 150 | 151 | 5. Combined Libraries. 152 | 153 | You may place library facilities that are a work based on the 154 | Library side by side in a single library together with other library 155 | facilities that are not Applications and are not covered by this 156 | License, and convey such a combined library under terms of your 157 | choice, if you do both of the following: 158 | 159 | a) Accompany the combined library with a copy of the same work based 160 | on the Library, uncombined with any other library facilities, 161 | conveyed under the terms of this License. 162 | 163 | b) Give prominent notice with the combined library that part of it 164 | is a work based on the Library, and explaining where to find the 165 | accompanying uncombined form of the same work. 166 | 167 | 6. Revised Versions of the GNU Lesser General Public License. 168 | 169 | The Free Software Foundation may publish revised and/or new versions 170 | of the GNU Lesser General Public License from time to time. Such new 171 | versions will be similar in spirit to the present version, but may 172 | differ in detail to address new problems or concerns. 173 | 174 | Each version is given a distinguishing version number. If the 175 | Library as you received it specifies that a certain numbered version 176 | of the GNU Lesser General Public License "or any later version" 177 | applies to it, you have the option of following the terms and 178 | conditions either of that published version or of any later version 179 | published by the Free Software Foundation. If the Library as you 180 | received it does not specify a version number of the GNU Lesser 181 | General Public License, you may choose any version of the GNU Lesser 182 | General Public License ever published by the Free Software Foundation. 183 | 184 | If the Library as you received it specifies that a proxy can decide 185 | whether future versions of the GNU Lesser General Public License shall 186 | apply, that proxy's public statement of acceptance of any version is 187 | permanent authorization for you to choose that version for the 188 | Library. 189 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | type T struct { 69 | A string 70 | B struct{C int; D []int ",flow"} 71 | } 72 | 73 | func main() { 74 | t := T{} 75 | 76 | err := yaml.Unmarshal([]byte(data), &t) 77 | if err != nil { 78 | log.Fatalf("error: %v", err) 79 | } 80 | fmt.Printf("--- t:\n%v\n\n", t) 81 | 82 | d, err := yaml.Marshal(&t) 83 | if err != nil { 84 | log.Fatalf("error: %v", err) 85 | } 86 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 87 | 88 | m := make(map[interface{}]interface{}) 89 | 90 | err = yaml.Unmarshal([]byte(data), &m) 91 | if err != nil { 92 | log.Fatalf("error: %v", err) 93 | } 94 | fmt.Printf("--- m:\n%v\n\n", m) 95 | 96 | d, err = yaml.Marshal(&m) 97 | if err != nil { 98 | log.Fatalf("error: %v", err) 99 | } 100 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 101 | } 102 | ``` 103 | 104 | This example will generate the following output: 105 | 106 | ``` 107 | --- t: 108 | {Easy! {2 [3 4]}} 109 | 110 | --- t dump: 111 | a: Easy! 112 | b: 113 | c: 2 114 | d: [3, 4] 115 | 116 | 117 | --- m: 118 | map[a:Easy! b:map[c:2 d:[3 4]]] 119 | 120 | --- m dump: 121 | a: Easy! 122 | b: 123 | c: 2 124 | d: 125 | - 3 126 | - 4 127 | ``` 128 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding" 5 | "reflect" 6 | "regexp" 7 | "sort" 8 | "strconv" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | type encoder struct { 14 | emitter yaml_emitter_t 15 | event yaml_event_t 16 | out []byte 17 | flow bool 18 | } 19 | 20 | func newEncoder() (e *encoder) { 21 | e = &encoder{} 22 | e.must(yaml_emitter_initialize(&e.emitter)) 23 | yaml_emitter_set_output_string(&e.emitter, &e.out) 24 | yaml_emitter_set_unicode(&e.emitter, true) 25 | e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) 26 | e.emit() 27 | e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) 28 | e.emit() 29 | return e 30 | } 31 | 32 | func (e *encoder) finish() { 33 | e.must(yaml_document_end_event_initialize(&e.event, true)) 34 | e.emit() 35 | e.emitter.open_ended = false 36 | e.must(yaml_stream_end_event_initialize(&e.event)) 37 | e.emit() 38 | } 39 | 40 | func (e *encoder) destroy() { 41 | yaml_emitter_delete(&e.emitter) 42 | } 43 | 44 | func (e *encoder) emit() { 45 | // This will internally delete the e.event value. 46 | if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { 47 | e.must(false) 48 | } 49 | } 50 | 51 | func (e *encoder) must(ok bool) { 52 | if !ok { 53 | msg := e.emitter.problem 54 | if msg == "" { 55 | msg = "unknown problem generating YAML content" 56 | } 57 | failf("%s", msg) 58 | } 59 | } 60 | 61 | func (e *encoder) marshal(tag string, in reflect.Value) { 62 | if !in.IsValid() { 63 | e.nilv() 64 | return 65 | } 66 | iface := in.Interface() 67 | if m, ok := iface.(Marshaler); ok { 68 | v, err := m.MarshalYAML() 69 | if err != nil { 70 | fail(err) 71 | } 72 | if v == nil { 73 | e.nilv() 74 | return 75 | } 76 | in = reflect.ValueOf(v) 77 | } 78 | if m, ok := iface.(encoding.TextMarshaler); ok { 79 | text, err := m.MarshalText() 80 | if err != nil { 81 | fail(err) 82 | } 83 | in = reflect.ValueOf(string(text)) 84 | } 85 | switch in.Kind() { 86 | case reflect.Interface: 87 | if in.IsNil() { 88 | e.nilv() 89 | } else { 90 | e.marshal(tag, in.Elem()) 91 | } 92 | case reflect.Map: 93 | e.mapv(tag, in) 94 | case reflect.Ptr: 95 | if in.IsNil() { 96 | e.nilv() 97 | } else { 98 | e.marshal(tag, in.Elem()) 99 | } 100 | case reflect.Struct: 101 | e.structv(tag, in) 102 | case reflect.Slice: 103 | if in.Type().Elem() == mapItemType { 104 | e.itemsv(tag, in) 105 | } else { 106 | e.slicev(tag, in) 107 | } 108 | case reflect.String: 109 | e.stringv(tag, in) 110 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 111 | if in.Type() == durationType { 112 | e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) 113 | } else { 114 | e.intv(tag, in) 115 | } 116 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 117 | e.uintv(tag, in) 118 | case reflect.Float32, reflect.Float64: 119 | e.floatv(tag, in) 120 | case reflect.Bool: 121 | e.boolv(tag, in) 122 | default: 123 | panic("cannot marshal type: " + in.Type().String()) 124 | } 125 | } 126 | 127 | func (e *encoder) mapv(tag string, in reflect.Value) { 128 | e.mappingv(tag, func() { 129 | keys := keyList(in.MapKeys()) 130 | sort.Sort(keys) 131 | for _, k := range keys { 132 | e.marshal("", k) 133 | e.marshal("", in.MapIndex(k)) 134 | } 135 | }) 136 | } 137 | 138 | func (e *encoder) itemsv(tag string, in reflect.Value) { 139 | e.mappingv(tag, func() { 140 | slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) 141 | for _, item := range slice { 142 | e.marshal("", reflect.ValueOf(item.Key)) 143 | e.marshal("", reflect.ValueOf(item.Value)) 144 | } 145 | }) 146 | } 147 | 148 | func (e *encoder) structv(tag string, in reflect.Value) { 149 | sinfo, err := getStructInfo(in.Type()) 150 | if err != nil { 151 | panic(err) 152 | } 153 | e.mappingv(tag, func() { 154 | for _, info := range sinfo.FieldsList { 155 | var value reflect.Value 156 | if info.Inline == nil { 157 | value = in.Field(info.Num) 158 | } else { 159 | value = in.FieldByIndex(info.Inline) 160 | } 161 | if info.OmitEmpty && isZero(value) { 162 | continue 163 | } 164 | e.marshal("", reflect.ValueOf(info.Key)) 165 | e.flow = info.Flow 166 | e.marshal("", value) 167 | } 168 | }) 169 | } 170 | 171 | func (e *encoder) mappingv(tag string, f func()) { 172 | implicit := tag == "" 173 | style := yaml_BLOCK_MAPPING_STYLE 174 | if e.flow { 175 | e.flow = false 176 | style = yaml_FLOW_MAPPING_STYLE 177 | } 178 | e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 179 | e.emit() 180 | f() 181 | e.must(yaml_mapping_end_event_initialize(&e.event)) 182 | e.emit() 183 | } 184 | 185 | func (e *encoder) slicev(tag string, in reflect.Value) { 186 | implicit := tag == "" 187 | style := yaml_BLOCK_SEQUENCE_STYLE 188 | if e.flow { 189 | e.flow = false 190 | style = yaml_FLOW_SEQUENCE_STYLE 191 | } 192 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 193 | e.emit() 194 | n := in.Len() 195 | for i := 0; i < n; i++ { 196 | e.marshal("", in.Index(i)) 197 | } 198 | e.must(yaml_sequence_end_event_initialize(&e.event)) 199 | e.emit() 200 | } 201 | 202 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 203 | // 204 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 205 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 206 | // the time being for compatibility with other parsers. 207 | func isBase60Float(s string) (result bool) { 208 | // Fast path. 209 | if s == "" { 210 | return false 211 | } 212 | c := s[0] 213 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 214 | return false 215 | } 216 | // Do the full match. 217 | return base60float.MatchString(s) 218 | } 219 | 220 | // From http://yaml.org/type/float.html, except the regular expression there 221 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 222 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 223 | 224 | func (e *encoder) stringv(tag string, in reflect.Value) { 225 | var style yaml_scalar_style_t 226 | s := in.String() 227 | rtag, rs := resolve("", s) 228 | if rtag == yaml_BINARY_TAG { 229 | if tag == "" || tag == yaml_STR_TAG { 230 | tag = rtag 231 | s = rs.(string) 232 | } else if tag == yaml_BINARY_TAG { 233 | failf("explicitly tagged !!binary data must be base64-encoded") 234 | } else { 235 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) 236 | } 237 | } 238 | if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { 239 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 240 | } else if strings.Contains(s, "\n") { 241 | style = yaml_LITERAL_SCALAR_STYLE 242 | } else { 243 | style = yaml_PLAIN_SCALAR_STYLE 244 | } 245 | e.emitScalar(s, "", tag, style) 246 | } 247 | 248 | func (e *encoder) boolv(tag string, in reflect.Value) { 249 | var s string 250 | if in.Bool() { 251 | s = "true" 252 | } else { 253 | s = "false" 254 | } 255 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 256 | } 257 | 258 | func (e *encoder) intv(tag string, in reflect.Value) { 259 | s := strconv.FormatInt(in.Int(), 10) 260 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 261 | } 262 | 263 | func (e *encoder) uintv(tag string, in reflect.Value) { 264 | s := strconv.FormatUint(in.Uint(), 10) 265 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 266 | } 267 | 268 | func (e *encoder) floatv(tag string, in reflect.Value) { 269 | // FIXME: Handle 64 bits here. 270 | s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) 271 | switch s { 272 | case "+Inf": 273 | s = ".inf" 274 | case "-Inf": 275 | s = "-.inf" 276 | case "NaN": 277 | s = ".nan" 278 | } 279 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 280 | } 281 | 282 | func (e *encoder) nilv() { 283 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 284 | } 285 | 286 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 287 | implicit := tag == "" 288 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 289 | e.emit() 290 | } 291 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strconv" 7 | "strings" 8 | "time" 9 | 10 | . "gopkg.in/check.v1" 11 | "github.com/stevenjack/cig/Godeps/_workspace/src/gopkg.in/yaml.v2" 12 | "net" 13 | ) 14 | 15 | var marshalIntTest = 123 16 | 17 | var marshalTests = []struct { 18 | value interface{} 19 | data string 20 | }{ 21 | { 22 | nil, 23 | "null\n", 24 | }, { 25 | &struct{}{}, 26 | "{}\n", 27 | }, { 28 | map[string]string{"v": "hi"}, 29 | "v: hi\n", 30 | }, { 31 | map[string]interface{}{"v": "hi"}, 32 | "v: hi\n", 33 | }, { 34 | map[string]string{"v": "true"}, 35 | "v: \"true\"\n", 36 | }, { 37 | map[string]string{"v": "false"}, 38 | "v: \"false\"\n", 39 | }, { 40 | map[string]interface{}{"v": true}, 41 | "v: true\n", 42 | }, { 43 | map[string]interface{}{"v": false}, 44 | "v: false\n", 45 | }, { 46 | map[string]interface{}{"v": 10}, 47 | "v: 10\n", 48 | }, { 49 | map[string]interface{}{"v": -10}, 50 | "v: -10\n", 51 | }, { 52 | map[string]uint{"v": 42}, 53 | "v: 42\n", 54 | }, { 55 | map[string]interface{}{"v": int64(4294967296)}, 56 | "v: 4294967296\n", 57 | }, { 58 | map[string]int64{"v": int64(4294967296)}, 59 | "v: 4294967296\n", 60 | }, { 61 | map[string]uint64{"v": 4294967296}, 62 | "v: 4294967296\n", 63 | }, { 64 | map[string]interface{}{"v": "10"}, 65 | "v: \"10\"\n", 66 | }, { 67 | map[string]interface{}{"v": 0.1}, 68 | "v: 0.1\n", 69 | }, { 70 | map[string]interface{}{"v": float64(0.1)}, 71 | "v: 0.1\n", 72 | }, { 73 | map[string]interface{}{"v": -0.1}, 74 | "v: -0.1\n", 75 | }, { 76 | map[string]interface{}{"v": math.Inf(+1)}, 77 | "v: .inf\n", 78 | }, { 79 | map[string]interface{}{"v": math.Inf(-1)}, 80 | "v: -.inf\n", 81 | }, { 82 | map[string]interface{}{"v": math.NaN()}, 83 | "v: .nan\n", 84 | }, { 85 | map[string]interface{}{"v": nil}, 86 | "v: null\n", 87 | }, { 88 | map[string]interface{}{"v": ""}, 89 | "v: \"\"\n", 90 | }, { 91 | map[string][]string{"v": []string{"A", "B"}}, 92 | "v:\n- A\n- B\n", 93 | }, { 94 | map[string][]string{"v": []string{"A", "B\nC"}}, 95 | "v:\n- A\n- |-\n B\n C\n", 96 | }, { 97 | map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, 98 | "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", 99 | }, { 100 | map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 101 | "a:\n b: c\n", 102 | }, { 103 | map[string]interface{}{"a": "-"}, 104 | "a: '-'\n", 105 | }, 106 | 107 | // Simple values. 108 | { 109 | &marshalIntTest, 110 | "123\n", 111 | }, 112 | 113 | // Structures 114 | { 115 | &struct{ Hello string }{"world"}, 116 | "hello: world\n", 117 | }, { 118 | &struct { 119 | A struct { 120 | B string 121 | } 122 | }{struct{ B string }{"c"}}, 123 | "a:\n b: c\n", 124 | }, { 125 | &struct { 126 | A *struct { 127 | B string 128 | } 129 | }{&struct{ B string }{"c"}}, 130 | "a:\n b: c\n", 131 | }, { 132 | &struct { 133 | A *struct { 134 | B string 135 | } 136 | }{}, 137 | "a: null\n", 138 | }, { 139 | &struct{ A int }{1}, 140 | "a: 1\n", 141 | }, { 142 | &struct{ A []int }{[]int{1, 2}}, 143 | "a:\n- 1\n- 2\n", 144 | }, { 145 | &struct { 146 | B int "a" 147 | }{1}, 148 | "a: 1\n", 149 | }, { 150 | &struct{ A bool }{true}, 151 | "a: true\n", 152 | }, 153 | 154 | // Conditional flag 155 | { 156 | &struct { 157 | A int "a,omitempty" 158 | B int "b,omitempty" 159 | }{1, 0}, 160 | "a: 1\n", 161 | }, { 162 | &struct { 163 | A int "a,omitempty" 164 | B int "b,omitempty" 165 | }{0, 0}, 166 | "{}\n", 167 | }, { 168 | &struct { 169 | A *struct{ X int } "a,omitempty" 170 | B int "b,omitempty" 171 | }{nil, 0}, 172 | "{}\n", 173 | }, 174 | 175 | // Flow flag 176 | { 177 | &struct { 178 | A []int "a,flow" 179 | }{[]int{1, 2}}, 180 | "a: [1, 2]\n", 181 | }, { 182 | &struct { 183 | A map[string]string "a,flow" 184 | }{map[string]string{"b": "c", "d": "e"}}, 185 | "a: {b: c, d: e}\n", 186 | }, { 187 | &struct { 188 | A struct { 189 | B, D string 190 | } "a,flow" 191 | }{struct{ B, D string }{"c", "e"}}, 192 | "a: {b: c, d: e}\n", 193 | }, 194 | 195 | // Unexported field 196 | { 197 | &struct { 198 | u int 199 | A int 200 | }{0, 1}, 201 | "a: 1\n", 202 | }, 203 | 204 | // Ignored field 205 | { 206 | &struct { 207 | A int 208 | B int "-" 209 | }{1, 2}, 210 | "a: 1\n", 211 | }, 212 | 213 | // Struct inlining 214 | { 215 | &struct { 216 | A int 217 | C inlineB `yaml:",inline"` 218 | }{1, inlineB{2, inlineC{3}}}, 219 | "a: 1\nb: 2\nc: 3\n", 220 | }, 221 | 222 | // Duration 223 | { 224 | map[string]time.Duration{"a": 3 * time.Second}, 225 | "a: 3s\n", 226 | }, 227 | 228 | // Issue #24: bug in map merging logic. 229 | { 230 | map[string]string{"a": ""}, 231 | "a: \n", 232 | }, 233 | 234 | // Issue #34: marshal unsupported base 60 floats quoted for compatibility 235 | // with old YAML 1.1 parsers. 236 | { 237 | map[string]string{"a": "1:1"}, 238 | "a: \"1:1\"\n", 239 | }, 240 | 241 | // Binary data. 242 | { 243 | map[string]string{"a": "\x00"}, 244 | "a: \"\\0\"\n", 245 | }, { 246 | map[string]string{"a": "\x80\x81\x82"}, 247 | "a: !!binary gIGC\n", 248 | }, { 249 | map[string]string{"a": strings.Repeat("\x90", 54)}, 250 | "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 251 | }, 252 | 253 | // Ordered maps. 254 | { 255 | &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 256 | "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", 257 | }, 258 | 259 | // Encode unicode as utf-8 rather than in escaped form. 260 | { 261 | map[string]string{"a": "你好"}, 262 | "a: 你好\n", 263 | }, 264 | 265 | // Support encoding.TextMarshaler. 266 | { 267 | map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, 268 | "a: 1.2.3.4\n", 269 | }, 270 | } 271 | 272 | func (s *S) TestMarshal(c *C) { 273 | for _, item := range marshalTests { 274 | data, err := yaml.Marshal(item.value) 275 | c.Assert(err, IsNil) 276 | c.Assert(string(data), Equals, item.data) 277 | } 278 | } 279 | 280 | var marshalErrorTests = []struct { 281 | value interface{} 282 | error string 283 | panic string 284 | }{{ 285 | value: &struct { 286 | B int 287 | inlineB ",inline" 288 | }{1, inlineB{2, inlineC{3}}}, 289 | panic: `Duplicated key 'b' in struct struct \{ B int; .*`, 290 | }} 291 | 292 | func (s *S) TestMarshalErrors(c *C) { 293 | for _, item := range marshalErrorTests { 294 | if item.panic != "" { 295 | c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) 296 | } else { 297 | _, err := yaml.Marshal(item.value) 298 | c.Assert(err, ErrorMatches, item.error) 299 | } 300 | } 301 | } 302 | 303 | func (s *S) TestMarshalTypeCache(c *C) { 304 | var data []byte 305 | var err error 306 | func() { 307 | type T struct{ A int } 308 | data, err = yaml.Marshal(&T{}) 309 | c.Assert(err, IsNil) 310 | }() 311 | func() { 312 | type T struct{ B int } 313 | data, err = yaml.Marshal(&T{}) 314 | c.Assert(err, IsNil) 315 | }() 316 | c.Assert(string(data), Equals, "b: 0\n") 317 | } 318 | 319 | var marshalerTests = []struct { 320 | data string 321 | value interface{} 322 | }{ 323 | {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, 324 | {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, 325 | {"_: 10\n", 10}, 326 | {"_: null\n", nil}, 327 | {"_: BAR!\n", "BAR!"}, 328 | } 329 | 330 | type marshalerType struct { 331 | value interface{} 332 | } 333 | 334 | func (o marshalerType) MarshalYAML() (interface{}, error) { 335 | return o.value, nil 336 | } 337 | 338 | type marshalerValue struct { 339 | Field marshalerType "_" 340 | } 341 | 342 | func (s *S) TestMarshaler(c *C) { 343 | for _, item := range marshalerTests { 344 | obj := &marshalerValue{} 345 | obj.Field.value = item.value 346 | data, err := yaml.Marshal(obj) 347 | c.Assert(err, IsNil) 348 | c.Assert(string(data), Equals, string(item.data)) 349 | } 350 | } 351 | 352 | func (s *S) TestMarshalerWholeDocument(c *C) { 353 | obj := &marshalerType{} 354 | obj.value = map[string]string{"hello": "world!"} 355 | data, err := yaml.Marshal(obj) 356 | c.Assert(err, IsNil) 357 | c.Assert(string(data), Equals, "hello: world!\n") 358 | } 359 | 360 | type failingMarshaler struct{} 361 | 362 | func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { 363 | return nil, failingErr 364 | } 365 | 366 | func (s *S) TestMarshalerError(c *C) { 367 | _, err := yaml.Marshal(&failingMarshaler{}) 368 | c.Assert(err, Equals, failingErr) 369 | } 370 | 371 | func (s *S) TestSortedOutput(c *C) { 372 | order := []interface{}{ 373 | false, 374 | true, 375 | 1, 376 | uint(1), 377 | 1.0, 378 | 1.1, 379 | 1.2, 380 | 2, 381 | uint(2), 382 | 2.0, 383 | 2.1, 384 | "", 385 | ".1", 386 | ".2", 387 | ".a", 388 | "1", 389 | "2", 390 | "a!10", 391 | "a/2", 392 | "a/10", 393 | "a~10", 394 | "ab/1", 395 | "b/1", 396 | "b/01", 397 | "b/2", 398 | "b/02", 399 | "b/3", 400 | "b/03", 401 | "b1", 402 | "b01", 403 | "b3", 404 | "c2.10", 405 | "c10.2", 406 | "d1", 407 | "d12", 408 | "d12a", 409 | } 410 | m := make(map[interface{}]int) 411 | for _, k := range order { 412 | m[k] = 1 413 | } 414 | data, err := yaml.Marshal(m) 415 | c.Assert(err, IsNil) 416 | out := "\n" + string(data) 417 | last := 0 418 | for i, k := range order { 419 | repr := fmt.Sprint(k) 420 | if s, ok := k.(string); ok { 421 | if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { 422 | repr = `"` + repr + `"` 423 | } 424 | } 425 | index := strings.Index(out, "\n"+repr+":") 426 | if index == -1 { 427 | c.Fatalf("%#v is not in the output: %#v", k, out) 428 | } 429 | if index < last { 430 | c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) 431 | } 432 | last = index 433 | } 434 | } 435 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "math" 6 | "strconv" 7 | "strings" 8 | "unicode/utf8" 9 | ) 10 | 11 | type resolveMapItem struct { 12 | value interface{} 13 | tag string 14 | } 15 | 16 | var resolveTable = make([]byte, 256) 17 | var resolveMap = make(map[string]resolveMapItem) 18 | 19 | func init() { 20 | t := resolveTable 21 | t[int('+')] = 'S' // Sign 22 | t[int('-')] = 'S' 23 | for _, c := range "0123456789" { 24 | t[int(c)] = 'D' // Digit 25 | } 26 | for _, c := range "yYnNtTfFoO~" { 27 | t[int(c)] = 'M' // In map 28 | } 29 | t[int('.')] = '.' // Float (potentially in map) 30 | 31 | var resolveMapList = []struct { 32 | v interface{} 33 | tag string 34 | l []string 35 | }{ 36 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 37 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 38 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 39 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 40 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 41 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 42 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 43 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 44 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 46 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 47 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 48 | } 49 | 50 | m := resolveMap 51 | for _, item := range resolveMapList { 52 | for _, s := range item.l { 53 | m[s] = resolveMapItem{item.v, item.tag} 54 | } 55 | } 56 | } 57 | 58 | const longTagPrefix = "tag:yaml.org,2002:" 59 | 60 | func shortTag(tag string) string { 61 | // TODO This can easily be made faster and produce less garbage. 62 | if strings.HasPrefix(tag, longTagPrefix) { 63 | return "!!" + tag[len(longTagPrefix):] 64 | } 65 | return tag 66 | } 67 | 68 | func longTag(tag string) string { 69 | if strings.HasPrefix(tag, "!!") { 70 | return longTagPrefix + tag[2:] 71 | } 72 | return tag 73 | } 74 | 75 | func resolvableTag(tag string) bool { 76 | switch tag { 77 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: 78 | return true 79 | } 80 | return false 81 | } 82 | 83 | func resolve(tag string, in string) (rtag string, out interface{}) { 84 | if !resolvableTag(tag) { 85 | return tag, in 86 | } 87 | 88 | defer func() { 89 | switch tag { 90 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 91 | return 92 | } 93 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 94 | }() 95 | 96 | // Any data is accepted as a !!str or !!binary. 97 | // Otherwise, the prefix is enough of a hint about what it might be. 98 | hint := byte('N') 99 | if in != "" { 100 | hint = resolveTable[in[0]] 101 | } 102 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 103 | // Handle things we can lookup in a map. 104 | if item, ok := resolveMap[in]; ok { 105 | return item.tag, item.value 106 | } 107 | 108 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 109 | // are purposefully unsupported here. They're still quoted on 110 | // the way out for compatibility with other parser, though. 111 | 112 | switch hint { 113 | case 'M': 114 | // We've already checked the map above. 115 | 116 | case '.': 117 | // Not in the map, so maybe a normal float. 118 | floatv, err := strconv.ParseFloat(in, 64) 119 | if err == nil { 120 | return yaml_FLOAT_TAG, floatv 121 | } 122 | 123 | case 'D', 'S': 124 | // Int, float, or timestamp. 125 | plain := strings.Replace(in, "_", "", -1) 126 | intv, err := strconv.ParseInt(plain, 0, 64) 127 | if err == nil { 128 | if intv == int64(int(intv)) { 129 | return yaml_INT_TAG, int(intv) 130 | } else { 131 | return yaml_INT_TAG, intv 132 | } 133 | } 134 | uintv, err := strconv.ParseUint(plain, 0, 64) 135 | if err == nil { 136 | return yaml_INT_TAG, uintv 137 | } 138 | floatv, err := strconv.ParseFloat(plain, 64) 139 | if err == nil { 140 | return yaml_FLOAT_TAG, floatv 141 | } 142 | if strings.HasPrefix(plain, "0b") { 143 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 144 | if err == nil { 145 | if intv == int64(int(intv)) { 146 | return yaml_INT_TAG, int(intv) 147 | } else { 148 | return yaml_INT_TAG, intv 149 | } 150 | } 151 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 152 | if err == nil { 153 | return yaml_INT_TAG, uintv 154 | } 155 | } else if strings.HasPrefix(plain, "-0b") { 156 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 157 | if err == nil { 158 | if intv == int64(int(intv)) { 159 | return yaml_INT_TAG, -int(intv) 160 | } else { 161 | return yaml_INT_TAG, -intv 162 | } 163 | } 164 | } 165 | // XXX Handle timestamps here. 166 | 167 | default: 168 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 169 | } 170 | } 171 | if tag == yaml_BINARY_TAG { 172 | return yaml_BINARY_TAG, in 173 | } 174 | if utf8.ValidString(in) { 175 | return yaml_STR_TAG, in 176 | } 177 | return yaml_BINARY_TAG, encodeBase64(in) 178 | } 179 | 180 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 181 | // as appropriate for the resulting length. 182 | func encodeBase64(s string) string { 183 | const lineLen = 70 184 | encLen := base64.StdEncoding.EncodedLen(len(s)) 185 | lines := encLen/lineLen + 1 186 | buf := make([]byte, encLen*2+lines) 187 | in := buf[0:encLen] 188 | out := buf[encLen:] 189 | base64.StdEncoding.Encode(in, []byte(s)) 190 | k := 0 191 | for i := 0; i < len(in); i += lineLen { 192 | j := i + lineLen 193 | if j > len(in) { 194 | j = len(in) 195 | } 196 | k += copy(out[k:], in[i:j]) 197 | if lines > 1 { 198 | out[k] = '\n' 199 | k++ 200 | } 201 | } 202 | return string(out[:k]) 203 | } 204 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 55 | an = an*10 + int64(ar[ai]-'0') 56 | } 57 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 58 | bn = bn*10 + int64(br[bi]-'0') 59 | } 60 | if an != bn { 61 | return an < bn 62 | } 63 | if ai != bi { 64 | return ai < bi 65 | } 66 | return ar[i] < br[i] 67 | } 68 | return len(ar) < len(br) 69 | } 70 | 71 | // keyFloat returns a float value for v if it is a number/bool 72 | // and whether it is a number/bool or not. 73 | func keyFloat(v reflect.Value) (f float64, ok bool) { 74 | switch v.Kind() { 75 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 76 | return float64(v.Int()), true 77 | case reflect.Float32, reflect.Float64: 78 | return v.Float(), true 79 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 80 | return float64(v.Uint()), true 81 | case reflect.Bool: 82 | if v.Bool() { 83 | return 1, true 84 | } 85 | return 0, true 86 | } 87 | return 0, false 88 | } 89 | 90 | // numLess returns whether a < b. 91 | // a and b must necessarily have the same kind. 92 | func numLess(a, b reflect.Value) bool { 93 | switch a.Kind() { 94 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 95 | return a.Int() < b.Int() 96 | case reflect.Float32, reflect.Float64: 97 | return a.Float() < b.Float() 98 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 99 | return a.Uint() < b.Uint() 100 | case reflect.Bool: 101 | return !a.Bool() && b.Bool() 102 | } 103 | panic("not a number") 104 | } 105 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { TestingT(t) } 9 | 10 | type S struct{} 11 | 12 | var _ = Suite(&S{}) 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | // If the output encoding is UTF-8, we don't need to recode the buffer. 22 | if emitter.encoding == yaml_UTF8_ENCODING { 23 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 24 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 25 | } 26 | emitter.buffer_pos = 0 27 | return true 28 | } 29 | 30 | // Recode the buffer into the raw buffer. 31 | var low, high int 32 | if emitter.encoding == yaml_UTF16LE_ENCODING { 33 | low, high = 0, 1 34 | } else { 35 | high, low = 1, 0 36 | } 37 | 38 | pos := 0 39 | for pos < emitter.buffer_pos { 40 | // See the "reader.c" code for more details on UTF-8 encoding. Note 41 | // that we assume that the buffer contains a valid UTF-8 sequence. 42 | 43 | // Read the next UTF-8 character. 44 | octet := emitter.buffer[pos] 45 | 46 | var w int 47 | var value rune 48 | switch { 49 | case octet&0x80 == 0x00: 50 | w, value = 1, rune(octet&0x7F) 51 | case octet&0xE0 == 0xC0: 52 | w, value = 2, rune(octet&0x1F) 53 | case octet&0xF0 == 0xE0: 54 | w, value = 3, rune(octet&0x0F) 55 | case octet&0xF8 == 0xF0: 56 | w, value = 4, rune(octet&0x07) 57 | } 58 | for k := 1; k < w; k++ { 59 | octet = emitter.buffer[pos+k] 60 | value = (value << 6) + (rune(octet) & 0x3F) 61 | } 62 | pos += w 63 | 64 | // Write the character. 65 | if value < 0x10000 { 66 | var b [2]byte 67 | b[high] = byte(value >> 8) 68 | b[low] = byte(value & 0xFF) 69 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) 70 | } else { 71 | // Write the character using a surrogate pair (check "reader.c"). 72 | var b [4]byte 73 | value -= 0x10000 74 | b[high] = byte(0xD8 + (value >> 18)) 75 | b[low] = byte((value >> 10) & 0xFF) 76 | b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) 77 | b[low+2] = byte(value & 0xFF) 78 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) 79 | } 80 | } 81 | 82 | // Write the raw buffer. 83 | if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { 84 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 85 | } 86 | emitter.buffer_pos = 0 87 | emitter.raw_buffer = emitter.raw_buffer[:0] 88 | return true 89 | } 90 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go: -------------------------------------------------------------------------------- 1 | // Package yaml implements YAML support for the Go language. 2 | // 3 | // Source code and other details for the project are available at GitHub: 4 | // 5 | // https://github.com/go-yaml/yaml 6 | // 7 | package yaml 8 | 9 | import ( 10 | "errors" 11 | "fmt" 12 | "reflect" 13 | "strings" 14 | "sync" 15 | ) 16 | 17 | // MapSlice encodes and decodes as a YAML map. 18 | // The order of keys is preserved when encoding and decoding. 19 | type MapSlice []MapItem 20 | 21 | // MapItem is an item in a MapSlice. 22 | type MapItem struct { 23 | Key, Value interface{} 24 | } 25 | 26 | // The Unmarshaler interface may be implemented by types to customize their 27 | // behavior when being unmarshaled from a YAML document. The UnmarshalYAML 28 | // method receives a function that may be called to unmarshal the original 29 | // YAML value into a field or variable. It is safe to call the unmarshal 30 | // function parameter more than once if necessary. 31 | type Unmarshaler interface { 32 | UnmarshalYAML(unmarshal func(interface{}) error) error 33 | } 34 | 35 | 36 | // The Marshaler interface may be implemented by types to customize their 37 | // behavior when being marshaled into a YAML document. The returned value 38 | // is marshaled in place of the original value implementing Marshaler. 39 | // 40 | // If an error is returned by MarshalYAML, the marshaling procedure stops 41 | // and returns with the provided error. 42 | type Marshaler interface { 43 | MarshalYAML() (interface{}, error) 44 | } 45 | 46 | // Unmarshal decodes the first document found within the in byte slice 47 | // and assigns decoded values into the out value. 48 | // 49 | // Maps and pointers (to a struct, string, int, etc) are accepted as out 50 | // values. If an internal pointer within a struct is not initialized, 51 | // the yaml package will initialize it if necessary for unmarshalling 52 | // the provided data. The out parameter must not be nil. 53 | // 54 | // The type of the decoded values should be compatible with the respective 55 | // values in out. If one or more values cannot be decoded due to a type 56 | // mismatches, decoding continues partially until the end of the YAML 57 | // content, and a *yaml.TypeError is returned with details for all 58 | // missed values. 59 | // 60 | // Struct fields are only unmarshalled if they are exported (have an 61 | // upper case first letter), and are unmarshalled using the field name 62 | // lowercased as the default key. Custom keys may be defined via the 63 | // "yaml" name in the field tag: the content preceding the first comma 64 | // is used as the key, and the following comma-separated options are 65 | // used to tweak the marshalling process (see Marshal). 66 | // Conflicting names result in a runtime error. 67 | // 68 | // For example: 69 | // 70 | // type T struct { 71 | // F int `yaml:"a,omitempty"` 72 | // B int 73 | // } 74 | // var t T 75 | // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) 76 | // 77 | // See the documentation of Marshal for the format of tags and a list of 78 | // supported tag options. 79 | // 80 | func Unmarshal(in []byte, out interface{}) (err error) { 81 | defer handleErr(&err) 82 | d := newDecoder() 83 | p := newParser(in) 84 | defer p.destroy() 85 | node := p.parse() 86 | if node != nil { 87 | v := reflect.ValueOf(out) 88 | if v.Kind() == reflect.Ptr && !v.IsNil() { 89 | v = v.Elem() 90 | } 91 | d.unmarshal(node, v) 92 | } 93 | if d.terrors != nil { 94 | return &TypeError{d.terrors} 95 | } 96 | return nil 97 | } 98 | 99 | // Marshal serializes the value provided into a YAML document. The structure 100 | // of the generated document will reflect the structure of the value itself. 101 | // Maps and pointers (to struct, string, int, etc) are accepted as the in value. 102 | // 103 | // Struct fields are only unmarshalled if they are exported (have an upper case 104 | // first letter), and are unmarshalled using the field name lowercased as the 105 | // default key. Custom keys may be defined via the "yaml" name in the field 106 | // tag: the content preceding the first comma is used as the key, and the 107 | // following comma-separated options are used to tweak the marshalling process. 108 | // Conflicting names result in a runtime error. 109 | // 110 | // The field tag format accepted is: 111 | // 112 | // `(...) yaml:"[][,[,]]" (...)` 113 | // 114 | // The following flags are currently supported: 115 | // 116 | // omitempty Only include the field if it's not set to the zero 117 | // value for the type or to empty slices or maps. 118 | // Does not apply to zero valued structs. 119 | // 120 | // flow Marshal using a flow style (useful for structs, 121 | // sequences and maps. 122 | // 123 | // inline Inline the struct it's applied to, so its fields 124 | // are processed as if they were part of the outer 125 | // struct. 126 | // 127 | // In addition, if the key is "-", the field is ignored. 128 | // 129 | // For example: 130 | // 131 | // type T struct { 132 | // F int "a,omitempty" 133 | // B int 134 | // } 135 | // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" 136 | // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" 137 | // 138 | func Marshal(in interface{}) (out []byte, err error) { 139 | defer handleErr(&err) 140 | e := newEncoder() 141 | defer e.destroy() 142 | e.marshal("", reflect.ValueOf(in)) 143 | e.finish() 144 | out = e.out 145 | return 146 | } 147 | 148 | func handleErr(err *error) { 149 | if v := recover(); v != nil { 150 | if e, ok := v.(yamlError); ok { 151 | *err = e.err 152 | } else { 153 | panic(v) 154 | } 155 | } 156 | } 157 | 158 | type yamlError struct { 159 | err error 160 | } 161 | 162 | func fail(err error) { 163 | panic(yamlError{err}) 164 | } 165 | 166 | func failf(format string, args ...interface{}) { 167 | panic(yamlError{fmt.Errorf("yaml: " + format, args...)}) 168 | } 169 | 170 | // A TypeError is returned by Unmarshal when one or more fields in 171 | // the YAML document cannot be properly decoded into the requested 172 | // types. When this error is returned, the value is still 173 | // unmarshaled partially. 174 | type TypeError struct { 175 | Errors []string 176 | } 177 | 178 | func (e *TypeError) Error() string { 179 | return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) 180 | } 181 | 182 | // -------------------------------------------------------------------------- 183 | // Maintain a mapping of keys to structure field indexes 184 | 185 | // The code in this section was copied from mgo/bson. 186 | 187 | // structInfo holds details for the serialization of fields of 188 | // a given struct. 189 | type structInfo struct { 190 | FieldsMap map[string]fieldInfo 191 | FieldsList []fieldInfo 192 | 193 | // InlineMap is the number of the field in the struct that 194 | // contains an ,inline map, or -1 if there's none. 195 | InlineMap int 196 | } 197 | 198 | type fieldInfo struct { 199 | Key string 200 | Num int 201 | OmitEmpty bool 202 | Flow bool 203 | 204 | // Inline holds the field index if the field is part of an inlined struct. 205 | Inline []int 206 | } 207 | 208 | var structMap = make(map[reflect.Type]*structInfo) 209 | var fieldMapMutex sync.RWMutex 210 | 211 | func getStructInfo(st reflect.Type) (*structInfo, error) { 212 | fieldMapMutex.RLock() 213 | sinfo, found := structMap[st] 214 | fieldMapMutex.RUnlock() 215 | if found { 216 | return sinfo, nil 217 | } 218 | 219 | n := st.NumField() 220 | fieldsMap := make(map[string]fieldInfo) 221 | fieldsList := make([]fieldInfo, 0, n) 222 | inlineMap := -1 223 | for i := 0; i != n; i++ { 224 | field := st.Field(i) 225 | if field.PkgPath != "" { 226 | continue // Private field 227 | } 228 | 229 | info := fieldInfo{Num: i} 230 | 231 | tag := field.Tag.Get("yaml") 232 | if tag == "" && strings.Index(string(field.Tag), ":") < 0 { 233 | tag = string(field.Tag) 234 | } 235 | if tag == "-" { 236 | continue 237 | } 238 | 239 | inline := false 240 | fields := strings.Split(tag, ",") 241 | if len(fields) > 1 { 242 | for _, flag := range fields[1:] { 243 | switch flag { 244 | case "omitempty": 245 | info.OmitEmpty = true 246 | case "flow": 247 | info.Flow = true 248 | case "inline": 249 | inline = true 250 | default: 251 | return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) 252 | } 253 | } 254 | tag = fields[0] 255 | } 256 | 257 | if inline { 258 | switch field.Type.Kind() { 259 | // TODO: Implement support for inline maps. 260 | //case reflect.Map: 261 | // if inlineMap >= 0 { 262 | // return nil, errors.New("Multiple ,inline maps in struct " + st.String()) 263 | // } 264 | // if field.Type.Key() != reflect.TypeOf("") { 265 | // return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) 266 | // } 267 | // inlineMap = info.Num 268 | case reflect.Struct: 269 | sinfo, err := getStructInfo(field.Type) 270 | if err != nil { 271 | return nil, err 272 | } 273 | for _, finfo := range sinfo.FieldsList { 274 | if _, found := fieldsMap[finfo.Key]; found { 275 | msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() 276 | return nil, errors.New(msg) 277 | } 278 | if finfo.Inline == nil { 279 | finfo.Inline = []int{i, finfo.Num} 280 | } else { 281 | finfo.Inline = append([]int{i}, finfo.Inline...) 282 | } 283 | fieldsMap[finfo.Key] = finfo 284 | fieldsList = append(fieldsList, finfo) 285 | } 286 | default: 287 | //return nil, errors.New("Option ,inline needs a struct value or map field") 288 | return nil, errors.New("Option ,inline needs a struct value field") 289 | } 290 | continue 291 | } 292 | 293 | if tag != "" { 294 | info.Key = tag 295 | } else { 296 | info.Key = strings.ToLower(field.Name) 297 | } 298 | 299 | if _, found = fieldsMap[info.Key]; found { 300 | msg := "Duplicated key '" + info.Key + "' in struct " + st.String() 301 | return nil, errors.New(msg) 302 | } 303 | 304 | fieldsList = append(fieldsList, info) 305 | fieldsMap[info.Key] = info 306 | } 307 | 308 | sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} 309 | 310 | fieldMapMutex.Lock() 311 | structMap[st] = sinfo 312 | fieldMapMutex.Unlock() 313 | return sinfo, nil 314 | } 315 | 316 | func isZero(v reflect.Value) bool { 317 | switch v.Kind() { 318 | case reflect.String: 319 | return len(v.String()) == 0 320 | case reflect.Interface, reflect.Ptr: 321 | return v.IsNil() 322 | case reflect.Slice: 323 | return v.Len() == 0 324 | case reflect.Map: 325 | return v.Len() == 0 326 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 327 | return v.Int() == 0 328 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 329 | return v.Uint() == 0 330 | case reflect.Bool: 331 | return !v.Bool() 332 | } 333 | return false 334 | } 335 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Steven Jack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERISON ?= "" 2 | TYPE ?= "" 3 | 4 | PHONY: bump run build 5 | SILENT: bump run build 6 | 7 | current_version: 8 | $(eval CURRENT_VERSION:=$(shell cat VERSION)) 9 | 10 | update_files: current_version 11 | echo "=> Bumping release to v${VERSION}" 12 | for file in "cig.go" "README.md" "install.sh" "VERSION" ; do \ 13 | sed -i '' "s/${CURRENT_VERSION}/${VERSION}/g" $$file; \ 14 | done 15 | 16 | tag: 17 | echo "=> Tagging latest release" 18 | git tag v${VERSION} 19 | 20 | commit: 21 | echo "=> Commiting version bump" 22 | git add cig.go README.md install.sh VERSION 23 | git commit -m "${TYPE} release ${VERSION}" 24 | 25 | push: 26 | echo "=> pushing changes up" 27 | git push origin master 28 | git push origin --tags 29 | 30 | bump: update_files commit tag 31 | 32 | run: 33 | docker-compose run dev 34 | 35 | build: 36 | docker-compose run build 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

cig

2 | 3 |

4 | 5 | 6 | 7 | 8 |

9 | 10 |

11 | Can I go? CLI app for checking the state of your git repositories. 12 |

13 | 14 | ![cig](https://cloud.githubusercontent.com/assets/527874/7220202/faaedf0c-e6b6-11e4-9cb8-bf62295f4128.png) 15 | 16 | ### Installation 17 | 18 | To install cig, follow the instructions for your OS below: 19 | 20 | #### GO 21 | 22 | If you have [go](http://golang.org/) installed and the bin folder added to your path, just run: 23 | 24 | ```bash 25 | $: go get github.com/stevenjack/cig 26 | ``` 27 | 28 | #### OSX 29 | 30 | Make sure you have [homebrew](https://www.github.com/homebrew/homebrew) installed, then run the 31 | following: 32 | 33 | `$: brew install cig` 34 | 35 | > Alternatively you can follow the install instructions for `Linux` below if you don't have or 36 | want to install homebrew. 37 | 38 | #### Linux 39 | 40 | ##### One line install 41 | 42 | ```bash 43 | curl -L https://bit.ly/cig-install | sudo bash 44 | ``` 45 | 46 | > Note: this command downloads the binary and changes the execute permission on it 47 | 48 | ##### Manual install 49 | 50 | ```bash 51 | curl -L https://github.com/stevenjack/cig/releases/download/v0.1.5/cig_`uname -s`_x86_64 > /usr/local/bin/cig 52 | chmod +x /usr/local/bin/cig 53 | ``` 54 | 55 | ### Windows 56 | 57 | Download the following binary: 58 | 59 | * [64bit](https://github.com/stevenjack/cig/releases/download/v0.1.5/cig_windows_x86_64.exe) 60 | 61 | Once you have the binary, run it via your cmd prompt: 62 | 63 | ``` 64 | C: cig_windows_amd64.exe 65 | ``` 66 | 67 | ### Setup 68 | 69 | Create a `.cig.yaml` configuration file within your home directory: 70 | 71 | #### Linux 72 | 73 | > ~/.cig.yaml 74 | 75 | ```yaml 76 | work: /path/to/work/repos 77 | personal: /path/to/personal/repos 78 | ``` 79 | 80 | #### Windows 81 | 82 | > ~/Users/Steven Jack/.cig.yaml 83 | 84 | ```yaml 85 | work: C:\path\to\work\repos 86 | personal: C:\path\to\personal\repos 87 | ``` 88 | 89 | The configuration file defines the different folder locations that contain the `.git` repos you want cig to check for you. 90 | 91 | ### Usage 92 | 93 | Simply run: 94 | 95 | `$: cig` 96 | 97 | Once executed, cig will check all your repos and the following information will be displayed: 98 | 99 | * Repos that need pushing up to the origin: `P` 100 | * Repos that have new, unstaged and staged changes: `M(10)` 101 | 102 | > Note: the values will soon be replaced with something similar to: 103 | > `(S)taged, (M)odified, (N)ew` 104 | > Please see the [issues page](https://github.com/stevenjack/cig/issues) for full details 105 | 106 | #### Filters 107 | 108 | If you just want to check your 'work' repos for changes: 109 | 110 | `$: cig -t work` 111 | 112 | To filter them based on a certain string such as 'steve': 113 | 114 | `$: cig -f steve` 115 | 116 | You can also combine them, so to only show 'work' repos with 'steve' 117 | in the path: 118 | 119 | `$: cig -t work -f steve` 120 | 121 | ### TODO 122 | 123 | Please see [issues](https://www.github.com/stevenjack/cig/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3ATODO) 124 | 125 | ### Contributing 126 | 127 | 1. Fork it ( http://github.com/stevenjack/cig/fork ) 128 | 2. Create your feature branch (`git checkout -b my-new-feature`) 129 | 3. Commit your changes (`git commit -am 'Add some feature'`) 130 | 4. Push to the branch (`git push origin my-new-feature`) 131 | 5. Create new Pull Request 132 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.5 2 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "regexp" 8 | "strings" 9 | "sync" 10 | 11 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/mitchellh/go-homedir" 12 | "github.com/stevenjack/cig/output" 13 | "github.com/stevenjack/cig/repo" 14 | ) 15 | 16 | func Handle(repoList map[string]string, projectTypeToCheck string, filter string, outputChannel chan output.Payload) { 17 | var wg sync.WaitGroup 18 | 19 | for projectType, path := range repoList { 20 | if projectTypeToCheck == "" || projectTypeToCheck == projectType { 21 | outputChannel <- output.Print(fmt.Sprintf("\nChecking '%s' (%s) repos...", projectType, path)) 22 | path = resolvePath(path) 23 | 24 | visit := func(visitedPath string, info os.FileInfo, err error) error { 25 | if err != nil { 26 | outputChannel <- output.Error(fmt.Sprintf("- %s", err.Error())) 27 | return nil 28 | } 29 | matched, _ := regexp.MatchString(filter, visitedPath) 30 | if info.IsDir() && (filter == "" || matched) { 31 | wg.Add(1) 32 | go repo.Check(path, visitedPath, outputChannel, &wg) 33 | } 34 | return nil 35 | } 36 | 37 | err := filepath.Walk(path, visit) 38 | if err != nil { 39 | outputChannel <- output.Error(err.Error()) 40 | } 41 | } 42 | 43 | wg.Wait() 44 | } 45 | wg.Wait() 46 | } 47 | 48 | func resolvePath(path string) string { 49 | hasTilde := strings.HasPrefix(path, "~") 50 | if hasTilde { 51 | homeDir, err := homedir.Dir() 52 | if err == nil { 53 | return strings.Replace(path, "~", homeDir, -1) 54 | } 55 | } 56 | return path 57 | } 58 | -------------------------------------------------------------------------------- /app/config.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | "path/filepath" 8 | 9 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/mitchellh/go-homedir" 10 | "github.com/stevenjack/cig/Godeps/_workspace/src/gopkg.in/yaml.v2" 11 | ) 12 | 13 | func Config(configPath string) (map[string]string, error) { 14 | repoList := make(map[string]string) 15 | homeDir, err := homedir.Dir() 16 | 17 | if configPath != "" { 18 | homeDir = configPath 19 | } 20 | 21 | if err != nil { 22 | return nil, errors.New("Couldn't determine home directory") 23 | } 24 | 25 | path := filepath.Join(homeDir, ".cig.yaml") 26 | data, err := ioutil.ReadFile(path) 27 | 28 | if err != nil { 29 | return nil, errors.New(fmt.Sprintf("Can't find config '%s'", path)) 30 | } 31 | 32 | err = yaml.Unmarshal([]byte(data), &repoList) 33 | 34 | if err != nil { 35 | return nil, errors.New(fmt.Sprintf("Problem parsing '%s', please check documentation", path)) 36 | } 37 | 38 | return repoList, nil 39 | } 40 | -------------------------------------------------------------------------------- /app/config_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | 9 | "github.com/stevenjack/cig/app" 10 | ) 11 | 12 | func TestMapReturnedFromCigYaml(t *testing.T) { 13 | repoList, err := config("valid") 14 | 15 | if err != nil { 16 | t.Error(fmt.Sprintf("return of app.Config should be of type 'map[string]string, got: %s", repoList)) 17 | } 18 | } 19 | 20 | func TestErrorRaisedWhenConfigDoesNotExist(t *testing.T) { 21 | _, err := config("cig_doesnt_exist_path") 22 | 23 | if err == nil { 24 | t.Error("app.Config should raise error with invalid path") 25 | } 26 | } 27 | 28 | func TestMalformedYamlRasiesError(t *testing.T) { 29 | _, err := config("invalid") 30 | 31 | if err == nil { 32 | t.Error("app.Config should raise error with invalid yaml") 33 | } 34 | } 35 | 36 | func config(config_path string) (map[string]string, error) { 37 | cwd, _ := os.Getwd() 38 | path := filepath.Join(cwd, "..", "test", "fixtures", config_path) 39 | return app.Config(path) 40 | } 41 | -------------------------------------------------------------------------------- /build/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | go test */**_test.go 4 | 5 | if [[ $TRAVIS_TAG =~ ^v[0-9\.]+ ]]; then 6 | go get github.com/mitchellh/gox 7 | gox -os="darwin linux windows" -arch="amd64" -build-toolchain 8 | gox -os="darwin linux windows" -arch="amd64" -output="{{.Dir}}_{{.OS}}_x86_64" 9 | fi 10 | -------------------------------------------------------------------------------- /cig.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/codegangsta/cli" 7 | "github.com/stevenjack/cig/app" 8 | "github.com/stevenjack/cig/output" 9 | ) 10 | 11 | const version string = "0.1.5" 12 | 13 | func main() { 14 | var outputChannel = make(chan output.Payload) 15 | 16 | go output.Wait(outputChannel) 17 | cliWrapper := mainApp() 18 | 19 | cliWrapper.Action = func(context *cli.Context) { 20 | configPath := context.String("config-path") 21 | projectType := context.String("type") 22 | filter := context.String("filter") 23 | repoList, err := app.Config(configPath) 24 | 25 | if err != nil { 26 | outputChannel <- output.FatalError(err.Error()) 27 | } 28 | 29 | app.Handle(repoList, projectType, filter, outputChannel) 30 | } 31 | 32 | cliWrapper.Run(os.Args) 33 | } 34 | 35 | func mainApp() *cli.App { 36 | app := cli.NewApp() 37 | app.Name = "cig" 38 | app.Usage = "cig (Can I go?) checks all your git repos to see if they're in the state you want them to be" 39 | app.Version = version 40 | 41 | app.Flags = []cli.Flag{ 42 | cli.StringFlag{ 43 | Name: "filter, f", 44 | Value: "", 45 | Usage: "Filter repos being searched", 46 | }, 47 | cli.StringFlag{ 48 | Name: "type, t", 49 | Value: "", 50 | Usage: "Filter by type", 51 | }, 52 | cli.StringFlag{ 53 | Name: "config-path, cp", 54 | Value: "", 55 | Usage: "Path to the cig config (Default ~/.cig.yaml)", 56 | }, 57 | } 58 | return app 59 | } 60 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | common: &common 2 | build: . 3 | working_dir: /go/src/github.com/stevenjack/cig 4 | 5 | dev: 6 | <<: *common 7 | command: go run cig.go --cp /go/src/github.com/stevenjack/cig 8 | volumes: 9 | - .:/go/src/github.com/stevenjack/cig 10 | - ~/Projects:/projects 11 | 12 | build: 13 | <<: *common 14 | command: gox 15 | volumes: 16 | - .:/go/src/github.com/stevenjack/cig 17 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -L https://github.com/stevenjack/cig/releases/download/v0.1.5/cig_`uname -s`_x86_64 > /usr/local/bin/cig 4 | chmod +x /usr/local/bin/cig 5 | -------------------------------------------------------------------------------- /output/output.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "runtime" 7 | 8 | "github.com/stevenjack/cig/Godeps/_workspace/src/github.com/fatih/color" 9 | ) 10 | 11 | type Payload struct { 12 | Message string 13 | Error bool 14 | Fatal bool 15 | } 16 | 17 | func (p *Payload) IsError() { 18 | p.Error = true 19 | } 20 | 21 | func (p *Payload) IsFatal() { 22 | p.Fatal = true 23 | } 24 | 25 | func FatalError(message string) Payload { 26 | payload := Error(message) 27 | payload.IsFatal() 28 | return payload 29 | } 30 | 31 | func Error(message string) Payload { 32 | formatted := ApplyColour(message, "red") 33 | payload := Print(formatted) 34 | payload.IsError() 35 | return payload 36 | } 37 | 38 | func Print(message string) Payload { 39 | return Payload{message, false, false} 40 | } 41 | 42 | func ApplyColour(message string, outputType string) string { 43 | if runtime.GOOS != "windows" { 44 | switch outputType { 45 | case "red": 46 | return color.RedString(message) 47 | case "blue": 48 | return color.BlueString(message) 49 | } 50 | 51 | } 52 | return message 53 | } 54 | 55 | func Wait(channel chan Payload) { 56 | for { 57 | entry := <-channel 58 | fmt.Println(entry.Message) 59 | if entry.Fatal { 60 | os.Exit(-1) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /repo/repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "path/filepath" 9 | "strings" 10 | "sync" 11 | 12 | "github.com/stevenjack/cig/output" 13 | ) 14 | 15 | func Check(root string, path string, outputChannel chan output.Payload, wg *sync.WaitGroup) { 16 | defer wg.Done() 17 | exists, err := Exists(filepath.Join(path, ".git")) 18 | 19 | if err != nil { 20 | return 21 | } 22 | 23 | if exists { 24 | modifiedFiles := exec.Command("git", "status", "--porcelain") 25 | modifiedFiles.Dir = path 26 | 27 | countOut, _ := modifiedFiles.Output() 28 | modifiedLines := strings.Split(string(countOut), "\n") 29 | modified := len(modifiedLines) - 1 30 | 31 | if err != nil { 32 | outputChannel <- output.FatalError(err.Error()) 33 | } 34 | 35 | changes := []string{} 36 | 37 | if modified > 0 && modifiedLines[0] != "" { 38 | changes = append(changes, output.ApplyColour(fmt.Sprintf(" M(%d)", modified), "red")) 39 | } 40 | 41 | branch := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") 42 | branch.Dir = path 43 | bstdout, _ := branch.Output() 44 | branchName := strings.TrimSpace(string(bstdout[:])) 45 | 46 | local := exec.Command("git", "rev-parse", branchName) 47 | local.Dir = path 48 | lstdout, _ := local.Output() 49 | localRef := strings.TrimSpace(string(lstdout[:])) 50 | 51 | remote := exec.Command("git", "rev-parse", fmt.Sprintf("origin/%s", branchName)) 52 | remote.Dir = path 53 | rstdout, err := remote.Output() 54 | remoteRef := strings.TrimSpace(string(rstdout[:])) 55 | 56 | if err == nil && remoteRef != localRef { 57 | changes = append(changes, output.ApplyColour(" P", "blue")) 58 | } 59 | 60 | if len(changes) > 0 { 61 | var buffer bytes.Buffer 62 | 63 | repoName := strings.Replace(path, fmt.Sprintf("%s%s", root, string(os.PathSeparator)), "", -1) 64 | 65 | buffer.WriteString(fmt.Sprintf("- %s (%s)", repoName, branchName)) 66 | for _, change := range changes { 67 | buffer.WriteString(change) 68 | } 69 | outputChannel <- output.Print(buffer.String()) 70 | } 71 | 72 | } 73 | } 74 | 75 | func Exists(path string) (bool, error) { 76 | _, err := os.Stat(path) 77 | if err == nil { 78 | return true, nil 79 | } 80 | if os.IsNotExist(err) { 81 | return false, nil 82 | } 83 | return false, err 84 | } 85 | -------------------------------------------------------------------------------- /test/fixtures/invalid/.cig.yaml: -------------------------------------------------------------------------------- 1 | * 2 | & ^% 3 | foo: /test/path 4 | bar: /another/test/path 5 | -------------------------------------------------------------------------------- /test/fixtures/valid/.cig.yaml: -------------------------------------------------------------------------------- 1 | foo: /test/path 2 | bar: /another/test/path 3 | --------------------------------------------------------------------------------