Full Code of donkeysharp/gocho for AI

master 90af18ba15da cached
87 files
547.4 KB
152.9k tokens
840 symbols
1 requests
Download .txt
Showing preview only (576K chars total). Download the full file or copy to clipboard to get everything.
Repository: donkeysharp/gocho
Branch: master
Commit: 90af18ba15da
Files: 87
Total size: 547.4 KB

Directory structure:
gitextract_kbx_5a4t/

├── .gitignore
├── .travis.yml
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── assets/
│   ├── .gitignore
│   └── assets.go
├── cmd/
│   └── gocho/
│       └── gocho.go
├── docs/
│   └── building.md
├── pkg/
│   ├── cmds/
│   │   └── cmds.go
│   ├── config/
│   │   ├── config.go
│   │   ├── utils.go
│   │   └── wizard.go
│   ├── info/
│   │   └── info.go
│   └── node/
│       ├── dashboard.go
│       ├── index.go
│       ├── net.go
│       ├── node.go
│       ├── packet.go
│       ├── serve.go
│       └── utils.go
├── ui/
│   ├── .gitignore
│   ├── package.json
│   ├── public/
│   │   ├── index.html
│   │   └── lang/
│   │       ├── en.json
│   │       └── es.json
│   └── src/
│       ├── App.css
│       ├── App.js
│       ├── components/
│       │   ├── FormField.js
│       │   ├── NodeDetails.js
│       │   ├── NodeList.js
│       │   ├── Panel.js
│       │   └── SideBar.js
│       ├── containers/
│       │   ├── Discover.js
│       │   └── NodeInfo.js
│       ├── i18n.js
│       ├── index.css
│       └── index.js
└── vendor/
    ├── github.com/
    │   ├── Pallinder/
    │   │   └── go-randomdata/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── fullprofile.go
    │   │       ├── jsondata.go
    │   │       ├── postalcodes.go
    │   │       └── random_data.go
    │   ├── elazarl/
    │   │   └── go-bindata-assetfs/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── assetfs.go
    │   │       └── doc.go
    │   ├── mitchellh/
    │   │   └── go-homedir/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       └── homedir.go
    │   └── urfave/
    │       └── cli/
    │           ├── CHANGELOG.md
    │           ├── LICENSE
    │           ├── README.md
    │           ├── app.go
    │           ├── appveyor.yml
    │           ├── category.go
    │           ├── cli.go
    │           ├── command.go
    │           ├── context.go
    │           ├── errors.go
    │           ├── flag-types.json
    │           ├── flag.go
    │           ├── flag_generated.go
    │           ├── funcs.go
    │           ├── generate-flag-types
    │           ├── help.go
    │           ├── runtests
    │           └── sort.go
    ├── gopkg.in/
    │   └── yaml.v2/
    │       ├── LICENSE
    │       ├── LICENSE.libyaml
    │       ├── README.md
    │       ├── apic.go
    │       ├── decode.go
    │       ├── emitterc.go
    │       ├── encode.go
    │       ├── parserc.go
    │       ├── readerc.go
    │       ├── resolve.go
    │       ├── scannerc.go
    │       ├── sorter.go
    │       ├── writerc.go
    │       ├── yaml.go
    │       ├── yamlh.go
    │       └── yamlprivateh.go
    └── vendor.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
dist/
build/


================================================
FILE: .travis.yml
================================================
language: go
install: true
sudo: required

before_install:
  - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
  - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
  - sudo apt-get update
  - sudo apt-get install apt-transport-https -y
  - curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
  - sudo apt-get install yarn -y -qq

cache:
  yarn: true

go: "1.10"

script:
  - go get -u -v github.com/jteeuwen/go-bindata/...
  - cd ui
  - yarn install
  - cd ..
  - make dist


================================================
FILE: Dockerfile
================================================
FROM debian:latest

COPY ./dist/gocho /usr/local/bin/gocho

RUN chmod +x /usr/local/bin/gocho \
    && mkdir -p /root/public \
    && echo 'file1' > /root/public/file1 \
    && echo 'file2' > /root/public/file2 \
    && echo 'file3' > /root/public/file3 \
    && echo 'file4' > /root/public/file4 \
    && echo 'file5' > /root/public/file5 \
    && echo 'NodeId: root' > /root/.gocho.conf \
    && echo 'WebPort: "5555"' >> /root/.gocho.conf \
    && echo 'LocalPort: "1337"' >> /root/.gocho.conf \
    && echo 'ShareDirectory: "/root/public"' >> /root/.gocho.conf

CMD ["/usr/local/bin/gocho", "start"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Sergio Guillen Mantilla<serguimant@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
VERSION = 0.2.0
GOPATH := $(PWD)/build:$(GOPATH)

build-dev:
	@echo "Building gocho"
	rm -rf build && mkdir -p build/src/github.com/donkeysharp
	ln -s $(PWD) $(PWD)/build/src/github.com/donkeysharp/gocho
	go install -i github.com/donkeysharp/gocho/cmd/gocho

clean:
	rm -rf dist/*
	rm -rf build

dist: clean ui generate
	@echo "Building gocho for Linux x86_64..."
	mkdir -p dist/linux64
	go build -o dist/linux64/gocho cmd/gocho/gocho.go
	@zip -j dist/gocho_${VERSION}_linux64.zip dist/linux64/gocho

generate:
	go generate cmd/gocho/gocho.go

dist-linux32:
	@echo "Building gocho for Linux 32bits..."
	mkdir -p dist/linux386
	GOOS=linux GOARCH=386 go build -o dist/linux386/gocho cmd/gocho/gocho.go
	@zip -j dist/gocho_${VERSION}_linux386.zip dist/linux386/gocho

dist-win32:
	@echo "Building gocho for Windows 32bits..."
	mkdir -p dist/win32
	GOOS=windows GOARCH=386 go build -o dist/win32/gocho.exe cmd/gocho/gocho.go
	@zip -j dist/gocho_${VERSION}_win32.zip dist/win32/gocho.exe

dist-win64:
	@echo "Building gocho for Windows 64bits..."
	mkdir -p dist/win64
	GOOS=windows GOARCH=amd64 go build -o dist/win64/gocho.exe cmd/gocho/gocho.go
	@zip -j dist/gocho_${VERSION}_win64.zip dist/win64/gocho.exe

dist-darwin:
	@echo "Building gocho for Darwin 64bits..."
	mkdir -p dist/darwin
	GOOS=darwin GOARCH=amd64 go build -o dist/darwin/gocho cmd/gocho/gocho.go
	@zip -j dist/gocho_${VERSION}_darwin.zip dist/darwin/gocho

docker: dist
	docker build . -t donkeysharp/gocho

start:
	docker run -it -p "1337:1337" --rm donkeysharp/gocho gocho start --debug || true

test:
	docker run -it --rm donkeysharp/gocho || true

clean-dashboard:
	rm -rf assets/assets_gen.go

ui: clean-dashboard
	cd ui \
	&& yarn build


================================================
FILE: README.md
================================================
Gocho - Local Network File Sharing [![Build Status](https://travis-ci.org/donkeysharp/gocho.svg?branch=master)](https://travis-ci.org/donkeysharp/gocho)
==================================

Gocho allows you to share a chosen directory with others on the same local network, without the need to setup Samba or OS-oriented settings. It provides a local dashboard which you can access through your browser, to discover what others are sharing without knowing other's IP addresses.

Run Gocho, browse to [localhost:1337](http://localhost:1337) and see what others are sharing!

<!-- Image of dashboard -->
![alt Gocho dashboard](docs/gocho-dashboard.gif)

> **Building The Project:**
>
> If you want to help and contribute don't forget to check the [Building document](docs/building.md) in order to have your environment ready.

## Install
[Download the latest release](https://github.com/donkeysharp/gocho/releases) for your operating system. Currently the following operating systems are being supported:

* GNU/Linux 32 bits
* GNU/Linux 64 bits
* OSX
* Windows 32 bits
* Windows 64 bits

Download, unzip the file and add it to your path or a directory that is already in your system's path.

**Example unix-like**

    $ unzip gocho_0.1.0_darwin.zip
    $ mv gocho /usr/bin
    $ gocho --help

## Instructions
Gocho needs to be executed using the command line in order to initiate the sharing.

There are two ways to start sharing:
1. Specify the settings on a config file
2. Specify the settings using command line flags.

### Specify a settings file
Gocho reads a settings file that is located at `$USER_HOME/.gocho.conf`. The format of the file is as follows:

```
NodeId: my-computer
WebPort: "5555"
LocalPort: "1337"
ShareDirectory: /home/user/some/directory
```

If you want Gocho to create this file for you, it's possible to run the configuration wizard by running:

    $ gocho configure

Which will ask for the different settings and create a `.gocho.conf` file.

Once settings file is created, run the next to start sharing:

    $ gocho start

![alt Gocho wizard](docs/gocho-configure.gif)

### Use command line flags
If you don't want to specify a configuration file, or want to share a directory which is not specified on the `.gocho.conf` file, run:

    $ gocho start --dir /some/directory --id my-computer-tmp

This is the list of available flags

Flag | Description
--- | ---
--id {value} | Node ID that will be shared to other peers (**Required**)
--dir {value} | Directory to share (**Required**)
--share-port {value} |  Port that will be exposed for file sharing (default: "5555")
--local-port {value} | Port for local dashboard (default: "1337")

<!-- gocho using flags -->
![alt Gocho flags](docs/gocho-start.gif)

## License
Licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.


================================================
FILE: assets/.gitignore
================================================
assets_gen.go


================================================
FILE: assets/assets.go
================================================
package assets

import (
	"github.com/elazarl/go-bindata-assetfs"
)

func AssetFS() *assetfs.AssetFS {
	return &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "../../ui/build"}
}


================================================
FILE: cmd/gocho/gocho.go
================================================
package main

//go:generate go-bindata -o ../../assets/assets_gen.go -pkg assets ../../ui/build/...

import (
	"github.com/donkeysharp/gocho/pkg/cmds"
	"os"
)

func main() {
	cmds.New().Run(os.Args)
}


================================================
FILE: docs/building.md
================================================
Building Instructions
=====================

## Requirements
You need these tools installed in order to develop Gocho:

* Yarn (ui)
* NodeJS (ui)
* GNU Make (for general process building)
* Go (for main code compilation)
* go-bindata (for embedding UI inside final binary). 


> *Installing go-bindata creates a binary, don't forget to add $GOPATH/bin to your path* It's important that go-bindata is in the path becuase `make generate` &mdash;the command that embeds ui code into binary&mdash; needs it.

## Service Development
In order to run Gocho service and start development on it there are some things to consider: the next steps need to be run only the first time if you don't want to modify the UI.

This steps need to be executed in the root directory of the project.

#### Step 1
Build the UI files e.g. html, javascript and css.

    $ make ui

It will create a `ui/build` directory with the resulting files for the UI

#### Step 2
As UI files are embedded inside the final binary, we use [go-binddata](https://github.com/jteeuwen/go-bindata) to achieve this. The `generate` command in the Makefile creates an `assets/assets_gen.go` file with the embedded UI code.

    $ make generate

So far the previous steps need to be run only the first time unless you are modifying UI, in that case check the `UI Development` section.

To build `gocho` binary and test it while you do changes run:

    $ make build-dev

Which will create the `gocho` binary at `$GOPATH/bin/gocho` as that command runs `go install github.com/donkeysharp/gocho/cmd/gocho`

## UI Development
Gocho UI uses React and was intialized using [Create React App](https://github.com/facebook/create-react-app).

All React code for the dashboard is located in the `ui` directory. This directory has the package.json and the yarn.lock file, in order to develop and test the UI you need to run the next

    $ cd ui
    # Install UI dependencies
    $ yarn install
    # Start development server
    $ yarn start

That will bring up a development server at http://localhost:3000 with the UI so it can be developed. The development server for UI is configured to use a proxy to `http://localhost:1337` (see `package.json`) so it's important to have a backend running, check `Service Development` section.


================================================
FILE: pkg/cmds/cmds.go
================================================
package cmds

import (
	"fmt"
	"github.com/donkeysharp/gocho/pkg/config"
	"github.com/donkeysharp/gocho/pkg/info"
	"github.com/donkeysharp/gocho/pkg/node"
	"github.com/urfave/cli"
)

func ConfigureAction(c *cli.Context) error {
	err := config.ConfigureWizard()
	if err != nil {
		return cli.NewExitError(err, 1)
	}
	return nil
}

func StartAction(c *cli.Context) error {
	fmt.Println("Starting Gocho Node...")
	conf := &config.Config{}
	conf.Debug = c.Bool("debug")
	conf.LocalPort = c.String("local-port")
	conf.WebPort = c.String("share-port")
	conf.ShareDirectory = c.String("dir")
	conf.NodeId = c.String("id")

	if conf.NodeId == "" || conf.ShareDirectory == "" {
		fmt.Println("Both --dir and --id should be set.")
		fmt.Println("Checking config file.")
		var err error
		conf, err = config.LoadConfig()
		if err != nil {
			return cli.NewExitError(err, 1)
		}
	}

	fmt.Println("Configuration loaded")
	fmt.Println("---")
	fmt.Println(conf)
	fmt.Println("---")

	node.Serve(conf)

	return nil
}

func New() *cli.App {
	app := cli.NewApp()
	app.Name = info.APP_NAME
	app.Usage = "Auto-discovery local area network file sharing"
	app.Version = info.VERSION
	app.Authors = []cli.Author{
		cli.Author{
			Name:  "Sergio Guillen Mantilla",
			Email: "serguimant@gmail.com",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:  "start",
			Usage: "Start Gocho node",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "debug",
					Usage: "Start gocho in debug mode",
				},
				cli.StringFlag{
					Name:   "id",
					Usage:  "Node ID that will be shared to other peers",
					EnvVar: "GOCHO_ID",
				},
				cli.StringFlag{
					Name:   "dir",
					Usage:  "Directory to share",
					EnvVar: "GOCHO_DIR",
				},
				cli.StringFlag{
					Name:   "share-port",
					Usage:  "Port that will be exposed for file sharing",
					EnvVar: "GOCHO_SHARE_PORT",
					Value:  "5555",
				},
				cli.StringFlag{
					Name:   "local-port",
					Usage:  "Port for local dashboard",
					EnvVar: "GOCHO_LOCAL_PORT",
					Value:  "1337",
				},
			},
			Action: StartAction,
		},
		{
			Name:   "configure",
			Usage:  "Create a configuration file for Gocho node",
			Action: ConfigureAction,
		},
	}

	return app
}


================================================
FILE: pkg/config/config.go
================================================
package config

import (
	"fmt"
	yaml "gopkg.in/yaml.v2"
	"io/ioutil"
)

type Config struct {
	NodeId         string `yaml:"NodeId" json:"nodeId"`
	WebPort        string `yaml:"WebPort" json:"webPort"`
	LocalPort      string `yaml:"LocalPort" json:"localPort"`
	ShareDirectory string `yaml:"ShareDirectory" json:"sharedDirectory"`
	ConfigFile     string `yaml:"-" json:"-"`
	Debug          bool   `yaml:"-" json:"-"`
}

func (c *Config) String() string {
	data, err := yaml.Marshal(c)
	if err != nil {
		return ""
	}
	return string(data)
}

func ConfigureWizard() error {
	return configureWizard()
}

func LoadConfig() (*Config, error) {
	configFile, err := getConfigFileName()
	if err != nil {
		return nil, err
	}

	if !fileExists(configFile) {
		return nil, fmt.Errorf("Error: Config file does not exist\nUse:\n\t$ gocho configure")
	}

	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		return nil, err
	}
	config := &Config{}

	err = yaml.Unmarshal(data, config)
	if err != nil {
		return nil, err
	}
	config.ShareDirectory = CleanPath(config.ShareDirectory)
	return config, nil
}


================================================
FILE: pkg/config/utils.go
================================================
package config

import (
	"fmt"
	"github.com/Pallinder/go-randomdata"
	homedir "github.com/mitchellh/go-homedir"
	"io/ioutil"
	"os"
	"os/user"
	"strings"
)

func fileExists(file string) bool {
	_, err := os.Stat(file)
	return err == nil
}

func CleanPath(str string) string {
	return strings.TrimRight(str, string(os.PathSeparator))
}

func writeConfigToFile(c *Config, fileName string) error {
	data := []byte(c.String())
	return ioutil.WriteFile(fileName, data, 0644)
}

func getConfigFileName() (string, error) {
	userHome, err := homedir.Dir()
	if err != nil {
		return "", err
	}

	configFile := fmt.Sprintf("%s%c%s", userHome, os.PathSeparator, ".gocho.conf")
	return configFile, nil
}

func getDefaultConfig() (*Config, error) {
	configFile, err := getConfigFileName()
	if err != nil {
		return nil, err
	}

	defaultWebPort := "5555"
	defaultLocalPort := "1337"
	defaultNodeId := randomdata.SillyName()
	currentUser, err := user.Current()
	if err == nil {
		defaultNodeId = currentUser.Username
	}

	config := &Config{
		ShareDirectory: "",
		WebPort:        defaultWebPort,
		LocalPort:      defaultLocalPort,
		NodeId:         defaultNodeId,
		ConfigFile:     configFile,
	}
	return config, nil
}


================================================
FILE: pkg/config/wizard.go
================================================
package config

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func configureWizard() error {
	reader := bufio.NewReader(os.Stdin)

	config, err := getDefaultConfig()
	if err != nil {
		return err
	}

	fmt.Println("Gocho Configure Wizard")
	fmt.Println("It will reset previous \"Gocho\" configure file")
	var (
		shareDirectory string
		webPort        string
		localPort      string
		nodeId         string
	)

	fmt.Printf("Node Id: (%s) ", config.NodeId)
	fmt.Scanf("%s", &nodeId)
	fmt.Printf("Share Directory: ")
	// In windows it fails using fmt.Scanf
	lineRaw, _, err := reader.ReadLine()
	fmt.Println(string(lineRaw))
	if err != nil || strings.Trim(string(lineRaw), " \t") == "" {
		fmt.Println("Invalid value for \"Share Directory\"")
		os.Exit(1)
	}
	shareDirectory = string(lineRaw)
	fmt.Printf("Share Port: (%s) ", config.WebPort)
	fmt.Scanf("%s", &webPort)
	fmt.Printf("Dashboard Port: (%s) ", config.LocalPort)
	fmt.Scanf("%s", &localPort)

	if nodeId != "" {
		config.NodeId = nodeId
	}
	if shareDirectory != "" {
		config.ShareDirectory = CleanPath(shareDirectory)
	}
	if webPort != "" {
		config.WebPort = webPort
	}
	if localPort != "" {
		config.LocalPort = localPort
	}

	if fileExists(config.ConfigFile) {
		err := os.Remove(config.ConfigFile)
		if err != nil {
			return err
		}
	}

	return writeConfigToFile(config, config.ConfigFile)
}


================================================
FILE: pkg/info/info.go
================================================
package info

const (
	APP_NAME = "gocho"
	VERSION  = "0.2.0-alfa"
)


================================================
FILE: pkg/node/dashboard.go
================================================
package node

import (
	"container/list"
	"encoding/json"
	"fmt"
	"github.com/donkeysharp/gocho/assets"
	"github.com/donkeysharp/gocho/pkg/config"
	"net/http"
	"log"
)

func configHandler(conf *config.Config) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		data, err := json.Marshal(conf)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		w.Header().Add("Content-Type", "application/json")
		w.Write(data)
	}
}

func nodesHandler(nodeList *list.List) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		nodes := make([]*NodeInfo, 0)
		for el := nodeList.Front(); el != nil; el = el.Next() {
			tmp := el.Value.(*NodeInfo)
			nodes = append(nodes, tmp)
		}

		data, err := json.Marshal(nodes)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		w.Header().Add("Content-Type", "application/json")
		w.Write(data)
	}
}

func dashboardServe(conf *config.Config, nodeList *list.List) {
	dashboardMux := http.NewServeMux()
	dashboardMux.Handle("/", http.FileServer(assets.AssetFS()))
	dashboardMux.HandleFunc("/api/config", configHandler(conf))
	dashboardMux.HandleFunc("/api/nodes", nodesHandler(nodeList))

	// We don't want the dashboard to be public
	address := "localhost"
	if conf.Debug {
		address = "0.0.0.0"
	}

	fmt.Printf("Starting dashboard at %s:%s\n", address, conf.LocalPort)
	err := http.ListenAndServe(fmt.Sprintf("%s:%s", address, conf.LocalPort), dashboardMux)
	if err != nil {
		log.Fatal(err)
	}
}


================================================
FILE: pkg/node/index.go
================================================
package node

import (
	"bytes"
	"fmt"
	"github.com/donkeysharp/gocho/pkg/config"
	"net/http"
	"regexp"
)

const (
	HTML_BODY = `<html>
<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css">
    <style>
        * {
            font-family: sans-serif;
        }
        a {
            text-decoration: none;
            color: #1552A8;
            display: block;
            padding-bottom: 3px;
        }
        a.directory:before {
            color: #FFCF30;
            font-family: FontAwesome;
            content: "\f07b\00a0";
        }
        a.file:before {
            font-family: FontAwesome;
            content: "\f016\00a0";
        }
    </style>
    <script>
        function goBack() {
            var path = window.location.pathname.split('/');
            if (path.length <= 3) {
                window.location = '/';
                return;
            }
            window.location = path.slice(0, path.length - 2).join('/');
        }
    </script>
</head>
<body>
<a class="directory" onClick="javascript:goBack()" href="#">..</a>`
	HTML_END = `<script type="text/javascript">
    document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll(".file").forEach((el) => {
            document.body.appendChild(el);
        })
    })
</script>
</body>
</html>`
)

type FileServerResponseInterceptor struct {
	OriginalWriter http.ResponseWriter
	IndexBuffer    *bytes.Buffer
}

func (f *FileServerResponseInterceptor) WriteHeader(status int) {
	f.OriginalWriter.WriteHeader(status)
}

func (f *FileServerResponseInterceptor) Header() http.Header {
	return f.OriginalWriter.Header()
}

func (f *FileServerResponseInterceptor) Write(content []byte) (int, error) {
	// if it's not an html tag why bother evaluating with regex?
	if content[0] != byte('<') {
		return f.OriginalWriter.Write(content)
	}
	re := regexp.MustCompile("^<a.+href=\"(.+)\".*>(.+)</a>$|^</{0,1}pre>$")
	if !re.Match(bytes.Trim(content, "\n\r")) {
		return f.OriginalWriter.Write(content)
	}
	content = bytes.Trim(content, "\n\r")
	directoryRegex := regexp.MustCompile("^<a.+href=\"(.+/)\".*>(.+)</a>$")
	if directoryRegex.Match(content) {
		directoryLink := "<a class=\"directory\" href=\"$1\">$2</a>\n"
		content = directoryRegex.ReplaceAll(content, []byte(directoryLink))
		return f.IndexBuffer.Write(content)
	}
	fileRegex := regexp.MustCompile("^<a.+href=\"(.+)\".*>(.+)</a>$")
	if fileRegex.Match(content) {
		fileLink := "<a class=\"file\" href=\"$1\">$2</a>\n"
		content = fileRegex.ReplaceAll(content, []byte(fileLink))
		return f.IndexBuffer.Write(content)
	}
	return 0, nil
}

func interceptorHandler(next http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		interceptor := &FileServerResponseInterceptor{
			OriginalWriter: w,
			IndexBuffer:    bytes.NewBuffer(nil),
		}
		r.Header.Del("If-Modified-Since")
		next.ServeHTTP(interceptor, r)

		if interceptor.IndexBuffer.Len() > 0 {
			w.Write([]byte(HTML_BODY))
			w.Write(interceptor.IndexBuffer.Bytes())
			w.Write([]byte(HTML_END))
		}
	}
	return http.HandlerFunc(fn)
}

func fileServe(conf *config.Config) {
	fileMux := http.NewServeMux()
	fileMux.Handle("/", interceptorHandler(http.FileServer(http.Dir(conf.ShareDirectory))))
	http.ListenAndServe(fmt.Sprintf("0.0.0.0:%s", conf.WebPort), fileMux)
}


================================================
FILE: pkg/node/net.go
================================================
package node

import (
	"container/list"
	"fmt"
	"net"
	"sync"
	"time"
)

var (
	nodeMutex sync.Mutex
)

func announceNode(nodeInfo *NodeInfo) {
	address, err := net.ResolveUDPAddr("udp", MULTICAST_ADDRESS)
	if err != nil {
		return
	}

	conn, err := net.DialUDP("udp", nil, address)
	if err != nil {
		return
	}

	for {
		fmt.Println("sending multicast info")

		message, err := NewAnnouncePacket(nodeInfo)
		if err != nil {
			fmt.Println("Could not get announce package")
			fmt.Println(err)
			continue
		}

		conn.Write([]byte(message))
		time.Sleep(ANNOUNCE_INTERVAL_SEC * time.Second)
	}
}

func listenForNodes(nodeList *list.List) {
	address, err := net.ResolveUDPAddr("udp", MULTICAST_ADDRESS)
	if err != nil {
		return
	}

	conn, err := net.ListenMulticastUDP("udp", nil, address)
	if err != nil {
		return
	}

	conn.SetReadBuffer(MULTICAST_BUFFER_SIZE)

	for {
		packet := make([]byte, MULTICAST_BUFFER_SIZE)
		size, udpAddr, err := conn.ReadFromUDP(packet)
		if err != nil {
			fmt.Println(err)
			continue
		}

		nodeInfo, err := ParseAnnouncePacket(size, udpAddr, packet)

		if err != nil {
			fmt.Println(err)
			continue
		}
		fmt.Printf("Received multicast packet from %s Id: %s\n", udpAddr.String(), nodeInfo.Id)

		go announcedNodeHandler(nodeInfo, nodeList)
	}
}

func announcedNodeHandler(nodeInfo *NodeInfo, nodeList *list.List) {
	nodeMutex.Lock()
	updateNodeList(nodeInfo, nodeList)
	nodeMutex.Unlock()

	fmt.Println("Printing nodes")

	fmt.Print("[")
	for el := nodeList.Front(); el != nil; el = el.Next() {
		fmt.Print(el.Value.(*NodeInfo).Id, " ")
	}
	fmt.Print("]\n\n")
}

func updateNodeList(nodeInfo *NodeInfo, nodeList *list.List) {
	nodeExists := false
	for el := nodeList.Front(); el != nil; el = el.Next() {
		tmp := el.Value.(*NodeInfo)

		// Already in list
		if tmp.Id == nodeInfo.Id {
			tmp.LastMulticast = time.Now().Unix()
			fmt.Printf("Updating node %s multicast\n", nodeInfo.Id)
			nodeExists = true
			break
		}

	}

	for el := nodeList.Front(); el != nil; el = el.Next() {
		tmp := el.Value.(*NodeInfo)
		if isNodeExpired(tmp, EXPIRE_TIMEOUT_SEC) {
			fmt.Println("Node expired, removing: ", tmp.Id)
			nodeList.Remove(el)
		}
	}

	if !nodeExists {
		fmt.Printf("Adding new node! %p %s\n", nodeInfo, nodeInfo.Id)
		nodeInfo.LastMulticast = time.Now().Unix()
		nodeList.PushBack(nodeInfo)
	}
}

func isNodeExpired(nodeInfo *NodeInfo, timeout int) bool {
	diff := time.Now().Unix() - nodeInfo.LastMulticast
	return diff > int64(timeout)
}


================================================
FILE: pkg/node/node.go
================================================
package node

import (
	"container/list"
	"github.com/donkeysharp/gocho/pkg/config"
)

const (
	MULTICAST_ADDRESS     = "239.6.6.6:1337"
	MULTICAST_BUFFER_SIZE = 4096

	NODE_ANNOUNCE_COMMAND = "\x01"
	HEADER                = "\x60\x0D\xF0\x0D"
	MIN_PACKET_SIZE       = 6

	EXPIRE_TIMEOUT_SEC    = 50
	ANNOUNCE_INTERVAL_SEC = 10
)

type NodeInfo struct {
	Id            string `json:"nodeId"`
	Address       string `json:"ipAddress"`
	WebPort       string `json:"webPort"`
	LastMulticast int64  `json:"-"`
}

type Announcer struct {
	config *config.Config
}

func (a *Announcer) Start(nodeList *list.List) {
	nodeInfo := &NodeInfo{
		Id:            a.config.NodeId,
		Address:       "",
		WebPort:       a.config.WebPort,
		LastMulticast: 0,
	}

	go announceNode(nodeInfo)
	go listenForNodes(nodeList)

}


================================================
FILE: pkg/node/packet.go
================================================
package node

import (
	"encoding/json"
	"fmt"
	"net"
	"strings"
)

func NewAnnouncePacket(n *NodeInfo) (string, error) {
	jsonMessage, err := json.Marshal(n)
	if err != nil {
		return "", err
	}

	message := fmt.Sprintf("%s%s%s", HEADER, NODE_ANNOUNCE_COMMAND, jsonMessage)

	return message, nil
}

func ParseAnnouncePacket(size int, addr *net.UDPAddr, packet []byte) (*NodeInfo, error) {
	if size <= MIN_PACKET_SIZE {
		return nil, fmt.Errorf("Invalid packet size")
	}
	if strings.Compare(string(packet[0:len(HEADER)]), HEADER) != 0 {
		return nil, fmt.Errorf("Invalid packet header")
	}

	if string(packet[len(HEADER):len(HEADER)+1]) != NODE_ANNOUNCE_COMMAND[0:] {
		return nil, fmt.Errorf("Command different than NODE_ANNOUNCE_COMMAND")
	}
	fmt.Println("Packet command is NODE_ANNOUNCE_COMMAND")

	payload := string(packet[len(HEADER)+1:])
	payload = strings.Trim(payload, "\x00")

	nodeInfo := &NodeInfo{}

	err := json.Unmarshal([]byte(payload), nodeInfo)
	nodeInfo.Address = addr.IP.String()
	nodeInfo.Id = fmt.Sprintf("%s-%s", nodeInfo.Id, nodeInfo.Address)
	if err != nil {
		return nil, err
	}

	return nodeInfo, nil
}


================================================
FILE: pkg/node/serve.go
================================================
package node

import (
	"container/list"
	"github.com/donkeysharp/gocho/pkg/config"
	"time"
)

func startAnnouncer(conf *config.Config, nodeList *list.List) {
	announcer := &Announcer{
		config: conf,
	}
	announcer.Start(nodeList)
}

func Serve(conf *config.Config) {
	nodeList := list.New()

	go startAnnouncer(conf, nodeList)
	go fileServe(conf)
	go dashboardServe(conf, nodeList)

	// Enhancement. Open the UI app in a browser
	openUrl("http://localhost:" + conf.LocalPort)

	for {
		time.Sleep(time.Minute * 15)
	}
}


================================================
FILE: pkg/node/utils.go
================================================
package node

import (
	"os/exec"
	"runtime"
)

// https://stackoverflow.com/a/39324149/916063
// open opens the specified URL in the default browser of the user.
func openUrl(url string) error {
	var cmd string
	var args []string

	switch runtime.GOOS {
	case "windows":
		cmd = "cmd"
		args = []string{"/c", "start"}
	case "darwin":
		cmd = "open"
	default: // "linux", "freebsd", "openbsd", "netbsd"
		cmd = "xdg-open"
	}
	args = append(args, url)
	return exec.Command(cmd, args...).Start()
}


================================================
FILE: ui/.gitignore
================================================
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node_modules

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: ui/package.json
================================================
{
  "name": "ui",
  "version": "0.1.0",
  "private": false,
  "proxy": "http://localhost:1337",
  "dependencies": {
    "react": "^16.10.0",
    "react-dom": "^16.10.0",
    "react-scripts": "3.2.0",
    "react-i18next": "^10.13.1",
    "i18next": "^17.2.0",
    "i18next-browser-languagedetector": "^4.0.0",
    "i18next-xhr-backend": "^3.2.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build && rm build/static/js/*.map && rm build/static/css/*.map && rm build/service-worker.js && rm build/asset-manifest.json",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": {}
}


================================================
FILE: ui/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <link rel="stylesheet" type="text/css" href="%PUBLIC_URL%/bootstrap.min.css">
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>Gocho - Local Network File Sharing</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: ui/public/lang/en.json
================================================
{
    "menus": [
        {
            "node_information": "Node Information"
        },
        {
            "discover": "Discover"
        }
    ],
    "sections": {
        "node_information": {
            "title": "Node Information",
            "node_settings": "Node Settings",
            "node_id": "Node ID",
            "web_port": "Web Port",
            "dashboard_port": "Dashboard Port",
            "shared_directory": "Shared Directory"
        },
        "discover": {
            "title": "Discover",
            "auto_discovery": "Auto-Discovery",
            "node_details": "Node Details",
            "no_node_selected": "No node selected",
            "no_nodes_available": "No nodes available",
            "node_id": "Node ID",
            "web_port": "Web Port",
            "URL": "URL",
            "view_files": "View Files",
            "hide_files": "Hide Files",
            "open_in_tab": "Open in tab"
        }
    }
}


================================================
FILE: ui/public/lang/es.json
================================================
{
    "menus": [
        {
            "node_information": "Información del Nodo"
        },
        {
            "discover": "Descubrir"
        }
    ],
    "sections": {
        "node_information": {
            "title": "Información del Nodo",
            "node_settings": "Ajustes del Nodo",
            "node_id": "ID Nodo",
            "web_port": "Puerto Web",
            "dashboard_port": "Puerto Panel de Control",
            "shared_directory": "Directorio Compartido"
        },
        "discover": {
            "title": "Descubrir",
            "auto_discovery": "Auto-Descubrir",
            "node_details": "Detalles del nodo",
            "no_node_selected": "Ningún nodo seleccionado",
            "no_nodes_available": "No hay nodos disponibles",
            "node_id": "ID Nodo",
            "web_port": "Puerto Web",
            "URL": "URL",
            "view_files": "Ver Archivos",
            "hide_files": "Ocultar Archivos",
            "open_in_tab": "Abrir en otra pestaña"
        }
    }
}


================================================
FILE: ui/src/App.css
================================================
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";

body {
  font-family: 'Poppins', sans-serif;
  background-color: #f4f3ef;
}

.wrapper {
  display: flex;
}

.content-wrapper {
  position: relative;
  margin-left: 250px;
  width: 100%;
}

.content {
  padding: 10px 80px;
}

.content-wrapper .nav {
  border-bottom: 1px #d5d5d5 solid;
  color: #747474;
  padding: 23px 50px;
}

.content-wrapper .nav .navbar-btn {
  display: none;
  top: 15px;
  right: 8px;
}

.panel {
  background-color: #fff;
  border-radius: 5px;
  border: 1px #d5d5d5 solid;
  box-shadow: 0 2px 2px rgba(204, 197, 185, 0.5);
}

.panel header {
  color: #53BD82;
  font-weight: bold;
  font-size: 20px;
  padding: 10px 15px;
  border-bottom: 1px #d5d5d5 solid;
}

.panel .panel-body {
  padding: 20px;
}

.sidebar {
  position: fixed;
  min-width: 250px;
  max-width: 250px;
  min-height: 100vh;
  background: #fff;
  transition: all 0.3s;
  z-index: 99999;
  border-right: 1px #d5d5d5 solid;
}
.sidebar a, a:hover, a:focus {
  color: inherit;
  text-decoration: none;
  transition: all 0.3s;
}

.navbar-btn {
  position: absolute;
  right: 0;
}

.sidebar .sidebar-header {
  padding: 20px;
  margin-left: 15px;
  margin-right: 20px;
  border-bottom: 1px solid #d5d5d5;
  font-size: 20px;
  text-align: center;
}

.sidebar ul.components {
  padding: 20px 0;
}

.sidebar ul li a {
  padding: 10px 10px 10px 20px;
  font-size: 1.1em;
  display: block;
  color: #959595;
  width: 100%;
}

.sidebar ul li a:hover {
  color: #313131;
}

.sidebar ul li.active > a {
  color: #53BD82;
}

@media (max-width: 768px) {
  .sidebar {
    margin-left: -250px;
  }
  .sidebar.active {
    margin-left: 0;
  }
  .content-wrapper {
    margin-left: 0;
  }

  .content-wrapper .nav .navbar-btn {
    display: inline-block;
  }

  .content {
    padding: 10px 10px;
  }
}

ul.node-list {
  padding: 0;
  list-style-type: none;
  width: 100%;
  max-height: 350px;
  min-height: 0px;
  overflow: auto;
}

.node-list li {
  list-style-type: none;
  display: block;
  background-color: #53BD82;
  color: #fff;
  margin-bottom: 5px;
}

.node-list li a {
  color: #fff;
  display: block;
  width: 100%;
  padding: 8px;
  border: 1px transparent solid;
  border-left: 8px #149D51 solid;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.node-list li a.active {
  background-color: #fff;
  color: #000;
  border: 1px #149D51 solid;
  border-left: 8px #149D51 solid;
}

.node-list li a.active:hover {
  background-color: #fff;
}

.node-list li a:hover {
  background-color: #73CD9A;
}

.node-details {
  border-left: 1px #d5d5d5 solid;
  padding-left: 20px;
}

.node-details a {
  color: #149D51;
}

.node-details a:hover {
  color: #000;
}

.files {
  width: 100%;
  height: 500px;
  border: 1px #d5d5d5 solid;
}


================================================
FILE: ui/src/App.js
================================================
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';
import SideBar from './components/SideBar';
import Discover from './containers/Discover';
import NodeInfo from './containers/NodeInfo';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.menu = [
      {
        name: 'menus.0.node_information',
        component: <NodeInfo />
      },
      {
        name: 'menus.1.discover',
        component: <Discover />
      }
    ];
    this.state = {
      title: this.menu[0].name,
      selectedItem: 0,
      toggle: false,
    }
  }
  collapse(e) {
    this.setState({
      toggle: !this.state.toggle,
    })
  }
  menuSelectedHandler(index) {
    this.setState({
      title: this.menu[index].name,
      selectedItem: index,
    })
  }
  render() {
    const { t } = this.props;
    return (
      <div className="wrapper">
        <span>{t("node_information")}</span>
        <SideBar
          toggle={this.state.toggle}
          title="Gocho"
          menu={this.menu}
          onMenuSelected={this.menuSelectedHandler.bind(this)} />
        <div className="content-wrapper">
          <nav className="nav">
            <b>{t(this.state.title)}</b>
            <button
              type="button"
              className="btn btn-info navbar-btn"
              onClick={this.collapse.bind(this)}
            >
              &lt;
            </button>
          </nav>
          <div className="content">
            {this.menu[this.state.selectedItem].component}
          </div>
        </div>
      </div>
    );
  }
}

export default withTranslation()(App);


================================================
FILE: ui/src/components/FormField.js
================================================
import React, {Component} from 'react';

class FormField extends Component {
  render() {
    let disabled = 'false';
    if (this.props.isDisabled) {
      disabled = 'true';
    }
    let leftCol = this.props.leftCol ? this.props.leftCol : 'col-md-3';
    let rightCol = this.props.rightCol ? this.props.rightCol : 'col-md-9';
    return <div className="form-group row">
      <label className={leftCol + ' col-form-label'}>{this.props.label}</label>
      <div className={rightCol}>
        <input className="form-control" disabled={disabled} value={this.props.value} />
      </div>
    </div>;
  }
}

export default FormField;


================================================
FILE: ui/src/components/NodeDetails.js
================================================
import React, {Component} from 'react';
import { withTranslation } from 'react-i18next';
import FormField from './FormField';


const IframeViewer = ((props) => {
  return <div className="row">
    <div className="col-md-12">
      <iframe frameBorder="0" className="files" src={props.url} title="shared-files" />
    </div>
  </div>
})

class NodeDetails extends Component {
  constructor(props) {
    super(props)
    this.state = {
      displayIframe: false,
    }
  }
  componentWillReceiveProps(nextProps) {
    if (this.props.node.nodeId !== nextProps.node.nodeId) {
      this.setState({
        displayIframe: false,
      })
    }
  }
  onClickHandler() {
    this.setState({
      displayIframe: !this.state.displayIframe,
    })
  }
  render() {
    const { t } = this.props;
    let nodeUrl = `http://${this.props.node.ipAddress}:${this.props.node.webPort}`;
    let iframeViewer = '';
    if (this.state.displayIframe) {
      iframeViewer = <IframeViewer url={nodeUrl} />
    }
    return <div className="node-details">
      <h4>{t('sections.discover.node_details')}</h4>
      <div className="form">
        <FormField label={t('sections.discover.node_id')} 
          value={this.props.node.nodeId}
          leftCol="col-md-2" rightCol="col-md-5" />
        <FormField label={t('sections.discover.web_port')} 
          value={this.props.node.webPort}
          leftCol="col-md-2" rightCol="col-md-5" />
        <FormField label={t('sections.discover.URL')} 
          value={nodeUrl}
          leftCol="col-md-2" rightCol="col-md-5" />
      </div>
      <div className="row">
        <div className="col-md-12">
          &nbsp;|&nbsp;
          <a
            href="#/"
            onClick={this.onClickHandler.bind(this)} >
            {
              this.state.displayIframe ? 
              t('sections.discover.hide_files') : 
              t('sections.discover.view_files')
            }
          </a>
          &nbsp;|&nbsp;
          <a href={nodeUrl} target="_">
            { t('sections.discover.open_in_tab') }
          </a>
          &nbsp;|&nbsp;
        </div>
      </div>
      { iframeViewer }
    </div>
  }
}

export default withTranslation()(NodeDetails);


================================================
FILE: ui/src/components/NodeList.js
================================================
import React, {Component} from 'react';

class NodeList extends Component {
  constructor(props) {
    super(props)
    this.state = {
      currentItem: -1
    }
  }
  onClickHandler(e) {
    let index = parseInt(e.currentTarget.dataset.index, 10);
    if (index === this.state.currentItem) {
      return;
    }
    this.setState({
      currentItem: index,
    })
    if (this.props.onNodeSelected) {
      this.props.onNodeSelected(index);
    }
  }
  render() {
    if (this.props.nodes && this.props.nodes.length === 0) {
      return <span>No nodes available</span>
    }
    return <ul className="node-list">
      {this.props.nodes.map((item, index) => {
        let className = ''
        if (index === this.state.currentItem) {
          className = 'active'
        }
        return <li key={index}>
          <a
            data-index={index}
            className={className}
            href="#/"
            onClick={this.onClickHandler.bind(this)}>
            {item.nodeId}
          </a>
        </li>
      })}
    </ul>
  }
}

export default NodeList;


================================================
FILE: ui/src/components/Panel.js
================================================
import React, {Component} from 'react';

class Panel extends Component {
  render() {
    return  <div className="panel">
      <header>
        {this.props.title}
      </header>
      <div className="panel-body">
        {this.props.children}
      </div>
    </div>
  }
}

export default Panel;


================================================
FILE: ui/src/components/SideBar.js
================================================
import React, {Component} from 'react';
import { withTranslation } from 'react-i18next';

class SideBar extends Component {
  constructor(props) {
    super(props)
    this.state = {
      currentItem: 0
    }
  }
  itemClickHandler(e) {
    let index = parseInt(e.currentTarget.dataset.index, 10)
    if (index === this.state.currentItem) {
      return
    }
    this.setState({
      currentItem: index,
    })

    if (this.props.onMenuSelected) {
      this.props.onMenuSelected(index)
    }
  }
  render() {
    const { t } = this.props;
    let className = 'sidebar';
    if (this.props.toggle) {
      className += ' active';
    }
    return <nav className={className}>
      <div className="sidebar-header">
        {this.props.title}
      </div>
      <ul className="list-unstyled components">
        {this.props.menu.map((item, index) => {
          let className = (index === this.state.currentItem ? 'active' : '');
          return <li className={className} key={index}>
            <a data-index={index}
              href="#/"
              onClick={this.itemClickHandler.bind(this)}>
              {t(item.name)}
            </a>
          </li>
        })}
      </ul>
    </nav>
  }
}

export default withTranslation()(SideBar);


================================================
FILE: ui/src/containers/Discover.js
================================================
import React, {Component} from 'react';
import { withTranslation } from 'react-i18next';
import Panel from '../components/Panel';
import NodeList from '../components/NodeList';
import NodeDetails from '../components/NodeDetails';


class Discover extends Component {
  constructor(props) {
    super(props)
    this.state = {
      nodes: [],
      currentNode: -1,
    }
  }
  retrieveData() {
    fetch('/api/nodes').then((resp) => {
      return resp.json()
    }).then((data) => {
      this.setState({
        nodes: data
      })
    })
  }
  componentDidMount() {
    this.retrieveData()
  }
  nodeSelectedHandler(index) {
    this.setState({
      currentNode: index,
    });
  }
  render() {
    const { t } = this.props;
    let detailsBody = <span>{t('sections.discover.no_node_selected')}</span>
    if (this.state.currentNode !== -1) {
      detailsBody = <NodeDetails
        node={this.state.nodes[this.state.currentNode]}
      />
    }
    return <Panel title={t("sections.discover.auto_discovery")}>
      <div className="row">
        <div className="col-md-3">
          <NodeList
            nodes={this.state.nodes}
            onNodeSelected={this.nodeSelectedHandler.bind(this)} />
        </div>
        <div className="col-md-9">
          {detailsBody}
        </div>
      </div>
    </Panel>
  }
}

export default withTranslation()(Discover);


================================================
FILE: ui/src/containers/NodeInfo.js
================================================
import React, {Component} from 'react';
import { withTranslation } from 'react-i18next';
import Panel from '../components/Panel'
import FormField from '../components/FormField'

class NodeInfo extends Component {
  constructor(props) {
    super(props)
    this.state = {
      nodeInfo: null
    }
  }
  componentDidMount() {
    fetch('/api/config').then((resp) => {
      return resp.json()
    }).then((data) => {
      this.setState({
        nodeInfo: data
      })
    })
  }
  render() {
    const { t } = this.props;
    if (!this.state.nodeInfo) {
      return <span>Loading...</span>
    }
    return <Panel title={t("sections.node_information.node_settings")}>
      <div className="form">
        <FormField
          label={t("sections.node_information.node_id")} 
          value={this.state.nodeInfo.nodeId}
          leftCol="col-md-3" rightCol="col-md-5" />
        <FormField label={t("sections.node_information.web_port")} 
          value={this.state.nodeInfo.webPort}
          leftCol="col-md-3" rightCol="col-md-5" />
        <FormField label={t("sections.node_information.dashboard_port")} 
          value={this.state.nodeInfo.localPort}
          leftCol="col-md-3" rightCol="col-md-5" />
        <FormField label={t("sections.node_information.shared_directory")} 
          value={this.state.nodeInfo.sharedDirectory}
          leftCol="col-md-3" rightCol="col-md-5" />
      </div>
    </Panel>
  }
}

export default withTranslation()(NodeInfo);


================================================
FILE: ui/src/i18n.js
================================================
import i18n from "i18next";
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from "react-i18next";

i18n
  .use(initReactI18next)
  .use(Backend)
  .use(LanguageDetector)
  .init({
    keySeparator: '.',
    interpolation: {
      escapeValue: false
    },
    backend: {
      loadPath: 'lang/{{lng}}.json'
    },
    fallbackLng: 'en'
  });

export default i18n;

================================================
FILE: ui/src/index.css
================================================
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}


================================================
FILE: ui/src/index.js
================================================
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import './i18n';
import './index.css';
import App from './App';

ReactDOM.render(
  <Suspense fallback="loading">
    <App />
  </Suspense>,
  document.getElementById('root')
);


================================================
FILE: vendor/github.com/Pallinder/go-randomdata/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 David Pallinder

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: vendor/github.com/Pallinder/go-randomdata/README.md
================================================
# go-randomdata

[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/Pallinder/go-randomdata/issues)
[![GoDoc](https://godoc.org/github.com/Pallinder/go-randomdata?status.svg)](https://godoc.org/github.com/Pallinder/go-randomdata)
[![Build Status](https://travis-ci.org/Pallinder/go-randomdata.png)](https://travis-ci.org/Pallinder/go-randomdata)
[![Go Report Card](https://goreportcard.com/badge/github.com/Pallinder/go-randomdata)](https://goreportcard.com/report/github.com/Pallinder/go-randomdata)

randomdata is a tiny help suite for generating random data such as

* first names (male or female)
* last names
* full names (male or female)
* country names (full name or iso 3166.1 alpha-2 or alpha-3)
* random email address
* city names
* American state names (two chars or full)
* random numbers (in an interval)
* random paragraphs
* random bool values
* postal- or zip-codes formatted for a range of different countries.
* american sounding addresses / street names
* silly names - suitable for names of things
* random days
* random months
* random full date
* random full profile
* random date inside range

## Installation

```go get github.com/Pallinder/go-randomdata```

## Usage

```go

package main

import (
    "fmt"
    "github.com/Pallinder/go-randomdata"
)

func main() {
    // Print a random silly name
    fmt.Println(randomdata.SillyName())

    // Print a male title
    fmt.Println(randomdata.Title(randomdata.Male))

    // Print a female title
    fmt.Println(randomdata.Title(randomdata.Female))

    // Print a title with random gender
    fmt.Println(randomdata.Title(randomdata.RandomGender))

    // Print a male first name
    fmt.Println(randomdata.FirstName(randomdata.Male))

    // Print a female first name
    fmt.Println(randomdata.FirstName(randomdata.Female))

    // Print a last name
    fmt.Println(randomdata.LastName())

    // Print a male name
    fmt.Println(randomdata.FullName(randomdata.Male))

    // Print a female name
    fmt.Println(randomdata.FullName(randomdata.Female))

    // Print a name with random gender
    fmt.Println(randomdata.FullName(randomdata.RandomGender))

    // Print an email
    fmt.Println(randomdata.Email())

    // Print a country with full text representation
    fmt.Println(randomdata.Country(randomdata.FullCountry))

    // Print a country using ISO 3166-1 alpha-2
    fmt.Println(randomdata.Country(randomdata.TwoCharCountry))

    // Print a country using ISO 3166-1 alpha-3
    fmt.Println(randomdata.Country(randomdata.ThreeCharCountry))

    // Print a currency using ISO 4217
    fmt.Println(randomdata.Currency())

    // Print the name of a random city
    fmt.Println(randomdata.City())

    // Print the name of a random american state
    fmt.Println(randomdata.State(randomdata.Large))

    // Print the name of a random american state using two chars
    fmt.Println(randomdata.State(randomdata.Small))

    // Print an american sounding street name
    fmt.Println(randomdata.Street())

    // Print an american sounding address
    fmt.Println(randomdata.Address())

    // Print a random number >= 10 and <= 20
    fmt.Println(randomdata.Number(10, 20))

    // Print a number >= 0 and <= 20
    fmt.Println(randomdata.Number(20))

    // Print a random float >= 0 and <= 20 with decimal point 3
    fmt.Println(randomdata.Decimal(0, 20, 3))

    // Print a random float >= 10 and <= 20
    fmt.Println(randomdata.Decimal(10, 20))

    // Print a random float >= 0 and <= 20
    fmt.Println(randomdata.Decimal(20))

    // Print a bool
    fmt.Println(randomdata.Boolean())

    // Print a paragraph
    fmt.Println(randomdata.Paragraph())

    // Print a postal code
    fmt.Println(randomdata.PostalCode("SE"))

    // Print a set of 2 random numbers as a string
    fmt.Println(randomdata.StringNumber(2, "-"))

    // Print a set of 2 random 3-Digits numbers as a string
    fmt.Println(randomdata.StringNumberExt(2, "-", 3))

    // Print a random string sampled from a list of strings
    fmt.Println(randomdata.StringSample("my string 1", "my string 2", "my string 3"))

    // Print a valid random IPv4 address
    fmt.Println(randomdata.IpV4Address())

    // Print a valid random IPv6 address
    fmt.Println(randomdata.IpV6Address())

    // Print a browser's user agent string
    fmt.Println(randomdata.UserAgentString())

    // Print a day
    fmt.Println(randomdata.Day())

    // Print a month
    fmt.Println(randomdata.Month())

    // Print full date like Monday 22 Aug 2016
    fmt.Println(randomdata.FullDate())

    // Print full date <= Monday 22 Aug 2016
    fmt.Println(randomdata.FullDateInRange("2016-08-22"))

    // Print full date >= Monday 01 Aug 2016 and <= Monday 22 Aug 2016
    fmt.Println(randomdata.FullDateInRange("2016-08-01", "2016-08-22"))

    // Get a complete and randomised profile of data generally used for users
    // There are many fields in the profile to use check the Profile struct definition in fullprofile.go
    profile := randomdata.GenerateProfile(randomdata.Male | randomdata.Female | randomdata.RandomGender)
    fmt.Printf("The new profile's username is: %s and password (md5): %s\n", profile.Login.Username, profile.Login.Md5)
}

```

## Contributors

* [jteeuwen](https://github.com/jteeuwen)
* [n1try](https://github.com/n1try)

All the other contributors are listed [here](https://github.com/Pallinder/go-randomdata/graphs/contributors).

================================================
FILE: vendor/github.com/Pallinder/go-randomdata/fullprofile.go
================================================
package randomdata

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

var letterRunes = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
var portraitDirs = []string{"men", "women"}

type Profile struct {
	Gender string `json:"gender"`
	Name   struct {
		First string `json:"first"`
		Last  string `json:"last"`
		Title string `json:"title"`
	} `json:"name"`
	Location struct {
		Street   string `json:"street"`
		City     string `json:"city"`
		State    string `json:"state"`
		Postcode int    `json:"postcode"`
	} `json:"location"`

	Email string `json:"email"`
	Login struct {
		Username string `json:"username"`
		Password string `json:"password"`
		Salt     string `json:"salt"`
		Md5      string `json:"md5"`
		Sha1     string `json:"sha1"`
		Sha256   string `json:"sha256"`
	} `json:"login"`

	Dob        string `json:"dob"`
	Registered string `json:"registered"`
	Phone      string `json:"phone"`
	Cell       string `json:"cell"`

	ID struct {
		Name  string      `json:"name"`
		Value interface{} `json:"value"`
	} `json:"id"`

	Picture struct {
		Large     string `json:"large"`
		Medium    string `json:"medium"`
		Thumbnail string `json:"thumbnail"`
	} `json:"picture"`
	Nat string `json:"nat"`
}

func RandStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func getMD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

func getSha1(text string) string {
	hasher := sha1.New()
	hasher.Write([]byte(text))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

func getSha256(text string) string {
	hasher := sha256.New()
	hasher.Write([]byte(text))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

func GenerateProfile(gender int) *Profile {
	rand.Seed(time.Now().UnixNano())
	profile := &Profile{}
	if gender == Male {
		profile.Gender = "male"
	} else if gender == Female {
		profile.Gender = "female"
	} else {
		gender = rand.Intn(2)
		if gender == Male {
			profile.Gender = "male"
		} else {
			profile.Gender = "female"
		}
	}
	profile.Name.Title = Title(gender)
	profile.Name.First = FirstName(gender)
	profile.Name.Last = LastName()
	profile.ID.Name = "SSN"
	profile.ID.Value = fmt.Sprintf("%d-%d-%d",
		Number(101, 999),
		Number(01, 99),
		Number(100, 9999),
	)

	profile.Email = strings.ToLower(profile.Name.First) + "." + strings.ToLower(profile.Name.Last) + "@example.com"
	profile.Cell = fmt.Sprintf("%d-%d-%d",
		Number(201, 999),
		Number(201, 999),
		Number(1000, 9999),
	)
	profile.Phone = fmt.Sprintf("%d-%d-%d",
		Number(201, 999),
		Number(201, 999),
		Number(1000, 9999),
	)
	profile.Dob = FullDate()
	profile.Registered = FullDate()
	profile.Nat = "US"

	profile.Location.City = City()
	i, _ := strconv.Atoi(PostalCode("US"))
	profile.Location.Postcode = i
	profile.Location.State = State(2)
	profile.Location.Street = StringNumber(1, "") + " " + Street()

	profile.Login.Username = SillyName()
	pass := SillyName()
	salt := RandStringRunes(16)
	profile.Login.Password = pass
	profile.Login.Salt = salt
	profile.Login.Md5 = getMD5Hash(pass + salt)
	profile.Login.Sha1 = getSha1(pass + salt)
	profile.Login.Sha256 = getSha256(pass + salt)

	pic := rand.Intn(35)
	profile.Picture.Large = fmt.Sprintf("https://randomuser.me/api/portraits/%s/%d.jpg", portraitDirs[gender], pic)
	profile.Picture.Medium = fmt.Sprintf("https://randomuser.me/api/portraits/med/%s/%d.jpg", portraitDirs[gender], pic)
	profile.Picture.Thumbnail = fmt.Sprintf("https://randomuser.me/api/portraits/thumb/%s/%d.jpg", portraitDirs[gender], pic)

	return profile
}


================================================
FILE: vendor/github.com/Pallinder/go-randomdata/jsondata.go
================================================
package randomdata

var data = []byte(`{
    "adjectives": [
        "black",
        "white",
        "gray",
        "brown",
        "red",
        "pink",
        "crimson",
        "carnelian",
        "orange",
        "yellow",
        "ivory",
        "cream",
        "green",
        "viridian",
        "aquamarine",
        "cyan",
        "blue",
        "cerulean",
        "azure",
        "indigo",
        "navy",
        "violet",
        "purple",
        "lavender",
        "magenta",
        "rainbow",
        "iridescent",
        "spectrum",
        "prism",
        "bold",
        "vivid",
        "pale",
        "clear",
        "glass",
        "translucent",
        "misty",
        "dark",
        "light",
        "gold",
        "silver",
        "copper",
        "bronze",
        "steel",
        "iron",
        "brass",
        "mercury",
        "zinc",
        "chrome",
        "platinum",
        "titanium",
        "nickel",
        "lead",
        "pewter",
        "rust",
        "metal",
        "stone",
        "quartz",
        "granite",
        "marble",
        "alabaster",
        "agate",
        "jasper",
        "pebble",
        "pyrite",
        "crystal",
        "geode",
        "obsidian",
        "mica",
        "flint",
        "sand",
        "gravel",
        "boulder",
        "basalt",
        "ruby",
        "beryl",
        "scarlet",
        "citrine",
        "sulpher",
        "topaz",
        "amber",
        "emerald",
        "malachite",
        "jade",
        "abalone",
        "lapis",
        "sapphire",
        "diamond",
        "peridot",
        "gem",
        "jewel",
        "bevel",
        "coral",
        "jet",
        "ebony",
        "wood",
        "tree",
        "cherry",
        "maple",
        "cedar",
        "branch",
        "bramble",
        "rowan",
        "ash",
        "fir",
        "pine",
        "cactus",
        "alder",
        "grove",
        "forest",
        "jungle",
        "palm",
        "bush",
        "mulberry",
        "juniper",
        "vine",
        "ivy",
        "rose",
        "lily",
        "tulip",
        "daffodil",
        "honeysuckle",
        "fuschia",
        "hazel",
        "walnut",
        "almond",
        "lime",
        "lemon",
        "apple",
        "blossom",
        "bloom",
        "crocus",
        "rose",
        "buttercup",
        "dandelion",
        "iris",
        "carnation",
        "fern",
        "root",
        "branch",
        "leaf",
        "seed",
        "flower",
        "petal",
        "pollen",
        "orchid",
        "mangrove",
        "cypress",
        "sequoia",
        "sage",
        "heather",
        "snapdragon",
        "daisy",
        "mountain",
        "hill",
        "alpine",
        "chestnut",
        "valley",
        "glacier",
        "forest",
        "grove",
        "glen",
        "tree",
        "thorn",
        "stump",
        "desert",
        "canyon",
        "dune",
        "oasis",
        "mirage",
        "well",
        "spring",
        "meadow",
        "field",
        "prairie",
        "grass",
        "tundra",
        "island",
        "shore",
        "sand",
        "shell",
        "surf",
        "wave",
        "foam",
        "tide",
        "lake",
        "river",
        "brook",
        "stream",
        "pool",
        "pond",
        "sun",
        "sprinkle",
        "shade",
        "shadow",
        "rain",
        "cloud",
        "storm",
        "hail",
        "snow",
        "sleet",
        "thunder",
        "lightning",
        "wind",
        "hurricane",
        "typhoon",
        "dawn",
        "sunrise",
        "morning",
        "noon",
        "twilight",
        "evening",
        "sunset",
        "midnight",
        "night",
        "sky",
        "star",
        "stellar",
        "comet",
        "nebula",
        "quasar",
        "solar",
        "lunar",
        "planet",
        "meteor",
        "sprout",
        "pear",
        "plum",
        "kiwi",
        "berry",
        "apricot",
        "peach",
        "mango",
        "pineapple",
        "coconut",
        "olive",
        "ginger",
        "root",
        "plain",
        "fancy",
        "stripe",
        "spot",
        "speckle",
        "spangle",
        "ring",
        "band",
        "blaze",
        "paint",
        "pinto",
        "shade",
        "tabby",
        "brindle",
        "patch",
        "calico",
        "checker",
        "dot",
        "pattern",
        "glitter",
        "glimmer",
        "shimmer",
        "dull",
        "dust",
        "dirt",
        "glaze",
        "scratch",
        "quick",
        "swift",
        "fast",
        "slow",
        "clever",
        "fire",
        "flicker",
        "flash",
        "spark",
        "ember",
        "coal",
        "flame",
        "chocolate",
        "vanilla",
        "sugar",
        "spice",
        "cake",
        "pie",
        "cookie",
        "candy",
        "caramel",
        "spiral",
        "round",
        "jelly",
        "square",
        "narrow",
        "long",
        "short",
        "small",
        "tiny",
        "big",
        "giant",
        "great",
        "atom",
        "peppermint",
        "mint",
        "butter",
        "fringe",
        "rag",
        "quilt",
        "truth",
        "lie",
        "holy",
        "curse",
        "noble",
        "sly",
        "brave",
        "shy",
        "lava",
        "foul",
        "leather",
        "fantasy",
        "keen",
        "luminous",
        "feather",
        "sticky",
        "gossamer",
        "cotton",
        "rattle",
        "silk",
        "satin",
        "cord",
        "denim",
        "flannel",
        "plaid",
        "wool",
        "linen",
        "silent",
        "flax",
        "weak",
        "valiant",
        "fierce",
        "gentle",
        "rhinestone",
        "splash",
        "north",
        "south",
        "east",
        "west",
        "summer",
        "winter",
        "autumn",
        "spring",
        "season",
        "equinox",
        "solstice",
        "paper",
        "motley",
        "torch",
        "ballistic",
        "rampant",
        "shag",
        "freckle",
        "wild",
        "free",
        "chain",
        "sheer",
        "crazy",
        "mad",
        "candle",
        "ribbon",
        "lace",
        "notch",
        "wax",
        "shine",
        "shallow",
        "deep",
        "bubble",
        "harvest",
        "fluff",
        "venom",
        "boom",
        "slash",
        "rune",
        "cold",
        "quill",
        "love",
        "hate",
        "garnet",
        "zircon",
        "power",
        "bone",
        "void",
        "horn",
        "glory",
        "cyber",
        "nova",
        "hot",
        "helix",
        "cosmic",
        "quark",
        "quiver",
        "holly",
        "clover",
        "polar",
        "regal",
        "ripple",
        "ebony",
        "wheat",
        "phantom",
        "dew",
        "chisel",
        "crack",
        "chatter",
        "laser",
        "foil",
        "tin",
        "clever",
        "treasure",
        "maze",
        "twisty",
        "curly",
        "fortune",
        "fate",
        "destiny",
        "cute",
        "slime",
        "ink",
        "disco",
        "plume",
        "time",
        "psychadelic",
        "relic",
        "fossil",
        "water",
        "savage",
        "ancient",
        "rapid",
        "road",
        "trail",
        "stitch",
        "button",
        "bow",
        "nimble",
        "zest",
        "sour",
        "bitter",
        "phase",
        "fan",
        "frill",
        "plump",
        "pickle",
        "mud",
        "puddle",
        "pond",
        "river",
        "spring",
        "stream",
        "battle",
        "arrow",
        "plume",
        "roan",
        "pitch",
        "tar",
        "cat",
        "dog",
        "horse",
        "lizard",
        "bird",
        "fish",
        "saber",
        "scythe",
        "sharp",
        "soft",
        "razor",
        "neon",
        "dandy",
        "weed",
        "swamp",
        "marsh",
        "bog",
        "peat",
        "moor",
        "muck",
        "mire",
        "grave",
        "fair",
        "just",
        "brick",
        "puzzle",
        "skitter",
        "prong",
        "fork",
        "dent",
        "dour",
        "warp",
        "luck",
        "coffee",
        "split",
        "chip",
        "hollow",
        "heavy",
        "legend",
        "hickory",
        "mesquite",
        "nettle",
        "rogue",
        "charm",
        "prickle",
        "bead",
        "sponge",
        "whip",
        "bald",
        "frost",
        "fog",
        "oil",
        "veil",
        "cliff",
        "volcano",
        "rift",
        "maze",
        "proud",
        "dew",
        "mirror",
        "shard",
        "salt",
        "pepper",
        "honey",
        "thread",
        "bristle",
        "ripple",
        "glow",
        "zenith"
    ],
    "nouns": [
        "head",
        "crest",
        "crown",
        "tooth",
        "fang",
        "horn",
        "frill",
        "skull",
        "bone",
        "tongue",
        "throat",
        "voice",
        "nose",
        "snout",
        "chin",
        "eye",
        "sight",
        "seer",
        "speaker",
        "singer",
        "song",
        "chanter",
        "howler",
        "chatter",
        "shrieker",
        "shriek",
        "jaw",
        "bite",
        "biter",
        "neck",
        "shoulder",
        "fin",
        "wing",
        "arm",
        "lifter",
        "grasp",
        "grabber",
        "hand",
        "paw",
        "foot",
        "finger",
        "toe",
        "thumb",
        "talon",
        "palm",
        "touch",
        "racer",
        "runner",
        "hoof",
        "fly",
        "flier",
        "swoop",
        "roar",
        "hiss",
        "hisser",
        "snarl",
        "dive",
        "diver",
        "rib",
        "chest",
        "back",
        "ridge",
        "leg",
        "legs",
        "tail",
        "beak",
        "walker",
        "lasher",
        "swisher",
        "carver",
        "kicker",
        "roarer",
        "crusher",
        "spike",
        "shaker",
        "charger",
        "hunter",
        "weaver",
        "crafter",
        "binder",
        "scribe",
        "muse",
        "snap",
        "snapper",
        "slayer",
        "stalker",
        "track",
        "tracker",
        "scar",
        "scarer",
        "fright",
        "killer",
        "death",
        "doom",
        "healer",
        "saver",
        "friend",
        "foe",
        "guardian",
        "thunder",
        "lightning",
        "cloud",
        "storm",
        "forger",
        "scale",
        "hair",
        "braid",
        "nape",
        "belly",
        "thief",
        "stealer",
        "reaper",
        "giver",
        "taker",
        "dancer",
        "player",
        "gambler",
        "twister",
        "turner",
        "painter",
        "dart",
        "drifter",
        "sting",
        "stinger",
        "venom",
        "spur",
        "ripper",
        "swallow",
        "devourer",
        "knight",
        "lady",
        "lord",
        "queen",
        "king",
        "master",
        "mistress",
        "prince",
        "princess",
        "duke",
        "dutchess",
        "samurai",
        "ninja",
        "knave",
        "slave",
        "servant",
        "sage",
        "wizard",
        "witch",
        "warlock",
        "warrior",
        "jester",
        "paladin",
        "bard",
        "trader",
        "sword",
        "shield",
        "knife",
        "dagger",
        "arrow",
        "bow",
        "fighter",
        "bane",
        "follower",
        "leader",
        "scourge",
        "watcher",
        "cat",
        "panther",
        "tiger",
        "cougar",
        "puma",
        "jaguar",
        "ocelot",
        "lynx",
        "lion",
        "leopard",
        "ferret",
        "weasel",
        "wolverine",
        "bear",
        "raccoon",
        "dog",
        "wolf",
        "kitten",
        "puppy",
        "cub",
        "fox",
        "hound",
        "terrier",
        "coyote",
        "hyena",
        "jackal",
        "pig",
        "horse",
        "donkey",
        "stallion",
        "mare",
        "zebra",
        "antelope",
        "gazelle",
        "deer",
        "buffalo",
        "bison",
        "boar",
        "elk",
        "whale",
        "dolphin",
        "shark",
        "fish",
        "minnow",
        "salmon",
        "ray",
        "fisher",
        "otter",
        "gull",
        "duck",
        "goose",
        "crow",
        "raven",
        "bird",
        "eagle",
        "raptor",
        "hawk",
        "falcon",
        "moose",
        "heron",
        "owl",
        "stork",
        "crane",
        "sparrow",
        "robin",
        "parrot",
        "cockatoo",
        "carp",
        "lizard",
        "gecko",
        "iguana",
        "snake",
        "python",
        "viper",
        "boa",
        "condor",
        "vulture",
        "spider",
        "fly",
        "scorpion",
        "heron",
        "oriole",
        "toucan",
        "bee",
        "wasp",
        "hornet",
        "rabbit",
        "bunny",
        "hare",
        "brow",
        "mustang",
        "ox",
        "piper",
        "soarer",
        "flasher",
        "moth",
        "mask",
        "hide",
        "hero",
        "antler",
        "chill",
        "chiller",
        "gem",
        "ogre",
        "myth",
        "elf",
        "fairy",
        "pixie",
        "dragon",
        "griffin",
        "unicorn",
        "pegasus",
        "sprite",
        "fancier",
        "chopper",
        "slicer",
        "skinner",
        "butterfly",
        "legend",
        "wanderer",
        "rover",
        "raver",
        "loon",
        "lancer",
        "glass",
        "glazer",
        "flame",
        "crystal",
        "lantern",
        "lighter",
        "cloak",
        "bell",
        "ringer",
        "keeper",
        "centaur",
        "bolt",
        "catcher",
        "whimsey",
        "quester",
        "rat",
        "mouse",
        "serpent",
        "wyrm",
        "gargoyle",
        "thorn",
        "whip",
        "rider",
        "spirit",
        "sentry",
        "bat",
        "beetle",
        "burn",
        "cowl",
        "stone",
        "gem",
        "collar",
        "mark",
        "grin",
        "scowl",
        "spear",
        "razor",
        "edge",
        "seeker",
        "jay",
        "ape",
        "monkey",
        "gorilla",
        "koala",
        "kangaroo",
        "yak",
        "sloth",
        "ant",
        "roach",
        "weed",
        "seed",
        "eater",
        "razor",
        "shirt",
        "face",
        "goat",
        "mind",
        "shift",
        "rider",
        "face",
        "mole",
        "vole",
        "pirate",
        "llama",
        "stag",
        "bug",
        "cap",
        "boot",
        "drop",
        "hugger",
        "sargent",
        "snagglefoot",
        "carpet",
        "curtain"
    ],
    "firstNamesMale": [
        "Jacob",
        "Mason",
        "Ethan",
        "Noah",
        "William",
        "Liam",
        "Jayden",
        "Michael",
        "Alexander",
        "Aiden",
        "Daniel",
        "Matthew",
        "Elijah",
        "James",
        "Anthony",
        "Benjamin",
        "Joshua",
        "Andrew",
        "David",
        "Joseph"
    ],
    "firstNamesFemale": [
        "Sophia",
        "Emma",
        "Isabella",
        "Olivia",
        "Ava",
        "Emily",
        "Abigail",
        "Mia",
        "Madison",
        "Elizabeth",
        "Chloe",
        "Ella",
        "Avery",
        "Addison",
        "Aubrey",
        "Lily",
        "Natalie",
        "Sofia",
        "Charlotte",
        "Zoey"
    ],
    "lastNames": [
        "Smith",
        "Johnson",
        "Williams",
        "Jones",
        "Brown",
        "Davis",
        "Miller",
        "Wilson",
        "Moore",
        "Taylor",
        "Anderson",
        "Thomas",
        "Jackson",
        "White",
        "Harris",
        "Martin",
        "Thompson",
        "Garcia",
        "Martinez",
        "Robinson"
    ],
    "domains": [
        "test.com",
        "test.net",
        "test.org",
        "example.com",
        "example.net",
        "example.org"
    ],
    "people": [
        "Adams",
        "Franklin",
        "Jackson",
        "Jefferson",
        "Lincoln",
        "Madison",
        "Washington",
        "Wilson"
    ],
    "streetTypes": [
        "St",
        "Ave",
        "Rd",
        "Blvd",
        "Trl",
        "Ter",
        "Rdg",
        "Pl",
        "Pkwy",
        "Ct",
        "Circle"
    ],
    "paragraphs": [
        "The Nellie, a cruising yawl, swung to her anchor without a flutter of the sails, and was at rest.",
        "The sun set; the dusk fell on the stream, and lights began to appear along the shore. The Chapman light–house, a three–legged thing erect on a mud–flat, shone strongly.",
        "He spoke of the happiness that was now certainly theirs, of the folly of not breaking sooner out of that magnificent prison of latter-day life, of the old romantic days that had passed from the world for ever.",
        "One dog rolled before him, well-nigh slashed in half; but a second had him by the thigh, a third gripped his collar be- hind, and a fourth had the blade of the sword between its teeth, tasting its own blood.",
        "She stared at him in astonishment, and as she read something of the significant hieroglyphic of his battered face, her lips whitened.",
        "He completely abandoned the child of his marriage with Adelaida Ivanovna, not from malice, nor because of his matrimoni- al grievances, but simply because he forgot him.",
        "It was at this time that the meeting, or, rather gathering of the mem- bers of this inharmonious family took place in the cell of the elder who had such an extraordinary influence on Alyosha.",
        "The secular cooling that must someday overtake our planet has already gone far indeed with our neighbour.",
        "Near it in the field, I remember, were three faint points of light, three telescopic stars infinitely remote, and all around it was the unfathomable darkness of empty space."
    ],
    "countries": [
        "Afghanistan",
        "Albania",
        "Algeria",
        "American Samoa",
        "Andorra",
        "Angola",
        "Antigua and Barbuda",
        "Argentina",
        "Armenia",
        "Aruba",
        "Australia",
        "Austria",
        "Azerbaijan",
        "Bahamas, The",
        "Bahrain",
        "Bangladesh",
        "Barbados",
        "Belarus",
        "Belgium",
        "Belize",
        "Benin",
        "Bermuda",
        "Bhutan",
        "Bolivia",
        "Bosnia and Herzegovina",
        "Botswana",
        "Brazil",
        "Brunei Darussalam",
        "Bulgaria",
        "Burkina Faso",
        "Burundi",
        "Cambodia",
        "Cameroon",
        "Canada",
        "Cape Verde",
        "Cayman Islands",
        "Central African Republic",
        "Chad",
        "Channel Islands",
        "Chile",
        "China",
        "Colombia",
        "Comoros",
        "Congo, Dem. Rep.",
        "Congo, Rep.",
        "Costa Rica",
        "Côte dIvoire",
        "Croatia",
        "Cuba",
        "Cyprus",
        "Czech Republic",
        "Denmark",
        "Djibouti",
        "Dominica",
        "Dominican Republic",
        "Ecuador",
        "Egypt, Arab Rep.",
        "El Salvador",
        "Equatorial Guinea",
        "Eritrea",
        "Estonia",
        "Ethiopia",
        "Faeroe Islands",
        "Fiji",
        "Finland",
        "France",
        "French Polynesia",
        "Gabon",
        "Gambia, The",
        "Georgia",
        "Germany",
        "Ghana",
        "Greece",
        "Greenland",
        "Grenada",
        "Guam",
        "Guatemala",
        "Guinea",
        "Guinea-Bissau",
        "Guyana",
        "Haiti",
        "Honduras",
        "Hong Kong, China",
        "Hungary",
        "Iceland",
        "India",
        "Indonesia",
        "Iran, Islamic Rep.",
        "Iraq",
        "Ireland",
        "Isle of Man",
        "Israel",
        "Italy",
        "Jamaica",
        "Japan",
        "Jordan",
        "Kazakhstan",
        "Kenya",
        "Kiribati",
        "Korea, Dem. Rep.",
        "Korea, Rep.",
        "Kuwait",
        "Kyrgyz Republic",
        "Lao PDR",
        "Latvia",
        "Lebanon",
        "Lesotho",
        "Liberia",
        "Libya",
        "Liechtenstein",
        "Lithuania",
        "Luxembourg",
        "Macao, China",
        "Macedonia, FYR",
        "Madagascar",
        "Malawi",
        "Malaysia",
        "Maldives",
        "Mali",
        "Malta",
        "Marshall Islands",
        "Mauritania",
        "Mauritius",
        "Mayotte",
        "Mexico",
        "Micronesia, Fed. Sts.",
        "Moldova",
        "Monaco",
        "Mongolia",
        "Montenegro",
        "Morocco",
        "Mozambique",
        "Myanmar",
        "Namibia",
        "Nepal",
        "Netherlands",
        "Netherlands Antilles",
        "New Caledonia",
        "New Zealand",
        "Nicaragua",
        "Niger",
        "Nigeria",
        "Northern Mariana Islands",
        "Norway",
        "Oman",
        "Pakistan",
        "Palau",
        "Panama",
        "Papua New Guinea",
        "Paraguay",
        "Peru",
        "Philippines",
        "Poland",
        "Portugal",
        "Puerto Rico",
        "Qatar",
        "Romania",
        "Russian Federation",
        "Rwanda",
        "Samoa",
        "San Marino",
        "São Tomé and Principe",
        "Saudi Arabia",
        "Senegal",
        "Serbia",
        "Seychelles",
        "Sierra Leone",
        "Singapore",
        "Slovak Republic",
        "Slovenia",
        "Solomon Islands",
        "Somalia",
        "South Africa",
        "Spain",
        "Sri Lanka",
        "St. Kitts and Nevis",
        "St. Lucia",
        "St. Vincent and the Grenadines",
        "Sudan",
        "Suriname",
        "Swaziland",
        "Sweden",
        "Switzerland",
        "Syrian Arab Republic",
        "Tajikistan",
        "Tanzania",
        "Thailand",
        "Timor-Leste",
        "Togo",
        "Tonga",
        "Trinidad and Tobago",
        "Tunisia",
        "Turkey",
        "Turkmenistan",
        "Uganda",
        "Ukraine",
        "United Arab Emirates",
        "United Kingdom",
        "United States",
        "Uruguay",
        "Uzbekistan",
        "Vanuatu",
        "Venezuela, RB",
        "Vietnam",
        "Virgin Islands (U.S.)",
        "West Bank and Gaza",
        "Yemen, Rep.",
        "Zambia",
        "Zimbabwe"
    ],
    "countriesThreeChars": [
        "AFG",
        "ALB",
        "DZA",
        "ASM",
        "ADO",
        "AGO",
        "ATG",
        "ARG",
        "ARM",
        "ABW",
        "AUS",
        "AUT",
        "AZE",
        "BHS",
        "BHR",
        "BGD",
        "BRB",
        "BLR",
        "BEL",
        "BLZ",
        "BEN",
        "BMU",
        "BTN",
        "BOL",
        "BIH",
        "BWA",
        "BRA",
        "BRN",
        "BGR",
        "BFA",
        "BDI",
        "KHM",
        "CMR",
        "CAN",
        "CPV",
        "CYM",
        "CAF",
        "TCD",
        "CHI",
        "CHL",
        "CHN",
        "COL",
        "COM",
        "ZAR",
        "COG",
        "CRI",
        "CIV",
        "HRV",
        "CUB",
        "CUW",
        "CYP",
        "CZE",
        "DNK",
        "DJI",
        "DMA",
        "DOM",
        "ECU",
        "EGY",
        "SLV",
        "GNQ",
        "ERI",
        "EST",
        "ETH",
        "FRO",
        "FJI",
        "FIN",
        "FRA",
        "PYF",
        "GAB",
        "GMB",
        "GEO",
        "DEU",
        "GHA",
        "GRC",
        "GRL",
        "GRD",
        "GUM",
        "GTM",
        "GIN",
        "GNB",
        "GUY",
        "HTI",
        "HND",
        "HKG",
        "HUN",
        "ISL",
        "IND",
        "IDN",
        "IRN",
        "IRQ",
        "IRL",
        "IMY",
        "ISR",
        "ITA",
        "JAM",
        "JPN",
        "JOR",
        "KAZ",
        "KEN",
        "KIR",
        "PRK",
        "KOR",
        "KSV",
        "KWT",
        "KGZ",
        "LAO",
        "LVA",
        "LBN",
        "LSO",
        "LBR",
        "LBY",
        "LIE",
        "LTU",
        "LUX",
        "MAC",
        "MKD",
        "MDG",
        "MWI",
        "MYS",
        "MDV",
        "MLI",
        "MLT",
        "MHL",
        "MRT",
        "MUS",
        "MEX",
        "FSM",
        "MDA",
        "MCO",
        "MNG",
        "MNE",
        "MAR",
        "MOZ",
        "MMR",
        "NAM",
        "NPL",
        "NLD",
        "NCL",
        "NZL",
        "NIC",
        "NER",
        "NGA",
        "MNP",
        "NOR",
        "OMN",
        "PAK",
        "PLW",
        "PAN",
        "PNG",
        "PRY",
        "PER",
        "PHL",
        "POL",
        "PRT",
        "PRI",
        "QAT",
        "ROM",
        "RUS",
        "RWA",
        "WSM",
        "SMR",
        "STP",
        "SAU",
        "SEN",
        "SRB",
        "SYC",
        "SLE",
        "SGP",
        "SXM",
        "SVK",
        "SVN",
        "SLB",
        "SOM",
        "ZAF",
        "SSD",
        "ESP",
        "LKA",
        "KNA",
        "LCA",
        "MAF",
        "VCT",
        "SDN",
        "SUR",
        "SWZ",
        "SWE",
        "CHE",
        "SYR",
        "TJK",
        "TZA",
        "THA",
        "TMP",
        "TGO",
        "TON",
        "TTO",
        "TUN",
        "TUR",
        "TKM",
        "TCA",
        "TUV",
        "UGA",
        "UKR",
        "ARE",
        "GBR",
        "USA",
        "URY",
        "UZB",
        "VUT",
        "VEN",
        "VNM",
        "VIR",
        "WBG",
        "YEM",
        "ZMB",
        "ZWE"
    ],
    "countriesTwoChars": [
        "AF",
        "AX",
        "AL",
        "DZ",
        "AS",
        "AD",
        "AO",
        "AI",
        "AQ",
        "AG",
        "AR",
        "AM",
        "AW",
        "AU",
        "AT",
        "AZ",
        "BS",
        "BH",
        "BD",
        "BB",
        "BY",
        "BE",
        "BZ",
        "BJ",
        "BM",
        "BT",
        "BO",
        "BQ",
        "BA",
        "BW",
        "BV",
        "BR",
        "IO",
        "BN",
        "BG",
        "BF",
        "BI",
        "KH",
        "CM",
        "CA",
        "CV",
        "KY",
        "CF",
        "TD",
        "CL",
        "CN",
        "CX",
        "CC",
        "CO",
        "KM",
        "CG",
        "CD",
        "CK",
        "CR",
        "CI",
        "HR",
        "CU",
        "CW",
        "CY",
        "CZ",
        "DK",
        "DJ",
        "DM",
        "DO",
        "EC",
        "EG",
        "SV",
        "GQ",
        "ER",
        "EE",
        "ET",
        "FK",
        "FO",
        "FJ",
        "FI",
        "FR",
        "GF",
        "PF",
        "TF",
        "GA",
        "GM",
        "GE",
        "DE",
        "GH",
        "GI",
        "GR",
        "GL",
        "GD",
        "GP",
        "GU",
        "GT",
        "GG",
        "GN",
        "GW",
        "GY",
        "HT",
        "HM",
        "VA",
        "HN",
        "HK",
        "HU",
        "IS",
        "IN",
        "ID",
        "IR",
        "IQ",
        "IE",
        "IM",
        "IL",
        "IT",
        "JM",
        "JP",
        "JE",
        "JO",
        "KZ",
        "KE",
        "KI",
        "KP",
        "KR",
        "KW",
        "KG",
        "LA",
        "LV",
        "LB",
        "LS",
        "LR",
        "LY",
        "LI",
        "LT",
        "LU",
        "MO",
        "MK",
        "MG",
        "MW",
        "MY",
        "MV",
        "ML",
        "MT",
        "MH",
        "MQ",
        "MR",
        "MU",
        "YT",
        "MX",
        "FM",
        "MD",
        "MC",
        "MN",
        "ME",
        "MS",
        "MA",
        "MZ",
        "MM",
        "NA",
        "NR",
        "NP",
        "NL",
        "NC",
        "NZ",
        "NI",
        "NE",
        "NG",
        "NU",
        "NF",
        "MP",
        "NO",
        "OM",
        "PK",
        "PW",
        "PS",
        "PA",
        "PG",
        "PY",
        "PE",
        "PH",
        "PN",
        "PL",
        "PT",
        "PR",
        "QA",
        "RE",
        "RO",
        "RU",
        "RW",
        "BL",
        "SH",
        "KN",
        "LC",
        "MF",
        "PM",
        "VC",
        "WS",
        "SM",
        "ST",
        "SA",
        "SN",
        "RS",
        "SC",
        "SL",
        "SG",
        "SX",
        "SK",
        "SI",
        "SB",
        "SO",
        "ZA",
        "GS",
        "SS",
        "ES",
        "LK",
        "SD",
        "SR",
        "SJ",
        "SZ",
        "SE",
        "CH",
        "SY",
        "TW",
        "TJ",
        "TZ",
        "TH",
        "TL",
        "TG",
        "TK",
        "TO",
        "TT",
        "TN",
        "TR",
        "TM",
        "TC",
        "TV",
        "UG",
        "UA",
        "AE",
        "GB",
        "US",
        "UM",
        "UY",
        "UZ",
        "VU",
        "VE",
        "VN",
        "VG",
        "VI",
        "WF",
        "EH",
        "YE",
        "ZM",
        "ZW"
    ],
    "currencies": [
        "AED",
        "AFN",
        "ALL",
        "AMD",
        "ANG",
        "AOA",
        "ARS",
        "AUD",
        "AWG",
        "AZN",
        "BAM",
        "BBD",
        "BDT",
        "BGN",
        "BHD",
        "BIF",
        "BMD",
        "BND",
        "BOB",
        "BOV",
        "BRL",
        "BSD",
        "BTN",
        "BWP",
        "BYR",
        "BZD",
        "CAD",
        "CDF",
        "CHE",
        "CHF",
        "CHW",
        "CLF",
        "CLP",
        "CNY",
        "COP",
        "COU",
        "CRC",
        "CUC",
        "CUP",
        "CVE",
        "CZK",
        "DJF",
        "DKK",
        "DOP",
        "DZD",
        "EGP",
        "ERN",
        "ETB",
        "EUR",
        "FJD",
        "FKP",
        "GBP",
        "GEL",
        "GHS",
        "GIP",
        "GMD",
        "GNF",
        "GTQ",
        "GYD",
        "HKD",
        "HNL",
        "HRK",
        "HTG",
        "HUF",
        "IDR",
        "ILS",
        "INR",
        "IQD",
        "IRR",
        "ISK",
        "JMD",
        "JOD",
        "JPY",
        "KES",
        "KGS",
        "KHR",
        "KMF",
        "KPW",
        "KRW",
        "KWD",
        "KYD",
        "KZT",
        "LAK",
        "LBP",
        "LKR",
        "LRD",
        "LSL",
        "LTL",
        "LVL",
        "LYD",
        "MAD",
        "MDL",
        "MGA",
        "MKD",
        "MMK",
        "MNT",
        "MOP",
        "MRO",
        "MUR",
        "MVR",
        "MWK",
        "MXN",
        "MXV",
        "MYR",
        "MZN",
        "NAD",
        "NGN",
        "NIO",
        "NOK",
        "NPR",
        "NZD",
        "OMR",
        "PAB",
        "PEN",
        "PGK",
        "PHP",
        "PKR",
        "PLN",
        "PYG",
        "QAR",
        "RON",
        "RSD",
        "RUB",
        "RWF",
        "SAR",
        "SBD",
        "SCR",
        "SDG",
        "SEK",
        "SGD",
        "SHP",
        "SLL",
        "SOS",
        "SRD",
        "SSP",
        "STD",
        "SYP",
        "SZL",
        "THB",
        "TJS",
        "TMT",
        "TND",
        "TOP",
        "TRY",
        "TTD",
        "TWD",
        "TZS",
        "UAH",
        "UGX",
        "USD",
        "USN",
        "USS",
        "UYI",
        "UYU",
        "UZS",
        "VEF",
        "VND",
        "VUV",
        "WST",
        "XAF",
        "XCD",
        "XDR",
        "XFU",
        "XOF",
        "XPF",
        "YER",
        "ZAR",
        "ZMW"
    ],
    "cities": [
        "Derby Center",
        "New Deal",
        "Cienega Springs",
        "Ransom Canyon",
        "Burrton",
        "Hoonah",
        "Lucien",
        "San Martin",
        "Buffalo City",
        "Skidaway Island",
        "Kingsbridge",
        "Berkhamsted",
        "Bury",
        "Brandwell",
        "Campden",
        "Plympton",
        "Baldock",
        "Northleach",
        "Newstead"
    ],
    "states": [
        "Alabama",
        "Alaska",
        "Arizona",
        "Arkansas",
        "California",
        "Colorado",
        "Connecticut",
        "Delaware",
        "Florida",
        "Georgia",
        "Hawaii",
        "Idaho",
        "Illinois",
        "Indiana",
        "Iowa",
        "Kansas",
        "Kentucky",
        "Louisiana",
        "Maine",
        "Maryland",
        "Massachusetts",
        "Michigan",
        "Minnesota",
        "Mississippi",
        "Missouri",
        "Montana",
        "Nebraska",
        "Nevada",
        "New Hampshire",
        "New Jersey",
        "New Mexico",
        "New York",
        "North Carolina",
        "North Dakota",
        "Ohio",
        "Oklahoma",
        "Oregon",
        "Pennsylvania",
        "Rhode Island",
        "South Carolina",
        "South Dakota",
        "Tennessee",
        "Texas",
        "Utah",
        "Vermont",
        "Virginia",
        "Washington",
        "West Virginia",
        "Wisconsin",
        "Wyoming"
    ],
    "statesSmall": [
        "AL",
        "AK",
        "AS",
        "AZ",
        "AR",
        "CA",
        "CO",
        "CT",
        "DE",
        "DC",
        "FM",
        "FL",
        "GA",
        "GU",
        "HI",
        "ID",
        "IL",
        "IN",
        "IA",
        "KS",
        "KY",
        "LA",
        "ME",
        "MH",
        "MD",
        "MA",
        "MI",
        "MN",
        "MS",
        "MO",
        "MT",
        "NE",
        "NV",
        "NH",
        "NJ",
        "NM",
        "NY",
        "NC",
        "ND",
        "MP",
        "OH",
        "OK",
        "OR",
        "PW",
        "PA",
        "PR",
        "RI",
        "SC",
        "SD",
        "TN",
        "TX",
        "UT",
        "VT",
        "VA",
        "VI",
        "WA",
        "DC",
        "WV",
        "WI",
        "WY"
    ],
    "days" : [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday"
    ],
    "months": [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
    ],
    "femaleTitles": [
        "Ms",
        "Miss",
        "Mrs"
    ],
    "maleTitles": [
        "Mr"
    ],
    "timezones": [
        "Africa/Abidjan",
        "Africa/Accra",
        "Africa/Addis_Ababa",
        "Africa/Algiers",
        "Africa/Asmara",
        "Africa/Asmera",
        "Africa/Bamako",
        "Africa/Bangui",
        "Africa/Banjul",
        "Africa/Bissau",
        "Africa/Blantyre",
        "Africa/Brazzaville",
        "Africa/Bujumbura",
        "Africa/Cairo",
        "Africa/Casablanca",
        "Africa/Ceuta",
        "Africa/Conakry",
        "Africa/Dakar",
        "Africa/Dar_es_Salaam",
        "Africa/Djibouti",
        "Africa/Douala",
        "Africa/El_Aaiun",
        "Africa/Freetown",
        "Africa/Gaborone",
        "Africa/Harare",
        "Africa/Johannesburg",
        "Africa/Juba",
        "Africa/Kampala",
        "Africa/Khartoum",
        "Africa/Kigali",
        "Africa/Kinshasa",
        "Africa/Lagos",
        "Africa/Libreville",
        "Africa/Lome",
        "Africa/Luanda",
        "Africa/Lubumbashi",
        "Africa/Lusaka",
        "Africa/Malabo",
        "Africa/Maputo",
        "Africa/Maseru",
        "Africa/Mbabane",
        "Africa/Mogadishu",
        "Africa/Monrovia",
        "Africa/Nairobi",
        "Africa/Ndjamena",
        "Africa/Niamey",
        "Africa/Nouakchott",
        "Africa/Ouagadougou",
        "Africa/Porto-Novo",
        "Africa/Sao_Tome",
        "Africa/Timbuktu",
        "Africa/Tripoli",
        "Africa/Tunis",
        "Africa/Windhoek",
        "America/Argentina/Buenos_Aires",
        "America/Argentina/Catamarca",
        "America/Argentina/ComodRivadavia",
        "America/Argentina/Cordoba",
        "America/Argentina/Jujuy",
        "America/Argentina/La_Rioja",
        "America/Argentina/Mendoza",
        "America/Argentina/Rio_Gallegos",
        "America/Argentina/Salta",
        "America/Argentina/San_Juan",
        "America/Argentina/San_Luis",
        "America/Argentina/Tucuman",
        "America/Argentina/Ushuaia",
        "America/Indiana/Indianapolis",
        "America/Indiana/Knox",
        "America/Indiana/Marengo",
        "America/Indiana/Petersburg",
        "America/Indiana/Tell_City",
        "America/Indiana/Vevay",
        "America/Indiana/Vincennes",
        "America/Indiana/Winamac",
        "America/Kentucky/Louisville",
        "America/Kentucky/Monticello",
        "America/North_Dakota/Beulah",
        "America/North_Dakota/Center",
        "America/North_Dakota/New_Salem",
        "America/Adak",
        "America/Anchorage",
        "America/Anguilla",
        "America/Antigua",
        "America/Araguaina",
        "America/Aruba",
        "America/Asuncion",
        "America/Atikokan",
        "America/Atka",
        "America/Bahia",
        "America/Bahia_Banderas",
        "America/Barbados",
        "America/Belem",
        "America/Belize",
        "America/Blanc-Sablon",
        "America/Boa_Vista",
        "America/Bogota",
        "America/Boise",
        "America/Buenos_Aires",
        "America/Cambridge_Bay",
        "America/Campo_Grande",
        "America/Cancun",
        "America/Caracas",
        "America/Catamarca",
        "America/Cayenne",
        "America/Cayman",
        "America/Chicago",
        "America/Chihuahua",
        "America/Coral_Harbour",
        "America/Cordoba",
        "America/Costa_Rica",
        "America/Creston",
        "America/Cuiaba",
        "America/Curacao",
        "America/Danmarkshavn",
        "America/Dawson",
        "America/Dawson_Creek",
        "America/Denver",
        "America/Detroit",
        "America/Dominica",
        "America/Edmonton",
        "America/Eirunepe",
        "America/El_Salvador",
        "America/Ensenada",
        "America/Fortaleza",
        "America/Fort_Nelson",
        "America/Fort_Wayne",
        "America/Glace_Bay",
        "America/Godthab",
        "America/Goose_Bay",
        "America/Grand_Turk",
        "America/Grenada",
        "America/Guadeloupe",
        "America/Guatemala",
        "America/Guayaquil",
        "America/Guyana",
        "America/Halifax",
        "America/Havana",
        "America/Hermosillo",
        "America/Indianapolis",
        "America/Inuvik",
        "America/Iqaluit",
        "America/Jamaica",
        "America/Jujuy",
        "America/Juneau",
        "America/Knox_IN",
        "America/Kralendijk",
        "America/La_Paz",
        "America/Lima",
        "America/Los_Angeles",
        "America/Louisville",
        "America/Lower_Princes",
        "America/Maceio",
        "America/Managua",
        "America/Manaus",
        "America/Marigot",
        "America/Martinique",
        "America/Matamoros",
        "America/Mazatlan",
        "America/Mendoza",
        "America/Menominee",
        "America/Merida",
        "America/Metlakatla",
        "America/Mexico_City",
        "America/Miquelon",
        "America/Moncton",
        "America/Monterrey",
        "America/Montevideo",
        "America/Montreal",
        "America/Montserrat",
        "America/Nassau",
        "America/New_York",
        "America/Nipigon",
        "America/Nome",
        "America/Noronha",
        "America/Ojinaga",
        "America/Panama",
        "America/Pangnirtung",
        "America/Paramaribo",
        "America/Phoenix",
        "America/Port-au-Prince",
        "America/Porto_Acre",
        "America/Port_of_Spain",
        "America/Porto_Velho",
        "America/Puerto_Rico",
        "America/Rainy_River",
        "America/Rankin_Inlet",
        "America/Recife",
        "America/Regina",
        "America/Resolute",
        "America/Rio_Branco",
        "America/Rosario",
        "America/Santa_Isabel",
        "America/Santarem",
        "America/Santiago",
        "America/Santo_Domingo",
        "America/Sao_Paulo",
        "America/Scoresbysund",
        "America/Shiprock",
        "America/Sitka",
        "America/St_Barthelemy",
        "America/St_Johns",
        "America/St_Kitts",
        "America/St_Lucia",
        "America/St_Thomas",
        "America/St_Vincent",
        "America/Swift_Current",
        "America/Tegucigalpa",
        "America/Thule",
        "America/Thunder_Bay",
        "America/Tijuana",
        "America/Toronto",
        "America/Tortola",
        "America/Vancouver",
        "America/Virgin",
        "America/Whitehorse",
        "America/Winnipeg",
        "America/Yakutat",
        "America/Yellowknife",
        "Antarctica/Casey",
        "Antarctica/Davis",
        "Antarctica/DumontDUrville",
        "Antarctica/Macquarie",
        "Antarctica/Mawson",
        "Antarctica/McMurdo",
        "Antarctica/Palmer",
        "Antarctica/Rothera",
        "Antarctica/South_Pole",
        "Antarctica/Syowa",
        "Antarctica/Troll",
        "Antarctica/Vostok",
        "Arctic/Longyearbyen",
        "Asia/Aden",
        "Asia/Almaty",
        "Asia/Amman",
        "Asia/Anadyr",
        "Asia/Aqtau",
        "Asia/Aqtobe",
        "Asia/Ashgabat",
        "Asia/Ashkhabad",
        "Asia/Atyrau",
        "Asia/Baghdad",
        "Asia/Bahrain",
        "Asia/Baku",
        "Asia/Bangkok",
        "Asia/Barnaul",
        "Asia/Beirut",
        "Asia/Bishkek",
        "Asia/Brunei",
        "Asia/Calcutta",
        "Asia/Chita",
        "Asia/Choibalsan",
        "Asia/Chongqing",
        "Asia/Chungking",
        "Asia/Colombo",
        "Asia/Dacca",
        "Asia/Damascus",
        "Asia/Dhaka",
        "Asia/Dili",
        "Asia/Dubai",
        "Asia/Dushanbe",
        "Asia/Famagusta",
        "Asia/Gaza",
        "Asia/Harbin",
        "Asia/Hebron",
        "Asia/Ho_Chi_Minh",
        "Asia/Hong_Kong",
        "Asia/Hovd",
        "Asia/Irkutsk",
        "Asia/Istanbul",
        "Asia/Jakarta",
        "Asia/Jayapura",
        "Asia/Jerusalem",
        "Asia/Kabul",
        "Asia/Kamchatka",
        "Asia/Karachi",
        "Asia/Kashgar",
        "Asia/Kathmandu",
        "Asia/Katmandu",
        "Asia/Khandyga",
        "Asia/Kolkata",
        "Asia/Krasnoyarsk",
        "Asia/Kuala_Lumpur",
        "Asia/Kuching",
        "Asia/Kuwait",
        "Asia/Macao",
        "Asia/Macau",
        "Asia/Magadan",
        "Asia/Makassar",
        "Asia/Manila",
        "Asia/Muscat",
        "Asia/Nicosia",
        "Asia/Novokuznetsk",
        "Asia/Novosibirsk",
        "Asia/Omsk",
        "Asia/Oral",
        "Asia/Phnom_Penh",
        "Asia/Pontianak",
        "Asia/Pyongyang",
        "Asia/Qatar",
        "Asia/Qyzylorda",
        "Asia/Rangoon",
        "Asia/Riyadh",
        "Asia/Saigon",
        "Asia/Sakhalin",
        "Asia/Samarkand",
        "Asia/Seoul",
        "Asia/Shanghai",
        "Asia/Singapore",
        "Asia/Srednekolymsk",
        "Asia/Taipei",
        "Asia/Tashkent",
        "Asia/Tbilisi",
        "Asia/Tehran",
        "Asia/Tel_Aviv",
        "Asia/Thimbu",
        "Asia/Thimphu",
        "Asia/Tokyo",
        "Asia/Tomsk",
        "Asia/Ujung_Pandang",
        "Asia/Ulaanbaatar",
        "Asia/Ulan_Bator",
        "Asia/Urumqi",
        "Asia/Ust-Nera",
        "Asia/Vientiane",
        "Asia/Vladivostok",
        "Asia/Yakutsk",
        "Asia/Yangon",
        "Asia/Yekaterinburg",
        "Asia/Yerevan",
        "Atlantic/Azores",
        "Atlantic/Bermuda",
        "Atlantic/Canary",
        "Atlantic/Cape_Verde",
        "Atlantic/Faeroe",
        "Atlantic/Faroe",
        "Atlantic/Jan_Mayen",
        "Atlantic/Madeira",
        "Atlantic/Reykjavik",
        "Atlantic/South_Georgia",
        "Atlantic/Stanley",
        "Atlantic/St_Helena",
        "Australia/ACT",
        "Australia/Adelaide",
        "Australia/Brisbane",
        "Australia/Broken_Hill",
        "Australia/Canberra",
        "Australia/Currie",
        "Australia/Darwin",
        "Australia/Eucla",
        "Australia/Hobart",
        "Australia/LHI",
        "Australia/Lindeman",
        "Australia/Lord_Howe",
        "Australia/Melbourne",
        "Australia/North",
        "Australia/NSW",
        "Australia/Perth",
        "Australia/Queensland",
        "Australia/South",
        "Australia/Sydney",
        "Australia/Tasmania",
        "Australia/Victoria",
        "Australia/West",
        "Australia/Yancowinna",
        "Brazil/Acre",
        "Brazil/DeNoronha",
        "Brazil/East",
        "Brazil/West",
        "Canada/Atlantic",
        "Canada/Central",
        "Canada/Eastern",
        "Canada/East-Saskatchewan",
        "Canada/Mountain",
        "Canada/Newfoundland",
        "Canada/Pacific",
        "Canada/Saskatchewan",
        "Canada/Yukon",
        "Chile/Continental",
        "Chile/EasterIsland",
        "Etc/GMT",
        "Etc/GMT0",
        "Etc/GMT-0",
        "Etc/GMT+0",
        "Etc/GMT-1",
        "Etc/GMT+1",
        "Etc/GMT-10",
        "Etc/GMT+10",
        "Etc/GMT-11",
        "Etc/GMT+11",
        "Etc/GMT-12",
        "Etc/GMT+12",
        "Etc/GMT-13",
        "Etc/GMT-14",
        "Etc/GMT-2",
        "Etc/GMT+2",
        "Etc/GMT-3",
        "Etc/GMT+3",
        "Etc/GMT-4",
        "Etc/GMT+4",
        "Etc/GMT-5",
        "Etc/GMT+5",
        "Etc/GMT-6",
        "Etc/GMT+6",
        "Etc/GMT-7",
        "Etc/GMT+7",
        "Etc/GMT-8",
        "Etc/GMT+8",
        "Etc/GMT-9",
        "Etc/GMT+9",
        "Etc/Greenwich",
        "Etc/UCT",
        "Etc/Universal",
        "Etc/UTC",
        "Etc/Zulu",
        "Europe/Amsterdam",
        "Europe/Andorra",
        "Europe/Astrakhan",
        "Europe/Athens",
        "Europe/Belfast",
        "Europe/Belgrade",
        "Europe/Berlin",
        "Europe/Bratislava",
        "Europe/Brussels",
        "Europe/Bucharest",
        "Europe/Budapest",
        "Europe/Busingen",
        "Europe/Chisinau",
        "Europe/Copenhagen",
        "Europe/Dublin",
        "Europe/Gibraltar",
        "Europe/Guernsey",
        "Europe/Helsinki",
        "Europe/Isle_of_Man",
        "Europe/Istanbul",
        "Europe/Jersey",
        "Europe/Kaliningrad",
        "Europe/Kiev",
        "Europe/Kirov",
        "Europe/Lisbon",
        "Europe/Ljubljana",
        "Europe/London",
        "Europe/Luxembourg",
        "Europe/Madrid",
        "Europe/Malta",
        "Europe/Mariehamn",
        "Europe/Minsk",
        "Europe/Monaco",
        "Europe/Moscow",
        "Europe/Nicosia",
        "Europe/Oslo",
        "Europe/Paris",
        "Europe/Podgorica",
        "Europe/Prague",
        "Europe/Riga",
        "Europe/Rome",
        "Europe/Samara",
        "Europe/San_Marino",
        "Europe/Sarajevo",
        "Europe/Saratov",
        "Europe/Simferopol",
        "Europe/Skopje",
        "Europe/Sofia",
        "Europe/Stockholm",
        "Europe/Tallinn",
        "Europe/Tirane",
        "Europe/Tiraspol",
        "Europe/Ulyanovsk",
        "Europe/Uzhgorod",
        "Europe/Vaduz",
        "Europe/Vatican",
        "Europe/Vienna",
        "Europe/Vilnius",
        "Europe/Volgograd",
        "Europe/Warsaw",
        "Europe/Zagreb",
        "Europe/Zaporozhye",
        "Europe/Zurich",
        "Indian/Antananarivo",
        "Indian/Chagos",
        "Indian/Christmas",
        "Indian/Cocos",
        "Indian/Comoro",
        "Indian/Kerguelen",
        "Indian/Mahe",
        "Indian/Maldives",
        "Indian/Mauritius",
        "Indian/Mayotte",
        "Indian/Reunion",
        "Mexico/BajaNorte",
        "Mexico/BajaSur",
        "Mexico/General",
        "Pacific/Apia",
        "Pacific/Auckland",
        "Pacific/Bougainville",
        "Pacific/Chatham",
        "Pacific/Chuuk",
        "Pacific/Easter",
        "Pacific/Efate",
        "Pacific/Enderbury",
        "Pacific/Fakaofo",
        "Pacific/Fiji",
        "Pacific/Funafuti",
        "Pacific/Galapagos",
        "Pacific/Gambier",
        "Pacific/Guadalcanal",
        "Pacific/Guam",
        "Pacific/Honolulu",
        "Pacific/Johnston",
        "Pacific/Kiritimati",
        "Pacific/Kosrae",
        "Pacific/Kwajalein",
        "Pacific/Majuro",
        "Pacific/Marquesas",
        "Pacific/Midway",
        "Pacific/Nauru",
        "Pacific/Niue",
        "Pacific/Norfolk",
        "Pacific/Noumea",
        "Pacific/Pago_Pago",
        "Pacific/Palau",
        "Pacific/Pitcairn",
        "Pacific/Pohnpei",
        "Pacific/Ponape",
        "Pacific/Port_Moresby",
        "Pacific/Rarotonga",
        "Pacific/Saipan",
        "Pacific/Samoa",
        "Pacific/Tahiti",
        "Pacific/Tarawa",
        "Pacific/Tongatapu",
        "Pacific/Truk",
        "Pacific/Wake",
        "Pacific/Wallis",
        "Pacific/Yap",
        "US/Alaska",
        "US/Aleutian",
        "US/Arizona",
        "US/Central",
        "US/Eastern",
        "US/East-Indiana",
        "US/Hawaii",
        "US/Indiana-Starke",
        "US/Michigan",
        "US/Mountain",
        "US/Pacific",
        "US/Pacific-New",
        "US/Samoa",
        "CET",
        "CST6CDT",
        "Cuba",
        "EET",
        "Egypt",
        "Eire",
        "EST",
        "EST5EDT",
        "Factory",
        "GB",
        "GB-Eire",
        "GMT",
        "GMT0",
        "GMT-0",
        "GMT+0",
        "Greenwich",
        "Hongkong",
        "HST",
        "Iceland",
        "Iran",
        "Israel",
        "Jamaica",
        "Japan",
        "Kwajalein",
        "Libya",
        "MET",
        "MST",
        "MST7MDT",
        "Navajo",
        "NZ",
        "NZ-CHAT",
        "Poland",
        "Portugal",
        "PRC",
        "PST8PDT",
        "ROC",
        "ROK",
        "Singapore",
        "Turkey",
        "UCT",
        "Universal",
        "UTC",
        "WET",
        "W-SU",
        "Zulu"
    ],
    "userAgents": [
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/28.0.1469.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2869.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3191.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0",
        "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0",
        "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; WOW64; Trident/5.0)",
        "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
        "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; MALNJS; rv:11.0) like Gecko",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55",
        "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.91 Safari/537.36 Vivaldi/1.92.917.39",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.49 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
        "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML like Gecko) Chrome/22.0.1229.56 Safari/537.4",
        "Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
        "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/60.0.3112.78 Chrome/60.0.3112.78 Safari/537.36",
        "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0",
        "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.166 Safari/537.36 OPR/20.0.1396.73172",
        "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36 OPR/40.0.2308.62",
        "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36",
        "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch)",
        "Opera/10.61 (J2ME/MIDP; Opera Mini/5.1.21219/19.999; en-US; rv:1.9.3a5) WebKit/534.5 Presto/2.6.30",
        "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1",
        "Mozilla/5.0 (Linux; Android 8.0.0; Pixel XL Build/OPR6.170623.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.107 Mobile Safari/537.36",
        "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Mobile Safari/537.36 Edge/12.0",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14",
        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
    ]
}`)


================================================
FILE: vendor/github.com/Pallinder/go-randomdata/postalcodes.go
================================================
package randomdata

import (
	"fmt"
	"math"
	"math/rand"
	"strings"
)

// Supported formats obtained from:
// * http://www.geopostcodes.com/GeoPC_Postal_codes_formats

// PostalCode yields a random postal/zip code for the given 2-letter country code.
//
// These codes are not guaranteed to refer to actually locations.
// They merely follow the correct format as far as letters and digits goes.
// Where possible, the function enforces valid ranges of letters and digits.
func PostalCode(countrycode string) string {
	switch strings.ToUpper(countrycode) {
	case "LS", "MG", "IS", "OM", "PG":
		return Digits(3)

	case "AM", "GE", "NZ", "NE", "NO", "PY", "ZA", "MZ", "SJ", "LI", "AL",
		"BD", "CV", "GL":
		return Digits(4)

	case "DZ", "BA", "KH", "DO", "EG", "EE", "GP", "GT", "ID", "IL", "JO",
		"KW", "MQ", "MX", "LK", "SD", "TR", "UA", "US", "CR", "IQ", "KV", "MY",
		"MN", "ME", "PK", "SM", "MA", "UY", "EH", "ZM":
		return Digits(5)

	case "BY", "CN", "IN", "KZ", "KG", "NG", "RO", "RU", "SG", "TJ", "TM", "UZ", "VN":
		return Digits(6)

	case "CL":
		return Digits(7)

	case "IR":
		return Digits(10)

	case "FO":
		return "FO " + Digits(3)

	case "AF":
		return BoundedDigits(2, 10, 43) + BoundedDigits(2, 1, 99)

	case "AU", "AT", "BE", "BG", "CY", "DK", "ET", "GW", "HU", "LR", "MK", "PH",
		"CH", "TN", "VE":
		return BoundedDigits(4, 1000, 9999)

	case "SV":
		return "CP " + BoundedDigits(4, 1000, 9999)

	case "HT":
		return "HT" + Digits(4)

	case "LB":
		return Digits(4) + " " + Digits(4)

	case "LU":
		return BoundedDigits(4, 6600, 6999)

	case "MD":
		return "MD-" + BoundedDigits(4, 1000, 9999)

	case "HR":
		return "HR-" + Digits(5)

	case "CU":
		return "CP " + BoundedDigits(5, 10000, 99999)

	case "FI":
		// Last digit is usually 0 but can, in some cases, be 1 or 5.
		switch rand.Intn(2) {
		case 0:
			return Digits(4) + "0"
		case 1:
			return Digits(4) + "1"
		}

		return Digits(4) + "5"

	case "FR", "GF", "PF", "YT", "MC", "RE", "BL", "MF", "PM", "RS", "TH":
		return BoundedDigits(5, 10000, 99999)

	case "DE":
		return BoundedDigits(5, 1000, 99999)

	case "GR":
		return BoundedDigits(3, 100, 999) + " " + Digits(2)

	case "HN":
		return "CM" + Digits(4)

	case "IT", "VA":
		return BoundedDigits(5, 10, 99999)

	case "KE":
		return BoundedDigits(5, 100, 99999)

	case "LA":
		return BoundedDigits(5, 1000, 99999)

	case "MH":
		return BoundedDigits(5, 96960, 96970)

	case "FM":
		return "FM" + BoundedDigits(5, 96941, 96944)

	case "MM":
		return BoundedDigits(2, 1, 14) + Digits(3)

	case "NP":
		return BoundedDigits(5, 10700, 56311)

	case "NC":
		return "98" + Digits(3)

	case "PW":
		return "PW96940"

	case "PR":
		return "PR " + Digits(5)

	case "SA":
		return BoundedDigits(5, 10000, 99999) + "-" + BoundedDigits(4, 1000, 9999)

	case "ES":
		return BoundedDigits(2, 1, 52) + BoundedDigits(3, 100, 999)

	case "WF":
		return "986" + Digits(2)

	case "SZ":
		return Letters(1) + Digits(3)

	case "BM":
		return Letters(2) + Digits(2)

	case "AD":
		return Letters(2) + Digits(3)

	case "BN", "AZ", "VG", "PE":
		return Letters(2) + Digits(4)

	case "BB":
		return Letters(2) + Digits(5)

	case "EC":
		return Letters(2) + Digits(6)

	case "MT":
		return Letters(3) + Digits(4)

	case "JM":
		return "JM" + Letters(3) + Digits(2)

	case "AR":
		return Letters(1) + Digits(4) + Letters(3)

	case "CA":
		return Letters(1) + Digits(1) + Letters(1) + Digits(1) + Letters(1) + Digits(1)

	case "FK", "TC":
		return Letters(4) + Digits(1) + Letters(2)

	case "GG", "IM", "JE", "GB":
		return Letters(2) + Digits(2) + Letters(2)

	case "KY":
		return Letters(2) + Digits(1) + "-" + Digits(4)

	case "JP":
		return Digits(3) + "-" + Digits(4)

	case "LV", "SI":
		return Letters(2) + "-" + Digits(4)

	case "LT":
		return Letters(2) + "-" + Digits(5)

	case "SE", "TW":
		return Digits(5)

	case "MV":
		return Digits(2) + "-" + Digits(2)

	case "PL":
		return Digits(2) + "-" + Digits(3)

	case "NI":
		return Digits(3) + "-" + Digits(3) + "-" + Digits(1)

	case "KR":
		return Digits(3) + "-" + Digits(3)

	case "PT":
		return Digits(4) + "-" + Digits(3)

	case "NL":
		return Digits(4) + Letters(2)

	case "BR":
		return Digits(5) + "-" + Digits(3)
	}

	return ""
}

// Letters generates a string of N random leters (A-Z).
func Letters(letters int) string {
	list := make([]byte, letters)

	for i := range list {
		list[i] = byte(rand.Intn('Z'-'A') + 'A')
	}

	return string(list)
}

// Digits generates a string of N random digits, padded with zeros if necessary.
func Digits(digits int) string {
	max := int(math.Pow10(digits)) - 1
	num := rand.Intn(max)
	format := fmt.Sprintf("%%0%dd", digits)
	return fmt.Sprintf(format, num)
}

// BoundedDigits generates a string of N random digits, padded with zeros if necessary.
// The output is restricted to the given range.
func BoundedDigits(digits, low, high int) string {
	if low > high {
		low, high = high, low
	}

	max := int(math.Pow10(digits)) - 1
	if high > max {
		high = max
	}

	num := rand.Intn(high-low+1) + low
	format := fmt.Sprintf("%%0%dd", digits)
	return fmt.Sprintf(format, num)
}


================================================
FILE: vendor/github.com/Pallinder/go-randomdata/random_data.go
================================================
// Package randomdata implements a bunch of simple ways to generate (pseudo) random data
package randomdata

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"net"
	"strconv"
	"strings"
	"time"
	"unicode"
)

const (
	Male         int = 0
	Female       int = 1
	RandomGender int = 2
)

const (
	Small int = 0
	Large int = 1
)

const (
	FullCountry      = 0
	TwoCharCountry   = 1
	ThreeCharCountry = 2
)

const (
	DateInputLayout  = "2006-01-02"
	DateOutputLayout = "Monday 2 Jan 2006"
)

type jsonContent struct {
	Adjectives          []string `json:"adjectives"`
	Nouns               []string `json:"nouns"`
	FirstNamesFemale    []string `json:"firstNamesFemale"`
	FirstNamesMale      []string `json:"firstNamesMale"`
	LastNames           []string `json:"lastNames"`
	Domains             []string `json:"domains"`
	People              []string `json:"people"`
	StreetTypes         []string `json:"streetTypes"` // Taken from https://github.com/tomharris/random_data/blob/master/lib/random_data/locations.rb
	Paragraphs          []string `json:"paragraphs"`  // Taken from feedbooks.com
	Countries           []string `json:"countries"`   // Fetched from the world bank at http://siteresources.worldbank.org/DATASTATISTICS/Resources/CLASS.XLS
	CountriesThreeChars []string `json:"countriesThreeChars"`
	CountriesTwoChars   []string `json:"countriesTwoChars"`
	Currencies          []string `json:"currencies"` //https://github.com/OpenBookPrices/country-data
	Cities              []string `json:"cities"`
	States              []string `json:"states"`
	StatesSmall         []string `json:"statesSmall"`
	Days                []string `json:"days"`
	Months              []string `json:"months"`
	FemaleTitles        []string `json:"femaleTitles"`
	MaleTitles          []string `json:"maleTitles"`
	Timezones           []string `json:"timezones"`  // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
	UserAgents          []string `json:"userAgents"` // http://techpatterns.com/downloads/firefox/useragentswitcher.xml
}

var jsonData = jsonContent{}

func init() {
	jsonData = jsonContent{}

	err := json.Unmarshal(data, &jsonData)

	if err != nil {
		log.Fatal(err)
	}
}

func seedAndReturnRandom(n int) int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(n)
}

func seedAndReturnRandomFloat() float64 {
	rand.Seed(time.Now().UnixNano())
	return rand.Float64()
}

// Returns a random part of a slice
func randomFrom(source []string) string {
	return source[seedAndReturnRandom(len(source))]
}

// Title returns a random title, gender decides the gender of the name
func Title(gender int) string {
	var title = ""
	switch gender {
	case Male:
		title = randomFrom(jsonData.MaleTitles)
		break
	case Female:
		title = randomFrom(jsonData.FemaleTitles)
		break
	default:
		rand.Seed(time.Now().UnixNano())
		title = FirstName(rand.Intn(2))
		break
	}
	return title
}

// FirstName returns a random first name, gender decides the gender of the name
func FirstName(gender int) string {
	var name = ""
	switch gender {
	case Male:
		name = randomFrom(jsonData.FirstNamesMale)
		break
	case Female:
		name = randomFrom(jsonData.FirstNamesFemale)
		break
	default:
		rand.Seed(time.Now().UnixNano())
		name = FirstName(rand.Intn(2))
		break
	}
	return name
}

// LastName returns a random last name
func LastName() string {
	return randomFrom(jsonData.LastNames)
}

// FullName returns a combination of FirstName LastName randomized, gender decides the gender of the name
func FullName(gender int) string {
	return FirstName(gender) + " " + LastName()
}

// Email returns a random email
func Email() string {
	return strings.ToLower(FirstName(RandomGender)+LastName()) + StringNumberExt(1, "", 3) + "@" + randomFrom(jsonData.Domains)
}

// Country returns a random country, countryStyle decides what kind of format the returned country will have
func Country(countryStyle int64) string {
	country := ""
	switch countryStyle {

	default:

	case FullCountry:
		country = randomFrom(jsonData.Countries)
		break

	case TwoCharCountry:
		country = randomFrom(jsonData.CountriesTwoChars)
		break

	case ThreeCharCountry:
		country = randomFrom(jsonData.CountriesThreeChars)
		break
	}
	return country
}

// Currency returns a random currency under ISO 4217 format
func Currency() string {
	return randomFrom(jsonData.Currencies)
}

// City returns a random city
func City() string {
	return randomFrom(jsonData.Cities)
}

// State returns a random american state
func State(typeOfState int) string {
	if typeOfState == Small {
		return randomFrom(jsonData.StatesSmall)
	}
	return randomFrom(jsonData.States)
}

// Street returns a random fake street name
func Street() string {
	return fmt.Sprintf("%s %s", randomFrom(jsonData.People), randomFrom(jsonData.StreetTypes))
}

// Address returns an american style address
func Address() string {
	return fmt.Sprintf("%d %s,\n%s, %s, %s", Number(100), Street(), City(), State(Small), PostalCode("US"))
}

// Paragraph returns a random paragraph
func Paragraph() string {
	return randomFrom(jsonData.Paragraphs)
}

// Number returns a random number, if only one integer is supplied it is treated as the max value to return
// if a second argument is supplied it returns a number between (and including) the two numbers
func Number(numberRange ...int) int {
	nr := 0
	rand.Seed(time.Now().UnixNano())
	if len(numberRange) > 1 {
		nr = 1
		nr = seedAndReturnRandom(numberRange[1]-numberRange[0]) + numberRange[0]
	} else {
		nr = seedAndReturnRandom(numberRange[0])
	}
	return nr
}

func Decimal(numberRange ...int) float64 {
	nr := 0.0
	rand.Seed(time.Now().UnixNano())
	if len(numberRange) > 1 {
		nr = 1.0
		nr = seedAndReturnRandomFloat()*(float64(numberRange[1])-float64(numberRange[0])) + float64(numberRange[0])
	} else {
		nr = seedAndReturnRandomFloat() * float64(numberRange[0])
	}

	if len(numberRange) > 2 {
		sf := strconv.FormatFloat(nr, 'f', numberRange[2], 64)
		nr, _ = strconv.ParseFloat(sf, 64)
	}
	return nr
}

func StringNumberExt(numberPairs int, separator string, numberOfDigits int) string {
	numberString := ""

	for i := 0; i < numberPairs; i++ {
		for d := 0; d < numberOfDigits; d++ {
			numberString += fmt.Sprintf("%d", Number(0, 9))
		}

		if i+1 != numberPairs {
			numberString += separator
		}
	}

	return numberString
}

// StringNumber returns a random number as a string
func StringNumber(numberPairs int, separator string) string {
	return StringNumberExt(numberPairs, separator, 2)
}

// StringSample returns a random string from a list of strings
func StringSample(stringList ...string) string {
	str := ""
	if len(stringList) > 0 {
		str = stringList[Number(0, len(stringList))]
	}
	return str
}

func Boolean() bool {
	nr := seedAndReturnRandom(2)
	return nr != 0
}

// Noun returns a random noun
func Noun() string {
	return randomFrom(jsonData.Nouns)
}

// Adjective returns a random adjective
func Adjective() string {
	return randomFrom(jsonData.Adjectives)
}

func uppercaseFirstLetter(word string) string {
	a := []rune(word)
	a[0] = unicode.ToUpper(a[0])
	return string(a)
}

func lowercaseFirstLetter(word string) string {
	a := []rune(word)
	a[0] = unicode.ToLower(a[0])
	return string(a)
}

// SillyName returns a silly name, useful for randomizing naming of things
func SillyName() string {
	return uppercaseFirstLetter(Noun()) + Adjective()
}

// IpV4Address returns a valid IPv4 address as string
func IpV4Address() string {
	blocks := []string{}
	for i := 0; i < 4; i++ {
		number := seedAndReturnRandom(255)
		blocks = append(blocks, strconv.Itoa(number))
	}

	return strings.Join(blocks, ".")
}

// IpV6Address returns a valid IPv6 address as net.IP
func IpV6Address() string {
	var ip net.IP
	for i := 0; i < net.IPv6len; i++ {
		number := uint8(seedAndReturnRandom(255))
		ip = append(ip, number)
	}
	return ip.String()
}

// MacAddress returns an mac address string
func MacAddress() string {
	blocks := []string{}
	for i := 0; i < 6; i++ {
		number := fmt.Sprintf("%02x", seedAndReturnRandom(255))
		blocks = append(blocks, number)
	}

	return strings.Join(blocks, ":")
}

// Day returns random day
func Day() string {
	return randomFrom(jsonData.Days)
}

// Month returns random month
func Month() string {
	return randomFrom(jsonData.Months)
}

// FullDate returns full date
func FullDate() string {
	timestamp := time.Now()
	day := Day()
	month := Month()
	year := timestamp.Year()
	fullDate := day + " " + strconv.Itoa(Number(1, 30)) + " " + month[0:3] + " " + strconv.Itoa(year)
	return fullDate
}

// FullDateInRange returns a date string within a given range, given in the format "2006-01-02".
// If no argument is supplied it will return the result of randomdata.FullDate().
// If only one argument is supplied it is treated as the max date to return.
// If a second argument is supplied it returns a date between (and including) the two dates.
// Returned date is in format "Monday 2 Jan 2006".
func FullDateInRange(dateRange ...string) string {
	var (
		min        time.Time
		max        time.Time
		duration   int
		dateString string
	)
	if len(dateRange) == 1 {
		max, _ = time.Parse(DateInputLayout, dateRange[0])
	} else if len(dateRange) == 2 {
		min, _ = time.Parse(DateInputLayout, dateRange[0])
		max, _ = time.Parse(DateInputLayout, dateRange[1])
	}
	if !max.IsZero() && max.After(min) {
		duration = Number(int(max.Sub(min))) * -1
		dateString = max.Add(time.Duration(duration)).Format(DateOutputLayout)
	} else if !max.IsZero() && !max.After(min) {
		dateString = max.Format(DateOutputLayout)
	} else {
		dateString = FullDate()
	}
	return dateString
}

func Timezone() string {
	return randomFrom(jsonData.Timezones)
}

func UserAgentString() string {
	return randomFrom(jsonData.UserAgents)
}


================================================
FILE: vendor/github.com/elazarl/go-bindata-assetfs/LICENSE
================================================
Copyright (c) 2014, Elazar Leibovich
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: vendor/github.com/elazarl/go-bindata-assetfs/README.md
================================================
# go-bindata-assetfs

Serve embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/http`.

[GoDoc](http://godoc.org/github.com/elazarl/go-bindata-assetfs)

### Installation

Install with

    $ go get github.com/jteeuwen/go-bindata/...
    $ go get github.com/elazarl/go-bindata-assetfs/...

### Creating embedded data

Usage is identical to [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) usage,
instead of running `go-bindata` run `go-bindata-assetfs`.

The tool will create a `bindata_assetfs.go` file, which contains the embedded data.

A typical use case is

    $ go-bindata-assetfs data/...

### Using assetFS in your code

The generated file provides an `assetFS()` function that returns a `http.Filesystem`
wrapping the embedded files. What you usually want to do is:

    http.Handle("/", http.FileServer(assetFS()))

This would run an HTTP server serving the embedded files.

## Without running binary tool

You can always just run the `go-bindata` tool, and then

use

     import "github.com/elazarl/go-bindata-assetfs"
     ...
     http.Handle("/",
        http.FileServer(
        &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo, Prefix: "data"}))

to serve files embedded from the `data` directory.


================================================
FILE: vendor/github.com/elazarl/go-bindata-assetfs/assetfs.go
================================================
package assetfs

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

var (
	defaultFileTimestamp = time.Now()
)

// FakeFile implements os.FileInfo interface for a given path and size
type FakeFile struct {
	// Path is the path of this file
	Path string
	// Dir marks of the path is a directory
	Dir bool
	// Len is the length of the fake file, zero if it is a directory
	Len int64
	// Timestamp is the ModTime of this file
	Timestamp time.Time
}

func (f *FakeFile) Name() string {
	_, name := filepath.Split(f.Path)
	return name
}

func (f *FakeFile) Mode() os.FileMode {
	mode := os.FileMode(0644)
	if f.Dir {
		return mode | os.ModeDir
	}
	return mode
}

func (f *FakeFile) ModTime() time.Time {
	return f.Timestamp
}

func (f *FakeFile) Size() int64 {
	return f.Len
}

func (f *FakeFile) IsDir() bool {
	return f.Mode().IsDir()
}

func (f *FakeFile) Sys() interface{} {
	return nil
}

// AssetFile implements http.File interface for a no-directory file with content
type AssetFile struct {
	*bytes.Reader
	io.Closer
	FakeFile
}

func NewAssetFile(name string, content []byte, timestamp time.Time) *AssetFile {
	if timestamp.IsZero() {
		timestamp = defaultFileTimestamp
	}
	return &AssetFile{
		bytes.NewReader(content),
		ioutil.NopCloser(nil),
		FakeFile{name, false, int64(len(content)), timestamp}}
}

func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, errors.New("not a directory")
}

func (f *AssetFile) Size() int64 {
	return f.FakeFile.Size()
}

func (f *AssetFile) Stat() (os.FileInfo, error) {
	return f, nil
}

// AssetDirectory implements http.File interface for a directory
type AssetDirectory struct {
	AssetFile
	ChildrenRead int
	Children     []os.FileInfo
}

func NewAssetDirectory(name string, children []string, fs *AssetFS) *AssetDirectory {
	fileinfos := make([]os.FileInfo, 0, len(children))
	for _, child := range children {
		_, err := fs.AssetDir(filepath.Join(name, child))
		fileinfos = append(fileinfos, &FakeFile{child, err == nil, 0, time.Time{}})
	}
	return &AssetDirectory{
		AssetFile{
			bytes.NewReader(nil),
			ioutil.NopCloser(nil),
			FakeFile{name, true, 0, time.Time{}},
		},
		0,
		fileinfos}
}

func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
	if count <= 0 {
		return f.Children, nil
	}
	if f.ChildrenRead+count > len(f.Children) {
		count = len(f.Children) - f.ChildrenRead
	}
	rv := f.Children[f.ChildrenRead : f.ChildrenRead+count]
	f.ChildrenRead += count
	return rv, nil
}

func (f *AssetDirectory) Stat() (os.FileInfo, error) {
	return f, nil
}

// AssetFS implements http.FileSystem, allowing
// embedded files to be served from net/http package.
type AssetFS struct {
	// Asset should return content of file in path if exists
	Asset func(path string) ([]byte, error)
	// AssetDir should return list of files in the path
	AssetDir func(path string) ([]string, error)
	// AssetInfo should return the info of file in path if exists
	AssetInfo func(path string) (os.FileInfo, error)
	// Prefix would be prepended to http requests
	Prefix string
}

func (fs *AssetFS) Open(name string) (http.File, error) {
	name = path.Join(fs.Prefix, name)
	if len(name) > 0 && name[0] == '/' {
		name = name[1:]
	}
	if b, err := fs.Asset(name); err == nil {
		timestamp := defaultFileTimestamp
		if fs.AssetInfo != nil {
			if info, err := fs.AssetInfo(name); err == nil {
				timestamp = info.ModTime()
			}
		}
		return NewAssetFile(name, b, timestamp), nil
	}
	if children, err := fs.AssetDir(name); err == nil {
		return NewAssetDirectory(name, children, fs), nil
	} else {
		// If the error is not found, return an error that will
		// result in a 404 error. Otherwise the server returns
		// a 500 error for files not found.
		if strings.Contains(err.Error(), "not found") {
			return nil, os.ErrNotExist
		}
		return nil, err
	}
}


================================================
FILE: vendor/github.com/elazarl/go-bindata-assetfs/doc.go
================================================
// assetfs allows packages to serve static content embedded
// with the go-bindata tool with the standard net/http package.
//
// See https://github.com/jteeuwen/go-bindata for more information
// about embedding binary data with go-bindata.
//
// Usage example, after running
//    $ go-bindata data/...
// use:
//     http.Handle("/",
//        http.FileServer(
//        &assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, Prefix: "data"}))
package assetfs


================================================
FILE: vendor/github.com/mitchellh/go-homedir/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 Mitchell Hashimoto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: vendor/github.com/mitchellh/go-homedir/README.md
================================================
# go-homedir

This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.

Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
for a user, and `homedir.Expand()` to expand the `~` in a path to the home
directory.

**Why not just use `os/user`?** The built-in `os/user` package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for `os/user` is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.


================================================
FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
================================================
package homedir

import (
	"bytes"
	"errors"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
)

// DisableCache will disable caching of the home directory. Caching is enabled
// by default.
var DisableCache bool

var homedirCache string
var cacheLock sync.RWMutex

// Dir returns the home directory for the executing user.
//
// This uses an OS-specific method for discovering the home directory.
// An error is returned if a home directory cannot be detected.
func Dir() (string, error) {
	if !DisableCache {
		cacheLock.RLock()
		cached := homedirCache
		cacheLock.RUnlock()
		if cached != "" {
			return cached, nil
		}
	}

	cacheLock.Lock()
	defer cacheLock.Unlock()

	var result string
	var err error
	if runtime.GOOS == "windows" {
		result, err = dirWindows()
	} else {
		// Unix-like system, so just assume Unix
		result, err = dirUnix()
	}

	if err != nil {
		return "", err
	}
	homedirCache = result
	return result, nil
}

// Expand expands the path to include the home directory if the path
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
// returned as-is.
func Expand(path string) (string, error) {
	if len(path) == 0 {
		return path, nil
	}

	if path[0] != '~' {
		return path, nil
	}

	if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
		return "", errors.New("cannot expand user-specific home dir")
	}

	dir, err := Dir()
	if err != nil {
		return "", err
	}

	return filepath.Join(dir, path[1:]), nil
}

func dirUnix() (string, error) {
	// First prefer the HOME environmental variable
	if home := os.Getenv("HOME"); home != "" {
		return home, nil
	}

	// If that fails, try getent
	var stdout bytes.Buffer
	cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		// If the error is ErrNotFound, we ignore it. Otherwise, return it.
		if err != exec.ErrNotFound {
			return "", err
		}
	} else {
		if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
			// username:password:uid:gid:gecos:home:shell
			passwdParts := strings.SplitN(passwd, ":", 7)
			if len(passwdParts) > 5 {
				return passwdParts[5], nil
			}
		}
	}

	// If all else fails, try the shell
	stdout.Reset()
	cmd = exec.Command("sh", "-c", "cd && pwd")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	result := strings.TrimSpace(stdout.String())
	if result == "" {
		return "", errors.New("blank output when reading home directory")
	}

	return result, nil
}

func dirWindows() (string, error) {
	// First prefer the HOME environmental variable
	if home := os.Getenv("HOME"); home != "" {
		return home, nil
	}

	drive := os.Getenv("HOMEDRIVE")
	path := os.Getenv("HOMEPATH")
	home := drive + path
	if drive == "" || path == "" {
		home = os.Getenv("USERPROFILE")
	}
	if home == "" {
		return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
	}

	return home, nil
}


================================================
FILE: vendor/github.com/urfave/cli/CHANGELOG.md
================================================
# Change Log

**ATTN**: This project uses [semantic versioning](http://semver.org/).

## [Unreleased]

## 1.20.0 - 2017-08-10

### Fixed

* `HandleExitCoder` is now correctly iterates over all errors in
  a `MultiError`. The exit code is the exit code of the last error or `1` if
  there are no `ExitCoder`s in the `MultiError`.
* Fixed YAML file loading on Windows (previously would fail validate the file path)
* Subcommand `Usage`, `Description`, `ArgsUsage`, `OnUsageError` correctly
  propogated
* `ErrWriter` is now passed downwards through command structure to avoid the
  need to redefine it
* Pass `Command` context into `OnUsageError` rather than parent context so that
  all fields are avaiable
* Errors occuring in `Before` funcs are no longer double printed
* Use `UsageText` in the help templates for commands and subcommands if
  defined; otherwise build the usage as before (was previously ignoring this
  field)
* `IsSet` and `GlobalIsSet` now correctly return whether a flag is set if
  a program calls `Set` or `GlobalSet` directly after flag parsing (would
  previously only return `true` if the flag was set during parsing)

### Changed

* No longer exit the program on command/subcommand error if the error raised is
  not an `OsExiter`. This exiting behavior was introduced in 1.19.0, but was
  determined to be a regression in functionality. See [the
  PR](https://github.com/urfave/cli/pull/595) for discussion.

### Added

* `CommandsByName` type was added to make it easy to sort `Command`s by name,
  alphabetically
* `altsrc` now handles loading of string and int arrays from TOML
* Support for definition of custom help templates for `App` via
  `CustomAppHelpTemplate`
* Support for arbitrary key/value fields on `App` to be used with
  `CustomAppHelpTemplate` via `ExtraInfo`
* `HelpFlag`, `VersionFlag`, and `BashCompletionFlag` changed to explictly be
  `cli.Flag`s allowing for the use of custom flags satisfying the `cli.Flag`
  interface to be used.


## [1.19.1] - 2016-11-21

### Fixed

- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as
  the `Action` for a command would cause it to error rather than calling the
  function. Should not have a affected declarative cases using `func(c
  *cli.Context) err)`.
- Shell completion now handles the case where the user specifies
  `--generate-bash-completion` immediately after a flag that takes an argument.
  Previously it call the application with `--generate-bash-completion` as the
  flag value.

## [1.19.0] - 2016-11-19
### Added
- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
- A `Description` field was added to `App` for a more detailed description of
  the application (similar to the existing `Description` field on `Command`)
- Flag type code generation via `go generate`
- Write to stderr and exit 1 if action returns non-nil error
- Added support for TOML to the `altsrc` loader
- `SkipArgReorder` was added to allow users to skip the argument reordering.
  This is useful if you want to consider all "flags" after an argument as
  arguments rather than flags (the default behavior of the stdlib `flag`
  library). This is backported functionality from the [removal of the flag
  reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
  2
- For formatted errors (those implementing `ErrorFormatter`), the errors will
  be formatted during output. Compatible with `pkg/errors`.

### Changed
- Raise minimum tested/supported Go version to 1.2+

### Fixed
- Consider empty environment variables as set (previously environment variables
  with the equivalent of `""` would be skipped rather than their value used).
- Return an error if the value in a given environment variable cannot be parsed
  as the flag type. Previously these errors were silently swallowed.
- Print full error when an invalid flag is specified (which includes the invalid flag)
- `App.Writer` defaults to `stdout` when `nil`
- If no action is specified on a command or app, the help is now printed instead of `panic`ing
- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
- Correctly show help message if `-h` is provided to a subcommand
- `context.(Global)IsSet` now respects environment variables. Previously it
  would return `false` if a flag was specified in the environment rather than
  as an argument
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
  fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
  as `altsrc` where Go would complain that the types didn't match

## [1.18.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)

## [1.18.0] - 2016-06-27
### Added
- `./runtests` test runner with coverage tracking by default
- testing on OS X
- testing on Windows
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code

### Changed
- Use spaces for alignment in help/usage output instead of tabs, making the
  output alignment consistent regardless of tab width

### Fixed
- Printing of command aliases in help text
- Printing of visible flags for both struct and struct pointer flags
- Display the `help` subcommand when using `CommandCategories`
- No longer swallows `panic`s that occur within the `Action`s themselves when
  detecting the signature of the `Action` field

## [1.17.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user

## [1.17.0] - 2016-05-09
### Added
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
- Support for hiding commands by setting `Hidden: true` -- this will hide the
  commands in help output

### Changed
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
  quoted in help text output.
- All flag types now include `(default: {value})` strings following usage when a
  default value can be (reasonably) detected.
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
  with non-slice flag types
- Apps now exit with a code of 3 if an unknown subcommand is specified
  (previously they printed "No help topic for...", but still exited 0. This
  makes it easier to script around apps built using `cli` since they can trust
  that a 0 exit code indicated a successful execution.
- cleanups based on [Go Report Card
  feedback](https://goreportcard.com/report/github.com/urfave/cli)

## [1.16.1] - 2016-08-28
### Fixed
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user

## [1.16.0] - 2016-05-02
### Added
- `Hidden` field on all flag struct types to omit from generated help text

### Changed
- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
generated help text via the `Hidden` field

### Fixed
- handling of error values in `HandleAction` and `HandleExitCoder`

## [1.15.0] - 2016-04-30
### Added
- This file!
- Support for placeholders in flag usage strings
- `App.Metadata` map for arbitrary data/state management
- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
parsing.
- Support for nested lookup of dot-delimited keys in structures loaded from
YAML.

### Changed
- The `App.Action` and `Command.Action` now prefer a return signature of
`func(*cli.Context) error`, as defined by `cli.ActionFunc`.  If a non-nil
`error` is returned, there may be two outcomes:
    - If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
    automatically
    - Else the error is bubbled up and returned from `App.Run`
- Specifying an `Action` with the legacy return signature of
`func(*cli.Context)` will produce a deprecation message to stderr
- Specifying an `Action` that is not a `func` type will produce a non-zero exit
from `App.Run`
- Specifying an `Action` func that has an invalid (input) signature will
produce a non-zero exit from `App.Run`

### Deprecated
- <a name="deprecated-cli-app-runandexitonerror"></a>
`cli.App.RunAndExitOnError`, which should now be done by returning an error
that fulfills `cli.ExitCoder` to `cli.App.Run`.
- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
`cli.App.Action` of `func(*cli.Context)`, which should now have a return
signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.

### Fixed
- Added missing `*cli.Context.GlobalFloat64` method

## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
### Added
- Codebeat badge
- Support for categorization via `CategorizedHelp` and `Categories` on app.

### Changed
- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.

### Fixed
- Ensure version is not shown in help text when `HideVersion` set.

## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
### Added
- YAML file input support.
- `NArg` method on context.

## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
### Added
- Custom usage error handling.
- Custom text support in `USAGE` section of help output.
- Improved help messages for empty strings.
- AppVeyor CI configuration.

### Changed
- Removed `panic` from default help printer func.
- De-duping and optimizations.

### Fixed
- Correctly handle `Before`/`After` at command level when no subcommands.
- Case of literal `-` argument causing flag reordering.
- Environment variable hints on Windows.
- Docs updates.

## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
### Changed
- Use `path.Base` in `Name` and `HelpName`
- Export `GetName` on flag types.

### Fixed
- Flag parsing when skipping is enabled.
- Test output cleanup.
- Move completion check to account for empty input case.

## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
### Added
- Destination scan support for flags.
- Testing against `tip` in Travis CI config.

### Changed
- Go version in Travis CI config.

### Fixed
- Removed redundant tests.
- Use correct example naming in tests.

## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
### Fixed
- Remove unused var in bash completion.

## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
### Added
- Coverage and reference logos in README.

### Fixed
- Use specified values in help and version parsing.
- Only display app version and help message once.

## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
### Added
- More tests for existing functionality.
- `ArgsUsage` at app and command level for help text flexibility.

### Fixed
- Honor `HideHelp` and `HideVersion` in `App.Run`.
- Remove juvenile word from README.

## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
### Added
- `FullName` on command with accompanying help output update.
- Set default `$PROG` in bash completion.

### Changed
- Docs formatting.

### Fixed
- Removed self-referential imports in tests.

## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
### Added
- Support for `Copyright` at app level.
- `Parent` func at context level to walk up context lineage.

### Fixed
- Global flag processing at top level.

## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
### Added
- Aggregate errors from `Before`/`After` funcs.
- Doc comments on flag structs.
- Include non-global flags when checking version and help.
- Travis CI config updates.

### Fixed
- Ensure slice type flags have non-nil values.
- Collect global flags from the full command hierarchy.
- Docs prose.

## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
### Changed
- `HelpPrinter` signature includes output writer.

### Fixed
- Specify go 1.1+ in docs.
- Set `Writer` when running command as app.

## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
### Added
- Multiple author support.
- `NumFlags` at context level.
- `Aliases` at command level.

### Deprecated
- `ShortName` at command level.

### Fixed
- Subcommand help output.
- Backward compatible support for deprecated `Author` and `Email` fields.
- Docs regarding `Names`/`Aliases`.

## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
### Added
- `After` hook func support at app and command level.

### Fixed
- Use parsed context when running command as subcommand.
- Docs prose.

## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
### Added
- Support for hiding `-h / --help` flags, but not `help` subcommand.
- Stop flag parsing after `--`.

### Fixed
- Help text for generic flags to specify single value.
- Use double quotes in output for defaults.
- Use `ParseInt` instead of `ParseUint` for int environment var values.
- Use `0` as base when parsing int environment var values.

## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
### Added
- Support for environment variable lookup "cascade".
- Support for `Stdout` on app for output redirection.

### Fixed
- Print command help instead of app help in `ShowCommandHelp`.

## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
### Added
- Docs and example code updates.

### Changed
- Default `-v / --version` flag made optional.

## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
### Added
- `FlagNames` at context level.
- Exposed `VersionPrinter` var for more control over version output.
- Zsh completion hook.
- `AUTHOR` section in default app help template.
- Contribution guidelines.
- `DurationFlag` type.

## [1.2.0] - 2014-08-02
### Added
- Support for environment variable defaults on flags plus tests.

## [1.1.0] - 2014-07-15
### Added
- Bash completion.
- Optional hiding of built-in help command.
- Optional skipping of flag parsing at command level.
- `Author`, `Email`, and `Compiled` metadata on app.
- `Before` hook func support at app and command level.
- `CommandNotFound` func support at app level.
- Command reference available on context.
- `GenericFlag` type.
- `Float64Flag` type.
- `BoolTFlag` type.
- `IsSet` flag helper on context.
- More flag lookup funcs at context level.
- More tests &amp; docs.

### Changed
- Help template updates to account for presence/absence of flags.
- Separated subcommand help template.
- Exposed `HelpPrinter` var for more control over help output.

## [1.0.0] - 2013-11-01
### Added
- `help` flag in default app flag set and each command flag set.
- Custom handling of argument parsing errors.
- Command lookup by name at app level.
- `StringSliceFlag` type and supporting `StringSlice` type.
- `IntSliceFlag` type and supporting `IntSlice` type.
- Slice type flag lookups by name at context level.
- Export of app and command help functions.
- More tests &amp; docs.

## 0.1.0 - 2013-07-22
### Added
- Initial implementation.

[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0


================================================
FILE: vendor/github.com/urfave/cli/LICENSE
================================================
MIT License

Copyright (c) 2016 Jeremy Saenz & Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: vendor/github.com/urfave/cli/README.md
================================================
cli
===

[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli)
[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli)
[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli)
[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli)
[![top level coverage](https://gocover.io/_badge/github.com/urfave/cli?0 "top level coverage")](http://gocover.io/github.com/urfave/cli) /
[![altsrc coverage](https://gocover.io/_badge/github.com/urfave/cli/altsrc?0 "altsrc coverage")](http://gocover.io/github.com/urfave/cli/altsrc)

**Notice:** This is the library formerly known as
`github.com/codegangsta/cli` -- Github will automatically redirect requests
to this repository, but we recommend updating your references for clarity.

cli is a 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.

<!-- toc -->

- [Overview](#overview)
- [Installation](#installation)
  * [Supported platforms](#supported-platforms)
  * [Using the `v2` branch](#using-the-v2-branch)
  * [Pinning to the `v1` releases](#pinning-to-the-v1-releases)
- [Getting Started](#getting-started)
- [Examples](#examples)
  * [Arguments](#arguments)
  * [Flags](#flags)
    + [Placeholder Values](#placeholder-values)
    + [Alternate Names](#alternate-names)
    + [Ordering](#ordering)
    + [Values from the Environment](#values-from-the-environment)
    + [Values from files](#values-from-files)
    + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
    + [Precedence](#precedence)
  * [Subcommands](#subcommands)
  * [Subcommands categories](#subcommands-categories)
  * [Exit code](#exit-code)
  * [Bash Completion](#bash-completion)
    + [Enabling](#enabling)
    + [Distribution](#distribution)
    + [Customization](#customization)
  * [Generated Help Text](#generated-help-text)
    + [Customization](#customization-1)
  * [Version Flag](#version-flag)
    + [Customization](#customization-2)
    + [Full API Example](#full-api-example)
  * [Combining short Bool options](#combining-short-bool-options)
- [Contribution Guidelines](#contribution-guidelines)

<!-- tocstop -->

## Overview

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.

**This is where cli comes into play.** cli makes command line programming fun,
organized, and expressive!

## Installation

Make sure you have a working Go environment.  Go version 1.2+ is supported.  [See
the install instructions for Go](http://golang.org/doc/install.html).

To install cli, simply run:
```
$ go get github.com/urfave/cli
```

Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can
be easily used:
```
export PATH=$PATH:$GOPATH/bin
```

### Supported platforms

cli is tested against multiple versions of Go on Linux, and against the latest
released version of Go on OS X and Windows.  For full details, see
[`./.travis.yml`](./.travis.yml) and [`./appveyor.yml`](./appveyor.yml).

### Using the `v2` branch

**Warning**: The `v2` branch is currently unreleased and considered unstable.

There is currently a long-lived branch named `v2` that is intended to land as
the new `master` branch once development there has settled down.  The current
`master` branch (mirrored as `v1`) is being manually merged into `v2` on
an irregular human-based schedule, but generally if one wants to "upgrade" to
`v2` *now* and accept the volatility (read: "awesomeness") that comes along with
that, please use whatever version pinning of your preference, such as via
`gopkg.in`:

```
$ go get gopkg.in/urfave/cli.v2
```

``` go
...
import (
  "gopkg.in/urfave/cli.v2" // imports as package "cli"
)
...
```

### Pinning to the `v1` releases

Similarly to the section above describing use of the `v2` branch, if one wants
to avoid any unexpected compatibility pains once `v2` becomes `master`, then
pinning to `v1` is an acceptable option, e.g.:

```
$ go get gopkg.in/urfave/cli.v1
```

``` go
...
import (
  "gopkg.in/urfave/cli.v1" // imports as package "cli"
)
...
```

This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing).

## Getting Started

One of the philosophies behind cli is that an API should be playful and full of
discovery. So a cli app can be as little as one line of code in `main()`.

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "A new cli application"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.NewApp().Run(os.Args)
}
```

This app will run and show help text, but is not very useful. Let's give an
action to execute and some help documentation:

<!-- {
  "output": "boom! I say!"
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "boom"
  app.Usage = "make an explosive entrance"
  app.Action = func(c *cli.Context) error {
    fmt.Println("boom! I say!")
    return nil
  }

  app.Run(os.Args)
}
```

Running this already gives you a ton of functionality, plus support for things
like subcommands and flags, which are covered below.

## Examples

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!

Start by creating a directory named `greet`, and within it, add a file,
`greet.go` with the following code in it:

<!-- {
  "output": "Hello friend!"
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "greet"
  app.Usage = "fight the loneliness!"
  app.Action = func(c *cli.Context) error {
    fmt.Println("Hello friend!")
    return nil
  }

  app.Run(os.Args)
}
```

Install our command to the `$GOPATH/bin` directory:

```
$ go install
```

Finally run our new command:

```
$ greet
Hello friend!
```

cli also generates neat help text:

```
$ greet help
NAME:
    greet - fight the loneliness!

USAGE:
    greet [global options] command [command options] [arguments...]

VERSION:
    0.0.0

COMMANDS:
    help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS
    --version Shows version information
```

### Arguments

You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.:

<!-- {
  "output": "Hello \""
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Action = func(c *cli.Context) error {
    fmt.Printf("Hello %q", c.Args().Get(0))
    return nil
  }

  app.Run(os.Args)
}
```

### Flags

Setting and querying flags is simple.

<!-- {
  "output": "Hello Nefertiti"
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang",
      Value: "english",
      Usage: "language for the greeting",
    },
  }

  app.Action = func(c *cli.Context) error {
    name := "Nefertiti"
    if c.NArg() > 0 {
      name = c.Args().Get(0)
    }
    if c.String("lang") == "spanish" {
      fmt.Println("Hola", name)
    } else {
      fmt.Println("Hello", name)
    }
    return nil
  }

  app.Run(os.Args)
}
```

You can also set a destination variable for a flag, to which the content will be
scanned.

<!-- {
  "output": "Hello someone"
} -->
``` go
package main

import (
  "os"
  "fmt"

  "github.com/urfave/cli"
)

func main() {
  var language string

  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name:        "lang",
      Value:       "english",
      Usage:       "language for the greeting",
      Destination: &language,
    },
  }

  app.Action = func(c *cli.Context) error {
    name := "someone"
    if c.NArg() > 0 {
      name = c.Args()[0]
    }
    if language == "spanish" {
      fmt.Println("Hola", name)
    } else {
      fmt.Println("Hello", name)
    }
    return nil
  }

  app.Run(os.Args)
}
```

See full list of flags at http://godoc.org/github.com/urfave/cli

#### Placeholder Values

Sometimes it's useful to specify a flag's value within the usage string itself.
Such placeholders are indicated with back quotes.

For example this:

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "&#45;&#45;config FILE, &#45;c FILE"
} -->
```go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag{
    cli.StringFlag{
      Name:  "config, c",
      Usage: "Load configuration from `FILE`",
    },
  }

  app.Run(os.Args)
}
```

Will result in help output like:

```
--config FILE, -c FILE   Load configuration from FILE
```

Note that only the first placeholder is used. Subsequent back-quoted words will
be left as-is.

#### Alternate Names

You can set alternate (or short) names for flags by providing a comma-delimited
list for the `Name`. e.g.

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "&#45;&#45;lang value, &#45;l value.*language for the greeting.*default: \"english\""
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
    },
  }

  app.Run(os.Args)
}
```

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.

#### Ordering

Flags for the application and commands are shown in the order they are defined.
However, it's possible to sort them from outside this library by using `FlagsByName`
or `CommandsByName` with `sort`.

For example this:

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "add a task to the list\n.*complete a task on the list\n.*\n\n.*\n.*Load configuration from FILE\n.*Language for the greeting.*"
} -->
``` go
package main

import (
  "os"
  "sort"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "Language for the greeting",
    },
    cli.StringFlag{
      Name: "config, c",
      Usage: "Load configuration from `FILE`",
    },
  }

  app.Commands = []cli.Command{
    {
      Name:    "complete",
      Aliases: []string{"c"},
      Usage:   "complete a task on the list",
      Action:  func(c *cli.Context) error {
        return nil
      },
    },
    {
      Name:    "add",
      Aliases: []string{"a"},
      Usage:   "add a task to the list",
      Action:  func(c *cli.Context) error {
        return nil
      },
    },
  }

  sort.Sort(cli.FlagsByName(app.Flags))
  sort.Sort(cli.CommandsByName(app.Commands))

  app.Run(os.Args)
}
```

Will result in help output like:

```
--config FILE, -c FILE  Load configuration from FILE
--lang value, -l value  Language for the greeting (default: "english")
```

#### Values from the Environment

You can also have the default value set from the environment via `EnvVar`.  e.g.

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "language for the greeting.*APP_LANG"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
      EnvVar: "APP_LANG",
    },
  }

  app.Run(os.Args)
}
```

The `EnvVar` may also be given as a comma-delimited "cascade", where the first
environment variable that resolves is used as the default.

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "language for the greeting.*LEGACY_COMPAT_LANG.*APP_LANG.*LANG"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
      EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
    },
  }

  app.Run(os.Args)
}
```

#### Values from files

You can also have the default value set from file via `FilePath`.  e.g.

<!-- {
  "args": ["&#45;&#45;help"],
  "output": "password for the mysql database"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "password, p",
      Usage: "password for the mysql database",
      FilePath: "/etc/mysql/password",
    },
  }

  app.Run(os.Args)
}
```

Note that default values set from file (e.g. `FilePath`) take precedence over
default values set from the enviornment (e.g. `EnvVar`).

#### Values from alternate input sources (YAML, TOML, and others)

There is a separate package altsrc that adds support for getting flag values
from other file input sources.

Currently supported input source formats:
* YAML
* TOML

In order to get values for a flag from an alternate input source the following
code would be added to wrap an existing cli.Flag like below:

``` go
  altsrc.NewIntFlag(cli.IntFlag{Name: "test"})
```

Initialization must also occur for these flags. Below is an example initializing
getting data from a yaml file below.

``` go
  command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
```

The code above will use the "load" string as a flag name to get the file name of
a yaml file from the cli.Context.  It will then use that file name to initialize
the yaml input source for any flags that are defined on that command.  As a note
the "load" flag used would also have to be defined on the command flags in order
for this code snipped to work.

Currently only the aboved specified formats are supported but developers can
add support for other input sources by implementing the
altsrc.InputSourceContext for their given sources.

Here is a more complete sample of a command using YAML support:

<!-- {
  "args": ["test-cmd", "&#45;&#45;help"],
  "output": "&#45&#45;test value.*default: 0"
} -->
``` go
package notmain

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
  "github.com/urfave/cli/altsrc"
)

func main() {
  app := cli.NewApp()

  flags := []cli.Flag{
    altsrc.NewIntFlag(cli.IntFlag{Name: "test"}),
    cli.StringFlag{Name: "load"},
  }

  app.Action = func(c *cli.Context) error {
    fmt.Println("yaml ist rad")
    return nil
  }

  app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
  app.Flags = flags

  app.Run(os.Args)
}
```

#### Precedence

The precedence for flag value sources is as follows (highest to lowest):

0. Command line flag value from user
0. Environment variable (if specified)
0. Configuration file (if specified)
0. Default defined on the flag

### Subcommands

Subcommands can be defined for a more git-like command line app.

<!-- {
  "args": ["template", "add"],
  "output": "new task template: .+"
} -->
```go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Commands = []cli.Command{
    {
      Name:    "add",
      Aliases: []string{"a"},
      Usage:   "add a task to the list",
      Action:  func(c *cli.Context) error {
        fmt.Println("added task: ", c.Args().First())
        return nil
      },
    },
    {
      Name:    "complete",
      Aliases: []string{"c"},
      Usage:   "complete a task on the list",
      Action:  func(c *cli.Context) error {
        fmt.Println("completed task: ", c.Args().First())
        return nil
      },
    },
    {
      Name:        "template",
      Aliases:     []string{"t"},
      Usage:       "options for task templates",
      Subcommands: []cli.Command{
        {
          Name:  "add",
          Usage: "add a new template",
          Action: func(c *cli.Context) error {
            fmt.Println("new task template: ", c.Args().First())
            return nil
          },
        },
        {
          Name:  "remove",
          Usage: "remove an existing template",
          Action: func(c *cli.Context) error {
            fmt.Println("removed task template: ", c.Args().First())
            return nil
          },
        },
      },
    },
  }

  app.Run(os.Args)
}
```

### Subcommands categories

For additional organization in apps that have many subcommands, you can
associate a category for each command to group them together in the help
output.

E.g.

```go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Commands = []cli.Command{
    {
      Name: "noop",
    },
    {
      Name:     "add",
      Category: "Template actions",
    },
    {
      Name:     "remove",
      Category: "Template actions",
    },
  }

  app.Run(os.Args)
}
```

Will include:

```
COMMANDS:
    noop

  Template actions:
    add
    remove
```

### Exit code

Calling `App.Run` will not automatically call `os.Exit`, which means that by
default the exit code will "fall through" to being `0`.  An explicit exit code
may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:

``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Flags = []cli.Flag{
    cli.BoolTFlag{
      Name:  "ginger-crouton",
      Usage: "is it in the soup?",
    },
  }
  app.Action = func(ctx *cli.Context) error {
    if !ctx.Bool("ginger-crouton") {
      return cli.NewExitError("it is not in the soup", 86)
    }
    return nil
  }

  app.Run(os.Args)
}
```

### Bash Completion

You can enable completion commands by setting the `EnableBashCompletion`
flag on the `App` object.  By default, this setting will only auto-complete to
show an app's subcommands, but you can write your own completion methods for
the App or its subcommands.

<!-- {
  "args": ["complete", "&#45;&#45;generate&#45;bash&#45;completion"],
  "output": "laundry"
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}

  app := cli.NewApp()
  app.EnableBashCompletion = true
  app.Commands = []cli.Command{
    {
      Name:  "complete",
      Aliases: []string{"c"},
      Usage: "complete a task on the list",
      Action: func(c *cli.Context) error {
         fmt.Println("completed task: ", c.Args().First())
         return nil
      },
      BashComplete: func(c *cli.Context) {
        // This will complete if no args are passed
        if c.NArg() > 0 {
          return
        }
        for _, t := range tasks {
          fmt.Println(t)
        }
      },
    },
  }

  app.Run(os.Args)
}
```

#### Enabling

Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
setting the `PROG` variable to the name of your program:

`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`

#### Distribution

Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
it to the name of the program you wish to add autocomplete support for (or
automatically install it there if you are distributing a package). Don't forget
to source the file to make it active in the current shell.

```
sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
source /etc/bash_completion.d/<myprogram>
```

Alternatively, you can just document that users should source the generic
`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
to the name of their program (as above).

#### Customization

The default bash completion flag (`--generate-bash-completion`) is defined as
`cli.BashCompletionFlag`, and may be redefined if desired, e.g.:

<!-- {
  "args": ["&#45;&#45;compgen"],
  "output": "wat\nhelp\nh"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.BashCompletionFlag = cli.BoolFlag{
    Name:   "compgen",
    Hidden: true,
  }

  app := cli.NewApp()
  app.EnableBashCompletion = true
  app.Commands = []cli.Command{
    {
      Name: "wat",
    },
  }
  app.Run(os.Args)
}
```

### Generated Help Text

The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked
by the cli internals in order to print generated help text for the app, command,
or subcommand, and break execution.

#### Customization

All of the help text generation may be customized, and at multiple levels.  The
templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
e.g.:

<!-- {
  "output": "Ha HA.  I pwnd the help!!1"
} -->
``` go
package main

import (
  "fmt"
  "io"
  "os"

  "github.com/urfave/cli"
)

func main() {
  // EXAMPLE: Append to an existing template
  cli.AppHelpTemplate = fmt.Sprintf(`%s

WEBSITE: http://awesometown.example.com

SUPPORT: support@awesometown.example.com

`, cli.AppHelpTemplate)

  // EXAMPLE: Override a template
  cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}
USAGE:
   {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
   {{if len .Authors}}
AUTHOR:
   {{range .Authors}}{{ . }}{{end}}
   {{end}}{{if .Commands}}
COMMANDS:
{{range .Commands}}{{if not .HideHelp}}   {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
   {{range .VisibleFlags}}{{.}}
   {{end}}{{end}}{{if .Copyright }}
COPYRIGHT:
   {{.Copyright}}
   {{end}}{{if .Version}}
VERSION:
   {{.Version}}
   {{end}}
`

  // EXAMPLE: Replace the `HelpPrinter` func
  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
    fmt.Println("Ha HA.  I pwnd the help!!1")
  }

  cli.NewApp().Run(os.Args)
}
```

The default flag may be customized to something other than `-h/--help` by
setting `cli.HelpFlag`, e.g.:

<!-- {
  "args": ["&#45;&#45halp"],
  "output": "haaaaalp.*HALP"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.HelpFlag = cli.BoolFlag{
    Name: "halp, haaaaalp",
    Usage: "HALP",
    EnvVar: "SHOW_HALP,HALPPLZ",
  }

  cli.NewApp().Run(os.Args)
}
```

### Version Flag

The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which
is checked by the cli internals in order to print the `App.Version` via
`cli.VersionPrinter` and break execution.

#### Customization

The default flag may be customized to something other than `-v/--version` by
setting `cli.VersionFlag`, e.g.:

<!-- {
  "args": ["&#45;&#45print-version"],
  "output": "partay version 19\\.99\\.0"
} -->
``` go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.VersionFlag = cli.BoolFlag{
    Name: "print-version, V",
    Usage: "print only the version",
  }

  app := cli.NewApp()
  app.Name = "partay"
  app.Version = "19.99.0"
  app.Run(os.Args)
}
```

Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.:

<!-- {
  "args": ["&#45;&#45version"],
  "output": "version=19\\.99\\.0 revision=fafafaf"
} -->
``` go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

var (
  Revision = "fafafaf"
)

func main() {
  cli.VersionPrinter = func(c *cli.Context) {
    fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
  }

  app := cli.NewApp()
  app.Name = "partay"
  app.Version = "19.99.0"
  app.Run(os.Args)
}
```

#### Full API Example

**Notice**: This is a contrived (functioning) example meant strictly for API
demonstration purposes.  Use of one's imagination is encouraged.

<!-- {
  "output": "made it!\nPhew!"
} -->
``` go
package main

import (
  "errors"
  "flag"
  "fmt"
  "io"
  "io/ioutil"
  "os"
  "time"

  "github.com/urfave/cli"
)

func init() {
  cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n"
  cli.CommandHelpTemplate += "\nYMMV\n"
  cli.SubcommandHelpTemplate += "\nor something\n"

  cli.HelpFlag = cli.BoolFlag{Name: "halp"}
  cli.BashCompletionFlag = cli.BoolFlag{Name: "compgen", Hidden: true}
  cli.VersionFlag = cli.BoolFlag{Name: "print-version, V"}

  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
    fmt.Fprintf(w, "best of luck to you\n")
  }
  cli.VersionPrinter = func(c *cli.Context) {
    fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version)
  }
  cli.OsExiter = func(c int) {
    fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c)
  }
  cli.ErrWriter = ioutil.Discard
  cli.FlagStringer = func(fl cli.Flag) string {
    return fmt.Sprintf("\t\t%s", fl.GetName())
  }
}

type hexWriter struct{}

func (w *hexWriter) Write(p []byte) (int, error) {
  for _, b := range p {
    fmt.Printf("%x", b)
  }
  fmt.Printf("\n")

  return len(p), nil
}

type genericType struct{
  s string
}

func (g *genericType) Set(value string) error {
  g.s = value
  return nil
}

func (g *genericType) String() string {
  return g.s
}

func main() {
  app := cli.NewApp()
  app.Name = "kənˈtrīv"
  app.Version = "19.99.0"
  app.Compiled = time.Now()
  app.Authors = []cli.Author{
    cli.Author{
      Name:  "Example Human",
      Email: "human@example.com",
    },
  }
  app.Copyright = "(c) 1999 Serious Enterprise"
  app.HelpName = "contrive"
  app.Usage = "demonstrate available API"
  app.UsageText = "contrive - demonstrating the available API"
  app.ArgsUsage = "[args and such]"
  app.Commands = []cli.Command{
    cli.Command{
      Name:        "doo",
      Aliases:     []string{"do"},
      Category:    "motion",
      Usage:       "do the doo",
      UsageText:   "doo - does the dooing",
      Description: "no really, there is a lot of dooing to be done",
      ArgsUsage:   "[arrgh]",
      Flags: []cli.Flag{
        cli.BoolFlag{Name: "forever, forevvarr"},
      },
      Subcommands: cli.Commands{
        cli.Command{
          Name:   "wop",
          Action: wopAction,
        },
      },
      SkipFlagParsing: false,
      HideHelp:        false,
      Hidden:          false,
      HelpName:        "doo!",
      BashComplete: func(c *cli.Context) {
        fmt.Fprintf(c.App.Writer, "--better\n")
      },
      Before: func(c *cli.Context) error {
        fmt.Fprintf(c.App.Writer, "brace for impact\n")
        return nil
      },
      After: func(c *cli.Context) error {
        fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
        return nil
      },
      Action: func(c *cli.Context) error {
        c.Command.FullName()
        c.Command.HasName("wop")
        c.Command.Names()
        c.Command.VisibleFlags()
        fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
        if c.Bool("forever") {
          c.Command.Run(c)
        }
        return nil
      },
      OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
        fmt.Fprintf(c.App.Writer, "for shame\n")
        return err
      },
    },
  }
  app.Flags = []cli.Flag{
    cli.BoolFlag{Name: "fancy"},
    cli.BoolTFlag{Name: "fancier"},
    cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3},
    cli.Float64Flag{Name: "howmuch"},
    cli.GenericFlag{Name: "wat", Value: &genericType{}},
    cli.Int64Flag{Name: "longdistance"},
    cli.Int64SliceFlag{Name: "intervals"},
    cli.IntFlag{Name: "distance"},
    cli.IntSliceFlag{Name: "times"},
    cli.StringFlag{Name: "dance-move, d"},
    cli.StringSliceFlag{Name: "names, N"},
    cli.UintFlag{Name: "age"},
    cli.Uint64Flag{Name: "bigage"},
  }
  app.EnableBashCompletion = true
  app.HideHelp = false
  app.HideVersion = false
  app.BashComplete = func(c *cli.Context) {
    fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
  }
  app.Before = func(c *cli.Context) error {
    fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
    return nil
  }
  app.After = func(c *cli.Context) error {
    fmt.Fprintf(c.App.Writer, "Phew!\n")
    return nil
  }
  app.CommandNotFound = func(c *cli.Context, command string) {
    fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
  }
  app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error {
    if isSubcommand {
      return err
    }

    fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
    return nil
  }
  app.Action = func(c *cli.Context) error {
    cli.DefaultAppComplete(c)
    cli.HandleExitCoder(errors.New("not an exit coder, though"))
    cli.ShowAppHelp(c)
    cli.ShowCommandCompletions(c, "nope")
    cli.ShowCommandHelp(c, "also-nope")
    cli.ShowCompletions(c)
    cli.ShowSubcommandHelp(c)
    cli.ShowVersion(c)

    categories := c.App.Categories()
    categories.AddCommand("sounds", cli.Command{
      Name: "bloop",
    })

    for _, category := range c.App.Categories() {
      fmt.Fprintf(c.App.Writer, "%s\n", category.Name)
      fmt.Fprintf(c.App.Writer, "%#v\n", category.Commands)
      fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
    }

    fmt.Printf("%#v\n", c.App.Command("doo"))
    if c.Bool("infinite") {
      c.App.Run([]string{"app", "doo", "wop"})
    }

    if c.Bool("forevar") {
      c.App.RunAsSubcommand(c)
    }
    c.App.Setup()
    fmt.Printf("%#v\n", c.App.VisibleCategories())
    fmt.Printf("%#v\n", c.App.VisibleCommands())
    fmt.Printf("%#v\n", c.App.VisibleFlags())

    fmt.Printf("%#v\n", c.Args().First())
    if len(c.Args()) > 0 {
      fmt.Printf("%#v\n", c.Args()[1])
    }
    fmt.Printf("%#v\n", c.Args().Present())
    fmt.Printf("%#v\n", c.Args().Tail())

    set := flag.NewFlagSet("contrive", 0)
    nc := cli.NewContext(c.App, set, c)

    fmt.Printf("%#v\n", nc.Args())
    fmt.Printf("%#v\n", nc.Bool("nope"))
    fmt.Printf("%#v\n", nc.BoolT("nerp"))
    fmt.Printf("%#v\n", nc.Duration("howlong"))
    fmt.Printf("%#v\n", nc.Float64("hay"))
    fmt.Printf("%#v\n", nc.Generic("bloop"))
    fmt.Printf("%#v\n", nc.Int64("bonk"))
    fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
    fmt.Printf("%#v\n", nc.Int("bips"))
    fmt.Printf("%#v\n", nc.IntSlice("blups"))
    fmt.Printf("%#v\n", nc.String("snurt"))
    fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
    fmt.Printf("%#v\n", nc.Uint("flub"))
    fmt.Printf("%#v\n", nc.Uint64("florb"))
    fmt.Printf("%#v\n", nc.GlobalBool("global-nope"))
    fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp"))
    fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong"))
    fmt.Printf("%#v\n", nc.GlobalFloat64("global-hay"))
    fmt.Printf("%#v\n", nc.GlobalGeneric("global-bloop"))
    fmt.Printf("%#v\n", nc.GlobalInt("global-bips"))
    fmt.Printf("%#v\n", nc.GlobalIntSlice("global-blups"))
    fmt.Printf("%#v\n", nc.GlobalString("global-snurt"))
    fmt.Printf("%#v\n", nc.GlobalStringSlice("global-snurkles"))

    fmt.Printf("%#v\n", nc.FlagNames())
    fmt.Printf("%#v\n", nc.GlobalFlagNames())
    fmt.Printf("%#v\n", nc.GlobalIsSet("wat"))
    fmt.Printf("%#v\n", nc.GlobalSet("wat", "nope"))
    fmt.Printf("%#v\n", nc.NArg())
    fmt.Printf("%#v\n", nc.NumFlags())
    fmt.Printf("%#v\n", nc.Parent())

    nc.Set("wat", "also-nope")

    ec := cli.NewExitError("ohwell", 86)
    fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
    fmt.Printf("made it!\n")
    return ec
  }

  if os.Getenv("HEXY") != "" {
    app.Writer = &hexWriter{}
    app.ErrWriter = &hexWriter{}
  }

  app.Metadata = map[string]interface{}{
    "layers":     "many",
    "explicable": false,
    "whatever-values": 19.99,
  }

  app.Run(os.Args)
}

func wopAction(c *cli.Context) error {
  fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n")
  return nil
}
```

### Combining short Bool options

Traditional use of boolean options using their shortnames look like this:
```
# cmd foobar -s -o
```

Suppose you want users to be able to combine your bool options with their shortname.  This
can be done using the **UseShortOptionHandling** bool in your commands.  Suppose your program
has a two bool flags such as *serve* and *option* with the short options of *-o* and
*-s* respectively. With **UseShortOptionHandling** set to *true*, a user can use a syntax
like:
```
# cmd foobar -so
```

If you enable the **UseShortOptionHandling*, then you must not use any flags that have a single
leading *-* or this will result in failures.  For example, **-option** can no longer be used.  Flags
with two leading dashes (such as **--options**) are still valid.

## Contribution Guidelines

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.

If you have contributed something significant to the project, we 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 feel like you have contributed to the project but have not yet been
added as a collaborator, we probably forgot to add you, please open an issue.


================================================
FILE: vendor/github.com/urfave/cli/app.go
================================================
package cli

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"time"
)

var (
	changeLogURL                    = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
	appActionDeprecationURL         = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
	runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)

	contactSysadmin = "This is an error in the application.  Please contact the distributor of this application if this is not you."

	errInvalidActionType = NewExitError("ERROR invalid Action type. "+
		fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error).  %s", contactSysadmin)+
		fmt.Sprintf("See %s", appActionDeprecationURL), 2)
)

// App is the main structure of a cli application. It is recommended that
// an app be created with the cli.NewApp() function
type App struct {
	// The name of the program. Defaults to path.Base(os.Args[0])
	Name string
	// Full name of command for help, defaults to Name
	HelpName string
	// Description of the program.
	Usage string
	// Text to override the USAGE section of help
	UsageText string
	// Description of the program argument format.
	ArgsUsage string
	// Version of the program
	Version string
	// Description of the program
	Description string
	// List of commands to execute
	Commands []Command
	// List of flags to parse
	Flags []Flag
	// Boolean to enable bash completion commands
	EnableBashCompletion bool
	// Boolean to hide built-in help command
	HideHelp bool
	// Boolean to hide built-in version flag and the VERSION section of help
	HideVersion bool
	// Populate on app startup, only gettable through method Categories()
	categories CommandCategories
	// An action to execute when the bash-completion flag is set
	BashComplete BashCompleteFunc
	// An action to execute before any subcommands are run, but after the context is ready
	// If a non-nil error is returned, no subcommands are run
	Before BeforeFunc
	// An action to execute after any subcommands are run, but after the subcommand has finished
	// It is run even if Action() panics
	After AfterFunc

	// The action to execute when no subcommands are specified
	// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
	// *Note*: support for the deprecated `Action` signature will be removed in a future version
	Action interface{}

	// Execute this function if the proper command cannot be found
	CommandNotFound CommandNotFoundFunc
	// Execute this function if an usage error occurs
	OnUsageError OnUsageErrorFunc
	// Compilation date
	Compiled time.Time
	// List of all authors who contributed
	Authors []Author
	// Copyright of the binary if any
	Copyright string
	// Name of Author (Note: Use App.Authors, this is deprecated)
	Author string
	// Email of Author (Note: Use App.Authors, this is deprecated)
	Email string
	// Writer writer to write output to
	Writer io.Writer
	// ErrWriter writes error output
	ErrWriter io.Writer
	// Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to
	// function as a default, so this is optional.
	ExitErrHandler ExitErrHandlerFunc
	// Other custom info
	Metadata map[string]interface{}
	// Carries a function which returns app specific info.
	ExtraInfo func() map[string]string
	// CustomAppHelpTemplate the text template for app help topic.
	// cli.go uses text/template to render templates. You can
	// render custom help text by setting this variable.
	CustomAppHelpTemplate string

	didSetup bool
}

// Tries to find out when this binary was compiled.
// Returns the current time if it fails to find it.
func compileTime() time.Time {
	info, err := os.Stat(os.Args[0])
	if err != nil {
		return time.Now()
	}
	return info.ModTime()
}

// NewApp creates a new cli Application with some reasonable defaults for Name,
// Usage, Version and Action.
func NewApp() *App {
	return &App{
		Name:         filepath.Base(os.Args[0]),
		HelpName:     filepath.Base(os.Args[0]),
		Usage:        "A new cli application",
		UsageText:    "",
		Version:      "0.0.0",
		BashComplete: DefaultAppComplete,
		Action:       helpCommand.Action,
		Compiled:     compileTime(),
		Writer:       os.Stdout,
	}
}

// Setup runs initialization code to ensure all data structures are ready for
// `Run` or inspection prior to `Run`.  It is internally called by `Run`, but
// will return early if setup has already happened.
func (a *App) Setup() {
	if a.didSetup {
		return
	}

	a.didSetup = true

	if a.Author != "" 
Download .txt
gitextract_kbx_5a4t/

├── .gitignore
├── .travis.yml
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── assets/
│   ├── .gitignore
│   └── assets.go
├── cmd/
│   └── gocho/
│       └── gocho.go
├── docs/
│   └── building.md
├── pkg/
│   ├── cmds/
│   │   └── cmds.go
│   ├── config/
│   │   ├── config.go
│   │   ├── utils.go
│   │   └── wizard.go
│   ├── info/
│   │   └── info.go
│   └── node/
│       ├── dashboard.go
│       ├── index.go
│       ├── net.go
│       ├── node.go
│       ├── packet.go
│       ├── serve.go
│       └── utils.go
├── ui/
│   ├── .gitignore
│   ├── package.json
│   ├── public/
│   │   ├── index.html
│   │   └── lang/
│   │       ├── en.json
│   │       └── es.json
│   └── src/
│       ├── App.css
│       ├── App.js
│       ├── components/
│       │   ├── FormField.js
│       │   ├── NodeDetails.js
│       │   ├── NodeList.js
│       │   ├── Panel.js
│       │   └── SideBar.js
│       ├── containers/
│       │   ├── Discover.js
│       │   └── NodeInfo.js
│       ├── i18n.js
│       ├── index.css
│       └── index.js
└── vendor/
    ├── github.com/
    │   ├── Pallinder/
    │   │   └── go-randomdata/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── fullprofile.go
    │   │       ├── jsondata.go
    │   │       ├── postalcodes.go
    │   │       └── random_data.go
    │   ├── elazarl/
    │   │   └── go-bindata-assetfs/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── assetfs.go
    │   │       └── doc.go
    │   ├── mitchellh/
    │   │   └── go-homedir/
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       └── homedir.go
    │   └── urfave/
    │       └── cli/
    │           ├── CHANGELOG.md
    │           ├── LICENSE
    │           ├── README.md
    │           ├── app.go
    │           ├── appveyor.yml
    │           ├── category.go
    │           ├── cli.go
    │           ├── command.go
    │           ├── context.go
    │           ├── errors.go
    │           ├── flag-types.json
    │           ├── flag.go
    │           ├── flag_generated.go
    │           ├── funcs.go
    │           ├── generate-flag-types
    │           ├── help.go
    │           ├── runtests
    │           └── sort.go
    ├── gopkg.in/
    │   └── yaml.v2/
    │       ├── LICENSE
    │       ├── LICENSE.libyaml
    │       ├── README.md
    │       ├── apic.go
    │       ├── decode.go
    │       ├── emitterc.go
    │       ├── encode.go
    │       ├── parserc.go
    │       ├── readerc.go
    │       ├── resolve.go
    │       ├── scannerc.go
    │       ├── sorter.go
    │       ├── writerc.go
    │       ├── yaml.go
    │       ├── yamlh.go
    │       └── yamlprivateh.go
    └── vendor.json
Download .txt
SYMBOL INDEX (840 symbols across 50 files)

FILE: assets/assets.go
  function AssetFS (line 7) | func AssetFS() *assetfs.AssetFS {

FILE: cmd/gocho/gocho.go
  function main (line 10) | func main() {

FILE: pkg/cmds/cmds.go
  function ConfigureAction (line 11) | func ConfigureAction(c *cli.Context) error {
  function StartAction (line 19) | func StartAction(c *cli.Context) error {
  function New (line 48) | func New() *cli.App {

FILE: pkg/config/config.go
  type Config (line 9) | type Config struct
    method String (line 18) | func (c *Config) String() string {
  function ConfigureWizard (line 26) | func ConfigureWizard() error {
  function LoadConfig (line 30) | func LoadConfig() (*Config, error) {

FILE: pkg/config/utils.go
  function fileExists (line 13) | func fileExists(file string) bool {
  function CleanPath (line 18) | func CleanPath(str string) string {
  function writeConfigToFile (line 22) | func writeConfigToFile(c *Config, fileName string) error {
  function getConfigFileName (line 27) | func getConfigFileName() (string, error) {
  function getDefaultConfig (line 37) | func getDefaultConfig() (*Config, error) {

FILE: pkg/config/wizard.go
  function configureWizard (line 10) | func configureWizard() error {

FILE: pkg/info/info.go
  constant APP_NAME (line 4) | APP_NAME = "gocho"
  constant VERSION (line 5) | VERSION  = "0.2.0-alfa"

FILE: pkg/node/dashboard.go
  function configHandler (line 13) | func configHandler(conf *config.Config) func(w http.ResponseWriter, r *h...
  function nodesHandler (line 26) | func nodesHandler(nodeList *list.List) func(http.ResponseWriter, *http.R...
  function dashboardServe (line 45) | func dashboardServe(conf *config.Config, nodeList *list.List) {

FILE: pkg/node/index.go
  constant HTML_BODY (line 12) | HTML_BODY = `<html>
  constant HTML_END (line 48) | HTML_END = `<script type="text/javascript">
  type FileServerResponseInterceptor (line 59) | type FileServerResponseInterceptor struct
    method WriteHeader (line 64) | func (f *FileServerResponseInterceptor) WriteHeader(status int) {
    method Header (line 68) | func (f *FileServerResponseInterceptor) Header() http.Header {
    method Write (line 72) | func (f *FileServerResponseInterceptor) Write(content []byte) (int, er...
  function interceptorHandler (line 97) | func interceptorHandler(next http.Handler) http.Handler {
  function fileServe (line 115) | func fileServe(conf *config.Config) {

FILE: pkg/node/net.go
  function announceNode (line 15) | func announceNode(nodeInfo *NodeInfo) {
  function listenForNodes (line 41) | func listenForNodes(nodeList *list.List) {
  function announcedNodeHandler (line 74) | func announcedNodeHandler(nodeInfo *NodeInfo, nodeList *list.List) {
  function updateNodeList (line 88) | func updateNodeList(nodeInfo *NodeInfo, nodeList *list.List) {
  function isNodeExpired (line 118) | func isNodeExpired(nodeInfo *NodeInfo, timeout int) bool {

FILE: pkg/node/node.go
  constant MULTICAST_ADDRESS (line 9) | MULTICAST_ADDRESS     = "239.6.6.6:1337"
  constant MULTICAST_BUFFER_SIZE (line 10) | MULTICAST_BUFFER_SIZE = 4096
  constant NODE_ANNOUNCE_COMMAND (line 12) | NODE_ANNOUNCE_COMMAND = "\x01"
  constant HEADER (line 13) | HEADER                = "\x60\x0D\xF0\x0D"
  constant MIN_PACKET_SIZE (line 14) | MIN_PACKET_SIZE       = 6
  constant EXPIRE_TIMEOUT_SEC (line 16) | EXPIRE_TIMEOUT_SEC    = 50
  constant ANNOUNCE_INTERVAL_SEC (line 17) | ANNOUNCE_INTERVAL_SEC = 10
  type NodeInfo (line 20) | type NodeInfo struct
  type Announcer (line 27) | type Announcer struct
    method Start (line 31) | func (a *Announcer) Start(nodeList *list.List) {

FILE: pkg/node/packet.go
  function NewAnnouncePacket (line 10) | func NewAnnouncePacket(n *NodeInfo) (string, error) {
  function ParseAnnouncePacket (line 21) | func ParseAnnouncePacket(size int, addr *net.UDPAddr, packet []byte) (*N...

FILE: pkg/node/serve.go
  function startAnnouncer (line 9) | func startAnnouncer(conf *config.Config, nodeList *list.List) {
  function Serve (line 16) | func Serve(conf *config.Config) {

FILE: pkg/node/utils.go
  function openUrl (line 10) | func openUrl(url string) error {

FILE: ui/src/App.js
  class App (line 8) | class App extends Component {
    method constructor (line 9) | constructor(props) {
    method collapse (line 27) | collapse(e) {
    method menuSelectedHandler (line 32) | menuSelectedHandler(index) {
    method render (line 38) | render() {

FILE: ui/src/components/FormField.js
  class FormField (line 3) | class FormField extends Component {
    method render (line 4) | render() {

FILE: ui/src/components/NodeDetails.js
  class NodeDetails (line 14) | class NodeDetails extends Component {
    method constructor (line 15) | constructor(props) {
    method componentWillReceiveProps (line 21) | componentWillReceiveProps(nextProps) {
    method onClickHandler (line 28) | onClickHandler() {
    method render (line 33) | render() {

FILE: ui/src/components/NodeList.js
  class NodeList (line 3) | class NodeList extends Component {
    method constructor (line 4) | constructor(props) {
    method onClickHandler (line 10) | onClickHandler(e) {
    method render (line 22) | render() {

FILE: ui/src/components/Panel.js
  class Panel (line 3) | class Panel extends Component {
    method render (line 4) | render() {

FILE: ui/src/components/SideBar.js
  class SideBar (line 4) | class SideBar extends Component {
    method constructor (line 5) | constructor(props) {
    method itemClickHandler (line 11) | itemClickHandler(e) {
    method render (line 24) | render() {

FILE: ui/src/containers/Discover.js
  class Discover (line 8) | class Discover extends Component {
    method constructor (line 9) | constructor(props) {
    method retrieveData (line 16) | retrieveData() {
    method componentDidMount (line 25) | componentDidMount() {
    method nodeSelectedHandler (line 28) | nodeSelectedHandler(index) {
    method render (line 33) | render() {

FILE: ui/src/containers/NodeInfo.js
  class NodeInfo (line 6) | class NodeInfo extends Component {
    method constructor (line 7) | constructor(props) {
    method componentDidMount (line 13) | componentDidMount() {
    method render (line 22) | render() {

FILE: vendor/github.com/Pallinder/go-randomdata/fullprofile.go
  type Profile (line 19) | type Profile struct
  function RandStringRunes (line 61) | func RandStringRunes(n int) string {
  function getMD5Hash (line 69) | func getMD5Hash(text string) string {
  function getSha1 (line 75) | func getSha1(text string) string {
  function getSha256 (line 82) | func getSha256(text string) string {
  function GenerateProfile (line 89) | func GenerateProfile(gender int) *Profile {

FILE: vendor/github.com/Pallinder/go-randomdata/postalcodes.go
  function PostalCode (line 18) | func PostalCode(countrycode string) string {
  function Letters (line 211) | func Letters(letters int) string {
  function Digits (line 222) | func Digits(digits int) string {
  function BoundedDigits (line 231) | func BoundedDigits(digits, low, high int) string {

FILE: vendor/github.com/Pallinder/go-randomdata/random_data.go
  constant Male (line 17) | Male         int = 0
  constant Female (line 18) | Female       int = 1
  constant RandomGender (line 19) | RandomGender int = 2
  constant Small (line 23) | Small int = 0
  constant Large (line 24) | Large int = 1
  constant FullCountry (line 28) | FullCountry      = 0
  constant TwoCharCountry (line 29) | TwoCharCountry   = 1
  constant ThreeCharCountry (line 30) | ThreeCharCountry = 2
  constant DateInputLayout (line 34) | DateInputLayout  = "2006-01-02"
  constant DateOutputLayout (line 35) | DateOutputLayout = "Monday 2 Jan 2006"
  type jsonContent (line 38) | type jsonContent struct
  function init (line 65) | func init() {
  function seedAndReturnRandom (line 75) | func seedAndReturnRandom(n int) int {
  function seedAndReturnRandomFloat (line 80) | func seedAndReturnRandomFloat() float64 {
  function randomFrom (line 86) | func randomFrom(source []string) string {
  function Title (line 91) | func Title(gender int) string {
  function FirstName (line 109) | func FirstName(gender int) string {
  function LastName (line 127) | func LastName() string {
  function FullName (line 132) | func FullName(gender int) string {
  function Email (line 137) | func Email() string {
  function Country (line 142) | func Country(countryStyle int64) string {
  function Currency (line 164) | func Currency() string {
  function City (line 169) | func City() string {
  function State (line 174) | func State(typeOfState int) string {
  function Street (line 182) | func Street() string {
  function Address (line 187) | func Address() string {
  function Paragraph (line 192) | func Paragraph() string {
  function Number (line 198) | func Number(numberRange ...int) int {
  function Decimal (line 210) | func Decimal(numberRange ...int) float64 {
  function StringNumberExt (line 227) | func StringNumberExt(numberPairs int, separator string, numberOfDigits i...
  function StringNumber (line 244) | func StringNumber(numberPairs int, separator string) string {
  function StringSample (line 249) | func StringSample(stringList ...string) string {
  function Boolean (line 257) | func Boolean() bool {
  function Noun (line 263) | func Noun() string {
  function Adjective (line 268) | func Adjective() string {
  function uppercaseFirstLetter (line 272) | func uppercaseFirstLetter(word string) string {
  function lowercaseFirstLetter (line 278) | func lowercaseFirstLetter(word string) string {
  function SillyName (line 285) | func SillyName() string {
  function IpV4Address (line 290) | func IpV4Address() string {
  function IpV6Address (line 301) | func IpV6Address() string {
  function MacAddress (line 311) | func MacAddress() string {
  function Day (line 322) | func Day() string {
  function Month (line 327) | func Month() string {
  function FullDate (line 332) | func FullDate() string {
  function FullDateInRange (line 346) | func FullDateInRange(dateRange ...string) string {
  function Timezone (line 370) | func Timezone() string {
  function UserAgentString (line 374) | func UserAgentString() string {

FILE: vendor/github.com/elazarl/go-bindata-assetfs/assetfs.go
  type FakeFile (line 21) | type FakeFile struct
    method Name (line 32) | func (f *FakeFile) Name() string {
    method Mode (line 37) | func (f *FakeFile) Mode() os.FileMode {
    method ModTime (line 45) | func (f *FakeFile) ModTime() time.Time {
    method Size (line 49) | func (f *FakeFile) Size() int64 {
    method IsDir (line 53) | func (f *FakeFile) IsDir() bool {
    method Sys (line 57) | func (f *FakeFile) Sys() interface{} {
  type AssetFile (line 62) | type AssetFile struct
    method Readdir (line 78) | func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
    method Size (line 82) | func (f *AssetFile) Size() int64 {
    method Stat (line 86) | func (f *AssetFile) Stat() (os.FileInfo, error) {
  function NewAssetFile (line 68) | func NewAssetFile(name string, content []byte, timestamp time.Time) *Ass...
  type AssetDirectory (line 91) | type AssetDirectory struct
    method Readdir (line 113) | func (f *AssetDirectory) Readdir(count int) ([]os.FileInfo, error) {
    method Stat (line 125) | func (f *AssetDirectory) Stat() (os.FileInfo, error) {
  function NewAssetDirectory (line 97) | func NewAssetDirectory(name string, children []string, fs *AssetFS) *Ass...
  type AssetFS (line 131) | type AssetFS struct
    method Open (line 142) | func (fs *AssetFS) Open(name string) (http.File, error) {

FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
  function Dir (line 26) | func Dir() (string, error) {
  function Expand (line 58) | func Expand(path string) (string, error) {
  function dirUnix (line 79) | func dirUnix() (string, error) {
  function dirWindows (line 120) | func dirWindows() (string, error) {

FILE: vendor/github.com/urfave/cli/app.go
  type App (line 27) | type App struct
    method Setup (line 130) | func (a *App) Setup() {
    method Run (line 178) | func (a *App) Run(arguments []string) (err error) {
    method RunAndExitOnError (line 279) | func (a *App) RunAndExitOnError() {
    method RunAsSubcommand (line 288) | func (a *App) RunAsSubcommand(ctx *Context) (err error) {
    method Command (line 395) | func (a *App) Command(name string) *Command {
    method Categories (line 406) | func (a *App) Categories() CommandCategories {
    method VisibleCategories (line 412) | func (a *App) VisibleCategories() []*CommandCategory {
    method VisibleCommands (line 430) | func (a *App) VisibleCommands() []Command {
    method VisibleFlags (line 441) | func (a *App) VisibleFlags() []Flag {
    method hasFlag (line 445) | func (a *App) hasFlag(flag Flag) bool {
    method errWriter (line 455) | func (a *App) errWriter() io.Writer {
    method appendFlag (line 464) | func (a *App) appendFlag(flag Flag) {
    method handleExitCoder (line 470) | func (a *App) handleExitCoder(context *Context, err error) {
  function compileTime (line 103) | func compileTime() time.Time {
  function NewApp (line 113) | func NewApp() *App {
  type Author (line 479) | type Author struct
    method String (line 485) | func (a Author) String() string {
  function HandleAction (line 497) | func HandleAction(action interface{}, context *Context) (err error) {

FILE: vendor/github.com/urfave/cli/category.go
  type CommandCategories (line 4) | type CommandCategories
    method Less (line 12) | func (c CommandCategories) Less(i, j int) bool {
    method Len (line 16) | func (c CommandCategories) Len() int {
    method Swap (line 20) | func (c CommandCategories) Swap(i, j int) {
    method AddCommand (line 25) | func (c CommandCategories) AddCommand(category string, command Command...
  type CommandCategory (line 7) | type CommandCategory struct
    method VisibleCommands (line 36) | func (c *CommandCategory) VisibleCommands() []Command {

FILE: vendor/github.com/urfave/cli/command.go
  type Command (line 12) | type Command struct
    method FullName (line 90) | func (c Command) FullName() string {
    method Run (line 101) | func (c Command) Run(ctx *Context) (err error) {
    method parseFlags (line 173) | func (c *Command) parseFlags(args Args) (*flag.FlagSet, error) {
    method Names (line 250) | func (c Command) Names() []string {
    method HasName (line 261) | func (c Command) HasName(name string) bool {
    method startApp (line 270) | func (c Command) startApp(ctx *Context) error {
    method VisibleFlags (line 333) | func (c Command) VisibleFlags() []Flag {
  type CommandsByName (line 74) | type CommandsByName
    method Len (line 76) | func (c CommandsByName) Len() int {
    method Less (line 80) | func (c CommandsByName) Less(i, j int) bool {
    method Swap (line 84) | func (c CommandsByName) Swap(i, j int) {
  type Commands (line 98) | type Commands
  function reorderArgs (line 206) | func reorderArgs(args []string) []string {
  function translateShortOptions (line 234) | func translateShortOptions(flagArgs Args) []string {

FILE: vendor/github.com/urfave/cli/context.go
  type Context (line 16) | type Context struct
    method NumFlags (line 37) | func (c *Context) NumFlags() int {
    method Set (line 42) | func (c *Context) Set(name, value string) error {
    method GlobalSet (line 48) | func (c *Context) GlobalSet(name, value string) error {
    method IsSet (line 54) | func (c *Context) IsSet(name string) bool {
    method GlobalIsSet (line 125) | func (c *Context) GlobalIsSet(name string) bool {
    method FlagNames (line 140) | func (c *Context) FlagNames() (names []string) {
    method GlobalFlagNames (line 152) | func (c *Context) GlobalFlagNames() (names []string) {
    method Parent (line 164) | func (c *Context) Parent() *Context {
    method value (line 169) | func (c *Context) value(name string) interface{} {
    method Args (line 177) | func (c *Context) Args() Args {
    method NArg (line 183) | func (c *Context) NArg() int {
  function NewContext (line 26) | func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
  type Args (line 174) | type Args
    method Get (line 188) | func (a Args) Get(n int) string {
    method First (line 196) | func (a Args) First() string {
    method Tail (line 202) | func (a Args) Tail() []string {
    method Present (line 210) | func (a Args) Present() bool {
    method Swap (line 215) | func (a Args) Swap(from, to int) error {
  function globalContext (line 223) | func globalContext(ctx *Context) *Context {
  function lookupGlobalFlagSet (line 236) | func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
  function copyFlag (line 248) | func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
  function normalizeFlags (line 256) | func normalizeFlags(flags []Flag, set *flag.FlagSet) error {

FILE: vendor/github.com/urfave/cli/errors.go
  type MultiError (line 18) | type MultiError struct
    method Error (line 28) | func (m MultiError) Error() string {
  function NewMultiError (line 23) | func NewMultiError(err ...error) MultiError {
  type ErrorFormatter (line 37) | type ErrorFormatter interface
  type ExitCoder (line 43) | type ExitCoder interface
  type ExitError (line 49) | type ExitError struct
    method Error (line 64) | func (ee *ExitError) Error() string {
    method ExitCode (line 70) | func (ee *ExitError) ExitCode() int {
  function NewExitError (line 55) | func NewExitError(message interface{}, exitCode int) *ExitError {
  function HandleExitCoder (line 78) | func HandleExitCoder(err error) {
  function handleMultiError (line 102) | func handleMultiError(multiErr MultiError) int {

FILE: vendor/github.com/urfave/cli/flag.go
  constant defaultPlaceholder (line 15) | defaultPlaceholder = "value"
  type FlagsByName (line 54) | type FlagsByName
    method Len (line 56) | func (f FlagsByName) Len() int {
    method Less (line 60) | func (f FlagsByName) Less(i, j int) bool {
    method Swap (line 64) | func (f FlagsByName) Swap(i, j int) {
  type Flag (line 71) | type Flag interface
  type errorableFlag (line 81) | type errorableFlag interface
  function flagSet (line 87) | func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
  function eachName (line 103) | func eachName(longName string, fn func(string)) {
  type Generic (line 112) | type Generic interface
  method Apply (line 120) | func (f GenericFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 126) | func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
  type StringSlice (line 142) | type StringSlice
    method Set (line 145) | func (f *StringSlice) Set(value string) error {
    method String (line 151) | func (f *StringSlice) String() string {
    method Value (line 156) | func (f *StringSlice) Value() []string {
    method Get (line 161) | func (f *StringSlice) Get() interface{} {
  method Apply (line 167) | func (f StringSliceFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 172) | func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
  type IntSlice (line 199) | type IntSlice
    method Set (line 202) | func (f *IntSlice) Set(value string) error {
    method String (line 212) | func (f *IntSlice) String() string {
    method Value (line 217) | func (f *IntSlice) Value() []int {
    method Get (line 222) | func (f *IntSlice) Get() interface{} {
  method Apply (line 228) | func (f IntSliceFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 233) | func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
  type Int64Slice (line 260) | type Int64Slice
    method Set (line 263) | func (f *Int64Slice) Set(value string) error {
    method String (line 273) | func (f *Int64Slice) String() string {
    method Value (line 278) | func (f *Int64Slice) Value() []int64 {
    method Get (line 283) | func (f *Int64Slice) Get() interface{} {
  method Apply (line 289) | func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 294) | func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 321) | func (f BoolFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 326) | func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 353) | func (f BoolTFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 358) | func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 386) | func (f StringFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 391) | func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 409) | func (f IntFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 414) | func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 436) | func (f Int64Flag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 441) | func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 464) | func (f UintFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 469) | func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 492) | func (f Uint64Flag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 497) | func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 520) | func (f DurationFlag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 525) | func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
  method Apply (line 548) | func (f Float64Flag) Apply(set *flag.FlagSet) {
  method ApplyWithError (line 553) | func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
  function visibleFlags (line 574) | func visibleFlags(fl []Flag) []Flag {
  function prefixFor (line 585) | func prefixFor(name string) (prefix string) {
  function unquoteUsage (line 596) | func unquoteUsage(usage string) (string, string) {
  function prefixedNames (line 612) | func prefixedNames(fullName, placeholder string) string {
  function withEnvHint (line 628) | func withEnvHint(envVar, str string) string {
  function withFileHint (line 644) | func withFileHint(filePath, str string) string {
  function flagValue (line 652) | func flagValue(f Flag) reflect.Value {
  function stringifyFlag (line 660) | func stringifyFlag(f Flag) string {
  function stringifyIntSliceFlag (line 723) | func stringifyIntSliceFlag(f IntSliceFlag) string {
  function stringifyInt64SliceFlag (line 734) | func stringifyInt64SliceFlag(f Int64SliceFlag) string {
  function stringifyStringSliceFlag (line 745) | func stringifyStringSliceFlag(f StringSliceFlag) string {
  function stringifySliceFlag (line 758) | func stringifySliceFlag(usage, name string, defaultVals []string) string {
  function flagFromFileEnv (line 773) | func flagFromFileEnv(filePath, envName string) (val string, ok bool) {

FILE: vendor/github.com/urfave/cli/flag_generated.go
  type BoolFlag (line 12) | type BoolFlag struct
    method String (line 23) | func (f BoolFlag) String() string {
    method GetName (line 28) | func (f BoolFlag) GetName() string {
  method Bool (line 34) | func (c *Context) Bool(name string) bool {
  method GlobalBool (line 40) | func (c *Context) GlobalBool(name string) bool {
  function lookupBool (line 47) | func lookupBool(name string, set *flag.FlagSet) bool {
  type BoolTFlag (line 60) | type BoolTFlag struct
    method String (line 71) | func (f BoolTFlag) String() string {
    method GetName (line 76) | func (f BoolTFlag) GetName() string {
  method BoolT (line 82) | func (c *Context) BoolT(name string) bool {
  method GlobalBoolT (line 88) | func (c *Context) GlobalBoolT(name string) bool {
  function lookupBoolT (line 95) | func lookupBoolT(name string, set *flag.FlagSet) bool {
  type DurationFlag (line 108) | type DurationFlag struct
    method String (line 120) | func (f DurationFlag) String() string {
    method GetName (line 125) | func (f DurationFlag) GetName() string {
  method Duration (line 131) | func (c *Context) Duration(name string) time.Duration {
  method GlobalDuration (line 137) | func (c *Context) GlobalDuration(name string) time.Duration {
  function lookupDuration (line 144) | func lookupDuration(name string, set *flag.FlagSet) time.Duration {
  type Float64Flag (line 157) | type Float64Flag struct
    method String (line 169) | func (f Float64Flag) String() string {
    method GetName (line 174) | func (f Float64Flag) GetName() string {
  method Float64 (line 180) | func (c *Context) Float64(name string) float64 {
  method GlobalFloat64 (line 186) | func (c *Context) GlobalFloat64(name string) float64 {
  function lookupFloat64 (line 193) | func lookupFloat64(name string, set *flag.FlagSet) float64 {
  type GenericFlag (line 206) | type GenericFlag struct
    method String (line 217) | func (f GenericFlag) String() string {
    method GetName (line 222) | func (f GenericFlag) GetName() string {
  method Generic (line 228) | func (c *Context) Generic(name string) interface{} {
  method GlobalGeneric (line 234) | func (c *Context) GlobalGeneric(name string) interface{} {
  function lookupGeneric (line 241) | func lookupGeneric(name string, set *flag.FlagSet) interface{} {
  type Int64Flag (line 254) | type Int64Flag struct
    method String (line 266) | func (f Int64Flag) String() string {
    method GetName (line 271) | func (f Int64Flag) GetName() string {
  method Int64 (line 277) | func (c *Context) Int64(name string) int64 {
  method GlobalInt64 (line 283) | func (c *Context) GlobalInt64(name string) int64 {
  function lookupInt64 (line 290) | func lookupInt64(name string, set *flag.FlagSet) int64 {
  type IntFlag (line 303) | type IntFlag struct
    method String (line 315) | func (f IntFlag) String() string {
    method GetName (line 320) | func (f IntFlag) GetName() string {
  method Int (line 326) | func (c *Context) Int(name string) int {
  method GlobalInt (line 332) | func (c *Context) GlobalInt(name string) int {
  function lookupInt (line 339) | func lookupInt(name string, set *flag.FlagSet) int {
  type IntSliceFlag (line 352) | type IntSliceFlag struct
    method String (line 363) | func (f IntSliceFlag) String() string {
    method GetName (line 368) | func (f IntSliceFlag) GetName() string {
  method IntSlice (line 374) | func (c *Context) IntSlice(name string) []int {
  method GlobalIntSlice (line 380) | func (c *Context) GlobalIntSlice(name string) []int {
  function lookupIntSlice (line 387) | func lookupIntSlice(name string, set *flag.FlagSet) []int {
  type Int64SliceFlag (line 400) | type Int64SliceFlag struct
    method String (line 411) | func (f Int64SliceFlag) String() string {
    method GetName (line 416) | func (f Int64SliceFlag) GetName() string {
  method Int64Slice (line 422) | func (c *Context) Int64Slice(name string) []int64 {
  method GlobalInt64Slice (line 428) | func (c *Context) GlobalInt64Slice(name string) []int64 {
  function lookupInt64Slice (line 435) | func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
  type StringFlag (line 448) | type StringFlag struct
    method String (line 460) | func (f StringFlag) String() string {
    method GetName (line 465) | func (f StringFlag) GetName() string {
  method String (line 471) | func (c *Context) String(name string) string {
  method GlobalString (line 477) | func (c *Context) GlobalString(name string) string {
  function lookupString (line 484) | func lookupString(name string, set *flag.FlagSet) string {
  type StringSliceFlag (line 497) | type StringSliceFlag struct
    method String (line 508) | func (f StringSliceFlag) String() string {
    method GetName (line 513) | func (f StringSliceFlag) GetName() string {
  method StringSlice (line 519) | func (c *Context) StringSlice(name string) []string {
  method GlobalStringSlice (line 525) | func (c *Context) GlobalStringSlice(name string) []string {
  function lookupStringSlice (line 532) | func lookupStringSlice(name string, set *flag.FlagSet) []string {
  type Uint64Flag (line 545) | type Uint64Flag struct
    method String (line 557) | func (f Uint64Flag) String() string {
    method GetName (line 562) | func (f Uint64Flag) GetName() string {
  method Uint64 (line 568) | func (c *Context) Uint64(name string) uint64 {
  method GlobalUint64 (line 574) | func (c *Context) GlobalUint64(name string) uint64 {
  function lookupUint64 (line 581) | func lookupUint64(name string, set *flag.FlagSet) uint64 {
  type UintFlag (line 594) | type UintFlag struct
    method String (line 606) | func (f UintFlag) String() string {
    method GetName (line 611) | func (f UintFlag) GetName() string {
  method Uint (line 617) | func (c *Context) Uint(name string) uint {
  method GlobalUint (line 623) | func (c *Context) GlobalUint(name string) uint {
  function lookupUint (line 630) | func lookupUint(name string, set *flag.FlagSet) uint {

FILE: vendor/github.com/urfave/cli/funcs.go
  type BashCompleteFunc (line 4) | type BashCompleteFunc
  type BeforeFunc (line 8) | type BeforeFunc
  type AfterFunc (line 12) | type AfterFunc
  type ActionFunc (line 15) | type ActionFunc
  type CommandNotFoundFunc (line 18) | type CommandNotFoundFunc
  type OnUsageErrorFunc (line 24) | type OnUsageErrorFunc
  type ExitErrHandlerFunc (line 28) | type ExitErrHandlerFunc
  type FlagStringFunc (line 32) | type FlagStringFunc
  type FlagNamePrefixFunc (line 36) | type FlagNamePrefixFunc
  type FlagEnvHintFunc (line 40) | type FlagEnvHintFunc
  type FlagFileHintFunc (line 44) | type FlagFileHintFunc

FILE: vendor/github.com/urfave/cli/help.go
  type helpPrinter (line 114) | type helpPrinter
  type helpPrinterCustom (line 117) | type helpPrinterCustom
  function ShowAppHelpAndExit (line 132) | func ShowAppHelpAndExit(c *Context, exitCode int) {
  function ShowAppHelp (line 138) | func ShowAppHelp(c *Context) (err error) {
  function DefaultAppComplete (line 156) | func DefaultAppComplete(c *Context) {
  function ShowCommandHelpAndExit (line 168) | func ShowCommandHelpAndExit(c *Context, command string, code int) {
  function ShowCommandHelp (line 174) | func ShowCommandHelp(ctx *Context, command string) error {
  function ShowSubcommandHelp (line 201) | func ShowSubcommandHelp(c *Context) error {
  function ShowVersion (line 206) | func ShowVersion(c *Context) {
  function printVersion (line 210) | func printVersion(c *Context) {
  function ShowCompletions (line 215) | func ShowCompletions(c *Context) {
  function ShowCommandCompletions (line 223) | func ShowCommandCompletions(ctx *Context, command string) {
  function printHelpCustom (line 230) | func printHelpCustom(out io.Writer, templ string, data interface{}, cust...
  function printHelp (line 254) | func printHelp(out io.Writer, templ string, data interface{}) {
  function checkVersion (line 258) | func checkVersion(c *Context) bool {
  function checkHelp (line 270) | func checkHelp(c *Context) bool {
  function checkCommandHelp (line 282) | func checkCommandHelp(c *Context, name string) bool {
  function checkSubcommandHelp (line 291) | func checkSubcommandHelp(c *Context) bool {
  function checkShellCompleteFlag (line 300) | func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
  function checkCompletions (line 315) | func checkCompletions(c *Context) bool {
  function checkCommandCompletions (line 332) | func checkCommandCompletions(c *Context, name string) bool {

FILE: vendor/github.com/urfave/cli/sort.go
  function lexicographicLess (line 6) | func lexicographicLess(i, j string) bool {

FILE: vendor/gopkg.in/yaml.v2/apic.go
  function yaml_insert_token (line 8) | func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token...
  function yaml_parser_initialize (line 28) | func yaml_parser_initialize(parser *yaml_parser_t) bool {
  function yaml_parser_delete (line 37) | func yaml_parser_delete(parser *yaml_parser_t) {
  function yaml_string_read_handler (line 42) | func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n i...
  function yaml_file_read_handler (line 52) | func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int...
  function yaml_parser_set_input_string (line 57) | func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
  function yaml_parser_set_input_file (line 67) | func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) {
  function yaml_parser_set_encoding (line 76) | func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encod...
  function yaml_emitter_initialize (line 84) | func yaml_emitter_initialize(emitter *yaml_emitter_t) bool {
  function yaml_emitter_delete (line 95) | func yaml_emitter_delete(emitter *yaml_emitter_t) {
  function yaml_string_write_handler (line 100) | func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) e...
  function yaml_file_write_handler (line 106) | func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) err...
  function yaml_emitter_set_output_string (line 112) | func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buff...
  function yaml_emitter_set_output_file (line 121) | func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Write...
  function yaml_emitter_set_encoding (line 130) | func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_en...
  function yaml_emitter_set_canonical (line 138) | func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
  function yaml_emitter_set_indent (line 143) | func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
  function yaml_emitter_set_width (line 151) | func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
  function yaml_emitter_set_unicode (line 159) | func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
  function yaml_emitter_set_break (line 164) | func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_bre...
  function yaml_stream_start_event_initialize (line 255) | func yaml_stream_start_event_initialize(event *yaml_event_t, encoding ya...
  function yaml_stream_end_event_initialize (line 264) | func yaml_stream_end_event_initialize(event *yaml_event_t) bool {
  function yaml_document_start_event_initialize (line 272) | func yaml_document_start_event_initialize(event *yaml_event_t, version_d...
  function yaml_document_end_event_initialize (line 284) | func yaml_document_end_event_initialize(event *yaml_event_t, implicit bo...
  function yaml_scalar_event_initialize (line 317) | func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, valu...
  function yaml_sequence_start_event_initialize (line 331) | func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, t...
  function yaml_sequence_end_event_initialize (line 343) | func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
  function yaml_mapping_start_event_initialize (line 351) | func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, ta...
  function yaml_mapping_end_event_initialize (line 363) | func yaml_mapping_end_event_initialize(event *yaml_event_t) bool {
  function yaml_event_delete (line 371) | func yaml_event_delete(event *yaml_event_t) {

FILE: vendor/gopkg.in/yaml.v2/decode.go
  constant documentNode (line 14) | documentNode = 1 << iota
  constant mappingNode (line 15) | mappingNode
  constant sequenceNode (line 16) | sequenceNode
  constant scalarNode (line 17) | scalarNode
  constant aliasNode (line 18) | aliasNode
  type node (line 21) | type node struct
  type parser (line 34) | type parser struct
    method destroy (line 60) | func (p *parser) destroy() {
    method skip (line 67) | func (p *parser) skip() {
    method fail (line 79) | func (p *parser) fail() {
    method anchor (line 99) | func (p *parser) anchor(n *node, anchor []byte) {
    method parse (line 105) | func (p *parser) parse() *node {
    method node (line 125) | func (p *parser) node(kind int) *node {
    method document (line 133) | func (p *parser) document() *node {
    method alias (line 146) | func (p *parser) alias() *node {
    method scalar (line 153) | func (p *parser) scalar() *node {
    method sequence (line 163) | func (p *parser) sequence() *node {
    method mapping (line 174) | func (p *parser) mapping() *node {
  function newParser (line 40) | func newParser(b []byte) *parser {
  type decoder (line 188) | type decoder struct
    method terror (line 209) | func (d *decoder) terror(n *node, tag string, out reflect.Value) {
    method callUnmarshaler (line 224) | func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
    method prepare (line 253) | func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect....
    method unmarshal (line 277) | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
    method document (line 301) | func (d *decoder) document(n *node, out reflect.Value) (good bool) {
    method alias (line 310) | func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
    method scalar (line 332) | func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
    method sequence (line 478) | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
    method mapping (line 510) | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
    method mappingSlice (line 572) | func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
    method mappingStruct (line 603) | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
    method merge (line 654) | func (d *decoder) merge(n *node, out reflect.Value) {
  function newDecoder (line 203) | func newDecoder(strict bool) *decoder {
  function resetMap (line 326) | func resetMap(out reflect.Value) {
  function settableValueOf (line 471) | func settableValueOf(i interface{}) reflect.Value {
  function failWantMap (line 650) | func failWantMap() {
  function isMerge (line 683) | func isMerge(n *node) bool {

FILE: vendor/gopkg.in/yaml.v2/emitterc.go
  function flush (line 8) | func flush(emitter *yaml_emitter_t) bool {
  function put (line 16) | func put(emitter *yaml_emitter_t, value byte) bool {
  function put_break (line 27) | func put_break(emitter *yaml_emitter_t) bool {
  function write (line 51) | func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
  function write_all (line 79) | func write_all(emitter *yaml_emitter_t, s []byte) bool {
  function write_break (line 89) | func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
  function yaml_emitter_set_emitter_error (line 106) | func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem str...
  function yaml_emitter_emit (line 113) | func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
  function yaml_emitter_need_more_events (line 136) | func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
  function yaml_emitter_append_tag_directive (line 173) | func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *y...
  function yaml_emitter_increase_indent (line 196) | func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentl...
  function yaml_emitter_state_machine (line 211) | func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_eve...
  function yaml_emitter_emit_stream_start (line 272) | func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml...
  function yaml_emitter_emit_document_start (line 311) | func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_emit_document_content (line 425) | func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *...
  function yaml_emitter_emit_document_end (line 431) | func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml...
  function yaml_emitter_emit_flow_sequence_item (line 456) | func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event...
  function yaml_emitter_emit_flow_mapping_key (line 504) | func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *...
  function yaml_emitter_emit_flow_mapping_value (line 558) | func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event...
  function yaml_emitter_emit_block_sequence_item (line 578) | func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, even...
  function yaml_emitter_emit_block_mapping_key (line 602) | func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event ...
  function yaml_emitter_emit_block_mapping_value (line 630) | func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, even...
  function yaml_emitter_emit_node (line 648) | func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
  function yaml_emitter_emit_alias (line 672) | func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_...
  function yaml_emitter_emit_scalar (line 682) | func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event...
  function yaml_emitter_emit_sequence_start (line 706) | func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_emit_mapping_start (line 723) | func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yam...
  function yaml_emitter_check_empty_document (line 740) | func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_empty_sequence (line 745) | func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_empty_mapping (line 754) | func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
  function yaml_emitter_check_simple_key (line 763) | func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
  function yaml_emitter_select_scalar_style (line 797) | func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *ya...
  function yaml_emitter_process_anchor (line 846) | func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
  function yaml_emitter_process_tag (line 861) | func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
  function yaml_emitter_process_scalar (line 890) | func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
  function yaml_emitter_analyze_version_directive (line 911) | func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, ver...
  function yaml_emitter_analyze_tag_directive (line 919) | func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_dir...
  function yaml_emitter_analyze_anchor (line 943) | func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte,...
  function yaml_emitter_analyze_tag (line 966) | func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
  function yaml_emitter_analyze_scalar (line 983) | func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) ...
  function yaml_emitter_analyze_event (line 1132) | func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_eve...
  function yaml_emitter_write_bom (line 1188) | func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
  function yaml_emitter_write_indent (line 1200) | func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
  function yaml_emitter_write_indicator (line 1220) | func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []b...
  function yaml_emitter_write_anchor (line 1235) | func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bo...
  function yaml_emitter_write_tag_handle (line 1244) | func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte...
  function yaml_emitter_write_tag_content (line 1258) | func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byt...
  function yaml_emitter_write_plain_scalar (line 1312) | func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []by...
  function yaml_emitter_write_single_quoted_scalar (line 1369) | func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, va...
  function yaml_emitter_write_double_quoted_scalar (line 1428) | func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, va...
  function yaml_emitter_write_block_scalar_hints (line 1549) | func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, valu...
  function yaml_emitter_write_literal_scalar (line 1591) | func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []...
  function yaml_emitter_write_folded_scalar (line 1628) | func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []b...

FILE: vendor/gopkg.in/yaml.v2/encode.go
  type encoder (line 14) | type encoder struct
    method finish (line 33) | func (e *encoder) finish() {
    method destroy (line 41) | func (e *encoder) destroy() {
    method emit (line 45) | func (e *encoder) emit() {
    method must (line 52) | func (e *encoder) must(ok bool) {
    method marshal (line 62) | func (e *encoder) marshal(tag string, in reflect.Value) {
    method mapv (line 127) | func (e *encoder) mapv(tag string, in reflect.Value) {
    method itemsv (line 138) | func (e *encoder) itemsv(tag string, in reflect.Value) {
    method structv (line 148) | func (e *encoder) structv(tag string, in reflect.Value) {
    method mappingv (line 187) | func (e *encoder) mappingv(tag string, f func()) {
    method slicev (line 201) | func (e *encoder) slicev(tag string, in reflect.Value) {
    method stringv (line 240) | func (e *encoder) stringv(tag string, in reflect.Value) {
    method boolv (line 264) | func (e *encoder) boolv(tag string, in reflect.Value) {
    method intv (line 274) | func (e *encoder) intv(tag string, in reflect.Value) {
    method uintv (line 279) | func (e *encoder) uintv(tag string, in reflect.Value) {
    method floatv (line 284) | func (e *encoder) floatv(tag string, in reflect.Value) {
    method nilv (line 298) | func (e *encoder) nilv() {
    method emitScalar (line 302) | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_sca...
  function newEncoder (line 21) | func newEncoder() (e *encoder) {
  function isBase60Float (line 223) | func isBase60Float(s string) (result bool) {

FILE: vendor/gopkg.in/yaml.v2/parserc.go
  function peek_token (line 46) | func peek_token(parser *yaml_parser_t) *yaml_token_t {
  function skip_token (line 54) | func skip_token(parser *yaml_parser_t) {
  function yaml_parser_parse (line 62) | func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
  function yaml_parser_set_parser_error (line 76) | func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string,...
  function yaml_parser_set_parser_error_context (line 83) | func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context...
  function yaml_parser_state_machine (line 93) | func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_...
  function yaml_parser_parse_stream_start (line 174) | func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_e...
  function yaml_parser_parse_document_start (line 198) | func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml...
  function yaml_parser_parse_document_content (line 282) | func yaml_parser_parse_document_content(parser *yaml_parser_t, event *ya...
  function yaml_parser_parse_document_end (line 305) | func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_e...
  function yaml_parser_parse_node (line 359) | func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, ...
  function yaml_parser_parse_block_sequence_entry (line 579) | func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event...
  function yaml_parser_parse_indentless_sequence_entry (line 631) | func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, ...
  function yaml_parser_parse_block_mapping_key (line 675) | func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *y...
  function yaml_parser_parse_block_mapping_value (line 733) | func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event ...
  function yaml_parser_parse_flow_sequence_entry (line 770) | func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event ...
  function yaml_parser_parse_flow_sequence_entry_mapping_key (line 833) | func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_pars...
  function yaml_parser_parse_flow_sequence_entry_mapping_value (line 854) | func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_pa...
  function yaml_parser_parse_flow_sequence_entry_mapping_end (line 878) | func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_pars...
  function yaml_parser_parse_flow_mapping_key (line 904) | func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *ya...
  function yaml_parser_parse_flow_mapping_value (line 970) | func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *...
  function yaml_parser_process_empty_scalar (line 995) | func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml...
  function yaml_parser_process_directives (line 1013) | func yaml_parser_process_directives(parser *yaml_parser_t,
  function yaml_parser_append_tag_directive (line 1075) | func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_...

FILE: vendor/gopkg.in/yaml.v2/readerc.go
  function yaml_parser_set_reader_error (line 8) | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string,...
  constant bom_UTF8 (line 18) | bom_UTF8    = "\xef\xbb\xbf"
  constant bom_UTF16LE (line 19) | bom_UTF16LE = "\xff\xfe"
  constant bom_UTF16BE (line 20) | bom_UTF16BE = "\xfe\xff"
  function yaml_parser_determine_encoding (line 25) | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
  function yaml_parser_update_raw_buffer (line 56) | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
  function yaml_parser_update_buffer (line 91) | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {

FILE: vendor/gopkg.in/yaml.v2/resolve.go
  type resolveMapItem (line 12) | type resolveMapItem struct
  function init (line 20) | func init() {
  constant longTagPrefix (line 59) | longTagPrefix = "tag:yaml.org,2002:"
  function shortTag (line 61) | func shortTag(tag string) string {
  function longTag (line 69) | func longTag(tag string) string {
  function resolvableTag (line 76) | func resolvableTag(tag string) bool {
  function resolve (line 86) | func resolve(tag string, in string) (rtag string, out interface{}) {
  function encodeBase64 (line 187) | func encodeBase64(s string) string {

FILE: vendor/gopkg.in/yaml.v2/scannerc.go
  function cache (line 485) | func cache(parser *yaml_parser_t, length int) bool {
  function skip (line 491) | func skip(parser *yaml_parser_t) {
  function skip_line (line 498) | func skip_line(parser *yaml_parser_t) {
  function read (line 515) | func read(parser *yaml_parser_t, s []byte) []byte {
  function read_line (line 538) | func read_line(parser *yaml_parser_t, s []byte) []byte {
  function yaml_parser_scan (line 571) | func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
  function yaml_parser_set_scanner_error (line 600) | func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string...
  function yaml_parser_set_scanner_tag_error (line 609) | func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive ...
  function trace (line 617) | func trace(args ...interface{}) func() {
  function yaml_parser_fetch_more_tokens (line 626) | func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_next_token (line 665) | func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
  function yaml_parser_stale_simple_keys (line 842) | func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {
  function yaml_parser_save_simple_key (line 867) | func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
  function yaml_parser_remove_simple_key (line 900) | func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
  function yaml_parser_increase_flow_level (line 916) | func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
  function yaml_parser_decrease_flow_level (line 926) | func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
  function yaml_parser_roll_indent (line 937) | func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, ...
  function yaml_parser_unroll_indent (line 966) | func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
  function yaml_parser_fetch_stream_start (line 990) | func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_stream_end (line 1016) | func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_directive (line 1047) | func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_document_indicator (line 1071) | func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yam...
  function yaml_parser_fetch_flow_collection_start (line 1105) | func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ ...
  function yaml_parser_fetch_flow_collection_end (line 1136) | func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ ya...
  function yaml_parser_fetch_flow_entry (line 1168) | func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_block_entry (line 1193) | func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_key (line 1235) | func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_value (line 1274) | func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_anchor (line 1339) | func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type...
  function yaml_parser_fetch_tag (line 1358) | func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
  function yaml_parser_fetch_block_scalar (line 1377) | func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool)...
  function yaml_parser_fetch_flow_scalar (line 1396) | func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) b...
  function yaml_parser_fetch_plain_scalar (line 1415) | func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
  function yaml_parser_scan_to_next_token (line 1434) | func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
  function yaml_parser_scan_directive (line 1499) | func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token...
  function yaml_parser_scan_directive_name (line 1600) | func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark y...
  function yaml_parser_scan_version_directive_value (line 1636) | func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, sta...
  constant max_number_length (line 1668) | max_number_length = 2
  function yaml_parser_scan_version_directive_number (line 1677) | func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, st...
  function yaml_parser_scan_tag_directive_value (line 1713) | func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_m...
  function yaml_parser_scan_anchor (line 1771) | func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t,...
  function yaml_parser_scan_tag (line 1829) | func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bo...
  function yaml_parser_scan_tag_handle (line 1914) | func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, ...
  function yaml_parser_scan_tag_uri (line 1959) | func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, hea...
  function yaml_parser_scan_uri_escapes (line 2017) | func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool,...
  function yaml_parser_scan_block_scalar (line 2063) | func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_to...
  function yaml_parser_scan_block_scalar_breaks (line 2251) | func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent ...
  function yaml_parser_scan_flow_scalar (line 2305) | func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_tok...
  function yaml_parser_scan_plain_scalar (line 2561) | func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_to...

FILE: vendor/gopkg.in/yaml.v2/sorter.go
  type keyList (line 8) | type keyList
    method Len (line 10) | func (l keyList) Len() int      { return len(l) }
    method Swap (line 11) | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
    method Less (line 12) | func (l keyList) Less(i, j int) bool {
  function keyFloat (line 73) | func keyFloat(v reflect.Value) (f float64, ok bool) {
  function numLess (line 92) | func numLess(a, b reflect.Value) bool {

FILE: vendor/gopkg.in/yaml.v2/writerc.go
  function yaml_emitter_set_writer_error (line 4) | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem stri...
  function yaml_emitter_flush (line 11) | func yaml_emitter_flush(emitter *yaml_emitter_t) bool {

FILE: vendor/gopkg.in/yaml.v2/yaml.go
  type MapSlice (line 19) | type MapSlice
  type MapItem (line 22) | type MapItem struct
  type Unmarshaler (line 31) | type Unmarshaler interface
  type Marshaler (line 41) | type Marshaler interface
  function Unmarshal (line 79) | func Unmarshal(in []byte, out interface{}) (err error) {
  function UnmarshalStrict (line 86) | func UnmarshalStrict(in []byte, out interface{}) (err error) {
  function unmarshal (line 90) | func unmarshal(in []byte, out interface{}, strict bool) (err error) {
  function Marshal (line 149) | func Marshal(in interface{}) (out []byte, err error) {
  function handleErr (line 159) | func handleErr(err *error) {
  type yamlError (line 169) | type yamlError struct
  function fail (line 173) | func fail(err error) {
  function failf (line 177) | func failf(format string, args ...interface{}) {
  type TypeError (line 185) | type TypeError struct
    method Error (line 189) | func (e *TypeError) Error() string {
  type structInfo (line 200) | type structInfo struct
  type fieldInfo (line 209) | type fieldInfo struct
  function getStructInfo (line 222) | func getStructInfo(st reflect.Type) (*structInfo, error) {
  function isZero (line 326) | func isZero(v reflect.Value) bool {

FILE: vendor/gopkg.in/yaml.v2/yamlh.go
  type yaml_version_directive_t (line 8) | type yaml_version_directive_t struct
  type yaml_tag_directive_t (line 14) | type yaml_tag_directive_t struct
  type yaml_encoding_t (line 19) | type yaml_encoding_t
  constant yaml_ANY_ENCODING (line 24) | yaml_ANY_ENCODING yaml_encoding_t = iota
  constant yaml_UTF8_ENCODING (line 26) | yaml_UTF8_ENCODING
  constant yaml_UTF16LE_ENCODING (line 27) | yaml_UTF16LE_ENCODING
  constant yaml_UTF16BE_ENCODING (line 28) | yaml_UTF16BE_ENCODING
  type yaml_break_t (line 31) | type yaml_break_t
  constant yaml_ANY_BREAK (line 36) | yaml_ANY_BREAK yaml_break_t = iota
  constant yaml_CR_BREAK (line 38) | yaml_CR_BREAK
  constant yaml_LN_BREAK (line 39) | yaml_LN_BREAK
  constant yaml_CRLN_BREAK (line 40) | yaml_CRLN_BREAK
  type yaml_error_type_t (line 43) | type yaml_error_type_t
  constant yaml_NO_ERROR (line 48) | yaml_NO_ERROR yaml_error_type_t = iota
  constant yaml_MEMORY_ERROR (line 50) | yaml_MEMORY_ERROR
  constant yaml_READER_ERROR (line 51) | yaml_READER_ERROR
  constant yaml_SCANNER_ERROR (line 52) | yaml_SCANNER_ERROR
  constant yaml_PARSER_ERROR (line 53) | yaml_PARSER_ERROR
  constant yaml_COMPOSER_ERROR (line 54) | yaml_COMPOSER_ERROR
  constant yaml_WRITER_ERROR (line 55) | yaml_WRITER_ERROR
  constant yaml_EMITTER_ERROR (line 56) | yaml_EMITTER_ERROR
  type yaml_mark_t (line 60) | type yaml_mark_t struct
  type yaml_style_t (line 68) | type yaml_style_t
  type yaml_scalar_style_t (line 70) | type yaml_scalar_style_t
  constant yaml_ANY_SCALAR_STYLE (line 75) | yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
  constant yaml_PLAIN_SCALAR_STYLE (line 77) | yaml_PLAIN_SCALAR_STYLE
  constant yaml_SINGLE_QUOTED_SCALAR_STYLE (line 78) | yaml_SINGLE_QUOTED_SCALAR_STYLE
  constant yaml_DOUBLE_QUOTED_SCALAR_STYLE (line 79) | yaml_DOUBLE_QUOTED_SCALAR_STYLE
  constant yaml_LITERAL_SCALAR_STYLE (line 80) | yaml_LITERAL_SCALAR_STYLE
  constant yaml_FOLDED_SCALAR_STYLE (line 81) | yaml_FOLDED_SCALAR_STYLE
  type yaml_sequence_style_t (line 84) | type yaml_sequence_style_t
  constant yaml_ANY_SEQUENCE_STYLE (line 89) | yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
  constant yaml_BLOCK_SEQUENCE_STYLE (line 91) | yaml_BLOCK_SEQUENCE_STYLE
  constant yaml_FLOW_SEQUENCE_STYLE (line 92) | yaml_FLOW_SEQUENCE_STYLE
  type yaml_mapping_style_t (line 95) | type yaml_mapping_style_t
  constant yaml_ANY_MAPPING_STYLE (line 100) | yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
  constant yaml_BLOCK_MAPPING_STYLE (line 102) | yaml_BLOCK_MAPPING_STYLE
  constant yaml_FLOW_MAPPING_STYLE (line 103) | yaml_FLOW_MAPPING_STYLE
  type yaml_token_type_t (line 108) | type yaml_token_type_t
    method String (line 143) | func (tt yaml_token_type_t) String() string {
  constant yaml_NO_TOKEN (line 113) | yaml_NO_TOKEN yaml_token_type_t = iota
  constant yaml_STREAM_START_TOKEN (line 115) | yaml_STREAM_START_TOKEN
  constant yaml_STREAM_END_TOKEN (line 116) | yaml_STREAM_END_TOKEN
  constant yaml_VERSION_DIRECTIVE_TOKEN (line 118) | yaml_VERSION_DIRECTIVE_TOKEN
  constant yaml_TAG_DIRECTIVE_TOKEN (line 119) | yaml_TAG_DIRECTIVE_TOKEN
  constant yaml_DOCUMENT_START_TOKEN (line 120) | yaml_DOCUMENT_START_TOKEN
  constant yaml_DOCUMENT_END_TOKEN (line 121) | yaml_DOCUMENT_END_TOKEN
  constant yaml_BLOCK_SEQUENCE_START_TOKEN (line 123) | yaml_BLOCK_SEQUENCE_START_TOKEN
  constant yaml_BLOCK_MAPPING_START_TOKEN (line 124) | yaml_BLOCK_MAPPING_START_TOKEN
  constant yaml_BLOCK_END_TOKEN (line 125) | yaml_BLOCK_END_TOKEN
  constant yaml_FLOW_SEQUENCE_START_TOKEN (line 127) | yaml_FLOW_SEQUENCE_START_TOKEN
  constant yaml_FLOW_SEQUENCE_END_TOKEN (line 128) | yaml_FLOW_SEQUENCE_END_TOKEN
  constant yaml_FLOW_MAPPING_START_TOKEN (line 129) | yaml_FLOW_MAPPING_START_TOKEN
  constant yaml_FLOW_MAPPING_END_TOKEN (line 130) | yaml_FLOW_MAPPING_END_TOKEN
  constant yaml_BLOCK_ENTRY_TOKEN (line 132) | yaml_BLOCK_ENTRY_TOKEN
  constant yaml_FLOW_ENTRY_TOKEN (line 133) | yaml_FLOW_ENTRY_TOKEN
  constant yaml_KEY_TOKEN (line 134) | yaml_KEY_TOKEN
  constant yaml_VALUE_TOKEN (line 135) | yaml_VALUE_TOKEN
  constant yaml_ALIAS_TOKEN (line 137) | yaml_ALIAS_TOKEN
  constant yaml_ANCHOR_TOKEN (line 138) | yaml_ANCHOR_TOKEN
  constant yaml_TAG_TOKEN (line 139) | yaml_TAG_TOKEN
  constant yaml_SCALAR_TOKEN (line 140) | yaml_SCALAR_TOKEN
  type yaml_token_t (line 194) | type yaml_token_t struct
  type yaml_event_type_t (line 223) | type yaml_event_type_t
  constant yaml_NO_EVENT (line 228) | yaml_NO_EVENT yaml_event_type_t = iota
  constant yaml_STREAM_START_EVENT (line 230) | yaml_STREAM_START_EVENT
  constant yaml_STREAM_END_EVENT (line 231) | yaml_STREAM_END_EVENT
  constant yaml_DOCUMENT_START_EVENT (line 232) | yaml_DOCUMENT_START_EVENT
  constant yaml_DOCUMENT_END_EVENT (line 233) | yaml_DOCUMENT_END_EVENT
  constant yaml_ALIAS_EVENT (line 234) | yaml_ALIAS_EVENT
  constant yaml_SCALAR_EVENT (line 235) | yaml_SCALAR_EVENT
  constant yaml_SEQUENCE_START_EVENT (line 236) | yaml_SEQUENCE_START_EVENT
  constant yaml_SEQUENCE_END_EVENT (line 237) | yaml_SEQUENCE_END_EVENT
  constant yaml_MAPPING_START_EVENT (line 238) | yaml_MAPPING_START_EVENT
  constant yaml_MAPPING_END_EVENT (line 239) | yaml_MAPPING_END_EVENT
  type yaml_event_t (line 243) | type yaml_event_t struct
    method scalar_style (line 280) | func (e *yaml_event_t) scalar_style() yaml_scalar_style_t     { return...
    method sequence_style (line 281) | func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return...
    method mapping_style (line 282) | func (e *yaml_event_t) mapping_style() yaml_mapping_style_t   { return...
  constant yaml_NULL_TAG (line 287) | yaml_NULL_TAG      = "tag:yaml.org,2002:null"
  constant yaml_BOOL_TAG (line 288) | yaml_BOOL_TAG      = "tag:yaml.org,2002:bool"
  constant yaml_STR_TAG (line 289) | yaml_STR_TAG       = "tag:yaml.org,2002:str"
  constant yaml_INT_TAG (line 290) | yaml_INT_TAG       = "tag:yaml.org,2002:int"
  constant yaml_FLOAT_TAG (line 291) | yaml_FLOAT_TAG     = "tag:yaml.org,2002:float"
  constant yaml_TIMESTAMP_TAG (line 292) | yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp"
  constant yaml_SEQ_TAG (line 294) | yaml_SEQ_TAG = "tag:yaml.org,2002:seq"
  constant yaml_MAP_TAG (line 295) | yaml_MAP_TAG = "tag:yaml.org,2002:map"
  constant yaml_BINARY_TAG (line 298) | yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
  constant yaml_MERGE_TAG (line 299) | yaml_MERGE_TAG  = "tag:yaml.org,2002:merge"
  constant yaml_DEFAULT_SCALAR_TAG (line 301) | yaml_DEFAULT_SCALAR_TAG   = yaml_STR_TAG
  constant yaml_DEFAULT_SEQUENCE_TAG (line 302) | yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG
  constant yaml_DEFAULT_MAPPING_TAG (line 303) | yaml_DEFAULT_MAPPING_TAG  = yaml_MAP_TAG
  type yaml_node_type_t (line 306) | type yaml_node_type_t
  constant yaml_NO_NODE (line 311) | yaml_NO_NODE yaml_node_type_t = iota
  constant yaml_SCALAR_NODE (line 313) | yaml_SCALAR_NODE
  constant yaml_SEQUENCE_NODE (line 314) | yaml_SEQUENCE_NODE
  constant yaml_MAPPING_NODE (line 315) | yaml_MAPPING_NODE
  type yaml_node_item_t (line 319) | type yaml_node_item_t
  type yaml_node_pair_t (line 322) | type yaml_node_pair_t struct
  type yaml_node_t (line 328) | type yaml_node_t struct
  type yaml_document_t (line 362) | type yaml_document_t struct
  type yaml_read_handler_t (line 397) | type yaml_read_handler_t
  type yaml_simple_key_t (line 400) | type yaml_simple_key_t struct
  type yaml_parser_state_t (line 408) | type yaml_parser_state_t
    method String (line 438) | func (ps yaml_parser_state_t) String() string {
  constant yaml_PARSE_STREAM_START_STATE (line 411) | yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
  constant yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE (line 413) | yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
  constant yaml_PARSE_DOCUMENT_START_STATE (line 414) | yaml_PARSE_DOCUMENT_START_STATE
  constant yaml_PARSE_DOCUMENT_CONTENT_STATE (line 415) | yaml_PARSE_DOCUMENT_CONTENT_STATE
  constant yaml_PARSE_DOCUMENT_END_STATE (line 416) | yaml_PARSE_DOCUMENT_END_STATE
  constant yaml_PARSE_BLOCK_NODE_STATE (line 417) | yaml_PARSE_BLOCK_NODE_STATE
  constant yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE (line 418) | yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE
  constant yaml_PARSE_FLOW_NODE_STATE (line 419) | yaml_PARSE_FLOW_NODE_STATE
  constant yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE (line 420) | yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
  constant yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE (line 421) | yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE (line 422) | yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE (line 423) | yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_KEY_STATE (line 424) | yaml_PARSE_BLOCK_MAPPING_KEY_STATE
  constant yaml_PARSE_BLOCK_MAPPING_VALUE_STATE (line 425) | yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE (line 426) | yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE (line 427) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE (line 428) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE (line 429) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE (line 430) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
  constant yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE (line 431) | yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
  constant yaml_PARSE_FLOW_MAPPING_KEY_STATE (line 432) | yaml_PARSE_FLOW_MAPPING_KEY_STATE
  constant yaml_PARSE_FLOW_MAPPING_VALUE_STATE (line 433) | yaml_PARSE_FLOW_MAPPING_VALUE_STATE
  constant yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE (line 434) | yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
  constant yaml_PARSE_END_STATE (line 435) | yaml_PARSE_END_STATE
  type yaml_alias_data_t (line 493) | type yaml_alias_data_t struct
  type yaml_parser_t (line 503) | type yaml_parser_t struct
  type yaml_write_handler_t (line 591) | type yaml_write_handler_t
  type yaml_emitter_state_t (line 593) | type yaml_emitter_state_t
  constant yaml_EMIT_STREAM_START_STATE (line 598) | yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
  constant yaml_EMIT_FIRST_DOCUMENT_START_STATE (line 600) | yaml_EMIT_FIRST_DOCUMENT_START_STATE
  constant yaml_EMIT_DOCUMENT_START_STATE (line 601) | yaml_EMIT_DOCUMENT_START_STATE
  constant yaml_EMIT_DOCUMENT_CONTENT_STATE (line 602) | yaml_EMIT_DOCUMENT_CONTENT_STATE
  constant yaml_EMIT_DOCUMENT_END_STATE (line 603) | yaml_EMIT_DOCUMENT_END_STATE
  constant yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE (line 604) | yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
  constant yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE (line 605) | yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE
  constant yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE (line 606) | yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
  constant yaml_EMIT_FLOW_MAPPING_KEY_STATE (line 607) | yaml_EMIT_FLOW_MAPPING_KEY_STATE
  constant yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE (line 608) | yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE
  constant yaml_EMIT_FLOW_MAPPING_VALUE_STATE (line 609) | yaml_EMIT_FLOW_MAPPING_VALUE_STATE
  constant yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE (line 610) | yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
  constant yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE (line 611) | yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE
  constant yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE (line 612) | yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
  constant yaml_EMIT_BLOCK_MAPPING_KEY_STATE (line 613) | yaml_EMIT_BLOCK_MAPPING_KEY_STATE
  constant yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE (line 614) | yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE
  constant yaml_EMIT_BLOCK_MAPPING_VALUE_STATE (line 615) | yaml_EMIT_BLOCK_MAPPING_VALUE_STATE
  constant yaml_EMIT_END_STATE (line 616) | yaml_EMIT_END_STATE
  type yaml_emitter_t (line 623) | type yaml_emitter_t struct

FILE: vendor/gopkg.in/yaml.v2/yamlprivateh.go
  constant input_raw_buffer_size (line 5) | input_raw_buffer_size = 512
  constant input_buffer_size (line 9) | input_buffer_size = input_raw_buffer_size * 3
  constant output_buffer_size (line 12) | output_buffer_size = 128
  constant output_raw_buffer_size (line 16) | output_raw_buffer_size = (output_buffer_size*2 + 2)
  constant initial_stack_size (line 19) | initial_stack_size  = 16
  constant initial_queue_size (line 20) | initial_queue_size  = 16
  constant initial_string_size (line 21) | initial_string_size = 16
  function is_alpha (line 26) | func is_alpha(b []byte, i int) bool {
  function is_digit (line 31) | func is_digit(b []byte, i int) bool {
  function as_digit (line 36) | func as_digit(b []byte, i int) int {
  function is_hex (line 41) | func is_hex(b []byte, i int) bool {
  function as_hex (line 46) | func as_hex(b []byte, i int) int {
  function is_ascii (line 58) | func is_ascii(b []byte, i int) bool {
  function is_printable (line 63) | func is_printable(b []byte, i int) bool {
  function is_z (line 76) | func is_z(b []byte, i int) bool {
  function is_bom (line 81) | func is_bom(b []byte, i int) bool {
  function is_space (line 86) | func is_space(b []byte, i int) bool {
  function is_tab (line 91) | func is_tab(b []byte, i int) bool {
  function is_blank (line 96) | func is_blank(b []byte, i int) bool {
  function is_break (line 102) | func is_break(b []byte, i int) bool {
  function is_crlf (line 110) | func is_crlf(b []byte, i int) bool {
  function is_breakz (line 115) | func is_breakz(b []byte, i int) bool {
  function is_spacez (line 128) | func is_spacez(b []byte, i int) bool {
  function is_blankz (line 142) | func is_blankz(b []byte, i int) bool {
  function width (line 156) | func width(b byte) int {
Condensed preview — 87 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (614K chars).
[
  {
    "path": ".gitignore",
    "chars": 13,
    "preview": "dist/\nbuild/\n"
  },
  {
    "path": ".travis.yml",
    "chars": 558,
    "preview": "language: go\ninstall: true\nsudo: required\n\nbefore_install:\n  - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo "
  },
  {
    "path": "Dockerfile",
    "chars": 604,
    "preview": "FROM debian:latest\n\nCOPY ./dist/gocho /usr/local/bin/gocho\n\nRUN chmod +x /usr/local/bin/gocho \\\n    && mkdir -p /root/pu"
  },
  {
    "path": "LICENSE",
    "chars": 1102,
    "preview": "MIT License\n\nCopyright (c) 2018 Sergio Guillen Mantilla<serguimant@gmail.com>\n\nPermission is hereby granted, free of cha"
  },
  {
    "path": "Makefile",
    "chars": 1707,
    "preview": "VERSION = 0.2.0\nGOPATH := $(PWD)/build:$(GOPATH)\n\nbuild-dev:\n\t@echo \"Building gocho\"\n\trm -rf build && mkdir -p build/src"
  },
  {
    "path": "README.md",
    "chars": 2829,
    "preview": "Gocho - Local Network File Sharing [![Build Status](https://travis-ci.org/donkeysharp/gocho.svg?branch=master)](https://"
  },
  {
    "path": "assets/.gitignore",
    "chars": 14,
    "preview": "assets_gen.go\n"
  },
  {
    "path": "assets/assets.go",
    "chars": 212,
    "preview": "package assets\n\nimport (\n\t\"github.com/elazarl/go-bindata-assetfs\"\n)\n\nfunc AssetFS() *assetfs.AssetFS {\n\treturn &assetfs."
  },
  {
    "path": "cmd/gocho/gocho.go",
    "chars": 201,
    "preview": "package main\n\n//go:generate go-bindata -o ../../assets/assets_gen.go -pkg assets ../../ui/build/...\n\nimport (\n\t\"github.c"
  },
  {
    "path": "docs/building.md",
    "chars": 2276,
    "preview": "Building Instructions\n=====================\n\n## Requirements\nYou need these tools installed in order to develop Gocho:\n\n"
  },
  {
    "path": "pkg/cmds/cmds.go",
    "chars": 2202,
    "preview": "package cmds\n\nimport (\n\t\"fmt\"\n\t\"github.com/donkeysharp/gocho/pkg/config\"\n\t\"github.com/donkeysharp/gocho/pkg/info\"\n\t\"gith"
  },
  {
    "path": "pkg/config/config.go",
    "chars": 1096,
    "preview": "package config\n\nimport (\n\t\"fmt\"\n\tyaml \"gopkg.in/yaml.v2\"\n\t\"io/ioutil\"\n)\n\ntype Config struct {\n\tNodeId         string `ya"
  },
  {
    "path": "pkg/config/utils.go",
    "chars": 1206,
    "preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"github.com/Pallinder/go-randomdata\"\n\thomedir \"github.com/mitchellh/go-homedir\"\n\t\"io/io"
  },
  {
    "path": "pkg/config/wizard.go",
    "chars": 1355,
    "preview": "package config\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc configureWizard() error {\n\treader := bufio.NewReader(o"
  },
  {
    "path": "pkg/info/info.go",
    "chars": 69,
    "preview": "package info\n\nconst (\n\tAPP_NAME = \"gocho\"\n\tVERSION  = \"0.2.0-alfa\"\n)\n"
  },
  {
    "path": "pkg/node/dashboard.go",
    "chars": 1583,
    "preview": "package node\n\nimport (\n\t\"container/list\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"github.com/donkeysharp/gocho/assets\"\n\t\"github.com/don"
  },
  {
    "path": "pkg/node/index.go",
    "chars": 3406,
    "preview": "package node\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"github.com/donkeysharp/gocho/pkg/config\"\n\t\"net/http\"\n\t\"regexp\"\n)\n\nconst (\n\tHTML"
  },
  {
    "path": "pkg/node/net.go",
    "chars": 2483,
    "preview": "package node\n\nimport (\n\t\"container/list\"\n\t\"fmt\"\n\t\"net\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar (\n\tnodeMutex sync.Mutex\n)\n\nfunc announceNo"
  },
  {
    "path": "pkg/node/node.go",
    "chars": 804,
    "preview": "package node\n\nimport (\n\t\"container/list\"\n\t\"github.com/donkeysharp/gocho/pkg/config\"\n)\n\nconst (\n\tMULTICAST_ADDRESS     = "
  },
  {
    "path": "pkg/node/packet.go",
    "chars": 1129,
    "preview": "package node\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n)\n\nfunc NewAnnouncePacket(n *NodeInfo) (string, error) "
  },
  {
    "path": "pkg/node/serve.go",
    "chars": 521,
    "preview": "package node\n\nimport (\n\t\"container/list\"\n\t\"github.com/donkeysharp/gocho/pkg/config\"\n\t\"time\"\n)\n\nfunc startAnnouncer(conf "
  },
  {
    "path": "pkg/node/utils.go",
    "chars": 496,
    "preview": "package node\n\nimport (\n\t\"os/exec\"\n\t\"runtime\"\n)\n\n// https://stackoverflow.com/a/39324149/916063\n// open opens the specifi"
  },
  {
    "path": "ui/.gitignore",
    "chars": 285,
    "preview": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n\n# testing\n/cov"
  },
  {
    "path": "ui/package.json",
    "chars": 665,
    "preview": "{\n  \"name\": \"ui\",\n  \"version\": \"0.1.0\",\n  \"private\": false,\n  \"proxy\": \"http://localhost:1337\",\n  \"dependencies\": {\n    "
  },
  {
    "path": "ui/public/index.html",
    "chars": 1637,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "ui/public/lang/en.json",
    "chars": 956,
    "preview": "{\n    \"menus\": [\n        {\n            \"node_information\": \"Node Information\"\n        },\n        {\n            \"discover"
  },
  {
    "path": "ui/public/lang/es.json",
    "chars": 1024,
    "preview": "{\n    \"menus\": [\n        {\n            \"node_information\": \"Información del Nodo\"\n        },\n        {\n            \"disc"
  },
  {
    "path": "ui/src/App.css",
    "chars": 2812,
    "preview": "@import \"https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700\";\n\nbody {\n  font-family: 'Poppins', sans-se"
  },
  {
    "path": "ui/src/App.js",
    "chars": 1659,
    "preview": "import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\nimport SideBar from './compon"
  },
  {
    "path": "ui/src/components/FormField.js",
    "chars": 632,
    "preview": "import React, {Component} from 'react';\n\nclass FormField extends Component {\n  render() {\n    let disabled = 'false';\n  "
  },
  {
    "path": "ui/src/components/NodeDetails.js",
    "chars": 2201,
    "preview": "import React, {Component} from 'react';\nimport { withTranslation } from 'react-i18next';\nimport FormField from './FormFi"
  },
  {
    "path": "ui/src/components/NodeList.js",
    "chars": 1073,
    "preview": "import React, {Component} from 'react';\n\nclass NodeList extends Component {\n  constructor(props) {\n    super(props)\n    "
  },
  {
    "path": "ui/src/components/Panel.js",
    "chars": 298,
    "preview": "import React, {Component} from 'react';\n\nclass Panel extends Component {\n  render() {\n    return  <div className=\"panel\""
  },
  {
    "path": "ui/src/components/SideBar.js",
    "chars": 1251,
    "preview": "import React, {Component} from 'react';\nimport { withTranslation } from 'react-i18next';\n\nclass SideBar extends Componen"
  },
  {
    "path": "ui/src/containers/Discover.js",
    "chars": 1372,
    "preview": "import React, {Component} from 'react';\nimport { withTranslation } from 'react-i18next';\nimport Panel from '../component"
  },
  {
    "path": "ui/src/containers/NodeInfo.js",
    "chars": 1475,
    "preview": "import React, {Component} from 'react';\nimport { withTranslation } from 'react-i18next';\nimport Panel from '../component"
  },
  {
    "path": "ui/src/i18n.js",
    "chars": 451,
    "preview": "import i18n from \"i18next\";\nimport Backend from 'i18next-xhr-backend';\nimport LanguageDetector from 'i18next-browser-lan"
  },
  {
    "path": "ui/src/index.css",
    "chars": 63,
    "preview": "body {\n  margin: 0;\n  padding: 0;\n  font-family: sans-serif;\n}\n"
  },
  {
    "path": "ui/src/index.js",
    "chars": 253,
    "preview": "import React, { Suspense } from 'react';\nimport ReactDOM from 'react-dom';\nimport './i18n';\nimport './index.css';\nimport"
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/LICENSE",
    "chars": 1082,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 David Pallinder\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/README.md",
    "chars": 5484,
    "preview": "# go-randomdata\n\n[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat"
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/fullprofile.go",
    "chars": 3795,
    "preview": "package randomdata\n\nimport (\n\t\"crypto/md5\"\n\t\"crypto/sha1\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"m"
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/jsondata.go",
    "chars": 56038,
    "preview": "package randomdata\n\nvar data = []byte(`{\n    \"adjectives\": [\n        \"black\",\n        \"white\",\n        \"gray\",\n        \""
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/postalcodes.go",
    "chars": 5090,
    "preview": "package randomdata\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n\t\"strings\"\n)\n\n// Supported formats obtained from:\n// * http://w"
  },
  {
    "path": "vendor/github.com/Pallinder/go-randomdata/random_data.go",
    "chars": 9722,
    "preview": "// Package randomdata implements a bunch of simple ways to generate (pseudo) random data\npackage randomdata\n\nimport (\n\t\""
  },
  {
    "path": "vendor/github.com/elazarl/go-bindata-assetfs/LICENSE",
    "chars": 1299,
    "preview": "Copyright (c) 2014, Elazar Leibovich\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or wi"
  },
  {
    "path": "vendor/github.com/elazarl/go-bindata-assetfs/README.md",
    "chars": 1291,
    "preview": "# go-bindata-assetfs\n\nServe embedded files from [jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata) with `net/"
  },
  {
    "path": "vendor/github.com/elazarl/go-bindata-assetfs/assetfs.go",
    "chars": 3882,
    "preview": "package assetfs\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\""
  },
  {
    "path": "vendor/github.com/elazarl/go-bindata-assetfs/doc.go",
    "chars": 459,
    "preview": "// assetfs allows packages to serve static content embedded\n// with the go-bindata tool with the standard net/http packa"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/LICENSE",
    "chars": 1085,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Mitchell Hashimoto\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/README.md",
    "chars": 681,
    "preview": "# go-homedir\n\nThis is a Go library for detecting the user's home directory without\nthe use of cgo, so the library can be"
  },
  {
    "path": "vendor/github.com/mitchellh/go-homedir/homedir.go",
    "chars": 2931,
    "preview": "package homedir\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n"
  },
  {
    "path": "vendor/github.com/urfave/cli/CHANGELOG.md",
    "chars": 16210,
    "preview": "# Change Log\n\n**ATTN**: This project uses [semantic versioning](http://semver.org/).\n\n## [Unreleased]\n\n## 1.20.0 - 2017-"
  },
  {
    "path": "vendor/github.com/urfave/cli/LICENSE",
    "chars": 1084,
    "preview": "MIT License\n\nCopyright (c) 2016 Jeremy Saenz & Contributors\n\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "vendor/github.com/urfave/cli/README.md",
    "chars": 33830,
    "preview": "cli\n===\n\n[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli)\n[![Wind"
  },
  {
    "path": "vendor/github.com/urfave/cli/app.go",
    "chars": 12873,
    "preview": "package cli\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"time\"\n)\n\nvar (\n\tchangeLogURL           "
  },
  {
    "path": "vendor/github.com/urfave/cli/appveyor.yml",
    "chars": 460,
    "preview": "version: \"{build}\"\n\nos: Windows Server 2016\n\nimage: Visual Studio 2017\n\nclone_folder: c:\\gopath\\src\\github.com\\urfave\\cl"
  },
  {
    "path": "vendor/github.com/urfave/cli/category.go",
    "chars": 1107,
    "preview": "package cli\n\n// CommandCategories is a slice of *CommandCategory.\ntype CommandCategories []*CommandCategory\n\n// CommandC"
  },
  {
    "path": "vendor/github.com/urfave/cli/cli.go",
    "chars": 721,
    "preview": "// Package cli provides a minimal framework for creating and organizing command line\n// Go applications. cli is designed"
  },
  {
    "path": "vendor/github.com/urfave/cli/command.go",
    "chars": 8239,
    "preview": "package cli\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// Command is a subcommand for a cli.App.\ntype C"
  },
  {
    "path": "vendor/github.com/urfave/cli/context.go",
    "chars": 6743,
    "preview": "package cli\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"syscall\"\n)\n\n// Context is a type that is passed th"
  },
  {
    "path": "vendor/github.com/urfave/cli/errors.go",
    "chars": 2713,
    "preview": "package cli\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n)\n\n// OsExiter is the function used when the app exits. If not set d"
  },
  {
    "path": "vendor/github.com/urfave/cli/flag-types.json",
    "chars": 2188,
    "preview": "[\n  {\n    \"name\": \"Bool\",\n    \"type\": \"bool\",\n    \"value\": false,\n    \"context_default\": \"false\",\n    \"parser\": \"strconv"
  },
  {
    "path": "vendor/github.com/urfave/cli/flag.go",
    "chars": 19948,
    "preview": "package cli\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"reflect\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n)\n\ncons"
  },
  {
    "path": "vendor/github.com/urfave/cli/flag_generated.go",
    "chars": 14150,
    "preview": "package cli\n\nimport (\n\t\"flag\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// WARNING: This file is generated!\n\n// BoolFlag is a flag with type"
  },
  {
    "path": "vendor/github.com/urfave/cli/funcs.go",
    "chars": 1975,
    "preview": "package cli\n\n// BashCompleteFunc is an action to execute when the bash-completion flag is set\ntype BashCompleteFunc func"
  },
  {
    "path": "vendor/github.com/urfave/cli/generate-flag-types",
    "chars": 8211,
    "preview": "#!/usr/bin/env python\n\"\"\"\nThe flag types that ship with the cli library have many things in common, and\nso we can take a"
  },
  {
    "path": "vendor/github.com/urfave/cli/help.go",
    "chars": 8873,
    "preview": "package cli\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\t\"text/tabwriter\"\n\t\"text/template\"\n)\n\n// AppHelpTemplate is the text"
  },
  {
    "path": "vendor/github.com/urfave/cli/runtests",
    "chars": 2929,
    "preview": "#!/usr/bin/env python\nfrom __future__ import print_function\n\nimport argparse\nimport os\nimport sys\nimport tempfile\n\nfrom "
  },
  {
    "path": "vendor/github.com/urfave/cli/sort.go",
    "chars": 520,
    "preview": "package cli\n\nimport \"unicode\"\n\n// lexicographicLess compares strings alphabetically considering case.\nfunc lexicographic"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/LICENSE.libyaml",
    "chars": 1313,
    "preview": "The following files were ported to Go from C files of libyaml, and thus\nare still covered by their original copyright an"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/README.md",
    "chars": 2754,
    "preview": "# YAML support for the Go language\n\nIntroduction\n------------\n\nThe yaml package enables Go programs to comfortably encod"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/apic.go",
    "chars": 21246,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n\nfunc yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {\n\t//f"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/decode.go",
    "chars": 15658,
    "preview": "package yaml\n\nimport (\n\t\"encoding\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"time\"\n)\n\nconst (\n\tdocumentN"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/emitterc.go",
    "chars": 45287,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// Flush the buffer if needed.\nfunc flush(emitter *yaml_emitter_t) bool {\n\tif emitter"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/encode.go",
    "chars": 7458,
    "preview": "package yaml\n\nimport (\n\t\"encoding\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype encoder str"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/parserc.go",
    "chars": 34761,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// The parser implements the following grammar:\n//\n// stream               ::= STREAM"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/readerc.go",
    "chars": 11950,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// Set the reader error and return 0.\nfunc yaml_parser_set_reader_error(parser *yaml_par"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/resolve.go",
    "chars": 5240,
    "preview": "package yaml\n\nimport (\n\t\"encoding/base64\"\n\t\"math\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\ntype resolveMapItem"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/scannerc.go",
    "chars": 77227,
    "preview": "package yaml\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// Introduction\n// ************\n//\n// The following notes assume that you are "
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/sorter.go",
    "chars": 2476,
    "preview": "package yaml\n\nimport (\n\t\"reflect\"\n\t\"unicode\"\n)\n\ntype keyList []reflect.Value\n\nfunc (l keyList) Len() int      { return l"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/writerc.go",
    "chars": 2435,
    "preview": "package yaml\n\n// Set the writer error and return false.\nfunc yaml_emitter_set_writer_error(emitter *yaml_emitter_t, prob"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/yaml.go",
    "chars": 10260,
    "preview": "// Package yaml implements YAML support for the Go language.\n//\n// Source code and other details for the project are ava"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/yamlh.go",
    "chars": 25410,
    "preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// The version directive data.\ntype yaml_version_directive_t struct {\n\tmajor int8 // The"
  },
  {
    "path": "vendor/gopkg.in/yaml.v2/yamlprivateh.go",
    "chars": 4961,
    "preview": "package yaml\n\nconst (\n\t// The size of the input raw buffer.\n\tinput_raw_buffer_size = 512\n\n\t// The size of the input buff"
  },
  {
    "path": "vendor/vendor.json",
    "chars": 1119,
    "preview": "{\n\t\"comment\": \"\",\n\t\"ignore\": \"test\",\n\t\"package\": [\n\t\t{\n\t\t\t\"checksumSHA1\": \"cD+MATXYc1X6VHlQukvZ4VZlPYM=\",\n\t\t\t\"path\": \"gi"
  }
]

About this extraction

This page contains the full source code of the donkeysharp/gocho GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 87 files (547.4 KB), approximately 152.9k tokens, and a symbol index with 840 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!