diff --git a/.appveyor.yml b/.appveyor.yml index ac6de9b..0eebf56 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,11 +1,12 @@ version: '{build}' image: 'Visual Studio 2017' -platform: x64 +platform: 'x64' -clone_folder: 'c:\go\src\github.com\drone-plugins\drone-matrix' +clone_folder: 'c:\gopath\src\github.com\drone-plugins\drone-matrix' max_jobs: 1 environment: + GOPATH: c:\gopath DOCKER_USERNAME: secure: '4YzzahbEiMZQJpOCOd1LAw==' DOCKER_PASSWORD: @@ -15,14 +16,19 @@ install: - ps: | docker version go version + - ps: | + $env:Path = "c:\gopath\bin;$env:Path" build_script: - ps: | + go get -u github.com/golang/dep/cmd/dep + dep ensure + if ( $env:APPVEYOR_REPO_TAG -eq 'false' ) { - go build -ldflags "-X main.build=$env:APPVEYOR_BUILD_VERSION" -a -o drone-matrix.exe + go build -ldflags "-X main.build=$env:APPVEYOR_BUILD_VERSION" -a -o release/drone-matrix.exe } else { $version = $env:APPVEYOR_REPO_TAG_NAME.substring(1) - go build -ldflags "-X main.version=$version -X main.build=$env:APPVEYOR_BUILD_VERSION" -a -o drone-matrix.exe + go build -ldflags "-X main.version=$version -X main.build=$env:APPVEYOR_BUILD_VERSION" -a -o release/drone-matrix.exe } docker pull microsoft/nanoserver:10.0.14393.1593 diff --git a/.drone.yml b/.drone.yml index 8ea74cf..394f063 100644 --- a/.drone.yml +++ b/.drone.yml @@ -3,18 +3,22 @@ workspace: path: src/github.com/drone-plugins/drone-matrix pipeline: - test: - image: golang:1.9 + deps: + image: golang:1.10 pull: true commands: - - go vet - - | - for PKG in $(go list ./... | grep -v /vendor/); do - go test -cover -coverprofile $GOPATH/src/$PKG/coverage.out $PKG - done + - go get -u github.com/golang/dep/cmd/dep + - dep ensure + + test: + image: golang:1.10 + pull: true + commands: + - go vet ./... + - go test -cover ./... build_linux_amd64: - image: golang:1.9 + image: golang:1.10 pull: true group: build environment: @@ -30,7 +34,7 @@ pipeline: fi build_linux_i386: - image: golang:1.9 + image: golang:1.10 pull: true group: build environment: @@ -46,7 +50,7 @@ pipeline: fi build_linux_arm64: - image: golang:1.9 + image: golang:1.10 pull: true group: build environment: @@ -62,7 +66,7 @@ pipeline: fi build_linux_arm: - image: golang:1.9 + image: golang:1.10 pull: true group: build environment: @@ -79,7 +83,7 @@ pipeline: fi publish_linux_amd64: - image: plugins/docker:17.05 + image: plugins/docker:17.12 pull: true secrets: [ docker_username, docker_password ] group: docker @@ -91,7 +95,7 @@ pipeline: event: [ push, tag ] publish_linux_i386: - image: plugins/docker:17.05 + image: plugins/docker:17.12 pull: true secrets: [ docker_username, docker_password ] group: docker @@ -103,7 +107,7 @@ pipeline: event: [ push, tag ] publish_linux_arm64: - image: plugins/docker:17.05 + image: plugins/docker:17.12 pull: true secrets: [ docker_username, docker_password ] group: docker @@ -115,7 +119,7 @@ pipeline: event: [ push, tag ] publish_linux_arm: - image: plugins/docker:17.05 + image: plugins/docker:17.12 pull: true secrets: [ docker_username, docker_password ] group: docker diff --git a/.gitignore b/.gitignore index 57472fa..0779c6e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,5 +24,7 @@ _testmain.go *.prof release/ +vendor/ + coverage.out drone-matrix diff --git a/Dockerfile.windows b/Dockerfile.windows index 910e01d..77d199a 100644 --- a/Dockerfile.windows +++ b/Dockerfile.windows @@ -6,5 +6,7 @@ LABEL maintainer="Drone.IO Community " ` org.label-schema.vendor="Drone.IO Community" ` org.label-schema.schema-version="1.0" -ADD drone-matrix.exe c:\drone-matrix.exe +SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] + +ADD release\drone-matrix.exe c:\drone-matrix.exe ENTRYPOINT [ "c:\\drone-matrix.exe" ] diff --git a/Gopkg.toml b/Gopkg.toml index 3edad83..d3a5c73 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,26 +1,3 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - [[constraint]] name = "github.com/aymerick/raymond" version = "2.0.1" diff --git a/vendor/github.com/aymerick/raymond/.gitmodules b/vendor/github.com/aymerick/raymond/.gitmodules deleted file mode 100644 index a757998..0000000 --- a/vendor/github.com/aymerick/raymond/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "mustache"] - path = mustache - url = git://github.com/mustache/spec.git diff --git a/vendor/github.com/aymerick/raymond/.travis.yml b/vendor/github.com/aymerick/raymond/.travis.yml deleted file mode 100644 index 43aaf87..0000000 --- a/vendor/github.com/aymerick/raymond/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -language: go - -go: - - 1.3 - - tip diff --git a/vendor/github.com/aymerick/raymond/BENCHMARKS.md b/vendor/github.com/aymerick/raymond/BENCHMARKS.md deleted file mode 100644 index c3af56c..0000000 --- a/vendor/github.com/aymerick/raymond/BENCHMARKS.md +++ /dev/null @@ -1,46 +0,0 @@ -# Benchmarks - -Hardware: MacBookPro11,1 - Intel Core i5 - 2,6 GHz - 8 Go RAM - -With: - - - handlebars.js #8cba84df119c317fcebc49fb285518542ca9c2d0 - - raymond #7bbaaf50ed03c96b56687d7fa6c6e04e02375a98 - - -## handlebars.js (ops/ms) - - arguments 198 ±4 (5) - array-each 568 ±23 (5) - array-mustache 522 ±18 (4) - complex 71 ±7 (3) - data 67 ±2 (3) - depth-1 47 ±2 (3) - depth-2 14 ±1 (2) - object-mustache 1099 ±47 (5) - object 907 ±58 (4) - partial-recursion 46 ±3 (4) - partial 68 ±3 (3) - paths 1650 ±50 (3) - string 2552 ±157 (3) - subexpression 141 ±2 (4) - variables 2671 ±83 (4) - - -## raymond - - BenchmarkArguments 200000 6642 ns/op 151 ops/ms - BenchmarkArrayEach 100000 19584 ns/op 51 ops/ms - BenchmarkArrayMustache 100000 17305 ns/op 58 ops/ms - BenchmarkComplex 30000 50270 ns/op 20 ops/ms - BenchmarkData 50000 25551 ns/op 39 ops/ms - BenchmarkDepth1 100000 20162 ns/op 50 ops/ms - BenchmarkDepth2 30000 47782 ns/op 21 ops/ms - BenchmarkObjectMustache 200000 7668 ns/op 130 ops/ms - BenchmarkObject 200000 8843 ns/op 113 ops/ms - BenchmarkPartialRecursion 50000 23139 ns/op 43 ops/ms - BenchmarkPartial 50000 31015 ns/op 32 ops/ms - BenchmarkPath 200000 8997 ns/op 111 ops/ms - BenchmarkString 1000000 1879 ns/op 532 ops/ms - BenchmarkSubExpression 300000 4935 ns/op 203 ops/ms - BenchmarkVariables 200000 6478 ns/op 154 ops/ms diff --git a/vendor/github.com/aymerick/raymond/CHANGELOG.md b/vendor/github.com/aymerick/raymond/CHANGELOG.md deleted file mode 100644 index c438a5c..0000000 --- a/vendor/github.com/aymerick/raymond/CHANGELOG.md +++ /dev/null @@ -1,33 +0,0 @@ -# Raymond Changelog - -### Raymond 2.0.1 _(June 01, 2016)_ - -- [BUGFIX] Removes data races [#3](https://github.com/aymerick/raymond/issues/3) - Thanks [@markbates](https://github.com/markbates) - -### Raymond 2.0.0 _(May 01, 2016)_ - -- [BUGFIX] Fixes passing of context in helper options [#2](https://github.com/aymerick/raymond/issues/2) - Thanks [@GhostRussia](https://github.com/GhostRussia) -- [BREAKING] Renames and unexports constants: - - - `handlebars.DUMP_TPL` - - `lexer.ESCAPED_ESCAPED_OPEN_MUSTACHE` - - `lexer.ESCAPED_OPEN_MUSTACHE` - - `lexer.OPEN_MUSTACHE` - - `lexer.CLOSE_MUSTACHE` - - `lexer.CLOSE_STRIP_MUSTACHE` - - `lexer.CLOSE_UNESCAPED_STRIP_MUSTACHE` - - `lexer.DUMP_TOKEN_POS` - - `lexer.DUMP_ALL_TOKENS_VAL` - - -### Raymond 1.1.0 _(June 15, 2015)_ - -- Permits templates references with lowercase versions of struct fields. -- Adds `ParseFile()` function. -- Adds `RegisterPartialFile()`, `RegisterPartialFiles()` and `Clone()` methods on `Template`. -- Helpers can now be struct methods. -- Ensures safe concurrent access to helpers and partials. - -### Raymond 1.0.0 _(June 09, 2015)_ - -- This is the first release. Raymond supports almost all handlebars features. See https://github.com/aymerick/raymond#limitations for a list of differences with the javascript implementation. diff --git a/vendor/github.com/aymerick/raymond/LICENSE b/vendor/github.com/aymerick/raymond/LICENSE deleted file mode 100644 index 6ce87cd..0000000 --- a/vendor/github.com/aymerick/raymond/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Aymerick JEHANNE - -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. - diff --git a/vendor/github.com/aymerick/raymond/README.md b/vendor/github.com/aymerick/raymond/README.md deleted file mode 100644 index 0721bcc..0000000 --- a/vendor/github.com/aymerick/raymond/README.md +++ /dev/null @@ -1,1382 +0,0 @@ -# raymond [![Build Status](https://secure.travis-ci.org/aymerick/raymond.svg?branch=master)](http://travis-ci.org/aymerick/raymond) [![GoDoc](https://godoc.org/github.com/aymerick/raymond?status.svg)](http://godoc.org/github.com/aymerick/raymond) - -Handlebars for [golang](https://golang.org) with the same features as [handlebars.js](http://handlebarsjs.com) `3.0`. - -The full API documentation is available here: . - -![Raymond Logo](https://github.com/aymerick/raymond/blob/master/raymond.png?raw=true "Raymond") - - -# Table of Contents - -- [Quick Start](#quick-start) -- [Correct Usage](#correct-usage) -- [Context](#context) -- [HTML Escaping](#html-escaping) -- [Helpers](#helpers) - - [Template Helpers](#template-helpers) - - [Built-In Helpers](#built-in-helpers) - - [The `if` block helper](#the-if-block-helper) - - [The `unless` block helper](#the-unless-block-helper) - - [The `each` block helper](#the-each-block-helper) - - [The `with` block helper](#the-with-block-helper) - - [The `lookup` helper](#the-lookup-helper) - - [The `log` helper](#the-log-helper) - - [Block Helpers](#block-helpers) - - [Block Evaluation](#block-evaluation) - - [Conditional](#conditional) - - [Else Block Evaluation](#else-block-evaluation) - - [Block Parameters](#block-parameters) - - [Helper Parameters](#helper-parameters) - - [Automatic conversion](#automatic-conversion) - - [Options Argument](#options-argument) - - [Context Values](#context-values) - - [Helper Hash Arguments](#helper-hash-arguments) - - [Private Data](#private-data) - - [Utilites](#utilites) - - [`Str()`](#str) - - [`IsTrue()`](#istrue) -- [Context Functions](#context-functions) -- [Partials](#partials) - - [Template Partials](#template-partials) - - [Global Partials](#global-partials) - - [Dynamic Partials](#dynamic-partials) - - [Partial Contexts](#partial-contexts) - - [Partial Parameters](#partial-parameters) -- [Utility Functions](#utility-functions) -- [Mustache](#mustache) -- [Limitations](#limitations) -- [Handlebars Lexer](#handlebars-lexer) -- [Handlebars Parser](#handlebars-parser) -- [Test](#test) -- [References](#references) -- [Others Implementations](#others-implementations) - - -## Quick Start - - $ go get github.com/aymerick/raymond - -The quick and dirty way of rendering a handlebars template: - -```go -package main - -import ( - "fmt" - - "github.com/aymerick/raymond" -) - -func main() { - tpl := `
-

{{title}}

-
- {{body}} -
-
-` - - ctx := map[string]string{ - "title": "My New Post", - "body": "This is my first post!", - } - - result, err := raymond.Render(tpl, ctx) - if err != nil { - panic("Please fill a bug :)") - } - - fmt.Print(result) -} -``` - -Displays: - -```html -
-

My New Post

-
- This is my first post! -
-
-``` - -Please note that the template will be parsed everytime you call `Render()` function. So you probably want to read the next section. - - -## Correct Usage - -To avoid parsing a template several times, use the `Parse()` and `Exec()` functions: - -```go -package main - -import ( - "fmt" - - "github.com/aymerick/raymond" -) - -func main() { - source := `
-

{{title}}

-
- {{body}} -
-
-` - - ctxList := []map[string]string{ - { - "title": "My New Post", - "body": "This is my first post!", - }, - { - "title": "Here is another post", - "body": "This is my second post!", - }, - } - - // parse template - tpl, err := raymond.Parse(source) - if err != nil { - panic(err) - } - - for _, ctx := range ctxList { - // render template - result, err := tpl.Exec(ctx) - if err != nil { - panic(err) - } - - fmt.Print(result) - } -} - -``` - -Displays: - -```html -
-

My New Post

-
- This is my first post! -
-
-
-

Here is another post

-
- This is my second post! -
-
-``` - -You can use `MustParse()` and `MustExec()` functions if you don't want to deal with errors: - -```go -// parse template -tpl := raymond.MustParse(source) - -// render template -result := tpl.MustExec(ctx) -``` - - -## Context - -The rendering context can contain any type of values, including `array`, `slice`, `map`, `struct` and `func`. - -When using structs, be warned that only exported fields are accessible. However you can access exported fields in template with their lowercase names. - -For example, both `{{author.firstName}}` and `{{Author.FirstName}}` references give the same result, as long as `Author` and `FirstName` are exported struct fields. - -```go -package main - -import ( - "fmt" - - "github.com/aymerick/raymond" -) - -func main() { - source := `
-

By {{author.firstName}} {{author.lastName}}

-
{{body}}
- -

Comments

- - {{#each comments}} -

By {{author.firstName}} {{author.lastName}}

-
{{body}}
- {{/each}} -
` - - type Post struct { - Author Person - Body string - Comments []Comment - } - - type Person struct { - FirstName string - LastName string - } - - type Comment struct { - Author Person - Body string - } - - ctx := Post{ - Person{"Jean", "Valjean"}, - "Life is difficult", - []Comment{ - Comment{ - Person{"Marcel", "Beliveau"}, - "LOL!", - }, - }, - } - - output := raymond.MustRender(source, ctx) - - fmt.Print(output) -} -``` - -Output: - -```html -
-

By Jean Valjean

-
Life is difficult
- -

Comments

- -

By Marcel Beliveau

-
LOL!
-
-``` - - -## HTML Escaping - -By default, the result of a mustache expression is HTML escaped. Use the triple mustache `{{{` to output unescaped values. - -```go -source := `
-

{{title}}

-
- {{{body}}} -
-
-` - -ctx := map[string]string{ - "title": "All about

Tags", - "body": "

This is a post about <p> tags

", -} - -tpl := raymond.MustParse(source) -result := tpl.MustExec(ctx) - -fmt.Print(result) -``` - -Output: - -```html -
-

All about <p> Tags

-
-

This is a post about <p> tags

-
-
-``` - -When returning HTML from a helper, you should return a `SafeString` if you don't want it to be escaped by default. When using `SafeString` all unknown or unsafe data should be manually escaped with the `Escape` method. - -```go -raymond.RegisterHelper("link", func(url, text string) raymond.SafeString { - return raymond.SafeString("" + raymond.Escape(text) + "") -}) - -tpl := raymond.MustParse("{{link url text}}") - -ctx := map[string]string{ - "url": "http://www.aymerick.com/", - "text": "This is a cool website", -} - -result := tpl.MustExec(ctx) -fmt.Print(result) -``` - -Output: - -```html -This is a <em>cool</em> website -``` - - -## Helpers - -Helpers can be accessed from any context in a template. You can register a helper with the `RegisterHelper` function. - -For example: - -```html -
-

By {{fullName author}}

-
{{body}}
- -

Comments

- - {{#each comments}} -

By {{fullName author}}

-
{{body}}
- {{/each}} -
-``` - -With this context and helper: - -```go -ctx := map[string]interface{}{ - "author": map[string]string{"firstName": "Jean", "lastName": "Valjean"}, - "body": "Life is difficult", - "comments": []map[string]interface{}{{ - "author": map[string]string{"firstName": "Marcel", "lastName": "Beliveau"}, - "body": "LOL!", - }}, -} - -raymond.RegisterHelper("fullName", func(person map[string]string) string { - return person["firstName"] + " " + person["lastName"] -}) -``` - -Outputs: - -```html -
-

By Jean Valjean

-
Life is difficult
- -

Comments

- -

By Marcel Beliveau

-
LOL!
-
-``` - -Helper arguments can be any type. - -The following example uses structs instead of maps and produces the same output as the previous one: - -```html -
-

By {{fullName author}}

-
{{body}}
- -

Comments

- - {{#each comments}} -

By {{fullName author}}

-
{{body}}
- {{/each}} -
-``` - -With this context and helper: - -```go -type Post struct { - Author Person - Body string - Comments []Comment -} - -type Person struct { - FirstName string - LastName string -} - -type Comment struct { - Author Person - Body string -} - -ctx := Post{ - Person{"Jean", "Valjean"}, - "Life is difficult", - []Comment{ - Comment{ - Person{"Marcel", "Beliveau"}, - "LOL!", - }, - }, -} - -RegisterHelper("fullName", func(person Person) string { - return person.FirstName + " " + person.LastName -}) -``` - - -### Template Helpers - -You can register a helper on a specific template, and in that case that helper will be available to that template only: - -```go -tpl := raymond.MustParse("User: {{fullName user.firstName user.lastName}}") - -tpl.RegisterHelper("fullName", func(firstName, lastName string) string { - return firstName + " " + lastName -}) -``` - - -### Built-In Helpers - -Those built-in helpers are available to all templates. - - -#### The `if` block helper - -You can use the `if` helper to conditionally render a block. If its argument returns `false`, `nil`, `0`, `""`, an empty array, an empty slice or an empty map, then raymond will not render the block. - -```html -
- {{#if author}} -

{{firstName}} {{lastName}}

- {{/if}} -
-``` - -When using a block expression, you can specify a template section to run if the expression returns a falsy value. That section, marked by `{{else}}` is called an "else section". - -```html -
- {{#if author}} -

{{firstName}} {{lastName}}

- {{else}} -

Unknown Author

- {{/if}} -
-``` - -You can chain several blocks. For example that template: - -```html -{{#if isActive}} - Active -{{else if isInactive}} - Inactive -{{else}} - Unknown -{{/if}} -``` - -With that context: - -```go -ctx := map[string]interface{}{ - "isActive": false, - "isInactive": false, -} -``` - -Outputs: - -```html - Unknown -``` - - -#### The `unless` block helper - -You can use the `unless` helper as the inverse of the `if` helper. Its block will be rendered if the expression returns a falsy value. - -```html -
- {{#unless license}} -

WARNING: This entry does not have a license!

- {{/unless}} -
-``` - - -#### The `each` block helper - -You can iterate over an array, a slice, a map or a struct instance using this built-in `each` helper. Inside the block, you can use `this` to reference the element being iterated over. - -For example: - -```html - -``` - -With this context: - -```go -map[string]interface{}{ - "people": []string{ - "Marcel", "Jean-Claude", "Yvette", - }, -} -``` - -Outputs: - -```html - -``` - -You can optionally provide an `{{else}}` section which will display only when the passed argument is an empty array, an empty slice or an empty map (a `struct` instance is never considered empty). - -```html -{{#each paragraphs}} -

{{this}}

-{{else}} -

No content

-{{/each}} -``` - -When looping through items in `each`, you can optionally reference the current loop index via `{{@index}}`. - -```html -{{#each array}} - {{@index}}: {{this}} -{{/each}} -``` - -Additionally for map and struct instance iteration, `{{@key}}` references the current map key or struct field name: - -```html -{{#each map}} - {{@key}}: {{this}} -{{/each}} -``` - -The first and last steps of iteration are noted via the `@first` and `@last` variables. - - -#### The `with` block helper - -You can shift the context for a section of a template by using the built-in `with` block helper. - -```html -
-

{{title}}

- - {{#with author}} -

By {{firstName}} {{lastName}}

- {{/with}} -
-``` - -With this context: - -```go -map[string]interface{}{ - "title": "My first post!", - "author": map[string]string{ - "firstName": "Jean", - "lastName": "Valjean", - }, -} -``` - -Outputs: - -```html -
-

My first post!

- -

By Jean Valjean

-
-``` - -You can optionally provide an `{{else}}` section which will display only when the passed argument is falsy. - -```html -{{#with author}} -

{{name}}

-{{else}} -

No content

-{{/with}} -``` - - -#### The `lookup` helper - -The `lookup` helper allows for dynamic parameter resolution using handlebars variables. - -```html -{{#each bar}} - {{lookup ../foo @index}} -{{/each}} -``` - - -#### The `log` helper - -The `log` helper allows for logging while rendering a template. - -```html -{{log "Look at me!"}} -``` - -Note that the handlebars.js `@level` variable is not supported. - - -### Block Helpers - -Block helpers make it possible to define custom iterators and other functionality that can invoke the passed block with a new context. - - -#### Block Evaluation - -As an example, let's define a block helper that adds some markup to the wrapped text. - -```html -
-

{{title}}

-
- {{#bold}}{{body}}{{/bold}} -
-
-``` - -The `bold` helper will add markup to make its text bold. - -```go -raymond.RegisterHelper("bold", func(options *raymond.Options) raymond.SafeString { - return raymond.SafeString(`
` + options.Fn() + "
") -}) -``` - -A helper evaluates the block content with current context by calling `options.Fn()`. - -If you want to evaluate the block with another context, then use `options.FnWith(ctx)`, like this french version of built-in `with` block helper: - -```go -raymond.RegisterHelper("avec", func(context interface{}, options *raymond.Options) string { - return options.FnWith(context) -}) -``` - -With that template: - -```html -{{#avec obj.text}}{{this}}{{/avec}} -``` - - -#### Conditional - -Let's write a french version of `if` block helper: - -```go -source := `{{#si yep}}YEP !{{/si}}` - -ctx := map[string]interface{}{"yep": true} - -raymond.RegisterHelper("si", func(conditional bool, options *raymond.Options) string { - if conditional { - return options.Fn() - } - return "" -}) -``` - -Note that as the first parameter of the helper is typed as `bool` an automatic conversion is made if corresponding context value is not a boolean. So this helper works with that context too: - -```go -ctx := map[string]interface{}{"yep": "message"} -``` - -Here, `"message"` is converted to `true` because it is an non-empty string. See `IsTrue()` function for more informations on boolean conversion. - - -#### Else Block Evaluation - -We can enhance the `si` block helper to evaluate the `else block` by calling `options.Inverse()` if conditional is false: - -```go -source := `{{#si yep}}YEP !{{else}}NOP !{{/si}}` - -ctx := map[string]interface{}{"yep": false} - -raymond.RegisterHelper("si", func(conditional bool, options *raymond.Options) string { - if conditional { - return options.Fn() - } - return options.Inverse() -}) -``` - -Outputs: -``` -NOP ! -``` - - -#### Block Parameters - -It's possible to receive named parameters from supporting helpers. - -```html -{{#each users as |user userId|}} - Id: {{userId}} Name: {{user.name}} -{{/each}} -``` - -In this particular example, `user` will have the same value as the current context and `userId` will have the index/key value for the iteration. - -This allows for nested helpers to avoid name conflicts. - -For example: - -```html -{{#each users as |user userId|}} - {{#each user.books as |book bookId|}} - User: {{userId}} Book: {{bookId}} - {{/each}} -{{/each}} -``` - -With this context: - -```go -ctx := map[string]interface{}{ - "users": map[string]interface{}{ - "marcel": map[string]interface{}{ - "books": map[string]interface{}{ - "book1": "My first book", - "book2": "My second book", - }, - }, - "didier": map[string]interface{}{ - "books": map[string]interface{}{ - "bookA": "Good book", - "bookB": "Bad book", - }, - }, - }, -} -``` - -Outputs: - -```html - User: marcel Book: book1 - User: marcel Book: book2 - User: didier Book: bookA - User: didier Book: bookB -``` - -As you can see, the second block parameter is the map key. When using structs, it is the struct field name. - -When using arrays and slices, the second parameter is element index: - -```go -ctx := map[string]interface{}{ - "users": []map[string]interface{}{ - { - "id": "marcel", - "books": []map[string]interface{}{ - {"id": "book1", "title": "My first book"}, - {"id": "book2", "title": "My second book"}, - }, - }, - { - "id": "didier", - "books": []map[string]interface{}{ - {"id": "bookA", "title": "Good book"}, - {"id": "bookB", "title": "Bad book"}, - }, - }, - }, -} -``` - -Outputs: - -```html - User: 0 Book: 0 - User: 0 Book: 1 - User: 1 Book: 0 - User: 1 Book: 1 -``` - - -### Helper Parameters - -When calling a helper in a template, raymond expects the same number of arguments as the number of helper function parameters. - -So this template: - -```html -{{add a}} -``` - -With this helper: - -```go -raymond.RegisterHelper("add", func(val1, val2 int) string { - return strconv.Itoa(val1 + val2) -}) -``` - -Will simply panics, because we call the helper with one argument whereas it expects two. - - -#### Automatic conversion - -Let's create a `concat` helper that expects two strings and concat them: - -```go -source := `{{concat a b}}` - -ctx := map[string]interface{}{ - "a": "Jean", - "b": "Valjean", -} - -raymond.RegisterHelper("concat", func(val1, val2 string) string { - return val1 + " " + val2 -}) -``` - -Everything goes well, two strings are passed as arguments to the helper that outputs: - -```html -Jean VALJEAN -``` - -But what happens if there is another type than `string` in the context ? For example: - -```go -ctx := map[string]interface{}{ - "a": 10, - "b": "Valjean", -} -``` - -Actually, raymond perfoms automatic string conversion. So because the first parameter of the helper is typed as `string`, the first argument will be converted from the `10` integer to `"10"`, and the helper outputs: - -```html -10 VALJEAN -``` - -Note that this kind of automatic conversion is done with `bool` type too, thanks to the `IsTrue()` function. - - -### Options Argument - -If a helper needs the `Options` argument, just add it at the end of helper parameters: - -```go -raymond.RegisterHelper("add", func(val1, val2 int, options *raymond.Options) string { - return strconv.Itoa(val1 + val2) + " " + options.ValueStr("bananas") -}) -``` - -Thanks to the `options` argument, helpers have access to the current evaluation context, to the `Hash` arguments, and they can manipulate the private data variables. - -The `Options` argument is even necessary for Block Helpers to evaluate block and "else block". - - -#### Context Values - -Helpers fetch current context values with `options.Value()` and `options.ValuesStr()`. - -`Value()` returns an `interface{}` and lets the helper do the type assertions whereas `ValueStr()` automatically converts the value to a `string`. - -For example: - -```go -source := `{{concat a b}}` - -ctx := map[string]interface{}{ - "a": "Marcel", - "b": "Beliveau", - "suffix": "FOREVER !", -} - -raymond.RegisterHelper("concat", func(val1, val2 string, options *raymond.Options) string { - return val1 + " " + val2 + " " + options.ValueStr("suffix") -}) -``` - -Outputs: - -```html -Marcel Beliveau FOREVER ! -``` - -Helpers can get the entire current context with `options.Ctx()` that returns an `interface{}`. - - -#### Helper Hash Arguments - -Helpers access hash arguments with `options.HashProp()` and `options.HashStr()`. - -`HashProp()` returns an `interface{}` and lets the helper do the type assertions whereas `HashStr()` automatically converts the value to a `string`. - -For example: - -```go -source := `{{concat suffix first=a second=b}}` - -ctx := map[string]interface{}{ - "a": "Marcel", - "b": "Beliveau", - "suffix": "FOREVER !", -} - -raymond.RegisterHelper("concat", func(suffix string, options *raymond.Options) string { - return options.HashStr("first") + " " + options.HashStr("second") + " " + suffix -}) -``` - -Outputs: - -```html -Marcel Beliveau FOREVER ! -``` - -Helpers can get the full hash with `options.Hash()` that returns a `map[string]interface{}`. - - -#### Private Data - -Helpers access private data variables with `options.Data()` and `options.DataStr()`. - -`Data()` returns an `interface{}` and lets the helper do the type assertions whereas `DataStr()` automatically converts the value to a `string`. - -Helpers can get the entire current data frame with `options.DataFrame()` that returns a `*DataFrame`. - -For helpers that need to inject their own private data frame, use `options.NewDataFrame()` to create the frame and `options.FnData()` to evaluate the block with that frame. - -For example: - -```go -source := `{{#voodoo kind=a}}Voodoo is {{@magix}}{{/voodoo}}` - -ctx := map[string]interface{}{ - "a": "awesome", -} - -raymond.RegisterHelper("voodoo", func(options *raymond.Options) string { - // create data frame with @magix data - frame := options.NewDataFrame() - frame.Set("magix", options.HashProp("kind")) - - // evaluates block with new data frame - return options.FnData(frame) -}) -``` - -Helpers that need to evaluate the block with a private data frame and a new context can call `options.FnCtxData()`. - - -### Utilites - -In addition to `Escape()`, raymond provides utility functions that can be usefull for helpers. - - -#### `Str()` - -`Str()` converts its parameter to a `string`. - -Booleans: - -```go -raymond.Str(3) + " foos and " + raymond.Str(-1.25) + " bars" -// Outputs: "3 foos and -1.25 bars" -``` - -Numbers: - -``` go -"everything is " + raymond.Str(true) + " and nothing is " + raymond.Str(false) -// Outputs: "everything is true and nothing is false" -``` - -Maps: - -```go -raymond.Str(map[string]string{"foo": "bar"}) -// Outputs: "map[foo:bar]" -``` - -Arrays and Slices: - -```go -raymond.Str([]interface{}{true, 10, "foo", 5, "bar"}) -// Outputs: "true10foo5bar" -``` - - -#### `IsTrue()` - -`IsTrue()` returns the truthy version of its parameter. - -It returns `false` when parameter is either: - - - an empty array - - an empty slice - - an empty map - - `""` - - `nil` - - `0` - - `false` - -For all others values, `IsTrue()` returns `true`. - - -## Context Functions - -In addition to helpers, lambdas found in context are evaluated. - -For example, that template and context: - -```go -source := "I {{feeling}} you" - -ctx := map[string]interface{}{ - "feeling": func() string { - rand.Seed(time.Now().UTC().UnixNano()) - - feelings := []string{"hate", "love"} - return feelings[rand.Intn(len(feelings))] - }, -} -``` - -Randomly renders `I hate you` or `I love you`. - -Those context functions behave like helper functions: they can be called with parameters and they can have an `Options` argument. - - -## Partials - -### Template Partials - -You can register template partials before execution: - -```go -tpl := raymond.MustParse("{{> foo}} baz") -tpl.RegisterPartial("foo", "bar") - -result := tpl.MustExec(nil) -fmt.Print(result) -``` - -Output: - -```html -bar baz -``` - -You can register several partials at once: - -```go -tpl := raymond.MustParse("{{> foo}} and {{> baz}}") -tpl.RegisterPartials(map[string]string{ - "foo": "bar", - "baz": "bat", -}) - -result := tpl.MustExec(nil) -fmt.Print(result) -``` - -Output: - -```html -bar and bat -``` - - -### Global Partials - -You can registers global partials that will be accessible by all templates: - -```go -raymond.RegisterPartial("foo", "bar") - -tpl := raymond.MustParse("{{> foo}} baz") -result := tpl.MustExec(nil) -fmt.Print(result) -``` - -Or: - -```go -raymond.RegisterPartials(map[string]string{ - "foo": "bar", - "baz": "bat", -}) - -tpl := raymond.MustParse("{{> foo}} and {{> baz}}") -result := tpl.MustExec(nil) -fmt.Print(result) -``` - - -### Dynamic Partials - -It's possible to dynamically select the partial to be executed by using sub expression syntax. - -For example, that template randomly evaluates the `foo` or `baz` partial: - -```go -tpl := raymond.MustParse("{{> (whichPartial) }}") -tpl.RegisterPartials(map[string]string{ - "foo": "bar", - "baz": "bat", -}) - -ctx := map[string]interface{}{ - "whichPartial": func() string { - rand.Seed(time.Now().UTC().UnixNano()) - - names := []string{"foo", "baz"} - return names[rand.Intn(len(names))] - }, -} - -result := tpl.MustExec(ctx) -fmt.Print(result) -``` - - -### Partial Contexts - -It's possible to execute partials on a custom context by passing in the context to the partial call. - -For example: - -```go -tpl := raymond.MustParse("User: {{> userDetails user }}") -tpl.RegisterPartial("userDetails", "{{firstname}} {{lastname}}") - -ctx := map[string]interface{}{ - "user": map[string]string{ - "firstname": "Jean", - "lastname": "Valjean", - }, -} - -result := tpl.MustExec(ctx) -fmt.Print(result) -``` - -Displays: - -```html -User: Jean Valjean -``` - - -### Partial Parameters - -Custom data can be passed to partials through hash parameters. - -For example: - -```go -tpl := raymond.MustParse("{{> myPartial name=hero }}") -tpl.RegisterPartial("myPartial", "My hero is {{name}}") - -ctx := map[string]interface{}{ - "hero": "Goldorak", -} - -result := tpl.MustExec(ctx) -fmt.Print(result) -``` - -Displays: - -```html -My hero is Goldorak -``` - - -## Utility Functions - -You can use following utility fuctions to parse and register partials from files: - -- `ParseFile()` - reads a file and return parsed template -- `Template.RegisterPartialFile()` - reads a file and registers its content as a partial with given name -- `Template.RegisterPartialFiles()` - reads several files and registers them as partials, the filename base is used as the partial name - - -## Mustache - -Handlebars is a superset of [mustache](https://mustache.github.io) but it differs on those points: - -- Alternative delimiters are not supported -- There is no recursive lookup - - -## Limitations - -These handlebars options are currently NOT implemented: - -- `compat` - enables recursive field lookup -- `knownHelpers` - list of helpers that are known to exist (truthy) at template execution time -- `knownHelpersOnly` - allows further optimizations based on the known helpers list -- `trackIds` - include the id names used to resolve parameters for helpers -- `noEscape` - disables HTML escaping globally -- `strict` - templates will throw rather than silently ignore missing fields -- `assumeObjects` - removes object existence checks when traversing paths -- `preventIndent` - disables the auto-indententation of nested partials -- `stringParams` - resolves a parameter to it's name if the value isn't present in the context stack - -These handlebars features are currently NOT implemented: - -- raw block content is not passed as a parameter to helper -- `blockHelperMissing` - helper called when a helper can not be directly resolved -- `helperMissing` - helper called when a potential helper expression was not found -- `@contextPath` - value set in `trackIds` mode that records the lookup path for the current context -- `@level` - log level - - -## Handlebars Lexer - -You should not use the lexer directly, but for your information here is an example: - -```go -package main - -import ( - "fmt" - - "github.com/aymerick/raymond/lexer" -) - -func main() { - source := "You know {{nothing}} John Snow" - - output := "" - - lex := lexer.Scan(source) - for { - // consume next token - token := lex.NextToken() - - output += fmt.Sprintf(" %s", token) - - // stops when all tokens have been consumed, or on error - if token.Kind == lexer.TokenEOF || token.Kind == lexer.TokenError { - break - } - } - - fmt.Print(output) -} -``` - -Outputs: - -``` -Content{"You know "} Open{"{{"} ID{"nothing"} Close{"}}"} Content{" John Snow"} EOF -``` - - -## Handlebars Parser - -You should not use the parser directly, but for your information here is an example: - -```go -package main - -import ( - "fmt" - - "github.com/aymerick/raymond/ast" - "github.com/aymerick/raymond/parser" -) - -fu nc main() { - source := "You know {{nothing}} John Snow" - - // parse template - program, err := parser.Parse(source) - if err != nil { - panic(err) - } - - // print AST - output := ast.Print(program) - - fmt.Print(output) -} -``` - -Outputs: - -``` -CONTENT[ 'You know ' ] -{{ PATH:nothing [] }} -CONTENT[ ' John Snow' ] -``` - - -## Test - -First, fetch mustache tests: - - $ git submodule update --init - -To run all tests: - - $ go test ./... - -To filter tests: - - $ go test -run="Partials" - -To run all test and all benchmarks: - - $ go test -bench . ./... - -To test with race detection: - - $ go test -race ./... - - -## References - - - - - - - - - - - -## Others Implementations - -- [handlebars.js](http://handlebarsjs.com) - javascript -- [handlebars.java](https://github.com/jknack/handlebars.java) - java -- [handlebars.rb](https://github.com/cowboyd/handlebars.rb) - ruby -- [handlebars.php](https://github.com/XaminProject/handlebars.php) - php -- [handlebars-objc](https://github.com/Bertrand/handlebars-objc) - Objective C -- [rumblebars](https://github.com/nicolas-cherel/rumblebars) - rust diff --git a/vendor/github.com/aymerick/raymond/VERSION b/vendor/github.com/aymerick/raymond/VERSION deleted file mode 100644 index 38f77a6..0000000 --- a/vendor/github.com/aymerick/raymond/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.0.1 diff --git a/vendor/github.com/aymerick/raymond/ast/node.go b/vendor/github.com/aymerick/raymond/ast/node.go deleted file mode 100644 index aaef066..0000000 --- a/vendor/github.com/aymerick/raymond/ast/node.go +++ /dev/null @@ -1,785 +0,0 @@ -// Package ast provides structures to represent a handlebars Abstract Syntax Tree, and a Visitor interface to visit that tree. -package ast - -import ( - "fmt" - "strconv" -) - -// References: -// - https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler/ast.js -// - https://github.com/wycats/handlebars.js/blob/master/docs/compiler-api.md -// - https://github.com/golang/go/blob/master/src/text/template/parse/node.go - -// Node is an element in the AST. -type Node interface { - // node type - Type() NodeType - - // location of node in original input string - Location() Loc - - // string representation, used for debugging - String() string - - // accepts visitor - Accept(Visitor) interface{} -} - -// Visitor is the interface to visit an AST. -type Visitor interface { - VisitProgram(*Program) interface{} - - // statements - VisitMustache(*MustacheStatement) interface{} - VisitBlock(*BlockStatement) interface{} - VisitPartial(*PartialStatement) interface{} - VisitContent(*ContentStatement) interface{} - VisitComment(*CommentStatement) interface{} - - // expressions - VisitExpression(*Expression) interface{} - VisitSubExpression(*SubExpression) interface{} - VisitPath(*PathExpression) interface{} - - // literals - VisitString(*StringLiteral) interface{} - VisitBoolean(*BooleanLiteral) interface{} - VisitNumber(*NumberLiteral) interface{} - - // miscellaneous - VisitHash(*Hash) interface{} - VisitHashPair(*HashPair) interface{} -} - -// NodeType represents an AST Node type. -type NodeType int - -// Type returns itself, and permits struct includers to satisfy that part of Node interface. -func (t NodeType) Type() NodeType { - return t -} - -const ( - // NodeProgram is the program node - NodeProgram NodeType = iota - - // NodeMustache is the mustache statement node - NodeMustache - - // NodeBlock is the block statement node - NodeBlock - - // NodePartial is the partial statement node - NodePartial - - // NodeContent is the content statement node - NodeContent - - // NodeComment is the comment statement node - NodeComment - - // NodeExpression is the expression node - NodeExpression - - // NodeSubExpression is the subexpression node - NodeSubExpression - - // NodePath is the expression path node - NodePath - - // NodeBoolean is the literal boolean node - NodeBoolean - - // NodeNumber is the literal number node - NodeNumber - - // NodeString is the literal string node - NodeString - - // NodeHash is the hash node - NodeHash - - // NodeHashPair is the hash pair node - NodeHashPair -) - -// Loc represents the position of a parsed node in source file. -type Loc struct { - Pos int // Byte position - Line int // Line number -} - -// Location returns itself, and permits struct includers to satisfy that part of Node interface. -func (l Loc) Location() Loc { - return l -} - -// Strip describes node whitespace management. -type Strip struct { - Open bool - Close bool - - OpenStandalone bool - CloseStandalone bool - InlineStandalone bool -} - -// NewStrip instanciates a Strip for given open and close mustaches. -func NewStrip(openStr, closeStr string) *Strip { - return &Strip{ - Open: (len(openStr) > 2) && openStr[2] == '~', - Close: (len(closeStr) > 2) && closeStr[len(closeStr)-3] == '~', - } -} - -// NewStripForStr instanciates a Strip for given tag. -func NewStripForStr(str string) *Strip { - return &Strip{ - Open: (len(str) > 2) && str[2] == '~', - Close: (len(str) > 2) && str[len(str)-3] == '~', - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (s *Strip) String() string { - return fmt.Sprintf("Open: %t, Close: %t, OpenStandalone: %t, CloseStandalone: %t, InlineStandalone: %t", s.Open, s.Close, s.OpenStandalone, s.CloseStandalone, s.InlineStandalone) -} - -// -// Program -// - -// Program represents a program node. -type Program struct { - NodeType - Loc - - Body []Node // [ Statement ... ] - BlockParams []string - Chained bool - - // whitespace management - Strip *Strip -} - -// NewProgram instanciates a new program node. -func NewProgram(pos int, line int) *Program { - return &Program{ - NodeType: NodeProgram, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *Program) String() string { - return fmt.Sprintf("Program{Pos: %d}", node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *Program) Accept(visitor Visitor) interface{} { - return visitor.VisitProgram(node) -} - -// AddStatement adds given statement to program. -func (node *Program) AddStatement(statement Node) { - node.Body = append(node.Body, statement) -} - -// -// Mustache Statement -// - -// MustacheStatement represents a mustache node. -type MustacheStatement struct { - NodeType - Loc - - Unescaped bool - Expression *Expression - - // whitespace management - Strip *Strip -} - -// NewMustacheStatement instanciates a new mustache node. -func NewMustacheStatement(pos int, line int, unescaped bool) *MustacheStatement { - return &MustacheStatement{ - NodeType: NodeMustache, - Loc: Loc{pos, line}, - Unescaped: unescaped, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *MustacheStatement) String() string { - return fmt.Sprintf("Mustache{Pos: %d}", node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *MustacheStatement) Accept(visitor Visitor) interface{} { - return visitor.VisitMustache(node) -} - -// -// Block Statement -// - -// BlockStatement represents a block node. -type BlockStatement struct { - NodeType - Loc - - Expression *Expression - - Program *Program - Inverse *Program - - // whitespace management - OpenStrip *Strip - InverseStrip *Strip - CloseStrip *Strip -} - -// NewBlockStatement instanciates a new block node. -func NewBlockStatement(pos int, line int) *BlockStatement { - return &BlockStatement{ - NodeType: NodeBlock, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *BlockStatement) String() string { - return fmt.Sprintf("Block{Pos: %d}", node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *BlockStatement) Accept(visitor Visitor) interface{} { - return visitor.VisitBlock(node) -} - -// -// Partial Statement -// - -// PartialStatement represents a partial node. -type PartialStatement struct { - NodeType - Loc - - Name Node // PathExpression | SubExpression - Params []Node // [ Expression ... ] - Hash *Hash - - // whitespace management - Strip *Strip - Indent string -} - -// NewPartialStatement instanciates a new partial node. -func NewPartialStatement(pos int, line int) *PartialStatement { - return &PartialStatement{ - NodeType: NodePartial, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *PartialStatement) String() string { - return fmt.Sprintf("Partial{Name:%s, Pos:%d}", node.Name, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *PartialStatement) Accept(visitor Visitor) interface{} { - return visitor.VisitPartial(node) -} - -// -// Content Statement -// - -// ContentStatement represents a content node. -type ContentStatement struct { - NodeType - Loc - - Value string - Original string - - // whitespace management - RightStripped bool - LeftStripped bool -} - -// NewContentStatement instanciates a new content node. -func NewContentStatement(pos int, line int, val string) *ContentStatement { - return &ContentStatement{ - NodeType: NodeContent, - Loc: Loc{pos, line}, - - Value: val, - Original: val, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *ContentStatement) String() string { - return fmt.Sprintf("Content{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *ContentStatement) Accept(visitor Visitor) interface{} { - return visitor.VisitContent(node) -} - -// -// Comment Statement -// - -// CommentStatement represents a comment node. -type CommentStatement struct { - NodeType - Loc - - Value string - - // whitespace management - Strip *Strip -} - -// NewCommentStatement instanciates a new comment node. -func NewCommentStatement(pos int, line int, val string) *CommentStatement { - return &CommentStatement{ - NodeType: NodeComment, - Loc: Loc{pos, line}, - - Value: val, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *CommentStatement) String() string { - return fmt.Sprintf("Comment{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *CommentStatement) Accept(visitor Visitor) interface{} { - return visitor.VisitComment(node) -} - -// -// Expression -// - -// Expression represents an expression node. -type Expression struct { - NodeType - Loc - - Path Node // PathExpression | StringLiteral | BooleanLiteral | NumberLiteral - Params []Node // [ Expression ... ] - Hash *Hash -} - -// NewExpression instanciates a new expression node. -func NewExpression(pos int, line int) *Expression { - return &Expression{ - NodeType: NodeExpression, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *Expression) String() string { - return fmt.Sprintf("Expr{Path:%s, Pos:%d}", node.Path, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *Expression) Accept(visitor Visitor) interface{} { - return visitor.VisitExpression(node) -} - -// HelperName returns helper name, or an empty string if this expression can't be a helper. -func (node *Expression) HelperName() string { - path, ok := node.Path.(*PathExpression) - if !ok { - return "" - } - - if path.Data || (len(path.Parts) != 1) || (path.Depth > 0) || path.Scoped { - return "" - } - - return path.Parts[0] -} - -// FieldPath returns path expression representing a field path, or nil if this is not a field path. -func (node *Expression) FieldPath() *PathExpression { - path, ok := node.Path.(*PathExpression) - if !ok { - return nil - } - - return path -} - -// LiteralStr returns the string representation of literal value, with a boolean set to false if this is not a literal. -func (node *Expression) LiteralStr() (string, bool) { - return LiteralStr(node.Path) -} - -// Canonical returns the canonical form of expression node as a string. -func (node *Expression) Canonical() string { - if str, ok := HelperNameStr(node.Path); ok { - return str - } - - return "" -} - -// HelperNameStr returns the string representation of a helper name, with a boolean set to false if this is not a valid helper name. -// -// helperName : path | dataName | STRING | NUMBER | BOOLEAN | UNDEFINED | NULL -func HelperNameStr(node Node) (string, bool) { - // PathExpression - if str, ok := PathExpressionStr(node); ok { - return str, ok - } - - // Literal - if str, ok := LiteralStr(node); ok { - return str, ok - } - - return "", false -} - -// PathExpressionStr returns the string representation of path expression value, with a boolean set to false if this is not a path expression. -func PathExpressionStr(node Node) (string, bool) { - if path, ok := node.(*PathExpression); ok { - result := path.Original - - // "[foo bar]"" => "foo bar" - if (len(result) >= 2) && (result[0] == '[') && (result[len(result)-1] == ']') { - result = result[1 : len(result)-1] - } - - return result, true - } - - return "", false -} - -// LiteralStr returns the string representation of literal value, with a boolean set to false if this is not a literal. -func LiteralStr(node Node) (string, bool) { - if lit, ok := node.(*StringLiteral); ok { - return lit.Value, true - } - - if lit, ok := node.(*BooleanLiteral); ok { - return lit.Canonical(), true - } - - if lit, ok := node.(*NumberLiteral); ok { - return lit.Canonical(), true - } - - return "", false -} - -// -// SubExpression -// - -// SubExpression represents a subexpression node. -type SubExpression struct { - NodeType - Loc - - Expression *Expression -} - -// NewSubExpression instanciates a new subexpression node. -func NewSubExpression(pos int, line int) *SubExpression { - return &SubExpression{ - NodeType: NodeSubExpression, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *SubExpression) String() string { - return fmt.Sprintf("Sexp{Path:%s, Pos:%d}", node.Expression.Path, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *SubExpression) Accept(visitor Visitor) interface{} { - return visitor.VisitSubExpression(node) -} - -// -// Path Expression -// - -// PathExpression represents a path expression node. -type PathExpression struct { - NodeType - Loc - - Original string - Depth int - Parts []string - Data bool - Scoped bool -} - -// NewPathExpression instanciates a new path expression node. -func NewPathExpression(pos int, line int, data bool) *PathExpression { - result := &PathExpression{ - NodeType: NodePath, - Loc: Loc{pos, line}, - - Data: data, - } - - if data { - result.Original = "@" - } - - return result -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *PathExpression) String() string { - return fmt.Sprintf("Path{Original:'%s', Pos:%d}", node.Original, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *PathExpression) Accept(visitor Visitor) interface{} { - return visitor.VisitPath(node) -} - -// Part adds path part. -func (node *PathExpression) Part(part string) { - node.Original += part - - switch part { - case "..": - node.Depth++ - node.Scoped = true - case ".", "this": - node.Scoped = true - default: - node.Parts = append(node.Parts, part) - } -} - -// Sep adds path separator. -func (node *PathExpression) Sep(separator string) { - node.Original += separator -} - -// IsDataRoot returns true if path expression is @root. -func (node *PathExpression) IsDataRoot() bool { - return node.Data && (node.Parts[0] == "root") -} - -// -// String Literal -// - -// StringLiteral represents a string node. -type StringLiteral struct { - NodeType - Loc - - Value string -} - -// NewStringLiteral instanciates a new string node. -func NewStringLiteral(pos int, line int, val string) *StringLiteral { - return &StringLiteral{ - NodeType: NodeString, - Loc: Loc{pos, line}, - - Value: val, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *StringLiteral) String() string { - return fmt.Sprintf("String{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *StringLiteral) Accept(visitor Visitor) interface{} { - return visitor.VisitString(node) -} - -// -// Boolean Literal -// - -// BooleanLiteral represents a boolean node. -type BooleanLiteral struct { - NodeType - Loc - - Value bool - Original string -} - -// NewBooleanLiteral instanciates a new boolean node. -func NewBooleanLiteral(pos int, line int, val bool, original string) *BooleanLiteral { - return &BooleanLiteral{ - NodeType: NodeBoolean, - Loc: Loc{pos, line}, - - Value: val, - Original: original, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *BooleanLiteral) String() string { - return fmt.Sprintf("Boolean{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *BooleanLiteral) Accept(visitor Visitor) interface{} { - return visitor.VisitBoolean(node) -} - -// Canonical returns the canonical form of boolean node as a string (ie. "true" | "false"). -func (node *BooleanLiteral) Canonical() string { - if node.Value { - return "true" - } - - return "false" -} - -// -// Number Literal -// - -// NumberLiteral represents a number node. -type NumberLiteral struct { - NodeType - Loc - - Value float64 - IsInt bool - Original string -} - -// NewNumberLiteral instanciates a new number node. -func NewNumberLiteral(pos int, line int, val float64, isInt bool, original string) *NumberLiteral { - return &NumberLiteral{ - NodeType: NodeNumber, - Loc: Loc{pos, line}, - - Value: val, - IsInt: isInt, - Original: original, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *NumberLiteral) String() string { - return fmt.Sprintf("Number{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *NumberLiteral) Accept(visitor Visitor) interface{} { - return visitor.VisitNumber(node) -} - -// Canonical returns the canonical form of number node as a string (eg: "12", "-1.51"). -func (node *NumberLiteral) Canonical() string { - prec := -1 - if node.IsInt { - prec = 0 - } - return strconv.FormatFloat(node.Value, 'f', prec, 64) -} - -// Number returns an integer or a float. -func (node *NumberLiteral) Number() interface{} { - if node.IsInt { - return int(node.Value) - } - - return node.Value -} - -// -// Hash -// - -// Hash represents a hash node. -type Hash struct { - NodeType - Loc - - Pairs []*HashPair -} - -// NewHash instanciates a new hash node. -func NewHash(pos int, line int) *Hash { - return &Hash{ - NodeType: NodeHash, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *Hash) String() string { - result := fmt.Sprintf("Hash{[%d", node.Loc.Pos) - - for i, p := range node.Pairs { - if i > 0 { - result += ", " - } - result += p.String() - } - - return result + fmt.Sprintf("], Pos:%d}", node.Loc.Pos) -} - -// Accept is the receiver entry point for visitors. -func (node *Hash) Accept(visitor Visitor) interface{} { - return visitor.VisitHash(node) -} - -// -// HashPair -// - -// HashPair represents a hash pair node. -type HashPair struct { - NodeType - Loc - - Key string - Val Node // Expression -} - -// NewHashPair instanciates a new hash pair node. -func NewHashPair(pos int, line int) *HashPair { - return &HashPair{ - NodeType: NodeHashPair, - Loc: Loc{pos, line}, - } -} - -// String returns a string representation of receiver that can be used for debugging. -func (node *HashPair) String() string { - return node.Key + "=" + node.Val.String() -} - -// Accept is the receiver entry point for visitors. -func (node *HashPair) Accept(visitor Visitor) interface{} { - return visitor.VisitHashPair(node) -} diff --git a/vendor/github.com/aymerick/raymond/ast/print.go b/vendor/github.com/aymerick/raymond/ast/print.go deleted file mode 100644 index 133ae6e..0000000 --- a/vendor/github.com/aymerick/raymond/ast/print.go +++ /dev/null @@ -1,279 +0,0 @@ -package ast - -import ( - "fmt" - "strings" -) - -// printVisitor implements the Visitor interface to print a AST. -type printVisitor struct { - buf string - depth int - - original bool - inBlock bool -} - -func newPrintVisitor() *printVisitor { - return &printVisitor{} -} - -// Print returns a string representation of given AST, that can be used for debugging purpose. -func Print(node Node) string { - visitor := newPrintVisitor() - node.Accept(visitor) - return visitor.output() -} - -func (v *printVisitor) output() string { - return v.buf -} - -func (v *printVisitor) indent() { - for i := 0; i < v.depth; { - v.buf += " " - i++ - } -} - -func (v *printVisitor) str(val string) { - v.buf += val -} - -func (v *printVisitor) nl() { - v.str("\n") -} - -func (v *printVisitor) line(val string) { - v.indent() - v.str(val) - v.nl() -} - -// -// Visitor interface -// - -// Statements - -// VisitProgram implements corresponding Visitor interface method -func (v *printVisitor) VisitProgram(node *Program) interface{} { - if len(node.BlockParams) > 0 { - v.line("BLOCK PARAMS: [ " + strings.Join(node.BlockParams, " ") + " ]") - } - - for _, n := range node.Body { - n.Accept(v) - } - - return nil -} - -// VisitMustache implements corresponding Visitor interface method -func (v *printVisitor) VisitMustache(node *MustacheStatement) interface{} { - v.indent() - v.str("{{ ") - - node.Expression.Accept(v) - - v.str(" }}") - v.nl() - - return nil -} - -// VisitBlock implements corresponding Visitor interface method -func (v *printVisitor) VisitBlock(node *BlockStatement) interface{} { - v.inBlock = true - - v.line("BLOCK:") - v.depth++ - - node.Expression.Accept(v) - - if node.Program != nil { - v.line("PROGRAM:") - v.depth++ - node.Program.Accept(v) - v.depth-- - } - - if node.Inverse != nil { - // if node.Program != nil { - // v.depth++ - // } - - v.line("{{^}}") - v.depth++ - node.Inverse.Accept(v) - v.depth-- - - // if node.Program != nil { - // v.depth-- - // } - } - - v.inBlock = false - - return nil -} - -// VisitPartial implements corresponding Visitor interface method -func (v *printVisitor) VisitPartial(node *PartialStatement) interface{} { - v.indent() - v.str("{{> PARTIAL:") - - v.original = true - node.Name.Accept(v) - v.original = false - - if len(node.Params) > 0 { - v.str(" ") - node.Params[0].Accept(v) - } - - // hash - if node.Hash != nil { - v.str(" ") - node.Hash.Accept(v) - } - - v.str(" }}") - v.nl() - - return nil -} - -// VisitContent implements corresponding Visitor interface method -func (v *printVisitor) VisitContent(node *ContentStatement) interface{} { - v.line("CONTENT[ '" + node.Value + "' ]") - - return nil -} - -// VisitComment implements corresponding Visitor interface method -func (v *printVisitor) VisitComment(node *CommentStatement) interface{} { - v.line("{{! '" + node.Value + "' }}") - - return nil -} - -// Expressions - -// VisitExpression implements corresponding Visitor interface method -func (v *printVisitor) VisitExpression(node *Expression) interface{} { - if v.inBlock { - v.indent() - } - - // path - node.Path.Accept(v) - - // params - v.str(" [") - for i, n := range node.Params { - if i > 0 { - v.str(", ") - } - n.Accept(v) - } - v.str("]") - - // hash - if node.Hash != nil { - v.str(" ") - node.Hash.Accept(v) - } - - if v.inBlock { - v.nl() - } - - return nil -} - -// VisitSubExpression implements corresponding Visitor interface method -func (v *printVisitor) VisitSubExpression(node *SubExpression) interface{} { - node.Expression.Accept(v) - - return nil -} - -// VisitPath implements corresponding Visitor interface method -func (v *printVisitor) VisitPath(node *PathExpression) interface{} { - if v.original { - v.str(node.Original) - } else { - path := strings.Join(node.Parts, "/") - - result := "" - if node.Data { - result += "@" - } - - v.str(result + "PATH:" + path) - } - - return nil -} - -// Literals - -// VisitString implements corresponding Visitor interface method -func (v *printVisitor) VisitString(node *StringLiteral) interface{} { - if v.original { - v.str(node.Value) - } else { - v.str("\"" + node.Value + "\"") - } - - return nil -} - -// VisitBoolean implements corresponding Visitor interface method -func (v *printVisitor) VisitBoolean(node *BooleanLiteral) interface{} { - if v.original { - v.str(node.Original) - } else { - v.str(fmt.Sprintf("BOOLEAN{%s}", node.Canonical())) - } - - return nil -} - -// VisitNumber implements corresponding Visitor interface method -func (v *printVisitor) VisitNumber(node *NumberLiteral) interface{} { - if v.original { - v.str(node.Original) - } else { - v.str(fmt.Sprintf("NUMBER{%s}", node.Canonical())) - } - - return nil -} - -// Miscellaneous - -// VisitHash implements corresponding Visitor interface method -func (v *printVisitor) VisitHash(node *Hash) interface{} { - v.str("HASH{") - - for i, p := range node.Pairs { - if i > 0 { - v.str(", ") - } - p.Accept(v) - } - - v.str("}") - - return nil -} - -// VisitHashPair implements corresponding Visitor interface method -func (v *printVisitor) VisitHashPair(node *HashPair) interface{} { - v.str(node.Key + "=") - node.Val.Accept(v) - - return nil -} diff --git a/vendor/github.com/aymerick/raymond/base_test.go b/vendor/github.com/aymerick/raymond/base_test.go deleted file mode 100644 index b769331..0000000 --- a/vendor/github.com/aymerick/raymond/base_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package raymond - -import ( - "fmt" - "regexp" - "testing" -) - -type Test struct { - name string - input string - data interface{} - privData map[string]interface{} - helpers map[string]interface{} - partials map[string]string - output interface{} -} - -func launchTests(t *testing.T, tests []Test) { - // NOTE: TestMustache() makes Parallel testing fail - // t.Parallel() - - for _, test := range tests { - var err error - var tpl *Template - - // parse template - tpl, err = Parse(test.input) - if err != nil { - t.Errorf("Test '%s' failed - Failed to parse template\ninput:\n\t'%s'\nerror:\n\t%s", test.name, test.input, err) - } else { - if len(test.helpers) > 0 { - // register helpers - tpl.RegisterHelpers(test.helpers) - } - - if len(test.partials) > 0 { - // register partials - tpl.RegisterPartials(test.partials) - } - - // setup private data frame - var privData *DataFrame - if test.privData != nil { - privData = NewDataFrame() - for k, v := range test.privData { - privData.Set(k, v) - } - } - - // render template - output, err := tpl.ExecWith(test.data, privData) - if err != nil { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\nerror:\n\t%s\nAST:\n\t%s", test.name, test.input, Str(test.data), err, tpl.PrintAST()) - } else { - // check output - var expectedArr []string - expectedArr, ok := test.output.([]string) - if ok { - match := false - for _, expectedStr := range expectedArr { - if expectedStr == output { - match = true - break - } - } - - if !match { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\npartials:\n\t%s\nexpected\n\t%q\ngot\n\t%q\nAST:\n%s", test.name, test.input, Str(test.data), Str(test.partials), expectedArr, output, tpl.PrintAST()) - } - } else { - expectedStr, ok := test.output.(string) - if !ok { - panic(fmt.Errorf("Erroneous test output description: %q", test.output)) - } - - if expectedStr != output { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\npartials:\n\t%s\nexpected\n\t%q\ngot\n\t%q\nAST:\n%s", test.name, test.input, Str(test.data), Str(test.partials), expectedStr, output, tpl.PrintAST()) - } - } - } - } - } -} - -func launchErrorTests(t *testing.T, tests []Test) { - t.Parallel() - - for _, test := range tests { - var err error - var tpl *Template - - // parse template - tpl, err = Parse(test.input) - if err != nil { - t.Errorf("Test '%s' failed - Failed to parse template\ninput:\n\t'%s'\nerror:\n\t%s", test.name, test.input, err) - } else { - if len(test.helpers) > 0 { - // register helpers - tpl.RegisterHelpers(test.helpers) - } - - if len(test.partials) > 0 { - // register partials - tpl.RegisterPartials(test.partials) - } - - // setup private data frame - var privData *DataFrame - if test.privData != nil { - privData := NewDataFrame() - for k, v := range test.privData { - privData.Set(k, v) - } - } - - // render template - output, err := tpl.ExecWith(test.data, privData) - if err == nil { - t.Errorf("Test '%s' failed - Error expected\ninput:\n\t'%s'\ngot\n\t%q\nAST:\n%q", test.name, test.input, output, tpl.PrintAST()) - } else { - var errMatch error - match := false - - // check output - var expectedArr []string - expectedArr, ok := test.output.([]string) - if ok { - if len(expectedArr) > 0 { - for _, expectedStr := range expectedArr { - match, errMatch = regexp.MatchString(regexp.QuoteMeta(expectedStr), fmt.Sprint(err)) - if errMatch != nil { - panic("Failed to match regexp") - } - - if match { - break - } - } - } else { - // nothing to test - match = true - } - } else { - expectedStr, ok := test.output.(string) - if !ok { - panic(fmt.Errorf("Erroneous test output description: %q", test.output)) - } - - if expectedStr != "" { - match, errMatch = regexp.MatchString(regexp.QuoteMeta(expectedStr), fmt.Sprint(err)) - if errMatch != nil { - panic("Failed to match regexp") - } - } else { - // nothing to test - match = true - } - } - - if !match { - t.Errorf("Test '%s' failed - Incorrect error returned\ninput:\n\t'%s'\ndata:\n\t%s\nexpected\n\t%q\ngot\n\t%q", test.name, test.input, Str(test.data), test.output, err) - } - } - } - } -} diff --git a/vendor/github.com/aymerick/raymond/benchmark_test.go b/vendor/github.com/aymerick/raymond/benchmark_test.go deleted file mode 100644 index f9ea74c..0000000 --- a/vendor/github.com/aymerick/raymond/benchmark_test.go +++ /dev/null @@ -1,316 +0,0 @@ -package raymond - -import "testing" - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/bench/ -// -// Note that handlebars.js does NOT benchmark template compilation, it only benchmarks evaluation. -// - -func BenchmarkArguments(b *testing.B) { - source := `{{foo person "person" 1 true foo=bar foo="person" foo=1 foo=true}}` - - ctx := map[string]bool{ - "bar": true, - } - - tpl := MustParse(source) - tpl.RegisterHelper("foo", func(a, b, c, d interface{}) string { return "" }) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkArrayEach(b *testing.B) { - source := `{{#each names}}{{name}}{{/each}}` - - ctx := map[string][]map[string]string{ - "names": { - {"name": "Moe"}, - {"name": "Larry"}, - {"name": "Curly"}, - {"name": "Shemp"}, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkArrayMustache(b *testing.B) { - source := `{{#names}}{{name}}{{/names}}` - - ctx := map[string][]map[string]string{ - "names": { - {"name": "Moe"}, - {"name": "Larry"}, - {"name": "Curly"}, - {"name": "Shemp"}, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkComplex(b *testing.B) { - source := `

{{header}}

-{{#if items}} -
    - {{#each items}} - {{#if current}} -
  • {{name}}
  • - {{^}} -
  • {{name}}
  • - {{/if}} - {{/each}} -
-{{^}} -

The list is empty.

-{{/if}} -` - - ctx := map[string]interface{}{ - "header": func() string { return "Colors" }, - "hasItems": true, - "items": []map[string]interface{}{ - {"name": "red", "current": true, "url": "#Red"}, - {"name": "green", "current": false, "url": "#Green"}, - {"name": "blue", "current": false, "url": "#Blue"}, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkData(b *testing.B) { - source := `{{#each names}}{{@index}}{{name}}{{/each}}` - - ctx := map[string][]map[string]string{ - "names": { - {"name": "Moe"}, - {"name": "Larry"}, - {"name": "Curly"}, - {"name": "Shemp"}, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkDepth1(b *testing.B) { - source := `{{#each names}}{{../foo}}{{/each}}` - - ctx := map[string]interface{}{ - "names": []map[string]string{ - {"name": "Moe"}, - {"name": "Larry"}, - {"name": "Curly"}, - {"name": "Shemp"}, - }, - "foo": "bar", - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkDepth2(b *testing.B) { - source := `{{#each names}}{{#each name}}{{../bat}}{{../../foo}}{{/each}}{{/each}}` - - ctx := map[string]interface{}{ - "names": []map[string]interface{}{ - {"bat": "foo", "name": []string{"Moe"}}, - {"bat": "foo", "name": []string{"Larry"}}, - {"bat": "foo", "name": []string{"Curly"}}, - {"bat": "foo", "name": []string{"Shemp"}}, - }, - "foo": "bar", - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkObjectMustache(b *testing.B) { - source := `{{#person}}{{name}}{{age}}{{/person}}` - - ctx := map[string]interface{}{ - "person": map[string]interface{}{ - "name": "Larry", - "age": 45, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkObject(b *testing.B) { - source := `{{#with person}}{{name}}{{age}}{{/with}}` - - ctx := map[string]interface{}{ - "person": map[string]interface{}{ - "name": "Larry", - "age": 45, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkPartialRecursion(b *testing.B) { - source := `{{name}}{{#each kids}}{{>recursion}}{{/each}}` - - ctx := map[string]interface{}{ - "name": 1, - "kids": []map[string]interface{}{ - { - "name": "1.1", - "kids": []map[string]interface{}{ - { - "name": "1.1.1", - "kids": []map[string]interface{}{}, - }, - }, - }, - }, - } - - tpl := MustParse(source) - - partial := MustParse(`{{name}}{{#each kids}}{{>recursion}}{{/each}}`) - tpl.RegisterPartialTemplate("recursion", partial) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkPartial(b *testing.B) { - source := `{{#each peeps}}{{>variables}}{{/each}}` - - ctx := map[string]interface{}{ - "peeps": []map[string]interface{}{ - {"name": "Moe", "count": 15}, - {"name": "Moe", "count": 5}, - {"name": "Curly", "count": 1}, - }, - } - - tpl := MustParse(source) - - partial := MustParse(`Hello {{name}}! You have {{count}} new messages.`) - tpl.RegisterPartialTemplate("variables", partial) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkPath(b *testing.B) { - source := `{{person.name.bar.baz}}{{person.age}}{{person.foo}}{{animal.age}}` - - ctx := map[string]interface{}{ - "person": map[string]interface{}{ - "name": map[string]interface{}{ - "bar": map[string]string{ - "baz": "Larry", - }, - }, - "age": 45, - }, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkString(b *testing.B) { - source := `Hello world` - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(nil) - } -} - -func BenchmarkSubExpression(b *testing.B) { - source := `{{echo (header)}}` - - ctx := map[string]interface{}{} - - tpl := MustParse(source) - tpl.RegisterHelpers(map[string]interface{}{ - "echo": func(v string) string { return "foo " + v }, - "header": func() string { return "Colors" }, - }) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} - -func BenchmarkVariables(b *testing.B) { - source := `Hello {{name}}! You have {{count}} new messages.` - - ctx := map[string]interface{}{ - "name": "Mick", - "count": 30, - } - - tpl := MustParse(source) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - tpl.MustExec(ctx) - } -} diff --git a/vendor/github.com/aymerick/raymond/data_frame.go b/vendor/github.com/aymerick/raymond/data_frame.go deleted file mode 100644 index ce63218..0000000 --- a/vendor/github.com/aymerick/raymond/data_frame.go +++ /dev/null @@ -1,95 +0,0 @@ -package raymond - -import "reflect" - -// DataFrame represents a private data frame. -// -// Cf. private variables documentation at: http://handlebarsjs.com/block_helpers.html -type DataFrame struct { - parent *DataFrame - data map[string]interface{} -} - -// NewDataFrame instanciates a new private data frame. -func NewDataFrame() *DataFrame { - return &DataFrame{ - data: make(map[string]interface{}), - } -} - -// Copy instanciates a new private data frame with receiver as parent. -func (p *DataFrame) Copy() *DataFrame { - result := NewDataFrame() - - for k, v := range p.data { - result.data[k] = v - } - - result.parent = p - - return result -} - -// newIterDataFrame instanciates a new private data frame with receiver as parent and with iteration data set (@index, @key, @first, @last) -func (p *DataFrame) newIterDataFrame(length int, i int, key interface{}) *DataFrame { - result := p.Copy() - - result.Set("index", i) - result.Set("key", key) - result.Set("first", i == 0) - result.Set("last", i == length-1) - - return result -} - -// Set sets a data value. -func (p *DataFrame) Set(key string, val interface{}) { - p.data[key] = val -} - -// Get gets a data value. -func (p *DataFrame) Get(key string) interface{} { - return p.find([]string{key}) -} - -// find gets a deep data value -// -// @todo This is NOT consistent with the way we resolve data in template (cf. `evalDataPathExpression()`) ! FIX THAT ! -func (p *DataFrame) find(parts []string) interface{} { - data := p.data - - for i, part := range parts { - val := data[part] - if val == nil { - return nil - } - - if i == len(parts)-1 { - // found - return val - } - - valValue := reflect.ValueOf(val) - if valValue.Kind() != reflect.Map { - // not found - return nil - } - - // continue - data = mapStringInterface(valValue) - } - - // not found - return nil -} - -// mapStringInterface converts any `map` to `map[string]interface{}` -func mapStringInterface(value reflect.Value) map[string]interface{} { - result := make(map[string]interface{}) - - for _, key := range value.MapKeys() { - result[strValue(key)] = value.MapIndex(key).Interface() - } - - return result -} diff --git a/vendor/github.com/aymerick/raymond/escape.go b/vendor/github.com/aymerick/raymond/escape.go deleted file mode 100644 index 6a0363c..0000000 --- a/vendor/github.com/aymerick/raymond/escape.go +++ /dev/null @@ -1,65 +0,0 @@ -package raymond - -import ( - "bytes" - "strings" -) - -// -// That whole file is borrowed from https://github.com/golang/go/tree/master/src/html/escape.go -// -// With changes: -// ' => ' -// " => " -// -// To stay in sync with JS implementation, and make mustache tests pass. -// - -type writer interface { - WriteString(string) (int, error) -} - -const escapedChars = `&'<>"` - -func escape(w writer, s string) error { - i := strings.IndexAny(s, escapedChars) - for i != -1 { - if _, err := w.WriteString(s[:i]); err != nil { - return err - } - var esc string - switch s[i] { - case '&': - esc = "&" - case '\'': - esc = "'" - case '<': - esc = "<" - case '>': - esc = ">" - case '"': - esc = """ - default: - panic("unrecognized escape character") - } - s = s[i+1:] - if _, err := w.WriteString(esc); err != nil { - return err - } - i = strings.IndexAny(s, escapedChars) - } - _, err := w.WriteString(s) - return err -} - -// Escape escapes special HTML characters. -// -// It can be used by helpers that return a SafeString and that need to escape some content by themselves. -func Escape(s string) string { - if strings.IndexAny(s, escapedChars) == -1 { - return s - } - var buf bytes.Buffer - escape(&buf, s) - return buf.String() -} diff --git a/vendor/github.com/aymerick/raymond/escape_test.go b/vendor/github.com/aymerick/raymond/escape_test.go deleted file mode 100644 index b77bb09..0000000 --- a/vendor/github.com/aymerick/raymond/escape_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package raymond - -import "fmt" - -func ExampleEscape() { - tpl := MustParse("{{link url text}}") - - tpl.RegisterHelper("link", func(url string, text string) SafeString { - return SafeString("" + Escape(text) + "") - }) - - ctx := map[string]string{ - "url": "http://www.aymerick.com/", - "text": "This is a cool website", - } - - result := tpl.MustExec(ctx) - fmt.Print(result) - // Output: This is a <em>cool</em> website -} diff --git a/vendor/github.com/aymerick/raymond/eval.go b/vendor/github.com/aymerick/raymond/eval.go deleted file mode 100644 index d49b708..0000000 --- a/vendor/github.com/aymerick/raymond/eval.go +++ /dev/null @@ -1,984 +0,0 @@ -package raymond - -import ( - "bytes" - "fmt" - "reflect" - "strconv" - "strings" - - "github.com/aymerick/raymond/ast" -) - -var ( - // @note borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go - errorType = reflect.TypeOf((*error)(nil)).Elem() - fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() - - zero reflect.Value -) - -// evalVisitor evaluates a handlebars template with context -type evalVisitor struct { - tpl *Template - - // contexts stack - ctx []reflect.Value - - // current data frame (chained with parent) - dataFrame *DataFrame - - // block parameters stack - blockParams []map[string]interface{} - - // block statements stack - blocks []*ast.BlockStatement - - // expressions stack - exprs []*ast.Expression - - // memoize expressions that were function calls - exprFunc map[*ast.Expression]bool - - // used for info on panic - curNode ast.Node -} - -// NewEvalVisitor instanciate a new evaluation visitor with given context and initial private data frame -// -// If privData is nil, then a default data frame is created -func newEvalVisitor(tpl *Template, ctx interface{}, privData *DataFrame) *evalVisitor { - frame := privData - if frame == nil { - frame = NewDataFrame() - } - - return &evalVisitor{ - tpl: tpl, - ctx: []reflect.Value{reflect.ValueOf(ctx)}, - dataFrame: frame, - exprFunc: make(map[*ast.Expression]bool), - } -} - -// at sets current node -func (v *evalVisitor) at(node ast.Node) { - v.curNode = node -} - -// -// Contexts stack -// - -// pushCtx pushes new context to the stack -func (v *evalVisitor) pushCtx(ctx reflect.Value) { - v.ctx = append(v.ctx, ctx) -} - -// popCtx pops last context from stack -func (v *evalVisitor) popCtx() reflect.Value { - if len(v.ctx) == 0 { - return zero - } - - var result reflect.Value - result, v.ctx = v.ctx[len(v.ctx)-1], v.ctx[:len(v.ctx)-1] - - return result -} - -// rootCtx returns root context -func (v *evalVisitor) rootCtx() reflect.Value { - return v.ctx[0] -} - -// curCtx returns current context -func (v *evalVisitor) curCtx() reflect.Value { - return v.ancestorCtx(0) -} - -// ancestorCtx returns ancestor context -func (v *evalVisitor) ancestorCtx(depth int) reflect.Value { - index := len(v.ctx) - 1 - depth - if index < 0 { - return zero - } - - return v.ctx[index] -} - -// -// Private data frame -// - -// setDataFrame sets new data frame -func (v *evalVisitor) setDataFrame(frame *DataFrame) { - v.dataFrame = frame -} - -// popDataFrame sets back parent data frame -func (v *evalVisitor) popDataFrame() { - v.dataFrame = v.dataFrame.parent -} - -// -// Block Parameters stack -// - -// pushBlockParams pushes new block params to the stack -func (v *evalVisitor) pushBlockParams(params map[string]interface{}) { - v.blockParams = append(v.blockParams, params) -} - -// popBlockParams pops last block params from stack -func (v *evalVisitor) popBlockParams() map[string]interface{} { - var result map[string]interface{} - - if len(v.blockParams) == 0 { - return result - } - - result, v.blockParams = v.blockParams[len(v.blockParams)-1], v.blockParams[:len(v.blockParams)-1] - return result -} - -// blockParam iterates on stack to find given block parameter, and returns its value or nil if not founc -func (v *evalVisitor) blockParam(name string) interface{} { - for i := len(v.blockParams) - 1; i >= 0; i-- { - for k, v := range v.blockParams[i] { - if name == k { - return v - } - } - } - - return nil -} - -// -// Blocks stack -// - -// pushBlock pushes new block statement to stack -func (v *evalVisitor) pushBlock(block *ast.BlockStatement) { - v.blocks = append(v.blocks, block) -} - -// popBlock pops last block statement from stack -func (v *evalVisitor) popBlock() *ast.BlockStatement { - if len(v.blocks) == 0 { - return nil - } - - var result *ast.BlockStatement - result, v.blocks = v.blocks[len(v.blocks)-1], v.blocks[:len(v.blocks)-1] - - return result -} - -// curBlock returns current block statement -func (v *evalVisitor) curBlock() *ast.BlockStatement { - if len(v.blocks) == 0 { - return nil - } - - return v.blocks[len(v.blocks)-1] -} - -// -// Expressions stack -// - -// pushExpr pushes new expression to stack -func (v *evalVisitor) pushExpr(expression *ast.Expression) { - v.exprs = append(v.exprs, expression) -} - -// popExpr pops last expression from stack -func (v *evalVisitor) popExpr() *ast.Expression { - if len(v.exprs) == 0 { - return nil - } - - var result *ast.Expression - result, v.exprs = v.exprs[len(v.exprs)-1], v.exprs[:len(v.exprs)-1] - - return result -} - -// curExpr returns current expression -func (v *evalVisitor) curExpr() *ast.Expression { - if len(v.exprs) == 0 { - return nil - } - - return v.exprs[len(v.exprs)-1] -} - -// -// Error functions -// - -// errPanic panics -func (v *evalVisitor) errPanic(err error) { - panic(fmt.Errorf("Evaluation error: %s\nCurrent node:\n\t%s", err, v.curNode)) -} - -// errorf panics with a custom message -func (v *evalVisitor) errorf(format string, args ...interface{}) { - v.errPanic(fmt.Errorf(format, args...)) -} - -// -// Evaluation -// - -// evalProgram eEvaluates program with given context and returns string result -func (v *evalVisitor) evalProgram(program *ast.Program, ctx interface{}, data *DataFrame, key interface{}) string { - blockParams := make(map[string]interface{}) - - // compute block params - if len(program.BlockParams) > 0 { - blockParams[program.BlockParams[0]] = ctx - } - - if (len(program.BlockParams) > 1) && (key != nil) { - blockParams[program.BlockParams[1]] = key - } - - // push contexts - if len(blockParams) > 0 { - v.pushBlockParams(blockParams) - } - - ctxVal := reflect.ValueOf(ctx) - if ctxVal.IsValid() { - v.pushCtx(ctxVal) - } - - if data != nil { - v.setDataFrame(data) - } - - // evaluate program - result, _ := program.Accept(v).(string) - - // pop contexts - if data != nil { - v.popDataFrame() - } - - if ctxVal.IsValid() { - v.popCtx() - } - - if len(blockParams) > 0 { - v.popBlockParams() - } - - return result -} - -// evalPath evaluates all path parts with given context -func (v *evalVisitor) evalPath(ctx reflect.Value, parts []string, exprRoot bool) (reflect.Value, bool) { - partResolved := false - - for i := 0; i < len(parts); i++ { - part := parts[i] - - // "[foo bar]"" => "foo bar" - if (len(part) >= 2) && (part[0] == '[') && (part[len(part)-1] == ']') { - part = part[1 : len(part)-1] - } - - ctx = v.evalField(ctx, part, exprRoot) - if !ctx.IsValid() { - break - } - - // we resolved at least one part of path - partResolved = true - } - - return ctx, partResolved -} - -// evalField evaluates field with given context -func (v *evalVisitor) evalField(ctx reflect.Value, fieldName string, exprRoot bool) reflect.Value { - result := zero - - ctx, _ = indirect(ctx) - if !ctx.IsValid() { - return result - } - - // check if this is a method call - result, isMeth := v.evalMethod(ctx, fieldName, exprRoot) - if !isMeth { - switch ctx.Kind() { - case reflect.Struct: - // example: firstName => FirstName - expFieldName := strings.Title(fieldName) - - // check if struct have this field and that it is exported - if tField, ok := ctx.Type().FieldByName(expFieldName); ok && (tField.PkgPath == "") { - // struct field - result = ctx.FieldByIndex(tField.Index) - } - case reflect.Map: - nameVal := reflect.ValueOf(fieldName) - if nameVal.Type().AssignableTo(ctx.Type().Key()) { - // map key - result = ctx.MapIndex(nameVal) - } - case reflect.Array, reflect.Slice: - if i, err := strconv.Atoi(fieldName); (err == nil) && (i < ctx.Len()) { - result = ctx.Index(i) - } - } - } - - // check if result is a function - result, _ = indirect(result) - if result.Kind() == reflect.Func { - result = v.evalFieldFunc(fieldName, result, exprRoot) - } - - return result -} - -// evalFieldFunc tries to evaluate given method name, and a boolean to indicate if this was a method call -func (v *evalVisitor) evalMethod(ctx reflect.Value, name string, exprRoot bool) (reflect.Value, bool) { - if ctx.Kind() != reflect.Interface && ctx.CanAddr() { - ctx = ctx.Addr() - } - - method := ctx.MethodByName(name) - if !method.IsValid() { - // example: subject() => Subject() - method = ctx.MethodByName(strings.Title(name)) - } - - if !method.IsValid() { - return zero, false - } - - return v.evalFieldFunc(name, method, exprRoot), true -} - -// evalFieldFunc evaluates given function -func (v *evalVisitor) evalFieldFunc(name string, funcVal reflect.Value, exprRoot bool) reflect.Value { - ensureValidHelper(name, funcVal) - - var options *Options - if exprRoot { - // create function arg with all params/hash - expr := v.curExpr() - options = v.helperOptions(expr) - - // ok, that expression was a function call - v.exprFunc[expr] = true - } else { - // we are not at root of expression, so we are a parameter... and we don't like - // infinite loops caused by trying to parse ourself forever - options = newEmptyOptions(v) - } - - return v.callFunc(name, funcVal, options) -} - -// findBlockParam returns node's block parameter -func (v *evalVisitor) findBlockParam(node *ast.PathExpression) (string, interface{}) { - if len(node.Parts) > 0 { - name := node.Parts[0] - if value := v.blockParam(name); value != nil { - return name, value - } - } - - return "", nil -} - -// evalPathExpression evaluates a path expression -func (v *evalVisitor) evalPathExpression(node *ast.PathExpression, exprRoot bool) interface{} { - var result interface{} - - if name, value := v.findBlockParam(node); value != nil { - // block parameter value - - // We push a new context so we can evaluate the path expression (note: this may be a bad idea). - // - // Example: - // {{#foo as |bar|}} - // {{bar.baz}} - // {{/foo}} - // - // With data: - // {"foo": {"baz": "bat"}} - newCtx := map[string]interface{}{name: value} - - v.pushCtx(reflect.ValueOf(newCtx)) - result = v.evalCtxPathExpression(node, exprRoot) - v.popCtx() - } else { - ctxTried := false - - if node.IsDataRoot() { - // context path - result = v.evalCtxPathExpression(node, exprRoot) - - ctxTried = true - } - - if (result == nil) && node.Data { - // if it is @root, then we tried to evaluate with root context but nothing was found - // so let's try with private data - - // private data - result = v.evalDataPathExpression(node, exprRoot) - } - - if (result == nil) && !ctxTried { - // context path - result = v.evalCtxPathExpression(node, exprRoot) - } - } - - return result -} - -// evalDataPathExpression evaluates a private data path expression -func (v *evalVisitor) evalDataPathExpression(node *ast.PathExpression, exprRoot bool) interface{} { - // find data frame - frame := v.dataFrame - for i := node.Depth; i > 0; i-- { - if frame.parent == nil { - return nil - } - frame = frame.parent - } - - // resolve data - // @note Can be changed to v.evalCtx() as context can't be an array - result, _ := v.evalCtxPath(reflect.ValueOf(frame.data), node.Parts, exprRoot) - return result -} - -// evalCtxPathExpression evaluates a context path expression -func (v *evalVisitor) evalCtxPathExpression(node *ast.PathExpression, exprRoot bool) interface{} { - v.at(node) - - if node.IsDataRoot() { - // `@root` - remove the first part - parts := node.Parts[1:len(node.Parts)] - - result, _ := v.evalCtxPath(v.rootCtx(), parts, exprRoot) - return result - } - - return v.evalDepthPath(node.Depth, node.Parts, exprRoot) -} - -// evalDepthPath iterates on contexts, starting at given depth, until there is one that resolve given path parts -func (v *evalVisitor) evalDepthPath(depth int, parts []string, exprRoot bool) interface{} { - var result interface{} - partResolved := false - - ctx := v.ancestorCtx(depth) - - for (result == nil) && ctx.IsValid() && (depth <= len(v.ctx) && !partResolved) { - // try with context - result, partResolved = v.evalCtxPath(ctx, parts, exprRoot) - - // As soon as we find the first part of a path, we must not try to resolve with parent context if result is finally `nil` - // Reference: "Dotted Names - Context Precedence" mustache test - if !partResolved && (result == nil) { - // try with previous context - depth++ - ctx = v.ancestorCtx(depth) - } - } - - return result -} - -// evalCtxPath evaluates path with given context -func (v *evalVisitor) evalCtxPath(ctx reflect.Value, parts []string, exprRoot bool) (interface{}, bool) { - var result interface{} - partResolved := false - - switch ctx.Kind() { - case reflect.Array, reflect.Slice: - // Array context - var results []interface{} - - for i := 0; i < ctx.Len(); i++ { - value, _ := v.evalPath(ctx.Index(i), parts, exprRoot) - if value.IsValid() { - results = append(results, value.Interface()) - } - } - - result = results - default: - // NOT array context - var value reflect.Value - - value, partResolved = v.evalPath(ctx, parts, exprRoot) - if value.IsValid() { - result = value.Interface() - } - } - - return result, partResolved -} - -// -// Helpers -// - -// isHelperCall returns true if given expression is a helper call -func (v *evalVisitor) isHelperCall(node *ast.Expression) bool { - if helperName := node.HelperName(); helperName != "" { - return v.findHelper(helperName) != zero - } - return false -} - -// findHelper finds given helper -func (v *evalVisitor) findHelper(name string) reflect.Value { - // check template helpers - if h := v.tpl.findHelper(name); h != zero { - return h - } - - // check global helpers - return findHelper(name) -} - -// callFunc calls function with given options -func (v *evalVisitor) callFunc(name string, funcVal reflect.Value, options *Options) reflect.Value { - params := options.Params() - - funcType := funcVal.Type() - - // @todo Is there a better way to do that ? - strType := reflect.TypeOf("") - boolType := reflect.TypeOf(true) - - // check parameters number - addOptions := false - numIn := funcType.NumIn() - - if numIn == len(params)+1 { - lastArgType := funcType.In(numIn - 1) - if reflect.TypeOf(options).AssignableTo(lastArgType) { - addOptions = true - } - } - - if !addOptions && (len(params) != numIn) { - v.errorf("Helper '%s' called with wrong number of arguments, needed %d but got %d", name, numIn, len(params)) - } - - // check and collect arguments - args := make([]reflect.Value, numIn) - for i, param := range params { - arg := reflect.ValueOf(param) - argType := funcType.In(i) - - if !arg.IsValid() { - if canBeNil(argType) { - arg = reflect.Zero(argType) - } else if argType.Kind() == reflect.String { - arg = reflect.ValueOf("") - } else { - // @todo Maybe we can panic on that - return reflect.Zero(strType) - } - } - - if !arg.Type().AssignableTo(argType) { - if strType.AssignableTo(argType) { - // convert parameter to string - arg = reflect.ValueOf(strValue(arg)) - } else if boolType.AssignableTo(argType) { - // convert parameter to bool - val, _ := isTrueValue(arg) - arg = reflect.ValueOf(val) - } else { - v.errorf("Helper %s called with argument %d with type %s but it should be %s", name, i, arg.Type(), argType) - } - } - - args[i] = arg - } - - if addOptions { - args[numIn-1] = reflect.ValueOf(options) - } - - result := funcVal.Call(args) - - return result[0] -} - -// callHelper invoqs helper function for given expression node -func (v *evalVisitor) callHelper(name string, helper reflect.Value, node *ast.Expression) interface{} { - result := v.callFunc(name, helper, v.helperOptions(node)) - if !result.IsValid() { - return nil - } - - // @todo We maybe want to ensure here that helper returned a string or a SafeString - return result.Interface() -} - -// helperOptions computes helper options argument from an expression -func (v *evalVisitor) helperOptions(node *ast.Expression) *Options { - var params []interface{} - var hash map[string]interface{} - - for _, paramNode := range node.Params { - param := paramNode.Accept(v) - params = append(params, param) - } - - if node.Hash != nil { - hash, _ = node.Hash.Accept(v).(map[string]interface{}) - } - - return newOptions(v, params, hash) -} - -// -// Partials -// - -// findPartial finds given partial -func (v *evalVisitor) findPartial(name string) *partial { - // check template partials - if p := v.tpl.findPartial(name); p != nil { - return p - } - - // check global partials - return findPartial(name) -} - -// partialContext computes partial context -func (v *evalVisitor) partialContext(node *ast.PartialStatement) reflect.Value { - if nb := len(node.Params); nb > 1 { - v.errorf("Unsupported number of partial arguments: %d", nb) - } - - if (len(node.Params) > 0) && (node.Hash != nil) { - v.errorf("Passing both context and named parameters to a partial is not allowed") - } - - if len(node.Params) == 1 { - return reflect.ValueOf(node.Params[0].Accept(v)) - } - - if node.Hash != nil { - hash, _ := node.Hash.Accept(v).(map[string]interface{}) - return reflect.ValueOf(hash) - } - - return zero -} - -// evalPartial evaluates a partial -func (v *evalVisitor) evalPartial(p *partial, node *ast.PartialStatement) string { - // get partial template - partialTpl, err := p.template() - if err != nil { - v.errPanic(err) - } - - // push partial context - ctx := v.partialContext(node) - if ctx.IsValid() { - v.pushCtx(ctx) - } - - // evaluate partial template - result, _ := partialTpl.program.Accept(v).(string) - - // ident partial - result = indentLines(result, node.Indent) - - if ctx.IsValid() { - v.popCtx() - } - - return result -} - -// indentLines indents all lines of given string -func indentLines(str string, indent string) string { - if indent == "" { - return str - } - - var indented []string - - lines := strings.Split(str, "\n") - for i, line := range lines { - if (i == (len(lines) - 1)) && (line == "") { - // input string ends with a new line - indented = append(indented, line) - } else { - indented = append(indented, indent+line) - } - } - - return strings.Join(indented, "\n") -} - -// -// Functions -// - -// wasFuncCall returns true if given expression was a function call -func (v *evalVisitor) wasFuncCall(node *ast.Expression) bool { - // check if expression was tagged as a function call - return v.exprFunc[node] -} - -// -// Visitor interface -// - -// Statements - -// VisitProgram implements corresponding Visitor interface method -func (v *evalVisitor) VisitProgram(node *ast.Program) interface{} { - v.at(node) - - buf := new(bytes.Buffer) - - for _, n := range node.Body { - if str := Str(n.Accept(v)); str != "" { - if _, err := buf.Write([]byte(str)); err != nil { - v.errPanic(err) - } - } - } - - return buf.String() -} - -// VisitMustache implements corresponding Visitor interface method -func (v *evalVisitor) VisitMustache(node *ast.MustacheStatement) interface{} { - v.at(node) - - // evaluate expression - expr := node.Expression.Accept(v) - - // check if this is a safe string - isSafe := isSafeString(expr) - - // get string value - str := Str(expr) - if !isSafe && !node.Unescaped { - // escape html - str = Escape(str) - } - - return str -} - -// VisitBlock implements corresponding Visitor interface method -func (v *evalVisitor) VisitBlock(node *ast.BlockStatement) interface{} { - v.at(node) - - v.pushBlock(node) - - var result interface{} - - // evaluate expression - expr := node.Expression.Accept(v) - - if v.isHelperCall(node.Expression) || v.wasFuncCall(node.Expression) { - // it is the responsability of the helper/function to evaluate block - result = expr - } else { - val := reflect.ValueOf(expr) - - truth, _ := isTrueValue(val) - if truth { - if node.Program != nil { - switch val.Kind() { - case reflect.Array, reflect.Slice: - concat := "" - - // Array context - for i := 0; i < val.Len(); i++ { - // Computes new private data frame - frame := v.dataFrame.newIterDataFrame(val.Len(), i, nil) - - // Evaluate program - concat += v.evalProgram(node.Program, val.Index(i).Interface(), frame, i) - } - - result = concat - default: - // NOT array - result = v.evalProgram(node.Program, expr, nil, nil) - } - } - } else if node.Inverse != nil { - result, _ = node.Inverse.Accept(v).(string) - } - } - - v.popBlock() - - return result -} - -// VisitPartial implements corresponding Visitor interface method -func (v *evalVisitor) VisitPartial(node *ast.PartialStatement) interface{} { - v.at(node) - - // partialName: helperName | sexpr - name, ok := ast.HelperNameStr(node.Name) - if !ok { - if subExpr, ok := node.Name.(*ast.SubExpression); ok { - name, _ = subExpr.Accept(v).(string) - } - } - - if name == "" { - v.errorf("Unexpected partial name: %q", node.Name) - } - - partial := v.findPartial(name) - if partial == nil { - v.errorf("Partial not found: %s", name) - } - - return v.evalPartial(partial, node) -} - -// VisitContent implements corresponding Visitor interface method -func (v *evalVisitor) VisitContent(node *ast.ContentStatement) interface{} { - v.at(node) - - // write content as is - return node.Value -} - -// VisitComment implements corresponding Visitor interface method -func (v *evalVisitor) VisitComment(node *ast.CommentStatement) interface{} { - v.at(node) - - // ignore comments - return "" -} - -// Expressions - -// VisitExpression implements corresponding Visitor interface method -func (v *evalVisitor) VisitExpression(node *ast.Expression) interface{} { - v.at(node) - - var result interface{} - done := false - - v.pushExpr(node) - - // helper call - if helperName := node.HelperName(); helperName != "" { - if helper := v.findHelper(helperName); helper != zero { - result = v.callHelper(helperName, helper, node) - done = true - } - } - - if !done { - // literal - if literal, ok := node.LiteralStr(); ok { - if val := v.evalField(v.curCtx(), literal, true); val.IsValid() { - result = val.Interface() - done = true - } - } - } - - if !done { - // field path - if path := node.FieldPath(); path != nil { - // @todo Find a cleaner way ! Don't break the pattern ! - // this is an exception to visitor pattern, because we need to pass the info - // that this path is at root of current expression - if val := v.evalPathExpression(path, true); val != nil { - result = val - } - } - } - - v.popExpr() - - return result -} - -// VisitSubExpression implements corresponding Visitor interface method -func (v *evalVisitor) VisitSubExpression(node *ast.SubExpression) interface{} { - v.at(node) - - return node.Expression.Accept(v) -} - -// VisitPath implements corresponding Visitor interface method -func (v *evalVisitor) VisitPath(node *ast.PathExpression) interface{} { - return v.evalPathExpression(node, false) -} - -// Literals - -// VisitString implements corresponding Visitor interface method -func (v *evalVisitor) VisitString(node *ast.StringLiteral) interface{} { - v.at(node) - - return node.Value -} - -// VisitBoolean implements corresponding Visitor interface method -func (v *evalVisitor) VisitBoolean(node *ast.BooleanLiteral) interface{} { - v.at(node) - - return node.Value -} - -// VisitNumber implements corresponding Visitor interface method -func (v *evalVisitor) VisitNumber(node *ast.NumberLiteral) interface{} { - v.at(node) - - return node.Number() -} - -// Miscellaneous - -// VisitHash implements corresponding Visitor interface method -func (v *evalVisitor) VisitHash(node *ast.Hash) interface{} { - v.at(node) - - result := make(map[string]interface{}) - - for _, pair := range node.Pairs { - if value := pair.Accept(v); value != nil { - result[pair.Key] = value - } - } - - return result -} - -// VisitHashPair implements corresponding Visitor interface method -func (v *evalVisitor) VisitHashPair(node *ast.HashPair) interface{} { - v.at(node) - - return node.Val.Accept(v) -} diff --git a/vendor/github.com/aymerick/raymond/eval_test.go b/vendor/github.com/aymerick/raymond/eval_test.go deleted file mode 100644 index b7bd82e..0000000 --- a/vendor/github.com/aymerick/raymond/eval_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package raymond - -import "testing" - -var evalTests = []Test{ - { - "only content", - "this is content", - nil, nil, nil, nil, - "this is content", - }, - { - "checks path in parent contexts", - "{{#a}}{{one}}{{#b}}{{one}}{{two}}{{one}}{{/b}}{{/a}}", - map[string]interface{}{"a": map[string]int{"one": 1}, "b": map[string]int{"two": 2}}, - nil, nil, nil, - "1121", - }, - { - "block params", - "{{#foo as |bar|}}{{bar}}{{/foo}}{{bar}}", - map[string]string{"foo": "baz", "bar": "bat"}, - nil, nil, nil, - "bazbat", - }, - { - "block params on array", - "{{#foo as |bar i|}}{{i}}.{{bar}} {{/foo}}", - map[string][]string{"foo": {"baz", "bar", "bat"}}, - nil, nil, nil, - "0.baz 1.bar 2.bat ", - }, - { - "nested block params", - "{{#foos as |foo iFoo|}}{{#wats as |wat iWat|}}{{iFoo}}.{{iWat}}.{{foo}}-{{wat}} {{/wats}}{{/foos}}", - map[string][]string{"foos": {"baz", "bar"}, "wats": {"the", "phoque"}}, - nil, nil, nil, - "0.0.baz-the 0.1.baz-phoque 1.0.bar-the 1.1.bar-phoque ", - }, - { - "block params with path reference", - "{{#foo as |bar|}}{{bar.baz}}{{/foo}}", - map[string]map[string]string{"foo": {"baz": "bat"}}, - nil, nil, nil, - "bat", - }, - { - "falsy block evaluation", - "{{#foo}}bar{{/foo}} baz", - map[string]interface{}{"foo": false}, - nil, nil, nil, - " baz", - }, - { - "block helper returns a SafeString", - "{{title}} - {{#bold}}{{body}}{{/bold}}", - map[string]string{ - "title": "My new blog post", - "body": "I have so many things to say!", - }, - nil, - map[string]interface{}{"bold": func(options *Options) SafeString { - return SafeString(`
` + options.Fn() + "
") - }}, - nil, - `My new blog post -
I have so many things to say!
`, - }, - { - "chained blocks", - "{{#if a}}A{{else if b}}B{{else}}C{{/if}}", - map[string]interface{}{"b": false}, - nil, nil, nil, - "C", - }, - - // @todo Test with a "../../path" (depth 2 path) while context is only depth 1 -} - -func TestEval(t *testing.T) { - t.Parallel() - - launchTests(t, evalTests) -} - -var evalErrors = []Test{ - { - "functions with wrong number of arguments", - `{{foo "bar"}}`, - map[string]interface{}{"foo": func(a string, b string) string { return "foo" }}, - nil, nil, nil, - "Helper 'foo' called with wrong number of arguments, needed 2 but got 1", - }, - { - "functions with wrong number of returned values (1)", - "{{foo}}", - map[string]interface{}{"foo": func() {}}, - nil, nil, nil, - "Helper function must return a string or a SafeString", - }, - { - "functions with wrong number of returned values (2)", - "{{foo}}", - map[string]interface{}{"foo": func() (string, bool, string) { return "foo", true, "bar" }}, - nil, nil, nil, - "Helper function must return a string or a SafeString", - }, -} - -func TestEvalErrors(t *testing.T) { - launchErrorTests(t, evalErrors) -} - -func TestEvalStruct(t *testing.T) { - t.Parallel() - - source := `
-

By {{author.FirstName}} {{Author.lastName}}

-
{{Body}}
- -

Comments

- - {{#each comments}} -

By {{Author.FirstName}} {{author.LastName}}

-
{{body}}
- {{/each}} -
` - - expected := `
-

By Jean Valjean

-
Life is difficult
- -

Comments

- -

By Marcel Beliveau

-
LOL!
-
` - - type Person struct { - FirstName string - LastName string - } - - type Comment struct { - Author Person - Body string - } - - type Post struct { - Author Person - Body string - Comments []Comment - } - - ctx := Post{ - Person{"Jean", "Valjean"}, - "Life is difficult", - []Comment{ - Comment{ - Person{"Marcel", "Beliveau"}, - "LOL!", - }, - }, - } - - output := MustRender(source, ctx) - if output != expected { - t.Errorf("Failed to evaluate with struct context") - } -} - -type TestFoo struct { -} - -func (t *TestFoo) Subject() string { - return "foo" -} - -func TestEvalMethod(t *testing.T) { - t.Parallel() - - source := `Subject is {{subject}}! YES I SAID {{Subject}}!` - expected := `Subject is foo! YES I SAID foo!` - - ctx := &TestFoo{} - - output := MustRender(source, ctx) - if output != expected { - t.Errorf("Failed to evaluate struct method: %s", output) - } -} - -type TestBar struct { -} - -func (t *TestBar) Subject() interface{} { - return testBar -} - -func testBar() string { - return "bar" -} - -func TestEvalMethodReturningFunc(t *testing.T) { - t.Parallel() - - source := `Subject is {{subject}}! YES I SAID {{Subject}}!` - expected := `Subject is bar! YES I SAID bar!` - - ctx := &TestBar{} - - output := MustRender(source, ctx) - if output != expected { - t.Errorf("Failed to evaluate struct method: %s", output) - } -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/base_test.go b/vendor/github.com/aymerick/raymond/handlebars/base_test.go deleted file mode 100644 index 254b1a9..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/base_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package handlebars - -import ( - "fmt" - "io/ioutil" - "path" - "strconv" - "testing" - - "github.com/aymerick/raymond" -) - -// cf. https://github.com/aymerick/go-fuzz-tests/raymond -const dumpTpl = false - -var dumpTplNb = 0 - -type Test struct { - name string - input string - data interface{} - privData map[string]interface{} - helpers map[string]interface{} - partials map[string]string - output interface{} -} - -func launchTests(t *testing.T, tests []Test) { - t.Parallel() - - for _, test := range tests { - var err error - var tpl *raymond.Template - - if dumpTpl { - filename := strconv.Itoa(dumpTplNb) - if err := ioutil.WriteFile(path.Join(".", "dump_tpl", filename), []byte(test.input), 0644); err != nil { - panic(err) - } - dumpTplNb++ - } - - // parse template - tpl, err = raymond.Parse(test.input) - if err != nil { - t.Errorf("Test '%s' failed - Failed to parse template\ninput:\n\t'%s'\nerror:\n\t%s", test.name, test.input, err) - } else { - if len(test.helpers) > 0 { - // register helpers - tpl.RegisterHelpers(test.helpers) - } - - if len(test.partials) > 0 { - // register partials - tpl.RegisterPartials(test.partials) - } - - // setup private data frame - var privData *raymond.DataFrame - if test.privData != nil { - privData = raymond.NewDataFrame() - for k, v := range test.privData { - privData.Set(k, v) - } - } - - // render template - output, err := tpl.ExecWith(test.data, privData) - if err != nil { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\nerror:\n\t%s\nAST:\n\t%s", test.name, test.input, raymond.Str(test.data), err, tpl.PrintAST()) - } else { - // check output - var expectedArr []string - expectedArr, ok := test.output.([]string) - if ok { - match := false - for _, expectedStr := range expectedArr { - if expectedStr == output { - match = true - break - } - } - - if !match { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\npartials:\n\t%s\nexpected\n\t%q\ngot\n\t%q\nAST:\n%s", test.name, test.input, raymond.Str(test.data), raymond.Str(test.partials), expectedArr, output, tpl.PrintAST()) - } - } else { - expectedStr, ok := test.output.(string) - if !ok { - panic(fmt.Errorf("Erroneous test output description: %q", test.output)) - } - - if expectedStr != output { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\ndata:\n\t%s\npartials:\n\t%s\nexpected\n\t%q\ngot\n\t%q\nAST:\n%s", test.name, test.input, raymond.Str(test.data), raymond.Str(test.partials), expectedStr, output, tpl.PrintAST()) - } - } - } - } - } -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/basic_test.go b/vendor/github.com/aymerick/raymond/handlebars/basic_test.go deleted file mode 100644 index 6325341..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/basic_test.go +++ /dev/null @@ -1,650 +0,0 @@ -package handlebars - -import ( - "fmt" - "regexp" - "testing" - - "github.com/aymerick/raymond" -) - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/basic.js -// -var basicTests = []Test{ - { - "most basic", - "{{foo}}", - map[string]string{"foo": "foo"}, - nil, nil, nil, - "foo", - }, - { - "escaping (1)", - "\\{{foo}}", - map[string]string{"foo": "food"}, - nil, nil, nil, - "{{foo}}", - }, - { - "escaping (2)", - "content \\{{foo}}", - map[string]string{}, - nil, nil, nil, - "content {{foo}}", - }, - { - "escaping (3)", - "\\\\{{foo}}", - map[string]string{"foo": "food"}, - nil, nil, nil, - "\\food", - }, - { - "escaping (4)", - "content \\\\{{foo}}", - map[string]string{"foo": "food"}, - nil, nil, nil, - "content \\food", - }, - { - "escaping (5)", - "\\\\ {{foo}}", - map[string]string{"foo": "food"}, - nil, nil, nil, - "\\\\ food", - }, - { - "compiling with a basic context", - "Goodbye\n{{cruel}}\n{{world}}!", - map[string]string{"cruel": "cruel", "world": "world"}, - nil, nil, nil, - "Goodbye\ncruel\nworld!", - }, - { - "compiling with an undefined context (1)", - "Goodbye\n{{cruel}}\n{{world.bar}}!", - nil, nil, nil, nil, - "Goodbye\n\n!", - }, - { - "compiling with an undefined context (2)", - "{{#unless foo}}Goodbye{{../test}}{{test2}}{{/unless}}", - nil, nil, nil, nil, - "Goodbye", - }, - { - "comments (1)", - "{{! Goodbye}}Goodbye\n{{cruel}}\n{{world}}!", - map[string]string{"cruel": "cruel", "world": "world"}, - nil, nil, nil, - "Goodbye\ncruel\nworld!", - }, - { - "comments (2)", - " {{~! comment ~}} blah", - nil, nil, nil, nil, - "blah", - }, - { - "comments (3)", - " {{~!-- long-comment --~}} blah", - nil, nil, nil, nil, - "blah", - }, - { - "comments (4)", - " {{! comment ~}} blah", - nil, nil, nil, nil, - " blah", - }, - { - "comments (5)", - " {{!-- long-comment --~}} blah", - nil, nil, nil, nil, - " blah", - }, - { - "comments (6)", - " {{~! comment}} blah", - nil, nil, nil, nil, - " blah", - }, - { - "comments (7)", - " {{~!-- long-comment --}} blah", - nil, nil, nil, nil, - " blah", - }, - { - "boolean (1)", - "{{#goodbye}}GOODBYE {{/goodbye}}cruel {{world}}!", - map[string]interface{}{"goodbye": true, "world": "world"}, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "boolean (2)", - "{{#goodbye}}GOODBYE {{/goodbye}}cruel {{world}}!", - map[string]interface{}{"goodbye": false, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "zeros (1)", - "num1: {{num1}}, num2: {{num2}}", - map[string]interface{}{"num1": 42, "num2": 0}, - nil, nil, nil, - "num1: 42, num2: 0", - }, - { - "zeros (2)", - "num: {{.}}", - 0, - nil, nil, nil, - "num: 0", - }, - { - "zeros (3)", - "num: {{num1/num2}}", - map[string]map[string]interface{}{"num1": {"num2": 0}}, - nil, nil, nil, - "num: 0", - }, - { - "false (1)", - "val1: {{val1}}, val2: {{val2}}", - map[string]interface{}{"val1": false, "val2": false}, - nil, nil, nil, - "val1: false, val2: false", - }, - { - "false (2)", - "val: {{.}}", - false, - nil, nil, nil, - "val: false", - }, - { - "false (3)", - "val: {{val1/val2}}", - map[string]map[string]interface{}{"val1": {"val2": false}}, - nil, nil, nil, - "val: false", - }, - { - "false (4)", - "val1: {{{val1}}}, val2: {{{val2}}}", - map[string]interface{}{"val1": false, "val2": false}, - nil, nil, nil, - "val1: false, val2: false", - }, - { - "false (5)", - "val: {{{val1/val2}}}", - map[string]map[string]interface{}{"val1": {"val2": false}}, - nil, nil, nil, - "val: false", - }, - { - "newlines (1)", - "Alan's\nTest", - nil, nil, nil, nil, - "Alan's\nTest", - }, - { - "newlines (2)", - "Alan's\rTest", - nil, nil, nil, nil, - "Alan's\rTest", - }, - { - "escaping text (1)", - "Awesome's", - map[string]string{}, - nil, nil, nil, - "Awesome's", - }, - { - "escaping text (2)", - "Awesome\\", - map[string]string{}, - nil, nil, nil, - "Awesome\\", - }, - { - "escaping text (3)", - "Awesome\\\\ foo", - map[string]string{}, - nil, nil, nil, - "Awesome\\\\ foo", - }, - { - "escaping text (4)", - "Awesome {{foo}}", - map[string]string{"foo": "\\"}, - nil, nil, nil, - "Awesome \\", - }, - { - "escaping text (5)", - " ' ' ", - map[string]string{}, - nil, nil, nil, - " ' ' ", - }, - { - "escaping expressions (6)", - "{{{awesome}}}", - map[string]string{"awesome": "&'\\<>"}, - nil, nil, nil, - "&'\\<>", - }, - { - "escaping expressions (7)", - "{{&awesome}}", - map[string]string{"awesome": "&'\\<>"}, - nil, nil, nil, - "&'\\<>", - }, - { - "escaping expressions (8)", - "{{awesome}}", - map[string]string{"awesome": "&\"'`\\<>"}, - nil, nil, nil, - "&"'`\\<>", - }, - { - "escaping expressions (9)", - "{{awesome}}", - map[string]string{"awesome": "Escaped, looks like: <b>"}, - nil, nil, nil, - "Escaped, <b> looks like: &lt;b&gt;", - }, - { - "functions returning safestrings shouldn't be escaped", - "{{awesome}}", - map[string]interface{}{"awesome": func() raymond.SafeString { return raymond.SafeString("&'\\<>") }}, - nil, nil, nil, - "&'\\<>", - }, - { - "functions (1)", - "{{awesome}}", - map[string]interface{}{"awesome": func() string { return "Awesome" }}, - nil, nil, nil, - "Awesome", - }, - { - "functions (2)", - "{{awesome}}", - map[string]interface{}{"awesome": func(options *raymond.Options) string { - return options.ValueStr("more") - }, "more": "More awesome"}, - nil, nil, nil, - "More awesome", - }, - { - "functions with context argument", - "{{awesome frank}}", - map[string]interface{}{"awesome": func(context string) string { - return context - }, "frank": "Frank"}, - nil, nil, nil, - "Frank", - }, - { - "pathed functions with context argument", - "{{bar.awesome frank}}", - map[string]interface{}{"bar": map[string]interface{}{"awesome": func(context string) string { - return context - }}, "frank": "Frank"}, - nil, nil, nil, - "Frank", - }, - { - "depthed functions with context argument", - "{{#with frank}}{{../awesome .}}{{/with}}", - map[string]interface{}{"awesome": func(context string) string { - return context - }, "frank": "Frank"}, - nil, nil, nil, - "Frank", - }, - { - "block functions with context argument", - "{{#awesome 1}}inner {{.}}{{/awesome}}", - map[string]interface{}{"awesome": func(context interface{}, options *raymond.Options) string { - return options.FnWith(context) - }}, - nil, nil, nil, - "inner 1", - }, - { - "depthed block functions with context argument", - "{{#with value}}{{#../awesome 1}}inner {{.}}{{/../awesome}}{{/with}}", - map[string]interface{}{ - "awesome": func(context interface{}, options *raymond.Options) string { - return options.FnWith(context) - }, - "value": true, - }, - nil, nil, nil, - "inner 1", - }, - { - "block functions without context argument", - "{{#awesome}}inner{{/awesome}}", - map[string]interface{}{ - "awesome": func(options *raymond.Options) string { - return options.Fn() - }, - }, - nil, nil, nil, - "inner", - }, - // // @note I don't even understand why this test passes with the JS implementation... it should be - // // the responsability of the function to evaluate the block - // { - // "pathed block functions without context argument", - // "{{#foo.awesome}}inner{{/foo.awesome}}", - // map[string]map[string]interface{}{ - // "foo": { - // "awesome": func(options *raymond.Options) interface{} { - // return options.Ctx() - // }, - // }, - // }, - // nil, nil, nil, - // "inner", - // }, - // // @note I don't even understand why this test passes with the JS implementation... it should be - // // the responsability of the function to evaluate the block - // { - // "depthed block functions without context argument", - // "{{#with value}}{{#../awesome}}inner{{/../awesome}}{{/with}}", - // map[string]interface{}{ - // "value": true, - // "awesome": func(options *raymond.Options) interface{} { - // return options.Ctx() - // }, - // }, - // nil, nil, nil, - // "inner", - // }, - { - "paths with hyphens (1)", - "{{foo-bar}}", - map[string]string{"foo-bar": "baz"}, - nil, nil, nil, - "baz", - }, - { - "paths with hyphens (2)", - "{{foo.foo-bar}}", - map[string]map[string]string{"foo": {"foo-bar": "baz"}}, - nil, nil, nil, - "baz", - }, - { - "paths with hyphens (3)", - "{{foo/foo-bar}}", - map[string]map[string]string{"foo": {"foo-bar": "baz"}}, - nil, nil, nil, - "baz", - }, - { - "nested paths", - "Goodbye {{alan/expression}} world!", - map[string]map[string]string{"alan": {"expression": "beautiful"}}, - nil, nil, nil, - "Goodbye beautiful world!", - }, - { - "nested paths with empty string value", - "Goodbye {{alan/expression}} world!", - map[string]map[string]string{"alan": {"expression": ""}}, - nil, nil, nil, - "Goodbye world!", - }, - { - "literal paths (1)", - "Goodbye {{[@alan]/expression}} world!", - map[string]map[string]string{"@alan": {"expression": "beautiful"}}, - nil, nil, nil, - "Goodbye beautiful world!", - }, - { - "literal paths (2)", - "Goodbye {{[foo bar]/expression}} world!", - map[string]map[string]string{"foo bar": {"expression": "beautiful"}}, - nil, nil, nil, - "Goodbye beautiful world!", - }, - { - "literal references", - "Goodbye {{[foo bar]}} world!", - map[string]string{"foo bar": "beautiful"}, - nil, nil, nil, - "Goodbye beautiful world!", - }, - // @note MMm ok, well... no... I don't see the purpose of that test - { - "that current context path ({{.}}) doesn't hit helpers", - "test: {{.}}", - nil, nil, - map[string]interface{}{"helper": func() string { - panic("fail") - }}, - nil, - "test: ", - }, - { - "complex but empty paths (1)", - "{{person/name}}", - map[string]map[string]interface{}{"person": {"name": nil}}, - nil, nil, nil, - "", - }, - { - "complex but empty paths (2)", - "{{person/name}}", - map[string]map[string]string{"person": {}}, - nil, nil, nil, - "", - }, - { - "this keyword in paths (1)", - "{{#goodbyes}}{{this}}{{/goodbyes}}", - map[string]interface{}{"goodbyes": []string{"goodbye", "Goodbye", "GOODBYE"}}, - nil, nil, nil, - "goodbyeGoodbyeGOODBYE", - }, - { - "this keyword in paths (2)", - "{{#hellos}}{{this/text}}{{/hellos}}", - map[string]interface{}{"hellos": []interface{}{ - map[string]string{"text": "hello"}, - map[string]string{"text": "Hello"}, - map[string]string{"text": "HELLO"}, - }}, - nil, nil, nil, - "helloHelloHELLO", - }, - { - "this keyword nested inside path' (1)", - "{{[this]}}", - map[string]string{"this": "bar"}, - nil, nil, nil, - "bar", - }, - { - "this keyword nested inside path' (2)", - "{{text/[this]}}", - map[string]map[string]string{"text": {"this": "bar"}}, - nil, nil, nil, - "bar", - }, - { - "this keyword in helpers (1)", - "{{#goodbyes}}{{foo this}}{{/goodbyes}}", - map[string]interface{}{"goodbyes": []string{"goodbye", "Goodbye", "GOODBYE"}}, - nil, - map[string]interface{}{"foo": barSuffixHelper}, - nil, - "bar goodbyebar Goodbyebar GOODBYE", - }, - { - "this keyword in helpers (2)", - "{{#hellos}}{{foo this/text}}{{/hellos}}", - map[string]interface{}{"hellos": []map[string]string{{"text": "hello"}, {"text": "Hello"}, {"text": "HELLO"}}}, - nil, - map[string]interface{}{"foo": barSuffixHelper}, - nil, - "bar hellobar Hellobar HELLO", - }, - { - "this keyword nested inside helpers param (1)", - "{{foo [this]}}", - map[string]interface{}{"this": "bar"}, - nil, - map[string]interface{}{"foo": echoHelper}, - nil, - "bar", - }, - { - "this keyword nested inside helpers param (2)", - "{{foo text/[this]}}", - map[string]map[string]string{"text": {"this": "bar"}}, - nil, - map[string]interface{}{"foo": echoHelper}, - nil, - "bar", - }, - { - "pass string literals (1)", - `{{"foo"}}`, - map[string]string{}, - nil, nil, nil, - "", - }, - { - "pass string literals (2)", - `{{"foo"}}`, - map[string]string{"foo": "bar"}, - nil, nil, nil, - "bar", - }, - { - "pass string literals (3)", - `{{#"foo"}}{{.}}{{/"foo"}}`, - map[string]interface{}{"foo": []string{"bar", "baz"}}, - nil, nil, nil, - "barbaz", - }, - { - "pass number literals (1)", - "{{12}}", - map[string]string{}, - nil, nil, nil, - "", - }, - { - "pass number literals (2)", - "{{12}}", - map[string]string{"12": "bar"}, - nil, nil, nil, - "bar", - }, - { - "pass number literals (3)", - "{{12.34}}", - map[string]string{}, - nil, nil, nil, - "", - }, - { - "pass number literals (4)", - "{{12.34}}", - map[string]string{"12.34": "bar"}, - nil, nil, nil, - "bar", - }, - { - "pass number literals (5)", - "{{12.34 1}}", - map[string]interface{}{"12.34": func(context string) string { - return "bar" + context - }}, - nil, nil, nil, - "bar1", - }, - { - "pass boolean literals (1)", - "{{true}}", - map[string]string{}, - nil, nil, nil, - "", - }, - { - "pass boolean literals (2)", - "{{true}}", - map[string]string{"": "foo"}, - nil, nil, nil, - "", - }, - { - "pass boolean literals (3)", - "{{false}}", - map[string]string{"false": "foo"}, - nil, nil, nil, - "foo", - }, - { - "should handle literals in subexpression", - "{{foo (false)}}", - map[string]interface{}{"false": func() string { return "bar" }}, - nil, - map[string]interface{}{"foo": func(context string) string { - return context - }}, - nil, - "bar", - }, -} - -func TestBasic(t *testing.T) { - launchTests(t, basicTests) -} - -func TestBasicErrors(t *testing.T) { - t.Parallel() - - var err error - - inputs := []string{ - // this keyword nested inside path - "{{#hellos}}{{text/this/foo}}{{/hellos}}", - // this keyword nested inside helpers param - "{{#hellos}}{{foo text/this/foo}}{{/hellos}}", - } - - expectedError := regexp.QuoteMeta("Invalid path: text/this") - - for _, input := range inputs { - _, err = raymond.Parse(input) - if err == nil { - t.Errorf("Test failed - Error expected") - } - - match, errMatch := regexp.MatchString(expectedError, fmt.Sprint(err)) - if errMatch != nil { - panic("Failed to match regexp") - } - - if !match { - t.Errorf("Test failed - Expected error:\n\t%s\n\nGot:\n\t%s", expectedError, err) - } - } -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/blocks_test.go b/vendor/github.com/aymerick/raymond/handlebars/blocks_test.go deleted file mode 100644 index de435ba..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/blocks_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package handlebars - -import "testing" - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/blocks.js -// -var blocksTests = []Test{ - { - "array (1) - Arrays iterate over the contents when not empty", - "{{#goodbyes}}{{text}}! {{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "goodbye! Goodbye! GOODBYE! cruel world!", - }, - { - "array (2) - Arrays ignore the contents when empty", - "{{#goodbyes}}{{text}}! {{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "array without data", - "{{#goodbyes}}{{text}}{{/goodbyes}} {{#goodbyes}}{{text}}{{/goodbyes}}", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "goodbyeGoodbyeGOODBYE goodbyeGoodbyeGOODBYE", - }, - { - "array with @index - The @index variable is used", - "{{#goodbyes}}{{@index}}. {{text}}! {{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!", - }, - { - "empty block (1) - Arrays iterate over the contents when not empty", - "{{#goodbyes}}{{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "empty block (1) - Arrays ignore the contents when empty", - "{{#goodbyes}}{{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "block with complex lookup - Templates can access variables in contexts up the stack with relative path syntax", - "{{#goodbyes}}{{text}} cruel {{../name}}! {{/goodbyes}}", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "name": "Alan"}, - nil, nil, nil, - "goodbye cruel Alan! Goodbye cruel Alan! GOODBYE cruel Alan! ", - }, - { - "multiple blocks with complex lookup", - "{{#goodbyes}}{{../name}}{{../name}}{{/goodbyes}}", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "name": "Alan"}, - nil, nil, nil, - "AlanAlanAlanAlanAlanAlan", - }, - - // @todo "{{#goodbyes}}{{text}} cruel {{foo/../name}}! {{/goodbyes}}" should throw error - - { - "block with deep nested complex lookup", - "{{#outer}}Goodbye {{#inner}}cruel {{../sibling}} {{../../omg}}{{/inner}}{{/outer}}", - map[string]interface{}{"omg": "OMG!", "outer": []map[string]interface{}{{"sibling": "sad", "inner": []map[string]string{{"text": "goodbye"}}}}}, - nil, nil, nil, - "Goodbye cruel sad OMG!", - }, - { - "inverted sections with unset value - Inverted section rendered when value isn't set.", - "{{#goodbyes}}{{this}}{{/goodbyes}}{{^goodbyes}}Right On!{{/goodbyes}}", - map[string]interface{}{}, - nil, nil, nil, - "Right On!", - }, - { - "inverted sections with false value - Inverted section rendered when value is false.", - "{{#goodbyes}}{{this}}{{/goodbyes}}{{^goodbyes}}Right On!{{/goodbyes}}", - map[string]interface{}{"goodbyes": false}, - nil, nil, nil, - "Right On!", - }, - { - "inverted section with empty set - Inverted section rendered when value is empty set.", - "{{#goodbyes}}{{this}}{{/goodbyes}}{{^goodbyes}}Right On!{{/goodbyes}}", - map[string]interface{}{"goodbyes": []interface{}{}}, - nil, nil, nil, - "Right On!", - }, - { - "block inverted sections", - "{{#people}}{{name}}{{^}}{{none}}{{/people}}", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people", - }, - { - "chained inverted sections (1)", - "{{#people}}{{name}}{{else if none}}{{none}}{{/people}}", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people", - }, - { - "chained inverted sections (2)", - "{{#people}}{{name}}{{else if nothere}}fail{{else unless nothere}}{{none}}{{/people}}", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people", - }, - { - "chained inverted sections (3)", - "{{#people}}{{name}}{{else if none}}{{none}}{{else}}fail{{/people}}", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people", - }, - - // @todo "{{#people}}{{name}}{{else if none}}{{none}}{{/if}}" should throw error - - { - "block inverted sections with empty arrays", - "{{#people}}{{name}}{{^}}{{none}}{{/people}}", - map[string]interface{}{"none": "No people", "people": map[string]interface{}{}}, - nil, nil, nil, - "No people", - }, - { - "block standalone else sections (1)", - "{{#people}}\n{{name}}\n{{^}}\n{{none}}\n{{/people}}\n", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people\n", - }, - { - "block standalone else sections (2)", - "{{#none}}\n{{.}}\n{{^}}\n{{none}}\n{{/none}}\n", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people\n", - }, - { - "block standalone else sections (3)", - "{{#people}}\n{{name}}\n{{^}}\n{{none}}\n{{/people}}\n", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people\n", - }, - { - "block standalone chained else sections (1)", - "{{#people}}\n{{name}}\n{{else if none}}\n{{none}}\n{{/people}}\n", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people\n", - }, - { - "block standalone chained else sections (2)", - "{{#people}}\n{{name}}\n{{else if none}}\n{{none}}\n{{^}}\n{{/people}}\n", - map[string]interface{}{"none": "No people"}, - nil, nil, nil, - "No people\n", - }, - { - "should handle nesting", - "{{#data}}\n{{#if true}}\n{{.}}\n{{/if}}\n{{/data}}\nOK.", - map[string]interface{}{"data": []int{1, 3, 5}}, - nil, nil, nil, - "1\n3\n5\nOK.", - }, - // // @todo compat mode - // { - // "block with deep recursive lookup lookup", - // "{{#outer}}Goodbye {{#inner}}cruel {{omg}}{{/inner}}{{/outer}}", - // map[string]interface{}{"omg": "OMG!", "outer": []map[string]interface{}{{"inner": []map[string]string{{"text": "goodbye"}}}}}, - // nil, - // nil, - // nil, - // "Goodbye cruel OMG!", - // }, - // // @todo compat mode - // { - // "block with deep recursive pathed lookup", - // "{{#outer}}Goodbye {{#inner}}cruel {{omg.yes}}{{/inner}}{{/outer}}", - // map[string]interface{}{"omg": map[string]string{"yes": "OMG!"}, "outer": []map[string]interface{}{{"inner": []map[string]string{{"yes": "no", "text": "goodbye"}}}}}, - // nil, - // nil, - // nil, - // "Goodbye cruel OMG!", - // }, - { - "block with missed recursive lookup", - "{{#outer}}Goodbye {{#inner}}cruel {{omg.yes}}{{/inner}}{{/outer}}", - map[string]interface{}{"omg": map[string]string{"no": "OMG!"}, "outer": []map[string]interface{}{{"inner": []map[string]string{{"yes": "no", "text": "goodbye"}}}}}, - nil, nil, nil, - "Goodbye cruel ", - }, -} - -func TestBlocks(t *testing.T) { - launchTests(t, blocksTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/builtins_test.go b/vendor/github.com/aymerick/raymond/handlebars/builtins_test.go deleted file mode 100644 index 1f986e4..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/builtins_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package handlebars - -import "testing" - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/builtin.js -// -var builtinsTests = []Test{ - { - "#if - if with boolean argument shows the contents when true", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": true, "world": "world"}, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with string argument shows the contents", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": "dummy", "world": "world"}, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with boolean argument does not show the contents when false", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": false, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#if - if with undefined does not show the contents", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#if - if with non-empty array shows the contents", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": []string{"foo"}, "world": "world"}, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with empty array does not show the contents", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": []string{}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#if - if with zero does not show the contents", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": 0, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#if - if with zero and includeZero option shows the contents", - "{{#if goodbye includeZero=true}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{"goodbye": 0, "world": "world"}, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with function shows the contents when function returns true", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{ - "goodbye": func() bool { return true }, - "world": "world", - }, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with function shows the contents when function returns string", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{ - "goodbye": func() string { return "world" }, - "world": "world", - }, - nil, nil, nil, - "GOODBYE cruel world!", - }, - { - "#if - if with function does not show the contents when returns false", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{ - "goodbye": func() bool { return false }, - "world": "world", - }, - nil, nil, nil, - "cruel world!", - }, - { - "#if - if with function does not show the contents when returns undefined", - "{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!", - map[string]interface{}{ - "goodbye": func() interface{} { return nil }, - "world": "world", - }, - nil, nil, nil, - "cruel world!", - }, - { - "#with", - "{{#with person}}{{first}} {{last}}{{/with}}", - map[string]interface{}{"person": map[string]string{"first": "Alan", "last": "Johnson"}}, - nil, nil, nil, - "Alan Johnson", - }, - { - "#with - with with function argument", - "{{#with person}}{{first}} {{last}}{{/with}}", - map[string]interface{}{ - "person": func() map[string]string { return map[string]string{"first": "Alan", "last": "Johnson"} }, - }, nil, nil, nil, - "Alan Johnson", - }, - { - "#with - with with else", - "{{#with person}}Person is present{{else}}Person is not present{{/with}}", - map[string]interface{}{}, - nil, nil, nil, - "Person is not present", - }, - - { - "#each - each with array argument iterates over the contents when not empty", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "goodbye! Goodbye! GOODBYE! cruel world!", - }, - { - "#each - each with array argument ignores the contents when empty", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#each - each without data (1)", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "goodbye! Goodbye! GOODBYE! cruel world!", - }, - { - "#each - each without data (2)", - "{{#each .}}{{.}}{{/each}}", - map[string]interface{}{"goodbyes": "cruel", "world": "world"}, - nil, nil, nil, - // note: a go hash is not ordered, so result may vary, this behaviour differs from the JS implementation - []string{"cruelworld", "worldcruel"}, - }, - { - "#each - each without context", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - nil, nil, nil, nil, - "cruel !", - }, - - // NOTE: we test with a map instead of an object - { - "#each - each with an object and @key (map)", - "{{#each goodbyes}}{{@key}}. {{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": map[interface{}]map[string]string{"#1": {"text": "goodbye"}, 2: {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - []string{"<b>#1</b>. goodbye! 2. GOODBYE! cruel world!", "2. GOODBYE! <b>#1</b>. goodbye! cruel world!"}, - }, - // NOTE: An additional test with a struct, but without an html stuff for the key, because it is impossible - { - "#each - each with an object and @key (struct)", - "{{#each goodbyes}}{{@key}}. {{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{ - "goodbyes": struct { - Foo map[string]string - Bar map[string]int - }{map[string]string{"text": "baz"}, map[string]int{"text": 10}}, - "world": "world", - }, - nil, nil, nil, - []string{"Foo. baz! Bar. 10! cruel world!", "Bar. 10! Foo. baz! cruel world!"}, - }, - { - "#each - each with @index", - "{{#each goodbyes}}{{@index}}. {{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "0. goodbye! 1. Goodbye! 2. GOODBYE! cruel world!", - }, - { - "#each - each with nested @index", - "{{#each goodbyes}}{{@index}}. {{text}}! {{#each ../goodbyes}}{{@index}} {{/each}}After {{@index}} {{/each}}{{@index}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "0. goodbye! 0 1 2 After 0 1. Goodbye! 0 1 2 After 1 2. GOODBYE! 0 1 2 After 2 cruel world!", - }, - { - "#each - each with block params", - "{{#each goodbyes as |value index|}}{{index}}. {{value.text}}! {{#each ../goodbyes as |childValue childIndex|}} {{index}} {{childIndex}}{{/each}} After {{index}} {{/each}}{{index}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}}, "world": "world"}, - nil, nil, nil, - "0. goodbye! 0 0 0 1 After 0 1. Goodbye! 1 0 1 1 After 1 cruel world!", - }, - // @note: That test differs from JS impl because maps and structs are not ordered in go - { - "#each - each object with @index", - "{{#each goodbyes}}{{@index}}. {{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": map[string]map[string]string{"a": {"text": "goodbye"}, "b": {"text": "Goodbye"}}, "world": "world"}, - nil, nil, nil, - []string{"0. goodbye! 1. Goodbye! cruel world!", "0. Goodbye! 1. goodbye! cruel world!"}, - }, - { - "#each - each with nested @first", - "{{#each goodbyes}}({{#if @first}}{{text}}! {{/if}}{{#each ../goodbyes}}{{#if @first}}{{text}}!{{/if}}{{/each}}{{#if @first}} {{text}}!{{/if}}) {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "(goodbye! goodbye! goodbye!) (goodbye!) (goodbye!) cruel world!", - }, - // @note: That test differs from JS impl because maps and structs are not ordered in go - { - "#each - each object with @first", - "{{#each goodbyes}}{{#if @first}}{{text}}! {{/if}}{{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": map[string]map[string]string{"foo": {"text": "goodbye"}, "bar": {"text": "Goodbye"}}, "world": "world"}, - nil, nil, nil, - []string{"goodbye! cruel world!", "Goodbye! cruel world!"}, - }, - { - "#each - each with @last", - "{{#each goodbyes}}{{#if @last}}{{text}}! {{/if}}{{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "GOODBYE! cruel world!", - }, - // @note: That test differs from JS impl because maps and structs are not ordered in go - { - "#each - each object with @last", - "{{#each goodbyes}}{{#if @last}}{{text}}! {{/if}}{{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": map[string]map[string]string{"foo": {"text": "goodbye"}, "bar": {"text": "Goodbye"}}, "world": "world"}, - nil, nil, nil, - []string{"goodbye! cruel world!", "Goodbye! cruel world!"}, - }, - { - "#each - each with nested @last", - "{{#each goodbyes}}({{#if @last}}{{text}}! {{/if}}{{#each ../goodbyes}}{{#if @last}}{{text}}!{{/if}}{{/each}}{{#if @last}} {{text}}!{{/if}}) {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}}, "world": "world"}, - nil, nil, nil, - "(GOODBYE!) (GOODBYE!) (GOODBYE! GOODBYE! GOODBYE!) cruel world!", - }, - - { - "#each - each with function argument (1)", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": func() []map[string]string { - return []map[string]string{{"text": "goodbye"}, {"text": "Goodbye"}, {"text": "GOODBYE"}} - }, "world": "world"}, - nil, nil, nil, - "goodbye! Goodbye! GOODBYE! cruel world!", - }, - { - "#each - each with function argument (2)", - "{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!", - map[string]interface{}{"goodbyes": []map[string]string{}, "world": "world"}, - nil, nil, nil, - "cruel world!", - }, - { - "#each - data passed to helpers", - "{{#each letters}}{{this}}{{detectDataInsideEach}}{{/each}}", - map[string][]string{"letters": {"a", "b", "c"}}, - map[string]interface{}{"exclaim": "!"}, - map[string]interface{}{"detectDataInsideEach": detectDataHelper}, - nil, - "a!b!c!", - }, - - // @todo "each on implicit context" should throw error - - // SKIP: #log - "should call logger at default level" - // SKIP: #log - "should call logger at data level" - // SKIP: #log - "should output to info" - // SKIP: #log - "should log at data level" - // SKIP: #log - "should handle missing logger" - - // @note Test added - // @todo Check log output - { - "#log", - "{{log blah}}", - map[string]string{"blah": "whee"}, - nil, nil, nil, - "", - }, - - // @note Test added - { - "#lookup - should lookup array element", - "{{#each goodbyes}}{{lookup ../data @index}}{{/each}}", - map[string]interface{}{"goodbyes": []int{0, 1}, "data": []string{"foo", "bar"}}, - nil, nil, nil, - "foobar", - }, - { - "#lookup - should lookup map element", - "{{#each goodbyes}}{{lookup ../data .}}{{/each}}", - map[string]interface{}{"goodbyes": []string{"foo", "bar"}, "data": map[string]string{"foo": "baz", "bar": "bat"}}, - nil, nil, nil, - "bazbat", - }, - { - "#lookup - should lookup struct field", - "{{#each goodbyes}}{{lookup ../data .}}{{/each}}", - map[string]interface{}{"goodbyes": []string{"Foo", "Bar"}, "data": struct { - Foo string - Bar string - }{"baz", "bat"}}, - nil, nil, nil, - "bazbat", - }, - { - "#lookup - should lookup arbitrary content", - "{{#each goodbyes}}{{lookup ../data .}}{{/each}}", - map[string]interface{}{"goodbyes": []int{0, 1}, "data": []string{"foo", "bar"}}, - nil, nil, nil, - "foobar", - }, - { - "#lookup - should not fail on undefined value", - "{{#each goodbyes}}{{lookup ../bar .}}{{/each}}", - map[string]interface{}{"goodbyes": []int{0, 1}, "data": []string{"foo", "bar"}}, - nil, nil, nil, - "", - }, -} - -func TestBuiltins(t *testing.T) { - launchTests(t, builtinsTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/data_test.go b/vendor/github.com/aymerick/raymond/handlebars/data_test.go deleted file mode 100644 index fb80020..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/data_test.go +++ /dev/null @@ -1,300 +0,0 @@ -package handlebars - -import ( - "testing" - - "github.com/aymerick/raymond" -) - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/data.js -// -var dataTests = []Test{ - { - "passing in data to a compiled function that expects data - works with helpers", - "{{hello}}", - map[string]string{"noun": "cat"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{"hello": func(options *raymond.Options) string { - return options.DataStr("adjective") + " " + options.ValueStr("noun") - }}, - nil, - "happy cat", - }, - { - "data can be looked up via @foo", - "{{@hello}}", - nil, - map[string]interface{}{"hello": "hello"}, - nil, nil, - "hello", - }, - { - "deep @foo triggers automatic top-level data", - `{{#let world="world"}}{{#if foo}}{{#if foo}}Hello {{@world}}{{/if}}{{/if}}{{/let}}`, - map[string]bool{"foo": true}, - map[string]interface{}{"hello": "hello"}, - map[string]interface{}{"let": func(options *raymond.Options) string { - frame := options.NewDataFrame() - - for k, v := range options.Hash() { - frame.Set(k, v) - } - - return options.FnData(frame) - }}, - nil, - "Hello world", - }, - { - "parameter data can be looked up via @foo", - `{{hello @world}}`, - nil, - map[string]interface{}{"world": "world"}, - map[string]interface{}{"hello": func(context string) string { - return "Hello " + context - }}, - nil, - "Hello world", - }, - { - "hash values can be looked up via @foo", - `{{hello noun=@world}}`, - nil, - map[string]interface{}{"world": "world"}, - map[string]interface{}{"hello": func(options *raymond.Options) string { - return "Hello " + options.HashStr("noun") - }}, - nil, - "Hello world", - }, - { - "nested parameter data can be looked up via @foo.bar", - `{{hello @world.bar}}`, - nil, - map[string]interface{}{"world": map[string]string{"bar": "world"}}, - map[string]interface{}{"hello": func(context string) string { - return "Hello " + context - }}, - nil, - "Hello world", - }, - { - "nested parameter data does not fail with @world.bar", - `{{hello @world.bar}}`, - nil, - map[string]interface{}{"foo": map[string]string{"bar": "world"}}, - map[string]interface{}{"hello": func(context string) string { - return "Hello " + context - }}, - nil, - // @todo Test differs with JS implementation: we don't output `undefined` - "Hello ", - }, - - // @todo "parameter data throws when using complex scope references", - - { - "data can be functions", - `{{@hello}}`, - nil, - map[string]interface{}{"hello": func() string { return "hello" }}, - nil, nil, - "hello", - }, - { - "data can be functions with params", - `{{@hello "hello"}}`, - nil, - map[string]interface{}{"hello": func(context string) string { return context }}, - nil, nil, - "hello", - }, - - { - "data is inherited downstream", - `{{#let foo=1 bar=2}}{{#let foo=bar.baz}}{{@bar}}{{@foo}}{{/let}}{{@foo}}{{/let}}`, - map[string]map[string]string{"bar": {"baz": "hello world"}}, - nil, - map[string]interface{}{"let": func(options *raymond.Options) string { - frame := options.NewDataFrame() - - for k, v := range options.Hash() { - frame.Set(k, v) - } - - return options.FnData(frame) - }}, - nil, - "2hello world1", - }, - { - "passing in data to a compiled function that expects data - works with helpers in partials", - `{{>myPartial}}`, - map[string]string{"noun": "cat"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{"hello": func(options *raymond.Options) string { - return options.DataStr("adjective") + " " + options.ValueStr("noun") - }}, - map[string]string{ - "myPartial": "{{hello}}", - }, - "happy cat", - }, - { - "passing in data to a compiled function that expects data - works with helpers and parameters", - `{{hello world}}`, - map[string]interface{}{"exclaim": true, "world": "world"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{"hello": func(context string, options *raymond.Options) string { - str := "error" - if b, ok := options.Value("exclaim").(bool); ok { - if b { - str = "!" - } else { - str = "" - } - } - - return options.DataStr("adjective") + " " + context + str - }}, - nil, - "happy world!", - }, - { - "passing in data to a compiled function that expects data - works with block helpers", - `{{#hello}}{{world}}{{/hello}}`, - map[string]bool{"exclaim": true}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{ - "hello": func(options *raymond.Options) string { - return options.Fn() - }, - "world": func(options *raymond.Options) string { - str := "error" - if b, ok := options.Value("exclaim").(bool); ok { - if b { - str = "!" - } else { - str = "" - } - } - - return options.DataStr("adjective") + " world" + str - }, - }, - nil, - "happy world!", - }, - { - "passing in data to a compiled function that expects data - works with block helpers that use ..", - `{{#hello}}{{world ../zomg}}{{/hello}}`, - map[string]interface{}{"exclaim": true, "zomg": "world"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{ - "hello": func(options *raymond.Options) string { - return options.FnWith(map[string]string{"exclaim": "?"}) - }, - "world": func(context string, options *raymond.Options) string { - return options.DataStr("adjective") + " " + context + options.ValueStr("exclaim") - }, - }, - nil, - "happy world?", - }, - { - "passing in data to a compiled function that expects data - data is passed to with block helpers where children use ..", - `{{#hello}}{{world ../zomg}}{{/hello}}`, - map[string]interface{}{"exclaim": true, "zomg": "world"}, - map[string]interface{}{"adjective": "happy", "accessData": "#win"}, - map[string]interface{}{ - "hello": func(options *raymond.Options) string { - return options.DataStr("accessData") + " " + options.FnWith(map[string]string{"exclaim": "?"}) - }, - "world": func(context string, options *raymond.Options) string { - return options.DataStr("adjective") + " " + context + options.ValueStr("exclaim") - }, - }, - nil, - "#win happy world?", - }, - { - "you can override inherited data when invoking a helper", - `{{#hello}}{{world zomg}}{{/hello}}`, - map[string]interface{}{"exclaim": true, "zomg": "planet"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{ - "hello": func(options *raymond.Options) string { - ctx := map[string]string{"exclaim": "?", "zomg": "world"} - data := options.NewDataFrame() - data.Set("adjective", "sad") - - return options.FnCtxData(ctx, data) - }, - "world": func(context string, options *raymond.Options) string { - return options.DataStr("adjective") + " " + context + options.ValueStr("exclaim") - }, - }, - nil, - "sad world?", - }, - { - "you can override inherited data when invoking a helper with depth", - `{{#hello}}{{world ../zomg}}{{/hello}}`, - map[string]interface{}{"exclaim": true, "zomg": "world"}, - map[string]interface{}{"adjective": "happy"}, - map[string]interface{}{ - "hello": func(options *raymond.Options) string { - ctx := map[string]string{"exclaim": "?"} - data := options.NewDataFrame() - data.Set("adjective", "sad") - - return options.FnCtxData(ctx, data) - }, - "world": func(context string, options *raymond.Options) string { - return options.DataStr("adjective") + " " + context + options.ValueStr("exclaim") - }, - }, - nil, - "sad world?", - }, - { - "@root - the root context can be looked up via @root", - `{{@root.foo}}`, - map[string]interface{}{"foo": "hello"}, - nil, nil, nil, - "hello", - }, - { - "@root - passed root values take priority", - `{{@root.foo}}`, - nil, - map[string]interface{}{"root": map[string]string{"foo": "hello"}}, - nil, nil, - "hello", - }, - { - "nesting - the root context can be looked up via @root", - `{{#helper}}{{#helper}}{{@./depth}} {{@../depth}} {{@../../depth}}{{/helper}}{{/helper}}`, - map[string]interface{}{"foo": "hello"}, - map[string]interface{}{"depth": 0}, - map[string]interface{}{ - "helper": func(options *raymond.Options) string { - data := options.NewDataFrame() - - if depth, ok := options.Data("depth").(int); ok { - data.Set("depth", depth+1) - } - - return options.FnData(data) - }, - }, - nil, - "2 1 0", - }, -} - -func TestData(t *testing.T) { - launchTests(t, dataTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/doc.go b/vendor/github.com/aymerick/raymond/handlebars/doc.go deleted file mode 100644 index 6a4c50c..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package handlebars contains all the tests that come from handlebars.js project. -package handlebars diff --git a/vendor/github.com/aymerick/raymond/handlebars/helpers_test.go b/vendor/github.com/aymerick/raymond/handlebars/helpers_test.go deleted file mode 100644 index 45c5411..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/helpers_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package handlebars - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "github.com/aymerick/raymond" -) - -// -// Helpers -// - -func barSuffixHelper(context string) string { - return "bar " + context -} - -func echoHelper(str string) string { - return str -} - -func echoNbHelper(str string, nb int) string { - result := "" - for i := 0; i < nb; i++ { - result += str - } - - return result -} - -func linkHelper(prefix string, options *raymond.Options) string { - return fmt.Sprintf(`%s`, prefix, options.ValueStr("url"), options.ValueStr("text")) -} - -func rawHelper(options *raymond.Options) string { - return options.Fn() -} - -func rawThreeHelper(a, b, c string, options *raymond.Options) string { - return options.Fn() + a + b + c -} - -func formHelper(options *raymond.Options) string { - return "
" + options.Fn() + "
" -} - -func formCtxHelper(context interface{}, options *raymond.Options) string { - return "
" + options.FnWith(context) + "
" -} - -func listHelper(context interface{}, options *raymond.Options) string { - val := reflect.ValueOf(context) - switch val.Kind() { - case reflect.Array, reflect.Slice: - if val.Len() > 0 { - result := "
    " - for i := 0; i < val.Len(); i++ { - result += "
  • " - result += options.FnWith(val.Index(i).Interface()) - result += "
  • " - } - result += "
" - - return result - } - } - - return "

" + options.Inverse() + "

" -} - -func blogHelper(val string) string { - return "val is " + val -} - -func equalHelper(a, b string) string { - return raymond.Str(a == b) -} - -func dashHelper(a, b string) string { - return a + "-" + b -} - -func concatHelper(a, b string) string { - return a + b -} - -func detectDataHelper(options *raymond.Options) string { - if val, ok := options.DataFrame().Get("exclaim").(string); ok { - return val - } - - return "" -} - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/helper.js -// -var helpersTests = []Test{ - { - "helper with complex lookup", - "{{#goodbyes}}{{{link ../prefix}}}{{/goodbyes}}", - map[string]interface{}{"prefix": "/root", "goodbyes": []map[string]string{{"text": "Goodbye", "url": "goodbye"}}}, - nil, - map[string]interface{}{"link": linkHelper}, - nil, - `Goodbye`, - }, - { - "helper for raw block gets raw content", - "{{{{raw}}}} {{test}} {{{{/raw}}}}", - map[string]interface{}{"test": "hello"}, - nil, - map[string]interface{}{"raw": rawHelper}, - nil, - " {{test}} ", - }, - { - "helper for raw block gets parameters", - "{{{{raw 1 2 3}}}} {{test}} {{{{/raw}}}}", - map[string]interface{}{"test": "hello"}, - nil, - map[string]interface{}{"raw": rawThreeHelper}, - nil, - " {{test}} 123", - }, - { - "helper block with complex lookup expression", - "{{#goodbyes}}{{../name}}{{/goodbyes}}", - map[string]interface{}{"name": "Alan"}, - nil, - map[string]interface{}{"goodbyes": func(options *raymond.Options) string { - out := "" - for _, str := range []string{"Goodbye", "goodbye", "GOODBYE"} { - out += str + " " + options.FnWith(str) + "! " - } - return out - }}, - nil, - "Goodbye Alan! goodbye Alan! GOODBYE Alan! ", - }, - { - "helper with complex lookup and nested template", - "{{#goodbyes}}{{#link ../prefix}}{{text}}{{/link}}{{/goodbyes}}", - map[string]interface{}{"prefix": "/root", "goodbyes": []map[string]string{{"text": "Goodbye", "url": "goodbye"}}}, - nil, - map[string]interface{}{"link": linkHelper}, - nil, - `Goodbye`, - }, - { - // note: The JS implementation returns undefined, we return empty string - "helper returning undefined value (1)", - " {{nothere}}", - map[string]interface{}{}, - nil, - map[string]interface{}{"nothere": func() string { - return "" - }}, - nil, - " ", - }, - { - // note: The JS implementation returns undefined, we return empty string - "helper returning undefined value (2)", - " {{#nothere}}{{/nothere}}", - map[string]interface{}{}, - nil, - map[string]interface{}{"nothere": func() string { - return "" - }}, - nil, - " ", - }, - { - "block helper", - "{{#goodbyes}}{{text}}! {{/goodbyes}}cruel {{world}}!", - map[string]interface{}{"world": "world"}, - nil, - map[string]interface{}{"goodbyes": func(options *raymond.Options) string { - return options.FnWith(map[string]string{"text": "GOODBYE"}) - }}, - nil, - "GOODBYE! cruel world!", - }, - { - "block helper staying in the same context", - "{{#form}}

{{name}}

{{/form}}", - map[string]interface{}{"name": "Yehuda"}, - nil, - map[string]interface{}{"form": formHelper}, - nil, - "

Yehuda

", - }, - { - "block helper should have context in this", - "
    {{#people}}
  • {{#link}}{{name}}{{/link}}
  • {{/people}}
", - map[string]interface{}{"people": []map[string]interface{}{{"name": "Alan", "id": 1}, {"name": "Yehuda", "id": 2}}}, - nil, - map[string]interface{}{"link": func(options *raymond.Options) string { - return fmt.Sprintf("%s", options.ValueStr("id"), options.Fn()) - }}, - nil, - ``, - }, - { - "block helper for undefined value", - "{{#empty}}shouldn't render{{/empty}}", - nil, nil, nil, nil, - "", - }, - { - "block helper passing a new context", - "{{#form yehuda}}

{{name}}

{{/form}}", - map[string]map[string]string{"yehuda": {"name": "Yehuda"}}, - nil, - map[string]interface{}{"form": formCtxHelper}, - nil, - "

Yehuda

", - }, - { - "block helper passing a complex path context", - "{{#form yehuda/cat}}

{{name}}

{{/form}}", - map[string]map[string]interface{}{"yehuda": {"name": "Yehuda", "cat": map[string]string{"name": "Harold"}}}, - nil, - map[string]interface{}{"form": formCtxHelper}, - nil, - "

Harold

", - }, - { - "nested block helpers", - "{{#form yehuda}}

{{name}}

{{#link}}Hello{{/link}}{{/form}}", - map[string]map[string]string{"yehuda": {"name": "Yehuda"}}, - nil, - map[string]interface{}{"link": func(options *raymond.Options) string { - return fmt.Sprintf("%s", options.ValueStr("name"), options.Fn()) - }, "form": formCtxHelper}, - nil, - `

Yehuda

Hello
`, - }, - { - "block helper inverted sections (1) - an inverse wrapper is passed in as a new context", - "{{#list people}}{{name}}{{^}}Nobody's here{{/list}}", - map[string][]map[string]string{"people": {{"name": "Alan"}, {"name": "Yehuda"}}}, - nil, - map[string]interface{}{"list": listHelper}, - nil, - `
  • Alan
  • Yehuda
`, - }, - { - "block helper inverted sections (2) - an inverse wrapper can be optionally called", - "{{#list people}}{{name}}{{^}}Nobody's here{{/list}}", - map[string][]map[string]string{"people": {}}, - nil, - map[string]interface{}{"list": listHelper}, - nil, - `

Nobody's here

`, - }, - { - "block helper inverted sections (3) - the context of an inverse is the parent of the block", - "{{#list people}}Hello{{^}}{{message}}{{/list}}", - map[string]interface{}{"people": []interface{}{}, "message": "Nobody's here"}, - nil, - map[string]interface{}{"list": listHelper}, - nil, - `

Nobody's here

`, - }, - - { - "pathed lambdas with parameters (1)", - "{{./helper 1}}", - map[string]interface{}{ - "helper": func(param int) string { return "winning" }, - "hash": map[string]interface{}{ - "helper": func(param int) string { return "winning" }, - }}, - nil, - map[string]interface{}{"./helper": func(param int) string { return "fail" }}, - nil, - "winning", - }, - { - "pathed lambdas with parameters (2)", - "{{hash/helper 1}}", - map[string]interface{}{ - "helper": func(param int) string { return "winning" }, - "hash": map[string]interface{}{ - "helper": func(param int) string { return "winning" }, - }}, - nil, - map[string]interface{}{"./helper": func(param int) string { return "fail" }}, - nil, - "winning", - }, - - { - "helpers hash - providing a helpers hash (1)", - "Goodbye {{cruel}} {{world}}!", - map[string]interface{}{"cruel": "cruel"}, - nil, - map[string]interface{}{"world": func() string { return "world" }}, - nil, - "Goodbye cruel world!", - }, - { - "helpers hash - providing a helpers hash (2)", - "Goodbye {{#iter}}{{cruel}} {{world}}{{/iter}}!", - map[string]interface{}{"iter": []map[string]string{{"cruel": "cruel"}}}, - nil, - map[string]interface{}{"world": func() string { return "world" }}, - nil, - "Goodbye cruel world!", - }, - { - "helpers hash - in cases of conflict, helpers win (1)", - "{{{lookup}}}", - map[string]interface{}{"lookup": "Explicit"}, - nil, - map[string]interface{}{"lookup": func() string { return "helpers" }}, - nil, - "helpers", - }, - { - "helpers hash - in cases of conflict, helpers win (2)", - "{{lookup}}", - map[string]interface{}{"lookup": "Explicit"}, - nil, - map[string]interface{}{"lookup": func() string { return "helpers" }}, - nil, - "helpers", - }, - { - "helpers hash - the helpers hash is available is nested contexts", - "{{#outer}}{{#inner}}{{helper}}{{/inner}}{{/outer}}", - map[string]interface{}{"outer": map[string]interface{}{"inner": map[string]interface{}{"unused": []string{}}}}, - nil, - map[string]interface{}{"helper": func() string { return "helper" }}, - nil, - "helper", - }, - - // @todo "helpers hash - the helper hash should augment the global hash" - - // @todo "registration" - - { - "decimal number literals work", - "Message: {{hello -1.2 1.2}}", - nil, nil, - map[string]interface{}{"hello": func(times, times2 interface{}) string { - ts, t2s := "NaN", "NaN" - - if v, ok := times.(float64); ok { - ts = raymond.Str(v) - } - - if v, ok := times2.(float64); ok { - t2s = raymond.Str(v) - } - - return "Hello " + ts + " " + t2s + " times" - }}, - nil, - "Message: Hello -1.2 1.2 times", - }, - { - "negative number literals work", - "Message: {{hello -12}}", - nil, nil, - map[string]interface{}{"hello": func(times interface{}) string { - ts := "NaN" - - if v, ok := times.(int); ok { - ts = raymond.Str(v) - } - - return "Hello " + ts + " times" - }}, - nil, - "Message: Hello -12 times", - }, - - { - "String literal parameters - simple literals work", - `Message: {{hello "world" 12 true false}}`, - nil, nil, - map[string]interface{}{"hello": func(p, t, b, b2 interface{}) string { - times, bool1, bool2 := "NaN", "NaB", "NaB" - - param, ok := p.(string) - if !ok { - param = "NaN" - } - - if v, ok := t.(int); ok { - times = raymond.Str(v) - } - - if v, ok := b.(bool); ok { - bool1 = raymond.Str(v) - } - - if v, ok := b2.(bool); ok { - bool2 = raymond.Str(v) - } - - return "Hello " + param + " " + times + " times: " + bool1 + " " + bool2 - }}, - nil, - "Message: Hello world 12 times: true false", - }, - - // @todo "using a quote in the middle of a parameter raises an error" - - { - "String literal parameters - escaping a String is possible", - "Message: {{{hello \"\\\"world\\\"\"}}}", - nil, nil, - map[string]interface{}{"hello": func(param string) string { - return "Hello " + param - }}, - nil, - `Message: Hello "world"`, - }, - { - "String literal parameters - it works with ' marks", - "Message: {{{hello \"Alan's world\"}}}", - nil, nil, - map[string]interface{}{"hello": func(param string) string { - return "Hello " + param - }}, - nil, - `Message: Hello Alan's world`, - }, - - { - "multiple parameters - simple multi-params work", - "Message: {{goodbye cruel world}}", - map[string]string{"cruel": "cruel", "world": "world"}, - nil, - map[string]interface{}{"goodbye": func(cruel, world string) string { - return "Goodbye " + cruel + " " + world - }}, - nil, - "Message: Goodbye cruel world", - }, - { - "multiple parameters - block multi-params work", - "Message: {{#goodbye cruel world}}{{greeting}} {{adj}} {{noun}}{{/goodbye}}", - map[string]string{"cruel": "cruel", "world": "world"}, - nil, - map[string]interface{}{"goodbye": func(cruel, world string, options *raymond.Options) string { - return options.FnWith(map[string]interface{}{"greeting": "Goodbye", "adj": cruel, "noun": world}) - }}, - nil, - "Message: Goodbye cruel world", - }, - - { - "hash - helpers can take an optional hash", - `{{goodbye cruel="CRUEL" world="WORLD" times=12}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - return "GOODBYE " + options.HashStr("cruel") + " " + options.HashStr("world") + " " + options.HashStr("times") + " TIMES" - }}, - nil, - "GOODBYE CRUEL WORLD 12 TIMES", - }, - { - "hash - helpers can take an optional hash with booleans (1)", - `{{goodbye cruel="CRUEL" world="WORLD" print=true}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - p, ok := options.HashProp("print").(bool) - if ok { - if p { - return "GOODBYE " + options.HashStr("cruel") + " " + options.HashStr("world") - } - return "NOT PRINTING" - } - - return "THIS SHOULD NOT HAPPEN" - }}, - nil, - "GOODBYE CRUEL WORLD", - }, - { - "hash - helpers can take an optional hash with booleans (2)", - `{{goodbye cruel="CRUEL" world="WORLD" print=false}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - p, ok := options.HashProp("print").(bool) - if ok { - if p { - return "GOODBYE " + options.HashStr("cruel") + " " + options.HashStr("world") - } - return "NOT PRINTING" - } - - return "THIS SHOULD NOT HAPPEN" - }}, - nil, - "NOT PRINTING", - }, - { - "block helpers can take an optional hash", - `{{#goodbye cruel="CRUEL" times=12}}world{{/goodbye}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - return "GOODBYE " + options.HashStr("cruel") + " " + options.Fn() + " " + options.HashStr("times") + " TIMES" - }}, - nil, - "GOODBYE CRUEL world 12 TIMES", - }, - { - "block helpers can take an optional hash with single quoted stings", - `{{#goodbye cruel='CRUEL' times=12}}world{{/goodbye}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - return "GOODBYE " + options.HashStr("cruel") + " " + options.Fn() + " " + options.HashStr("times") + " TIMES" - }}, - nil, - "GOODBYE CRUEL world 12 TIMES", - }, - { - "block helpers can take an optional hash with booleans (1)", - `{{#goodbye cruel="CRUEL" print=true}}world{{/goodbye}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - p, ok := options.HashProp("print").(bool) - if ok { - if p { - return "GOODBYE " + options.HashStr("cruel") + " " + options.Fn() - } - return "NOT PRINTING" - } - - return "THIS SHOULD NOT HAPPEN" - }}, - nil, - "GOODBYE CRUEL world", - }, - { - "block helpers can take an optional hash with booleans (1)", - `{{#goodbye cruel="CRUEL" print=false}}world{{/goodbye}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - p, ok := options.HashProp("print").(bool) - if ok { - if p { - return "GOODBYE " + options.HashStr("cruel") + " " + options.Fn() - } - return "NOT PRINTING" - } - - return "THIS SHOULD NOT HAPPEN" - }}, - nil, - "NOT PRINTING", - }, - - // @todo "helperMissing - if a context is not found, helperMissing is used" throw error - - // @todo "helperMissing - if a context is not found, custom helperMissing is used" - - // @todo "helperMissing - if a value is not found, custom helperMissing is used" - - { - "block helpers can take an optional hash with booleans (1)", - `{{#goodbye cruel="CRUEL" print=false}}world{{/goodbye}}`, - nil, nil, - map[string]interface{}{"goodbye": func(options *raymond.Options) string { - p, ok := options.HashProp("print").(bool) - if ok { - if p { - return "GOODBYE " + options.HashStr("cruel") + " " + options.Fn() - } - return "NOT PRINTING" - } - - return "THIS SHOULD NOT HAPPEN" - }}, - nil, - "NOT PRINTING", - }, - - // @todo "knownHelpers/knownHelpersOnly" tests - - // @todo "blockHelperMissing" tests - - // @todo "name field" tests - - { - "name conflicts - helpers take precedence over same-named context properties", - `{{goodbye}} {{cruel world}}`, - map[string]string{"goodbye": "goodbye", "world": "world"}, - nil, - map[string]interface{}{ - "goodbye": func(options *raymond.Options) string { - return strings.ToUpper(options.ValueStr("goodbye")) - }, - "cruel": func(world string) string { - return "cruel " + strings.ToUpper(world) - }, - }, - nil, - "GOODBYE cruel WORLD", - }, - { - "name conflicts - helpers take precedence over same-named context properties", - `{{#goodbye}} {{cruel world}}{{/goodbye}}`, - map[string]string{"goodbye": "goodbye", "world": "world"}, - nil, - map[string]interface{}{ - "goodbye": func(options *raymond.Options) string { - return strings.ToUpper(options.ValueStr("goodbye")) + options.Fn() - }, - "cruel": func(world string) string { - return "cruel " + strings.ToUpper(world) - }, - }, - nil, - "GOODBYE cruel WORLD", - }, - { - "name conflicts - Scoped names take precedence over helpers", - `{{this.goodbye}} {{cruel world}} {{cruel this.goodbye}}`, - map[string]string{"goodbye": "goodbye", "world": "world"}, - nil, - map[string]interface{}{ - "goodbye": func(options *raymond.Options) string { - return strings.ToUpper(options.ValueStr("goodbye")) - }, - "cruel": func(world string) string { - return "cruel " + strings.ToUpper(world) - }, - }, - nil, - "goodbye cruel WORLD cruel GOODBYE", - }, - { - "name conflicts - Scoped names take precedence over block helpers", - `{{#goodbye}} {{cruel world}}{{/goodbye}} {{this.goodbye}}`, - map[string]string{"goodbye": "goodbye", "world": "world"}, - nil, - map[string]interface{}{ - "goodbye": func(options *raymond.Options) string { - return strings.ToUpper(options.ValueStr("goodbye")) + options.Fn() - }, - "cruel": func(world string) string { - return "cruel " + strings.ToUpper(world) - }, - }, - nil, - "GOODBYE cruel WORLD goodbye", - }, - - // @todo "block params" tests -} - -func TestHelpers(t *testing.T) { - launchTests(t, helpersTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/partials_test.go b/vendor/github.com/aymerick/raymond/handlebars/partials_test.go deleted file mode 100644 index 0c26662..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/partials_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package handlebars - -import "testing" - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/partials.js -// -var partialsTests = []Test{ - { - "basic partials", - "Dudes: {{#dudes}}{{> dude}}{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{name}} ({{url}}) "}, - "Dudes: Yehuda (http://yehuda) Alan (http://alan) ", - }, - { - "dynamic partials", - "Dudes: {{#dudes}}{{> (partial)}}{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, - map[string]interface{}{"partial": func() string { - return "dude" - }}, - map[string]string{"dude": "{{name}} ({{url}}) "}, - "Dudes: Yehuda (http://yehuda) Alan (http://alan) ", - }, - - // @todo "failing dynamic partials" - - { - "partials with context", - "Dudes: {{>dude dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{#this}}{{name}} ({{url}}) {{/this}}"}, - "Dudes: Yehuda (http://yehuda) Alan (http://alan) ", - }, - { - "partials with undefined context", - "Dudes: {{>dude dudes}}", - map[string]interface{}{}, - nil, nil, - map[string]string{"dude": "{{foo}} Empty"}, - "Dudes: Empty", - }, - - // @todo "partials with duplicate parameters" - - { - "partials with parameters", - "Dudes: {{#dudes}}{{> dude others=..}}{{/dudes}}", - map[string]interface{}{"foo": "bar", "dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{others.foo}}{{name}} ({{url}}) "}, - "Dudes: barYehuda (http://yehuda) barAlan (http://alan) ", - }, - { - "partial in a partial", - "Dudes: {{#dudes}}{{>dude}}{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{name}} {{> url}} ", "url": `{{url}}`}, - `Dudes: Yehuda http://yehuda Alan http://alan `, - }, - - // @todo "rendering undefined partial throws an exception" - - // @todo "registering undefined partial throws an exception" - - // SKIP: "rendering template partial in vm mode throws an exception" - // SKIP: "rendering function partial in vm mode" - - { - "GH-14: a partial preceding a selector", - "Dudes: {{>dude}} {{anotherDude}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"dude": "{{name}}"}, - "Dudes: Jeepers Creepers", - }, - { - "Partials with slash paths", - "Dudes: {{> shared/dude}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"shared/dude": "{{name}}"}, - "Dudes: Jeepers", - }, - { - "Partials with slash and point paths", - "Dudes: {{> shared/dude.thing}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"shared/dude.thing": "{{name}}"}, - "Dudes: Jeepers", - }, - - // @todo "Global Partials" - - // @todo "Multiple partial registration" - - { - "Partials with integer path", - "Dudes: {{> 404}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"404": "{{name}}"}, // @note Difference with JS test: partial name is a string - "Dudes: Jeepers", - }, - // @note This is not supported by our implementation. But really... who cares ? - // { - // "Partials with complex path", - // "Dudes: {{> 404/asdf?.bar}}", - // map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - // nil, nil, - // map[string]string{"404/asdf?.bar": "{{name}}"}, - // "Dudes: Jeepers", - // }, - { - "Partials with escaped", - "Dudes: {{> [+404/asdf?.bar]}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"+404/asdf?.bar": "{{name}}"}, - "Dudes: Jeepers", - }, - { - "Partials with string", - "Dudes: {{> '+404/asdf?.bar'}}", - map[string]string{"name": "Jeepers", "anotherDude": "Creepers"}, - nil, nil, - map[string]string{"+404/asdf?.bar": "{{name}}"}, - "Dudes: Jeepers", - }, - { - "should handle empty partial", - "Dudes: {{#dudes}}{{> dude}}{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": ""}, - "Dudes: ", - }, - - // @todo "throw on missing partial" - - // SKIP: "should pass compiler flags" - - { - "standalone partials (1) - indented partials", - "Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{name}}\n"}, - "Dudes:\n Yehuda\n Alan\n", - }, - { - "standalone partials (2) - nested indented partials", - "Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}", - map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - nil, nil, - map[string]string{"dude": "{{name}}\n {{> url}}", "url": "{{url}}!\n"}, - "Dudes:\n Yehuda\n http://yehuda!\n Alan\n http://alan!\n", - }, - - // // @todo preventIndent option - // { - // "standalone partials (3) - prevent nested indented partials", - // "Dudes:\n{{#dudes}}\n {{>dude}}\n{{/dudes}}", - // map[string]interface{}{"dudes": []map[string]string{{"name": "Yehuda", "url": "http://yehuda"}, {"name": "Alan", "url": "http://alan"}}}, - // nil, nil, - // map[string]string{"dude": "{{name}}\n {{> url}}", "url": "{{url}}!\n"}, - // "Dudes:\n Yehuda\n http://yehuda!\n Alan\n http://alan!\n", - // }, - - // @todo "compat mode" -} - -func TestPartials(t *testing.T) { - launchTests(t, partialsTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/subexpressions_test.go b/vendor/github.com/aymerick/raymond/handlebars/subexpressions_test.go deleted file mode 100644 index 31a12a7..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/subexpressions_test.go +++ /dev/null @@ -1,209 +0,0 @@ -package handlebars - -import ( - "testing" - - "github.com/aymerick/raymond" -) - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/subexpression.js -// -var subexpressionsTests = []Test{ - { - "arg-less helper", - "{{foo (bar)}}!", - map[string]interface{}{}, - nil, - map[string]interface{}{ - "foo": func(val string) string { - return val + val - }, - "bar": func() string { - return "LOL" - }, - }, - nil, - "LOLLOL!", - }, - { - "helper w args", - "{{blog (equal a b)}}", - map[string]interface{}{"bar": "LOL"}, - nil, - map[string]interface{}{ - "blog": blogHelper, - "equal": equalHelper, - }, - nil, - "val is true", - }, - { - "mixed paths and helpers", - "{{blog baz.bat (equal a b) baz.bar}}", - map[string]interface{}{"bar": "LOL", "baz": map[string]string{"bat": "foo!", "bar": "bar!"}}, - nil, - map[string]interface{}{ - "blog": func(p, p2, p3 string) string { - return "val is " + p + ", " + p2 + " and " + p3 - }, - "equal": equalHelper, - }, - nil, - "val is foo!, true and bar!", - }, - { - "supports much nesting", - "{{blog (equal (equal true true) true)}}", - map[string]interface{}{"bar": "LOL"}, - nil, - map[string]interface{}{ - "blog": blogHelper, - "equal": equalHelper, - }, - nil, - "val is true", - }, - - { - "GH-800 : Complex subexpressions (1)", - "{{dash 'abc' (concat a b)}}", - map[string]interface{}{"a": "a", "b": "b", "c": map[string]string{"c": "c"}, "d": "d", "e": map[string]string{"e": "e"}}, - nil, - map[string]interface{}{"dash": dashHelper, "concat": concatHelper}, - nil, - "abc-ab", - }, - { - "GH-800 : Complex subexpressions (2)", - "{{dash d (concat a b)}}", - map[string]interface{}{"a": "a", "b": "b", "c": map[string]string{"c": "c"}, "d": "d", "e": map[string]string{"e": "e"}}, - nil, - map[string]interface{}{"dash": dashHelper, "concat": concatHelper}, - nil, - "d-ab", - }, - { - "GH-800 : Complex subexpressions (3)", - "{{dash c.c (concat a b)}}", - map[string]interface{}{"a": "a", "b": "b", "c": map[string]string{"c": "c"}, "d": "d", "e": map[string]string{"e": "e"}}, - nil, - map[string]interface{}{"dash": dashHelper, "concat": concatHelper}, - nil, - "c-ab", - }, - { - "GH-800 : Complex subexpressions (4)", - "{{dash (concat a b) c.c}}", - map[string]interface{}{"a": "a", "b": "b", "c": map[string]string{"c": "c"}, "d": "d", "e": map[string]string{"e": "e"}}, - nil, - map[string]interface{}{"dash": dashHelper, "concat": concatHelper}, - nil, - "ab-c", - }, - { - "GH-800 : Complex subexpressions (5)", - "{{dash (concat a e.e) c.c}}", - map[string]interface{}{"a": "a", "b": "b", "c": map[string]string{"c": "c"}, "d": "d", "e": map[string]string{"e": "e"}}, - nil, - map[string]interface{}{"dash": dashHelper, "concat": concatHelper}, - nil, - "ae-c", - }, - - { - // note: test not relevant - "provides each nested helper invocation its own options hash", - "{{equal (equal true true) true}}", - map[string]interface{}{}, - nil, - map[string]interface{}{ - "equal": equalHelper, - }, - nil, - "true", - }, - { - "with hashes", - "{{blog (equal (equal true true) true fun='yes')}}", - map[string]interface{}{"bar": "LOL"}, - nil, - map[string]interface{}{ - "blog": blogHelper, - "equal": equalHelper, - }, - nil, - "val is true", - }, - { - "as hashes", - "{{blog fun=(equal (blog fun=1) 'val is 1')}}", - map[string]interface{}{}, - nil, - map[string]interface{}{ - "blog": func(options *raymond.Options) string { - return "val is " + options.HashStr("fun") - }, - "equal": equalHelper, - }, - nil, - "val is true", - }, - { - "multiple subexpressions in a hash", - `{{input aria-label=(t "Name") placeholder=(t "Example User")}}`, - map[string]interface{}{}, - nil, - map[string]interface{}{ - "input": func(options *raymond.Options) raymond.SafeString { - return raymond.SafeString(``) - }, - "t": func(param string) raymond.SafeString { - return raymond.SafeString(param) - }, - }, - nil, - ``, - }, - { - "multiple subexpressions in a hash with context", - `{{input aria-label=(t item.field) placeholder=(t item.placeholder)}}`, - map[string]map[string]string{"item": {"field": "Name", "placeholder": "Example User"}}, - nil, - map[string]interface{}{ - "input": func(options *raymond.Options) raymond.SafeString { - return raymond.SafeString(``) - }, - "t": func(param string) raymond.SafeString { - return raymond.SafeString(param) - }, - }, - nil, - ``, - }, - - // @todo "in string params mode" - - // @todo "as hashes in string params mode" - - { - "subexpression functions on the context", - "{{foo (bar)}}!", - map[string]interface{}{"bar": func() string { return "LOL" }}, - nil, - map[string]interface{}{ - "foo": func(val string) string { - return val + val - }, - }, - nil, - "LOLLOL!", - }, - - // @todo "subexpressions can't just be property lookups" should raise error -} - -func TestSubexpressions(t *testing.T) { - launchTests(t, subexpressionsTests) -} diff --git a/vendor/github.com/aymerick/raymond/handlebars/whitespace_test.go b/vendor/github.com/aymerick/raymond/handlebars/whitespace_test.go deleted file mode 100644 index f11e16e..0000000 --- a/vendor/github.com/aymerick/raymond/handlebars/whitespace_test.go +++ /dev/null @@ -1,259 +0,0 @@ -package handlebars - -import "testing" - -// -// Those tests come from: -// https://github.com/wycats/handlebars.js/blob/master/spec/whitespace-control.js -// -var whitespaceControlTests = []Test{ - { - "should strip whitespace around mustache calls (1)", - " {{~foo~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar<", - }, - { - "should strip whitespace around mustache calls (2)", - " {{~foo}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar< ", - }, - { - "should strip whitespace around mustache calls (3)", - " {{foo~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar<", - }, - { - "should strip whitespace around mustache calls (4)", - " {{~&foo~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar<", - }, - { - "should strip whitespace around mustache calls (5)", - " {{~{foo}~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar<", - }, - { - "should strip whitespace around mustache calls (6)", - "1\n{{foo~}} \n\n 23\n{{bar}}4", - nil, nil, nil, nil, - "1\n23\n4", - }, - - { - "blocks - should strip whitespace around simple block calls (1)", - " {{~#if foo~}} bar {{~/if~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar", - }, - { - "blocks - should strip whitespace around simple block calls (2)", - " {{#if foo~}} bar {{/if~}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar ", - }, - { - "blocks - should strip whitespace around simple block calls (3)", - " {{~#if foo}} bar {{~/if}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar ", - }, - { - "blocks - should strip whitespace around simple block calls (4)", - " {{#if foo}} bar {{/if}} ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar ", - }, - { - "blocks - should strip whitespace around simple block calls (5)", - " \n\n{{~#if foo~}} \n\nbar \n\n{{~/if~}}\n\n ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar", - }, - { - "blocks - should strip whitespace around simple block calls (6)", - " a\n\n{{~#if foo~}} \n\nbar \n\n{{~/if~}}\n\na ", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " abara ", - }, - - { - "should strip whitespace around inverse block calls (1)", - " {{~^if foo~}} bar {{~/if~}} ", - nil, nil, nil, nil, - "bar", - }, - { - "should strip whitespace around inverse block calls (2)", - " {{^if foo~}} bar {{/if~}} ", - nil, nil, nil, nil, - " bar ", - }, - { - "should strip whitespace around inverse block calls (3)", - " {{~^if foo}} bar {{~/if}} ", - nil, nil, nil, nil, - " bar ", - }, - { - "should strip whitespace around inverse block calls (4)", - " {{^if foo}} bar {{/if}} ", - nil, nil, nil, nil, - " bar ", - }, - { - "should strip whitespace around inverse block calls (5)", - " \n\n{{~^if foo~}} \n\nbar \n\n{{~/if~}}\n\n ", - nil, nil, nil, nil, - "bar", - }, - - { - "should strip whitespace around complex block calls (1)", - "{{#if foo~}} bar {{~^~}} baz {{~/if}}", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar", - }, - { - "should strip whitespace around complex block calls (2)", - "{{#if foo~}} bar {{^~}} baz {{/if}}", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar ", - }, - { - "should strip whitespace around complex block calls (3)", - "{{#if foo}} bar {{~^~}} baz {{~/if}}", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar", - }, - { - "should strip whitespace around complex block calls (4)", - "{{#if foo}} bar {{^~}} baz {{/if}}", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - " bar ", - }, - { - "should strip whitespace around complex block calls (5)", - "{{#if foo~}} bar {{~else~}} baz {{~/if}}", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar", - }, - { - "should strip whitespace around complex block calls (6)", - "\n\n{{~#if foo~}} \n\nbar \n\n{{~^~}} \n\nbaz \n\n{{~/if~}}\n\n", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar", - }, - { - "should strip whitespace around complex block calls (7)", - "\n\n{{~#if foo~}} \n\n{{{foo}}} \n\n{{~^~}} \n\nbaz \n\n{{~/if~}}\n\n", - map[string]string{"foo": "bar<"}, - nil, nil, nil, - "bar<", - }, - { - "should strip whitespace around complex block calls (8)", - "{{#if foo~}} bar {{~^~}} baz {{~/if}}", - nil, nil, nil, nil, - "baz", - }, - { - "should strip whitespace around complex block calls (9)", - "{{#if foo}} bar {{~^~}} baz {{/if}}", - nil, nil, nil, nil, - "baz ", - }, - { - "should strip whitespace around complex block calls (10)", - "{{#if foo~}} bar {{~^}} baz {{~/if}}", - nil, nil, nil, nil, - " baz", - }, - { - "should strip whitespace around complex block calls (11)", - "{{#if foo~}} bar {{~^}} baz {{/if}}", - nil, nil, nil, nil, - " baz ", - }, - { - "should strip whitespace around complex block calls (12)", - "{{#if foo~}} bar {{~else~}} baz {{~/if}}", - nil, nil, nil, nil, - "baz", - }, - { - "should strip whitespace around complex block calls (13)", - "\n\n{{~#if foo~}} \n\nbar \n\n{{~^~}} \n\nbaz \n\n{{~/if~}}\n\n", - nil, nil, nil, nil, - "baz", - }, - - { - "should strip whitespace around partials (1)", - "foo {{~> dude~}} ", - nil, nil, nil, - map[string]string{"dude": "bar"}, - "foobar", - }, - { - "should strip whitespace around partials (2)", - "foo {{> dude~}} ", - nil, nil, nil, - map[string]string{"dude": "bar"}, - "foo bar", - }, - { - "should strip whitespace around partials (3)", - "foo {{> dude}} ", - nil, nil, nil, - map[string]string{"dude": "bar"}, - "foo bar ", - }, - { - "should strip whitespace around partials (4)", - "foo\n {{~> dude}} ", - nil, nil, nil, - map[string]string{"dude": "bar"}, - "foobar", - }, - { - "should strip whitespace around partials (5)", - "foo\n {{> dude}} ", - nil, nil, nil, - map[string]string{"dude": "bar"}, - "foo\n bar", - }, - - { - "should only strip whitespace once", - " {{~foo~}} {{foo}} {{foo}} ", - map[string]string{"foo": "bar"}, - nil, nil, nil, - "barbar bar ", - }, -} - -func TestWhitespaceControl(t *testing.T) { - launchTests(t, whitespaceControlTests) -} diff --git a/vendor/github.com/aymerick/raymond/helper.go b/vendor/github.com/aymerick/raymond/helper.go deleted file mode 100644 index 0e5ed6e..0000000 --- a/vendor/github.com/aymerick/raymond/helper.go +++ /dev/null @@ -1,371 +0,0 @@ -package raymond - -import ( - "fmt" - "log" - "reflect" - "sync" -) - -// Options represents the options argument provided to helpers and context functions. -type Options struct { - // evaluation visitor - eval *evalVisitor - - // params - params []interface{} - hash map[string]interface{} -} - -// helpers stores all globally registered helpers -var helpers = make(map[string]reflect.Value) - -// protects global helpers -var helpersMutex sync.RWMutex - -func init() { - // register builtin helpers - RegisterHelper("if", ifHelper) - RegisterHelper("unless", unlessHelper) - RegisterHelper("with", withHelper) - RegisterHelper("each", eachHelper) - RegisterHelper("log", logHelper) - RegisterHelper("lookup", lookupHelper) -} - -// RegisterHelper registers a global helper. That helper will be available to all templates. -func RegisterHelper(name string, helper interface{}) { - helpersMutex.Lock() - defer helpersMutex.Unlock() - - if helpers[name] != zero { - panic(fmt.Errorf("Helper already registered: %s", name)) - } - - val := reflect.ValueOf(helper) - ensureValidHelper(name, val) - - helpers[name] = val -} - -// RegisterHelpers registers several global helpers. Those helpers will be available to all templates. -func RegisterHelpers(helpers map[string]interface{}) { - for name, helper := range helpers { - RegisterHelper(name, helper) - } -} - -// ensureValidHelper panics if given helper is not valid -func ensureValidHelper(name string, funcValue reflect.Value) { - if funcValue.Kind() != reflect.Func { - panic(fmt.Errorf("Helper must be a function: %s", name)) - } - - funcType := funcValue.Type() - - if funcType.NumOut() != 1 { - panic(fmt.Errorf("Helper function must return a string or a SafeString: %s", name)) - } - - // @todo Check if first returned value is a string, SafeString or interface{} ? -} - -// findHelper finds a globally registered helper -func findHelper(name string) reflect.Value { - helpersMutex.RLock() - defer helpersMutex.RUnlock() - - return helpers[name] -} - -// newOptions instanciates a new Options -func newOptions(eval *evalVisitor, params []interface{}, hash map[string]interface{}) *Options { - return &Options{ - eval: eval, - params: params, - hash: hash, - } -} - -// newEmptyOptions instanciates a new empty Options -func newEmptyOptions(eval *evalVisitor) *Options { - return &Options{ - eval: eval, - hash: make(map[string]interface{}), - } -} - -// -// Context Values -// - -// Value returns field value from current context. -func (options *Options) Value(name string) interface{} { - value := options.eval.evalField(options.eval.curCtx(), name, false) - if !value.IsValid() { - return nil - } - - return value.Interface() -} - -// ValueStr returns string representation of field value from current context. -func (options *Options) ValueStr(name string) string { - return Str(options.Value(name)) -} - -// Ctx returns current evaluation context. -func (options *Options) Ctx() interface{} { - return options.eval.curCtx().Interface() -} - -// -// Hash Arguments -// - -// HashProp returns hash property. -func (options *Options) HashProp(name string) interface{} { - return options.hash[name] -} - -// HashStr returns string representation of hash property. -func (options *Options) HashStr(name string) string { - return Str(options.hash[name]) -} - -// Hash returns entire hash. -func (options *Options) Hash() map[string]interface{} { - return options.hash -} - -// -// Parameters -// - -// Param returns parameter at given position. -func (options *Options) Param(pos int) interface{} { - if len(options.params) > pos { - return options.params[pos] - } - - return nil -} - -// ParamStr returns string representation of parameter at given position. -func (options *Options) ParamStr(pos int) string { - return Str(options.Param(pos)) -} - -// Params returns all parameters. -func (options *Options) Params() []interface{} { - return options.params -} - -// -// Private data -// - -// Data returns private data value. -func (options *Options) Data(name string) interface{} { - return options.eval.dataFrame.Get(name) -} - -// DataStr returns string representation of private data value. -func (options *Options) DataStr(name string) string { - return Str(options.eval.dataFrame.Get(name)) -} - -// DataFrame returns current private data frame. -func (options *Options) DataFrame() *DataFrame { - return options.eval.dataFrame -} - -// NewDataFrame instanciates a new data frame that is a copy of current evaluation data frame. -// -// Parent of returned data frame is set to current evaluation data frame. -func (options *Options) NewDataFrame() *DataFrame { - return options.eval.dataFrame.Copy() -} - -// newIterDataFrame instanciates a new data frame and set iteration specific vars -func (options *Options) newIterDataFrame(length int, i int, key interface{}) *DataFrame { - return options.eval.dataFrame.newIterDataFrame(length, i, key) -} - -// -// Evaluation -// - -// evalBlock evaluates block with given context, private data and iteration key -func (options *Options) evalBlock(ctx interface{}, data *DataFrame, key interface{}) string { - result := "" - - if block := options.eval.curBlock(); (block != nil) && (block.Program != nil) { - result = options.eval.evalProgram(block.Program, ctx, data, key) - } - - return result -} - -// Fn evaluates block with current evaluation context. -func (options *Options) Fn() string { - return options.evalBlock(nil, nil, nil) -} - -// FnCtxData evaluates block with given context and private data frame. -func (options *Options) FnCtxData(ctx interface{}, data *DataFrame) string { - return options.evalBlock(ctx, data, nil) -} - -// FnWith evaluates block with given context. -func (options *Options) FnWith(ctx interface{}) string { - return options.evalBlock(ctx, nil, nil) -} - -// FnData evaluates block with given private data frame. -func (options *Options) FnData(data *DataFrame) string { - return options.evalBlock(nil, data, nil) -} - -// Inverse evaluates "else block". -func (options *Options) Inverse() string { - result := "" - if block := options.eval.curBlock(); (block != nil) && (block.Inverse != nil) { - result, _ = block.Inverse.Accept(options.eval).(string) - } - - return result -} - -// Eval evaluates field for given context. -func (options *Options) Eval(ctx interface{}, field string) interface{} { - if ctx == nil { - return nil - } - - if field == "" { - return nil - } - - val := options.eval.evalField(reflect.ValueOf(ctx), field, false) - if !val.IsValid() { - return nil - } - - return val.Interface() -} - -// -// Misc -// - -// isIncludableZero returns true if 'includeZero' option is set and first param is the number 0 -func (options *Options) isIncludableZero() bool { - b, ok := options.HashProp("includeZero").(bool) - if ok && b { - nb, ok := options.Param(0).(int) - if ok && nb == 0 { - return true - } - } - - return false -} - -// -// Builtin helpers -// - -// #if block helper -func ifHelper(conditional interface{}, options *Options) interface{} { - if options.isIncludableZero() || IsTrue(conditional) { - return options.Fn() - } - - return options.Inverse() -} - -// #unless block helper -func unlessHelper(conditional interface{}, options *Options) interface{} { - if options.isIncludableZero() || IsTrue(conditional) { - return options.Inverse() - } - - return options.Fn() -} - -// #with block helper -func withHelper(context interface{}, options *Options) interface{} { - if IsTrue(context) { - return options.FnWith(context) - } - - return options.Inverse() -} - -// #each block helper -func eachHelper(context interface{}, options *Options) interface{} { - if !IsTrue(context) { - return options.Inverse() - } - - result := "" - - val := reflect.ValueOf(context) - switch val.Kind() { - case reflect.Array, reflect.Slice: - for i := 0; i < val.Len(); i++ { - // computes private data - data := options.newIterDataFrame(val.Len(), i, nil) - - // evaluates block - result += options.evalBlock(val.Index(i).Interface(), data, i) - } - case reflect.Map: - // note: a go hash is not ordered, so result may vary, this behaviour differs from the JS implementation - keys := val.MapKeys() - for i := 0; i < len(keys); i++ { - key := keys[i].Interface() - ctx := val.MapIndex(keys[i]).Interface() - - // computes private data - data := options.newIterDataFrame(len(keys), i, key) - - // evaluates block - result += options.evalBlock(ctx, data, key) - } - case reflect.Struct: - var exportedFields []int - - // collect exported fields only - for i := 0; i < val.NumField(); i++ { - if tField := val.Type().Field(i); tField.PkgPath == "" { - exportedFields = append(exportedFields, i) - } - } - - for i, fieldIndex := range exportedFields { - key := val.Type().Field(fieldIndex).Name - ctx := val.Field(fieldIndex).Interface() - - // computes private data - data := options.newIterDataFrame(len(exportedFields), i, key) - - // evaluates block - result += options.evalBlock(ctx, data, key) - } - } - - return result -} - -// #log helper -func logHelper(message string) interface{} { - log.Print(message) - return "" -} - -// #lookup helper -func lookupHelper(obj interface{}, field string, options *Options) interface{} { - return Str(options.Eval(obj, field)) -} diff --git a/vendor/github.com/aymerick/raymond/helper_test.go b/vendor/github.com/aymerick/raymond/helper_test.go deleted file mode 100644 index b867e3f..0000000 --- a/vendor/github.com/aymerick/raymond/helper_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package raymond - -import "testing" - -const ( - VERBOSE = false -) - -// -// Helpers -// - -func barHelper(options *Options) string { return "bar" } - -func echoHelper(str string, nb int) string { - result := "" - for i := 0; i < nb; i++ { - result += str - } - - return result -} - -func boolHelper(b bool) string { - if b { - return "yes it is" - } - - return "absolutely not" -} - -func gnakHelper(nb int) string { - result := "" - for i := 0; i < nb; i++ { - result += "GnAK!" - } - - return result -} - -// -// Tests -// - -var helperTests = []Test{ - { - "simple helper", - `{{foo}}`, - nil, nil, - map[string]interface{}{"foo": barHelper}, - nil, - `bar`, - }, - { - "helper with literal string param", - `{{echo "foo" 1}}`, - nil, nil, - map[string]interface{}{"echo": echoHelper}, - nil, - `foo`, - }, - { - "helper with identifier param", - `{{echo foo 1}}`, - map[string]interface{}{"foo": "bar"}, - nil, - map[string]interface{}{"echo": echoHelper}, - nil, - `bar`, - }, - { - "helper with literal boolean param", - `{{bool true}}`, - nil, nil, - map[string]interface{}{"bool": boolHelper}, - nil, - `yes it is`, - }, - { - "helper with literal boolean param", - `{{bool false}}`, - nil, nil, - map[string]interface{}{"bool": boolHelper}, - nil, - `absolutely not`, - }, - { - "helper with literal boolean param", - `{{gnak 5}}`, - nil, nil, - map[string]interface{}{"gnak": gnakHelper}, - nil, - `GnAK!GnAK!GnAK!GnAK!GnAK!`, - }, - { - "helper with several parameters", - `{{echo "GnAK!" 3}}`, - nil, nil, - map[string]interface{}{"echo": echoHelper}, - nil, - `GnAK!GnAK!GnAK!`, - }, - { - "#if helper with true literal", - `{{#if true}}YES MAN{{/if}}`, - nil, nil, nil, nil, - `YES MAN`, - }, - { - "#if helper with false literal", - `{{#if false}}YES MAN{{/if}}`, - nil, nil, nil, nil, - ``, - }, - { - "#if helper with truthy identifier", - `{{#if ok}}YES MAN{{/if}}`, - map[string]interface{}{"ok": true}, - nil, nil, nil, - `YES MAN`, - }, - { - "#if helper with falsy identifier", - `{{#if ok}}YES MAN{{/if}}`, - map[string]interface{}{"ok": false}, - nil, nil, nil, - ``, - }, - { - "#unless helper with true literal", - `{{#unless true}}YES MAN{{/unless}}`, - nil, nil, nil, nil, - ``, - }, - { - "#unless helper with false literal", - `{{#unless false}}YES MAN{{/unless}}`, - nil, nil, nil, nil, - `YES MAN`, - }, - { - "#unless helper with truthy identifier", - `{{#unless ok}}YES MAN{{/unless}}`, - map[string]interface{}{"ok": true}, - nil, nil, nil, - ``, - }, - { - "#unless helper with falsy identifier", - `{{#unless ok}}YES MAN{{/unless}}`, - map[string]interface{}{"ok": false}, - nil, nil, nil, - `YES MAN`, - }, -} - -// -// Let's go -// - -func TestHelper(t *testing.T) { - t.Parallel() - - launchTests(t, helperTests) -} - -// -// Fixes: https://github.com/aymerick/raymond/issues/2 -// - -type Author struct { - FirstName string - LastName string -} - -func TestHelperCtx(t *testing.T) { - RegisterHelper("template", func(name string, options *Options) SafeString { - context := options.Ctx() - - template := name + " - {{ firstName }} {{ lastName }}" - result, _ := Render(template, context) - - return SafeString(result) - }) - - template := `By {{ template "namefile" }}` - context := Author{"Alan", "Johnson"} - - result, _ := Render(template, context) - if result != "By namefile - Alan Johnson" { - t.Errorf("Failed to render template in helper: %q", result) - } -} diff --git a/vendor/github.com/aymerick/raymond/lexer/lexer.go b/vendor/github.com/aymerick/raymond/lexer/lexer.go deleted file mode 100644 index 48899f8..0000000 --- a/vendor/github.com/aymerick/raymond/lexer/lexer.go +++ /dev/null @@ -1,639 +0,0 @@ -// Package lexer provides a handlebars tokenizer. -package lexer - -import ( - "fmt" - "regexp" - "strings" - "unicode" - "unicode/utf8" -) - -// References: -// - https://github.com/wycats/handlebars.js/blob/master/src/handlebars.l -// - https://github.com/golang/go/blob/master/src/text/template/parse/lex.go - -const ( - // Mustaches detection - escapedEscapedOpenMustache = "\\\\{{" - escapedOpenMustache = "\\{{" - openMustache = "{{" - closeMustache = "}}" - closeStripMustache = "~}}" - closeUnescapedStripMustache = "}~}}" -) - -const eof = -1 - -// lexFunc represents a function that returns the next lexer function. -type lexFunc func(*Lexer) lexFunc - -// Lexer is a lexical analyzer. -type Lexer struct { - input string // input to scan - name string // lexer name, used for testing purpose - tokens chan Token // channel of scanned tokens - nextFunc lexFunc // the next function to execute - - pos int // current byte position in input string - line int // current line position in input string - width int // size of last rune scanned from input string - start int // start position of the token we are scanning - - // the shameful contextual properties needed because `nextFunc` is not enough - closeComment *regexp.Regexp // regexp to scan close of current comment - rawBlock bool // are we parsing a raw block content ? -} - -var ( - lookheadChars = `[\s` + regexp.QuoteMeta("=~}/)|") + `]` - literalLookheadChars = `[\s` + regexp.QuoteMeta("~})") + `]` - - // characters not allowed in an identifier - unallowedIDChars = " \n\t!\"#%&'()*+,./;<=>@[\\]^`{|}~" - - // regular expressions - rID = regexp.MustCompile(`^[^` + regexp.QuoteMeta(unallowedIDChars) + `]+`) - rDotID = regexp.MustCompile(`^\.` + lookheadChars) - rTrue = regexp.MustCompile(`^true` + literalLookheadChars) - rFalse = regexp.MustCompile(`^false` + literalLookheadChars) - rOpenRaw = regexp.MustCompile(`^\{\{\{\{`) - rCloseRaw = regexp.MustCompile(`^\}\}\}\}`) - rOpenEndRaw = regexp.MustCompile(`^\{\{\{\{/`) - rOpenEndRawLookAhead = regexp.MustCompile(`\{\{\{\{/`) - rOpenUnescaped = regexp.MustCompile(`^\{\{~?\{`) - rCloseUnescaped = regexp.MustCompile(`^\}~?\}\}`) - rOpenBlock = regexp.MustCompile(`^\{\{~?#`) - rOpenEndBlock = regexp.MustCompile(`^\{\{~?/`) - rOpenPartial = regexp.MustCompile(`^\{\{~?>`) - // {{^}} or {{else}} - rInverse = regexp.MustCompile(`^(\{\{~?\^\s*~?\}\}|\{\{~?\s*else\s*~?\}\})`) - rOpenInverse = regexp.MustCompile(`^\{\{~?\^`) - rOpenInverseChain = regexp.MustCompile(`^\{\{~?\s*else`) - // {{ or {{& - rOpen = regexp.MustCompile(`^\{\{~?&?`) - rClose = regexp.MustCompile(`^~?\}\}`) - rOpenBlockParams = regexp.MustCompile(`^as\s+\|`) - // {{!-- ... --}} - rOpenCommentDash = regexp.MustCompile(`^\{\{~?!--\s*`) - rCloseCommentDash = regexp.MustCompile(`^\s*--~?\}\}`) - // {{! ... }} - rOpenComment = regexp.MustCompile(`^\{\{~?!\s*`) - rCloseComment = regexp.MustCompile(`^\s*~?\}\}`) -) - -// Scan scans given input. -// -// Tokens can then be fetched sequentially thanks to NextToken() function on returned lexer. -func Scan(input string) *Lexer { - return scanWithName(input, "") -} - -// scanWithName scans given input, with a name used for testing -// -// Tokens can then be fetched sequentially thanks to NextToken() function on returned lexer. -func scanWithName(input string, name string) *Lexer { - result := &Lexer{ - input: input, - name: name, - tokens: make(chan Token), - line: 1, - } - - go result.run() - - return result -} - -// Collect scans and collect all tokens. -// -// This should be used for debugging purpose only. You should use Scan() and lexer.NextToken() functions instead. -func Collect(input string) []Token { - var result []Token - - l := Scan(input) - for { - token := l.NextToken() - result = append(result, token) - - if token.Kind == TokenEOF || token.Kind == TokenError { - break - } - } - - return result -} - -// NextToken returns the next scanned token. -func (l *Lexer) NextToken() Token { - result := <-l.tokens - - return result -} - -// run starts lexical analysis -func (l *Lexer) run() { - for l.nextFunc = lexContent; l.nextFunc != nil; { - l.nextFunc = l.nextFunc(l) - } -} - -// next returns next character from input, or eof of there is nothing left to scan -func (l *Lexer) next() rune { - if l.pos >= len(l.input) { - l.width = 0 - return eof - } - - r, w := utf8.DecodeRuneInString(l.input[l.pos:]) - l.width = w - l.pos += l.width - - return r -} - -func (l *Lexer) produce(kind TokenKind, val string) { - l.tokens <- Token{kind, val, l.start, l.line} - - // scanning a new token - l.start = l.pos - - // update line number - l.line += strings.Count(val, "\n") -} - -// emit emits a new scanned token -func (l *Lexer) emit(kind TokenKind) { - l.produce(kind, l.input[l.start:l.pos]) -} - -// emitContent emits scanned content -func (l *Lexer) emitContent() { - if l.pos > l.start { - l.emit(TokenContent) - } -} - -// emitString emits a scanned string -func (l *Lexer) emitString(delimiter rune) { - str := l.input[l.start:l.pos] - - // replace escaped delimiters - str = strings.Replace(str, "\\"+string(delimiter), string(delimiter), -1) - - l.produce(TokenString, str) -} - -// peek returns but does not consume the next character in the input -func (l *Lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// backup steps back one character -// -// WARNING: Can only be called once per call of next -func (l *Lexer) backup() { - l.pos -= l.width -} - -// ignoreskips all characters that have been scanned up to current position -func (l *Lexer) ignore() { - l.start = l.pos -} - -// accept scans the next character if it is included in given string -func (l *Lexer) accept(valid string) bool { - if strings.IndexRune(valid, l.next()) >= 0 { - return true - } - - l.backup() - - return false -} - -// acceptRun scans all following characters that are part of given string -func (l *Lexer) acceptRun(valid string) { - for strings.IndexRune(valid, l.next()) >= 0 { - } - - l.backup() -} - -// errorf emits an error token -func (l *Lexer) errorf(format string, args ...interface{}) lexFunc { - l.tokens <- Token{TokenError, fmt.Sprintf(format, args...), l.start, l.line} - return nil -} - -// isString returns true if content at current scanning position starts with given string -func (l *Lexer) isString(str string) bool { - return strings.HasPrefix(l.input[l.pos:], str) -} - -// findRegexp returns the first string from current scanning position that matches given regular expression -func (l *Lexer) findRegexp(r *regexp.Regexp) string { - return r.FindString(l.input[l.pos:]) -} - -// indexRegexp returns the index of the first string from current scanning position that matches given regular expression -// -// It returns -1 if not found -func (l *Lexer) indexRegexp(r *regexp.Regexp) int { - loc := r.FindStringIndex(l.input[l.pos:]) - if loc == nil { - return -1 - } - return loc[0] -} - -// lexContent scans content (ie: not between mustaches) -func lexContent(l *Lexer) lexFunc { - var next lexFunc - - if l.rawBlock { - if i := l.indexRegexp(rOpenEndRawLookAhead); i != -1 { - // {{{{/ - l.rawBlock = false - l.pos += i - - next = lexOpenMustache - } else { - return l.errorf("Unclosed raw block") - } - } else if l.isString(escapedEscapedOpenMustache) { - // \\{{ - - // emit content with only one escaped escape - l.next() - l.emitContent() - - // ignore second escaped escape - l.next() - l.ignore() - - next = lexContent - } else if l.isString(escapedOpenMustache) { - // \{{ - next = lexEscapedOpenMustache - } else if str := l.findRegexp(rOpenCommentDash); str != "" { - // {{!-- - l.closeComment = rCloseCommentDash - - next = lexComment - } else if str := l.findRegexp(rOpenComment); str != "" { - // {{! - l.closeComment = rCloseComment - - next = lexComment - } else if l.isString(openMustache) { - // {{ - next = lexOpenMustache - } - - if next != nil { - // emit scanned content - l.emitContent() - - // scan next token - return next - } - - // scan next rune - if l.next() == eof { - // emit scanned content - l.emitContent() - - // this is over - l.emit(TokenEOF) - return nil - } - - // continue content scanning - return lexContent -} - -// lexEscapedOpenMustache scans \{{ -func lexEscapedOpenMustache(l *Lexer) lexFunc { - // ignore escape character - l.next() - l.ignore() - - // scan mustaches - for l.peek() == '{' { - l.next() - } - - return lexContent -} - -// lexOpenMustache scans {{ -func lexOpenMustache(l *Lexer) lexFunc { - var str string - var tok TokenKind - - nextFunc := lexExpression - - if str = l.findRegexp(rOpenEndRaw); str != "" { - tok = TokenOpenEndRawBlock - } else if str = l.findRegexp(rOpenRaw); str != "" { - tok = TokenOpenRawBlock - l.rawBlock = true - } else if str = l.findRegexp(rOpenUnescaped); str != "" { - tok = TokenOpenUnescaped - } else if str = l.findRegexp(rOpenBlock); str != "" { - tok = TokenOpenBlock - } else if str = l.findRegexp(rOpenEndBlock); str != "" { - tok = TokenOpenEndBlock - } else if str = l.findRegexp(rOpenPartial); str != "" { - tok = TokenOpenPartial - } else if str = l.findRegexp(rInverse); str != "" { - tok = TokenInverse - nextFunc = lexContent - } else if str = l.findRegexp(rOpenInverse); str != "" { - tok = TokenOpenInverse - } else if str = l.findRegexp(rOpenInverseChain); str != "" { - tok = TokenOpenInverseChain - } else if str = l.findRegexp(rOpen); str != "" { - tok = TokenOpen - } else { - // this is rotten - panic("Current pos MUST be an opening mustache") - } - - l.pos += len(str) - l.emit(tok) - - return nextFunc -} - -// lexCloseMustache scans }} or ~}} -func lexCloseMustache(l *Lexer) lexFunc { - var str string - var tok TokenKind - - if str = l.findRegexp(rCloseRaw); str != "" { - // }}}} - tok = TokenCloseRawBlock - } else if str = l.findRegexp(rCloseUnescaped); str != "" { - // }}} - tok = TokenCloseUnescaped - } else if str = l.findRegexp(rClose); str != "" { - // }} - tok = TokenClose - } else { - // this is rotten - panic("Current pos MUST be a closing mustache") - } - - l.pos += len(str) - l.emit(tok) - - return lexContent -} - -// lexExpression scans inside mustaches -func lexExpression(l *Lexer) lexFunc { - // search close mustache delimiter - if l.isString(closeMustache) || l.isString(closeStripMustache) || l.isString(closeUnescapedStripMustache) { - return lexCloseMustache - } - - // search some patterns before advancing scanning position - - // "as |" - if str := l.findRegexp(rOpenBlockParams); str != "" { - l.pos += len(str) - l.emit(TokenOpenBlockParams) - return lexExpression - } - - // .. - if l.isString("..") { - l.pos += len("..") - l.emit(TokenID) - return lexExpression - } - - // . - if str := l.findRegexp(rDotID); str != "" { - l.pos += len(".") - l.emit(TokenID) - return lexExpression - } - - // true - if str := l.findRegexp(rTrue); str != "" { - l.pos += len("true") - l.emit(TokenBoolean) - return lexExpression - } - - // false - if str := l.findRegexp(rFalse); str != "" { - l.pos += len("false") - l.emit(TokenBoolean) - return lexExpression - } - - // let's scan next character - switch r := l.next(); { - case r == eof: - return l.errorf("Unclosed expression") - case isIgnorable(r): - return lexIgnorable - case r == '(': - l.emit(TokenOpenSexpr) - case r == ')': - l.emit(TokenCloseSexpr) - case r == '=': - l.emit(TokenEquals) - case r == '@': - l.emit(TokenData) - case r == '"' || r == '\'': - l.backup() - return lexString - case r == '/' || r == '.': - l.emit(TokenSep) - case r == '|': - l.emit(TokenCloseBlockParams) - case r == '+' || r == '-' || (r >= '0' && r <= '9'): - l.backup() - return lexNumber - case r == '[': - return lexPathLiteral - case strings.IndexRune(unallowedIDChars, r) < 0: - l.backup() - return lexIdentifier - default: - return l.errorf("Unexpected character in expression: '%c'", r) - } - - return lexExpression -} - -// lexComment scans {{!-- or {{! -func lexComment(l *Lexer) lexFunc { - if str := l.findRegexp(l.closeComment); str != "" { - l.pos += len(str) - l.emit(TokenComment) - - return lexContent - } - - if r := l.next(); r == eof { - return l.errorf("Unclosed comment") - } - - return lexComment -} - -// lexIgnorable scans all following ignorable characters -func lexIgnorable(l *Lexer) lexFunc { - for isIgnorable(l.peek()) { - l.next() - } - l.ignore() - - return lexExpression -} - -// lexString scans a string -func lexString(l *Lexer) lexFunc { - // get string delimiter - delim := l.next() - var prev rune - - // ignore delimiter - l.ignore() - - for { - r := l.next() - if r == eof || r == '\n' { - return l.errorf("Unterminated string") - } - - if (r == delim) && (prev != '\\') { - break - } - - prev = r - } - - // remove end delimiter - l.backup() - - // emit string - l.emitString(delim) - - // skip end delimiter - l.next() - l.ignore() - - return lexExpression -} - -// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This -// isn't a perfect number scanner - for instance it accepts "." and "0x0.2" -// and "089" - but when it's wrong the input is invalid and the parser (via -// strconv) will notice. -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/parse/lex.go -func lexNumber(l *Lexer) lexFunc { - if !l.scanNumber() { - return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) - } - if sign := l.peek(); sign == '+' || sign == '-' { - // Complex: 1+2i. No spaces, must end in 'i'. - if !l.scanNumber() || l.input[l.pos-1] != 'i' { - return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) - } - l.emit(TokenNumber) - } else { - l.emit(TokenNumber) - } - return lexExpression -} - -// scanNumber scans a number -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/parse/lex.go -func (l *Lexer) scanNumber() bool { - // Optional leading sign. - l.accept("+-") - - // Is it hex? - digits := "0123456789" - - if l.accept("0") && l.accept("xX") { - digits = "0123456789abcdefABCDEF" - } - - l.acceptRun(digits) - - if l.accept(".") { - l.acceptRun(digits) - } - - if l.accept("eE") { - l.accept("+-") - l.acceptRun("0123456789") - } - - // Is it imaginary? - l.accept("i") - - // Next thing mustn't be alphanumeric. - if isAlphaNumeric(l.peek()) { - l.next() - return false - } - - return true -} - -// lexIdentifier scans an ID -func lexIdentifier(l *Lexer) lexFunc { - str := l.findRegexp(rID) - if len(str) == 0 { - // this is rotten - panic("Identifier expected") - } - - l.pos += len(str) - l.emit(TokenID) - - return lexExpression -} - -// lexPathLiteral scans an [ID] -func lexPathLiteral(l *Lexer) lexFunc { - for { - r := l.next() - if r == eof || r == '\n' { - return l.errorf("Unterminated path literal") - } - - if r == ']' { - break - } - } - - l.emit(TokenID) - - return lexExpression -} - -// isIgnorable returns true if given character is ignorable (ie. whitespace of line feed) -func isIgnorable(r rune) bool { - return r == ' ' || r == '\t' || r == '\n' -} - -// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. -// -// NOTE borrowed from https://github.com/golang/go/tree/master/src/text/template/parse/lex.go -func isAlphaNumeric(r rune) bool { - return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) -} diff --git a/vendor/github.com/aymerick/raymond/lexer/lexer_test.go b/vendor/github.com/aymerick/raymond/lexer/lexer_test.go deleted file mode 100644 index 71e8bf0..0000000 --- a/vendor/github.com/aymerick/raymond/lexer/lexer_test.go +++ /dev/null @@ -1,541 +0,0 @@ -package lexer - -import ( - "fmt" - "testing" -) - -type lexTest struct { - name string - input string - tokens []Token -} - -// helpers -func tokContent(val string) Token { return Token{TokenContent, val, 0, 1} } -func tokID(val string) Token { return Token{TokenID, val, 0, 1} } -func tokSep(val string) Token { return Token{TokenSep, val, 0, 1} } -func tokString(val string) Token { return Token{TokenString, val, 0, 1} } -func tokNumber(val string) Token { return Token{TokenNumber, val, 0, 1} } -func tokInverse(val string) Token { return Token{TokenInverse, val, 0, 1} } -func tokBool(val string) Token { return Token{TokenBoolean, val, 0, 1} } -func tokError(val string) Token { return Token{TokenError, val, 0, 1} } -func tokComment(val string) Token { return Token{TokenComment, val, 0, 1} } - -var tokEOF = Token{TokenEOF, "", 0, 1} -var tokEquals = Token{TokenEquals, "=", 0, 1} -var tokData = Token{TokenData, "@", 0, 1} -var tokOpen = Token{TokenOpen, "{{", 0, 1} -var tokOpenAmp = Token{TokenOpen, "{{&", 0, 1} -var tokOpenPartial = Token{TokenOpenPartial, "{{>", 0, 1} -var tokClose = Token{TokenClose, "}}", 0, 1} -var tokOpenStrip = Token{TokenOpen, "{{~", 0, 1} -var tokCloseStrip = Token{TokenClose, "~}}", 0, 1} -var tokOpenUnescaped = Token{TokenOpenUnescaped, "{{{", 0, 1} -var tokCloseUnescaped = Token{TokenCloseUnescaped, "}}}", 0, 1} -var tokOpenUnescapedStrip = Token{TokenOpenUnescaped, "{{~{", 0, 1} -var tokCloseUnescapedStrip = Token{TokenCloseUnescaped, "}~}}", 0, 1} -var tokOpenBlock = Token{TokenOpenBlock, "{{#", 0, 1} -var tokOpenEndBlock = Token{TokenOpenEndBlock, "{{/", 0, 1} -var tokOpenInverse = Token{TokenOpenInverse, "{{^", 0, 1} -var tokOpenInverseChain = Token{TokenOpenInverseChain, "{{else", 0, 1} -var tokOpenSexpr = Token{TokenOpenSexpr, "(", 0, 1} -var tokCloseSexpr = Token{TokenCloseSexpr, ")", 0, 1} -var tokOpenBlockParams = Token{TokenOpenBlockParams, "as |", 0, 1} -var tokCloseBlockParams = Token{TokenCloseBlockParams, "|", 0, 1} -var tokOpenRawBlock = Token{TokenOpenRawBlock, "{{{{", 0, 1} -var tokCloseRawBlock = Token{TokenCloseRawBlock, "}}}}", 0, 1} -var tokOpenEndRawBlock = Token{TokenOpenEndRawBlock, "{{{{/", 0, 1} - -var lexTests = []lexTest{ - {"empty", "", []Token{tokEOF}}, - {"spaces", " \t\n", []Token{tokContent(" \t\n"), tokEOF}}, - {"content", `now is the time`, []Token{tokContent(`now is the time`), tokEOF}}, - - { - `does not tokenizes identifier starting with true as boolean`, - `{{ foo truebar }}`, - []Token{tokOpen, tokID("foo"), tokID("truebar"), tokClose, tokEOF}, - }, - { - `does not tokenizes identifier starting with false as boolean`, - `{{ foo falsebar }}`, - []Token{tokOpen, tokID("foo"), tokID("falsebar"), tokClose, tokEOF}, - }, - { - `tokenizes raw block`, - `{{{{foo}}}} {{{{/foo}}}}`, - []Token{tokOpenRawBlock, tokID("foo"), tokCloseRawBlock, tokContent(" "), tokOpenEndRawBlock, tokID("foo"), tokCloseRawBlock, tokEOF}, - }, - { - `tokenizes raw block with mustaches in content`, - `{{{{foo}}}}{{bar}}{{{{/foo}}}}`, - []Token{tokOpenRawBlock, tokID("foo"), tokCloseRawBlock, tokContent("{{bar}}"), tokOpenEndRawBlock, tokID("foo"), tokCloseRawBlock, tokEOF}, - }, - { - `tokenizes @../foo`, - `{{@../foo}}`, - []Token{tokOpen, tokData, tokID(".."), tokSep("/"), tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes escaped mustaches`, - "\\{{bar}}", - []Token{tokContent("{{bar}}"), tokEOF}, - }, - { - `tokenizes strip mustaches`, - `{{~ foo ~}}`, - []Token{tokOpenStrip, tokID("foo"), tokCloseStrip, tokEOF}, - }, - { - `tokenizes unescaped strip mustaches`, - `{{~{ foo }~}}`, - []Token{tokOpenUnescapedStrip, tokID("foo"), tokCloseUnescapedStrip, tokEOF}, - }, - - // - // Next tests come from: - // https://github.com/wycats/handlebars.js/blob/master/spec/tokenizer.js - // - { - `tokenizes a simple mustache as "OPEN ID CLOSE"`, - `{{foo}}`, - []Token{tokOpen, tokID("foo"), tokClose, tokEOF}, - }, - { - `supports unescaping with &`, - `{{&bar}}`, - []Token{tokOpenAmp, tokID("bar"), tokClose, tokEOF}, - }, - { - `supports unescaping with {{{`, - `{{{bar}}}`, - []Token{tokOpenUnescaped, tokID("bar"), tokCloseUnescaped, tokEOF}, - }, - { - `supports escaping delimiters`, - "{{foo}} \\{{bar}} {{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" "), tokContent("{{bar}} "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `supports escaping multiple delimiters`, - "{{foo}} \\{{bar}} \\{{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" "), tokContent("{{bar}} "), tokContent("{{baz}}"), tokEOF}, - }, - { - `supports escaping a triple stash`, - "{{foo}} \\{{{bar}}} {{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" "), tokContent("{{{bar}}} "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `supports escaping escape character`, - "{{foo}} \\\\{{bar}} {{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" \\"), tokOpen, tokID("bar"), tokClose, tokContent(" "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `supports escaping multiple escape characters`, - "{{foo}} \\\\{{bar}} \\\\{{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" \\"), tokOpen, tokID("bar"), tokClose, tokContent(" \\"), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `supports escaped mustaches after escaped escape characters`, - "{{foo}} \\\\{{bar}} \\{{baz}}", - // NOTE: JS implementation returns: - // ['OPEN', 'ID', 'CLOSE', 'CONTENT', 'OPEN', 'ID', 'CLOSE', 'CONTENT', 'CONTENT', 'CONTENT'], - // WTF is the last CONTENT ? - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" \\"), tokOpen, tokID("bar"), tokClose, tokContent(" "), tokContent("{{baz}}"), tokEOF}, - }, - { - `supports escaped escape characters after escaped mustaches`, - "{{foo}} \\{{bar}} \\\\{{baz}}", - // NOTE: JS implementation returns: - // []Token{tokOpen, tokID("foo"), tokClose, tokContent(" "), tokContent("{{bar}} "), tokContent("\\"), tokOpen, tokID("baz"), tokClose, tokEOF}, - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" "), tokContent("{{bar}} \\"), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `supports escaped escape character on a triple stash`, - "{{foo}} \\\\{{{bar}}} {{baz}}", - []Token{tokOpen, tokID("foo"), tokClose, tokContent(" \\"), tokOpenUnescaped, tokID("bar"), tokCloseUnescaped, tokContent(" "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes a simple path`, - `{{foo/bar}}`, - []Token{tokOpen, tokID("foo"), tokSep("/"), tokID("bar"), tokClose, tokEOF}, - }, - { - `allows dot notation (1)`, - `{{foo.bar}}`, - []Token{tokOpen, tokID("foo"), tokSep("."), tokID("bar"), tokClose, tokEOF}, - }, - { - `allows dot notation (2)`, - `{{foo.bar.baz}}`, - []Token{tokOpen, tokID("foo"), tokSep("."), tokID("bar"), tokSep("."), tokID("baz"), tokClose, tokEOF}, - }, - { - `allows path literals with []`, - `{{foo.[bar]}}`, - []Token{tokOpen, tokID("foo"), tokSep("."), tokID("[bar]"), tokClose, tokEOF}, - }, - { - `allows multiple path literals on a line with []`, - `{{foo.[bar]}}{{foo.[baz]}}`, - []Token{tokOpen, tokID("foo"), tokSep("."), tokID("[bar]"), tokClose, tokOpen, tokID("foo"), tokSep("."), tokID("[baz]"), tokClose, tokEOF}, - }, - { - `tokenizes {{.}} as OPEN ID CLOSE`, - `{{.}}`, - []Token{tokOpen, tokID("."), tokClose, tokEOF}, - }, - { - `tokenizes a path as "OPEN (ID SEP)* ID CLOSE"`, - `{{../foo/bar}}`, - []Token{tokOpen, tokID(".."), tokSep("/"), tokID("foo"), tokSep("/"), tokID("bar"), tokClose, tokEOF}, - }, - { - `tokenizes a path with .. as a parent path`, - `{{../foo.bar}}`, - []Token{tokOpen, tokID(".."), tokSep("/"), tokID("foo"), tokSep("."), tokID("bar"), tokClose, tokEOF}, - }, - { - `tokenizes a path with this/foo as OPEN ID SEP ID CLOSE`, - `{{this/foo}}`, - []Token{tokOpen, tokID("this"), tokSep("/"), tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes a simple mustache with spaces as "OPEN ID CLOSE"`, - `{{ foo }}`, - []Token{tokOpen, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes a simple mustache with line breaks as "OPEN ID ID CLOSE"`, - "{{ foo \n bar }}", - []Token{tokOpen, tokID("foo"), tokID("bar"), tokClose, tokEOF}, - }, - { - `tokenizes raw content as "CONTENT"`, - `foo {{ bar }} baz`, - []Token{tokContent("foo "), tokOpen, tokID("bar"), tokClose, tokContent(" baz"), tokEOF}, - }, - { - `tokenizes a partial as "OPEN_PARTIAL ID CLOSE"`, - `{{> foo}}`, - []Token{tokOpenPartial, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes a partial with context as "OPEN_PARTIAL ID ID CLOSE"`, - `{{> foo bar }}`, - []Token{tokOpenPartial, tokID("foo"), tokID("bar"), tokClose, tokEOF}, - }, - { - `tokenizes a partial without spaces as "OPEN_PARTIAL ID CLOSE"`, - `{{>foo}}`, - []Token{tokOpenPartial, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes a partial space at the }); as "OPEN_PARTIAL ID CLOSE"`, - `{{>foo }}`, - []Token{tokOpenPartial, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes a partial space at the }); as "OPEN_PARTIAL ID CLOSE"`, - `{{>foo/bar.baz }}`, - []Token{tokOpenPartial, tokID("foo"), tokSep("/"), tokID("bar"), tokSep("."), tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes a comment as "COMMENT"`, - `foo {{! this is a comment }} bar {{ baz }}`, - []Token{tokContent("foo "), tokComment("{{! this is a comment }}"), tokContent(" bar "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes a block comment as "COMMENT"`, - `foo {{!-- this is a {{comment}} --}} bar {{ baz }}`, - []Token{tokContent("foo "), tokComment("{{!-- this is a {{comment}} --}}"), tokContent(" bar "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes a block comment with whitespace as "COMMENT"`, - "foo {{!-- this is a\n{{comment}}\n--}} bar {{ baz }}", - []Token{tokContent("foo "), tokComment("{{!-- this is a\n{{comment}}\n--}}"), tokContent(" bar "), tokOpen, tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes open and closing blocks as OPEN_BLOCK, ID, CLOSE ..., OPEN_ENDBLOCK ID CLOSE`, - `{{#foo}}content{{/foo}}`, - []Token{tokOpenBlock, tokID("foo"), tokClose, tokContent("content"), tokOpenEndBlock, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes inverse sections as "INVERSE"`, - `{{^}}`, - []Token{tokInverse("{{^}}"), tokEOF}, - }, - { - `tokenizes inverse sections as "INVERSE" with alternate format`, - `{{else}}`, - []Token{tokInverse("{{else}}"), tokEOF}, - }, - { - `tokenizes inverse sections as "INVERSE" with spaces`, - `{{ else }}`, - []Token{tokInverse("{{ else }}"), tokEOF}, - }, - { - `tokenizes inverse sections with ID as "OPEN_INVERSE ID CLOSE"`, - `{{^foo}}`, - []Token{tokOpenInverse, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes inverse sections with ID and spaces as "OPEN_INVERSE ID CLOSE"`, - `{{^ foo }}`, - []Token{tokOpenInverse, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes mustaches with params as "OPEN ID ID ID CLOSE"`, - `{{ foo bar baz }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes mustaches with String params as "OPEN ID ID STRING CLOSE"`, - `{{ foo bar "baz" }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokString("baz"), tokClose, tokEOF}, - }, - { - `tokenizes mustaches with String params using single quotes as "OPEN ID ID STRING CLOSE"`, - `{{ foo bar 'baz' }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokString("baz"), tokClose, tokEOF}, - }, - { - `tokenizes String params with spaces inside as "STRING"`, - `{{ foo bar "baz bat" }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokString("baz bat"), tokClose, tokEOF}, - }, - { - `tokenizes String params with escapes quotes as STRING`, - `{{ foo "bar\"baz" }}`, - []Token{tokOpen, tokID("foo"), tokString(`bar"baz`), tokClose, tokEOF}, - }, - { - `tokenizes String params using single quotes with escapes quotes as STRING`, - `{{ foo 'bar\'baz' }}`, - []Token{tokOpen, tokID("foo"), tokString(`bar'baz`), tokClose, tokEOF}, - }, - { - `tokenizes numbers`, - `{{ foo 1 }}`, - []Token{tokOpen, tokID("foo"), tokNumber("1"), tokClose, tokEOF}, - }, - { - `tokenizes floats`, - `{{ foo 1.1 }}`, - []Token{tokOpen, tokID("foo"), tokNumber("1.1"), tokClose, tokEOF}, - }, - { - `tokenizes negative numbers`, - `{{ foo -1 }}`, - []Token{tokOpen, tokID("foo"), tokNumber("-1"), tokClose, tokEOF}, - }, - { - `tokenizes negative floats`, - `{{ foo -1.1 }}`, - []Token{tokOpen, tokID("foo"), tokNumber("-1.1"), tokClose, tokEOF}, - }, - { - `tokenizes boolean true`, - `{{ foo true }}`, - []Token{tokOpen, tokID("foo"), tokBool("true"), tokClose, tokEOF}, - }, - { - `tokenizes boolean false`, - `{{ foo false }}`, - []Token{tokOpen, tokID("foo"), tokBool("false"), tokClose, tokEOF}, - }, - // SKIP: 'tokenizes undefined and null' - { - `tokenizes hash arguments (1)`, - `{{ foo bar=baz }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokEquals, tokID("baz"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (2)`, - `{{ foo bar baz=bat }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokID("bat"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (3)`, - `{{ foo bar baz=1 }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokNumber("1"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (4)`, - `{{ foo bar baz=true }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokBool("true"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (5)`, - `{{ foo bar baz=false }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokBool("false"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (6)`, - "{{ foo bar\n baz=bat }}", - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokID("bat"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (7)`, - `{{ foo bar baz="bat" }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokString("bat"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (8)`, - `{{ foo bar baz="bat" bam=wot }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokID("baz"), tokEquals, tokString("bat"), tokID("bam"), tokEquals, tokID("wot"), tokClose, tokEOF}, - }, - { - `tokenizes hash arguments (9)`, - `{{foo omg bar=baz bat="bam"}}`, - []Token{tokOpen, tokID("foo"), tokID("omg"), tokID("bar"), tokEquals, tokID("baz"), tokID("bat"), tokEquals, tokString("bam"), tokClose, tokEOF}, - }, - { - `tokenizes special @ identifiers (1)`, - `{{ @foo }}`, - []Token{tokOpen, tokData, tokID("foo"), tokClose, tokEOF}, - }, - { - `tokenizes special @ identifiers (2)`, - `{{ foo @bar }}`, - []Token{tokOpen, tokID("foo"), tokData, tokID("bar"), tokClose, tokEOF}, - }, - { - `tokenizes special @ identifiers (3)`, - `{{ foo bar=@baz }}`, - []Token{tokOpen, tokID("foo"), tokID("bar"), tokEquals, tokData, tokID("baz"), tokClose, tokEOF}, - }, - { - `does not time out in a mustache with a single } followed by EOF`, - `{{foo}`, - []Token{tokOpen, tokID("foo"), tokError("Unexpected character in expression: '}'")}, - }, - { - `does not time out in a mustache when invalid ID characters are used`, - `{{foo & }}`, - []Token{tokOpen, tokID("foo"), tokError("Unexpected character in expression: '&'")}, - }, - { - `tokenizes subexpressions (1)`, - `{{foo (bar)}}`, - []Token{tokOpen, tokID("foo"), tokOpenSexpr, tokID("bar"), tokCloseSexpr, tokClose, tokEOF}, - }, - { - `tokenizes subexpressions (2)`, - `{{foo (a-x b-y)}}`, - []Token{tokOpen, tokID("foo"), tokOpenSexpr, tokID("a-x"), tokID("b-y"), tokCloseSexpr, tokClose, tokEOF}, - }, - { - `tokenizes nested subexpressions`, - `{{foo (bar (lol rofl)) (baz)}}`, - []Token{tokOpen, tokID("foo"), tokOpenSexpr, tokID("bar"), tokOpenSexpr, tokID("lol"), tokID("rofl"), tokCloseSexpr, tokCloseSexpr, tokOpenSexpr, tokID("baz"), tokCloseSexpr, tokClose, tokEOF}, - }, - { - `tokenizes nested subexpressions: literals`, - `{{foo (bar (lol true) false) (baz 1) (blah 'b') (blorg "c")}}`, - []Token{tokOpen, tokID("foo"), tokOpenSexpr, tokID("bar"), tokOpenSexpr, tokID("lol"), tokBool("true"), tokCloseSexpr, tokBool("false"), tokCloseSexpr, tokOpenSexpr, tokID("baz"), tokNumber("1"), tokCloseSexpr, tokOpenSexpr, tokID("blah"), tokString("b"), tokCloseSexpr, tokOpenSexpr, tokID("blorg"), tokString("c"), tokCloseSexpr, tokClose, tokEOF}, - }, - { - `tokenizes block params (1)`, - `{{#foo as |bar|}}`, - []Token{tokOpenBlock, tokID("foo"), tokOpenBlockParams, tokID("bar"), tokCloseBlockParams, tokClose, tokEOF}, - }, - { - `tokenizes block params (2)`, - `{{#foo as |bar baz|}}`, - []Token{tokOpenBlock, tokID("foo"), tokOpenBlockParams, tokID("bar"), tokID("baz"), tokCloseBlockParams, tokClose, tokEOF}, - }, - { - `tokenizes block params (3)`, - `{{#foo as | bar baz |}}`, - []Token{tokOpenBlock, tokID("foo"), tokOpenBlockParams, tokID("bar"), tokID("baz"), tokCloseBlockParams, tokClose, tokEOF}, - }, - { - `tokenizes block params (4)`, - `{{#foo as as | bar baz |}}`, - []Token{tokOpenBlock, tokID("foo"), tokID("as"), tokOpenBlockParams, tokID("bar"), tokID("baz"), tokCloseBlockParams, tokClose, tokEOF}, - }, - { - `tokenizes block params (5)`, - `{{else foo as |bar baz|}}`, - []Token{tokOpenInverseChain, tokID("foo"), tokOpenBlockParams, tokID("bar"), tokID("baz"), tokCloseBlockParams, tokClose, tokEOF}, - }, -} - -func collect(t *lexTest) []Token { - var result []Token - - l := scanWithName(t.input, t.name) - for { - token := l.NextToken() - result = append(result, token) - - if token.Kind == TokenEOF || token.Kind == TokenError { - break - } - } - - return result -} - -func equal(i1, i2 []Token, checkPos bool) bool { - if len(i1) != len(i2) { - return false - } - - for k := range i1 { - if i1[k].Kind != i2[k].Kind { - return false - } - - if checkPos && i1[k].Pos != i2[k].Pos { - return false - } - - if i1[k].Val != i2[k].Val { - return false - } - } - - return true -} - -func TestLexer(t *testing.T) { - t.Parallel() - - for _, test := range lexTests { - tokens := collect(&test) - if !equal(tokens, test.tokens, false) { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\nexpected\n\t%v\ngot\n\t%+v\n", test.name, test.input, test.tokens, tokens) - } - } -} - -// @todo Test errors: -// `{{{{raw foo` - -// package example -func Example() { - source := "You know {{nothing}} John Snow" - - output := "" - - lex := Scan(source) - for { - // consume next token - token := lex.NextToken() - - output += fmt.Sprintf(" %s", token) - - // stops when all tokens have been consumed, or on error - if token.Kind == TokenEOF || token.Kind == TokenError { - break - } - } - - fmt.Print(output) - // Output: Content{"You know "} Open{"{{"} ID{"nothing"} Close{"}}"} Content{" John Snow"} EOF -} diff --git a/vendor/github.com/aymerick/raymond/lexer/token.go b/vendor/github.com/aymerick/raymond/lexer/token.go deleted file mode 100644 index 13cf2e6..0000000 --- a/vendor/github.com/aymerick/raymond/lexer/token.go +++ /dev/null @@ -1,183 +0,0 @@ -package lexer - -import "fmt" - -const ( - // TokenError represents an error - TokenError TokenKind = iota - - // TokenEOF represents an End Of File - TokenEOF - - // - // Mustache delimiters - // - - // TokenOpen is the OPEN token - TokenOpen - - // TokenClose is the CLOSE token - TokenClose - - // TokenOpenRawBlock is the OPEN_RAW_BLOCK token - TokenOpenRawBlock - - // TokenCloseRawBlock is the CLOSE_RAW_BLOCK token - TokenCloseRawBlock - - // TokenOpenEndRawBlock is the END_RAW_BLOCK token - TokenOpenEndRawBlock - - // TokenOpenUnescaped is the OPEN_UNESCAPED token - TokenOpenUnescaped - - // TokenCloseUnescaped is the CLOSE_UNESCAPED token - TokenCloseUnescaped - - // TokenOpenBlock is the OPEN_BLOCK token - TokenOpenBlock - - // TokenOpenEndBlock is the OPEN_ENDBLOCK token - TokenOpenEndBlock - - // TokenInverse is the INVERSE token - TokenInverse - - // TokenOpenInverse is the OPEN_INVERSE token - TokenOpenInverse - - // TokenOpenInverseChain is the OPEN_INVERSE_CHAIN token - TokenOpenInverseChain - - // TokenOpenPartial is the OPEN_PARTIAL token - TokenOpenPartial - - // TokenComment is the COMMENT token - TokenComment - - // - // Inside mustaches - // - - // TokenOpenSexpr is the OPEN_SEXPR token - TokenOpenSexpr - - // TokenCloseSexpr is the CLOSE_SEXPR token - TokenCloseSexpr - - // TokenEquals is the EQUALS token - TokenEquals - - // TokenData is the DATA token - TokenData - - // TokenSep is the SEP token - TokenSep - - // TokenOpenBlockParams is the OPEN_BLOCK_PARAMS token - TokenOpenBlockParams - - // TokenCloseBlockParams is the CLOSE_BLOCK_PARAMS token - TokenCloseBlockParams - - // - // Tokens with content - // - - // TokenContent is the CONTENT token - TokenContent - - // TokenID is the ID token - TokenID - - // TokenString is the STRING token - TokenString - - // TokenNumber is the NUMBER token - TokenNumber - - // TokenBoolean is the BOOLEAN token - TokenBoolean -) - -const ( - // Option to generate token position in its string representation - dumpTokenPos = false - - // Option to generate values for all token kinds for their string representations - dumpAllTokensVal = true -) - -// TokenKind represents a Token type. -type TokenKind int - -// Token represents a scanned token. -type Token struct { - Kind TokenKind // Token kind - Val string // Token value - - Pos int // Byte position in input string - Line int // Line number in input string -} - -// tokenName permits to display token name given token type -var tokenName = map[TokenKind]string{ - TokenError: "Error", - TokenEOF: "EOF", - TokenContent: "Content", - TokenComment: "Comment", - TokenOpen: "Open", - TokenClose: "Close", - TokenOpenUnescaped: "OpenUnescaped", - TokenCloseUnescaped: "CloseUnescaped", - TokenOpenBlock: "OpenBlock", - TokenOpenEndBlock: "OpenEndBlock", - TokenOpenRawBlock: "OpenRawBlock", - TokenCloseRawBlock: "CloseRawBlock", - TokenOpenEndRawBlock: "OpenEndRawBlock", - TokenOpenBlockParams: "OpenBlockParams", - TokenCloseBlockParams: "CloseBlockParams", - TokenInverse: "Inverse", - TokenOpenInverse: "OpenInverse", - TokenOpenInverseChain: "OpenInverseChain", - TokenOpenPartial: "OpenPartial", - TokenOpenSexpr: "OpenSexpr", - TokenCloseSexpr: "CloseSexpr", - TokenID: "ID", - TokenEquals: "Equals", - TokenString: "String", - TokenNumber: "Number", - TokenBoolean: "Boolean", - TokenData: "Data", - TokenSep: "Sep", -} - -// String returns the token kind string representation for debugging. -func (k TokenKind) String() string { - s := tokenName[k] - if s == "" { - return fmt.Sprintf("Token-%d", int(k)) - } - return s -} - -// String returns the token string representation for debugging. -func (t Token) String() string { - result := "" - - if dumpTokenPos { - result += fmt.Sprintf("%d:", t.Pos) - } - - result += fmt.Sprintf("%s", t.Kind) - - if (dumpAllTokensVal || (t.Kind >= TokenContent)) && len(t.Val) > 0 { - if len(t.Val) > 100 { - result += fmt.Sprintf("{%.20q...}", t.Val) - } else { - result += fmt.Sprintf("{%q}", t.Val) - } - } - - return result -} diff --git a/vendor/github.com/aymerick/raymond/mustache_test.go b/vendor/github.com/aymerick/raymond/mustache_test.go deleted file mode 100644 index fadced5..0000000 --- a/vendor/github.com/aymerick/raymond/mustache_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package raymond - -import ( - "io/ioutil" - "path" - "regexp" - "strings" - "testing" - - "gopkg.in/yaml.v2" -) - -// -// Note, as the JS implementation, the divergences from mustache spec: -// - we don't support alternative delimeters -// - the mustache lambda spec differs -// - -type mustacheTest struct { - Name string - Desc string - Data interface{} - Template string - Expected string - Partials map[string]string -} - -type mustacheTestFile struct { - Overview string - Tests []mustacheTest -} - -var ( - rAltDelim = regexp.MustCompile(regexp.QuoteMeta("{{=")) -) - -var ( - musTestLambdaInterMult = 0 -) - -func TestMustache(t *testing.T) { - skipFiles := map[string]bool{ - // mustache lambdas differ from handlebars lambdas - "~lambdas.yml": true, - } - - for _, fileName := range mustacheTestFiles() { - if skipFiles[fileName] { - // fmt.Printf("Skipped file: %s\n", fileName) - continue - } - - launchTests(t, testsFromMustacheFile(fileName)) - } -} - -func testsFromMustacheFile(fileName string) []Test { - result := []Test{} - - fileData, err := ioutil.ReadFile(path.Join("mustache", "specs", fileName)) - if err != nil { - panic(err) - } - - var testFile mustacheTestFile - if err := yaml.Unmarshal(fileData, &testFile); err != nil { - panic(err) - } - - for _, mustacheTest := range testFile.Tests { - if mustBeSkipped(mustacheTest, fileName) { - // fmt.Printf("Skipped test: %s\n", mustacheTest.Name) - continue - } - - test := Test{ - name: mustacheTest.Name, - input: mustacheTest.Template, - data: mustacheTest.Data, - partials: mustacheTest.Partials, - output: mustacheTest.Expected, - } - - result = append(result, test) - } - - return result -} - -// returns true if test must be skipped -func mustBeSkipped(test mustacheTest, fileName string) bool { - // handlebars does not support alternative delimiters - return haveAltDelimiter(test) || - // the JS implementation skips those tests - fileName == "partials.yml" && (test.Name == "Failed Lookup" || test.Name == "Standalone Indentation") -} - -// returns true if test have alternative delimeter in template or in partials -func haveAltDelimiter(test mustacheTest) bool { - // check template - if rAltDelim.MatchString(test.Template) { - return true - } - - // check partials - for _, partial := range test.Partials { - if rAltDelim.MatchString(partial) { - return true - } - } - - return false -} - -func mustacheTestFiles() []string { - var result []string - - files, err := ioutil.ReadDir(path.Join("mustache", "specs")) - if err != nil { - panic(err) - } - - for _, file := range files { - fileName := file.Name() - - if !file.IsDir() && strings.HasSuffix(fileName, ".yml") { - result = append(result, fileName) - } - } - - return result -} - -// -// Following tests come fron ~lambdas.yml -// - -var mustacheLambdasTests = []Test{ - { - "Interpolation", - "Hello, {{lambda}}!", - map[string]interface{}{"lambda": func() string { return "world" }}, - nil, nil, nil, - "Hello, world!", - }, - - // // SKIP: lambda return value is not parsed - // { - // "Interpolation - Expansion", - // "Hello, {{lambda}}!", - // map[string]interface{}{"lambda": func() string { return "{{planet}}" }}, - // nil, nil, nil, - // "Hello, world!", - // }, - - // SKIP "Interpolation - Alternate Delimiters" - - { - "Interpolation - Multiple Calls", - "{{lambda}} == {{{lambda}}} == {{lambda}}", - map[string]interface{}{"lambda": func() string { - musTestLambdaInterMult++ - return Str(musTestLambdaInterMult) - }}, - nil, nil, nil, - "1 == 2 == 3", - }, - - { - "Escaping", - "<{{lambda}}{{{lambda}}}", - map[string]interface{}{"lambda": func() string { return ">" }}, - nil, nil, nil, - "<>>", - }, - - // // SKIP: "Lambdas used for sections should receive the raw section string." - // { - // "Section", - // "<{{#lambda}}{{x}}{{/lambda}}>", - // map[string]interface{}{"lambda": func(param string) string { - // if param == "{{x}}" { - // return "yes" - // } - - // return "false" - // }, "x": "Error!"}, - // nil, nil, nil, - // "", - // }, - - // // SKIP: lambda return value is not parsed - // { - // "Section - Expansion", - // "<{{#lambda}}-{{/lambda}}>", - // map[string]interface{}{"lambda": func(param string) string { - // return param + "{{planet}}" + param - // }, "planet": "Earth"}, - // nil, nil, nil, - // "<-Earth->", - // }, - - // SKIP: "Section - Alternate Delimiters" - - { - "Section - Multiple Calls", - "{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}", - map[string]interface{}{"lambda": func(options *Options) string { - return "__" + options.Fn() + "__" - }}, - nil, nil, nil, - "__FILE__ != __LINE__", - }, - - // // SKIP: "Lambdas used for inverted sections should be considered truthy." - // { - // "Inverted Section", - // "<{{^lambda}}{{static}}{{/lambda}}>", - // map[string]interface{}{ - // "lambda": func() interface{} { - // return false - // }, - // "static": "static", - // }, - // nil, nil, nil, - // "<>", - // }, -} - -func TestMustacheLambdas(t *testing.T) { - t.Parallel() - - launchTests(t, mustacheLambdasTests) -} diff --git a/vendor/github.com/aymerick/raymond/parser/parser.go b/vendor/github.com/aymerick/raymond/parser/parser.go deleted file mode 100644 index 22eed3c..0000000 --- a/vendor/github.com/aymerick/raymond/parser/parser.go +++ /dev/null @@ -1,846 +0,0 @@ -// Package parser provides a handlebars syntax analyser. It consumes the tokens provided by the lexer to build an AST. -package parser - -import ( - "fmt" - "regexp" - "runtime" - "strconv" - - "github.com/aymerick/raymond/ast" - "github.com/aymerick/raymond/lexer" -) - -// References: -// - https://github.com/wycats/handlebars.js/blob/master/src/handlebars.yy -// - https://github.com/golang/go/blob/master/src/text/template/parse/parse.go - -// parser is a syntax analyzer. -type parser struct { - // Lexer - lex *lexer.Lexer - - // Root node - root ast.Node - - // Tokens parsed but not consumed yet - tokens []*lexer.Token - - // All tokens have been retreieved from lexer - lexOver bool -} - -var ( - rOpenComment = regexp.MustCompile(`^\{\{~?!-?-?`) - rCloseComment = regexp.MustCompile(`-?-?~?\}\}$`) - rOpenAmp = regexp.MustCompile(`^\{\{~?&`) -) - -// new instanciates a new parser -func new(input string) *parser { - return &parser{ - lex: lexer.Scan(input), - } -} - -// Parse analyzes given input and returns the AST root node. -func Parse(input string) (result *ast.Program, err error) { - // recover error - defer errRecover(&err) - - parser := new(input) - - // parse - result = parser.parseProgram() - - // check last token - token := parser.shift() - if token.Kind != lexer.TokenEOF { - // Parsing ended before EOF - errToken(token, "Syntax error") - } - - // fix whitespaces - processWhitespaces(result) - - // named returned values - return -} - -// errRecover recovers parsing panic -func errRecover(errp *error) { - e := recover() - if e != nil { - switch err := e.(type) { - case runtime.Error: - panic(e) - case error: - *errp = err - default: - panic(e) - } - } -} - -// errPanic panics -func errPanic(err error, line int) { - panic(fmt.Errorf("Parse error on line %d:\n%s", line, err)) -} - -// errNode panics with given node infos -func errNode(node ast.Node, msg string) { - errPanic(fmt.Errorf("%s\nNode: %s", msg, node), node.Location().Line) -} - -// errNode panics with given Token infos -func errToken(tok *lexer.Token, msg string) { - errPanic(fmt.Errorf("%s\nToken: %s", msg, tok), tok.Line) -} - -// errNode panics because of an unexpected Token kind -func errExpected(expect lexer.TokenKind, tok *lexer.Token) { - errPanic(fmt.Errorf("Expecting %s, got: '%s'", expect, tok), tok.Line) -} - -// program : statement* -func (p *parser) parseProgram() *ast.Program { - result := ast.NewProgram(p.next().Pos, p.next().Line) - - for p.isStatement() { - result.AddStatement(p.parseStatement()) - } - - return result -} - -// statement : mustache | block | rawBlock | partial | content | COMMENT -func (p *parser) parseStatement() ast.Node { - var result ast.Node - - tok := p.next() - - switch tok.Kind { - case lexer.TokenOpen, lexer.TokenOpenUnescaped: - // mustache - result = p.parseMustache() - case lexer.TokenOpenBlock: - // block - result = p.parseBlock() - case lexer.TokenOpenInverse: - // block - result = p.parseInverse() - case lexer.TokenOpenRawBlock: - // rawBlock - result = p.parseRawBlock() - case lexer.TokenOpenPartial: - // partial - result = p.parsePartial() - case lexer.TokenContent: - // content - result = p.parseContent() - case lexer.TokenComment: - // COMMENT - result = p.parseComment() - } - - return result -} - -// isStatement returns true if next token starts a statement -func (p *parser) isStatement() bool { - if !p.have(1) { - return false - } - - switch p.next().Kind { - case lexer.TokenOpen, lexer.TokenOpenUnescaped, lexer.TokenOpenBlock, - lexer.TokenOpenInverse, lexer.TokenOpenRawBlock, lexer.TokenOpenPartial, - lexer.TokenContent, lexer.TokenComment: - return true - } - - return false -} - -// content : CONTENT -func (p *parser) parseContent() *ast.ContentStatement { - // CONTENT - tok := p.shift() - if tok.Kind != lexer.TokenContent { - // @todo This check can be removed if content is optional in a raw block - errExpected(lexer.TokenContent, tok) - } - - return ast.NewContentStatement(tok.Pos, tok.Line, tok.Val) -} - -// COMMENT -func (p *parser) parseComment() *ast.CommentStatement { - // COMMENT - tok := p.shift() - - value := rOpenComment.ReplaceAllString(tok.Val, "") - value = rCloseComment.ReplaceAllString(value, "") - - result := ast.NewCommentStatement(tok.Pos, tok.Line, value) - result.Strip = ast.NewStripForStr(tok.Val) - - return result -} - -// param* hash? -func (p *parser) parseExpressionParamsHash() ([]ast.Node, *ast.Hash) { - var params []ast.Node - var hash *ast.Hash - - // params* - if p.isParam() { - params = p.parseParams() - } - - // hash? - if p.isHashSegment() { - hash = p.parseHash() - } - - return params, hash -} - -// helperName param* hash? -func (p *parser) parseExpression(tok *lexer.Token) *ast.Expression { - result := ast.NewExpression(tok.Pos, tok.Line) - - // helperName - result.Path = p.parseHelperName() - - // param* hash? - result.Params, result.Hash = p.parseExpressionParamsHash() - - return result -} - -// rawBlock : openRawBlock content endRawBlock -// openRawBlock : OPEN_RAW_BLOCK helperName param* hash? CLOSE_RAW_BLOCK -// endRawBlock : OPEN_END_RAW_BLOCK helperName CLOSE_RAW_BLOCK -func (p *parser) parseRawBlock() *ast.BlockStatement { - // OPEN_RAW_BLOCK - tok := p.shift() - - result := ast.NewBlockStatement(tok.Pos, tok.Line) - - // helperName param* hash? - result.Expression = p.parseExpression(tok) - - openName := result.Expression.Canonical() - - // CLOSE_RAW_BLOCK - tok = p.shift() - if tok.Kind != lexer.TokenCloseRawBlock { - errExpected(lexer.TokenCloseRawBlock, tok) - } - - // content - // @todo Is content mandatory in a raw block ? - content := p.parseContent() - - program := ast.NewProgram(tok.Pos, tok.Line) - program.AddStatement(content) - - result.Program = program - - // OPEN_END_RAW_BLOCK - tok = p.shift() - if tok.Kind != lexer.TokenOpenEndRawBlock { - // should never happen as it is caught by lexer - errExpected(lexer.TokenOpenEndRawBlock, tok) - } - - // helperName - endID := p.parseHelperName() - - closeName, ok := ast.HelperNameStr(endID) - if !ok { - errNode(endID, "Erroneous closing expression") - } - - if openName != closeName { - errNode(endID, fmt.Sprintf("%s doesn't match %s", openName, closeName)) - } - - // CLOSE_RAW_BLOCK - tok = p.shift() - if tok.Kind != lexer.TokenCloseRawBlock { - errExpected(lexer.TokenCloseRawBlock, tok) - } - - return result -} - -// block : openBlock program inverseChain? closeBlock -func (p *parser) parseBlock() *ast.BlockStatement { - // openBlock - result, blockParams := p.parseOpenBlock() - - // program - program := p.parseProgram() - program.BlockParams = blockParams - result.Program = program - - // inverseChain? - if p.isInverseChain() { - result.Inverse = p.parseInverseChain() - } - - // closeBlock - p.parseCloseBlock(result) - - setBlockInverseStrip(result) - - return result -} - -// setBlockInverseStrip is called when parsing `block` (openBlock | openInverse) and `inverseChain` -// -// TODO: This was totally cargo culted ! CHECK THAT ! -// -// cf. prepareBlock() in: -// https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler/helper.js -func setBlockInverseStrip(block *ast.BlockStatement) { - if block.Inverse == nil { - return - } - - if block.Inverse.Chained { - b, _ := block.Inverse.Body[0].(*ast.BlockStatement) - b.CloseStrip = block.CloseStrip - } - - block.InverseStrip = block.Inverse.Strip -} - -// block : openInverse program inverseAndProgram? closeBlock -func (p *parser) parseInverse() *ast.BlockStatement { - // openInverse - result, blockParams := p.parseOpenBlock() - - // program - program := p.parseProgram() - - program.BlockParams = blockParams - result.Inverse = program - - // inverseAndProgram? - if p.isInverse() { - result.Program = p.parseInverseAndProgram() - } - - // closeBlock - p.parseCloseBlock(result) - - setBlockInverseStrip(result) - - return result -} - -// helperName param* hash? blockParams? -func (p *parser) parseOpenBlockExpression(tok *lexer.Token) (*ast.BlockStatement, []string) { - var blockParams []string - - result := ast.NewBlockStatement(tok.Pos, tok.Line) - - // helperName param* hash? - result.Expression = p.parseExpression(tok) - - // blockParams? - if p.isBlockParams() { - blockParams = p.parseBlockParams() - } - - // named returned values - return result, blockParams -} - -// inverseChain : openInverseChain program inverseChain? -// | inverseAndProgram -func (p *parser) parseInverseChain() *ast.Program { - if p.isInverse() { - // inverseAndProgram - return p.parseInverseAndProgram() - } - - result := ast.NewProgram(p.next().Pos, p.next().Line) - - // openInverseChain - block, blockParams := p.parseOpenBlock() - - // program - program := p.parseProgram() - - program.BlockParams = blockParams - block.Program = program - - // inverseChain? - if p.isInverseChain() { - block.Inverse = p.parseInverseChain() - } - - setBlockInverseStrip(block) - - result.Chained = true - result.AddStatement(block) - - return result -} - -// Returns true if current token starts an inverse chain -func (p *parser) isInverseChain() bool { - return p.isOpenInverseChain() || p.isInverse() -} - -// inverseAndProgram : INVERSE program -func (p *parser) parseInverseAndProgram() *ast.Program { - // INVERSE - tok := p.shift() - - // program - result := p.parseProgram() - result.Strip = ast.NewStripForStr(tok.Val) - - return result -} - -// openBlock : OPEN_BLOCK helperName param* hash? blockParams? CLOSE -// openInverse : OPEN_INVERSE helperName param* hash? blockParams? CLOSE -// openInverseChain: OPEN_INVERSE_CHAIN helperName param* hash? blockParams? CLOSE -func (p *parser) parseOpenBlock() (*ast.BlockStatement, []string) { - // OPEN_BLOCK | OPEN_INVERSE | OPEN_INVERSE_CHAIN - tok := p.shift() - - // helperName param* hash? blockParams? - result, blockParams := p.parseOpenBlockExpression(tok) - - // CLOSE - tokClose := p.shift() - if tokClose.Kind != lexer.TokenClose { - errExpected(lexer.TokenClose, tokClose) - } - - result.OpenStrip = ast.NewStrip(tok.Val, tokClose.Val) - - // named returned values - return result, blockParams -} - -// closeBlock : OPEN_ENDBLOCK helperName CLOSE -func (p *parser) parseCloseBlock(block *ast.BlockStatement) { - // OPEN_ENDBLOCK - tok := p.shift() - if tok.Kind != lexer.TokenOpenEndBlock { - errExpected(lexer.TokenOpenEndBlock, tok) - } - - // helperName - endID := p.parseHelperName() - - closeName, ok := ast.HelperNameStr(endID) - if !ok { - errNode(endID, "Erroneous closing expression") - } - - openName := block.Expression.Canonical() - if openName != closeName { - errNode(endID, fmt.Sprintf("%s doesn't match %s", openName, closeName)) - } - - // CLOSE - tokClose := p.shift() - if tokClose.Kind != lexer.TokenClose { - errExpected(lexer.TokenClose, tokClose) - } - - block.CloseStrip = ast.NewStrip(tok.Val, tokClose.Val) -} - -// mustache : OPEN helperName param* hash? CLOSE -// | OPEN_UNESCAPED helperName param* hash? CLOSE_UNESCAPED -func (p *parser) parseMustache() *ast.MustacheStatement { - // OPEN | OPEN_UNESCAPED - tok := p.shift() - - closeToken := lexer.TokenClose - if tok.Kind == lexer.TokenOpenUnescaped { - closeToken = lexer.TokenCloseUnescaped - } - - unescaped := false - if (tok.Kind == lexer.TokenOpenUnescaped) || (rOpenAmp.MatchString(tok.Val)) { - unescaped = true - } - - result := ast.NewMustacheStatement(tok.Pos, tok.Line, unescaped) - - // helperName param* hash? - result.Expression = p.parseExpression(tok) - - // CLOSE | CLOSE_UNESCAPED - tokClose := p.shift() - if tokClose.Kind != closeToken { - errExpected(closeToken, tokClose) - } - - result.Strip = ast.NewStrip(tok.Val, tokClose.Val) - - return result -} - -// partial : OPEN_PARTIAL partialName param* hash? CLOSE -func (p *parser) parsePartial() *ast.PartialStatement { - // OPEN_PARTIAL - tok := p.shift() - - result := ast.NewPartialStatement(tok.Pos, tok.Line) - - // partialName - result.Name = p.parsePartialName() - - // param* hash? - result.Params, result.Hash = p.parseExpressionParamsHash() - - // CLOSE - tokClose := p.shift() - if tokClose.Kind != lexer.TokenClose { - errExpected(lexer.TokenClose, tokClose) - } - - result.Strip = ast.NewStrip(tok.Val, tokClose.Val) - - return result -} - -// helperName | sexpr -func (p *parser) parseHelperNameOrSexpr() ast.Node { - if p.isSexpr() { - // sexpr - return p.parseSexpr() - } - - // helperName - return p.parseHelperName() -} - -// param : helperName | sexpr -func (p *parser) parseParam() ast.Node { - return p.parseHelperNameOrSexpr() -} - -// Returns true if next tokens represent a `param` -func (p *parser) isParam() bool { - return (p.isSexpr() || p.isHelperName()) && !p.isHashSegment() -} - -// param* -func (p *parser) parseParams() []ast.Node { - var result []ast.Node - - for p.isParam() { - result = append(result, p.parseParam()) - } - - return result -} - -// sexpr : OPEN_SEXPR helperName param* hash? CLOSE_SEXPR -func (p *parser) parseSexpr() *ast.SubExpression { - // OPEN_SEXPR - tok := p.shift() - - result := ast.NewSubExpression(tok.Pos, tok.Line) - - // helperName param* hash? - result.Expression = p.parseExpression(tok) - - // CLOSE_SEXPR - tok = p.shift() - if tok.Kind != lexer.TokenCloseSexpr { - errExpected(lexer.TokenCloseSexpr, tok) - } - - return result -} - -// hash : hashSegment+ -func (p *parser) parseHash() *ast.Hash { - var pairs []*ast.HashPair - - for p.isHashSegment() { - pairs = append(pairs, p.parseHashSegment()) - } - - firstLoc := pairs[0].Location() - - result := ast.NewHash(firstLoc.Pos, firstLoc.Line) - result.Pairs = pairs - - return result -} - -// returns true if next tokens represents a `hashSegment` -func (p *parser) isHashSegment() bool { - return p.have(2) && (p.next().Kind == lexer.TokenID) && (p.nextAt(1).Kind == lexer.TokenEquals) -} - -// hashSegment : ID EQUALS param -func (p *parser) parseHashSegment() *ast.HashPair { - // ID - tok := p.shift() - - // EQUALS - p.shift() - - // param - param := p.parseParam() - - result := ast.NewHashPair(tok.Pos, tok.Line) - result.Key = tok.Val - result.Val = param - - return result -} - -// blockParams : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -func (p *parser) parseBlockParams() []string { - var result []string - - // OPEN_BLOCK_PARAMS - tok := p.shift() - - // ID+ - for p.isID() { - result = append(result, p.shift().Val) - } - - if len(result) == 0 { - errExpected(lexer.TokenID, p.next()) - } - - // CLOSE_BLOCK_PARAMS - tok = p.shift() - if tok.Kind != lexer.TokenCloseBlockParams { - errExpected(lexer.TokenCloseBlockParams, tok) - } - - return result -} - -// helperName : path | dataName | STRING | NUMBER | BOOLEAN | UNDEFINED | NULL -func (p *parser) parseHelperName() ast.Node { - var result ast.Node - - tok := p.next() - - switch tok.Kind { - case lexer.TokenBoolean: - // BOOLEAN - p.shift() - result = ast.NewBooleanLiteral(tok.Pos, tok.Line, (tok.Val == "true"), tok.Val) - case lexer.TokenNumber: - // NUMBER - p.shift() - - val, isInt := parseNumber(tok) - result = ast.NewNumberLiteral(tok.Pos, tok.Line, val, isInt, tok.Val) - case lexer.TokenString: - // STRING - p.shift() - result = ast.NewStringLiteral(tok.Pos, tok.Line, tok.Val) - case lexer.TokenData: - // dataName - result = p.parseDataName() - default: - // path - result = p.parsePath(false) - } - - return result -} - -// parseNumber parses a number -func parseNumber(tok *lexer.Token) (result float64, isInt bool) { - var valInt int - var err error - - valInt, err = strconv.Atoi(tok.Val) - if err == nil { - isInt = true - - result = float64(valInt) - } else { - isInt = false - - result, err = strconv.ParseFloat(tok.Val, 64) - if err != nil { - errToken(tok, fmt.Sprintf("Failed to parse number: %s", tok.Val)) - } - } - - // named returned values - return -} - -// Returns true if next tokens represent a `helperName` -func (p *parser) isHelperName() bool { - switch p.next().Kind { - case lexer.TokenBoolean, lexer.TokenNumber, lexer.TokenString, lexer.TokenData, lexer.TokenID: - return true - } - - return false -} - -// partialName : helperName | sexpr -func (p *parser) parsePartialName() ast.Node { - return p.parseHelperNameOrSexpr() -} - -// dataName : DATA pathSegments -func (p *parser) parseDataName() *ast.PathExpression { - // DATA - p.shift() - - // pathSegments - return p.parsePath(true) -} - -// path : pathSegments -// pathSegments : pathSegments SEP ID -// | ID -func (p *parser) parsePath(data bool) *ast.PathExpression { - var tok *lexer.Token - - // ID - tok = p.shift() - if tok.Kind != lexer.TokenID { - errExpected(lexer.TokenID, tok) - } - - result := ast.NewPathExpression(tok.Pos, tok.Line, data) - result.Part(tok.Val) - - for p.isPathSep() { - // SEP - tok = p.shift() - result.Sep(tok.Val) - - // ID - tok = p.shift() - if tok.Kind != lexer.TokenID { - errExpected(lexer.TokenID, tok) - } - - result.Part(tok.Val) - - if len(result.Parts) > 0 { - switch tok.Val { - case "..", ".", "this": - errToken(tok, "Invalid path: "+result.Original) - } - } - } - - return result -} - -// Ensures there is token to parse at given index -func (p *parser) ensure(index int) { - if p.lexOver { - // nothing more to grab - return - } - - nb := index + 1 - - for len(p.tokens) < nb { - // fetch next token - tok := p.lex.NextToken() - - // queue it - p.tokens = append(p.tokens, &tok) - - if (tok.Kind == lexer.TokenEOF) || (tok.Kind == lexer.TokenError) { - p.lexOver = true - break - } - } -} - -// have returns true is there are a list given number of tokens to consume left -func (p *parser) have(nb int) bool { - p.ensure(nb - 1) - - return len(p.tokens) >= nb -} - -// nextAt returns next token at given index, without consuming it -func (p *parser) nextAt(index int) *lexer.Token { - p.ensure(index) - - return p.tokens[index] -} - -// next returns next token without consuming it -func (p *parser) next() *lexer.Token { - return p.nextAt(0) -} - -// shift returns next token and remove it from the tokens buffer -// -// Panics if next token is `TokenError` -func (p *parser) shift() *lexer.Token { - var result *lexer.Token - - p.ensure(0) - - result, p.tokens = p.tokens[0], p.tokens[1:] - - // check error token - if result.Kind == lexer.TokenError { - errToken(result, "Lexer error") - } - - return result -} - -// isToken returns true if next token is of given type -func (p *parser) isToken(kind lexer.TokenKind) bool { - return p.have(1) && p.next().Kind == kind -} - -// isSexpr returns true if next token starts a sexpr -func (p *parser) isSexpr() bool { - return p.isToken(lexer.TokenOpenSexpr) -} - -// isPathSep returns true if next token is a path separator -func (p *parser) isPathSep() bool { - return p.isToken(lexer.TokenSep) -} - -// isID returns true if next token is an ID -func (p *parser) isID() bool { - return p.isToken(lexer.TokenID) -} - -// isBlockParams returns true if next token starts a block params -func (p *parser) isBlockParams() bool { - return p.isToken(lexer.TokenOpenBlockParams) -} - -// isInverse returns true if next token starts an INVERSE sequence -func (p *parser) isInverse() bool { - return p.isToken(lexer.TokenInverse) -} - -// isOpenInverseChain returns true if next token is OPEN_INVERSE_CHAIN -func (p *parser) isOpenInverseChain() bool { - return p.isToken(lexer.TokenOpenInverseChain) -} diff --git a/vendor/github.com/aymerick/raymond/parser/parser_test.go b/vendor/github.com/aymerick/raymond/parser/parser_test.go deleted file mode 100644 index 0baafbc..0000000 --- a/vendor/github.com/aymerick/raymond/parser/parser_test.go +++ /dev/null @@ -1,200 +0,0 @@ -package parser - -import ( - "fmt" - "regexp" - "testing" - - "github.com/aymerick/raymond/ast" - "github.com/aymerick/raymond/lexer" -) - -type parserTest struct { - name string - input string - output string -} - -var parserTests = []parserTest{ - // - // Next tests come from: - // https://github.com/wycats/handlebars.js/blob/master/spec/parser.js - // - {"parses simple mustaches (1)", `{{123}}`, "{{ NUMBER{123} [] }}\n"}, - {"parses simple mustaches (2)", `{{"foo"}}`, "{{ \"foo\" [] }}\n"}, - {"parses simple mustaches (3)", `{{false}}`, "{{ BOOLEAN{false} [] }}\n"}, - {"parses simple mustaches (4)", `{{true}}`, "{{ BOOLEAN{true} [] }}\n"}, - {"parses simple mustaches (5)", `{{foo}}`, "{{ PATH:foo [] }}\n"}, - {"parses simple mustaches (6)", `{{foo?}}`, "{{ PATH:foo? [] }}\n"}, - {"parses simple mustaches (7)", `{{foo_}}`, "{{ PATH:foo_ [] }}\n"}, - {"parses simple mustaches (8)", `{{foo-}}`, "{{ PATH:foo- [] }}\n"}, - {"parses simple mustaches (9)", `{{foo:}}`, "{{ PATH:foo: [] }}\n"}, - - {"parses simple mustaches with data", `{{@foo}}`, "{{ @PATH:foo [] }}\n"}, - {"parses simple mustaches with data paths", `{{@../foo}}`, "{{ @PATH:foo [] }}\n"}, - {"parses mustaches with paths", `{{foo/bar}}`, "{{ PATH:foo/bar [] }}\n"}, - {"parses mustaches with this/foo", `{{this/foo}}`, "{{ PATH:foo [] }}\n"}, - {"parses mustaches with - in a path", `{{foo-bar}}`, "{{ PATH:foo-bar [] }}\n"}, - {"parses mustaches with parameters", `{{foo bar}}`, "{{ PATH:foo [PATH:bar] }}\n"}, - {"parses mustaches with string parameters", `{{foo bar "baz" }}`, "{{ PATH:foo [PATH:bar, \"baz\"] }}\n"}, - {"parses mustaches with NUMBER parameters", `{{foo 1}}`, "{{ PATH:foo [NUMBER{1}] }}\n"}, - {"parses mustaches with BOOLEAN parameters (1)", `{{foo true}}`, "{{ PATH:foo [BOOLEAN{true}] }}\n"}, - {"parses mustaches with BOOLEAN parameters (2)", `{{foo false}}`, "{{ PATH:foo [BOOLEAN{false}] }}\n"}, - {"parses mustaches with DATA parameters", `{{foo @bar}}`, "{{ PATH:foo [@PATH:bar] }}\n"}, - - {"parses mustaches with hash arguments (01)", `{{foo bar=baz}}`, "{{ PATH:foo [] HASH{bar=PATH:baz} }}\n"}, - {"parses mustaches with hash arguments (02)", `{{foo bar=1}}`, "{{ PATH:foo [] HASH{bar=NUMBER{1}} }}\n"}, - {"parses mustaches with hash arguments (03)", `{{foo bar=true}}`, "{{ PATH:foo [] HASH{bar=BOOLEAN{true}} }}\n"}, - {"parses mustaches with hash arguments (04)", `{{foo bar=false}}`, "{{ PATH:foo [] HASH{bar=BOOLEAN{false}} }}\n"}, - {"parses mustaches with hash arguments (05)", `{{foo bar=@baz}}`, "{{ PATH:foo [] HASH{bar=@PATH:baz} }}\n"}, - {"parses mustaches with hash arguments (06)", `{{foo bar=baz bat=bam}}`, "{{ PATH:foo [] HASH{bar=PATH:baz, bat=PATH:bam} }}\n"}, - {"parses mustaches with hash arguments (07)", `{{foo bar=baz bat="bam"}}`, "{{ PATH:foo [] HASH{bar=PATH:baz, bat=\"bam\"} }}\n"}, - {"parses mustaches with hash arguments (08)", `{{foo bat='bam'}}`, "{{ PATH:foo [] HASH{bat=\"bam\"} }}\n"}, - {"parses mustaches with hash arguments (09)", `{{foo omg bar=baz bat="bam"}}`, "{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat=\"bam\"} }}\n"}, - {"parses mustaches with hash arguments (10)", `{{foo omg bar=baz bat="bam" baz=1}}`, "{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat=\"bam\", baz=NUMBER{1}} }}\n"}, - {"parses mustaches with hash arguments (11)", `{{foo omg bar=baz bat="bam" baz=true}}`, "{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat=\"bam\", baz=BOOLEAN{true}} }}\n"}, - {"parses mustaches with hash arguments (12)", `{{foo omg bar=baz bat="bam" baz=false}}`, "{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat=\"bam\", baz=BOOLEAN{false}} }}\n"}, - - {"parses contents followed by a mustache", `foo bar {{baz}}`, "CONTENT[ 'foo bar ' ]\n{{ PATH:baz [] }}\n"}, - - {"parses a partial (1)", `{{> foo }}`, "{{> PARTIAL:foo }}\n"}, - {"parses a partial (2)", `{{> "foo" }}`, "{{> PARTIAL:foo }}\n"}, - {"parses a partial (3)", `{{> 1 }}`, "{{> PARTIAL:1 }}\n"}, - {"parses a partial with context", `{{> foo bar}}`, "{{> PARTIAL:foo PATH:bar }}\n"}, - {"parses a partial with hash", `{{> foo bar=bat}}`, "{{> PARTIAL:foo HASH{bar=PATH:bat} }}\n"}, - {"parses a partial with context and hash", `{{> foo bar bat=baz}}`, "{{> PARTIAL:foo PATH:bar HASH{bat=PATH:baz} }}\n"}, - {"parses a partial with a complex name", `{{> shared/partial?.bar}}`, "{{> PARTIAL:shared/partial?.bar }}\n"}, - - {"parses a comment", `{{! this is a comment }}`, "{{! ' this is a comment ' }}\n"}, - {"parses a multi-line comment", "{{!\nthis is a multi-line comment\n}}", "{{! '\nthis is a multi-line comment\n' }}\n"}, - - {"parses an inverse section", `{{#foo}} bar {{^}} baz {{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]\n"}, - {"parses an inverse (else-style) section", `{{#foo}} bar {{else}} baz {{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n CONTENT[ ' baz ' ]\n"}, - {"parses multiple inverse sections", `{{#foo}} bar {{else if bar}}{{else}} baz {{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n BLOCK:\n PATH:if [PATH:bar]\n PROGRAM:\n {{^}}\n CONTENT[ ' baz ' ]\n"}, - {"parses empty blocks", `{{#foo}}{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n"}, - {"parses empty blocks with empty inverse section", `{{#foo}}{{^}}{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n"}, - {"parses empty blocks with empty inverse (else-style) section", `{{#foo}}{{else}}{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n"}, - {"parses non-empty blocks with empty inverse section", `{{#foo}} bar {{^}}{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n"}, - {"parses non-empty blocks with empty inverse (else-style) section", `{{#foo}} bar {{else}}{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n CONTENT[ ' bar ' ]\n {{^}}\n"}, - {"parses empty blocks with non-empty inverse section", `{{#foo}}{{^}} bar {{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]\n"}, - {"parses empty blocks with non-empty inverse (else-style) section", `{{#foo}}{{else}} bar {{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n CONTENT[ ' bar ' ]\n"}, - {"parses a standalone inverse section", `{{^foo}}bar{{/foo}}`, "BLOCK:\n PATH:foo []\n {{^}}\n CONTENT[ 'bar' ]\n"}, - {"parses block with block params", `{{#foo as |bar baz|}}content{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"}, - {"parses inverse block with block params", `{{^foo as |bar baz|}}content{{/foo}}`, "BLOCK:\n PATH:foo []\n {{^}}\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"}, - {"parses chained inverse block with block params", `{{#foo}}{{else foo as |bar baz|}}content{{/foo}}`, "BLOCK:\n PATH:foo []\n PROGRAM:\n {{^}}\n BLOCK:\n PATH:foo []\n PROGRAM:\n BLOCK PARAMS: [ bar baz ]\n CONTENT[ 'content' ]\n"}, -} - -func TestParser(t *testing.T) { - t.Parallel() - - for _, test := range parserTests { - output := "" - - node, err := Parse(test.input) - if err == nil { - output = ast.Print(node) - } - - if (err != nil) || (test.output != output) { - t.Errorf("Test '%s' failed\ninput:\n\t'%s'\nexpected\n\t%q\ngot\n\t%q\nerror:\n\t%s", test.name, test.input, test.output, output, err) - } - } -} - -var parserErrorTests = []parserTest{ - {"lexer error", `{{! unclosed comment`, "Lexer error"}, - {"syntax error", `foo{{^}}`, "Syntax error"}, - - {"open raw block must be closed", `{{{{raw foo}} bar {{{{/raw}}}}`, "Expecting CloseRawBlock"}, - {"end raw block must be closed", `{{{{raw foo}}}} bar {{{{/raw}}`, "Expecting CloseRawBlock"}, - - {"raw block names must match (1)", `{{{{1}}}}{{foo}}{{{{/raw}}}}`, "1 doesn't match raw"}, - {"raw block names must match (2)", `{{{{raw}}}}{{foo}}{{{{/1}}}}`, "raw doesn't match 1"}, - {"raw block names must match (3)", `{{{{goodbyes}}}}test{{{{/hellos}}}}`, "goodbyes doesn't match hellos"}, - - {"open block must be closed", `{{#foo bar}}}{{/foo}}`, "Expecting Close"}, - {"end block must be closed", `{{#foo bar}}{{/foo}}}`, "Expecting Close"}, - {"an open block must have a end block", `{{#foo}}test`, "Expecting OpenEndBlock"}, - - {"block names must match (1)", `{{#1 bar}}{{/foo}}`, "1 doesn't match foo"}, - {"block names must match (2)", `{{#foo bar}}{{/1}}`, "foo doesn't match 1"}, - {"block names must match (3)", `{{#foo}}test{{/bar}}`, "foo doesn't match bar"}, - - {"an mustache must terminate with a close mustache", `{{foo}}}`, "Expecting Close"}, - {"an unescaped mustache must terminate with a close unescaped mustache", `{{{foo}}`, "Expecting CloseUnescaped"}, - - {"an partial must terminate with a close mustache", `{{> foo}}}`, "Expecting Close"}, - {"a subexpression must terminate with a close subexpression", `{{foo (false}}`, "Expecting CloseSexpr"}, - - {"raises on missing hash value (1)", `{{foo bar=}}`, "Parse error on line 1"}, - {"raises on missing hash value (2)", `{{foo bar=baz bim=}}`, "Parse error on line 1"}, - - {"block param must have at least one param", `{{#foo as ||}}content{{/foo}}`, "Expecting ID"}, - {"open block params must be closed", `{{#foo as |}}content{{/foo}}`, "Expecting ID"}, - - {"a path must start with an ID", `{{#/}}content{{/foo}}`, "Expecting ID"}, - {"a path must end with an ID", `{{foo/bar/}}`, "Expecting ID"}, - - // - // Next tests come from: - // https://github.com/wycats/handlebars.js/blob/master/spec/parser.js - // - {"throws on old inverse section", `{{else foo}}bar{{/foo}}`, ""}, - - {"raises if there's a parser error (1)", `foo{{^}}bar`, "Parse error on line 1"}, - {"raises if there's a parser error (2)", `{{foo}`, "Parse error on line 1"}, - {"raises if there's a parser error (3)", `{{foo &}}`, "Parse error on line 1"}, - {"raises if there's a parser error (4)", `{{#goodbyes}}{{/hellos}}`, "Parse error on line 1"}, - {"raises if there's a parser error (5)", `{{#goodbyes}}{{/hellos}}`, "goodbyes doesn't match hellos"}, - - {"should handle invalid paths (1)", `{{foo/../bar}}`, `Invalid path: foo/..`}, - {"should handle invalid paths (2)", `{{foo/./bar}}`, `Invalid path: foo/.`}, - {"should handle invalid paths (3)", `{{foo/this/bar}}`, `Invalid path: foo/this`}, - - {"knows how to report the correct line number in errors (1)", "hello\nmy\n{{foo}", "Parse error on line 3"}, - {"knows how to report the correct line number in errors (2)", "hello\n\nmy\n\n{{foo}", "Parse error on line 5"}, - - {"knows how to report the correct line number in errors when the first character is a newline", "\n\nhello\n\nmy\n\n{{foo}", "Parse error on line 7"}, -} - -func TestParserErrors(t *testing.T) { - t.Parallel() - - for _, test := range parserErrorTests { - node, err := Parse(test.input) - if err == nil { - output := ast.Print(node) - tokens := lexer.Collect(test.input) - - t.Errorf("Test '%s' failed - Error expected\ninput:\n\t'%s'\ngot\n\t%q\ntokens:\n\t%q", test.name, test.input, output, tokens) - } else if test.output != "" { - matched, errMatch := regexp.MatchString(regexp.QuoteMeta(test.output), fmt.Sprint(err)) - if errMatch != nil { - panic("Failed to match regexp") - } - - if !matched { - t.Errorf("Test '%s' failed - Incorrect error returned\ninput:\n\t'%s'\nexpected\n\t%q\ngot\n\t%q", test.name, test.input, test.output, err) - } - } - } -} - -// package example -func Example() { - source := "You know {{nothing}} John Snow" - - // parse template - program, err := Parse(source) - if err != nil { - panic(err) - } - - // print AST - output := ast.Print(program) - - fmt.Print(output) - // CONTENT[ 'You know ' ] - // {{ PATH:nothing [] }} - // CONTENT[ ' John Snow' ] -} diff --git a/vendor/github.com/aymerick/raymond/parser/whitespace.go b/vendor/github.com/aymerick/raymond/parser/whitespace.go deleted file mode 100644 index 8f8c2c4..0000000 --- a/vendor/github.com/aymerick/raymond/parser/whitespace.go +++ /dev/null @@ -1,360 +0,0 @@ -package parser - -import ( - "regexp" - - "github.com/aymerick/raymond/ast" -) - -// whitespaceVisitor walks through the AST to perform whitespace control -// -// The logic was shamelessly borrowed from: -// https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler/whitespace-control.js -type whitespaceVisitor struct { - isRootSeen bool -} - -var ( - rTrimLeft = regexp.MustCompile(`^[ \t]*\r?\n?`) - rTrimLeftMultiple = regexp.MustCompile(`^\s+`) - - rTrimRight = regexp.MustCompile(`[ \t]+$`) - rTrimRightMultiple = regexp.MustCompile(`\s+$`) - - rPrevWhitespace = regexp.MustCompile(`\r?\n\s*?$`) - rPrevWhitespaceStart = regexp.MustCompile(`(^|\r?\n)\s*?$`) - - rNextWhitespace = regexp.MustCompile(`^\s*?\r?\n`) - rNextWhitespaceEnd = regexp.MustCompile(`^\s*?(\r?\n|$)`) - - rPartialIndent = regexp.MustCompile(`([ \t]+$)`) -) - -// newWhitespaceVisitor instanciates a new whitespaceVisitor -func newWhitespaceVisitor() *whitespaceVisitor { - return &whitespaceVisitor{} -} - -// processWhitespaces performs whitespace control on given AST -// -// WARNING: It must be called only once on AST. -func processWhitespaces(node ast.Node) { - node.Accept(newWhitespaceVisitor()) -} - -func omitRightFirst(body []ast.Node, multiple bool) { - omitRight(body, -1, multiple) -} - -func omitRight(body []ast.Node, i int, multiple bool) { - if i+1 >= len(body) { - return - } - - current := body[i+1] - - node, ok := current.(*ast.ContentStatement) - if !ok { - return - } - - if !multiple && node.RightStripped { - return - } - - original := node.Value - - r := rTrimLeft - if multiple { - r = rTrimLeftMultiple - } - - node.Value = r.ReplaceAllString(node.Value, "") - - node.RightStripped = (original != node.Value) -} - -func omitLeftLast(body []ast.Node, multiple bool) { - omitLeft(body, len(body), multiple) -} - -func omitLeft(body []ast.Node, i int, multiple bool) bool { - if i-1 < 0 { - return false - } - - current := body[i-1] - - node, ok := current.(*ast.ContentStatement) - if !ok { - return false - } - - if !multiple && node.LeftStripped { - return false - } - - original := node.Value - - r := rTrimRight - if multiple { - r = rTrimRightMultiple - } - - node.Value = r.ReplaceAllString(node.Value, "") - - node.LeftStripped = (original != node.Value) - - return node.LeftStripped -} - -func isPrevWhitespace(body []ast.Node) bool { - return isPrevWhitespaceProgram(body, len(body), false) -} - -func isPrevWhitespaceProgram(body []ast.Node, i int, isRoot bool) bool { - if i < 1 { - return isRoot - } - - prev := body[i-1] - - if node, ok := prev.(*ast.ContentStatement); ok { - if (node.Value == "") && node.RightStripped { - // already stripped, so it may be an empty string not catched by regexp - return true - } - - r := rPrevWhitespaceStart - if (i > 1) || !isRoot { - r = rPrevWhitespace - } - - return r.MatchString(node.Value) - } - - return false -} - -func isNextWhitespace(body []ast.Node) bool { - return isNextWhitespaceProgram(body, -1, false) -} - -func isNextWhitespaceProgram(body []ast.Node, i int, isRoot bool) bool { - if i+1 >= len(body) { - return isRoot - } - - next := body[i+1] - - if node, ok := next.(*ast.ContentStatement); ok { - if (node.Value == "") && node.LeftStripped { - // already stripped, so it may be an empty string not catched by regexp - return true - } - - r := rNextWhitespaceEnd - if (i+2 > len(body)) || !isRoot { - r = rNextWhitespace - } - - return r.MatchString(node.Value) - } - - return false -} - -// -// Visitor interface -// - -func (v *whitespaceVisitor) VisitProgram(program *ast.Program) interface{} { - isRoot := !v.isRootSeen - v.isRootSeen = true - - body := program.Body - for i, current := range body { - strip, _ := current.Accept(v).(*ast.Strip) - if strip == nil { - continue - } - - _isPrevWhitespace := isPrevWhitespaceProgram(body, i, isRoot) - _isNextWhitespace := isNextWhitespaceProgram(body, i, isRoot) - - openStandalone := strip.OpenStandalone && _isPrevWhitespace - closeStandalone := strip.CloseStandalone && _isNextWhitespace - inlineStandalone := strip.InlineStandalone && _isPrevWhitespace && _isNextWhitespace - - if strip.Close { - omitRight(body, i, true) - } - - if strip.Open && (i > 0) { - omitLeft(body, i, true) - } - - if inlineStandalone { - omitRight(body, i, false) - - if omitLeft(body, i, false) { - // If we are on a standalone node, save the indent info for partials - if partial, ok := current.(*ast.PartialStatement); ok { - // Pull out the whitespace from the final line - if i > 0 { - if prevContent, ok := body[i-1].(*ast.ContentStatement); ok { - partial.Indent = rPartialIndent.FindString(prevContent.Original) - } - } - } - } - } - - if b, ok := current.(*ast.BlockStatement); ok { - if openStandalone { - prog := b.Program - if prog == nil { - prog = b.Inverse - } - - omitRightFirst(prog.Body, false) - - // Strip out the previous content node if it's whitespace only - omitLeft(body, i, false) - } - - if closeStandalone { - prog := b.Inverse - if prog == nil { - prog = b.Program - } - - // Always strip the next node - omitRight(body, i, false) - - omitLeftLast(prog.Body, false) - } - - } - } - - return nil -} - -func (v *whitespaceVisitor) VisitBlock(block *ast.BlockStatement) interface{} { - if block.Program != nil { - block.Program.Accept(v) - } - - if block.Inverse != nil { - block.Inverse.Accept(v) - } - - program := block.Program - inverse := block.Inverse - - if program == nil { - program = inverse - inverse = nil - } - - firstInverse := inverse - lastInverse := inverse - - if (inverse != nil) && inverse.Chained { - b, _ := inverse.Body[0].(*ast.BlockStatement) - firstInverse = b.Program - - for lastInverse.Chained { - b, _ := lastInverse.Body[len(lastInverse.Body)-1].(*ast.BlockStatement) - lastInverse = b.Program - } - } - - closeProg := firstInverse - if closeProg == nil { - closeProg = program - } - - strip := &ast.Strip{ - Open: (block.OpenStrip != nil) && block.OpenStrip.Open, - Close: (block.CloseStrip != nil) && block.CloseStrip.Close, - - OpenStandalone: isNextWhitespace(program.Body), - CloseStandalone: isPrevWhitespace(closeProg.Body), - } - - if (block.OpenStrip != nil) && block.OpenStrip.Close { - omitRightFirst(program.Body, true) - } - - if inverse != nil { - if block.InverseStrip != nil { - inverseStrip := block.InverseStrip - - if inverseStrip.Open { - omitLeftLast(program.Body, true) - } - - if inverseStrip.Close { - omitRightFirst(firstInverse.Body, true) - } - } - - if (block.CloseStrip != nil) && block.CloseStrip.Open { - omitLeftLast(lastInverse.Body, true) - } - - // Find standalone else statements - if isPrevWhitespace(program.Body) && isNextWhitespace(firstInverse.Body) { - omitLeftLast(program.Body, false) - - omitRightFirst(firstInverse.Body, false) - } - } else if (block.CloseStrip != nil) && block.CloseStrip.Open { - omitLeftLast(program.Body, true) - } - - return strip -} - -func (v *whitespaceVisitor) VisitMustache(mustache *ast.MustacheStatement) interface{} { - return mustache.Strip -} - -func _inlineStandalone(strip *ast.Strip) interface{} { - return &ast.Strip{ - Open: strip.Open, - Close: strip.Close, - InlineStandalone: true, - } -} - -func (v *whitespaceVisitor) VisitPartial(node *ast.PartialStatement) interface{} { - strip := node.Strip - if strip == nil { - strip = &ast.Strip{} - } - - return _inlineStandalone(strip) -} - -func (v *whitespaceVisitor) VisitComment(node *ast.CommentStatement) interface{} { - strip := node.Strip - if strip == nil { - strip = &ast.Strip{} - } - - return _inlineStandalone(strip) -} - -// NOOP -func (v *whitespaceVisitor) VisitContent(node *ast.ContentStatement) interface{} { return nil } -func (v *whitespaceVisitor) VisitExpression(node *ast.Expression) interface{} { return nil } -func (v *whitespaceVisitor) VisitSubExpression(node *ast.SubExpression) interface{} { return nil } -func (v *whitespaceVisitor) VisitPath(node *ast.PathExpression) interface{} { return nil } -func (v *whitespaceVisitor) VisitString(node *ast.StringLiteral) interface{} { return nil } -func (v *whitespaceVisitor) VisitBoolean(node *ast.BooleanLiteral) interface{} { return nil } -func (v *whitespaceVisitor) VisitNumber(node *ast.NumberLiteral) interface{} { return nil } -func (v *whitespaceVisitor) VisitHash(node *ast.Hash) interface{} { return nil } -func (v *whitespaceVisitor) VisitHashPair(node *ast.HashPair) interface{} { return nil } diff --git a/vendor/github.com/aymerick/raymond/partial.go b/vendor/github.com/aymerick/raymond/partial.go deleted file mode 100644 index 3299d02..0000000 --- a/vendor/github.com/aymerick/raymond/partial.go +++ /dev/null @@ -1,85 +0,0 @@ -package raymond - -import ( - "fmt" - "sync" -) - -// partial represents a partial template -type partial struct { - name string - source string - tpl *Template -} - -// partials stores all global partials -var partials map[string]*partial - -// protects global partials -var partialsMutex sync.RWMutex - -func init() { - partials = make(map[string]*partial) -} - -// newPartial instanciates a new partial -func newPartial(name string, source string, tpl *Template) *partial { - return &partial{ - name: name, - source: source, - tpl: tpl, - } -} - -// RegisterPartial registers a global partial. That partial will be available to all templates. -func RegisterPartial(name string, source string) { - partialsMutex.Lock() - defer partialsMutex.Unlock() - - if partials[name] != nil { - panic(fmt.Errorf("Partial already registered: %s", name)) - } - - partials[name] = newPartial(name, source, nil) -} - -// RegisterPartials registers several global partials. Those partials will be available to all templates. -func RegisterPartials(partials map[string]string) { - for name, p := range partials { - RegisterPartial(name, p) - } -} - -// RegisterPartialTemplate registers a global partial with given parsed template. That partial will be available to all templates. -func RegisterPartialTemplate(name string, tpl *Template) { - partialsMutex.Lock() - defer partialsMutex.Unlock() - - if partials[name] != nil { - panic(fmt.Errorf("Partial already registered: %s", name)) - } - - partials[name] = newPartial(name, "", tpl) -} - -// findPartial finds a registered global partial -func findPartial(name string) *partial { - partialsMutex.RLock() - defer partialsMutex.RUnlock() - - return partials[name] -} - -// template returns parsed partial template -func (p *partial) template() (*Template, error) { - if p.tpl == nil { - var err error - - p.tpl, err = Parse(p.source) - if err != nil { - return nil, err - } - } - - return p.tpl, nil -} diff --git a/vendor/github.com/aymerick/raymond/raymond.go b/vendor/github.com/aymerick/raymond/raymond.go deleted file mode 100644 index c6df6b3..0000000 --- a/vendor/github.com/aymerick/raymond/raymond.go +++ /dev/null @@ -1,28 +0,0 @@ -// Package raymond provides handlebars evaluation -package raymond - -// Render parses a template and evaluates it with given context -// -// Note that this function call is not optimal as your template is parsed everytime you call it. You should use Parse() function instead. -func Render(source string, ctx interface{}) (string, error) { - // parse template - tpl, err := Parse(source) - if err != nil { - return "", err - } - - // renders template - str, err := tpl.Exec(ctx) - if err != nil { - return "", err - } - - return str, nil -} - -// MustRender parses a template and evaluates it with given context. It panics on error. -// -// Note that this function call is not optimal as your template is parsed everytime you call it. You should use Parse() function instead. -func MustRender(source string, ctx interface{}) string { - return MustParse(source).MustExec(ctx) -} diff --git a/vendor/github.com/aymerick/raymond/raymond.png b/vendor/github.com/aymerick/raymond/raymond.png deleted file mode 100644 index 6a7c942..0000000 Binary files a/vendor/github.com/aymerick/raymond/raymond.png and /dev/null differ diff --git a/vendor/github.com/aymerick/raymond/raymond_test.go b/vendor/github.com/aymerick/raymond/raymond_test.go deleted file mode 100644 index bd34eeb..0000000 --- a/vendor/github.com/aymerick/raymond/raymond_test.go +++ /dev/null @@ -1,115 +0,0 @@ -package raymond - -import "fmt" - -func Example() { - source := "

{{title}}

{{body.content}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // parse template - tpl := MustParse(source) - - // evaluate template with context - output := tpl.MustExec(ctx) - - // alternatively, for one shots: - // output := MustRender(source, ctx) - - fmt.Print(output) - // Output:

foo

bar

-} - -func Example_struct() { - source := `
-

By {{fullName author}}

-
{{body}}
- -

Comments

- - {{#each comments}} -

By {{fullName author}}

-
{{body}}
- {{/each}} -
` - - type Person struct { - FirstName string - LastName string - } - - type Comment struct { - Author Person - Body string - } - - type Post struct { - Author Person - Body string - Comments []Comment - } - - ctx := Post{ - Person{"Jean", "Valjean"}, - "Life is difficult", - []Comment{ - Comment{ - Person{"Marcel", "Beliveau"}, - "LOL!", - }, - }, - } - - RegisterHelper("fullName", func(person Person) string { - return person.FirstName + " " + person.LastName - }) - - output := MustRender(source, ctx) - - fmt.Print(output) - // Output:
- //

By Jean Valjean

- //
Life is difficult
- // - //

Comments

- // - //

By Marcel Beliveau

- //
LOL!
- //
-} - -func ExampleRender() { - tpl := "

{{title}}

{{body.content}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // render template with context - output, err := Render(tpl, ctx) - if err != nil { - panic(err) - } - - fmt.Print(output) - // Output:

foo

bar

-} - -func ExampleMustRender() { - tpl := "

{{title}}

{{body.content}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // render template with context - output := MustRender(tpl, ctx) - - fmt.Print(output) - // Output:

foo

bar

-} diff --git a/vendor/github.com/aymerick/raymond/string.go b/vendor/github.com/aymerick/raymond/string.go deleted file mode 100644 index 7194769..0000000 --- a/vendor/github.com/aymerick/raymond/string.go +++ /dev/null @@ -1,84 +0,0 @@ -package raymond - -import ( - "fmt" - "reflect" - "strconv" -) - -// SafeString represents a string that must not be escaped. -// -// A SafeString can be returned by helpers to disable escaping. -type SafeString string - -// isSafeString returns true if argument is a SafeString -func isSafeString(value interface{}) bool { - if _, ok := value.(SafeString); ok { - return true - } - return false -} - -// Str returns string representation of any basic type value. -func Str(value interface{}) string { - return strValue(reflect.ValueOf(value)) -} - -// strValue returns string representation of a reflect.Value -func strValue(value reflect.Value) string { - result := "" - - ival, ok := printableValue(value) - if !ok { - panic(fmt.Errorf("Can't print value: %q", value)) - } - - val := reflect.ValueOf(ival) - - switch val.Kind() { - case reflect.Array, reflect.Slice: - for i := 0; i < val.Len(); i++ { - result += strValue(val.Index(i)) - } - case reflect.Bool: - result = "false" - if val.Bool() { - result = "true" - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - result = fmt.Sprintf("%d", ival) - case reflect.Float32, reflect.Float64: - result = strconv.FormatFloat(val.Float(), 'f', -1, 64) - case reflect.Invalid: - result = "" - default: - result = fmt.Sprintf("%s", ival) - } - - return result -} - -// printableValue returns the, possibly indirected, interface value inside v that -// is best for a call to formatted printer. -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go -func printableValue(v reflect.Value) (interface{}, bool) { - if v.Kind() == reflect.Ptr { - v, _ = indirect(v) // fmt.Fprint handles nil. - } - if !v.IsValid() { - return "", true - } - - if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { - if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { - v = v.Addr() - } else { - switch v.Kind() { - case reflect.Chan, reflect.Func: - return nil, false - } - } - } - return v.Interface(), true -} diff --git a/vendor/github.com/aymerick/raymond/string_test.go b/vendor/github.com/aymerick/raymond/string_test.go deleted file mode 100644 index eaec630..0000000 --- a/vendor/github.com/aymerick/raymond/string_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package raymond - -import ( - "fmt" - "testing" -) - -type strTest struct { - name string - input interface{} - output string -} - -var strTests = []strTest{ - {"String", "foo", "foo"}, - {"Boolean true", true, "true"}, - {"Boolean false", false, "false"}, - {"Integer", 25, "25"}, - {"Float", 25.75, "25.75"}, - {"Nil", nil, ""}, - {"[]string", []string{"foo", "bar"}, "foobar"}, - {"[]interface{} (strings)", []interface{}{"foo", "bar"}, "foobar"}, - {"[]Boolean", []bool{true, false}, "truefalse"}, -} - -func TestStr(t *testing.T) { - t.Parallel() - - for _, test := range strTests { - if res := Str(test.input); res != test.output { - t.Errorf("Failed to stringify: %s\nexpected:\n\t'%s'got:\n\t%q", test.name, test.output, res) - } - } -} - -func ExampleStr() { - output := Str(3) + " foos are " + Str(true) + " and " + Str(-1.25) + " bars are " + Str(false) + "\n" - output += "But you know '" + Str(nil) + "' John Snow\n" - output += "map: " + Str(map[string]string{"foo": "bar"}) + "\n" - output += "array: " + Str([]interface{}{true, 10, "foo", 5, "bar"}) - - fmt.Println(output) - // Output: 3 foos are true and -1.25 bars are false - // But you know '' John Snow - // map: map[foo:bar] - // array: true10foo5bar -} - -func ExampleSafeString() { - RegisterHelper("em", func() SafeString { - return SafeString("FOO BAR") - }) - - tpl := MustParse("{{em}}") - - result := tpl.MustExec(nil) - fmt.Print(result) - // Output: FOO BAR -} diff --git a/vendor/github.com/aymerick/raymond/template.go b/vendor/github.com/aymerick/raymond/template.go deleted file mode 100644 index f16ed2f..0000000 --- a/vendor/github.com/aymerick/raymond/template.go +++ /dev/null @@ -1,248 +0,0 @@ -package raymond - -import ( - "fmt" - "io/ioutil" - "reflect" - "runtime" - "sync" - - "github.com/aymerick/raymond/ast" - "github.com/aymerick/raymond/parser" -) - -// Template represents a handlebars template. -type Template struct { - source string - program *ast.Program - helpers map[string]reflect.Value - partials map[string]*partial - mutex sync.RWMutex // protects helpers and partials -} - -// newTemplate instanciate a new template without parsing it -func newTemplate(source string) *Template { - return &Template{ - source: source, - helpers: make(map[string]reflect.Value), - partials: make(map[string]*partial), - } -} - -// Parse instanciates a template by parsing given source. -func Parse(source string) (*Template, error) { - tpl := newTemplate(source) - - // parse template - if err := tpl.parse(); err != nil { - return nil, err - } - - return tpl, nil -} - -// MustParse instanciates a template by parsing given source. It panics on error. -func MustParse(source string) *Template { - result, err := Parse(source) - if err != nil { - panic(err) - } - return result -} - -// ParseFile reads given file and returns parsed template. -func ParseFile(filePath string) (*Template, error) { - b, err := ioutil.ReadFile(filePath) - if err != nil { - return nil, err - } - - return Parse(string(b)) -} - -// parse parses the template -// -// It can be called several times, the parsing will be done only once. -func (tpl *Template) parse() error { - if tpl.program == nil { - var err error - - tpl.program, err = parser.Parse(tpl.source) - if err != nil { - return err - } - } - - return nil -} - -// Clone returns a copy of that template. -func (tpl *Template) Clone() *Template { - result := newTemplate(tpl.source) - - result.program = tpl.program - - tpl.mutex.RLock() - defer tpl.mutex.RUnlock() - - for name, helper := range tpl.helpers { - result.RegisterHelper(name, helper.Interface()) - } - - for name, partial := range tpl.partials { - result.addPartial(name, partial.source, partial.tpl) - } - - return result -} - -func (tpl *Template) findHelper(name string) reflect.Value { - tpl.mutex.RLock() - defer tpl.mutex.RUnlock() - - return tpl.helpers[name] -} - -// RegisterHelper registers a helper for that template. -func (tpl *Template) RegisterHelper(name string, helper interface{}) { - tpl.mutex.Lock() - defer tpl.mutex.Unlock() - - if tpl.helpers[name] != zero { - panic(fmt.Sprintf("Helper %s already registered", name)) - } - - val := reflect.ValueOf(helper) - ensureValidHelper(name, val) - - tpl.helpers[name] = val -} - -// RegisterHelpers registers several helpers for that template. -func (tpl *Template) RegisterHelpers(helpers map[string]interface{}) { - for name, helper := range helpers { - tpl.RegisterHelper(name, helper) - } -} - -func (tpl *Template) addPartial(name string, source string, template *Template) { - tpl.mutex.Lock() - defer tpl.mutex.Unlock() - - if tpl.partials[name] != nil { - panic(fmt.Sprintf("Partial %s already registered", name)) - } - - tpl.partials[name] = newPartial(name, source, template) -} - -func (tpl *Template) findPartial(name string) *partial { - tpl.mutex.RLock() - defer tpl.mutex.RUnlock() - - return tpl.partials[name] -} - -// RegisterPartial registers a partial for that template. -func (tpl *Template) RegisterPartial(name string, source string) { - tpl.addPartial(name, source, nil) -} - -// RegisterPartials registers several partials for that template. -func (tpl *Template) RegisterPartials(partials map[string]string) { - for name, partial := range partials { - tpl.RegisterPartial(name, partial) - } -} - -// RegisterPartialFile reads given file and registers its content as a partial with given name. -func (tpl *Template) RegisterPartialFile(filePath string, name string) error { - b, err := ioutil.ReadFile(filePath) - if err != nil { - return err - } - - tpl.RegisterPartial(name, string(b)) - - return nil -} - -// RegisterPartialFiles reads several files and registers them as partials, the filename base is used as the partial name. -func (tpl *Template) RegisterPartialFiles(filePaths ...string) error { - if len(filePaths) == 0 { - return nil - } - - for _, filePath := range filePaths { - name := fileBase(filePath) - - if err := tpl.RegisterPartialFile(filePath, name); err != nil { - return err - } - } - - return nil -} - -// RegisterPartialTemplate registers an already parsed partial for that template. -func (tpl *Template) RegisterPartialTemplate(name string, template *Template) { - tpl.addPartial(name, "", template) -} - -// Exec evaluates template with given context. -func (tpl *Template) Exec(ctx interface{}) (result string, err error) { - return tpl.ExecWith(ctx, nil) -} - -// MustExec evaluates template with given context. It panics on error. -func (tpl *Template) MustExec(ctx interface{}) string { - result, err := tpl.Exec(ctx) - if err != nil { - panic(err) - } - return result -} - -// ExecWith evaluates template with given context and private data frame. -func (tpl *Template) ExecWith(ctx interface{}, privData *DataFrame) (result string, err error) { - defer errRecover(&err) - - // parses template if necessary - err = tpl.parse() - if err != nil { - return - } - - // setup visitor - v := newEvalVisitor(tpl, ctx, privData) - - // visit AST - result, _ = tpl.program.Accept(v).(string) - - // named return values - return -} - -// errRecover recovers evaluation panic -func errRecover(errp *error) { - e := recover() - if e != nil { - switch err := e.(type) { - case runtime.Error: - panic(e) - case error: - *errp = err - default: - panic(e) - } - } -} - -// PrintAST returns string representation of parsed template. -func (tpl *Template) PrintAST() string { - if err := tpl.parse(); err != nil { - return fmt.Sprintf("PARSER ERROR: %s", err) - } - - return ast.Print(tpl.program) -} diff --git a/vendor/github.com/aymerick/raymond/template_test.go b/vendor/github.com/aymerick/raymond/template_test.go deleted file mode 100644 index c194b28..0000000 --- a/vendor/github.com/aymerick/raymond/template_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package raymond - -import ( - "fmt" - "testing" -) - -var sourceBasic = `
-

{{title}}

-
- {{body}} -
-
` - -var basicAST = `CONTENT[ '
-

' ] -{{ PATH:title [] }} -CONTENT[ '

-
- ' ] -{{ PATH:body [] }} -CONTENT[ ' -
-
' ] -` - -func TestNewTemplate(t *testing.T) { - t.Parallel() - - tpl := newTemplate(sourceBasic) - if tpl.source != sourceBasic { - t.Errorf("Failed to instantiate template") - } -} - -func TestParse(t *testing.T) { - t.Parallel() - - tpl, err := Parse(sourceBasic) - if err != nil || (tpl.source != sourceBasic) { - t.Errorf("Failed to parse template") - } - - if str := tpl.PrintAST(); str != basicAST { - t.Errorf("Template parsing incorrect: %s", str) - } -} - -func TestClone(t *testing.T) { - t.Parallel() - - sourcePartial := `I am a {{wat}} partial` - sourcePartial2 := `Partial for the {{wat}}` - - tpl := MustParse(sourceBasic) - tpl.RegisterPartial("p", sourcePartial) - - if (len(tpl.partials) != 1) || (tpl.partials["p"] == nil) { - t.Errorf("What?") - } - - cloned := tpl.Clone() - - if (len(cloned.partials) != 1) || (cloned.partials["p"] == nil) { - t.Errorf("Template partials must be cloned") - } - - cloned.RegisterPartial("p2", sourcePartial2) - - if (len(cloned.partials) != 2) || (cloned.partials["p"] == nil) || (cloned.partials["p2"] == nil) { - t.Errorf("Failed to register a partial on cloned template") - } - - if (len(tpl.partials) != 1) || (tpl.partials["p"] == nil) { - t.Errorf("Modification of a cloned template MUST NOT affect original template") - } -} - -func ExampleTemplate_Exec() { - source := "

{{title}}

{{body.content}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // parse template - tpl := MustParse(source) - - // evaluate template with context - output, err := tpl.Exec(ctx) - if err != nil { - panic(err) - } - - fmt.Print(output) - // Output:

foo

bar

-} - -func ExampleTemplate_MustExec() { - source := "

{{title}}

{{body.content}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // parse template - tpl := MustParse(source) - - // evaluate template with context - output := tpl.MustExec(ctx) - - fmt.Print(output) - // Output:

foo

bar

-} - -func ExampleTemplate_ExecWith() { - source := "

{{title}}

{{#body}}{{content}} and {{@baz.bat}}{{/body}}

" - - ctx := map[string]interface{}{ - "title": "foo", - "body": map[string]string{"content": "bar"}, - } - - // parse template - tpl := MustParse(source) - - // computes private data frame - frame := NewDataFrame() - frame.Set("baz", map[string]string{"bat": "unicorns"}) - - // evaluate template - output, err := tpl.ExecWith(ctx, frame) - if err != nil { - panic(err) - } - - fmt.Print(output) - // Output:

foo

bar and unicorns

-} - -func ExampleTemplate_PrintAST() { - source := "

{{title}}

{{#body}}{{content}} and {{@baz.bat}}{{/body}}

" - - // parse template - tpl := MustParse(source) - - // print AST - output := tpl.PrintAST() - - fmt.Print(output) - // Output: CONTENT[ '

' ] - // {{ PATH:title [] }} - // CONTENT[ '

' ] - // BLOCK: - // PATH:body [] - // PROGRAM: - // {{ PATH:content [] - // }} - // CONTENT[ ' and ' ] - // {{ @PATH:baz/bat [] - // }} - // CONTENT[ '

' ] - // -} diff --git a/vendor/github.com/aymerick/raymond/utils.go b/vendor/github.com/aymerick/raymond/utils.go deleted file mode 100644 index 3deaaf3..0000000 --- a/vendor/github.com/aymerick/raymond/utils.go +++ /dev/null @@ -1,85 +0,0 @@ -package raymond - -import ( - "path" - "reflect" -) - -// indirect returns the item at the end of indirection, and a bool to indicate if it's nil. -// We indirect through pointers and empty interfaces (only) because -// non-empty interfaces have methods we might need. -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go -func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { - for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { - if v.IsNil() { - return v, true - } - if v.Kind() == reflect.Interface && v.NumMethod() > 0 { - break - } - } - return v, false -} - -// IsTrue returns true if obj is a truthy value. -func IsTrue(obj interface{}) bool { - thruth, ok := isTrueValue(reflect.ValueOf(obj)) - if !ok { - return false - } - return thruth -} - -// isTrueValue reports whether the value is 'true', in the sense of not the zero of its type, -// and whether the value has a meaningful truth value -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go -func isTrueValue(val reflect.Value) (truth, ok bool) { - if !val.IsValid() { - // Something like var x interface{}, never set. It's a form of nil. - return false, true - } - switch val.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - truth = val.Len() > 0 - case reflect.Bool: - truth = val.Bool() - case reflect.Complex64, reflect.Complex128: - truth = val.Complex() != 0 - case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: - truth = !val.IsNil() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - truth = val.Int() != 0 - case reflect.Float32, reflect.Float64: - truth = val.Float() != 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - truth = val.Uint() != 0 - case reflect.Struct: - truth = true // Struct values are always true. - default: - return - } - return truth, true -} - -// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. -// -// NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go -func canBeNil(typ reflect.Type) bool { - switch typ.Kind() { - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: - return true - } - return false -} - -// fileBase returns base file name -// -// example: /foo/bar/baz.png => baz -func fileBase(filePath string) string { - fileName := path.Base(filePath) - fileExt := path.Ext(filePath) - - return fileName[:len(fileName)-len(fileExt)] -} diff --git a/vendor/github.com/aymerick/raymond/utils_test.go b/vendor/github.com/aymerick/raymond/utils_test.go deleted file mode 100644 index cecac37..0000000 --- a/vendor/github.com/aymerick/raymond/utils_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package raymond - -import "fmt" - -func ExampleIsTrue() { - output := "Empty array: " + Str(IsTrue([0]string{})) + "\n" - output += "Non empty array: " + Str(IsTrue([1]string{"foo"})) + "\n" - - output += "Empty slice: " + Str(IsTrue([]string{})) + "\n" - output += "Non empty slice: " + Str(IsTrue([]string{"foo"})) + "\n" - - output += "Empty map: " + Str(IsTrue(map[string]string{})) + "\n" - output += "Non empty map: " + Str(IsTrue(map[string]string{"foo": "bar"})) + "\n" - - output += "Empty string: " + Str(IsTrue("")) + "\n" - output += "Non empty string: " + Str(IsTrue("foo")) + "\n" - - output += "true bool: " + Str(IsTrue(true)) + "\n" - output += "false bool: " + Str(IsTrue(false)) + "\n" - - output += "0 integer: " + Str(IsTrue(0)) + "\n" - output += "positive integer: " + Str(IsTrue(10)) + "\n" - output += "negative integer: " + Str(IsTrue(-10)) + "\n" - - output += "0 float: " + Str(IsTrue(0.0)) + "\n" - output += "positive float: " + Str(IsTrue(10.0)) + "\n" - output += "negative integer: " + Str(IsTrue(-10.0)) + "\n" - - output += "struct: " + Str(IsTrue(struct{}{})) + "\n" - output += "nil: " + Str(IsTrue(nil)) + "\n" - - fmt.Println(output) - // Output: Empty array: false - // Non empty array: true - // Empty slice: false - // Non empty slice: true - // Empty map: false - // Non empty map: true - // Empty string: false - // Non empty string: true - // true bool: true - // false bool: false - // 0 integer: false - // positive integer: true - // negative integer: true - // 0 float: false - // positive float: true - // negative integer: true - // struct: true - // nil: false -} diff --git a/vendor/github.com/matrix-org/gomatrix/.gitignore b/vendor/github.com/matrix-org/gomatrix/.gitignore deleted file mode 100644 index daf913b..0000000 --- a/vendor/github.com/matrix-org/gomatrix/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/matrix-org/gomatrix/.travis.yml b/vendor/github.com/matrix-org/gomatrix/.travis.yml deleted file mode 100644 index fadc326..0000000 --- a/vendor/github.com/matrix-org/gomatrix/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go -go: - - 1.8 -install: - - go get github.com/golang/lint/golint - - go get github.com/fzipp/gocyclo - - go get github.com/client9/misspell/... - - go get github.com/gordonklaus/ineffassign -script: ./hooks/pre-commit diff --git a/vendor/github.com/matrix-org/gomatrix/LICENSE b/vendor/github.com/matrix-org/gomatrix/LICENSE deleted file mode 100644 index 8dada3e..0000000 --- a/vendor/github.com/matrix-org/gomatrix/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/matrix-org/gomatrix/README.md b/vendor/github.com/matrix-org/gomatrix/README.md deleted file mode 100644 index ea9109a..0000000 --- a/vendor/github.com/matrix-org/gomatrix/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# gomatrix -[![GoDoc](https://godoc.org/github.com/matrix-org/gomatrix?status.svg)](https://godoc.org/github.com/matrix-org/gomatrix) - -A Golang Matrix client. - -**THIS IS UNDER ACTIVE DEVELOPMENT: BREAKING CHANGES ARE FREQUENT.** diff --git a/vendor/github.com/matrix-org/gomatrix/client.go b/vendor/github.com/matrix-org/gomatrix/client.go deleted file mode 100644 index 90a07c6..0000000 --- a/vendor/github.com/matrix-org/gomatrix/client.go +++ /dev/null @@ -1,703 +0,0 @@ -// Package gomatrix implements the Matrix Client-Server API. -// -// Specification can be found at http://matrix.org/docs/spec/client_server/r0.2.0.html -package gomatrix - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "path" - "strconv" - "sync" - "time" -) - -// Client represents a Matrix client. -type Client struct { - HomeserverURL *url.URL // The base homeserver URL - Prefix string // The API prefix eg '/_matrix/client/r0' - UserID string // The user ID of the client. Used for forming HTTP paths which use the client's user ID. - AccessToken string // The access_token for the client. - Client *http.Client // The underlying HTTP client which will be used to make HTTP requests. - Syncer Syncer // The thing which can process /sync responses - Store Storer // The thing which can store rooms/tokens/ids - - // The ?user_id= query parameter for application services. This must be set *prior* to calling a method. If this is empty, - // no user_id parameter will be sent. - // See http://matrix.org/docs/spec/application_service/unstable.html#identity-assertion - AppServiceUserID string - - syncingMutex sync.Mutex // protects syncingID - syncingID uint32 // Identifies the current Sync. Only one Sync can be active at any given time. -} - -// HTTPError An HTTP Error response, which may wrap an underlying native Go Error. -type HTTPError struct { - WrappedError error - Message string - Code int -} - -func (e HTTPError) Error() string { - var wrappedErrMsg string - if e.WrappedError != nil { - wrappedErrMsg = e.WrappedError.Error() - } - return fmt.Sprintf("msg=%s code=%d wrapped=%s", e.Message, e.Code, wrappedErrMsg) -} - -// BuildURL builds a URL with the Client's homserver/prefix/access_token set already. -func (cli *Client) BuildURL(urlPath ...string) string { - ps := []string{cli.Prefix} - for _, p := range urlPath { - ps = append(ps, p) - } - return cli.BuildBaseURL(ps...) -} - -// BuildBaseURL builds a URL with the Client's homeserver/access_token set already. You must -// supply the prefix in the path. -func (cli *Client) BuildBaseURL(urlPath ...string) string { - // copy the URL. Purposefully ignore error as the input is from a valid URL already - hsURL, _ := url.Parse(cli.HomeserverURL.String()) - parts := []string{hsURL.Path} - parts = append(parts, urlPath...) - hsURL.Path = path.Join(parts...) - query := hsURL.Query() - if cli.AccessToken != "" { - query.Set("access_token", cli.AccessToken) - } - if cli.AppServiceUserID != "" { - query.Set("user_id", cli.AppServiceUserID) - } - hsURL.RawQuery = query.Encode() - return hsURL.String() -} - -// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix/access_token set already. -func (cli *Client) BuildURLWithQuery(urlPath []string, urlQuery map[string]string) string { - u, _ := url.Parse(cli.BuildURL(urlPath...)) - q := u.Query() - for k, v := range urlQuery { - q.Set(k, v) - } - u.RawQuery = q.Encode() - return u.String() -} - -// SetCredentials sets the user ID and access token on this client instance. -func (cli *Client) SetCredentials(userID, accessToken string) { - cli.AccessToken = accessToken - cli.UserID = userID -} - -// ClearCredentials removes the user ID and access token on this client instance. -func (cli *Client) ClearCredentials() { - cli.AccessToken = "" - cli.UserID = "" -} - -// Sync starts syncing with the provided Homeserver. If Sync() is called twice then the first sync will be stopped and the -// error will be nil. -// -// This function will block until a fatal /sync error occurs, so it should almost always be started as a new goroutine. -// Fatal sync errors can be caused by: -// - The failure to create a filter. -// - Client.Syncer.OnFailedSync returning an error in response to a failed sync. -// - Client.Syncer.ProcessResponse returning an error. -// If you wish to continue retrying in spite of these fatal errors, call Sync() again. -func (cli *Client) Sync() error { - // Mark the client as syncing. - // We will keep syncing until the syncing state changes. Either because - // Sync is called or StopSync is called. - syncingID := cli.incrementSyncingID() - nextBatch := cli.Store.LoadNextBatch(cli.UserID) - filterID := cli.Store.LoadFilterID(cli.UserID) - if filterID == "" { - filterJSON := cli.Syncer.GetFilterJSON(cli.UserID) - resFilter, err := cli.CreateFilter(filterJSON) - if err != nil { - return err - } - filterID = resFilter.FilterID - cli.Store.SaveFilterID(cli.UserID, filterID) - } - - for { - resSync, err := cli.SyncRequest(30000, nextBatch, filterID, false, "") - if err != nil { - duration, err2 := cli.Syncer.OnFailedSync(resSync, err) - if err2 != nil { - return err2 - } - time.Sleep(duration) - continue - } - - // Check that the syncing state hasn't changed - // Either because we've stopped syncing or another sync has been started. - // We discard the response from our sync. - if cli.getSyncingID() != syncingID { - return nil - } - - // Save the token now *before* processing it. This means it's possible - // to not process some events, but it means that we won't get constantly stuck processing - // a malformed/buggy event which keeps making us panic. - cli.Store.SaveNextBatch(cli.UserID, resSync.NextBatch) - if err = cli.Syncer.ProcessResponse(resSync, nextBatch); err != nil { - return err - } - - nextBatch = resSync.NextBatch - } -} - -func (cli *Client) incrementSyncingID() uint32 { - cli.syncingMutex.Lock() - defer cli.syncingMutex.Unlock() - cli.syncingID++ - return cli.syncingID -} - -func (cli *Client) getSyncingID() uint32 { - cli.syncingMutex.Lock() - defer cli.syncingMutex.Unlock() - return cli.syncingID -} - -// StopSync stops the ongoing sync started by Sync. -func (cli *Client) StopSync() { - // Advance the syncing state so that any running Syncs will terminate. - cli.incrementSyncingID() -} - -// MakeRequest makes a JSON HTTP request to the given URL. -// If "resBody" is not nil, the response body will be json.Unmarshalled into it. -// -// Returns the HTTP body as bytes on 2xx with a nil error. Returns an error if the response is not 2xx along -// with the HTTP body bytes if it got that far. This error is an HTTPError which includes the returned -// HTTP status code and possibly a RespError as the WrappedError, if the HTTP body could be decoded as a RespError. -func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) { - var req *http.Request - var err error - if reqBody != nil { - var jsonStr []byte - jsonStr, err = json.Marshal(reqBody) - if err != nil { - return nil, err - } - req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr)) - } else { - req, err = http.NewRequest(method, httpURL, nil) - } - - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/json") - res, err := cli.Client.Do(req) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - contents, err := ioutil.ReadAll(res.Body) - if res.StatusCode/100 != 2 { // not 2xx - var wrap error - var respErr RespError - if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" { - wrap = respErr - } - - // If we failed to decode as RespError, don't just drop the HTTP body, include it in the - // HTTP error instead (e.g proxy errors which return HTML). - msg := "Failed to " + method + " JSON to " + req.URL.Path - if wrap == nil { - msg = msg + ": " + string(contents) - } - - return contents, HTTPError{ - Code: res.StatusCode, - Message: msg, - WrappedError: wrap, - } - } - if err != nil { - return nil, err - } - - if resBody != nil { - if err = json.Unmarshal(contents, &resBody); err != nil { - return nil, err - } - } - - return contents, nil -} - -// CreateFilter makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter -func (cli *Client) CreateFilter(filter json.RawMessage) (resp *RespCreateFilter, err error) { - urlPath := cli.BuildURL("user", cli.UserID, "filter") - _, err = cli.MakeRequest("POST", urlPath, &filter, &resp) - return -} - -// SyncRequest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync -func (cli *Client) SyncRequest(timeout int, since, filterID string, fullState bool, setPresence string) (resp *RespSync, err error) { - query := map[string]string{ - "timeout": strconv.Itoa(timeout), - } - if since != "" { - query["since"] = since - } - if filterID != "" { - query["filter"] = filterID - } - if setPresence != "" { - query["set_presence"] = setPresence - } - if fullState { - query["full_state"] = "true" - } - urlPath := cli.BuildURLWithQuery([]string{"sync"}, query) - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func (cli *Client) register(u string, req *ReqRegister) (resp *RespRegister, uiaResp *RespUserInteractive, err error) { - var bodyBytes []byte - bodyBytes, err = cli.MakeRequest("POST", u, req, nil) - if err != nil { - httpErr, ok := err.(HTTPError) - if !ok { // network error - return - } - if httpErr.Code == 401 { - // body should be RespUserInteractive, if it isn't, fail with the error - err = json.Unmarshal(bodyBytes, &uiaResp) - return - } - return - } - // body should be RespRegister - err = json.Unmarshal(bodyBytes, &resp) - return -} - -// Register makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -// -// Registers with kind=user. For kind=guest, see RegisterGuest. -func (cli *Client) Register(req *ReqRegister) (*RespRegister, *RespUserInteractive, error) { - u := cli.BuildURL("register") - return cli.register(u, req) -} - -// RegisterGuest makes an HTTP request according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -// with kind=guest. -// -// For kind=user, see Register. -func (cli *Client) RegisterGuest(req *ReqRegister) (*RespRegister, *RespUserInteractive, error) { - query := map[string]string{ - "kind": "guest", - } - u := cli.BuildURLWithQuery([]string{"register"}, query) - return cli.register(u, req) -} - -// RegisterDummy performs m.login.dummy registration according to https://matrix.org/docs/spec/client_server/r0.2.0.html#dummy-auth -// -// Only a username and password need to be provided on the ReqRegister struct. Most local/developer homeservers will allow registration -// this way. If the homeserver does not, an error is returned. -// -// This does not set credentials on the client instance. See SetCredentials() instead. -// -// res, err := cli.RegisterDummy(&gomatrix.ReqRegister{ -// Username: "alice", -// Password: "wonderland", -// }) -// if err != nil { -// panic(err) -// } -// token := res.AccessToken -func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) { - res, uia, err := cli.Register(req) - if err != nil && uia == nil { - return nil, err - } - if uia != nil && uia.HasSingleStageFlow("m.login.dummy") { - req.Auth = struct { - Type string `json:"type"` - Session string `json:"session,omitempty"` - }{"m.login.dummy", uia.Session} - res, _, err = cli.Register(req) - if err != nil { - return nil, err - } - } - if res == nil { - return nil, fmt.Errorf("registration failed: does this server support m.login.dummy?") - } - return res, nil -} - -// Login a user to the homeserver according to http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -// This does not set credentials on this client instance. See SetCredentials() instead. -func (cli *Client) Login(req *ReqLogin) (resp *RespLogin, err error) { - urlPath := cli.BuildURL("login") - _, err = cli.MakeRequest("POST", urlPath, req, &resp) - return -} - -// Logout the current user. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-logout -// This does not clear the credentials from the client instance. See ClearCredentials() instead. -func (cli *Client) Logout() (resp *RespLogout, err error) { - urlPath := cli.BuildURL("logout") - _, err = cli.MakeRequest("POST", urlPath, nil, &resp) - return -} - -// Versions returns the list of supported Matrix versions on this homeserver. See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-versions -func (cli *Client) Versions() (resp *RespVersions, err error) { - urlPath := cli.BuildBaseURL("_matrix", "client", "versions") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias -// -// If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will -// be JSON encoded and used as the request body. -func (cli *Client) JoinRoom(roomIDorAlias, serverName string, content interface{}) (resp *RespJoinRoom, err error) { - var urlPath string - if serverName != "" { - urlPath = cli.BuildURLWithQuery([]string{"join", roomIDorAlias}, map[string]string{ - "server_name": serverName, - }) - } else { - urlPath = cli.BuildURL("join", roomIDorAlias) - } - _, err = cli.MakeRequest("POST", urlPath, content, &resp) - return -} - -// GetDisplayName returns the display name of the user from the specified MXID. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -func (cli *Client) GetDisplayName(mxid string) (resp *RespUserDisplayName, err error) { - urlPath := cli.BuildURL("profile", mxid, "displayname") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// GetOwnDisplayName returns the user's display name. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -func (cli *Client) GetOwnDisplayName() (resp *RespUserDisplayName, err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "displayname") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// SetDisplayName sets the user's profile display name. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-displayname -func (cli *Client) SetDisplayName(displayName string) (err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "displayname") - s := struct { - DisplayName string `json:"displayname"` - }{displayName} - _, err = cli.MakeRequest("PUT", urlPath, &s, nil) - return -} - -// GetAvatarURL gets the user's avatar URL. See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-avatar-url -func (cli *Client) GetAvatarURL() (url string, err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url") - s := struct { - AvatarURL string `json:"avatar_url"` - }{} - - _, err = cli.MakeRequest("GET", urlPath, nil, &s) - if err != nil { - return "", err - } - - return s.AvatarURL, nil -} - -// SetAvatarURL sets the user's avatar URL. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-profile-userid-avatar-url -func (cli *Client) SetAvatarURL(url string) (err error) { - urlPath := cli.BuildURL("profile", cli.UserID, "avatar_url") - s := struct { - AvatarURL string `json:"avatar_url"` - }{url} - _, err = cli.MakeRequest("PUT", urlPath, &s, nil) - if err != nil { - return err - } - - return nil -} - -// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) { - txnID := txnID() - urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey -// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal. -func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) { - urlPath := cli.BuildURL("rooms", roomID, "state", eventType, stateKey) - _, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp) - return -} - -// SendText sends an m.room.message event into the given room with a msgtype of m.text -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-text -func (cli *Client) SendText(roomID, text string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, "m.room.message", - TextMessage{"m.text", text}) -} - -// SendImage sends an m.room.message event into the given room with a msgtype of m.image -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-image -func (cli *Client) SendImage(roomID, body, url string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, "m.room.message", - ImageMessage{ - MsgType: "m.image", - Body: body, - URL: url, - }) -} - -// SendVideo sends an m.room.message event into the given room with a msgtype of m.video -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-video -func (cli *Client) SendVideo(roomID, body, url string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, "m.room.message", - VideoMessage{ - MsgType: "m.video", - Body: body, - URL: url, - }) -} - -// SendNotice sends an m.room.message event into the given room with a msgtype of m.notice -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-notice -func (cli *Client) SendNotice(roomID, text string) (*RespSendEvent, error) { - return cli.SendMessageEvent(roomID, "m.room.message", - TextMessage{"m.notice", text}) -} - -// RedactEvent redacts the given event. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid -func (cli *Client) RedactEvent(roomID, eventID string, req *ReqRedact) (resp *RespSendEvent, err error) { - txnID := txnID() - urlPath := cli.BuildURL("rooms", roomID, "redact", eventID, txnID) - _, err = cli.MakeRequest("PUT", urlPath, req, &resp) - return -} - -// CreateRoom creates a new Matrix room. See https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -// resp, err := cli.CreateRoom(&gomatrix.ReqCreateRoom{ -// Preset: "public_chat", -// }) -// fmt.Println("Room:", resp.RoomID) -func (cli *Client) CreateRoom(req *ReqCreateRoom) (resp *RespCreateRoom, err error) { - urlPath := cli.BuildURL("createRoom") - _, err = cli.MakeRequest("POST", urlPath, req, &resp) - return -} - -// LeaveRoom leaves the given room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave -func (cli *Client) LeaveRoom(roomID string) (resp *RespLeaveRoom, err error) { - u := cli.BuildURL("rooms", roomID, "leave") - _, err = cli.MakeRequest("POST", u, struct{}{}, &resp) - return -} - -// ForgetRoom forgets a room entirely. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-forget -func (cli *Client) ForgetRoom(roomID string) (resp *RespForgetRoom, err error) { - u := cli.BuildURL("rooms", roomID, "forget") - _, err = cli.MakeRequest("POST", u, struct{}{}, &resp) - return -} - -// InviteUser invites a user to a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -func (cli *Client) InviteUser(roomID string, req *ReqInviteUser) (resp *RespInviteUser, err error) { - u := cli.BuildURL("rooms", roomID, "invite") - _, err = cli.MakeRequest("POST", u, struct{}{}, &resp) - return -} - -// InviteUserByThirdParty invites a third-party identifier to a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#invite-by-third-party-id-endpoint -func (cli *Client) InviteUserByThirdParty(roomID string, req *ReqInvite3PID) (resp *RespInviteUser, err error) { - u := cli.BuildURL("rooms", roomID, "invite") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// KickUser kicks a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -func (cli *Client) KickUser(roomID string, req *ReqKickUser) (resp *RespKickUser, err error) { - u := cli.BuildURL("rooms", roomID, "kick") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// BanUser bans a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -func (cli *Client) BanUser(roomID string, req *ReqBanUser) (resp *RespBanUser, err error) { - u := cli.BuildURL("rooms", roomID, "ban") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// UnbanUser unbans a user from a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -func (cli *Client) UnbanUser(roomID string, req *ReqUnbanUser) (resp *RespUnbanUser, err error) { - u := cli.BuildURL("rooms", roomID, "unban") - _, err = cli.MakeRequest("POST", u, req, &resp) - return -} - -// UserTyping sets the typing status of the user. See https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -func (cli *Client) UserTyping(roomID string, typing bool, timeout int64) (resp *RespTyping, err error) { - req := ReqTyping{Typing: typing, Timeout: timeout} - u := cli.BuildURL("rooms", roomID, "typing", cli.UserID) - _, err = cli.MakeRequest("PUT", u, req, &resp) - return -} - -// StateEvent gets a single state event in a room. It will attempt to JSON unmarshal into the given "outContent" struct with -// the HTTP response body, or return an error. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey -func (cli *Client) StateEvent(roomID, eventType, stateKey string, outContent interface{}) (err error) { - u := cli.BuildURL("rooms", roomID, "state", eventType, stateKey) - _, err = cli.MakeRequest("GET", u, nil, outContent) - return -} - -// UploadLink uploads an HTTP URL and then returns an MXC URI. -func (cli *Client) UploadLink(link string) (*RespMediaUpload, error) { - res, err := cli.Client.Get(link) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - return cli.UploadToContentRepo(res.Body, res.Header.Get("Content-Type"), res.ContentLength) -} - -// UploadToContentRepo uploads the given bytes to the content repository and returns an MXC URI. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload -func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) { - req, err := http.NewRequest("POST", cli.BuildBaseURL("_matrix/media/r0/upload"), content) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", contentType) - req.ContentLength = contentLength - res, err := cli.Client.Do(req) - if res != nil { - defer res.Body.Close() - } - if err != nil { - return nil, err - } - if res.StatusCode != 200 { - contents, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, HTTPError{ - Message: "Upload request failed - Failed to read response body: " + err.Error(), - Code: res.StatusCode, - } - } - return nil, HTTPError{ - Message: "Upload request failed: " + string(contents), - Code: res.StatusCode, - } - } - var m RespMediaUpload - if err := json.NewDecoder(res.Body).Decode(&m); err != nil { - return nil, err - } - return &m, nil -} - -// JoinedMembers returns a map of joined room members. See TODO-SPEC. https://github.com/matrix-org/synapse/pull/1680 -// -// In general, usage of this API is discouraged in favour of /sync, as calling this API can race with incoming membership changes. -// This API is primarily designed for application services which may want to efficiently look up joined members in a room. -func (cli *Client) JoinedMembers(roomID string) (resp *RespJoinedMembers, err error) { - u := cli.BuildURL("rooms", roomID, "joined_members") - _, err = cli.MakeRequest("GET", u, nil, &resp) - return -} - -// JoinedRooms returns a list of rooms which the client is joined to. See TODO-SPEC. https://github.com/matrix-org/synapse/pull/1680 -// -// In general, usage of this API is discouraged in favour of /sync, as calling this API can race with incoming membership changes. -// This API is primarily designed for application services which may want to efficiently look up joined rooms. -func (cli *Client) JoinedRooms() (resp *RespJoinedRooms, err error) { - u := cli.BuildURL("joined_rooms") - _, err = cli.MakeRequest("GET", u, nil, &resp) - return -} - -// Messages returns a list of message and state events for a room. It uses -// pagination query parameters to paginate history in the room. -// See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages -func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp *RespMessages, err error) { - query := map[string]string{ - "from": from, - "dir": string(dir), - } - if to != "" { - query["to"] = to - } - if limit != 0 { - query["limit"] = strconv.Itoa(limit) - } - - urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "messages"}, query) - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -// TurnServer returns turn server details and credentials for the client to use when initiating calls. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-voip-turnserver -func (cli *Client) TurnServer() (resp *RespTurnServer, err error) { - urlPath := cli.BuildURL("voip", "turnServer") - _, err = cli.MakeRequest("GET", urlPath, nil, &resp) - return -} - -func txnID() string { - return "go" + strconv.FormatInt(time.Now().UnixNano(), 10) -} - -// NewClient creates a new Matrix Client ready for syncing -func NewClient(homeserverURL, userID, accessToken string) (*Client, error) { - hsURL, err := url.Parse(homeserverURL) - if err != nil { - return nil, err - } - // By default, use an in-memory store which will never save filter ids / next batch tokens to disk. - // The client will work with this storer: it just won't remember across restarts. - // In practice, a database backend should be used. - store := NewInMemoryStore() - cli := Client{ - AccessToken: accessToken, - HomeserverURL: hsURL, - UserID: userID, - Prefix: "/_matrix/client/r0", - Syncer: NewDefaultSyncer(userID, store), - Store: store, - } - // By default, use the default HTTP client. - cli.Client = http.DefaultClient - - return &cli, nil -} diff --git a/vendor/github.com/matrix-org/gomatrix/client_examples_test.go b/vendor/github.com/matrix-org/gomatrix/client_examples_test.go deleted file mode 100644 index e3c0f09..0000000 --- a/vendor/github.com/matrix-org/gomatrix/client_examples_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package gomatrix - -import ( - "fmt" - "net/http" -) - -func Example_sync() { - cli, _ := NewClient("https://matrix.org", "@example:matrix.org", "MDAefhiuwehfuiwe") - cli.Store.SaveFilterID("@example:matrix.org", "2") // Optional: if you know it already - cli.Store.SaveNextBatch("@example:matrix.org", "111_222_333_444") // Optional: if you know it already - syncer := cli.Syncer.(*DefaultSyncer) - syncer.OnEventType("m.room.message", func(ev *Event) { - fmt.Println("Message: ", ev) - }) - - // Blocking version - if err := cli.Sync(); err != nil { - fmt.Println("Sync() returned ", err) - } - - // Non-blocking version - go func() { - for { - if err := cli.Sync(); err != nil { - fmt.Println("Sync() returned ", err) - } - // Optional: Wait a period of time before trying to sync again. - } - }() -} - -func Example_customInterfaces() { - // Custom interfaces must be set prior to calling functions on the client. - cli, _ := NewClient("https://matrix.org", "@example:matrix.org", "MDAefhiuwehfuiwe") - - // anything which implements the Storer interface - customStore := NewInMemoryStore() - cli.Store = customStore - - // anything which implements the Syncer interface - customSyncer := NewDefaultSyncer("@example:matrix.org", customStore) - cli.Syncer = customSyncer - - // any http.Client - cli.Client = http.DefaultClient - - // Once you call a function, you can't safely change the interfaces. - cli.SendText("!foo:bar", "Down the rabbit hole") -} - -func ExampleClient_BuildURLWithQuery() { - cli, _ := NewClient("https://matrix.org", "@example:matrix.org", "abcdef123456") - out := cli.BuildURLWithQuery([]string{"sync"}, map[string]string{ - "filter_id": "5", - }) - fmt.Println(out) - // Output: https://matrix.org/_matrix/client/r0/sync?access_token=abcdef123456&filter_id=5 -} - -func ExampleClient_BuildURL() { - userID := "@example:matrix.org" - cli, _ := NewClient("https://matrix.org", userID, "abcdef123456") - out := cli.BuildURL("user", userID, "filter") - fmt.Println(out) - // Output: https://matrix.org/_matrix/client/r0/user/@example:matrix.org/filter?access_token=abcdef123456 -} - -func ExampleClient_BuildBaseURL() { - userID := "@example:matrix.org" - cli, _ := NewClient("https://matrix.org", userID, "abcdef123456") - out := cli.BuildBaseURL("_matrix", "client", "r0", "directory", "room", "#matrix:matrix.org") - fmt.Println(out) - // Output: https://matrix.org/_matrix/client/r0/directory/room/%23matrix:matrix.org?access_token=abcdef123456 -} - -// Retrieve the content of a m.room.name state event. -func ExampleClient_StateEvent() { - content := struct { - Name string `json:"name"` - }{} - cli, _ := NewClient("https://matrix.org", "@example:matrix.org", "abcdef123456") - if err := cli.StateEvent("!foo:bar", "m.room.name", "", &content); err != nil { - panic(err) - } -} - -// Join a room by ID. -func ExampleClient_JoinRoom_id() { - cli, _ := NewClient("http://localhost:8008", "@example:localhost", "abcdef123456") - if _, err := cli.JoinRoom("!uOILRrqxnsYgQdUzar:localhost", "", nil); err != nil { - panic(err) - } -} - -// Join a room by alias. -func ExampleClient_JoinRoom_alias() { - cli, _ := NewClient("http://localhost:8008", "@example:localhost", "abcdef123456") - if resp, err := cli.JoinRoom("#test:localhost", "", nil); err != nil { - panic(err) - } else { - // Use room ID for something. - _ = resp.RoomID - } -} - -// Login to a local homeserver and set the user ID and access token on success. -func ExampleClient_Login() { - cli, _ := NewClient("http://localhost:8008", "", "") - resp, err := cli.Login(&ReqLogin{ - Type: "m.login.password", - User: "alice", - Password: "wonderland", - }) - if err != nil { - panic(err) - } - cli.SetCredentials(resp.UserID, resp.AccessToken) -} diff --git a/vendor/github.com/matrix-org/gomatrix/client_test.go b/vendor/github.com/matrix-org/gomatrix/client_test.go deleted file mode 100644 index 9b7d2da..0000000 --- a/vendor/github.com/matrix-org/gomatrix/client_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package gomatrix - -import ( - "bytes" - "fmt" - "io/ioutil" - "net/http" - "testing" -) - -func TestClient_LeaveRoom(t *testing.T) { - cli := mockClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "POST" && req.URL.Path == "/_matrix/client/r0/rooms/!foo:bar/leave" { - return &http.Response{ - StatusCode: 200, - Body: ioutil.NopCloser(bytes.NewBufferString(`{}`)), - }, nil - } - return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path) - }) - - if _, err := cli.LeaveRoom("!foo:bar"); err != nil { - t.Fatalf("LeaveRoom: error, got %s", err.Error()) - } -} - -func TestClient_GetAvatarUrl(t *testing.T) { - cli := mockClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "GET" && req.URL.Path == "/_matrix/client/r0/profile/@user:test.gomatrix.org/avatar_url" { - return &http.Response{ - StatusCode: 200, - Body: ioutil.NopCloser(bytes.NewBufferString(`{"avatar_url":"mxc://matrix.org/iJaUjkshgdfsdkjfn"}`)), - }, nil - } - return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path) - }) - - if response, err := cli.GetAvatarURL(); err != nil { - t.Fatalf("GetAvatarURL: Got error: %s", err.Error()) - } else if response == "" { - t.Fatal("GetAvatarURL: Got empty response") - } else if response != "mxc://matrix.org/iJaUjkshgdfsdkjfn" { - t.Fatalf("Unexpected response URL: %s", response) - } - -} - -func TestClient_SetAvatarUrl(t *testing.T) { - cli := mockClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "PUT" && req.URL.Path == "/_matrix/client/r0/profile/@user:test.gomatrix.org/avatar_url" { - return &http.Response{ - StatusCode: 200, - Body: ioutil.NopCloser(bytes.NewBufferString(`{}`)), - }, nil - } - return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path) - }) - - if err := cli.SetAvatarURL("https://foo.com/bar.png"); err != nil { - t.Fatalf("GetAvatarURL: Got error: %s", err.Error()) - } -} - -func TestClient_StateEvent(t *testing.T) { - cli := mockClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "GET" && req.URL.Path == "/_matrix/client/r0/rooms/!foo:bar/state/m.room.name" { - return &http.Response{ - StatusCode: 200, - Body: ioutil.NopCloser(bytes.NewBufferString(`{"name":"Room Name Goes Here"}`)), - }, nil - } - return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path) - }) - - content := struct { - Name string `json:"name"` - }{} - - if err := cli.StateEvent("!foo:bar", "m.room.name", "", &content); err != nil { - t.Fatalf("StateEvent: error, got %s", err.Error()) - } - if content.Name != "Room Name Goes Here" { - t.Fatalf("StateEvent: got %s, want %s", content.Name, "Room Name Goes Here") - } -} - -func mockClient(fn func(*http.Request) (*http.Response, error)) *Client { - mrt := MockRoundTripper{ - RT: fn, - } - - cli, _ := NewClient("https://test.gomatrix.org", "@user:test.gomatrix.org", "abcdef") - cli.Client = &http.Client{ - Transport: mrt, - } - return cli -} - -type MockRoundTripper struct { - RT func(*http.Request) (*http.Response, error) -} - -func (t MockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - return t.RT(req) -} diff --git a/vendor/github.com/matrix-org/gomatrix/events.go b/vendor/github.com/matrix-org/gomatrix/events.go deleted file mode 100644 index 7427740..0000000 --- a/vendor/github.com/matrix-org/gomatrix/events.go +++ /dev/null @@ -1,101 +0,0 @@ -package gomatrix - -import ( - "html" - "regexp" -) - -// Event represents a single Matrix event. -type Event struct { - StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events. - Sender string `json:"sender"` // The user ID of the sender of the event - Type string `json:"type"` // The event type - Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server - ID string `json:"event_id"` // The unique ID of this event - RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence) - Content map[string]interface{} `json:"content"` // The JSON content of the event. -} - -// Body returns the value of the "body" key in the event content if it is -// present and is a string. -func (event *Event) Body() (body string, ok bool) { - value, exists := event.Content["body"] - if !exists { - return - } - body, ok = value.(string) - return -} - -// MessageType returns the value of the "msgtype" key in the event content if -// it is present and is a string. -func (event *Event) MessageType() (msgtype string, ok bool) { - value, exists := event.Content["msgtype"] - if !exists { - return - } - msgtype, ok = value.(string) - return -} - -// TextMessage is the contents of a Matrix formated message event. -type TextMessage struct { - MsgType string `json:"msgtype"` - Body string `json:"body"` -} - -// ImageInfo contains info about an image - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-image -type ImageInfo struct { - Height uint `json:"h,omitempty"` - Width uint `json:"w,omitempty"` - Mimetype string `json:"mimetype,omitempty"` - Size uint `json:"size,omitempty"` -} - -// VideoInfo contains info about a video - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video -type VideoInfo struct { - Mimetype string `json:"mimetype,omitempty"` - ThumbnailInfo ImageInfo `json:"thumbnail_info"` - ThumbnailURL string `json:"thumbnail_url,omitempty"` - Height uint `json:"h,omitempty"` - Width uint `json:"w,omitempty"` - Duration uint `json:"duration,omitempty"` - Size uint `json:"size,omitempty"` -} - -// VideoMessage is an m.video - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video -type VideoMessage struct { - MsgType string `json:"msgtype"` - Body string `json:"body"` - URL string `json:"url"` - Info VideoInfo `json:"info"` -} - -// ImageMessage is an m.image event -type ImageMessage struct { - MsgType string `json:"msgtype"` - Body string `json:"body"` - URL string `json:"url"` - Info ImageInfo `json:"info"` -} - -// An HTMLMessage is the contents of a Matrix HTML formated message event. -type HTMLMessage struct { - Body string `json:"body"` - MsgType string `json:"msgtype"` - Format string `json:"format"` - FormattedBody string `json:"formatted_body"` -} - -var htmlRegex = regexp.MustCompile("<[^<]+?>") - -// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition -// to the provided HTML. -func GetHTMLMessage(msgtype, htmlText string) HTMLMessage { - return HTMLMessage{ - Body: html.UnescapeString(htmlRegex.ReplaceAllLiteralString(htmlText, "")), - MsgType: msgtype, - Format: "org.matrix.custom.html", - FormattedBody: htmlText, - } -} diff --git a/vendor/github.com/matrix-org/gomatrix/filter.go b/vendor/github.com/matrix-org/gomatrix/filter.go deleted file mode 100644 index e4e7628..0000000 --- a/vendor/github.com/matrix-org/gomatrix/filter.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 Jan Christian Grünhage -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package gomatrix - -//Filter is used by clients to specify how the server should filter responses to e.g. sync requests -//Specified by: https://matrix.org/docs/spec/client_server/r0.2.0.html#filtering -type Filter struct { - AccountData FilterPart `json:"account_data,omitempty"` - EventFields []string `json:"event_fields,omitempty"` - EventFormat string `json:"event_format,omitempty"` - Presence FilterPart `json:"presence,omitempty"` - Room struct { - AccountData FilterPart `json:"account_data,omitempty"` - Ephemeral FilterPart `json:"ephemeral,omitempty"` - IncludeLeave bool `json:"include_leave,omitempty"` - NotRooms []string `json:"not_rooms,omitempty"` - Rooms []string `json:"rooms,omitempty"` - State FilterPart `json:"state,omitempty"` - Timeline FilterPart `json:"timeline,omitempty"` - } `json:"room,omitempty"` -} - -type FilterPart struct { - NotRooms []string `json:"not_rooms,omitempty"` - Rooms []string `json:"rooms,omitempty"` - Limit *int `json:"limit,omitempty"` - NotSenders []string `json:"not_senders,omitempty"` - NotTypes []string `json:"not_types,omitempty"` - Senders []string `json:"senders,omitempty"` - Types []string `json:"types,omitempty"` -} diff --git a/vendor/github.com/matrix-org/gomatrix/hooks/install.sh b/vendor/github.com/matrix-org/gomatrix/hooks/install.sh deleted file mode 100755 index f8aa331..0000000 --- a/vendor/github.com/matrix-org/gomatrix/hooks/install.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/bash - -DOT_GIT="$(dirname $0)/../.git" - -ln -s "../../hooks/pre-commit" "$DOT_GIT/hooks/pre-commit" \ No newline at end of file diff --git a/vendor/github.com/matrix-org/gomatrix/hooks/pre-commit b/vendor/github.com/matrix-org/gomatrix/hooks/pre-commit deleted file mode 100755 index bb0a27f..0000000 --- a/vendor/github.com/matrix-org/gomatrix/hooks/pre-commit +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/bash - -set -eu - -golint -misspell --error . - -# gofmt doesn't exit with an error code if the files don't match the expected -# format. So we have to run it and see if it outputs anything. -if gofmt -l -s . 2>&1 | read -then - echo "Error: not all code had been formatted with gofmt." - echo "Fixing the following files" - gofmt -s -w -l . - echo - echo "Please add them to the commit" - git status --short - exit 1 -fi - -ineffassign . - -go fmt -go tool vet --all --shadow . -gocyclo -over 12 . -go test -timeout 5s -test.v diff --git a/vendor/github.com/matrix-org/gomatrix/requests.go b/vendor/github.com/matrix-org/gomatrix/requests.go deleted file mode 100644 index af99a22..0000000 --- a/vendor/github.com/matrix-org/gomatrix/requests.go +++ /dev/null @@ -1,78 +0,0 @@ -package gomatrix - -// ReqRegister is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -type ReqRegister struct { - Username string `json:"username,omitempty"` - BindEmail bool `json:"bind_email,omitempty"` - Password string `json:"password,omitempty"` - DeviceID string `json:"device_id,omitempty"` - InitialDeviceDisplayName string `json:"initial_device_display_name"` - Auth interface{} `json:"auth,omitempty"` -} - -// ReqLogin is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -type ReqLogin struct { - Type string `json:"type"` - Password string `json:"password,omitempty"` - Medium string `json:"medium,omitempty"` - User string `json:"user,omitempty"` - Address string `json:"address,omitempty"` - Token string `json:"token,omitempty"` - DeviceID string `json:"device_id,omitempty"` - InitialDeviceDisplayName string `json:"initial_device_display_name,omitempty"` -} - -// ReqCreateRoom is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type ReqCreateRoom struct { - Visibility string `json:"visibility,omitempty"` - RoomAliasName string `json:"room_alias_name,omitempty"` - Name string `json:"name,omitempty"` - Topic string `json:"topic,omitempty"` - Invite []string `json:"invite,omitempty"` - Invite3PID []ReqInvite3PID `json:"invite_3pid,omitempty"` - CreationContent map[string]interface{} `json:"creation_content,omitempty"` - InitialState []Event `json:"initial_state,omitempty"` - Preset string `json:"preset,omitempty"` - IsDirect bool `json:"is_direct,omitempty"` -} - -// ReqRedact is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid -type ReqRedact struct { - Reason string `json:"reason,omitempty"` -} - -// ReqInvite3PID is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#id57 -// It is also a JSON object used in https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type ReqInvite3PID struct { - IDServer string `json:"id_server"` - Medium string `json:"medium"` - Address string `json:"address"` -} - -// ReqInviteUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -type ReqInviteUser struct { - UserID string `json:"user_id"` -} - -// ReqKickUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -type ReqKickUser struct { - Reason string `json:"reason,omitempty"` - UserID string `json:"user_id"` -} - -// ReqBanUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -type ReqBanUser struct { - Reason string `json:"reason,omitempty"` - UserID string `json:"user_id"` -} - -// ReqUnbanUser is the JSON request for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -type ReqUnbanUser struct { - UserID string `json:"user_id"` -} - -// ReqTyping is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -type ReqTyping struct { - Typing bool `json:"typing"` - Timeout int64 `json:"timeout"` -} diff --git a/vendor/github.com/matrix-org/gomatrix/responses.go b/vendor/github.com/matrix-org/gomatrix/responses.go deleted file mode 100644 index fe0eeb3..0000000 --- a/vendor/github.com/matrix-org/gomatrix/responses.go +++ /dev/null @@ -1,176 +0,0 @@ -package gomatrix - -// RespError is the standard JSON error response from Homeservers. It also implements the Golang "error" interface. -// See http://matrix.org/docs/spec/client_server/r0.2.0.html#api-standards -type RespError struct { - ErrCode string `json:"errcode"` - Err string `json:"error"` -} - -// Error returns the errcode and error message. -func (e RespError) Error() string { - return e.ErrCode + ": " + e.Err -} - -// RespCreateFilter is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-user-userid-filter -type RespCreateFilter struct { - FilterID string `json:"filter_id"` -} - -// RespVersions is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-versions -type RespVersions struct { - Versions []string `json:"versions"` -} - -// RespJoinRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-join -type RespJoinRoom struct { - RoomID string `json:"room_id"` -} - -// RespLeaveRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-leave -type RespLeaveRoom struct{} - -// RespForgetRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-forget -type RespForgetRoom struct{} - -// RespInviteUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-invite -type RespInviteUser struct{} - -// RespKickUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-kick -type RespKickUser struct{} - -// RespBanUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-ban -type RespBanUser struct{} - -// RespUnbanUser is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-unban -type RespUnbanUser struct{} - -// RespTyping is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid -type RespTyping struct{} - -// RespJoinedRooms is the JSON response for TODO-SPEC https://github.com/matrix-org/synapse/pull/1680 -type RespJoinedRooms struct { - JoinedRooms []string `json:"joined_rooms"` -} - -// RespJoinedMembers is the JSON response for TODO-SPEC https://github.com/matrix-org/synapse/pull/1680 -type RespJoinedMembers struct { - Joined map[string]struct { - DisplayName *string `json:"display_name"` - AvatarURL *string `json:"avatar_url"` - } `json:"joined"` -} - -// RespMessages is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages -type RespMessages struct { - Start string `json:"start"` - Chunk []Event `json:"chunk"` - End string `json:"end"` -} - -// RespSendEvent is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid -type RespSendEvent struct { - EventID string `json:"event_id"` -} - -// RespMediaUpload is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload -type RespMediaUpload struct { - ContentURI string `json:"content_uri"` -} - -// RespUserInteractive is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#user-interactive-authentication-api -type RespUserInteractive struct { - Flows []struct { - Stages []string `json:"stages"` - } `json:"flows"` - Params map[string]interface{} `json:"params"` - Session string `json:"string"` - Completed []string `json:"completed"` - ErrCode string `json:"errcode"` - Error string `json:"error"` -} - -// HasSingleStageFlow returns true if there exists at least 1 Flow with a single stage of stageName. -func (r RespUserInteractive) HasSingleStageFlow(stageName string) bool { - for _, f := range r.Flows { - if len(f.Stages) == 1 && f.Stages[0] == stageName { - return true - } - } - return false -} - -// RespUserDisplayName is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-profile-userid-displayname -type RespUserDisplayName struct { - DisplayName string `json:"displayname"` -} - -// RespRegister is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register -type RespRegister struct { - AccessToken string `json:"access_token"` - DeviceID string `json:"device_id"` - HomeServer string `json:"home_server"` - RefreshToken string `json:"refresh_token"` - UserID string `json:"user_id"` -} - -// RespLogin is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-login -type RespLogin struct { - AccessToken string `json:"access_token"` - DeviceID string `json:"device_id"` - HomeServer string `json:"home_server"` - UserID string `json:"user_id"` -} - -// RespLogout is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-logout -type RespLogout struct{} - -// RespCreateRoom is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-createroom -type RespCreateRoom struct { - RoomID string `json:"room_id"` -} - -// RespSync is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync -type RespSync struct { - NextBatch string `json:"next_batch"` - AccountData struct { - Events []Event `json:"events"` - } `json:"account_data"` - Presence struct { - Events []Event `json:"events"` - } `json:"presence"` - Rooms struct { - Leave map[string]struct { - State struct { - Events []Event `json:"events"` - } `json:"state"` - Timeline struct { - Events []Event `json:"events"` - Limited bool `json:"limited"` - PrevBatch string `json:"prev_batch"` - } `json:"timeline"` - } `json:"leave"` - Join map[string]struct { - State struct { - Events []Event `json:"events"` - } `json:"state"` - Timeline struct { - Events []Event `json:"events"` - Limited bool `json:"limited"` - PrevBatch string `json:"prev_batch"` - } `json:"timeline"` - } `json:"join"` - Invite map[string]struct { - State struct { - Events []Event - } `json:"invite_state"` - } `json:"invite"` - } `json:"rooms"` -} - -type RespTurnServer struct { - Username string `json:"username"` - Password string `json:"password"` - TTL int `json:"ttl"` - URIs []string `json:"uris"` -} diff --git a/vendor/github.com/matrix-org/gomatrix/room.go b/vendor/github.com/matrix-org/gomatrix/room.go deleted file mode 100644 index c9b2351..0000000 --- a/vendor/github.com/matrix-org/gomatrix/room.go +++ /dev/null @@ -1,50 +0,0 @@ -package gomatrix - -// Room represents a single Matrix room. -type Room struct { - ID string - State map[string]map[string]*Event -} - -// UpdateState updates the room's current state with the given Event. This will clobber events based -// on the type/state_key combination. -func (room Room) UpdateState(event *Event) { - _, exists := room.State[event.Type] - if !exists { - room.State[event.Type] = make(map[string]*Event) - } - room.State[event.Type][*event.StateKey] = event -} - -// GetStateEvent returns the state event for the given type/state_key combo, or nil. -func (room Room) GetStateEvent(eventType string, stateKey string) *Event { - stateEventMap, _ := room.State[eventType] - event, _ := stateEventMap[stateKey] - return event -} - -// GetMembershipState returns the membership state of the given user ID in this room. If there is -// no entry for this member, 'leave' is returned for consistency with left users. -func (room Room) GetMembershipState(userID string) string { - state := "leave" - event := room.GetStateEvent("m.room.member", userID) - if event != nil { - membershipState, found := event.Content["membership"] - if found { - mState, isString := membershipState.(string) - if isString { - state = mState - } - } - } - return state -} - -// NewRoom creates a new Room with the given ID -func NewRoom(roomID string) *Room { - // Init the State map and return a pointer to the Room - return &Room{ - ID: roomID, - State: make(map[string]map[string]*Event), - } -} diff --git a/vendor/github.com/matrix-org/gomatrix/store.go b/vendor/github.com/matrix-org/gomatrix/store.go deleted file mode 100644 index 6dc687e..0000000 --- a/vendor/github.com/matrix-org/gomatrix/store.go +++ /dev/null @@ -1,65 +0,0 @@ -package gomatrix - -// Storer is an interface which must be satisfied to store client data. -// -// You can either write a struct which persists this data to disk, or you can use the -// provided "InMemoryStore" which just keeps data around in-memory which is lost on -// restarts. -type Storer interface { - SaveFilterID(userID, filterID string) - LoadFilterID(userID string) string - SaveNextBatch(userID, nextBatchToken string) - LoadNextBatch(userID string) string - SaveRoom(room *Room) - LoadRoom(roomID string) *Room -} - -// InMemoryStore implements the Storer interface. -// -// Everything is persisted in-memory as maps. It is not safe to load/save filter IDs -// or next batch tokens on any goroutine other than the syncing goroutine: the one -// which called Client.Sync(). -type InMemoryStore struct { - Filters map[string]string - NextBatch map[string]string - Rooms map[string]*Room -} - -// SaveFilterID to memory. -func (s *InMemoryStore) SaveFilterID(userID, filterID string) { - s.Filters[userID] = filterID -} - -// LoadFilterID from memory. -func (s *InMemoryStore) LoadFilterID(userID string) string { - return s.Filters[userID] -} - -// SaveNextBatch to memory. -func (s *InMemoryStore) SaveNextBatch(userID, nextBatchToken string) { - s.NextBatch[userID] = nextBatchToken -} - -// LoadNextBatch from memory. -func (s *InMemoryStore) LoadNextBatch(userID string) string { - return s.NextBatch[userID] -} - -// SaveRoom to memory. -func (s *InMemoryStore) SaveRoom(room *Room) { - s.Rooms[room.ID] = room -} - -// LoadRoom from memory. -func (s *InMemoryStore) LoadRoom(roomID string) *Room { - return s.Rooms[roomID] -} - -// NewInMemoryStore constructs a new InMemoryStore. -func NewInMemoryStore() *InMemoryStore { - return &InMemoryStore{ - Filters: make(map[string]string), - NextBatch: make(map[string]string), - Rooms: make(map[string]*Room), - } -} diff --git a/vendor/github.com/matrix-org/gomatrix/sync.go b/vendor/github.com/matrix-org/gomatrix/sync.go deleted file mode 100644 index c4bea48..0000000 --- a/vendor/github.com/matrix-org/gomatrix/sync.go +++ /dev/null @@ -1,164 +0,0 @@ -package gomatrix - -import ( - "encoding/json" - "fmt" - "runtime/debug" - "time" -) - -// Syncer represents an interface that must be satisfied in order to do /sync requests on a client. -type Syncer interface { - // Process the /sync response. The since parameter is the since= value that was used to produce the response. - // This is useful for detecting the very first sync (since=""). If an error is return, Syncing will be stopped - // permanently. - ProcessResponse(resp *RespSync, since string) error - // OnFailedSync returns either the time to wait before retrying or an error to stop syncing permanently. - OnFailedSync(res *RespSync, err error) (time.Duration, error) - // GetFilterJSON for the given user ID. NOT the filter ID. - GetFilterJSON(userID string) json.RawMessage -} - -// DefaultSyncer is the default syncing implementation. You can either write your own syncer, or selectively -// replace parts of this default syncer (e.g. the ProcessResponse method). The default syncer uses the observer -// pattern to notify callers about incoming events. See DefaultSyncer.OnEventType for more information. -type DefaultSyncer struct { - UserID string - Store Storer - listeners map[string][]OnEventListener // event type to listeners array -} - -// OnEventListener can be used with DefaultSyncer.OnEventType to be informed of incoming events. -type OnEventListener func(*Event) - -// NewDefaultSyncer returns an instantiated DefaultSyncer -func NewDefaultSyncer(userID string, store Storer) *DefaultSyncer { - return &DefaultSyncer{ - UserID: userID, - Store: store, - listeners: make(map[string][]OnEventListener), - } -} - -// ProcessResponse processes the /sync response in a way suitable for bots. "Suitable for bots" means a stream of -// unrepeating events. Returns a fatal error if a listener panics. -func (s *DefaultSyncer) ProcessResponse(res *RespSync, since string) (err error) { - if !s.shouldProcessResponse(res, since) { - return - } - - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("ProcessResponse panicked! userID=%s since=%s panic=%s\n%s", s.UserID, since, r, debug.Stack()) - } - }() - - for roomID, roomData := range res.Rooms.Join { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.State.Events { - event.RoomID = roomID - room.UpdateState(&event) - s.notifyListeners(&event) - } - for _, event := range roomData.Timeline.Events { - event.RoomID = roomID - s.notifyListeners(&event) - } - } - for roomID, roomData := range res.Rooms.Invite { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.State.Events { - event.RoomID = roomID - room.UpdateState(&event) - s.notifyListeners(&event) - } - } - for roomID, roomData := range res.Rooms.Leave { - room := s.getOrCreateRoom(roomID) - for _, event := range roomData.Timeline.Events { - if event.StateKey != nil { - event.RoomID = roomID - room.UpdateState(&event) - s.notifyListeners(&event) - } - } - } - return -} - -// OnEventType allows callers to be notified when there are new events for the given event type. -// There are no duplicate checks. -func (s *DefaultSyncer) OnEventType(eventType string, callback OnEventListener) { - _, exists := s.listeners[eventType] - if !exists { - s.listeners[eventType] = []OnEventListener{} - } - s.listeners[eventType] = append(s.listeners[eventType], callback) -} - -// shouldProcessResponse returns true if the response should be processed. May modify the response to remove -// stuff that shouldn't be processed. -func (s *DefaultSyncer) shouldProcessResponse(resp *RespSync, since string) bool { - if since == "" { - return false - } - // This is a horrible hack because /sync will return the most recent messages for a room - // as soon as you /join it. We do NOT want to process those events in that particular room - // because they may have already been processed (if you toggle the bot in/out of the room). - // - // Work around this by inspecting each room's timeline and seeing if an m.room.member event for us - // exists and is "join" and then discard processing that room entirely if so. - // TODO: We probably want to process messages from after the last join event in the timeline. - for roomID, roomData := range resp.Rooms.Join { - for i := len(roomData.Timeline.Events) - 1; i >= 0; i-- { - e := roomData.Timeline.Events[i] - if e.Type == "m.room.member" && e.StateKey != nil && *e.StateKey == s.UserID { - m := e.Content["membership"] - mship, ok := m.(string) - if !ok { - continue - } - if mship == "join" { - _, ok := resp.Rooms.Join[roomID] - if !ok { - continue - } - delete(resp.Rooms.Join, roomID) // don't re-process messages - delete(resp.Rooms.Invite, roomID) // don't re-process invites - break - } - } - } - } - return true -} - -// getOrCreateRoom must only be called by the Sync() goroutine which calls ProcessResponse() -func (s *DefaultSyncer) getOrCreateRoom(roomID string) *Room { - room := s.Store.LoadRoom(roomID) - if room == nil { // create a new Room - room = NewRoom(roomID) - s.Store.SaveRoom(room) - } - return room -} - -func (s *DefaultSyncer) notifyListeners(event *Event) { - listeners, exists := s.listeners[event.Type] - if !exists { - return - } - for _, fn := range listeners { - fn(event) - } -} - -// OnFailedSync always returns a 10 second wait period between failed /syncs, never a fatal error. -func (s *DefaultSyncer) OnFailedSync(res *RespSync, err error) (time.Duration, error) { - return 10 * time.Second, nil -} - -// GetFilterJSON returns a filter with a timeline limit of 50. -func (s *DefaultSyncer) GetFilterJSON(userID string) json.RawMessage { - return json.RawMessage(`{"room":{"timeline":{"limit":50}}}`) -} diff --git a/vendor/github.com/matrix-org/gomatrix/userids.go b/vendor/github.com/matrix-org/gomatrix/userids.go deleted file mode 100644 index 23e7807..0000000 --- a/vendor/github.com/matrix-org/gomatrix/userids.go +++ /dev/null @@ -1,130 +0,0 @@ -package gomatrix - -import ( - "bytes" - "encoding/hex" - "fmt" - "strings" -) - -const lowerhex = "0123456789abcdef" - -// encode the given byte using quoted-printable encoding (e.g "=2f") -// and writes it to the buffer -// See https://golang.org/src/mime/quotedprintable/writer.go -func encode(buf *bytes.Buffer, b byte) { - buf.WriteByte('=') - buf.WriteByte(lowerhex[b>>4]) - buf.WriteByte(lowerhex[b&0x0f]) -} - -// escape the given alpha character and writes it to the buffer -func escape(buf *bytes.Buffer, b byte) { - buf.WriteByte('_') - if b == '_' { - buf.WriteByte('_') // another _ - } else { - buf.WriteByte(b + 0x20) // ASCII shift A-Z to a-z - } -} - -func shouldEncode(b byte) bool { - return b != '-' && b != '.' && b != '_' && !(b >= '0' && b <= '9') && !(b >= 'a' && b <= 'z') && !(b >= 'A' && b <= 'Z') -} - -func shouldEscape(b byte) bool { - return (b >= 'A' && b <= 'Z') || b == '_' -} - -func isValidByte(b byte) bool { - return isValidEscapedChar(b) || (b >= '0' && b <= '9') || b == '.' || b == '=' || b == '-' -} - -func isValidEscapedChar(b byte) bool { - return b == '_' || (b >= 'a' && b <= 'z') -} - -// EncodeUserLocalpart encodes the given string into Matrix-compliant user ID localpart form. -// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets -// -// This returns a string with only the characters "a-z0-9._=-". The uppercase range A-Z -// are encoded using leading underscores ("_"). Characters outside the aforementioned ranges -// (including literal underscores ("_") and equals ("=")) are encoded as UTF8 code points (NOT NCRs) -// and converted to lower-case hex with a leading "=". For example: -// Alph@Bet_50up => _alph=40_bet=5f50up -func EncodeUserLocalpart(str string) string { - strBytes := []byte(str) - var outputBuffer bytes.Buffer - for _, b := range strBytes { - if shouldEncode(b) { - encode(&outputBuffer, b) - } else if shouldEscape(b) { - escape(&outputBuffer, b) - } else { - outputBuffer.WriteByte(b) - } - } - return outputBuffer.String() -} - -// DecodeUserLocalpart decodes the given string back into the original input string. -// Returns an error if the given string is not a valid user ID localpart encoding. -// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets -// -// This decodes quoted-printable bytes back into UTF8, and unescapes casing. For -// example: -// _alph=40_bet=5f50up => Alph@Bet_50up -// Returns an error if the input string contains characters outside the -// range "a-z0-9._=-", has an invalid quote-printable byte (e.g. not hex), or has -// an invalid _ escaped byte (e.g. "_5"). -func DecodeUserLocalpart(str string) (string, error) { - strBytes := []byte(str) - var outputBuffer bytes.Buffer - for i := 0; i < len(strBytes); i++ { - b := strBytes[i] - if !isValidByte(b) { - return "", fmt.Errorf("Byte pos %d: Invalid byte", i) - } - - if b == '_' { // next byte is a-z and should be upper-case or is another _ and should be a literal _ - if i+1 >= len(strBytes) { - return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding but ran out of string", i) - } - if !isValidEscapedChar(strBytes[i+1]) { // invalid escaping - return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding", i) - } - if strBytes[i+1] == '_' { - outputBuffer.WriteByte('_') - } else { - outputBuffer.WriteByte(strBytes[i+1] - 0x20) // ASCII shift a-z to A-Z - } - i++ // skip next byte since we just handled it - } else if b == '=' { // next 2 bytes are hex and should be buffered ready to be read as utf8 - if i+2 >= len(strBytes) { - return "", fmt.Errorf("Byte pos: %d: expected quote-printable encoding but ran out of string", i) - } - dst := make([]byte, 1) - _, err := hex.Decode(dst, strBytes[i+1:i+3]) - if err != nil { - return "", err - } - outputBuffer.WriteByte(dst[0]) - i += 2 // skip next 2 bytes since we just handled it - } else { // pass through - outputBuffer.WriteByte(b) - } - } - return outputBuffer.String(), nil -} - -// ExtractUserLocalpart extracts the localpart portion of a user ID. -// See http://matrix.org/docs/spec/intro.html#user-identifiers -func ExtractUserLocalpart(userID string) (string, error) { - if len(userID) == 0 || userID[0] != '@' { - return "", fmt.Errorf("%s is not a valid user id", userID) - } - return strings.TrimPrefix( - strings.SplitN(userID, ":", 2)[0], // @foo:bar:8448 => [ "@foo", "bar:8448" ] - "@", // remove "@" prefix - ), nil -} diff --git a/vendor/github.com/matrix-org/gomatrix/userids_examples_test.go b/vendor/github.com/matrix-org/gomatrix/userids_examples_test.go deleted file mode 100644 index 6386b32..0000000 --- a/vendor/github.com/matrix-org/gomatrix/userids_examples_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package gomatrix - -import "fmt" - -func ExampleEncodeUserLocalpart() { - localpart := EncodeUserLocalpart("Alph@Bet_50up") - fmt.Println(localpart) - // Output: _alph=40_bet__50up -} - -func ExampleDecodeUserLocalpart() { - localpart, err := DecodeUserLocalpart("_alph=40_bet__50up") - if err != nil { - panic(err) - } - fmt.Println(localpart) - // Output: Alph@Bet_50up -} - -func ExampleExtractUserLocalpart() { - localpart, err := ExtractUserLocalpart("@alice:matrix.org") - if err != nil { - panic(err) - } - fmt.Println(localpart) - // Output: alice -} diff --git a/vendor/github.com/matrix-org/gomatrix/userids_test.go b/vendor/github.com/matrix-org/gomatrix/userids_test.go deleted file mode 100644 index b896740..0000000 --- a/vendor/github.com/matrix-org/gomatrix/userids_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package gomatrix - -import ( - "testing" -) - -var useridtests = []struct { - Input string - Output string -}{ - {"Alph@Bet_50up", "_alph=40_bet__50up"}, // The doc example - {"abcdef", "abcdef"}, // no-op - {"i_like_pie_", "i__like__pie__"}, // double underscore escaping - {"ABCDEF", "_a_b_c_d_e_f"}, // all-caps - {"!£", "=21=c2=a3"}, // punctuation and outside ascii range (U+00A3 => c2 a3) - {"___", "______"}, // literal underscores - {"hello-world.", "hello-world."}, // allowed punctuation - {"5+5=10", "5=2b5=3d10"}, // equals sign - {"東方Project", "=e6=9d=b1=e6=96=b9_project"}, // CJK mixed - {" foo bar", "=09foo=20bar"}, // whitespace (tab and space) -} - -func TestEncodeUserLocalpart(t *testing.T) { - for _, u := range useridtests { - out := EncodeUserLocalpart(u.Input) - if out != u.Output { - t.Fatalf("TestEncodeUserLocalpart(%s) => Got: %s Expected: %s", u.Input, out, u.Output) - } - } -} - -func TestDecodeUserLocalpart(t *testing.T) { - for _, u := range useridtests { - in, _ := DecodeUserLocalpart(u.Output) - if in != u.Input { - t.Fatalf("TestDecodeUserLocalpart(%s) => Got: %s Expected: %s", u.Output, in, u.Input) - } - } -} - -var errtests = []struct { - Input string -}{ - {"foo@bar"}, // invalid character @ - {"foo_5bar"}, // invalid character after _ - {"foo_._-bar"}, // multiple invalid characters after _ - {"foo=2Hbar"}, // invalid hex after = - {"foo=2hbar"}, // invalid hex after = (lower-case) - {"foo=======2fbar"}, // multiple invalid hex after = - {"foo=2"}, // end of string after = - {"foo_"}, // end of string after _ -} - -func TestDecodeUserLocalpartErrors(t *testing.T) { - for _, u := range errtests { - out, err := DecodeUserLocalpart(u.Input) - if out != "" { - t.Fatalf("TestDecodeUserLocalpartErrors(%s) => Got: %s Expected: empty string", u.Input, out) - } - if err == nil { - t.Fatalf("TestDecodeUserLocalpartErrors(%s) => Got: nil error Expected: error", u.Input) - } - } -} - -var localparttests = []struct { - Input string - ExpectOutput string -}{ - {"@foo:bar", "foo"}, - {"@foo:bar:8448", "foo"}, - {"@foo.bar:baz.quuz", "foo.bar"}, -} - -func TestExtractUserLocalpart(t *testing.T) { - for _, u := range localparttests { - out, err := ExtractUserLocalpart(u.Input) - if err != nil { - t.Errorf("TestExtractUserLocalpart(%s) => Error: %s", u.Input, err) - continue - } - if out != u.ExpectOutput { - t.Errorf("TestExtractUserLocalpart(%s) => Got: %s, Want %s", u.Input, out, u.ExpectOutput) - } - } -} diff --git a/vendor/github.com/urfave/cli/.flake8 b/vendor/github.com/urfave/cli/.flake8 deleted file mode 100644 index 6deafc2..0000000 --- a/vendor/github.com/urfave/cli/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 120 diff --git a/vendor/github.com/urfave/cli/.gitignore b/vendor/github.com/urfave/cli/.gitignore deleted file mode 100644 index faf70c4..0000000 --- a/vendor/github.com/urfave/cli/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.coverprofile -node_modules/ diff --git a/vendor/github.com/urfave/cli/.travis.yml b/vendor/github.com/urfave/cli/.travis.yml deleted file mode 100644 index cf8d098..0000000 --- a/vendor/github.com/urfave/cli/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: go -sudo: false -dist: trusty -osx_image: xcode8.3 -go: 1.8.x - -os: -- linux -- osx - -cache: - directories: - - node_modules - -before_script: -- go get github.com/urfave/gfmrun/... || true -- go get golang.org/x/tools/cmd/goimports -- if [ ! -f node_modules/.bin/markdown-toc ] ; then - npm install markdown-toc ; - fi - -script: -- ./runtests gen -- ./runtests vet -- ./runtests test -- ./runtests gfmrun -- ./runtests toc diff --git a/vendor/github.com/urfave/cli/CHANGELOG.md b/vendor/github.com/urfave/cli/CHANGELOG.md deleted file mode 100644 index 401eae5..0000000 --- a/vendor/github.com/urfave/cli/CHANGELOG.md +++ /dev/null @@ -1,435 +0,0 @@ -# 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 -- -`cli.App.RunAndExitOnError`, which should now be done by returning an error -that fulfills `cli.ExitCoder` to `cli.App.Run`. -- 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 & 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 & 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 diff --git a/vendor/github.com/urfave/cli/LICENSE b/vendor/github.com/urfave/cli/LICENSE deleted file mode 100644 index 42a597e..0000000 --- a/vendor/github.com/urfave/cli/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -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. diff --git a/vendor/github.com/urfave/cli/README.md b/vendor/github.com/urfave/cli/README.md deleted file mode 100644 index 2bbbd8e..0000000 --- a/vendor/github.com/urfave/cli/README.md +++ /dev/null @@ -1,1381 +0,0 @@ -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. - - - -- [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 alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) - * [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) -- [Contribution Guidelines](#contribution-guidelines) - - - -## 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()`. - - -``` 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: - - -``` 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: - - -``` 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.: - - -``` 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. - - -``` 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. - - -``` 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: - - -```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. - - -``` 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: - - -``` 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. - - -``` 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. - - -``` 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 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: - - -``` 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) -} -``` - -### Subcommands - -Subcommands can be defined for a more git-like command line app. - - -```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", - }, - { - Name: "remove", - Category: "template", - }, - } - - 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. - - -``` 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/ -source /etc/bash_completion.d/ -``` - -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.: - - -``` 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.: - - -``` 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.: - - -``` 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.: - - -``` 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.: - - -``` 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. - - -``` 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 -} -``` - -## 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. diff --git a/vendor/github.com/urfave/cli/altsrc/altsrc.go b/vendor/github.com/urfave/cli/altsrc/altsrc.go deleted file mode 100644 index ac34bf6..0000000 --- a/vendor/github.com/urfave/cli/altsrc/altsrc.go +++ /dev/null @@ -1,3 +0,0 @@ -package altsrc - -//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go diff --git a/vendor/github.com/urfave/cli/altsrc/flag.go b/vendor/github.com/urfave/cli/altsrc/flag.go deleted file mode 100644 index 84ef009..0000000 --- a/vendor/github.com/urfave/cli/altsrc/flag.go +++ /dev/null @@ -1,261 +0,0 @@ -package altsrc - -import ( - "fmt" - "strconv" - "strings" - "syscall" - - "gopkg.in/urfave/cli.v1" -) - -// FlagInputSourceExtension is an extension interface of cli.Flag that -// allows a value to be set on the existing parsed flags. -type FlagInputSourceExtension interface { - cli.Flag - ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error -} - -// ApplyInputSourceValues iterates over all provided flags and -// executes ApplyInputSourceValue on flags implementing the -// FlagInputSourceExtension interface to initialize these flags -// to an alternate input source. -func ApplyInputSourceValues(context *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error { - for _, f := range flags { - inputSourceExtendedFlag, isType := f.(FlagInputSourceExtension) - if isType { - err := inputSourceExtendedFlag.ApplyInputSourceValue(context, inputSourceContext) - if err != nil { - return err - } - } - } - - return nil -} - -// InitInputSource is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new -// input source based on the func provided. If there is no error it will then apply the new input source to any flags -// that are supported by the input source -func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc { - return func(context *cli.Context) error { - inputSource, err := createInputSource() - if err != nil { - return fmt.Errorf("Unable to create input source: inner error: \n'%v'", err.Error()) - } - - return ApplyInputSourceValues(context, inputSource, flags) - } -} - -// InitInputSourceWithContext is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new -// input source based on the func provided with potentially using existing cli.Context values to initialize itself. If there is -// no error it will then apply the new input source to any flags that are supported by the input source -func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(context *cli.Context) (InputSourceContext, error)) cli.BeforeFunc { - return func(context *cli.Context) error { - inputSource, err := createInputSource(context) - if err != nil { - return fmt.Errorf("Unable to create input source with context: inner error: \n'%v'", err.Error()) - } - - return ApplyInputSourceValues(context, inputSource, flags) - } -} - -// ApplyInputSourceValue applies a generic value to the flagSet if required -func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) { - value, err := isc.Generic(f.GenericFlag.Name) - if err != nil { - return err - } - if value != nil { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, value.String()) - }) - } - } - } - - return nil -} - -// ApplyInputSourceValue applies a StringSlice value to the flagSet if required -func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) { - value, err := isc.StringSlice(f.StringSliceFlag.Name) - if err != nil { - return err - } - if value != nil { - var sliceValue cli.StringSlice = value - eachName(f.Name, func(name string) { - underlyingFlag := f.set.Lookup(f.Name) - if underlyingFlag != nil { - underlyingFlag.Value = &sliceValue - } - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a IntSlice value if required -func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) { - value, err := isc.IntSlice(f.IntSliceFlag.Name) - if err != nil { - return err - } - if value != nil { - var sliceValue cli.IntSlice = value - eachName(f.Name, func(name string) { - underlyingFlag := f.set.Lookup(f.Name) - if underlyingFlag != nil { - underlyingFlag.Value = &sliceValue - } - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a Bool value to the flagSet if required -func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) { - value, err := isc.Bool(f.BoolFlag.Name) - if err != nil { - return err - } - if value { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, strconv.FormatBool(value)) - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a BoolT value to the flagSet if required -func (f *BoolTFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) { - value, err := isc.BoolT(f.BoolTFlag.Name) - if err != nil { - return err - } - if !value { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, strconv.FormatBool(value)) - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a String value to the flagSet if required -func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) { - value, err := isc.String(f.StringFlag.Name) - if err != nil { - return err - } - if value != "" { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, value) - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a int value to the flagSet if required -func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) { - value, err := isc.Int(f.IntFlag.Name) - if err != nil { - return err - } - if value > 0 { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, strconv.FormatInt(int64(value), 10)) - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a Duration value to the flagSet if required -func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) { - value, err := isc.Duration(f.DurationFlag.Name) - if err != nil { - return err - } - if value > 0 { - eachName(f.Name, func(name string) { - f.set.Set(f.Name, value.String()) - }) - } - } - } - return nil -} - -// ApplyInputSourceValue applies a Float64 value to the flagSet if required -func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { - if f.set != nil { - if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) { - value, err := isc.Float64(f.Float64Flag.Name) - if err != nil { - return err - } - if value > 0 { - floatStr := float64ToString(value) - eachName(f.Name, func(name string) { - f.set.Set(f.Name, floatStr) - }) - } - } - } - return nil -} - -func isEnvVarSet(envVars string) bool { - for _, envVar := range strings.Split(envVars, ",") { - envVar = strings.TrimSpace(envVar) - if _, ok := syscall.Getenv(envVar); ok { - // TODO: Can't use this for bools as - // set means that it was true or false based on - // Bool flag type, should work for other types - return true - } - } - - return false -} - -func float64ToString(f float64) string { - return fmt.Sprintf("%v", f) -} - -func eachName(longName string, fn func(string)) { - parts := strings.Split(longName, ",") - for _, name := range parts { - name = strings.Trim(name, " ") - fn(name) - } -} diff --git a/vendor/github.com/urfave/cli/altsrc/flag_generated.go b/vendor/github.com/urfave/cli/altsrc/flag_generated.go deleted file mode 100644 index 0aeb0b0..0000000 --- a/vendor/github.com/urfave/cli/altsrc/flag_generated.go +++ /dev/null @@ -1,347 +0,0 @@ -package altsrc - -import ( - "flag" - - "gopkg.in/urfave/cli.v1" -) - -// WARNING: This file is generated! - -// BoolFlag is the flag type that wraps cli.BoolFlag to allow -// for other values to be specified -type BoolFlag struct { - cli.BoolFlag - set *flag.FlagSet -} - -// NewBoolFlag creates a new BoolFlag -func NewBoolFlag(fl cli.BoolFlag) *BoolFlag { - return &BoolFlag{BoolFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped BoolFlag.Apply -func (f *BoolFlag) Apply(set *flag.FlagSet) { - f.set = set - f.BoolFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped BoolFlag.ApplyWithError -func (f *BoolFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.BoolFlag.ApplyWithError(set) -} - -// BoolTFlag is the flag type that wraps cli.BoolTFlag to allow -// for other values to be specified -type BoolTFlag struct { - cli.BoolTFlag - set *flag.FlagSet -} - -// NewBoolTFlag creates a new BoolTFlag -func NewBoolTFlag(fl cli.BoolTFlag) *BoolTFlag { - return &BoolTFlag{BoolTFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped BoolTFlag.Apply -func (f *BoolTFlag) Apply(set *flag.FlagSet) { - f.set = set - f.BoolTFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped BoolTFlag.ApplyWithError -func (f *BoolTFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.BoolTFlag.ApplyWithError(set) -} - -// DurationFlag is the flag type that wraps cli.DurationFlag to allow -// for other values to be specified -type DurationFlag struct { - cli.DurationFlag - set *flag.FlagSet -} - -// NewDurationFlag creates a new DurationFlag -func NewDurationFlag(fl cli.DurationFlag) *DurationFlag { - return &DurationFlag{DurationFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped DurationFlag.Apply -func (f *DurationFlag) Apply(set *flag.FlagSet) { - f.set = set - f.DurationFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped DurationFlag.ApplyWithError -func (f *DurationFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.DurationFlag.ApplyWithError(set) -} - -// Float64Flag is the flag type that wraps cli.Float64Flag to allow -// for other values to be specified -type Float64Flag struct { - cli.Float64Flag - set *flag.FlagSet -} - -// NewFloat64Flag creates a new Float64Flag -func NewFloat64Flag(fl cli.Float64Flag) *Float64Flag { - return &Float64Flag{Float64Flag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped Float64Flag.Apply -func (f *Float64Flag) Apply(set *flag.FlagSet) { - f.set = set - f.Float64Flag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped Float64Flag.ApplyWithError -func (f *Float64Flag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.Float64Flag.ApplyWithError(set) -} - -// GenericFlag is the flag type that wraps cli.GenericFlag to allow -// for other values to be specified -type GenericFlag struct { - cli.GenericFlag - set *flag.FlagSet -} - -// NewGenericFlag creates a new GenericFlag -func NewGenericFlag(fl cli.GenericFlag) *GenericFlag { - return &GenericFlag{GenericFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped GenericFlag.Apply -func (f *GenericFlag) Apply(set *flag.FlagSet) { - f.set = set - f.GenericFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped GenericFlag.ApplyWithError -func (f *GenericFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.GenericFlag.ApplyWithError(set) -} - -// Int64Flag is the flag type that wraps cli.Int64Flag to allow -// for other values to be specified -type Int64Flag struct { - cli.Int64Flag - set *flag.FlagSet -} - -// NewInt64Flag creates a new Int64Flag -func NewInt64Flag(fl cli.Int64Flag) *Int64Flag { - return &Int64Flag{Int64Flag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped Int64Flag.Apply -func (f *Int64Flag) Apply(set *flag.FlagSet) { - f.set = set - f.Int64Flag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped Int64Flag.ApplyWithError -func (f *Int64Flag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.Int64Flag.ApplyWithError(set) -} - -// IntFlag is the flag type that wraps cli.IntFlag to allow -// for other values to be specified -type IntFlag struct { - cli.IntFlag - set *flag.FlagSet -} - -// NewIntFlag creates a new IntFlag -func NewIntFlag(fl cli.IntFlag) *IntFlag { - return &IntFlag{IntFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped IntFlag.Apply -func (f *IntFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped IntFlag.ApplyWithError -func (f *IntFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.IntFlag.ApplyWithError(set) -} - -// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow -// for other values to be specified -type IntSliceFlag struct { - cli.IntSliceFlag - set *flag.FlagSet -} - -// NewIntSliceFlag creates a new IntSliceFlag -func NewIntSliceFlag(fl cli.IntSliceFlag) *IntSliceFlag { - return &IntSliceFlag{IntSliceFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped IntSliceFlag.Apply -func (f *IntSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntSliceFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped IntSliceFlag.ApplyWithError -func (f *IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.IntSliceFlag.ApplyWithError(set) -} - -// Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow -// for other values to be specified -type Int64SliceFlag struct { - cli.Int64SliceFlag - set *flag.FlagSet -} - -// NewInt64SliceFlag creates a new Int64SliceFlag -func NewInt64SliceFlag(fl cli.Int64SliceFlag) *Int64SliceFlag { - return &Int64SliceFlag{Int64SliceFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped Int64SliceFlag.Apply -func (f *Int64SliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.Int64SliceFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped Int64SliceFlag.ApplyWithError -func (f *Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.Int64SliceFlag.ApplyWithError(set) -} - -// StringFlag is the flag type that wraps cli.StringFlag to allow -// for other values to be specified -type StringFlag struct { - cli.StringFlag - set *flag.FlagSet -} - -// NewStringFlag creates a new StringFlag -func NewStringFlag(fl cli.StringFlag) *StringFlag { - return &StringFlag{StringFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped StringFlag.Apply -func (f *StringFlag) Apply(set *flag.FlagSet) { - f.set = set - f.StringFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped StringFlag.ApplyWithError -func (f *StringFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.StringFlag.ApplyWithError(set) -} - -// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow -// for other values to be specified -type StringSliceFlag struct { - cli.StringSliceFlag - set *flag.FlagSet -} - -// NewStringSliceFlag creates a new StringSliceFlag -func NewStringSliceFlag(fl cli.StringSliceFlag) *StringSliceFlag { - return &StringSliceFlag{StringSliceFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped StringSliceFlag.Apply -func (f *StringSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.StringSliceFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped StringSliceFlag.ApplyWithError -func (f *StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.StringSliceFlag.ApplyWithError(set) -} - -// Uint64Flag is the flag type that wraps cli.Uint64Flag to allow -// for other values to be specified -type Uint64Flag struct { - cli.Uint64Flag - set *flag.FlagSet -} - -// NewUint64Flag creates a new Uint64Flag -func NewUint64Flag(fl cli.Uint64Flag) *Uint64Flag { - return &Uint64Flag{Uint64Flag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped Uint64Flag.Apply -func (f *Uint64Flag) Apply(set *flag.FlagSet) { - f.set = set - f.Uint64Flag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped Uint64Flag.ApplyWithError -func (f *Uint64Flag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.Uint64Flag.ApplyWithError(set) -} - -// UintFlag is the flag type that wraps cli.UintFlag to allow -// for other values to be specified -type UintFlag struct { - cli.UintFlag - set *flag.FlagSet -} - -// NewUintFlag creates a new UintFlag -func NewUintFlag(fl cli.UintFlag) *UintFlag { - return &UintFlag{UintFlag: fl, set: nil} -} - -// Apply saves the flagSet for later usage calls, then calls the -// wrapped UintFlag.Apply -func (f *UintFlag) Apply(set *flag.FlagSet) { - f.set = set - f.UintFlag.Apply(set) -} - -// ApplyWithError saves the flagSet for later usage calls, then calls the -// wrapped UintFlag.ApplyWithError -func (f *UintFlag) ApplyWithError(set *flag.FlagSet) error { - f.set = set - return f.UintFlag.ApplyWithError(set) -} diff --git a/vendor/github.com/urfave/cli/altsrc/flag_test.go b/vendor/github.com/urfave/cli/altsrc/flag_test.go deleted file mode 100644 index cd18294..0000000 --- a/vendor/github.com/urfave/cli/altsrc/flag_test.go +++ /dev/null @@ -1,336 +0,0 @@ -package altsrc - -import ( - "flag" - "fmt" - "os" - "strings" - "testing" - "time" - - "gopkg.in/urfave/cli.v1" -) - -type testApplyInputSource struct { - Flag FlagInputSourceExtension - FlagName string - FlagSetName string - Expected string - ContextValueString string - ContextValue flag.Value - EnvVarValue string - EnvVarName string - MapValue interface{} -} - -func TestGenericApplyInputSourceValue(t *testing.T) { - v := &Parser{"abc", "def"} - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}), - FlagName: "test", - MapValue: v, - }) - expect(t, v, c.Generic("test")) -} - -func TestGenericApplyInputSourceMethodContextSet(t *testing.T) { - p := &Parser{"abc", "def"} - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}), - FlagName: "test", - MapValue: &Parser{"efg", "hig"}, - ContextValueString: p.String(), - }) - expect(t, p, c.Generic("test")) -} - -func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}, EnvVar: "TEST"}), - FlagName: "test", - MapValue: &Parser{"efg", "hij"}, - EnvVarName: "TEST", - EnvVarValue: "abc,def", - }) - expect(t, &Parser{"abc", "def"}, c.Generic("test")) -} - -func TestStringSliceApplyInputSourceValue(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - }) - expect(t, c.StringSlice("test"), []string{"hello", "world"}) -} - -func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - ContextValueString: "ohno", - }) - expect(t, c.StringSlice("test"), []string{"ohno"}) -} - -func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: []interface{}{"hello", "world"}, - EnvVarName: "TEST", - EnvVarValue: "oh,no", - }) - expect(t, c.StringSlice("test"), []string{"oh", "no"}) -} - -func TestIntSliceApplyInputSourceValue(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - }) - expect(t, c.IntSlice("test"), []int{1, 2}) -} - -func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - ContextValueString: "3", - }) - expect(t, c.IntSlice("test"), []int{3}) -} - -func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: []interface{}{1, 2}, - EnvVarName: "TEST", - EnvVarValue: "3,4", - }) - expect(t, c.IntSlice("test"), []int{3, 4}) -} - -func TestBoolApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(cli.BoolFlag{Name: "test"}), - FlagName: "test", - MapValue: true, - }) - expect(t, true, c.Bool("test")) -} - -func TestBoolApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(cli.BoolFlag{Name: "test"}), - FlagName: "test", - MapValue: false, - ContextValueString: "true", - }) - expect(t, true, c.Bool("test")) -} - -func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolFlag(cli.BoolFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: false, - EnvVarName: "TEST", - EnvVarValue: "true", - }) - expect(t, true, c.Bool("test")) -} - -func TestBoolTApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test"}), - FlagName: "test", - MapValue: false, - }) - expect(t, false, c.BoolT("test")) -} - -func TestBoolTApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test"}), - FlagName: "test", - MapValue: true, - ContextValueString: "false", - }) - expect(t, false, c.BoolT("test")) -} - -func TestBoolTApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: true, - EnvVarName: "TEST", - EnvVarValue: "false", - }) - expect(t, false, c.BoolT("test")) -} - -func TestStringApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(cli.StringFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - }) - expect(t, "hello", c.String("test")) -} - -func TestStringApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(cli.StringFlag{Name: "test"}), - FlagName: "test", - MapValue: "hello", - ContextValueString: "goodbye", - }) - expect(t, "goodbye", c.String("test")) -} - -func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewStringFlag(cli.StringFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: "hello", - EnvVarName: "TEST", - EnvVarValue: "goodbye", - }) - expect(t, "goodbye", c.String("test")) -} - -func TestIntApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(cli.IntFlag{Name: "test"}), - FlagName: "test", - MapValue: 15, - }) - expect(t, 15, c.Int("test")) -} - -func TestIntApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(cli.IntFlag{Name: "test"}), - FlagName: "test", - MapValue: 15, - ContextValueString: "7", - }) - expect(t, 7, c.Int("test")) -} - -func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: 15, - EnvVarName: "TEST", - EnvVarValue: "12", - }) - expect(t, 12, c.Int("test")) -} - -func TestDurationApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(cli.DurationFlag{Name: "test"}), - FlagName: "test", - MapValue: time.Duration(30 * time.Second), - }) - expect(t, time.Duration(30*time.Second), c.Duration("test")) -} - -func TestDurationApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(cli.DurationFlag{Name: "test"}), - FlagName: "test", - MapValue: time.Duration(30 * time.Second), - ContextValueString: time.Duration(15 * time.Second).String(), - }) - expect(t, time.Duration(15*time.Second), c.Duration("test")) -} - -func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewDurationFlag(cli.DurationFlag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: time.Duration(30 * time.Second), - EnvVarName: "TEST", - EnvVarValue: time.Duration(15 * time.Second).String(), - }) - expect(t, time.Duration(15*time.Second), c.Duration("test")) -} - -func TestFloat64ApplyInputSourceMethodSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(cli.Float64Flag{Name: "test"}), - FlagName: "test", - MapValue: 1.3, - }) - expect(t, 1.3, c.Float64("test")) -} - -func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(cli.Float64Flag{Name: "test"}), - FlagName: "test", - MapValue: 1.3, - ContextValueString: fmt.Sprintf("%v", 1.4), - }) - expect(t, 1.4, c.Float64("test")) -} - -func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) { - c := runTest(t, testApplyInputSource{ - Flag: NewFloat64Flag(cli.Float64Flag{Name: "test", EnvVar: "TEST"}), - FlagName: "test", - MapValue: 1.3, - EnvVarName: "TEST", - EnvVarValue: fmt.Sprintf("%v", 1.4), - }) - expect(t, 1.4, c.Float64("test")) -} - -func runTest(t *testing.T, test testApplyInputSource) *cli.Context { - inputSource := &MapInputSource{valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue}} - set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError) - c := cli.NewContext(nil, set, nil) - if test.EnvVarName != "" && test.EnvVarValue != "" { - os.Setenv(test.EnvVarName, test.EnvVarValue) - defer os.Setenv(test.EnvVarName, "") - } - - test.Flag.Apply(set) - if test.ContextValue != nil { - flag := set.Lookup(test.FlagName) - flag.Value = test.ContextValue - } - if test.ContextValueString != "" { - set.Set(test.FlagName, test.ContextValueString) - } - test.Flag.ApplyInputSourceValue(c, inputSource) - - return c -} - -type Parser [2]string - -func (p *Parser) Set(value string) error { - parts := strings.Split(value, ",") - if len(parts) != 2 { - return fmt.Errorf("invalid format") - } - - (*p)[0] = parts[0] - (*p)[1] = parts[1] - - return nil -} - -func (p *Parser) String() string { - return fmt.Sprintf("%s,%s", p[0], p[1]) -} diff --git a/vendor/github.com/urfave/cli/altsrc/helpers_test.go b/vendor/github.com/urfave/cli/altsrc/helpers_test.go deleted file mode 100644 index 3b7f7e9..0000000 --- a/vendor/github.com/urfave/cli/altsrc/helpers_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package altsrc - -import ( - "reflect" - "testing" -) - -func expect(t *testing.T, a interface{}, b interface{}) { - if !reflect.DeepEqual(b, a) { - t.Errorf("Expected %#v (type %v) - Got %#v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) - } -} - -func refute(t *testing.T, a interface{}, b interface{}) { - if a == b { - t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) - } -} diff --git a/vendor/github.com/urfave/cli/altsrc/input_source_context.go b/vendor/github.com/urfave/cli/altsrc/input_source_context.go deleted file mode 100644 index 276dcda..0000000 --- a/vendor/github.com/urfave/cli/altsrc/input_source_context.go +++ /dev/null @@ -1,21 +0,0 @@ -package altsrc - -import ( - "time" - - "gopkg.in/urfave/cli.v1" -) - -// InputSourceContext is an interface used to allow -// other input sources to be implemented as needed. -type InputSourceContext interface { - Int(name string) (int, error) - Duration(name string) (time.Duration, error) - Float64(name string) (float64, error) - String(name string) (string, error) - StringSlice(name string) ([]string, error) - IntSlice(name string) ([]int, error) - Generic(name string) (cli.Generic, error) - Bool(name string) (bool, error) - BoolT(name string) (bool, error) -} diff --git a/vendor/github.com/urfave/cli/altsrc/map_input_source.go b/vendor/github.com/urfave/cli/altsrc/map_input_source.go deleted file mode 100644 index b3169e0..0000000 --- a/vendor/github.com/urfave/cli/altsrc/map_input_source.go +++ /dev/null @@ -1,262 +0,0 @@ -package altsrc - -import ( - "fmt" - "reflect" - "strings" - "time" - - "gopkg.in/urfave/cli.v1" -) - -// MapInputSource implements InputSourceContext to return -// data from the map that is loaded. -type MapInputSource struct { - valueMap map[interface{}]interface{} -} - -// nestedVal checks if the name has '.' delimiters. -// If so, it tries to traverse the tree by the '.' delimited sections to find -// a nested value for the key. -func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool) { - if sections := strings.Split(name, "."); len(sections) > 1 { - node := tree - for _, section := range sections[:len(sections)-1] { - if child, ok := node[section]; !ok { - return nil, false - } else { - if ctype, ok := child.(map[interface{}]interface{}); !ok { - return nil, false - } else { - node = ctype - } - } - } - if val, ok := node[sections[len(sections)-1]]; ok { - return val, true - } - } - return nil, false -} - -// Int returns an int from the map if it exists otherwise returns 0 -func (fsm *MapInputSource) Int(name string) (int, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(int) - if !isType { - return 0, incorrectTypeForFlagError(name, "int", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(int) - if !isType { - return 0, incorrectTypeForFlagError(name, "int", nestedGenericValue) - } - return otherValue, nil - } - - return 0, nil -} - -// Duration returns a duration from the map if it exists otherwise returns 0 -func (fsm *MapInputSource) Duration(name string) (time.Duration, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(time.Duration) - if !isType { - return 0, incorrectTypeForFlagError(name, "duration", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(time.Duration) - if !isType { - return 0, incorrectTypeForFlagError(name, "duration", nestedGenericValue) - } - return otherValue, nil - } - - return 0, nil -} - -// Float64 returns an float64 from the map if it exists otherwise returns 0 -func (fsm *MapInputSource) Float64(name string) (float64, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(float64) - if !isType { - return 0, incorrectTypeForFlagError(name, "float64", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(float64) - if !isType { - return 0, incorrectTypeForFlagError(name, "float64", nestedGenericValue) - } - return otherValue, nil - } - - return 0, nil -} - -// String returns a string from the map if it exists otherwise returns an empty string -func (fsm *MapInputSource) String(name string) (string, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(string) - if !isType { - return "", incorrectTypeForFlagError(name, "string", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(string) - if !isType { - return "", incorrectTypeForFlagError(name, "string", nestedGenericValue) - } - return otherValue, nil - } - - return "", nil -} - -// StringSlice returns an []string from the map if it exists otherwise returns nil -func (fsm *MapInputSource) StringSlice(name string) ([]string, error) { - otherGenericValue, exists := fsm.valueMap[name] - if !exists { - otherGenericValue, exists = nestedVal(name, fsm.valueMap) - if !exists { - return nil, nil - } - } - - otherValue, isType := otherGenericValue.([]interface{}) - if !isType { - return nil, incorrectTypeForFlagError(name, "[]interface{}", otherGenericValue) - } - - var stringSlice = make([]string, 0, len(otherValue)) - for i, v := range otherValue { - stringValue, isType := v.(string) - - if !isType { - return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "string", v) - } - - stringSlice = append(stringSlice, stringValue) - } - - return stringSlice, nil -} - -// IntSlice returns an []int from the map if it exists otherwise returns nil -func (fsm *MapInputSource) IntSlice(name string) ([]int, error) { - otherGenericValue, exists := fsm.valueMap[name] - if !exists { - otherGenericValue, exists = nestedVal(name, fsm.valueMap) - if !exists { - return nil, nil - } - } - - otherValue, isType := otherGenericValue.([]interface{}) - if !isType { - return nil, incorrectTypeForFlagError(name, "[]interface{}", otherGenericValue) - } - - var intSlice = make([]int, 0, len(otherValue)) - for i, v := range otherValue { - intValue, isType := v.(int) - - if !isType { - return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "int", v) - } - - intSlice = append(intSlice, intValue) - } - - return intSlice, nil -} - -// Generic returns an cli.Generic from the map if it exists otherwise returns nil -func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(cli.Generic) - if !isType { - return nil, incorrectTypeForFlagError(name, "cli.Generic", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(cli.Generic) - if !isType { - return nil, incorrectTypeForFlagError(name, "cli.Generic", nestedGenericValue) - } - return otherValue, nil - } - - return nil, nil -} - -// Bool returns an bool from the map otherwise returns false -func (fsm *MapInputSource) Bool(name string) (bool, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(bool) - if !isType { - return false, incorrectTypeForFlagError(name, "bool", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(bool) - if !isType { - return false, incorrectTypeForFlagError(name, "bool", nestedGenericValue) - } - return otherValue, nil - } - - return false, nil -} - -// BoolT returns an bool from the map otherwise returns true -func (fsm *MapInputSource) BoolT(name string) (bool, error) { - otherGenericValue, exists := fsm.valueMap[name] - if exists { - otherValue, isType := otherGenericValue.(bool) - if !isType { - return true, incorrectTypeForFlagError(name, "bool", otherGenericValue) - } - return otherValue, nil - } - nestedGenericValue, exists := nestedVal(name, fsm.valueMap) - if exists { - otherValue, isType := nestedGenericValue.(bool) - if !isType { - return true, incorrectTypeForFlagError(name, "bool", nestedGenericValue) - } - return otherValue, nil - } - - return true, nil -} - -func incorrectTypeForFlagError(name, expectedTypeName string, value interface{}) error { - valueType := reflect.TypeOf(value) - valueTypeName := "" - if valueType != nil { - valueTypeName = valueType.Name() - } - - return fmt.Errorf("Mismatched type for flag '%s'. Expected '%s' but actual is '%s'", name, expectedTypeName, valueTypeName) -} diff --git a/vendor/github.com/urfave/cli/altsrc/toml_command_test.go b/vendor/github.com/urfave/cli/altsrc/toml_command_test.go deleted file mode 100644 index a5053d4..0000000 --- a/vendor/github.com/urfave/cli/altsrc/toml_command_test.go +++ /dev/null @@ -1,310 +0,0 @@ -// Disabling building of toml support in cases where golang is 1.0 or 1.1 -// as the encoding library is not implemented or supported. - -// +build go1.2 - -package altsrc - -import ( - "flag" - "io/ioutil" - "os" - "testing" - - "gopkg.in/urfave/cli.v1" -) - -func TestCommandTomFileTest(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) - defer os.Remove("current.toml") - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestGlobalEnvVarWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) - defer os.Remove("current.toml") - - os.Setenv("THE_TEST", "10") - defer os.Setenv("THE_TEST", "") - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 10) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestGlobalEnvVarWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) - defer os.Remove("current.toml") - - os.Setenv("THE_TEST", "10") - defer os.Setenv("THE_TEST", "") - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 10) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestSpecifiedFlagWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) - defer os.Remove("current.toml") - - test := []string{"test-cmd", "--load", "current.toml", "--test", "7"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 7) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestSpecifiedFlagWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte(`[top] - test = 15`), 0666) - defer os.Remove("current.toml") - - test := []string{"test-cmd", "--load", "current.toml", "--top.test", "7"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 7) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestDefaultValueFileWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) - defer os.Remove("current.toml") - - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", Value: 7}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileTestDefaultValueFileWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) - defer os.Remove("current.toml") - - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileFlagHasDefaultGlobalEnvTomlSetGlobalEnvWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) - defer os.Remove("current.toml") - - os.Setenv("THE_TEST", "11") - defer os.Setenv("THE_TEST", "") - - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 11) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandTomlFileFlagHasDefaultGlobalEnvTomlSetGlobalEnvWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) - defer os.Remove("current.toml") - - os.Setenv("THE_TEST", "11") - defer os.Setenv("THE_TEST", "") - - test := []string{"test-cmd", "--load", "current.toml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 11) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} diff --git a/vendor/github.com/urfave/cli/altsrc/toml_file_loader.go b/vendor/github.com/urfave/cli/altsrc/toml_file_loader.go deleted file mode 100644 index 37870fc..0000000 --- a/vendor/github.com/urfave/cli/altsrc/toml_file_loader.go +++ /dev/null @@ -1,113 +0,0 @@ -// Disabling building of toml support in cases where golang is 1.0 or 1.1 -// as the encoding library is not implemented or supported. - -// +build go1.2 - -package altsrc - -import ( - "fmt" - "reflect" - - "github.com/BurntSushi/toml" - "gopkg.in/urfave/cli.v1" -) - -type tomlMap struct { - Map map[interface{}]interface{} -} - -func unmarshalMap(i interface{}) (ret map[interface{}]interface{}, err error) { - ret = make(map[interface{}]interface{}) - m := i.(map[string]interface{}) - for key, val := range m { - v := reflect.ValueOf(val) - switch v.Kind() { - case reflect.Bool: - ret[key] = val.(bool) - case reflect.String: - ret[key] = val.(string) - case reflect.Int: - ret[key] = int(val.(int)) - case reflect.Int8: - ret[key] = int(val.(int8)) - case reflect.Int16: - ret[key] = int(val.(int16)) - case reflect.Int32: - ret[key] = int(val.(int32)) - case reflect.Int64: - ret[key] = int(val.(int64)) - case reflect.Uint: - ret[key] = int(val.(uint)) - case reflect.Uint8: - ret[key] = int(val.(uint8)) - case reflect.Uint16: - ret[key] = int(val.(uint16)) - case reflect.Uint32: - ret[key] = int(val.(uint32)) - case reflect.Uint64: - ret[key] = int(val.(uint64)) - case reflect.Float32: - ret[key] = float64(val.(float32)) - case reflect.Float64: - ret[key] = float64(val.(float64)) - case reflect.Map: - if tmp, err := unmarshalMap(val); err == nil { - ret[key] = tmp - } else { - return nil, err - } - case reflect.Array, reflect.Slice: - ret[key] = val.([]interface{}) - default: - return nil, fmt.Errorf("Unsupported: type = %#v", v.Kind()) - } - } - return ret, nil -} - -func (self *tomlMap) UnmarshalTOML(i interface{}) error { - if tmp, err := unmarshalMap(i); err == nil { - self.Map = tmp - } else { - return err - } - return nil -} - -type tomlSourceContext struct { - FilePath string -} - -// NewTomlSourceFromFile creates a new TOML InputSourceContext from a filepath. -func NewTomlSourceFromFile(file string) (InputSourceContext, error) { - tsc := &tomlSourceContext{FilePath: file} - var results tomlMap = tomlMap{} - if err := readCommandToml(tsc.FilePath, &results); err != nil { - return nil, fmt.Errorf("Unable to load TOML file '%s': inner error: \n'%v'", tsc.FilePath, err.Error()) - } - return &MapInputSource{valueMap: results.Map}, nil -} - -// NewTomlSourceFromFlagFunc creates a new TOML InputSourceContext from a provided flag name and source context. -func NewTomlSourceFromFlagFunc(flagFileName string) func(context *cli.Context) (InputSourceContext, error) { - return func(context *cli.Context) (InputSourceContext, error) { - filePath := context.String(flagFileName) - return NewTomlSourceFromFile(filePath) - } -} - -func readCommandToml(filePath string, container interface{}) (err error) { - b, err := loadDataFrom(filePath) - if err != nil { - return err - } - - err = toml.Unmarshal(b, container) - if err != nil { - return err - } - - err = nil - return -} diff --git a/vendor/github.com/urfave/cli/altsrc/yaml_command_test.go b/vendor/github.com/urfave/cli/altsrc/yaml_command_test.go deleted file mode 100644 index 9d3f431..0000000 --- a/vendor/github.com/urfave/cli/altsrc/yaml_command_test.go +++ /dev/null @@ -1,313 +0,0 @@ -// Disabling building of yaml support in cases where golang is 1.0 or 1.1 -// as the encoding library is not implemented or supported. - -// +build go1.2 - -package altsrc - -import ( - "flag" - "io/ioutil" - "os" - "testing" - - "gopkg.in/urfave/cli.v1" -) - -func TestCommandYamlFileTest(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) - defer os.Remove("current.yaml") - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) - defer os.Remove("current.yaml") - - os.Setenv("THE_TEST", "10") - defer os.Setenv("THE_TEST", "") - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 10) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte(`top: - test: 15`), 0666) - defer os.Remove("current.yaml") - - os.Setenv("THE_TEST", "10") - defer os.Setenv("THE_TEST", "") - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 10) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) - defer os.Remove("current.yaml") - - test := []string{"test-cmd", "--load", "current.yaml", "--test", "7"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 7) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte(`top: - test: 15`), 0666) - defer os.Remove("current.yaml") - - test := []string{"test-cmd", "--load", "current.yaml", "--top.test", "7"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 7) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) - defer os.Remove("current.yaml") - - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", Value: 7}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte(`top: - test: 15`), 0666) - defer os.Remove("current.yaml") - - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 15) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666) - defer os.Remove("current.yaml") - - os.Setenv("THE_TEST", "11") - defer os.Setenv("THE_TEST", "") - - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("test") - expect(t, val, 11) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} - -func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *testing.T) { - app := cli.NewApp() - set := flag.NewFlagSet("test", 0) - ioutil.WriteFile("current.yaml", []byte(`top: - test: 15`), 0666) - defer os.Remove("current.yaml") - - os.Setenv("THE_TEST", "11") - defer os.Setenv("THE_TEST", "") - - test := []string{"test-cmd", "--load", "current.yaml"} - set.Parse(test) - - c := cli.NewContext(app, set, nil) - - command := &cli.Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(c *cli.Context) error { - val := c.Int("top.test") - expect(t, val, 11) - return nil - }, - Flags: []cli.Flag{ - NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}), - cli.StringFlag{Name: "load"}}, - } - command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load")) - err := command.Run(c) - - expect(t, err, nil) -} diff --git a/vendor/github.com/urfave/cli/altsrc/yaml_file_loader.go b/vendor/github.com/urfave/cli/altsrc/yaml_file_loader.go deleted file mode 100644 index dd808d5..0000000 --- a/vendor/github.com/urfave/cli/altsrc/yaml_file_loader.go +++ /dev/null @@ -1,92 +0,0 @@ -// Disabling building of yaml support in cases where golang is 1.0 or 1.1 -// as the encoding library is not implemented or supported. - -// +build go1.2 - -package altsrc - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/url" - "os" - "runtime" - "strings" - - "gopkg.in/urfave/cli.v1" - - "gopkg.in/yaml.v2" -) - -type yamlSourceContext struct { - FilePath string -} - -// NewYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath. -func NewYamlSourceFromFile(file string) (InputSourceContext, error) { - ysc := &yamlSourceContext{FilePath: file} - var results map[interface{}]interface{} - err := readCommandYaml(ysc.FilePath, &results) - if err != nil { - return nil, fmt.Errorf("Unable to load Yaml file '%s': inner error: \n'%v'", ysc.FilePath, err.Error()) - } - - return &MapInputSource{valueMap: results}, nil -} - -// NewYamlSourceFromFlagFunc creates a new Yaml InputSourceContext from a provided flag name and source context. -func NewYamlSourceFromFlagFunc(flagFileName string) func(context *cli.Context) (InputSourceContext, error) { - return func(context *cli.Context) (InputSourceContext, error) { - filePath := context.String(flagFileName) - return NewYamlSourceFromFile(filePath) - } -} - -func readCommandYaml(filePath string, container interface{}) (err error) { - b, err := loadDataFrom(filePath) - if err != nil { - return err - } - - err = yaml.Unmarshal(b, container) - if err != nil { - return err - } - - err = nil - return -} - -func loadDataFrom(filePath string) ([]byte, error) { - u, err := url.Parse(filePath) - if err != nil { - return nil, err - } - - if u.Host != "" { // i have a host, now do i support the scheme? - switch u.Scheme { - case "http", "https": - res, err := http.Get(filePath) - if err != nil { - return nil, err - } - return ioutil.ReadAll(res.Body) - default: - return nil, fmt.Errorf("scheme of %s is unsupported", filePath) - } - } else if u.Path != "" { // i dont have a host, but I have a path. I am a local file. - if _, notFoundFileErr := os.Stat(filePath); notFoundFileErr != nil { - return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath) - } - return ioutil.ReadFile(filePath) - } else if runtime.GOOS == "windows" && strings.Contains(u.String(), "\\") { - // on Windows systems u.Path is always empty, so we need to check the string directly. - if _, notFoundFileErr := os.Stat(filePath); notFoundFileErr != nil { - return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath) - } - return ioutil.ReadFile(filePath) - } else { - return nil, fmt.Errorf("unable to determine how to load from path %s", filePath) - } -} diff --git a/vendor/github.com/urfave/cli/app.go b/vendor/github.com/urfave/cli/app.go deleted file mode 100644 index 51fc45d..0000000 --- a/vendor/github.com/urfave/cli/app.go +++ /dev/null @@ -1,497 +0,0 @@ -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 - // 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 != "" || a.Email != "" { - a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) - } - - newCmds := []Command{} - for _, c := range a.Commands { - if c.HelpName == "" { - c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) - } - newCmds = append(newCmds, c) - } - a.Commands = newCmds - - if a.Command(helpCommand.Name) == nil && !a.HideHelp { - a.Commands = append(a.Commands, helpCommand) - if (HelpFlag != BoolFlag{}) { - a.appendFlag(HelpFlag) - } - } - - if !a.HideVersion { - a.appendFlag(VersionFlag) - } - - a.categories = CommandCategories{} - for _, command := range a.Commands { - a.categories = a.categories.AddCommand(command.Category, command) - } - sort.Sort(a.categories) - - if a.Metadata == nil { - a.Metadata = make(map[string]interface{}) - } - - if a.Writer == nil { - a.Writer = os.Stdout - } -} - -// Run is the entry point to the cli app. Parses the arguments slice and routes -// to the proper flag/args combination -func (a *App) Run(arguments []string) (err error) { - a.Setup() - - // handle the completion flag separately from the flagset since - // completion could be attempted after a flag, but before its value was put - // on the command line. this causes the flagset to interpret the completion - // flag name as the value of the flag before it which is undesirable - // note that we can only do this because the shell autocomplete function - // always appends the completion flag at the end of the command - shellComplete, arguments := checkShellCompleteFlag(a, arguments) - - // parse flags - set, err := flagSet(a.Name, a.Flags) - if err != nil { - return err - } - - set.SetOutput(ioutil.Discard) - err = set.Parse(arguments[1:]) - nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, nil) - if nerr != nil { - fmt.Fprintln(a.Writer, nerr) - ShowAppHelp(context) - return nerr - } - context.shellComplete = shellComplete - - if checkCompletions(context) { - return nil - } - - if err != nil { - if a.OnUsageError != nil { - err := a.OnUsageError(context, err, false) - HandleExitCoder(err) - return err - } - fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - ShowAppHelp(context) - return err - } - - if !a.HideHelp && checkHelp(context) { - ShowAppHelp(context) - return nil - } - - if !a.HideVersion && checkVersion(context) { - ShowVersion(context) - return nil - } - - if a.After != nil { - defer func() { - if afterErr := a.After(context); afterErr != nil { - if err != nil { - err = NewMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } - - if a.Before != nil { - beforeErr := a.Before(context) - if beforeErr != nil { - ShowAppHelp(context) - HandleExitCoder(beforeErr) - err = beforeErr - return err - } - } - - args := context.Args() - if args.Present() { - name := args.First() - c := a.Command(name) - if c != nil { - return c.Run(context) - } - } - - if a.Action == nil { - a.Action = helpCommand.Action - } - - // Run default Action - err = HandleAction(a.Action, context) - - HandleExitCoder(err) - return err -} - -// RunAndExitOnError calls .Run() and exits non-zero if an error was returned -// -// Deprecated: instead you should return an error that fulfills cli.ExitCoder -// to cli.App.Run. This will cause the application to exit with the given eror -// code in the cli.ExitCoder -func (a *App) RunAndExitOnError() { - if err := a.Run(os.Args); err != nil { - fmt.Fprintln(a.errWriter(), err) - OsExiter(1) - } -} - -// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to -// generate command-specific flags -func (a *App) RunAsSubcommand(ctx *Context) (err error) { - // append help to commands - if len(a.Commands) > 0 { - if a.Command(helpCommand.Name) == nil && !a.HideHelp { - a.Commands = append(a.Commands, helpCommand) - if (HelpFlag != BoolFlag{}) { - a.appendFlag(HelpFlag) - } - } - } - - newCmds := []Command{} - for _, c := range a.Commands { - if c.HelpName == "" { - c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) - } - newCmds = append(newCmds, c) - } - a.Commands = newCmds - - // parse flags - set, err := flagSet(a.Name, a.Flags) - if err != nil { - return err - } - - set.SetOutput(ioutil.Discard) - err = set.Parse(ctx.Args().Tail()) - nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, ctx) - - if nerr != nil { - fmt.Fprintln(a.Writer, nerr) - fmt.Fprintln(a.Writer) - if len(a.Commands) > 0 { - ShowSubcommandHelp(context) - } else { - ShowCommandHelp(ctx, context.Args().First()) - } - return nerr - } - - if checkCompletions(context) { - return nil - } - - if err != nil { - if a.OnUsageError != nil { - err = a.OnUsageError(context, err, true) - HandleExitCoder(err) - return err - } - fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - ShowSubcommandHelp(context) - return err - } - - if len(a.Commands) > 0 { - if checkSubcommandHelp(context) { - return nil - } - } else { - if checkCommandHelp(ctx, context.Args().First()) { - return nil - } - } - - if a.After != nil { - defer func() { - afterErr := a.After(context) - if afterErr != nil { - HandleExitCoder(err) - if err != nil { - err = NewMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } - - if a.Before != nil { - beforeErr := a.Before(context) - if beforeErr != nil { - HandleExitCoder(beforeErr) - err = beforeErr - return err - } - } - - args := context.Args() - if args.Present() { - name := args.First() - c := a.Command(name) - if c != nil { - return c.Run(context) - } - } - - // Run default Action - err = HandleAction(a.Action, context) - - HandleExitCoder(err) - return err -} - -// Command returns the named command on App. Returns nil if the command does not exist -func (a *App) Command(name string) *Command { - for _, c := range a.Commands { - if c.HasName(name) { - return &c - } - } - - return nil -} - -// Categories returns a slice containing all the categories with the commands they contain -func (a *App) Categories() CommandCategories { - return a.categories -} - -// VisibleCategories returns a slice of categories and commands that are -// Hidden=false -func (a *App) VisibleCategories() []*CommandCategory { - ret := []*CommandCategory{} - for _, category := range a.categories { - if visible := func() *CommandCategory { - for _, command := range category.Commands { - if !command.Hidden { - return category - } - } - return nil - }(); visible != nil { - ret = append(ret, visible) - } - } - return ret -} - -// VisibleCommands returns a slice of the Commands with Hidden=false -func (a *App) VisibleCommands() []Command { - ret := []Command{} - for _, command := range a.Commands { - if !command.Hidden { - ret = append(ret, command) - } - } - return ret -} - -// VisibleFlags returns a slice of the Flags with Hidden=false -func (a *App) VisibleFlags() []Flag { - return visibleFlags(a.Flags) -} - -func (a *App) hasFlag(flag Flag) bool { - for _, f := range a.Flags { - if flag == f { - return true - } - } - - return false -} - -func (a *App) errWriter() io.Writer { - - // When the app ErrWriter is nil use the package level one. - if a.ErrWriter == nil { - return ErrWriter - } - - return a.ErrWriter -} - -func (a *App) appendFlag(flag Flag) { - if !a.hasFlag(flag) { - a.Flags = append(a.Flags, flag) - } -} - -// Author represents someone who has contributed to a cli project. -type Author struct { - Name string // The Authors name - Email string // The Authors email -} - -// String makes Author comply to the Stringer interface, to allow an easy print in the templating process -func (a Author) String() string { - e := "" - if a.Email != "" { - e = " <" + a.Email + ">" - } - - return fmt.Sprintf("%v%v", a.Name, e) -} - -// HandleAction attempts to figure out which Action signature was used. If -// it's an ActionFunc or a func with the legacy signature for Action, the func -// is run! -func HandleAction(action interface{}, context *Context) (err error) { - if a, ok := action.(ActionFunc); ok { - return a(context) - } else if a, ok := action.(func(*Context) error); ok { - return a(context) - } else if a, ok := action.(func(*Context)); ok { // deprecated function signature - a(context) - return nil - } else { - return errInvalidActionType - } -} diff --git a/vendor/github.com/urfave/cli/app_test.go b/vendor/github.com/urfave/cli/app_test.go deleted file mode 100644 index e14ddaf..0000000 --- a/vendor/github.com/urfave/cli/app_test.go +++ /dev/null @@ -1,1742 +0,0 @@ -package cli - -import ( - "bytes" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "reflect" - "strings" - "testing" -) - -var ( - lastExitCode = 0 - fakeOsExiter = func(rc int) { - lastExitCode = rc - } - fakeErrWriter = &bytes.Buffer{} -) - -func init() { - OsExiter = fakeOsExiter - ErrWriter = fakeErrWriter -} - -type opCounts struct { - Total, BashComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int -} - -func ExampleApp_Run() { - // set args for examples sake - os.Args = []string{"greet", "--name", "Jeremy"} - - app := NewApp() - app.Name = "greet" - app.Flags = []Flag{ - StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, - } - app.Action = func(c *Context) error { - fmt.Printf("Hello %v\n", c.String("name")) - return nil - } - app.UsageText = "app [first_arg] [second_arg]" - app.Author = "Harrison" - app.Email = "harrison@lolwut.com" - app.Authors = []Author{{Name: "Oliver Allen", Email: "oliver@toyshop.com"}} - app.Run(os.Args) - // Output: - // Hello Jeremy -} - -func ExampleApp_Run_subcommand() { - // set args for examples sake - os.Args = []string{"say", "hi", "english", "--name", "Jeremy"} - app := NewApp() - app.Name = "say" - app.Commands = []Command{ - { - Name: "hello", - Aliases: []string{"hi"}, - Usage: "use it to see a description", - Description: "This is how we describe hello the function", - Subcommands: []Command{ - { - Name: "english", - Aliases: []string{"en"}, - Usage: "sends a greeting in english", - Description: "greets someone in english", - Flags: []Flag{ - StringFlag{ - Name: "name", - Value: "Bob", - Usage: "Name of the person to greet", - }, - }, - Action: func(c *Context) error { - fmt.Println("Hello,", c.String("name")) - return nil - }, - }, - }, - }, - } - - app.Run(os.Args) - // Output: - // Hello, Jeremy -} - -func ExampleApp_Run_appHelp() { - // set args for examples sake - os.Args = []string{"greet", "help"} - - app := NewApp() - app.Name = "greet" - app.Version = "0.1.0" - app.Description = "This is how we describe greet the app" - app.Authors = []Author{ - {Name: "Harrison", Email: "harrison@lolwut.com"}, - {Name: "Oliver Allen", Email: "oliver@toyshop.com"}, - } - app.Flags = []Flag{ - StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, - } - app.Commands = []Command{ - { - Name: "describeit", - Aliases: []string{"d"}, - Usage: "use it to see a description", - Description: "This is how we describe describeit the function", - Action: func(c *Context) error { - fmt.Printf("i like to describe things") - return nil - }, - }, - } - app.Run(os.Args) - // Output: - // NAME: - // greet - A new cli application - // - // USAGE: - // greet [global options] command [command options] [arguments...] - // - // VERSION: - // 0.1.0 - // - // DESCRIPTION: - // This is how we describe greet the app - // - // AUTHORS: - // Harrison - // Oliver Allen - // - // COMMANDS: - // describeit, d use it to see a description - // help, h Shows a list of commands or help for one command - // - // GLOBAL OPTIONS: - // --name value a name to say (default: "bob") - // --help, -h show help - // --version, -v print the version -} - -func ExampleApp_Run_commandHelp() { - // set args for examples sake - os.Args = []string{"greet", "h", "describeit"} - - app := NewApp() - app.Name = "greet" - app.Flags = []Flag{ - StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, - } - app.Commands = []Command{ - { - Name: "describeit", - Aliases: []string{"d"}, - Usage: "use it to see a description", - Description: "This is how we describe describeit the function", - Action: func(c *Context) error { - fmt.Printf("i like to describe things") - return nil - }, - }, - } - app.Run(os.Args) - // Output: - // NAME: - // greet describeit - use it to see a description - // - // USAGE: - // greet describeit [arguments...] - // - // DESCRIPTION: - // This is how we describe describeit the function -} - -func ExampleApp_Run_noAction() { - app := App{} - app.Name = "greet" - app.Run([]string{"greet"}) - // Output: - // NAME: - // greet - // - // USAGE: - // [global options] command [command options] [arguments...] - // - // COMMANDS: - // help, h Shows a list of commands or help for one command - // - // GLOBAL OPTIONS: - // --help, -h show help - // --version, -v print the version -} - -func ExampleApp_Run_subcommandNoAction() { - app := App{} - app.Name = "greet" - app.Commands = []Command{ - { - Name: "describeit", - Aliases: []string{"d"}, - Usage: "use it to see a description", - Description: "This is how we describe describeit the function", - }, - } - app.Run([]string{"greet", "describeit"}) - // Output: - // NAME: - // describeit - use it to see a description - // - // USAGE: - // describeit [arguments...] - // - // DESCRIPTION: - // This is how we describe describeit the function - -} - -func ExampleApp_Run_bashComplete() { - // set args for examples sake - os.Args = []string{"greet", "--generate-bash-completion"} - - app := NewApp() - app.Name = "greet" - app.EnableBashCompletion = true - app.Commands = []Command{ - { - Name: "describeit", - Aliases: []string{"d"}, - Usage: "use it to see a description", - Description: "This is how we describe describeit the function", - Action: func(c *Context) error { - fmt.Printf("i like to describe things") - return nil - }, - }, { - Name: "next", - Usage: "next example", - Description: "more stuff to see when generating bash completion", - Action: func(c *Context) error { - fmt.Printf("the next example") - return nil - }, - }, - } - - app.Run(os.Args) - // Output: - // describeit - // d - // next - // help - // h -} - -func TestApp_Run(t *testing.T) { - s := "" - - app := NewApp() - app.Action = func(c *Context) error { - s = s + c.Args().First() - return nil - } - - err := app.Run([]string{"command", "foo"}) - expect(t, err, nil) - err = app.Run([]string{"command", "bar"}) - expect(t, err, nil) - expect(t, s, "foobar") -} - -var commandAppTests = []struct { - name string - expected bool -}{ - {"foobar", true}, - {"batbaz", true}, - {"b", true}, - {"f", true}, - {"bat", false}, - {"nothing", false}, -} - -func TestApp_Command(t *testing.T) { - app := NewApp() - fooCommand := Command{Name: "foobar", Aliases: []string{"f"}} - batCommand := Command{Name: "batbaz", Aliases: []string{"b"}} - app.Commands = []Command{ - fooCommand, - batCommand, - } - - for _, test := range commandAppTests { - expect(t, app.Command(test.name) != nil, test.expected) - } -} - -func TestApp_Setup_defaultsWriter(t *testing.T) { - app := &App{} - app.Setup() - expect(t, app.Writer, os.Stdout) -} - -func TestApp_CommandWithArgBeforeFlags(t *testing.T) { - var parsedOption, firstArg string - - app := NewApp() - command := Command{ - Name: "cmd", - Flags: []Flag{ - StringFlag{Name: "option", Value: "", Usage: "some option"}, - }, - Action: func(c *Context) error { - parsedOption = c.String("option") - firstArg = c.Args().First() - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"}) - - expect(t, parsedOption, "my-option") - expect(t, firstArg, "my-arg") -} - -func TestApp_RunAsSubcommandParseFlags(t *testing.T) { - var context *Context - - a := NewApp() - a.Commands = []Command{ - { - Name: "foo", - Action: func(c *Context) error { - context = c - return nil - }, - Flags: []Flag{ - StringFlag{ - Name: "lang", - Value: "english", - Usage: "language for the greeting", - }, - }, - Before: func(_ *Context) error { return nil }, - }, - } - a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) - - expect(t, context.Args().Get(0), "abcd") - expect(t, context.String("lang"), "spanish") -} - -func TestApp_RunAsSubCommandIncorrectUsage(t *testing.T) { - a := App{ - Flags: []Flag{ - StringFlag{Name: "--foo"}, - }, - Writer: bytes.NewBufferString(""), - } - - set := flag.NewFlagSet("", flag.ContinueOnError) - set.Parse([]string{"", "---foo"}) - c := &Context{flagSet: set} - - err := a.RunAsSubcommand(c) - - expect(t, err, errors.New("bad flag syntax: ---foo")) -} - -func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) { - var parsedOption string - var args []string - - app := NewApp() - command := Command{ - Name: "cmd", - Flags: []Flag{ - StringFlag{Name: "option", Value: "", Usage: "some option"}, - }, - Action: func(c *Context) error { - parsedOption = c.String("option") - args = c.Args() - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"}) - - expect(t, parsedOption, "my-option") - expect(t, args[0], "my-arg") - expect(t, args[1], "--") - expect(t, args[2], "--notARealFlag") -} - -func TestApp_CommandWithDash(t *testing.T) { - var args []string - - app := NewApp() - command := Command{ - Name: "cmd", - Action: func(c *Context) error { - args = c.Args() - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "-"}) - - expect(t, args[0], "my-arg") - expect(t, args[1], "-") -} - -func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) { - var args []string - - app := NewApp() - command := Command{ - Name: "cmd", - Action: func(c *Context) error { - args = c.Args() - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"}) - - expect(t, args[0], "my-arg") - expect(t, args[1], "--") - expect(t, args[2], "notAFlagAtAll") -} - -func TestApp_VisibleCommands(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Name: "frob", - HelpName: "foo frob", - Action: func(_ *Context) error { return nil }, - }, - { - Name: "frib", - HelpName: "foo frib", - Hidden: true, - Action: func(_ *Context) error { return nil }, - }, - } - - app.Setup() - expected := []Command{ - app.Commands[0], - app.Commands[2], // help - } - actual := app.VisibleCommands() - expect(t, len(expected), len(actual)) - for i, actualCommand := range actual { - expectedCommand := expected[i] - - if expectedCommand.Action != nil { - // comparing func addresses is OK! - expect(t, fmt.Sprintf("%p", expectedCommand.Action), fmt.Sprintf("%p", actualCommand.Action)) - } - - // nil out funcs, as they cannot be compared - // (https://github.com/golang/go/issues/8554) - expectedCommand.Action = nil - actualCommand.Action = nil - - if !reflect.DeepEqual(expectedCommand, actualCommand) { - t.Errorf("expected\n%#v\n!=\n%#v", expectedCommand, actualCommand) - } - } -} - -func TestApp_Float64Flag(t *testing.T) { - var meters float64 - - app := NewApp() - app.Flags = []Flag{ - Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"}, - } - app.Action = func(c *Context) error { - meters = c.Float64("height") - return nil - } - - app.Run([]string{"", "--height", "1.93"}) - expect(t, meters, 1.93) -} - -func TestApp_ParseSliceFlags(t *testing.T) { - var parsedOption, firstArg string - var parsedIntSlice []int - var parsedStringSlice []string - - app := NewApp() - command := Command{ - Name: "cmd", - Flags: []Flag{ - IntSliceFlag{Name: "p", Value: &IntSlice{}, Usage: "set one or more ip addr"}, - StringSliceFlag{Name: "ip", Value: &StringSlice{}, Usage: "set one or more ports to open"}, - }, - Action: func(c *Context) error { - parsedIntSlice = c.IntSlice("p") - parsedStringSlice = c.StringSlice("ip") - parsedOption = c.String("option") - firstArg = c.Args().First() - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"}) - - IntsEquals := func(a, b []int) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true - } - - StrsEquals := func(a, b []string) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if v != b[i] { - return false - } - } - return true - } - var expectedIntSlice = []int{22, 80} - var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"} - - if !IntsEquals(parsedIntSlice, expectedIntSlice) { - t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice) - } - - if !StrsEquals(parsedStringSlice, expectedStringSlice) { - t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice) - } -} - -func TestApp_ParseSliceFlagsWithMissingValue(t *testing.T) { - var parsedIntSlice []int - var parsedStringSlice []string - - app := NewApp() - command := Command{ - Name: "cmd", - Flags: []Flag{ - IntSliceFlag{Name: "a", Usage: "set numbers"}, - StringSliceFlag{Name: "str", Usage: "set strings"}, - }, - Action: func(c *Context) error { - parsedIntSlice = c.IntSlice("a") - parsedStringSlice = c.StringSlice("str") - return nil - }, - } - app.Commands = []Command{command} - - app.Run([]string{"", "cmd", "my-arg", "-a", "2", "-str", "A"}) - - var expectedIntSlice = []int{2} - var expectedStringSlice = []string{"A"} - - if parsedIntSlice[0] != expectedIntSlice[0] { - t.Errorf("%v does not match %v", parsedIntSlice[0], expectedIntSlice[0]) - } - - if parsedStringSlice[0] != expectedStringSlice[0] { - t.Errorf("%v does not match %v", parsedIntSlice[0], expectedIntSlice[0]) - } -} - -func TestApp_DefaultStdout(t *testing.T) { - app := NewApp() - - if app.Writer != os.Stdout { - t.Error("Default output writer not set.") - } -} - -type mockWriter struct { - written []byte -} - -func (fw *mockWriter) Write(p []byte) (n int, err error) { - if fw.written == nil { - fw.written = p - } else { - fw.written = append(fw.written, p...) - } - - return len(p), nil -} - -func (fw *mockWriter) GetWritten() (b []byte) { - return fw.written -} - -func TestApp_SetStdout(t *testing.T) { - w := &mockWriter{} - - app := NewApp() - app.Name = "test" - app.Writer = w - - err := app.Run([]string{"help"}) - - if err != nil { - t.Fatalf("Run error: %s", err) - } - - if len(w.written) == 0 { - t.Error("App did not write output to desired writer.") - } -} - -func TestApp_BeforeFunc(t *testing.T) { - counts := &opCounts{} - beforeError := fmt.Errorf("fail") - var err error - - app := NewApp() - - app.Before = func(c *Context) error { - counts.Total++ - counts.Before = counts.Total - s := c.String("opt") - if s == "fail" { - return beforeError - } - - return nil - } - - app.Commands = []Command{ - { - Name: "sub", - Action: func(c *Context) error { - counts.Total++ - counts.SubCommand = counts.Total - return nil - }, - }, - } - - app.Flags = []Flag{ - StringFlag{Name: "opt"}, - } - - // run with the Before() func succeeding - err = app.Run([]string{"command", "--opt", "succeed", "sub"}) - - if err != nil { - t.Fatalf("Run error: %s", err) - } - - if counts.Before != 1 { - t.Errorf("Before() not executed when expected") - } - - if counts.SubCommand != 2 { - t.Errorf("Subcommand not executed when expected") - } - - // reset - counts = &opCounts{} - - // run with the Before() func failing - err = app.Run([]string{"command", "--opt", "fail", "sub"}) - - // should be the same error produced by the Before func - if err != beforeError { - t.Errorf("Run error expected, but not received") - } - - if counts.Before != 1 { - t.Errorf("Before() not executed when expected") - } - - if counts.SubCommand != 0 { - t.Errorf("Subcommand executed when NOT expected") - } - - // reset - counts = &opCounts{} - - afterError := errors.New("fail again") - app.After = func(_ *Context) error { - return afterError - } - - // run with the Before() func failing, wrapped by After() - err = app.Run([]string{"command", "--opt", "fail", "sub"}) - - // should be the same error produced by the Before func - if _, ok := err.(MultiError); !ok { - t.Errorf("MultiError expected, but not received") - } - - if counts.Before != 1 { - t.Errorf("Before() not executed when expected") - } - - if counts.SubCommand != 0 { - t.Errorf("Subcommand executed when NOT expected") - } -} - -func TestApp_AfterFunc(t *testing.T) { - counts := &opCounts{} - afterError := fmt.Errorf("fail") - var err error - - app := NewApp() - - app.After = func(c *Context) error { - counts.Total++ - counts.After = counts.Total - s := c.String("opt") - if s == "fail" { - return afterError - } - - return nil - } - - app.Commands = []Command{ - { - Name: "sub", - Action: func(c *Context) error { - counts.Total++ - counts.SubCommand = counts.Total - return nil - }, - }, - } - - app.Flags = []Flag{ - StringFlag{Name: "opt"}, - } - - // run with the After() func succeeding - err = app.Run([]string{"command", "--opt", "succeed", "sub"}) - - if err != nil { - t.Fatalf("Run error: %s", err) - } - - if counts.After != 2 { - t.Errorf("After() not executed when expected") - } - - if counts.SubCommand != 1 { - t.Errorf("Subcommand not executed when expected") - } - - // reset - counts = &opCounts{} - - // run with the Before() func failing - err = app.Run([]string{"command", "--opt", "fail", "sub"}) - - // should be the same error produced by the Before func - if err != afterError { - t.Errorf("Run error expected, but not received") - } - - if counts.After != 2 { - t.Errorf("After() not executed when expected") - } - - if counts.SubCommand != 1 { - t.Errorf("Subcommand not executed when expected") - } -} - -func TestAppNoHelpFlag(t *testing.T) { - oldFlag := HelpFlag - defer func() { - HelpFlag = oldFlag - }() - - HelpFlag = BoolFlag{} - - app := NewApp() - app.Writer = ioutil.Discard - err := app.Run([]string{"test", "-h"}) - - if err != flag.ErrHelp { - t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err) - } -} - -func TestAppHelpPrinter(t *testing.T) { - oldPrinter := HelpPrinter - defer func() { - HelpPrinter = oldPrinter - }() - - var wasCalled = false - HelpPrinter = func(w io.Writer, template string, data interface{}) { - wasCalled = true - } - - app := NewApp() - app.Run([]string{"-h"}) - - if wasCalled == false { - t.Errorf("Help printer expected to be called, but was not") - } -} - -func TestApp_VersionPrinter(t *testing.T) { - oldPrinter := VersionPrinter - defer func() { - VersionPrinter = oldPrinter - }() - - var wasCalled = false - VersionPrinter = func(c *Context) { - wasCalled = true - } - - app := NewApp() - ctx := NewContext(app, nil, nil) - ShowVersion(ctx) - - if wasCalled == false { - t.Errorf("Version printer expected to be called, but was not") - } -} - -func TestApp_CommandNotFound(t *testing.T) { - counts := &opCounts{} - app := NewApp() - - app.CommandNotFound = func(c *Context, command string) { - counts.Total++ - counts.CommandNotFound = counts.Total - } - - app.Commands = []Command{ - { - Name: "bar", - Action: func(c *Context) error { - counts.Total++ - counts.SubCommand = counts.Total - return nil - }, - }, - } - - app.Run([]string{"command", "foo"}) - - expect(t, counts.CommandNotFound, 1) - expect(t, counts.SubCommand, 0) - expect(t, counts.Total, 1) -} - -func TestApp_OrderOfOperations(t *testing.T) { - counts := &opCounts{} - - resetCounts := func() { counts = &opCounts{} } - - app := NewApp() - app.EnableBashCompletion = true - app.BashComplete = func(c *Context) { - counts.Total++ - counts.BashComplete = counts.Total - } - - app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { - counts.Total++ - counts.OnUsageError = counts.Total - return errors.New("hay OnUsageError") - } - - beforeNoError := func(c *Context) error { - counts.Total++ - counts.Before = counts.Total - return nil - } - - beforeError := func(c *Context) error { - counts.Total++ - counts.Before = counts.Total - return errors.New("hay Before") - } - - app.Before = beforeNoError - app.CommandNotFound = func(c *Context, command string) { - counts.Total++ - counts.CommandNotFound = counts.Total - } - - afterNoError := func(c *Context) error { - counts.Total++ - counts.After = counts.Total - return nil - } - - afterError := func(c *Context) error { - counts.Total++ - counts.After = counts.Total - return errors.New("hay After") - } - - app.After = afterNoError - app.Commands = []Command{ - { - Name: "bar", - Action: func(c *Context) error { - counts.Total++ - counts.SubCommand = counts.Total - return nil - }, - }, - } - - app.Action = func(c *Context) error { - counts.Total++ - counts.Action = counts.Total - return nil - } - - _ = app.Run([]string{"command", "--nope"}) - expect(t, counts.OnUsageError, 1) - expect(t, counts.Total, 1) - - resetCounts() - - _ = app.Run([]string{"command", "--generate-bash-completion"}) - expect(t, counts.BashComplete, 1) - expect(t, counts.Total, 1) - - resetCounts() - - oldOnUsageError := app.OnUsageError - app.OnUsageError = nil - _ = app.Run([]string{"command", "--nope"}) - expect(t, counts.Total, 0) - app.OnUsageError = oldOnUsageError - - resetCounts() - - _ = app.Run([]string{"command", "foo"}) - expect(t, counts.OnUsageError, 0) - expect(t, counts.Before, 1) - expect(t, counts.CommandNotFound, 0) - expect(t, counts.Action, 2) - expect(t, counts.After, 3) - expect(t, counts.Total, 3) - - resetCounts() - - app.Before = beforeError - _ = app.Run([]string{"command", "bar"}) - expect(t, counts.OnUsageError, 0) - expect(t, counts.Before, 1) - expect(t, counts.After, 2) - expect(t, counts.Total, 2) - app.Before = beforeNoError - - resetCounts() - - app.After = nil - _ = app.Run([]string{"command", "bar"}) - expect(t, counts.OnUsageError, 0) - expect(t, counts.Before, 1) - expect(t, counts.SubCommand, 2) - expect(t, counts.Total, 2) - app.After = afterNoError - - resetCounts() - - app.After = afterError - err := app.Run([]string{"command", "bar"}) - if err == nil { - t.Fatalf("expected a non-nil error") - } - expect(t, counts.OnUsageError, 0) - expect(t, counts.Before, 1) - expect(t, counts.SubCommand, 2) - expect(t, counts.After, 3) - expect(t, counts.Total, 3) - app.After = afterNoError - - resetCounts() - - oldCommands := app.Commands - app.Commands = nil - _ = app.Run([]string{"command"}) - expect(t, counts.OnUsageError, 0) - expect(t, counts.Before, 1) - expect(t, counts.Action, 2) - expect(t, counts.After, 3) - expect(t, counts.Total, 3) - app.Commands = oldCommands -} - -func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) { - var subcommandHelpTopics = [][]string{ - {"command", "foo", "--help"}, - {"command", "foo", "-h"}, - {"command", "foo", "help"}, - } - - for _, flagSet := range subcommandHelpTopics { - t.Logf("==> checking with flags %v", flagSet) - - app := NewApp() - buf := new(bytes.Buffer) - app.Writer = buf - - subCmdBar := Command{ - Name: "bar", - Usage: "does bar things", - } - subCmdBaz := Command{ - Name: "baz", - Usage: "does baz things", - } - cmd := Command{ - Name: "foo", - Description: "descriptive wall of text about how it does foo things", - Subcommands: []Command{subCmdBar, subCmdBaz}, - Action: func(c *Context) error { return nil }, - } - - app.Commands = []Command{cmd} - err := app.Run(flagSet) - - if err != nil { - t.Error(err) - } - - output := buf.String() - t.Logf("output: %q\n", buf.Bytes()) - - if strings.Contains(output, "No help topic for") { - t.Errorf("expect a help topic, got none: \n%q", output) - } - - for _, shouldContain := range []string{ - cmd.Name, cmd.Description, - subCmdBar.Name, subCmdBar.Usage, - subCmdBaz.Name, subCmdBaz.Usage, - } { - if !strings.Contains(output, shouldContain) { - t.Errorf("want help to contain %q, did not: \n%q", shouldContain, output) - } - } - } -} - -func TestApp_Run_SubcommandFullPath(t *testing.T) { - app := NewApp() - buf := new(bytes.Buffer) - app.Writer = buf - app.Name = "command" - subCmd := Command{ - Name: "bar", - Usage: "does bar things", - } - cmd := Command{ - Name: "foo", - Description: "foo commands", - Subcommands: []Command{subCmd}, - } - app.Commands = []Command{cmd} - - err := app.Run([]string{"command", "foo", "bar", "--help"}) - if err != nil { - t.Error(err) - } - - output := buf.String() - if !strings.Contains(output, "command foo bar - does bar things") { - t.Errorf("expected full path to subcommand: %s", output) - } - if !strings.Contains(output, "command foo bar [arguments...]") { - t.Errorf("expected full path to subcommand: %s", output) - } -} - -func TestApp_Run_SubcommandHelpName(t *testing.T) { - app := NewApp() - buf := new(bytes.Buffer) - app.Writer = buf - app.Name = "command" - subCmd := Command{ - Name: "bar", - HelpName: "custom", - Usage: "does bar things", - } - cmd := Command{ - Name: "foo", - Description: "foo commands", - Subcommands: []Command{subCmd}, - } - app.Commands = []Command{cmd} - - err := app.Run([]string{"command", "foo", "bar", "--help"}) - if err != nil { - t.Error(err) - } - - output := buf.String() - if !strings.Contains(output, "custom - does bar things") { - t.Errorf("expected HelpName for subcommand: %s", output) - } - if !strings.Contains(output, "custom [arguments...]") { - t.Errorf("expected HelpName to subcommand: %s", output) - } -} - -func TestApp_Run_CommandHelpName(t *testing.T) { - app := NewApp() - buf := new(bytes.Buffer) - app.Writer = buf - app.Name = "command" - subCmd := Command{ - Name: "bar", - Usage: "does bar things", - } - cmd := Command{ - Name: "foo", - HelpName: "custom", - Description: "foo commands", - Subcommands: []Command{subCmd}, - } - app.Commands = []Command{cmd} - - err := app.Run([]string{"command", "foo", "bar", "--help"}) - if err != nil { - t.Error(err) - } - - output := buf.String() - if !strings.Contains(output, "command foo bar - does bar things") { - t.Errorf("expected full path to subcommand: %s", output) - } - if !strings.Contains(output, "command foo bar [arguments...]") { - t.Errorf("expected full path to subcommand: %s", output) - } -} - -func TestApp_Run_CommandSubcommandHelpName(t *testing.T) { - app := NewApp() - buf := new(bytes.Buffer) - app.Writer = buf - app.Name = "base" - subCmd := Command{ - Name: "bar", - HelpName: "custom", - Usage: "does bar things", - } - cmd := Command{ - Name: "foo", - Description: "foo commands", - Subcommands: []Command{subCmd}, - } - app.Commands = []Command{cmd} - - err := app.Run([]string{"command", "foo", "--help"}) - if err != nil { - t.Error(err) - } - - output := buf.String() - if !strings.Contains(output, "base foo - foo commands") { - t.Errorf("expected full path to subcommand: %s", output) - } - if !strings.Contains(output, "base foo command [command options] [arguments...]") { - t.Errorf("expected full path to subcommand: %s", output) - } -} - -func TestApp_Run_Help(t *testing.T) { - var helpArguments = [][]string{{"boom", "--help"}, {"boom", "-h"}, {"boom", "help"}} - - for _, args := range helpArguments { - buf := new(bytes.Buffer) - - t.Logf("==> checking with arguments %v", args) - - app := NewApp() - app.Name = "boom" - app.Usage = "make an explosive entrance" - app.Writer = buf - app.Action = func(c *Context) error { - buf.WriteString("boom I say!") - return nil - } - - err := app.Run(args) - if err != nil { - t.Error(err) - } - - output := buf.String() - t.Logf("output: %q\n", buf.Bytes()) - - if !strings.Contains(output, "boom - make an explosive entrance") { - t.Errorf("want help to contain %q, did not: \n%q", "boom - make an explosive entrance", output) - } - } -} - -func TestApp_Run_Version(t *testing.T) { - var versionArguments = [][]string{{"boom", "--version"}, {"boom", "-v"}} - - for _, args := range versionArguments { - buf := new(bytes.Buffer) - - t.Logf("==> checking with arguments %v", args) - - app := NewApp() - app.Name = "boom" - app.Usage = "make an explosive entrance" - app.Version = "0.1.0" - app.Writer = buf - app.Action = func(c *Context) error { - buf.WriteString("boom I say!") - return nil - } - - err := app.Run(args) - if err != nil { - t.Error(err) - } - - output := buf.String() - t.Logf("output: %q\n", buf.Bytes()) - - if !strings.Contains(output, "0.1.0") { - t.Errorf("want version to contain %q, did not: \n%q", "0.1.0", output) - } - } -} - -func TestApp_Run_Categories(t *testing.T) { - app := NewApp() - app.Name = "categories" - app.HideHelp = true - app.Commands = []Command{ - { - Name: "command1", - Category: "1", - }, - { - Name: "command2", - Category: "1", - }, - { - Name: "command3", - Category: "2", - }, - } - buf := new(bytes.Buffer) - app.Writer = buf - - app.Run([]string{"categories"}) - - expect := CommandCategories{ - &CommandCategory{ - Name: "1", - Commands: []Command{ - app.Commands[0], - app.Commands[1], - }, - }, - &CommandCategory{ - Name: "2", - Commands: []Command{ - app.Commands[2], - }, - }, - } - if !reflect.DeepEqual(app.Categories(), expect) { - t.Fatalf("expected categories %#v, to equal %#v", app.Categories(), expect) - } - - output := buf.String() - t.Logf("output: %q\n", buf.Bytes()) - - if !strings.Contains(output, "1:\n command1") { - t.Errorf("want buffer to include category %q, did not: \n%q", "1:\n command1", output) - } -} - -func TestApp_VisibleCategories(t *testing.T) { - app := NewApp() - app.Name = "visible-categories" - app.HideHelp = true - app.Commands = []Command{ - { - Name: "command1", - Category: "1", - HelpName: "foo command1", - Hidden: true, - }, - { - Name: "command2", - Category: "2", - HelpName: "foo command2", - }, - { - Name: "command3", - Category: "3", - HelpName: "foo command3", - }, - } - - expected := []*CommandCategory{ - { - Name: "2", - Commands: []Command{ - app.Commands[1], - }, - }, - { - Name: "3", - Commands: []Command{ - app.Commands[2], - }, - }, - } - - app.Setup() - expect(t, expected, app.VisibleCategories()) - - app = NewApp() - app.Name = "visible-categories" - app.HideHelp = true - app.Commands = []Command{ - { - Name: "command1", - Category: "1", - HelpName: "foo command1", - Hidden: true, - }, - { - Name: "command2", - Category: "2", - HelpName: "foo command2", - Hidden: true, - }, - { - Name: "command3", - Category: "3", - HelpName: "foo command3", - }, - } - - expected = []*CommandCategory{ - { - Name: "3", - Commands: []Command{ - app.Commands[2], - }, - }, - } - - app.Setup() - expect(t, expected, app.VisibleCategories()) - - app = NewApp() - app.Name = "visible-categories" - app.HideHelp = true - app.Commands = []Command{ - { - Name: "command1", - Category: "1", - HelpName: "foo command1", - Hidden: true, - }, - { - Name: "command2", - Category: "2", - HelpName: "foo command2", - Hidden: true, - }, - { - Name: "command3", - Category: "3", - HelpName: "foo command3", - Hidden: true, - }, - } - - expected = []*CommandCategory{} - - app.Setup() - expect(t, expected, app.VisibleCategories()) -} - -func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { - app := NewApp() - app.Action = func(c *Context) error { return nil } - app.Before = func(c *Context) error { return fmt.Errorf("before error") } - app.After = func(c *Context) error { return fmt.Errorf("after error") } - - err := app.Run([]string{"foo"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.Contains(err.Error(), "before error") { - t.Errorf("expected text of error from Before method, but got none in \"%v\"", err) - } - if !strings.Contains(err.Error(), "after error") { - t.Errorf("expected text of error from After method, but got none in \"%v\"", err) - } -} - -func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Subcommands: []Command{ - { - Name: "sub", - }, - }, - Name: "bar", - Before: func(c *Context) error { return fmt.Errorf("before error") }, - After: func(c *Context) error { return fmt.Errorf("after error") }, - }, - } - - err := app.Run([]string{"foo", "bar"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.Contains(err.Error(), "before error") { - t.Errorf("expected text of error from Before method, but got none in \"%v\"", err) - } - if !strings.Contains(err.Error(), "after error") { - t.Errorf("expected text of error from After method, but got none in \"%v\"", err) - } -} - -func TestApp_OnUsageError_WithWrongFlagValue(t *testing.T) { - app := NewApp() - app.Flags = []Flag{ - IntFlag{Name: "flag"}, - } - app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { - if isSubcommand { - t.Errorf("Expect no subcommand") - } - if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { - t.Errorf("Expect an invalid value error, but got \"%v\"", err) - } - return errors.New("intercepted: " + err.Error()) - } - app.Commands = []Command{ - { - Name: "bar", - }, - } - - err := app.Run([]string{"foo", "--flag=wrong"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.HasPrefix(err.Error(), "intercepted: invalid value") { - t.Errorf("Expect an intercepted error, but got \"%v\"", err) - } -} - -func TestApp_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) { - app := NewApp() - app.Flags = []Flag{ - IntFlag{Name: "flag"}, - } - app.OnUsageError = func(c *Context, err error, isSubcommand bool) error { - if isSubcommand { - t.Errorf("Expect subcommand") - } - if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { - t.Errorf("Expect an invalid value error, but got \"%v\"", err) - } - return errors.New("intercepted: " + err.Error()) - } - app.Commands = []Command{ - { - Name: "bar", - }, - } - - err := app.Run([]string{"foo", "--flag=wrong", "bar"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.HasPrefix(err.Error(), "intercepted: invalid value") { - t.Errorf("Expect an intercepted error, but got \"%v\"", err) - } -} - -// A custom flag that conforms to the relevant interfaces, but has none of the -// fields that the other flag types do. -type customBoolFlag struct { - Nombre string -} - -// Don't use the normal FlagStringer -func (c *customBoolFlag) String() string { - return "***" + c.Nombre + "***" -} - -func (c *customBoolFlag) GetName() string { - return c.Nombre -} - -func (c *customBoolFlag) Apply(set *flag.FlagSet) { - set.String(c.Nombre, c.Nombre, "") -} - -func TestCustomFlagsUnused(t *testing.T) { - app := NewApp() - app.Flags = []Flag{&customBoolFlag{"custom"}} - - err := app.Run([]string{"foo"}) - if err != nil { - t.Errorf("Run returned unexpected error: %v", err) - } -} - -func TestCustomFlagsUsed(t *testing.T) { - app := NewApp() - app.Flags = []Flag{&customBoolFlag{"custom"}} - - err := app.Run([]string{"foo", "--custom=bar"}) - if err != nil { - t.Errorf("Run returned unexpected error: %v", err) - } -} - -func TestCustomHelpVersionFlags(t *testing.T) { - app := NewApp() - - // Be sure to reset the global flags - defer func(helpFlag Flag, versionFlag Flag) { - HelpFlag = helpFlag - VersionFlag = versionFlag - }(HelpFlag, VersionFlag) - - HelpFlag = &customBoolFlag{"help-custom"} - VersionFlag = &customBoolFlag{"version-custom"} - - err := app.Run([]string{"foo", "--help-custom=bar"}) - if err != nil { - t.Errorf("Run returned unexpected error: %v", err) - } -} - -func TestHandleAction_WithNonFuncAction(t *testing.T) { - app := NewApp() - app.Action = 42 - fs, err := flagSet(app.Name, app.Flags) - if err != nil { - t.Errorf("error creating FlagSet: %s", err) - } - err = HandleAction(app.Action, NewContext(app, fs, nil)) - - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - exitErr, ok := err.(*ExitError) - - if !ok { - t.Fatalf("expected to receive a *ExitError") - } - - if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type.") { - t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error()) - } - - if exitErr.ExitCode() != 2 { - t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode()) - } -} - -func TestHandleAction_WithInvalidFuncSignature(t *testing.T) { - app := NewApp() - app.Action = func() string { return "" } - fs, err := flagSet(app.Name, app.Flags) - if err != nil { - t.Errorf("error creating FlagSet: %s", err) - } - err = HandleAction(app.Action, NewContext(app, fs, nil)) - - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - exitErr, ok := err.(*ExitError) - - if !ok { - t.Fatalf("expected to receive a *ExitError") - } - - if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") { - t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error()) - } - - if exitErr.ExitCode() != 2 { - t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode()) - } -} - -func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) { - app := NewApp() - app.Action = func(_ *Context) (int, error) { return 0, nil } - fs, err := flagSet(app.Name, app.Flags) - if err != nil { - t.Errorf("error creating FlagSet: %s", err) - } - err = HandleAction(app.Action, NewContext(app, fs, nil)) - - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - exitErr, ok := err.(*ExitError) - - if !ok { - t.Fatalf("expected to receive a *ExitError") - } - - if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") { - t.Fatalf("expected an invalid Action signature error, but got: %v", exitErr.Error()) - } - - if exitErr.ExitCode() != 2 { - t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode()) - } -} - -func TestHandleAction_WithUnknownPanic(t *testing.T) { - defer func() { refute(t, recover(), nil) }() - - var fn ActionFunc - - app := NewApp() - app.Action = func(ctx *Context) error { - fn(ctx) - return nil - } - fs, err := flagSet(app.Name, app.Flags) - if err != nil { - t.Errorf("error creating FlagSet: %s", err) - } - HandleAction(app.Action, NewContext(app, fs, nil)) -} - -func TestShellCompletionForIncompleteFlags(t *testing.T) { - app := NewApp() - app.Flags = []Flag{ - IntFlag{ - Name: "test-completion", - }, - } - app.EnableBashCompletion = true - app.BashComplete = func(ctx *Context) { - for _, command := range ctx.App.Commands { - if command.Hidden { - continue - } - - for _, name := range command.Names() { - fmt.Fprintln(ctx.App.Writer, name) - } - } - - for _, flag := range ctx.App.Flags { - for _, name := range strings.Split(flag.GetName(), ",") { - if name == BashCompletionFlag.GetName() { - continue - } - - switch name = strings.TrimSpace(name); len(name) { - case 0: - case 1: - fmt.Fprintln(ctx.App.Writer, "-"+name) - default: - fmt.Fprintln(ctx.App.Writer, "--"+name) - } - } - } - } - app.Action = func(ctx *Context) error { - return fmt.Errorf("should not get here") - } - err := app.Run([]string{"", "--test-completion", "--" + BashCompletionFlag.GetName()}) - if err != nil { - t.Errorf("app should not return an error: %s", err) - } -} - -func TestHandleActionActuallyWorksWithActions(t *testing.T) { - var f ActionFunc - called := false - f = func(c *Context) error { - called = true - return nil - } - - err := HandleAction(f, nil) - - if err != nil { - t.Errorf("Should not have errored: %v", err) - } - - if !called { - t.Errorf("Function was not called") - } -} diff --git a/vendor/github.com/urfave/cli/appveyor.yml b/vendor/github.com/urfave/cli/appveyor.yml deleted file mode 100644 index 1e1489c..0000000 --- a/vendor/github.com/urfave/cli/appveyor.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: "{build}" - -os: Windows Server 2016 - -image: Visual Studio 2017 - -clone_folder: c:\gopath\src\github.com\urfave\cli - -environment: - GOPATH: C:\gopath - GOVERSION: 1.8.x - PYTHON: C:\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - -install: -- set PATH=%GOPATH%\bin;C:\go\bin;%PATH% -- go version -- go env -- go get github.com/urfave/gfmrun/... -- go get -v -t ./... - -build_script: -- python runtests vet -- python runtests test -- python runtests gfmrun diff --git a/vendor/github.com/urfave/cli/autocomplete/bash_autocomplete b/vendor/github.com/urfave/cli/autocomplete/bash_autocomplete deleted file mode 100755 index 37d9c14..0000000 --- a/vendor/github.com/urfave/cli/autocomplete/bash_autocomplete +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/bash - -: ${PROG:=$(basename ${BASH_SOURCE})} - -_cli_bash_autocomplete() { - local cur opts base - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 -} - -complete -F _cli_bash_autocomplete $PROG - -unset PROG diff --git a/vendor/github.com/urfave/cli/autocomplete/zsh_autocomplete b/vendor/github.com/urfave/cli/autocomplete/zsh_autocomplete deleted file mode 100644 index 5430a18..0000000 --- a/vendor/github.com/urfave/cli/autocomplete/zsh_autocomplete +++ /dev/null @@ -1,5 +0,0 @@ -autoload -U compinit && compinit -autoload -U bashcompinit && bashcompinit - -script_dir=$(dirname $0) -source ${script_dir}/bash_autocomplete diff --git a/vendor/github.com/urfave/cli/category.go b/vendor/github.com/urfave/cli/category.go deleted file mode 100644 index 1a60550..0000000 --- a/vendor/github.com/urfave/cli/category.go +++ /dev/null @@ -1,44 +0,0 @@ -package cli - -// CommandCategories is a slice of *CommandCategory. -type CommandCategories []*CommandCategory - -// CommandCategory is a category containing commands. -type CommandCategory struct { - Name string - Commands Commands -} - -func (c CommandCategories) Less(i, j int) bool { - return c[i].Name < c[j].Name -} - -func (c CommandCategories) Len() int { - return len(c) -} - -func (c CommandCategories) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -// AddCommand adds a command to a category. -func (c CommandCategories) AddCommand(category string, command Command) CommandCategories { - for _, commandCategory := range c { - if commandCategory.Name == category { - commandCategory.Commands = append(commandCategory.Commands, command) - return c - } - } - return append(c, &CommandCategory{Name: category, Commands: []Command{command}}) -} - -// VisibleCommands returns a slice of the Commands with Hidden=false -func (c *CommandCategory) VisibleCommands() []Command { - ret := []Command{} - for _, command := range c.Commands { - if !command.Hidden { - ret = append(ret, command) - } - } - return ret -} diff --git a/vendor/github.com/urfave/cli/cli.go b/vendor/github.com/urfave/cli/cli.go deleted file mode 100644 index 90c07eb..0000000 --- a/vendor/github.com/urfave/cli/cli.go +++ /dev/null @@ -1,22 +0,0 @@ -// Package cli provides a minimal framework for creating and organizing command line -// Go applications. cli is designed to be easy to understand and write, the most simple -// cli application can be written as follows: -// func main() { -// cli.NewApp().Run(os.Args) -// } -// -// Of course this application does not do much, so let's make this an actual application: -// func main() { -// app := cli.NewApp() -// app.Name = "greet" -// app.Usage = "say a greeting" -// app.Action = func(c *cli.Context) error { -// println("Greetings") -// return nil -// } -// -// app.Run(os.Args) -// } -package cli - -//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go diff --git a/vendor/github.com/urfave/cli/command.go b/vendor/github.com/urfave/cli/command.go deleted file mode 100644 index 23de294..0000000 --- a/vendor/github.com/urfave/cli/command.go +++ /dev/null @@ -1,304 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "sort" - "strings" -) - -// Command is a subcommand for a cli.App. -type Command struct { - // The name of the command - Name string - // short name of the command. Typically one character (deprecated, use `Aliases`) - ShortName string - // A list of aliases for the command - Aliases []string - // A short description of the usage of this command - Usage string - // Custom text to show on USAGE section of help - UsageText string - // A longer explanation of how the command works - Description string - // A short description of the arguments of this command - ArgsUsage string - // The category the command is part of - Category string - // The function to call when checking for bash command completions - BashComplete BashCompleteFunc - // An action to execute before any sub-subcommands are run, but after the context is ready - // If a non-nil error is returned, no sub-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 function to call when this command is invoked - Action interface{} - // TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind - // of deprecation period has passed, maybe? - - // Execute this function if a usage error occurs. - OnUsageError OnUsageErrorFunc - // List of child commands - Subcommands Commands - // List of flags to parse - Flags []Flag - // Treat all flags as normal arguments if true - SkipFlagParsing bool - // Skip argument reordering which attempts to move flags before arguments, - // but only works if all flags appear after all arguments. This behavior was - // removed n version 2 since it only works under specific conditions so we - // backport here by exposing it as an option for compatibility. - SkipArgReorder bool - // Boolean to hide built-in help command - HideHelp bool - // Boolean to hide this command from help or completion - Hidden bool - - // Full name of command for help, defaults to full command name, including parent commands. - HelpName string - commandNamePath []string - - // CustomHelpTemplate the text template for the command help topic. - // cli.go uses text/template to render templates. You can - // render custom help text by setting this variable. - CustomHelpTemplate string -} - -type CommandsByName []Command - -func (c CommandsByName) Len() int { - return len(c) -} - -func (c CommandsByName) Less(i, j int) bool { - return c[i].Name < c[j].Name -} - -func (c CommandsByName) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -// FullName returns the full name of the command. -// For subcommands this ensures that parent commands are part of the command path -func (c Command) FullName() string { - if c.commandNamePath == nil { - return c.Name - } - return strings.Join(c.commandNamePath, " ") -} - -// Commands is a slice of Command -type Commands []Command - -// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c Command) Run(ctx *Context) (err error) { - if len(c.Subcommands) > 0 { - return c.startApp(ctx) - } - - if !c.HideHelp && (HelpFlag != BoolFlag{}) { - // append help to flags - c.Flags = append( - c.Flags, - HelpFlag, - ) - } - - set, err := flagSet(c.Name, c.Flags) - if err != nil { - return err - } - set.SetOutput(ioutil.Discard) - - if c.SkipFlagParsing { - err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...)) - } else if !c.SkipArgReorder { - firstFlagIndex := -1 - terminatorIndex := -1 - for index, arg := range ctx.Args() { - if arg == "--" { - terminatorIndex = index - break - } else if arg == "-" { - // Do nothing. A dash alone is not really a flag. - continue - } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 { - firstFlagIndex = index - } - } - - if firstFlagIndex > -1 { - args := ctx.Args() - regularArgs := make([]string, len(args[1:firstFlagIndex])) - copy(regularArgs, args[1:firstFlagIndex]) - - var flagArgs []string - if terminatorIndex > -1 { - flagArgs = args[firstFlagIndex:terminatorIndex] - regularArgs = append(regularArgs, args[terminatorIndex:]...) - } else { - flagArgs = args[firstFlagIndex:] - } - - err = set.Parse(append(flagArgs, regularArgs...)) - } else { - err = set.Parse(ctx.Args().Tail()) - } - } else { - err = set.Parse(ctx.Args().Tail()) - } - - nerr := normalizeFlags(c.Flags, set) - if nerr != nil { - fmt.Fprintln(ctx.App.Writer, nerr) - fmt.Fprintln(ctx.App.Writer) - ShowCommandHelp(ctx, c.Name) - return nerr - } - - context := NewContext(ctx.App, set, ctx) - context.Command = c - if checkCommandCompletions(context, c.Name) { - return nil - } - - if err != nil { - if c.OnUsageError != nil { - err := c.OnUsageError(context, err, false) - HandleExitCoder(err) - return err - } - fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) - fmt.Fprintln(context.App.Writer) - ShowCommandHelp(context, c.Name) - return err - } - - if checkCommandHelp(context, c.Name) { - return nil - } - - if c.After != nil { - defer func() { - afterErr := c.After(context) - if afterErr != nil { - HandleExitCoder(err) - if err != nil { - err = NewMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } - - if c.Before != nil { - err = c.Before(context) - if err != nil { - ShowCommandHelp(context, c.Name) - HandleExitCoder(err) - return err - } - } - - if c.Action == nil { - c.Action = helpSubcommand.Action - } - - err = HandleAction(c.Action, context) - - if err != nil { - HandleExitCoder(err) - } - return err -} - -// Names returns the names including short names and aliases. -func (c Command) Names() []string { - names := []string{c.Name} - - if c.ShortName != "" { - names = append(names, c.ShortName) - } - - return append(names, c.Aliases...) -} - -// HasName returns true if Command.Name or Command.ShortName matches given name -func (c Command) HasName(name string) bool { - for _, n := range c.Names() { - if n == name { - return true - } - } - return false -} - -func (c Command) startApp(ctx *Context) error { - app := NewApp() - app.Metadata = ctx.App.Metadata - // set the name and usage - app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) - if c.HelpName == "" { - app.HelpName = c.HelpName - } else { - app.HelpName = app.Name - } - - app.Usage = c.Usage - app.Description = c.Description - app.ArgsUsage = c.ArgsUsage - - // set CommandNotFound - app.CommandNotFound = ctx.App.CommandNotFound - app.CustomAppHelpTemplate = c.CustomHelpTemplate - - // set the flags and commands - app.Commands = c.Subcommands - app.Flags = c.Flags - app.HideHelp = c.HideHelp - - app.Version = ctx.App.Version - app.HideVersion = ctx.App.HideVersion - app.Compiled = ctx.App.Compiled - app.Author = ctx.App.Author - app.Email = ctx.App.Email - app.Writer = ctx.App.Writer - app.ErrWriter = ctx.App.ErrWriter - - app.categories = CommandCategories{} - for _, command := range c.Subcommands { - app.categories = app.categories.AddCommand(command.Category, command) - } - - sort.Sort(app.categories) - - // bash completion - app.EnableBashCompletion = ctx.App.EnableBashCompletion - if c.BashComplete != nil { - app.BashComplete = c.BashComplete - } - - // set the actions - app.Before = c.Before - app.After = c.After - if c.Action != nil { - app.Action = c.Action - } else { - app.Action = helpSubcommand.Action - } - app.OnUsageError = c.OnUsageError - - for index, cc := range app.Commands { - app.Commands[index].commandNamePath = []string{c.Name, cc.Name} - } - - return app.RunAsSubcommand(ctx) -} - -// VisibleFlags returns a slice of the Flags with Hidden=false -func (c Command) VisibleFlags() []Flag { - return visibleFlags(c.Flags) -} diff --git a/vendor/github.com/urfave/cli/command_test.go b/vendor/github.com/urfave/cli/command_test.go deleted file mode 100644 index 4ad994c..0000000 --- a/vendor/github.com/urfave/cli/command_test.go +++ /dev/null @@ -1,240 +0,0 @@ -package cli - -import ( - "errors" - "flag" - "fmt" - "io/ioutil" - "strings" - "testing" -) - -func TestCommandFlagParsing(t *testing.T) { - cases := []struct { - testArgs []string - skipFlagParsing bool - skipArgReorder bool - expectedErr error - }{ - // Test normal "not ignoring flags" flow - {[]string{"test-cmd", "blah", "blah", "-break"}, false, false, errors.New("flag provided but not defined: -break")}, - - // Test no arg reorder - {[]string{"test-cmd", "blah", "blah", "-break"}, false, true, nil}, - - {[]string{"test-cmd", "blah", "blah"}, true, false, nil}, // Test SkipFlagParsing without any args that look like flags - {[]string{"test-cmd", "blah", "-break"}, true, false, nil}, // Test SkipFlagParsing with random flag arg - {[]string{"test-cmd", "blah", "-help"}, true, false, nil}, // Test SkipFlagParsing with "special" help flag arg - } - - for _, c := range cases { - app := NewApp() - app.Writer = ioutil.Discard - set := flag.NewFlagSet("test", 0) - set.Parse(c.testArgs) - - context := NewContext(app, set, nil) - - command := Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(_ *Context) error { return nil }, - SkipFlagParsing: c.skipFlagParsing, - SkipArgReorder: c.skipArgReorder, - } - - err := command.Run(context) - - expect(t, err, c.expectedErr) - expect(t, []string(context.Args()), c.testArgs) - } -} - -func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Name: "bar", - Before: func(c *Context) error { - return fmt.Errorf("before error") - }, - After: func(c *Context) error { - return fmt.Errorf("after error") - }, - }, - } - - err := app.Run([]string{"foo", "bar"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.Contains(err.Error(), "before error") { - t.Errorf("expected text of error from Before method, but got none in \"%v\"", err) - } - if !strings.Contains(err.Error(), "after error") { - t.Errorf("expected text of error from After method, but got none in \"%v\"", err) - } -} - -func TestCommand_Run_BeforeSavesMetadata(t *testing.T) { - var receivedMsgFromAction string - var receivedMsgFromAfter string - - app := NewApp() - app.Commands = []Command{ - { - Name: "bar", - Before: func(c *Context) error { - c.App.Metadata["msg"] = "hello world" - return nil - }, - Action: func(c *Context) error { - msg, ok := c.App.Metadata["msg"] - if !ok { - return errors.New("msg not found") - } - receivedMsgFromAction = msg.(string) - return nil - }, - After: func(c *Context) error { - msg, ok := c.App.Metadata["msg"] - if !ok { - return errors.New("msg not found") - } - receivedMsgFromAfter = msg.(string) - return nil - }, - }, - } - - err := app.Run([]string{"foo", "bar"}) - if err != nil { - t.Fatalf("expected no error from Run, got %s", err) - } - - expectedMsg := "hello world" - - if receivedMsgFromAction != expectedMsg { - t.Fatalf("expected msg from Action to match. Given: %q\nExpected: %q", - receivedMsgFromAction, expectedMsg) - } - if receivedMsgFromAfter != expectedMsg { - t.Fatalf("expected msg from After to match. Given: %q\nExpected: %q", - receivedMsgFromAction, expectedMsg) - } -} - -func TestCommand_OnUsageError_hasCommandContext(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Name: "bar", - Flags: []Flag{ - IntFlag{Name: "flag"}, - }, - OnUsageError: func(c *Context, err error, _ bool) error { - return fmt.Errorf("intercepted in %s: %s", c.Command.Name, err.Error()) - }, - }, - } - - err := app.Run([]string{"foo", "bar", "--flag=wrong"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.HasPrefix(err.Error(), "intercepted in bar") { - t.Errorf("Expect an intercepted error, but got \"%v\"", err) - } -} - -func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Name: "bar", - Flags: []Flag{ - IntFlag{Name: "flag"}, - }, - OnUsageError: func(c *Context, err error, _ bool) error { - if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { - t.Errorf("Expect an invalid value error, but got \"%v\"", err) - } - return errors.New("intercepted: " + err.Error()) - }, - }, - } - - err := app.Run([]string{"foo", "bar", "--flag=wrong"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.HasPrefix(err.Error(), "intercepted: invalid value") { - t.Errorf("Expect an intercepted error, but got \"%v\"", err) - } -} - -func TestCommand_OnUsageError_WithSubcommand(t *testing.T) { - app := NewApp() - app.Commands = []Command{ - { - Name: "bar", - Subcommands: []Command{ - { - Name: "baz", - }, - }, - Flags: []Flag{ - IntFlag{Name: "flag"}, - }, - OnUsageError: func(c *Context, err error, _ bool) error { - if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") { - t.Errorf("Expect an invalid value error, but got \"%v\"", err) - } - return errors.New("intercepted: " + err.Error()) - }, - }, - } - - err := app.Run([]string{"foo", "bar", "--flag=wrong"}) - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - if !strings.HasPrefix(err.Error(), "intercepted: invalid value") { - t.Errorf("Expect an intercepted error, but got \"%v\"", err) - } -} - -func TestCommand_Run_SubcommandsCanUseErrWriter(t *testing.T) { - app := NewApp() - app.ErrWriter = ioutil.Discard - app.Commands = []Command{ - { - Name: "bar", - Usage: "this is for testing", - Subcommands: []Command{ - { - Name: "baz", - Usage: "this is for testing", - Action: func(c *Context) error { - if c.App.ErrWriter != ioutil.Discard { - return fmt.Errorf("ErrWriter not passed") - } - - return nil - }, - }, - }, - }, - } - - err := app.Run([]string{"foo", "bar", "baz"}) - if err != nil { - t.Fatal(err) - } -} diff --git a/vendor/github.com/urfave/cli/context.go b/vendor/github.com/urfave/cli/context.go deleted file mode 100644 index db94191..0000000 --- a/vendor/github.com/urfave/cli/context.go +++ /dev/null @@ -1,278 +0,0 @@ -package cli - -import ( - "errors" - "flag" - "reflect" - "strings" - "syscall" -) - -// Context is a type that is passed through to -// each Handler action in a cli application. Context -// can be used to retrieve context-specific Args and -// parsed command-line options. -type Context struct { - App *App - Command Command - shellComplete bool - flagSet *flag.FlagSet - setFlags map[string]bool - parentContext *Context -} - -// NewContext creates a new context. For use in when invoking an App or Command action. -func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { - c := &Context{App: app, flagSet: set, parentContext: parentCtx} - - if parentCtx != nil { - c.shellComplete = parentCtx.shellComplete - } - - return c -} - -// NumFlags returns the number of flags set -func (c *Context) NumFlags() int { - return c.flagSet.NFlag() -} - -// Set sets a context flag to a value. -func (c *Context) Set(name, value string) error { - c.setFlags = nil - return c.flagSet.Set(name, value) -} - -// GlobalSet sets a context flag to a value on the global flagset -func (c *Context) GlobalSet(name, value string) error { - globalContext(c).setFlags = nil - return globalContext(c).flagSet.Set(name, value) -} - -// IsSet determines if the flag was actually set -func (c *Context) IsSet(name string) bool { - if c.setFlags == nil { - c.setFlags = make(map[string]bool) - - c.flagSet.Visit(func(f *flag.Flag) { - c.setFlags[f.Name] = true - }) - - c.flagSet.VisitAll(func(f *flag.Flag) { - if _, ok := c.setFlags[f.Name]; ok { - return - } - c.setFlags[f.Name] = false - }) - - // XXX hack to support IsSet for flags with EnvVar - // - // There isn't an easy way to do this with the current implementation since - // whether a flag was set via an environment variable is very difficult to - // determine here. Instead, we intend to introduce a backwards incompatible - // change in version 2 to add `IsSet` to the Flag interface to push the - // responsibility closer to where the information required to determine - // whether a flag is set by non-standard means such as environment - // variables is avaliable. - // - // See https://github.com/urfave/cli/issues/294 for additional discussion - flags := c.Command.Flags - if c.Command.Name == "" { // cannot == Command{} since it contains slice types - if c.App != nil { - flags = c.App.Flags - } - } - for _, f := range flags { - eachName(f.GetName(), func(name string) { - if isSet, ok := c.setFlags[name]; isSet || !ok { - return - } - - val := reflect.ValueOf(f) - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - - envVarValue := val.FieldByName("EnvVar") - if !envVarValue.IsValid() { - return - } - - eachName(envVarValue.String(), func(envVar string) { - envVar = strings.TrimSpace(envVar) - if _, ok := syscall.Getenv(envVar); ok { - c.setFlags[name] = true - return - } - }) - }) - } - } - - return c.setFlags[name] -} - -// GlobalIsSet determines if the global flag was actually set -func (c *Context) GlobalIsSet(name string) bool { - ctx := c - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - - for ; ctx != nil; ctx = ctx.parentContext { - if ctx.IsSet(name) { - return true - } - } - return false -} - -// FlagNames returns a slice of flag names used in this context. -func (c *Context) FlagNames() (names []string) { - for _, flag := range c.Command.Flags { - name := strings.Split(flag.GetName(), ",")[0] - if name == "help" { - continue - } - names = append(names, name) - } - return -} - -// GlobalFlagNames returns a slice of global flag names used by the app. -func (c *Context) GlobalFlagNames() (names []string) { - for _, flag := range c.App.Flags { - name := strings.Split(flag.GetName(), ",")[0] - if name == "help" || name == "version" { - continue - } - names = append(names, name) - } - return -} - -// Parent returns the parent context, if any -func (c *Context) Parent() *Context { - return c.parentContext -} - -// value returns the value of the flag coressponding to `name` -func (c *Context) value(name string) interface{} { - return c.flagSet.Lookup(name).Value.(flag.Getter).Get() -} - -// Args contains apps console arguments -type Args []string - -// Args returns the command line arguments associated with the context. -func (c *Context) Args() Args { - args := Args(c.flagSet.Args()) - return args -} - -// NArg returns the number of the command line arguments. -func (c *Context) NArg() int { - return len(c.Args()) -} - -// Get returns the nth argument, or else a blank string -func (a Args) Get(n int) string { - if len(a) > n { - return a[n] - } - return "" -} - -// First returns the first argument, or else a blank string -func (a Args) First() string { - return a.Get(0) -} - -// Tail returns the rest of the arguments (not the first one) -// or else an empty string slice -func (a Args) Tail() []string { - if len(a) >= 2 { - return []string(a)[1:] - } - return []string{} -} - -// Present checks if there are any arguments present -func (a Args) Present() bool { - return len(a) != 0 -} - -// Swap swaps arguments at the given indexes -func (a Args) Swap(from, to int) error { - if from >= len(a) || to >= len(a) { - return errors.New("index out of range") - } - a[from], a[to] = a[to], a[from] - return nil -} - -func globalContext(ctx *Context) *Context { - if ctx == nil { - return nil - } - - for { - if ctx.parentContext == nil { - return ctx - } - ctx = ctx.parentContext - } -} - -func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet { - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - for ; ctx != nil; ctx = ctx.parentContext { - if f := ctx.flagSet.Lookup(name); f != nil { - return ctx.flagSet - } - } - return nil -} - -func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { - switch ff.Value.(type) { - case *StringSlice: - default: - set.Set(name, ff.Value.String()) - } -} - -func normalizeFlags(flags []Flag, set *flag.FlagSet) error { - visited := make(map[string]bool) - set.Visit(func(f *flag.Flag) { - visited[f.Name] = true - }) - for _, f := range flags { - parts := strings.Split(f.GetName(), ",") - if len(parts) == 1 { - continue - } - var ff *flag.Flag - for _, name := range parts { - name = strings.Trim(name, " ") - if visited[name] { - if ff != nil { - return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) - } - ff = set.Lookup(name) - } - } - if ff == nil { - continue - } - for _, name := range parts { - name = strings.Trim(name, " ") - if !visited[name] { - copyFlag(name, ff, set) - } - } - } - return nil -} diff --git a/vendor/github.com/urfave/cli/context_test.go b/vendor/github.com/urfave/cli/context_test.go deleted file mode 100644 index 7acca10..0000000 --- a/vendor/github.com/urfave/cli/context_test.go +++ /dev/null @@ -1,403 +0,0 @@ -package cli - -import ( - "flag" - "os" - "testing" - "time" -) - -func TestNewContext(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int("myflag", 12, "doc") - set.Int64("myflagInt64", int64(12), "doc") - set.Uint("myflagUint", uint(93), "doc") - set.Uint64("myflagUint64", uint64(93), "doc") - set.Float64("myflag64", float64(17), "doc") - globalSet := flag.NewFlagSet("test", 0) - globalSet.Int("myflag", 42, "doc") - globalSet.Int64("myflagInt64", int64(42), "doc") - globalSet.Uint("myflagUint", uint(33), "doc") - globalSet.Uint64("myflagUint64", uint64(33), "doc") - globalSet.Float64("myflag64", float64(47), "doc") - globalCtx := NewContext(nil, globalSet, nil) - command := Command{Name: "mycommand"} - c := NewContext(nil, set, globalCtx) - c.Command = command - expect(t, c.Int("myflag"), 12) - expect(t, c.Int64("myflagInt64"), int64(12)) - expect(t, c.Uint("myflagUint"), uint(93)) - expect(t, c.Uint64("myflagUint64"), uint64(93)) - expect(t, c.Float64("myflag64"), float64(17)) - expect(t, c.GlobalInt("myflag"), 42) - expect(t, c.GlobalInt64("myflagInt64"), int64(42)) - expect(t, c.GlobalUint("myflagUint"), uint(33)) - expect(t, c.GlobalUint64("myflagUint64"), uint64(33)) - expect(t, c.GlobalFloat64("myflag64"), float64(47)) - expect(t, c.Command.Name, "mycommand") -} - -func TestContext_Int(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int("myflag", 12, "doc") - c := NewContext(nil, set, nil) - expect(t, c.Int("myflag"), 12) -} - -func TestContext_Int64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int64("myflagInt64", 12, "doc") - c := NewContext(nil, set, nil) - expect(t, c.Int64("myflagInt64"), int64(12)) -} - -func TestContext_Uint(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Uint("myflagUint", uint(13), "doc") - c := NewContext(nil, set, nil) - expect(t, c.Uint("myflagUint"), uint(13)) -} - -func TestContext_Uint64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Uint64("myflagUint64", uint64(9), "doc") - c := NewContext(nil, set, nil) - expect(t, c.Uint64("myflagUint64"), uint64(9)) -} - -func TestContext_GlobalInt(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int("myflag", 12, "doc") - c := NewContext(nil, set, nil) - expect(t, c.GlobalInt("myflag"), 12) - expect(t, c.GlobalInt("nope"), 0) -} - -func TestContext_GlobalInt64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int64("myflagInt64", 12, "doc") - c := NewContext(nil, set, nil) - expect(t, c.GlobalInt64("myflagInt64"), int64(12)) - expect(t, c.GlobalInt64("nope"), int64(0)) -} - -func TestContext_Float64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Float64("myflag", float64(17), "doc") - c := NewContext(nil, set, nil) - expect(t, c.Float64("myflag"), float64(17)) -} - -func TestContext_GlobalFloat64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Float64("myflag", float64(17), "doc") - c := NewContext(nil, set, nil) - expect(t, c.GlobalFloat64("myflag"), float64(17)) - expect(t, c.GlobalFloat64("nope"), float64(0)) -} - -func TestContext_Duration(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Duration("myflag", time.Duration(12*time.Second), "doc") - c := NewContext(nil, set, nil) - expect(t, c.Duration("myflag"), time.Duration(12*time.Second)) -} - -func TestContext_String(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.String("myflag", "hello world", "doc") - c := NewContext(nil, set, nil) - expect(t, c.String("myflag"), "hello world") -} - -func TestContext_Bool(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - c := NewContext(nil, set, nil) - expect(t, c.Bool("myflag"), false) -} - -func TestContext_BoolT(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", true, "doc") - c := NewContext(nil, set, nil) - expect(t, c.BoolT("myflag"), true) -} - -func TestContext_GlobalBool(t *testing.T) { - set := flag.NewFlagSet("test", 0) - - globalSet := flag.NewFlagSet("test-global", 0) - globalSet.Bool("myflag", false, "doc") - globalCtx := NewContext(nil, globalSet, nil) - - c := NewContext(nil, set, globalCtx) - expect(t, c.GlobalBool("myflag"), false) - expect(t, c.GlobalBool("nope"), false) -} - -func TestContext_GlobalBoolT(t *testing.T) { - set := flag.NewFlagSet("test", 0) - - globalSet := flag.NewFlagSet("test-global", 0) - globalSet.Bool("myflag", true, "doc") - globalCtx := NewContext(nil, globalSet, nil) - - c := NewContext(nil, set, globalCtx) - expect(t, c.GlobalBoolT("myflag"), true) - expect(t, c.GlobalBoolT("nope"), false) -} - -func TestContext_Args(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - c := NewContext(nil, set, nil) - set.Parse([]string{"--myflag", "bat", "baz"}) - expect(t, len(c.Args()), 2) - expect(t, c.Bool("myflag"), true) -} - -func TestContext_NArg(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - c := NewContext(nil, set, nil) - set.Parse([]string{"--myflag", "bat", "baz"}) - expect(t, c.NArg(), 2) -} - -func TestContext_IsSet(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - set.String("otherflag", "hello world", "doc") - globalSet := flag.NewFlagSet("test", 0) - globalSet.Bool("myflagGlobal", true, "doc") - globalCtx := NewContext(nil, globalSet, nil) - c := NewContext(nil, set, globalCtx) - set.Parse([]string{"--myflag", "bat", "baz"}) - globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) - expect(t, c.IsSet("myflag"), true) - expect(t, c.IsSet("otherflag"), false) - expect(t, c.IsSet("bogusflag"), false) - expect(t, c.IsSet("myflagGlobal"), false) -} - -// XXX Corresponds to hack in context.IsSet for flags with EnvVar field -// Should be moved to `flag_test` in v2 -func TestContext_IsSet_fromEnv(t *testing.T) { - var ( - timeoutIsSet, tIsSet bool - noEnvVarIsSet, nIsSet bool - passwordIsSet, pIsSet bool - unparsableIsSet, uIsSet bool - ) - - clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "15.5") - os.Setenv("APP_PASSWORD", "") - a := App{ - Flags: []Flag{ - Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, - StringFlag{Name: "password, p", EnvVar: "APP_PASSWORD"}, - Float64Flag{Name: "unparsable, u", EnvVar: "APP_UNPARSABLE"}, - Float64Flag{Name: "no-env-var, n"}, - }, - Action: func(ctx *Context) error { - timeoutIsSet = ctx.IsSet("timeout") - tIsSet = ctx.IsSet("t") - passwordIsSet = ctx.IsSet("password") - pIsSet = ctx.IsSet("p") - unparsableIsSet = ctx.IsSet("unparsable") - uIsSet = ctx.IsSet("u") - noEnvVarIsSet = ctx.IsSet("no-env-var") - nIsSet = ctx.IsSet("n") - return nil - }, - } - a.Run([]string{"run"}) - expect(t, timeoutIsSet, true) - expect(t, tIsSet, true) - expect(t, passwordIsSet, true) - expect(t, pIsSet, true) - expect(t, noEnvVarIsSet, false) - expect(t, nIsSet, false) - - os.Setenv("APP_UNPARSABLE", "foobar") - a.Run([]string{"run"}) - expect(t, unparsableIsSet, false) - expect(t, uIsSet, false) -} - -func TestContext_GlobalIsSet(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - set.String("otherflag", "hello world", "doc") - globalSet := flag.NewFlagSet("test", 0) - globalSet.Bool("myflagGlobal", true, "doc") - globalSet.Bool("myflagGlobalUnset", true, "doc") - globalCtx := NewContext(nil, globalSet, nil) - c := NewContext(nil, set, globalCtx) - set.Parse([]string{"--myflag", "bat", "baz"}) - globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) - expect(t, c.GlobalIsSet("myflag"), false) - expect(t, c.GlobalIsSet("otherflag"), false) - expect(t, c.GlobalIsSet("bogusflag"), false) - expect(t, c.GlobalIsSet("myflagGlobal"), true) - expect(t, c.GlobalIsSet("myflagGlobalUnset"), false) - expect(t, c.GlobalIsSet("bogusGlobal"), false) -} - -// XXX Corresponds to hack in context.IsSet for flags with EnvVar field -// Should be moved to `flag_test` in v2 -func TestContext_GlobalIsSet_fromEnv(t *testing.T) { - var ( - timeoutIsSet, tIsSet bool - noEnvVarIsSet, nIsSet bool - passwordIsSet, pIsSet bool - unparsableIsSet, uIsSet bool - ) - - clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "15.5") - os.Setenv("APP_PASSWORD", "") - a := App{ - Flags: []Flag{ - Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, - StringFlag{Name: "password, p", EnvVar: "APP_PASSWORD"}, - Float64Flag{Name: "no-env-var, n"}, - Float64Flag{Name: "unparsable, u", EnvVar: "APP_UNPARSABLE"}, - }, - Commands: []Command{ - { - Name: "hello", - Action: func(ctx *Context) error { - timeoutIsSet = ctx.GlobalIsSet("timeout") - tIsSet = ctx.GlobalIsSet("t") - passwordIsSet = ctx.GlobalIsSet("password") - pIsSet = ctx.GlobalIsSet("p") - unparsableIsSet = ctx.GlobalIsSet("unparsable") - uIsSet = ctx.GlobalIsSet("u") - noEnvVarIsSet = ctx.GlobalIsSet("no-env-var") - nIsSet = ctx.GlobalIsSet("n") - return nil - }, - }, - }, - } - if err := a.Run([]string{"run", "hello"}); err != nil { - t.Logf("error running Run(): %+v", err) - } - expect(t, timeoutIsSet, true) - expect(t, tIsSet, true) - expect(t, passwordIsSet, true) - expect(t, pIsSet, true) - expect(t, noEnvVarIsSet, false) - expect(t, nIsSet, false) - - os.Setenv("APP_UNPARSABLE", "foobar") - if err := a.Run([]string{"run"}); err != nil { - t.Logf("error running Run(): %+v", err) - } - expect(t, unparsableIsSet, false) - expect(t, uIsSet, false) -} - -func TestContext_NumFlags(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Bool("myflag", false, "doc") - set.String("otherflag", "hello world", "doc") - globalSet := flag.NewFlagSet("test", 0) - globalSet.Bool("myflagGlobal", true, "doc") - globalCtx := NewContext(nil, globalSet, nil) - c := NewContext(nil, set, globalCtx) - set.Parse([]string{"--myflag", "--otherflag=foo"}) - globalSet.Parse([]string{"--myflagGlobal"}) - expect(t, c.NumFlags(), 2) -} - -func TestContext_GlobalFlag(t *testing.T) { - var globalFlag string - var globalFlagSet bool - app := NewApp() - app.Flags = []Flag{ - StringFlag{Name: "global, g", Usage: "global"}, - } - app.Action = func(c *Context) error { - globalFlag = c.GlobalString("global") - globalFlagSet = c.GlobalIsSet("global") - return nil - } - app.Run([]string{"command", "-g", "foo"}) - expect(t, globalFlag, "foo") - expect(t, globalFlagSet, true) - -} - -func TestContext_GlobalFlagsInSubcommands(t *testing.T) { - subcommandRun := false - parentFlag := false - app := NewApp() - - app.Flags = []Flag{ - BoolFlag{Name: "debug, d", Usage: "Enable debugging"}, - } - - app.Commands = []Command{ - { - Name: "foo", - Flags: []Flag{ - BoolFlag{Name: "parent, p", Usage: "Parent flag"}, - }, - Subcommands: []Command{ - { - Name: "bar", - Action: func(c *Context) error { - if c.GlobalBool("debug") { - subcommandRun = true - } - if c.GlobalBool("parent") { - parentFlag = true - } - return nil - }, - }, - }, - }, - } - - app.Run([]string{"command", "-d", "foo", "-p", "bar"}) - - expect(t, subcommandRun, true) - expect(t, parentFlag, true) -} - -func TestContext_Set(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int("int", 5, "an int") - c := NewContext(nil, set, nil) - - expect(t, c.IsSet("int"), false) - c.Set("int", "1") - expect(t, c.Int("int"), 1) - expect(t, c.IsSet("int"), true) -} - -func TestContext_GlobalSet(t *testing.T) { - gSet := flag.NewFlagSet("test", 0) - gSet.Int("int", 5, "an int") - - set := flag.NewFlagSet("sub", 0) - set.Int("int", 3, "an int") - - pc := NewContext(nil, gSet, nil) - c := NewContext(nil, set, pc) - - c.Set("int", "1") - expect(t, c.Int("int"), 1) - expect(t, c.GlobalInt("int"), 5) - - expect(t, c.GlobalIsSet("int"), false) - c.GlobalSet("int", "1") - expect(t, c.Int("int"), 1) - expect(t, c.GlobalInt("int"), 1) - expect(t, c.GlobalIsSet("int"), true) -} diff --git a/vendor/github.com/urfave/cli/errors.go b/vendor/github.com/urfave/cli/errors.go deleted file mode 100644 index 562b295..0000000 --- a/vendor/github.com/urfave/cli/errors.go +++ /dev/null @@ -1,115 +0,0 @@ -package cli - -import ( - "fmt" - "io" - "os" - "strings" -) - -// OsExiter is the function used when the app exits. If not set defaults to os.Exit. -var OsExiter = os.Exit - -// ErrWriter is used to write errors to the user. This can be anything -// implementing the io.Writer interface and defaults to os.Stderr. -var ErrWriter io.Writer = os.Stderr - -// MultiError is an error that wraps multiple errors. -type MultiError struct { - Errors []error -} - -// NewMultiError creates a new MultiError. Pass in one or more errors. -func NewMultiError(err ...error) MultiError { - return MultiError{Errors: err} -} - -// Error implements the error interface. -func (m MultiError) Error() string { - errs := make([]string, len(m.Errors)) - for i, err := range m.Errors { - errs[i] = err.Error() - } - - return strings.Join(errs, "\n") -} - -type ErrorFormatter interface { - Format(s fmt.State, verb rune) -} - -// ExitCoder is the interface checked by `App` and `Command` for a custom exit -// code -type ExitCoder interface { - error - ExitCode() int -} - -// ExitError fulfills both the builtin `error` interface and `ExitCoder` -type ExitError struct { - exitCode int - message interface{} -} - -// NewExitError makes a new *ExitError -func NewExitError(message interface{}, exitCode int) *ExitError { - return &ExitError{ - exitCode: exitCode, - message: message, - } -} - -// Error returns the string message, fulfilling the interface required by -// `error` -func (ee *ExitError) Error() string { - return fmt.Sprintf("%v", ee.message) -} - -// ExitCode returns the exit code, fulfilling the interface required by -// `ExitCoder` -func (ee *ExitError) ExitCode() int { - return ee.exitCode -} - -// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if -// so prints the error to stderr (if it is non-empty) and calls OsExiter with the -// given exit code. If the given error is a MultiError, then this func is -// called on all members of the Errors slice and calls OsExiter with the last exit code. -func HandleExitCoder(err error) { - if err == nil { - return - } - - if exitErr, ok := err.(ExitCoder); ok { - if err.Error() != "" { - if _, ok := exitErr.(ErrorFormatter); ok { - fmt.Fprintf(ErrWriter, "%+v\n", err) - } else { - fmt.Fprintln(ErrWriter, err) - } - } - OsExiter(exitErr.ExitCode()) - return - } - - if multiErr, ok := err.(MultiError); ok { - code := handleMultiError(multiErr) - OsExiter(code) - return - } -} - -func handleMultiError(multiErr MultiError) int { - code := 1 - for _, merr := range multiErr.Errors { - if multiErr2, ok := merr.(MultiError); ok { - code = handleMultiError(multiErr2) - } else { - fmt.Fprintln(ErrWriter, merr) - if exitErr, ok := merr.(ExitCoder); ok { - code = exitErr.ExitCode() - } - } - } - return code -} diff --git a/vendor/github.com/urfave/cli/errors_test.go b/vendor/github.com/urfave/cli/errors_test.go deleted file mode 100644 index 9b609c5..0000000 --- a/vendor/github.com/urfave/cli/errors_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package cli - -import ( - "bytes" - "errors" - "fmt" - "testing" -) - -func TestHandleExitCoder_nil(t *testing.T) { - exitCode := 0 - called := false - - OsExiter = func(rc int) { - if !called { - exitCode = rc - called = true - } - } - - defer func() { OsExiter = fakeOsExiter }() - - HandleExitCoder(nil) - - expect(t, exitCode, 0) - expect(t, called, false) -} - -func TestHandleExitCoder_ExitCoder(t *testing.T) { - exitCode := 0 - called := false - - OsExiter = func(rc int) { - if !called { - exitCode = rc - called = true - } - } - - defer func() { OsExiter = fakeOsExiter }() - - HandleExitCoder(NewExitError("galactic perimeter breach", 9)) - - expect(t, exitCode, 9) - expect(t, called, true) -} - -func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) { - exitCode := 0 - called := false - - OsExiter = func(rc int) { - if !called { - exitCode = rc - called = true - } - } - - defer func() { OsExiter = fakeOsExiter }() - - exitErr := NewExitError("galactic perimeter breach", 9) - exitErr2 := NewExitError("last ExitCoder", 11) - err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr, exitErr2) - HandleExitCoder(err) - - expect(t, exitCode, 11) - expect(t, called, true) -} - -// make a stub to not import pkg/errors -type ErrorWithFormat struct { - error -} - -func NewErrorWithFormat(m string) *ErrorWithFormat { - return &ErrorWithFormat{error: errors.New(m)} -} - -func (f *ErrorWithFormat) Format(s fmt.State, verb rune) { - fmt.Fprintf(s, "This the format: %v", f.error) -} - -func TestHandleExitCoder_ErrorWithFormat(t *testing.T) { - called := false - - OsExiter = func(rc int) { - if !called { - called = true - } - } - ErrWriter = &bytes.Buffer{} - - defer func() { - OsExiter = fakeOsExiter - ErrWriter = fakeErrWriter - }() - - err := NewExitError(NewErrorWithFormat("I am formatted"), 1) - HandleExitCoder(err) - - expect(t, called, true) - expect(t, ErrWriter.(*bytes.Buffer).String(), "This the format: I am formatted\n") -} - -func TestHandleExitCoder_MultiErrorWithFormat(t *testing.T) { - called := false - - OsExiter = func(rc int) { - if !called { - called = true - } - } - ErrWriter = &bytes.Buffer{} - - defer func() { OsExiter = fakeOsExiter }() - - err := NewMultiError(NewErrorWithFormat("err1"), NewErrorWithFormat("err2")) - HandleExitCoder(err) - - expect(t, called, true) - expect(t, ErrWriter.(*bytes.Buffer).String(), "This the format: err1\nThis the format: err2\n") -} diff --git a/vendor/github.com/urfave/cli/flag-types.json b/vendor/github.com/urfave/cli/flag-types.json deleted file mode 100644 index 1223107..0000000 --- a/vendor/github.com/urfave/cli/flag-types.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "name": "Bool", - "type": "bool", - "value": false, - "context_default": "false", - "parser": "strconv.ParseBool(f.Value.String())" - }, - { - "name": "BoolT", - "type": "bool", - "value": false, - "doctail": " that is true by default", - "context_default": "false", - "parser": "strconv.ParseBool(f.Value.String())" - }, - { - "name": "Duration", - "type": "time.Duration", - "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", - "context_default": "0", - "parser": "time.ParseDuration(f.Value.String())" - }, - { - "name": "Float64", - "type": "float64", - "context_default": "0", - "parser": "strconv.ParseFloat(f.Value.String(), 64)" - }, - { - "name": "Generic", - "type": "Generic", - "dest": false, - "context_default": "nil", - "context_type": "interface{}" - }, - { - "name": "Int64", - "type": "int64", - "context_default": "0", - "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" - }, - { - "name": "Int", - "type": "int", - "context_default": "0", - "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", - "parser_cast": "int(parsed)" - }, - { - "name": "IntSlice", - "type": "*IntSlice", - "dest": false, - "context_default": "nil", - "context_type": "[]int", - "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" - }, - { - "name": "Int64Slice", - "type": "*Int64Slice", - "dest": false, - "context_default": "nil", - "context_type": "[]int64", - "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" - }, - { - "name": "String", - "type": "string", - "context_default": "\"\"", - "parser": "f.Value.String(), error(nil)" - }, - { - "name": "StringSlice", - "type": "*StringSlice", - "dest": false, - "context_default": "nil", - "context_type": "[]string", - "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" - }, - { - "name": "Uint64", - "type": "uint64", - "context_default": "0", - "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" - }, - { - "name": "Uint", - "type": "uint", - "context_default": "0", - "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", - "parser_cast": "uint(parsed)" - } -] diff --git a/vendor/github.com/urfave/cli/flag.go b/vendor/github.com/urfave/cli/flag.go deleted file mode 100644 index 877ff35..0000000 --- a/vendor/github.com/urfave/cli/flag.go +++ /dev/null @@ -1,799 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "reflect" - "runtime" - "strconv" - "strings" - "syscall" - "time" -) - -const defaultPlaceholder = "value" - -// BashCompletionFlag enables bash-completion for all commands and subcommands -var BashCompletionFlag Flag = BoolFlag{ - Name: "generate-bash-completion", - Hidden: true, -} - -// VersionFlag prints the version for the application -var VersionFlag Flag = BoolFlag{ - Name: "version, v", - Usage: "print the version", -} - -// HelpFlag prints the help for all commands and subcommands -// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand -// unless HideHelp is set to true) -var HelpFlag Flag = BoolFlag{ - Name: "help, h", - Usage: "show help", -} - -// FlagStringer converts a flag definition to a string. This is used by help -// to display a flag. -var FlagStringer FlagStringFunc = stringifyFlag - -// FlagsByName is a slice of Flag. -type FlagsByName []Flag - -func (f FlagsByName) Len() int { - return len(f) -} - -func (f FlagsByName) Less(i, j int) bool { - return f[i].GetName() < f[j].GetName() -} - -func (f FlagsByName) Swap(i, j int) { - f[i], f[j] = f[j], f[i] -} - -// Flag is a common interface related to parsing flags in cli. -// For more advanced flag parsing techniques, it is recommended that -// this interface be implemented. -type Flag interface { - fmt.Stringer - // Apply Flag settings to the given flag set - Apply(*flag.FlagSet) - GetName() string -} - -// errorableFlag is an interface that allows us to return errors during apply -// it allows flags defined in this library to return errors in a fashion backwards compatible -// TODO remove in v2 and modify the existing Flag interface to return errors -type errorableFlag interface { - Flag - - ApplyWithError(*flag.FlagSet) error -} - -func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { - set := flag.NewFlagSet(name, flag.ContinueOnError) - - for _, f := range flags { - //TODO remove in v2 when errorableFlag is removed - if ef, ok := f.(errorableFlag); ok { - if err := ef.ApplyWithError(set); err != nil { - return nil, err - } - } else { - f.Apply(set) - } - } - return set, nil -} - -func eachName(longName string, fn func(string)) { - parts := strings.Split(longName, ",") - for _, name := range parts { - name = strings.Trim(name, " ") - fn(name) - } -} - -// Generic is a generic parseable type identified by a specific flag -type Generic interface { - Set(value string) error - String() string -} - -// Apply takes the flagset and calls Set on the generic flag with the value -// provided by the user for parsing by the flag -// Ignores parsing errors -func (f GenericFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError takes the flagset and calls Set on the generic flag with the value -// provided by the user for parsing by the flag -func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error { - val := f.Value - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - if err := val.Set(envVal); err != nil { - return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err) - } - break - } - } - } - - eachName(f.Name, func(name string) { - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter -type StringSlice []string - -// Set appends the string value to the list of values -func (f *StringSlice) Set(value string) error { - *f = append(*f, value) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *StringSlice) String() string { - return fmt.Sprintf("%s", *f) -} - -// Value returns the slice of strings set by this flag -func (f *StringSlice) Value() []string { - return *f -} - -// Get returns the slice of strings set by this flag -func (f *StringSlice) Get() interface{} { - return *f -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f StringSliceFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - newVal := &StringSlice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err) - } - } - f.Value = newVal - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &StringSlice{} - } - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter -type IntSlice []int - -// Set parses the value into an integer and appends it to the list of values -func (f *IntSlice) Set(value string) error { - tmp, err := strconv.Atoi(value) - if err != nil { - return err - } - *f = append(*f, tmp) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *IntSlice) String() string { - return fmt.Sprintf("%#v", *f) -} - -// Value returns the slice of ints set by this flag -func (f *IntSlice) Value() []int { - return *f -} - -// Get returns the slice of ints set by this flag -func (f *IntSlice) Get() interface{} { - return *f -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f IntSliceFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - newVal := &IntSlice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err) - } - } - f.Value = newVal - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &IntSlice{} - } - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter -type Int64Slice []int64 - -// Set parses the value into an integer and appends it to the list of values -func (f *Int64Slice) Set(value string) error { - tmp, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return err - } - *f = append(*f, tmp) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *Int64Slice) String() string { - return fmt.Sprintf("%#v", *f) -} - -// Value returns the slice of ints set by this flag -func (f *Int64Slice) Value() []int64 { - return *f -} - -// Get returns the slice of ints set by this flag -func (f *Int64Slice) Get() interface{} { - return *f -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Int64SliceFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - newVal := &Int64Slice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err) - } - } - f.Value = newVal - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &Int64Slice{} - } - set.Var(f.Value, name, f.Usage) - }) - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f BoolFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error { - val := false - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - if envVal == "" { - val = false - break - } - - envValBool, err := strconv.ParseBool(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) - } - - val = envValBool - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.BoolVar(f.Destination, name, val, f.Usage) - return - } - set.Bool(name, val, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f BoolTFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error { - val := true - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - if envVal == "" { - val = false - break - } - - envValBool, err := strconv.ParseBool(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) - } - - val = envValBool - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.BoolVar(f.Destination, name, val, f.Usage) - return - } - set.Bool(name, val, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f StringFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f StringFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - f.Value = envVal - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.StringVar(f.Destination, name, f.Value, f.Usage) - return - } - set.String(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f IntFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f IntFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) - } - f.Value = int(envValInt) - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.IntVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Int(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Int64Flag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValInt - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Int64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Int64(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f UintFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f UintFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = uint(envValInt) - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.UintVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Uint(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Uint64Flag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = uint64(envValInt) - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Uint64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Uint64(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f DurationFlag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValDuration, err := time.ParseDuration(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValDuration - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.DurationVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Duration(name, f.Value, f.Usage) - }) - - return nil -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Float64Flag) Apply(set *flag.FlagSet) { - f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error { - if f.EnvVar != "" { - for _, envVar := range strings.Split(f.EnvVar, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - envValFloat, err := strconv.ParseFloat(envVal, 10) - if err != nil { - return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = float64(envValFloat) - break - } - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Float64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Float64(name, f.Value, f.Usage) - }) - - return nil -} - -func visibleFlags(fl []Flag) []Flag { - visible := []Flag{} - for _, flag := range fl { - field := flagValue(flag).FieldByName("Hidden") - if !field.IsValid() || !field.Bool() { - visible = append(visible, flag) - } - } - return visible -} - -func prefixFor(name string) (prefix string) { - if len(name) == 1 { - prefix = "-" - } else { - prefix = "--" - } - - return -} - -// Returns the placeholder, if any, and the unquoted usage string. -func unquoteUsage(usage string) (string, string) { - for i := 0; i < len(usage); i++ { - if usage[i] == '`' { - for j := i + 1; j < len(usage); j++ { - if usage[j] == '`' { - name := usage[i+1 : j] - usage = usage[:i] + name + usage[j+1:] - return name, usage - } - } - break - } - } - return "", usage -} - -func prefixedNames(fullName, placeholder string) string { - var prefixed string - parts := strings.Split(fullName, ",") - for i, name := range parts { - name = strings.Trim(name, " ") - prefixed += prefixFor(name) + name - if placeholder != "" { - prefixed += " " + placeholder - } - if i < len(parts)-1 { - prefixed += ", " - } - } - return prefixed -} - -func withEnvHint(envVar, str string) string { - envText := "" - if envVar != "" { - prefix := "$" - suffix := "" - sep := ", $" - if runtime.GOOS == "windows" { - prefix = "%" - suffix = "%" - sep = "%, %" - } - envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix) - } - return str + envText -} - -func flagValue(f Flag) reflect.Value { - fv := reflect.ValueOf(f) - for fv.Kind() == reflect.Ptr { - fv = reflect.Indirect(fv) - } - return fv -} - -func stringifyFlag(f Flag) string { - fv := flagValue(f) - - switch f.(type) { - case IntSliceFlag: - return withEnvHint(fv.FieldByName("EnvVar").String(), - stringifyIntSliceFlag(f.(IntSliceFlag))) - case Int64SliceFlag: - return withEnvHint(fv.FieldByName("EnvVar").String(), - stringifyInt64SliceFlag(f.(Int64SliceFlag))) - case StringSliceFlag: - return withEnvHint(fv.FieldByName("EnvVar").String(), - stringifyStringSliceFlag(f.(StringSliceFlag))) - } - - placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) - - needsPlaceholder := false - defaultValueString := "" - - if val := fv.FieldByName("Value"); val.IsValid() { - needsPlaceholder = true - defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) - - if val.Kind() == reflect.String && val.String() != "" { - defaultValueString = fmt.Sprintf(" (default: %q)", val.String()) - } - } - - if defaultValueString == " (default: )" { - defaultValueString = "" - } - - if needsPlaceholder && placeholder == "" { - placeholder = defaultPlaceholder - } - - usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString)) - - return withEnvHint(fv.FieldByName("EnvVar").String(), - fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault)) -} - -func stringifyIntSliceFlag(f IntSliceFlag) string { - defaultVals := []string{} - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, fmt.Sprintf("%d", i)) - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifyInt64SliceFlag(f Int64SliceFlag) string { - defaultVals := []string{} - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, fmt.Sprintf("%d", i)) - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifyStringSliceFlag(f StringSliceFlag) string { - defaultVals := []string{} - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, s := range f.Value.Value() { - if len(s) > 0 { - defaultVals = append(defaultVals, fmt.Sprintf("%q", s)) - } - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifySliceFlag(usage, name string, defaultVals []string) string { - placeholder, usage := unquoteUsage(usage) - if placeholder == "" { - placeholder = defaultPlaceholder - } - - defaultVal := "" - if len(defaultVals) > 0 { - defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", ")) - } - - usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) - return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault) -} diff --git a/vendor/github.com/urfave/cli/flag_generated.go b/vendor/github.com/urfave/cli/flag_generated.go deleted file mode 100644 index 491b619..0000000 --- a/vendor/github.com/urfave/cli/flag_generated.go +++ /dev/null @@ -1,627 +0,0 @@ -package cli - -import ( - "flag" - "strconv" - "time" -) - -// WARNING: This file is generated! - -// BoolFlag is a flag with type bool -type BoolFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Destination *bool -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f BoolFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f BoolFlag) GetName() string { - return f.Name -} - -// Bool looks up the value of a local BoolFlag, returns -// false if not found -func (c *Context) Bool(name string) bool { - return lookupBool(name, c.flagSet) -} - -// GlobalBool looks up the value of a global BoolFlag, returns -// false if not found -func (c *Context) GlobalBool(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBool(name, fs) - } - return false -} - -func lookupBool(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return parsed - } - return false -} - -// BoolTFlag is a flag with type bool that is true by default -type BoolTFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Destination *bool -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f BoolTFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f BoolTFlag) GetName() string { - return f.Name -} - -// BoolT looks up the value of a local BoolTFlag, returns -// false if not found -func (c *Context) BoolT(name string) bool { - return lookupBoolT(name, c.flagSet) -} - -// GlobalBoolT looks up the value of a global BoolTFlag, returns -// false if not found -func (c *Context) GlobalBoolT(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBoolT(name, fs) - } - return false -} - -func lookupBoolT(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return parsed - } - return false -} - -// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) -type DurationFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value time.Duration - Destination *time.Duration -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f DurationFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f DurationFlag) GetName() string { - return f.Name -} - -// Duration looks up the value of a local DurationFlag, returns -// 0 if not found -func (c *Context) Duration(name string) time.Duration { - return lookupDuration(name, c.flagSet) -} - -// GlobalDuration looks up the value of a global DurationFlag, returns -// 0 if not found -func (c *Context) GlobalDuration(name string) time.Duration { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupDuration(name, fs) - } - return 0 -} - -func lookupDuration(name string, set *flag.FlagSet) time.Duration { - f := set.Lookup(name) - if f != nil { - parsed, err := time.ParseDuration(f.Value.String()) - if err != nil { - return 0 - } - return parsed - } - return 0 -} - -// Float64Flag is a flag with type float64 -type Float64Flag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value float64 - Destination *float64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Float64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Float64Flag) GetName() string { - return f.Name -} - -// Float64 looks up the value of a local Float64Flag, returns -// 0 if not found -func (c *Context) Float64(name string) float64 { - return lookupFloat64(name, c.flagSet) -} - -// GlobalFloat64 looks up the value of a global Float64Flag, returns -// 0 if not found -func (c *Context) GlobalFloat64(name string) float64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupFloat64(name, fs) - } - return 0 -} - -func lookupFloat64(name string, set *flag.FlagSet) float64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseFloat(f.Value.String(), 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} - -// GenericFlag is a flag with type Generic -type GenericFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value Generic -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f GenericFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f GenericFlag) GetName() string { - return f.Name -} - -// Generic looks up the value of a local GenericFlag, returns -// nil if not found -func (c *Context) Generic(name string) interface{} { - return lookupGeneric(name, c.flagSet) -} - -// GlobalGeneric looks up the value of a global GenericFlag, returns -// nil if not found -func (c *Context) GlobalGeneric(name string) interface{} { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupGeneric(name, fs) - } - return nil -} - -func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value, error(nil) - if err != nil { - return nil - } - return parsed - } - return nil -} - -// Int64Flag is a flag with type int64 -type Int64Flag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value int64 - Destination *int64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Int64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Int64Flag) GetName() string { - return f.Name -} - -// Int64 looks up the value of a local Int64Flag, returns -// 0 if not found -func (c *Context) Int64(name string) int64 { - return lookupInt64(name, c.flagSet) -} - -// GlobalInt64 looks up the value of a global Int64Flag, returns -// 0 if not found -func (c *Context) GlobalInt64(name string) int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64(name, fs) - } - return 0 -} - -func lookupInt64(name string, set *flag.FlagSet) int64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} - -// IntFlag is a flag with type int -type IntFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value int - Destination *int -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f IntFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f IntFlag) GetName() string { - return f.Name -} - -// Int looks up the value of a local IntFlag, returns -// 0 if not found -func (c *Context) Int(name string) int { - return lookupInt(name, c.flagSet) -} - -// GlobalInt looks up the value of a global IntFlag, returns -// 0 if not found -func (c *Context) GlobalInt(name string) int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt(name, fs) - } - return 0 -} - -func lookupInt(name string, set *flag.FlagSet) int { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return int(parsed) - } - return 0 -} - -// IntSliceFlag is a flag with type *IntSlice -type IntSliceFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value *IntSlice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f IntSliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f IntSliceFlag) GetName() string { - return f.Name -} - -// IntSlice looks up the value of a local IntSliceFlag, returns -// nil if not found -func (c *Context) IntSlice(name string) []int { - return lookupIntSlice(name, c.flagSet) -} - -// GlobalIntSlice looks up the value of a global IntSliceFlag, returns -// nil if not found -func (c *Context) GlobalIntSlice(name string) []int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupIntSlice(name, fs) - } - return nil -} - -func lookupIntSlice(name string, set *flag.FlagSet) []int { - f := set.Lookup(name) - if f != nil { - parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) - if err != nil { - return nil - } - return parsed - } - return nil -} - -// Int64SliceFlag is a flag with type *Int64Slice -type Int64SliceFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value *Int64Slice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Int64SliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Int64SliceFlag) GetName() string { - return f.Name -} - -// Int64Slice looks up the value of a local Int64SliceFlag, returns -// nil if not found -func (c *Context) Int64Slice(name string) []int64 { - return lookupInt64Slice(name, c.flagSet) -} - -// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns -// nil if not found -func (c *Context) GlobalInt64Slice(name string) []int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) - if err != nil { - return nil - } - return parsed - } - return nil -} - -// StringFlag is a flag with type string -type StringFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value string - Destination *string -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f StringFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f StringFlag) GetName() string { - return f.Name -} - -// String looks up the value of a local StringFlag, returns -// "" if not found -func (c *Context) String(name string) string { - return lookupString(name, c.flagSet) -} - -// GlobalString looks up the value of a global StringFlag, returns -// "" if not found -func (c *Context) GlobalString(name string) string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupString(name, fs) - } - return "" -} - -func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value.String(), error(nil) - if err != nil { - return "" - } - return parsed - } - return "" -} - -// StringSliceFlag is a flag with type *StringSlice -type StringSliceFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value *StringSlice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f StringSliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f StringSliceFlag) GetName() string { - return f.Name -} - -// StringSlice looks up the value of a local StringSliceFlag, returns -// nil if not found -func (c *Context) StringSlice(name string) []string { - return lookupStringSlice(name, c.flagSet) -} - -// GlobalStringSlice looks up the value of a global StringSliceFlag, returns -// nil if not found -func (c *Context) GlobalStringSlice(name string) []string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupStringSlice(name, fs) - } - return nil -} - -func lookupStringSlice(name string, set *flag.FlagSet) []string { - f := set.Lookup(name) - if f != nil { - parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) - if err != nil { - return nil - } - return parsed - } - return nil -} - -// Uint64Flag is a flag with type uint64 -type Uint64Flag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value uint64 - Destination *uint64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Uint64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Uint64Flag) GetName() string { - return f.Name -} - -// Uint64 looks up the value of a local Uint64Flag, returns -// 0 if not found -func (c *Context) Uint64(name string) uint64 { - return lookupUint64(name, c.flagSet) -} - -// GlobalUint64 looks up the value of a global Uint64Flag, returns -// 0 if not found -func (c *Context) GlobalUint64(name string) uint64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint64(name, fs) - } - return 0 -} - -func lookupUint64(name string, set *flag.FlagSet) uint64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} - -// UintFlag is a flag with type uint -type UintFlag struct { - Name string - Usage string - EnvVar string - Hidden bool - Value uint - Destination *uint -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f UintFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f UintFlag) GetName() string { - return f.Name -} - -// Uint looks up the value of a local UintFlag, returns -// 0 if not found -func (c *Context) Uint(name string) uint { - return lookupUint(name, c.flagSet) -} - -// GlobalUint looks up the value of a global UintFlag, returns -// 0 if not found -func (c *Context) GlobalUint(name string) uint { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint(name, fs) - } - return 0 -} - -func lookupUint(name string, set *flag.FlagSet) uint { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return uint(parsed) - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_test.go b/vendor/github.com/urfave/cli/flag_test.go deleted file mode 100644 index 1ccb639..0000000 --- a/vendor/github.com/urfave/cli/flag_test.go +++ /dev/null @@ -1,1215 +0,0 @@ -package cli - -import ( - "fmt" - "os" - "reflect" - "regexp" - "runtime" - "strings" - "testing" - "time" -) - -var boolFlagTests = []struct { - name string - expected string -}{ - {"help", "--help\t"}, - {"h", "-h\t"}, -} - -func TestBoolFlagHelpOutput(t *testing.T) { - for _, test := range boolFlagTests { - flag := BoolFlag{Name: test.name} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestFlagsFromEnv(t *testing.T) { - var flagTests = []struct { - input string - output interface{} - flag Flag - errRegexp string - }{ - {"", false, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"1", true, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"false", false, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"foobar", true, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, fmt.Sprintf(`could not parse foobar as bool value for flag debug: .*`)}, - - {"", false, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"1", true, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"false", false, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, ""}, - {"foobar", true, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, fmt.Sprintf(`could not parse foobar as bool value for flag debug: .*`)}, - - {"1s", 1 * time.Second, DurationFlag{Name: "time", EnvVar: "TIME"}, ""}, - {"foobar", false, DurationFlag{Name: "time", EnvVar: "TIME"}, fmt.Sprintf(`could not parse foobar as duration for flag time: .*`)}, - - {"1.2", 1.2, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1", 1.0, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"foobar", 0, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as float64 value for flag seconds: .*`)}, - - {"1", int64(1), Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2", 0, Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)}, - {"foobar", 0, Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)}, - - {"1", 1, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2", 0, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)}, - {"foobar", 0, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)}, - - {"1,2", IntSlice{1, 2}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2,2", IntSlice{}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2,2 as int slice value for flag seconds: .*`)}, - {"foobar", IntSlice{}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int slice value for flag seconds: .*`)}, - - {"1,2", Int64Slice{1, 2}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2,2", Int64Slice{}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2,2 as int64 slice value for flag seconds: .*`)}, - {"foobar", Int64Slice{}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int64 slice value for flag seconds: .*`)}, - - {"foo", "foo", StringFlag{Name: "name", EnvVar: "NAME"}, ""}, - - {"foo,bar", StringSlice{"foo", "bar"}, StringSliceFlag{Name: "names", EnvVar: "NAMES"}, ""}, - - {"1", uint(1), UintFlag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2", 0, UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as uint value for flag seconds: .*`)}, - {"foobar", 0, UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as uint value for flag seconds: .*`)}, - - {"1", uint64(1), Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""}, - {"1.2", 0, Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as uint64 value for flag seconds: .*`)}, - {"foobar", 0, Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as uint64 value for flag seconds: .*`)}, - - {"foo,bar", &Parser{"foo", "bar"}, GenericFlag{Name: "names", Value: &Parser{}, EnvVar: "NAMES"}, ""}, - } - - for _, test := range flagTests { - os.Clearenv() - os.Setenv(reflect.ValueOf(test.flag).FieldByName("EnvVar").String(), test.input) - a := App{ - Flags: []Flag{test.flag}, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.value(test.flag.GetName()), test.output) { - t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.value(test.flag.GetName())) - } - return nil - }, - } - - err := a.Run([]string{"run"}) - - if test.errRegexp != "" { - if err == nil { - t.Errorf("expected error to match %s, got none", test.errRegexp) - } else { - if matched, _ := regexp.MatchString(test.errRegexp, err.Error()); !matched { - t.Errorf("expected error to match %s, got error %s", test.errRegexp, err) - } - } - } else { - if err != nil && test.errRegexp == "" { - t.Errorf("expected no error got %s", err) - } - } - } -} - -var stringFlagTests = []struct { - name string - usage string - value string - expected string -}{ - {"foo", "", "", "--foo value\t"}, - {"f", "", "", "-f value\t"}, - {"f", "The total `foo` desired", "all", "-f foo\tThe total foo desired (default: \"all\")"}, - {"test", "", "Something", "--test value\t(default: \"Something\")"}, - {"config,c", "Load configuration from `FILE`", "", "--config FILE, -c FILE\tLoad configuration from FILE"}, - {"config,c", "Load configuration from `CONFIG`", "config.json", "--config CONFIG, -c CONFIG\tLoad configuration from CONFIG (default: \"config.json\")"}, -} - -func TestStringFlagHelpOutput(t *testing.T) { - for _, test := range stringFlagTests { - flag := StringFlag{Name: test.name, Usage: test.usage, Value: test.value} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestStringFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_FOO", "derp") - for _, test := range stringFlagTests { - flag := StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"} - output := flag.String() - - expectedSuffix := " [$APP_FOO]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_FOO%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var stringSliceFlagTests = []struct { - name string - value *StringSlice - expected string -}{ - {"foo", func() *StringSlice { - s := &StringSlice{} - s.Set("") - return s - }(), "--foo value\t"}, - {"f", func() *StringSlice { - s := &StringSlice{} - s.Set("") - return s - }(), "-f value\t"}, - {"f", func() *StringSlice { - s := &StringSlice{} - s.Set("Lipstick") - return s - }(), "-f value\t(default: \"Lipstick\")"}, - {"test", func() *StringSlice { - s := &StringSlice{} - s.Set("Something") - return s - }(), "--test value\t(default: \"Something\")"}, -} - -func TestStringSliceFlagHelpOutput(t *testing.T) { - for _, test := range stringSliceFlagTests { - flag := StringSliceFlag{Name: test.name, Value: test.value} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_QWWX", "11,4") - for _, test := range stringSliceFlagTests { - flag := StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"} - output := flag.String() - - expectedSuffix := " [$APP_QWWX]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_QWWX%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%q does not end with"+expectedSuffix, output) - } - } -} - -var intFlagTests = []struct { - name string - expected string -}{ - {"hats", "--hats value\t(default: 9)"}, - {"H", "-H value\t(default: 9)"}, -} - -func TestIntFlagHelpOutput(t *testing.T) { - for _, test := range intFlagTests { - flag := IntFlag{Name: test.name, Value: 9} - output := flag.String() - - if output != test.expected { - t.Errorf("%s does not match %s", output, test.expected) - } - } -} - -func TestIntFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAR", "2") - for _, test := range intFlagTests { - flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"} - output := flag.String() - - expectedSuffix := " [$APP_BAR]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAR%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var int64FlagTests = []struct { - name string - expected string -}{ - {"hats", "--hats value\t(default: 8589934592)"}, - {"H", "-H value\t(default: 8589934592)"}, -} - -func TestInt64FlagHelpOutput(t *testing.T) { - for _, test := range int64FlagTests { - flag := Int64Flag{Name: test.name, Value: 8589934592} - output := flag.String() - - if output != test.expected { - t.Errorf("%s does not match %s", output, test.expected) - } - } -} - -func TestInt64FlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAR", "2") - for _, test := range int64FlagTests { - flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"} - output := flag.String() - - expectedSuffix := " [$APP_BAR]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAR%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var uintFlagTests = []struct { - name string - expected string -}{ - {"nerfs", "--nerfs value\t(default: 41)"}, - {"N", "-N value\t(default: 41)"}, -} - -func TestUintFlagHelpOutput(t *testing.T) { - for _, test := range uintFlagTests { - flag := UintFlag{Name: test.name, Value: 41} - output := flag.String() - - if output != test.expected { - t.Errorf("%s does not match %s", output, test.expected) - } - } -} - -func TestUintFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAR", "2") - for _, test := range uintFlagTests { - flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"} - output := flag.String() - - expectedSuffix := " [$APP_BAR]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAR%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var uint64FlagTests = []struct { - name string - expected string -}{ - {"gerfs", "--gerfs value\t(default: 8589934582)"}, - {"G", "-G value\t(default: 8589934582)"}, -} - -func TestUint64FlagHelpOutput(t *testing.T) { - for _, test := range uint64FlagTests { - flag := Uint64Flag{Name: test.name, Value: 8589934582} - output := flag.String() - - if output != test.expected { - t.Errorf("%s does not match %s", output, test.expected) - } - } -} - -func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAR", "2") - for _, test := range uint64FlagTests { - flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"} - output := flag.String() - - expectedSuffix := " [$APP_BAR]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAR%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var durationFlagTests = []struct { - name string - expected string -}{ - {"hooting", "--hooting value\t(default: 1s)"}, - {"H", "-H value\t(default: 1s)"}, -} - -func TestDurationFlagHelpOutput(t *testing.T) { - for _, test := range durationFlagTests { - flag := DurationFlag{Name: test.name, Value: 1 * time.Second} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAR", "2h3m6s") - for _, test := range durationFlagTests { - flag := DurationFlag{Name: test.name, EnvVar: "APP_BAR"} - output := flag.String() - - expectedSuffix := " [$APP_BAR]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAR%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var intSliceFlagTests = []struct { - name string - value *IntSlice - expected string -}{ - {"heads", &IntSlice{}, "--heads value\t"}, - {"H", &IntSlice{}, "-H value\t"}, - {"H, heads", func() *IntSlice { - i := &IntSlice{} - i.Set("9") - i.Set("3") - return i - }(), "-H value, --heads value\t(default: 9, 3)"}, -} - -func TestIntSliceFlagHelpOutput(t *testing.T) { - for _, test := range intSliceFlagTests { - flag := IntSliceFlag{Name: test.name, Value: test.value} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_SMURF", "42,3") - for _, test := range intSliceFlagTests { - flag := IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"} - output := flag.String() - - expectedSuffix := " [$APP_SMURF]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_SMURF%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%q does not end with"+expectedSuffix, output) - } - } -} - -var int64SliceFlagTests = []struct { - name string - value *Int64Slice - expected string -}{ - {"heads", &Int64Slice{}, "--heads value\t"}, - {"H", &Int64Slice{}, "-H value\t"}, - {"H, heads", func() *Int64Slice { - i := &Int64Slice{} - i.Set("2") - i.Set("17179869184") - return i - }(), "-H value, --heads value\t(default: 2, 17179869184)"}, -} - -func TestInt64SliceFlagHelpOutput(t *testing.T) { - for _, test := range int64SliceFlagTests { - flag := Int64SliceFlag{Name: test.name, Value: test.value} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestInt64SliceFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_SMURF", "42,17179869184") - for _, test := range int64SliceFlagTests { - flag := Int64SliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"} - output := flag.String() - - expectedSuffix := " [$APP_SMURF]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_SMURF%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%q does not end with"+expectedSuffix, output) - } - } -} - -var float64FlagTests = []struct { - name string - expected string -}{ - {"hooting", "--hooting value\t(default: 0.1)"}, - {"H", "-H value\t(default: 0.1)"}, -} - -func TestFloat64FlagHelpOutput(t *testing.T) { - for _, test := range float64FlagTests { - flag := Float64Flag{Name: test.name, Value: float64(0.1)} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_BAZ", "99.4") - for _, test := range float64FlagTests { - flag := Float64Flag{Name: test.name, EnvVar: "APP_BAZ"} - output := flag.String() - - expectedSuffix := " [$APP_BAZ]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_BAZ%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -var genericFlagTests = []struct { - name string - value Generic - expected string -}{ - {"toads", &Parser{"abc", "def"}, "--toads value\ttest flag (default: abc,def)"}, - {"t", &Parser{"abc", "def"}, "-t value\ttest flag (default: abc,def)"}, -} - -func TestGenericFlagHelpOutput(t *testing.T) { - for _, test := range genericFlagTests { - flag := GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"} - output := flag.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) { - os.Clearenv() - os.Setenv("APP_ZAP", "3") - for _, test := range genericFlagTests { - flag := GenericFlag{Name: test.name, EnvVar: "APP_ZAP"} - output := flag.String() - - expectedSuffix := " [$APP_ZAP]" - if runtime.GOOS == "windows" { - expectedSuffix = " [%APP_ZAP%]" - } - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -func TestParseMultiString(t *testing.T) { - (&App{ - Flags: []Flag{ - StringFlag{Name: "serve, s"}, - }, - Action: func(ctx *Context) error { - if ctx.String("serve") != "10" { - t.Errorf("main name not set") - } - if ctx.String("s") != "10" { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run", "-s", "10"}) -} - -func TestParseDestinationString(t *testing.T) { - var dest string - a := App{ - Flags: []Flag{ - StringFlag{ - Name: "dest", - Destination: &dest, - }, - }, - Action: func(ctx *Context) error { - if dest != "10" { - t.Errorf("expected destination String 10") - } - return nil - }, - } - a.Run([]string{"run", "--dest", "10"}) -} - -func TestParseMultiStringFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_COUNT", "20") - (&App{ - Flags: []Flag{ - StringFlag{Name: "count, c", EnvVar: "APP_COUNT"}, - }, - Action: func(ctx *Context) error { - if ctx.String("count") != "20" { - t.Errorf("main name not set") - } - if ctx.String("c") != "20" { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiStringFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_COUNT", "20") - (&App{ - Flags: []Flag{ - StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"}, - }, - Action: func(ctx *Context) error { - if ctx.String("count") != "20" { - t.Errorf("main name not set") - } - if ctx.String("c") != "20" { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiStringSlice(t *testing.T) { - (&App{ - Flags: []Flag{ - StringSliceFlag{Name: "serve, s", Value: &StringSlice{}}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run", "-s", "10", "-s", "20"}) -} - -func TestParseMultiStringSliceFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,40") - - (&App{ - Flags: []Flag{ - StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiStringSliceFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,40") - - (&App{ - Flags: []Flag{ - StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiInt(t *testing.T) { - a := App{ - Flags: []Flag{ - IntFlag{Name: "serve, s"}, - }, - Action: func(ctx *Context) error { - if ctx.Int("serve") != 10 { - t.Errorf("main name not set") - } - if ctx.Int("s") != 10 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run", "-s", "10"}) -} - -func TestParseDestinationInt(t *testing.T) { - var dest int - a := App{ - Flags: []Flag{ - IntFlag{ - Name: "dest", - Destination: &dest, - }, - }, - Action: func(ctx *Context) error { - if dest != 10 { - t.Errorf("expected destination Int 10") - } - return nil - }, - } - a.Run([]string{"run", "--dest", "10"}) -} - -func TestParseMultiIntFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "10") - a := App{ - Flags: []Flag{ - IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, - }, - Action: func(ctx *Context) error { - if ctx.Int("timeout") != 10 { - t.Errorf("main name not set") - } - if ctx.Int("t") != 10 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiIntFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "10") - a := App{ - Flags: []Flag{ - IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, - }, - Action: func(ctx *Context) error { - if ctx.Int("timeout") != 10 { - t.Errorf("main name not set") - } - if ctx.Int("t") != 10 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiIntSlice(t *testing.T) { - (&App{ - Flags: []Flag{ - IntSliceFlag{Name: "serve, s", Value: &IntSlice{}}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run", "-s", "10", "-s", "20"}) -} - -func TestParseMultiIntSliceFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,40") - - (&App{ - Flags: []Flag{ - IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,40") - - (&App{ - Flags: []Flag{ - IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiInt64Slice(t *testing.T) { - (&App{ - Flags: []Flag{ - Int64SliceFlag{Name: "serve, s", Value: &Int64Slice{}}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("serve"), []int64{10, 17179869184}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.Int64Slice("s"), []int64{10, 17179869184}) { - t.Errorf("short name not set") - } - return nil - }, - }).Run([]string{"run", "-s", "10", "-s", "17179869184"}) -} - -func TestParseMultiInt64SliceFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,17179869184") - - (&App{ - Flags: []Flag{ - Int64SliceFlag{Name: "intervals, i", Value: &Int64Slice{}, EnvVar: "APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiInt64SliceFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_INTERVALS", "20,30,17179869184") - - (&App{ - Flags: []Flag{ - Int64SliceFlag{Name: "intervals, i", Value: &Int64Slice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run([]string{"run"}) -} - -func TestParseMultiFloat64(t *testing.T) { - a := App{ - Flags: []Flag{ - Float64Flag{Name: "serve, s"}, - }, - Action: func(ctx *Context) error { - if ctx.Float64("serve") != 10.2 { - t.Errorf("main name not set") - } - if ctx.Float64("s") != 10.2 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run", "-s", "10.2"}) -} - -func TestParseDestinationFloat64(t *testing.T) { - var dest float64 - a := App{ - Flags: []Flag{ - Float64Flag{ - Name: "dest", - Destination: &dest, - }, - }, - Action: func(ctx *Context) error { - if dest != 10.2 { - t.Errorf("expected destination Float64 10.2") - } - return nil - }, - } - a.Run([]string{"run", "--dest", "10.2"}) -} - -func TestParseMultiFloat64FromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "15.5") - a := App{ - Flags: []Flag{ - Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, - }, - Action: func(ctx *Context) error { - if ctx.Float64("timeout") != 15.5 { - t.Errorf("main name not set") - } - if ctx.Float64("t") != 15.5 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiFloat64FromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_TIMEOUT_SECONDS", "15.5") - a := App{ - Flags: []Flag{ - Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, - }, - Action: func(ctx *Context) error { - if ctx.Float64("timeout") != 15.5 { - t.Errorf("main name not set") - } - if ctx.Float64("t") != 15.5 { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiBool(t *testing.T) { - a := App{ - Flags: []Flag{ - BoolFlag{Name: "serve, s"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("serve") != true { - t.Errorf("main name not set") - } - if ctx.Bool("s") != true { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run", "--serve"}) -} - -func TestParseDestinationBool(t *testing.T) { - var dest bool - a := App{ - Flags: []Flag{ - BoolFlag{ - Name: "dest", - Destination: &dest, - }, - }, - Action: func(ctx *Context) error { - if dest != true { - t.Errorf("expected destination Bool true") - } - return nil - }, - } - a.Run([]string{"run", "--dest"}) -} - -func TestParseMultiBoolFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_DEBUG", "1") - a := App{ - Flags: []Flag{ - BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("debug") != true { - t.Errorf("main name not set from env") - } - if ctx.Bool("d") != true { - t.Errorf("short name not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiBoolFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_DEBUG", "1") - a := App{ - Flags: []Flag{ - BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("debug") != true { - t.Errorf("main name not set from env") - } - if ctx.Bool("d") != true { - t.Errorf("short name not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseBoolTFromEnv(t *testing.T) { - var boolTFlagTests = []struct { - input string - output bool - }{ - {"", false}, - {"1", true}, - {"false", false}, - {"true", true}, - } - - for _, test := range boolTFlagTests { - os.Clearenv() - os.Setenv("DEBUG", test.input) - a := App{ - Flags: []Flag{ - BoolTFlag{Name: "debug, d", EnvVar: "DEBUG"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("debug") != test.output { - t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.Bool("debug")) - } - if ctx.Bool("d") != test.output { - t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.Bool("d")) - } - return nil - }, - } - a.Run([]string{"run"}) - } -} - -func TestParseMultiBoolT(t *testing.T) { - a := App{ - Flags: []Flag{ - BoolTFlag{Name: "serve, s"}, - }, - Action: func(ctx *Context) error { - if ctx.BoolT("serve") != true { - t.Errorf("main name not set") - } - if ctx.BoolT("s") != true { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run", "--serve"}) -} - -func TestParseDestinationBoolT(t *testing.T) { - var dest bool - a := App{ - Flags: []Flag{ - BoolTFlag{ - Name: "dest", - Destination: &dest, - }, - }, - Action: func(ctx *Context) error { - if dest != true { - t.Errorf("expected destination BoolT true") - } - return nil - }, - } - a.Run([]string{"run", "--dest"}) -} - -func TestParseMultiBoolTFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_DEBUG", "0") - a := App{ - Flags: []Flag{ - BoolTFlag{Name: "debug, d", EnvVar: "APP_DEBUG"}, - }, - Action: func(ctx *Context) error { - if ctx.BoolT("debug") != false { - t.Errorf("main name not set from env") - } - if ctx.BoolT("d") != false { - t.Errorf("short name not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseMultiBoolTFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_DEBUG", "0") - a := App{ - Flags: []Flag{ - BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, - }, - Action: func(ctx *Context) error { - if ctx.BoolT("debug") != false { - t.Errorf("main name not set from env") - } - if ctx.BoolT("d") != false { - t.Errorf("short name not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -type Parser [2]string - -func (p *Parser) Set(value string) error { - parts := strings.Split(value, ",") - if len(parts) != 2 { - return fmt.Errorf("invalid format") - } - - (*p)[0] = parts[0] - (*p)[1] = parts[1] - - return nil -} - -func (p *Parser) String() string { - return fmt.Sprintf("%s,%s", p[0], p[1]) -} - -func (p *Parser) Get() interface{} { - return p -} - -func TestParseGeneric(t *testing.T) { - a := App{ - Flags: []Flag{ - GenericFlag{Name: "serve, s", Value: &Parser{}}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) { - t.Errorf("short name not set") - } - return nil - }, - } - a.Run([]string{"run", "-s", "10,20"}) -} - -func TestParseGenericFromEnv(t *testing.T) { - os.Clearenv() - os.Setenv("APP_SERVE", "20,30") - a := App{ - Flags: []Flag{ - GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"20", "30"}) { - t.Errorf("short name not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} - -func TestParseGenericFromEnvCascade(t *testing.T) { - os.Clearenv() - os.Setenv("APP_FOO", "99,2000") - a := App{ - Flags: []Flag{ - GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) { - t.Errorf("value not set from env") - } - return nil - }, - } - a.Run([]string{"run"}) -} diff --git a/vendor/github.com/urfave/cli/funcs.go b/vendor/github.com/urfave/cli/funcs.go deleted file mode 100644 index cba5e6c..0000000 --- a/vendor/github.com/urfave/cli/funcs.go +++ /dev/null @@ -1,28 +0,0 @@ -package cli - -// BashCompleteFunc is an action to execute when the bash-completion flag is set -type BashCompleteFunc func(*Context) - -// BeforeFunc is 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 -type BeforeFunc func(*Context) error - -// AfterFunc is an action to execute after any subcommands are run, but after the -// subcommand has finished it is run even if Action() panics -type AfterFunc func(*Context) error - -// ActionFunc is the action to execute when no subcommands are specified -type ActionFunc func(*Context) error - -// CommandNotFoundFunc is executed if the proper command cannot be found -type CommandNotFoundFunc func(*Context, string) - -// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying -// customized usage error messages. This function is able to replace the -// original error messages. If this function is not set, the "Incorrect usage" -// is displayed and the execution is interrupted. -type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error - -// FlagStringFunc is used by the help generation to display a flag, which is -// expected to be a single line. -type FlagStringFunc func(Flag) string diff --git a/vendor/github.com/urfave/cli/generate-flag-types b/vendor/github.com/urfave/cli/generate-flag-types deleted file mode 100755 index 7147381..0000000 --- a/vendor/github.com/urfave/cli/generate-flag-types +++ /dev/null @@ -1,255 +0,0 @@ -#!/usr/bin/env python -""" -The flag types that ship with the cli library have many things in common, and -so we can take advantage of the `go generate` command to create much of the -source code from a list of definitions. These definitions attempt to cover -the parts that vary between flag types, and should evolve as needed. - -An example of the minimum definition needed is: - - { - "name": "SomeType", - "type": "sometype", - "context_default": "nil" - } - -In this example, the code generated for the `cli` package will include a type -named `SomeTypeFlag` that is expected to wrap a value of type `sometype`. -Fetching values by name via `*cli.Context` will default to a value of `nil`. - -A more complete, albeit somewhat redundant, example showing all available -definition keys is: - - { - "name": "VeryMuchType", - "type": "*VeryMuchType", - "value": true, - "dest": false, - "doctail": " which really only wraps a []float64, oh well!", - "context_type": "[]float64", - "context_default": "nil", - "parser": "parseVeryMuchType(f.Value.String())", - "parser_cast": "[]float64(parsed)" - } - -The meaning of each field is as follows: - - name (string) - The type "name", which will be suffixed with - `Flag` when generating the type definition - for `cli` and the wrapper type for `altsrc` - type (string) - The type that the generated `Flag` type for `cli` - is expected to "contain" as its `.Value` member - value (bool) - Should the generated `cli` type have a `Value` - member? - dest (bool) - Should the generated `cli` type support a - destination pointer? - doctail (string) - Additional docs for the `cli` flag type comment - context_type (string) - The literal type used in the `*cli.Context` - reader func signature - context_default (string) - The literal value used as the default by the - `*cli.Context` reader funcs when no value is - present - parser (string) - Literal code used to parse the flag `f`, - expected to have a return signature of - (value, error) - parser_cast (string) - Literal code used to cast the `parsed` value - returned from the `parser` code -""" - -from __future__ import print_function, unicode_literals - -import argparse -import json -import os -import subprocess -import sys -import tempfile -import textwrap - - -class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter, - argparse.RawDescriptionHelpFormatter): - pass - - -def main(sysargs=sys.argv[:]): - parser = argparse.ArgumentParser( - description='Generate flag type code!', - formatter_class=_FancyFormatter) - parser.add_argument( - 'package', - type=str, default='cli', choices=_WRITEFUNCS.keys(), - help='Package for which flag types will be generated' - ) - parser.add_argument( - '-i', '--in-json', - type=argparse.FileType('r'), - default=sys.stdin, - help='Input JSON file which defines each type to be generated' - ) - parser.add_argument( - '-o', '--out-go', - type=argparse.FileType('w'), - default=sys.stdout, - help='Output file/stream to which generated source will be written' - ) - parser.epilog = __doc__ - - args = parser.parse_args(sysargs[1:]) - _generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json) - return 0 - - -def _generate_flag_types(writefunc, output_go, input_json): - types = json.load(input_json) - - tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False) - writefunc(tmp, types) - tmp.close() - - new_content = subprocess.check_output( - ['goimports', tmp.name] - ).decode('utf-8') - - print(new_content, file=output_go, end='') - output_go.flush() - os.remove(tmp.name) - - -def _set_typedef_defaults(typedef): - typedef.setdefault('doctail', '') - typedef.setdefault('context_type', typedef['type']) - typedef.setdefault('dest', True) - typedef.setdefault('value', True) - typedef.setdefault('parser', 'f.Value, error(nil)') - typedef.setdefault('parser_cast', 'parsed') - - -def _write_cli_flag_types(outfile, types): - _fwrite(outfile, """\ - package cli - - // WARNING: This file is generated! - - """) - - for typedef in types: - _set_typedef_defaults(typedef) - - _fwrite(outfile, """\ - // {name}Flag is a flag with type {type}{doctail} - type {name}Flag struct {{ - Name string - Usage string - EnvVar string - Hidden bool - """.format(**typedef)) - - if typedef['value']: - _fwrite(outfile, """\ - Value {type} - """.format(**typedef)) - - if typedef['dest']: - _fwrite(outfile, """\ - Destination *{type} - """.format(**typedef)) - - _fwrite(outfile, "\n}\n\n") - - _fwrite(outfile, """\ - // String returns a readable representation of this value - // (for usage defaults) - func (f {name}Flag) String() string {{ - return FlagStringer(f) - }} - - // GetName returns the name of the flag - func (f {name}Flag) GetName() string {{ - return f.Name - }} - - // {name} looks up the value of a local {name}Flag, returns - // {context_default} if not found - func (c *Context) {name}(name string) {context_type} {{ - return lookup{name}(name, c.flagSet) - }} - - // Global{name} looks up the value of a global {name}Flag, returns - // {context_default} if not found - func (c *Context) Global{name}(name string) {context_type} {{ - if fs := lookupGlobalFlagSet(name, c); fs != nil {{ - return lookup{name}(name, fs) - }} - return {context_default} - }} - - func lookup{name}(name string, set *flag.FlagSet) {context_type} {{ - f := set.Lookup(name) - if f != nil {{ - parsed, err := {parser} - if err != nil {{ - return {context_default} - }} - return {parser_cast} - }} - return {context_default} - }} - """.format(**typedef)) - - -def _write_altsrc_flag_types(outfile, types): - _fwrite(outfile, """\ - package altsrc - - import ( - "gopkg.in/urfave/cli.v1" - ) - - // WARNING: This file is generated! - - """) - - for typedef in types: - _set_typedef_defaults(typedef) - - _fwrite(outfile, """\ - // {name}Flag is the flag type that wraps cli.{name}Flag to allow - // for other values to be specified - type {name}Flag struct {{ - cli.{name}Flag - set *flag.FlagSet - }} - - // New{name}Flag creates a new {name}Flag - func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{ - return &{name}Flag{{{name}Flag: fl, set: nil}} - }} - - // Apply saves the flagSet for later usage calls, then calls the - // wrapped {name}Flag.Apply - func (f *{name}Flag) Apply(set *flag.FlagSet) {{ - f.set = set - f.{name}Flag.Apply(set) - }} - - // ApplyWithError saves the flagSet for later usage calls, then calls the - // wrapped {name}Flag.ApplyWithError - func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{ - f.set = set - return f.{name}Flag.ApplyWithError(set) - }} - """.format(**typedef)) - - -def _fwrite(outfile, text): - print(textwrap.dedent(text), end='', file=outfile) - - -_WRITEFUNCS = { - 'cli': _write_cli_flag_types, - 'altsrc': _write_altsrc_flag_types -} - -if __name__ == '__main__': - sys.exit(main()) diff --git a/vendor/github.com/urfave/cli/help.go b/vendor/github.com/urfave/cli/help.go deleted file mode 100644 index 57ec98d..0000000 --- a/vendor/github.com/urfave/cli/help.go +++ /dev/null @@ -1,338 +0,0 @@ -package cli - -import ( - "fmt" - "io" - "os" - "strings" - "text/tabwriter" - "text/template" -) - -// AppHelpTemplate is the text template for the Default help topic. -// cli.go uses text/template to render templates. You can -// render custom help text by setting this variable. -var AppHelpTemplate = `NAME: - {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} - -USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} - -VERSION: - {{.Version}}{{end}}{{end}}{{if .Description}} - -DESCRIPTION: - {{.Description}}{{end}}{{if len .Authors}} - -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} - -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} - -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} - -COPYRIGHT: - {{.Copyright}}{{end}} -` - -// CommandHelpTemplate is the text template for the command help topic. -// cli.go uses text/template to render templates. You can -// render custom help text by setting this variable. -var CommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} - -USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} - -CATEGORY: - {{.Category}}{{end}}{{if .Description}} - -DESCRIPTION: - {{.Description}}{{end}}{{if .VisibleFlags}} - -OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}} -` - -// SubcommandHelpTemplate is the text template for the subcommand help topic. -// cli.go uses text/template to render templates. You can -// render custom help text by setting this variable. -var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}} - -USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} - -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}} -{{end}}{{if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}} -` - -var helpCommand = Command{ - Name: "help", - Aliases: []string{"h"}, - Usage: "Shows a list of commands or help for one command", - ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() - if args.Present() { - return ShowCommandHelp(c, args.First()) - } - - ShowAppHelp(c) - return nil - }, -} - -var helpSubcommand = Command{ - Name: "help", - Aliases: []string{"h"}, - Usage: "Shows a list of commands or help for one command", - ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() - if args.Present() { - return ShowCommandHelp(c, args.First()) - } - - return ShowSubcommandHelp(c) - }, -} - -// Prints help for the App or Command -type helpPrinter func(w io.Writer, templ string, data interface{}) - -// Prints help for the App or Command with custom template function. -type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{}) - -// HelpPrinter is a function that writes the help output. If not set a default -// is used. The function signature is: -// func(w io.Writer, templ string, data interface{}) -var HelpPrinter helpPrinter = printHelp - -// HelpPrinterCustom is same as HelpPrinter but -// takes a custom function for template function map. -var HelpPrinterCustom helpPrinterCustom = printHelpCustom - -// VersionPrinter prints the version for the App -var VersionPrinter = printVersion - -// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code. -func ShowAppHelpAndExit(c *Context, exitCode int) { - ShowAppHelp(c) - os.Exit(exitCode) -} - -// ShowAppHelp is an action that displays the help. -func ShowAppHelp(c *Context) (err error) { - if c.App.CustomAppHelpTemplate == "" { - HelpPrinter(c.App.Writer, AppHelpTemplate, c.App) - return - } - customAppData := func() map[string]interface{} { - if c.App.ExtraInfo == nil { - return nil - } - return map[string]interface{}{ - "ExtraInfo": c.App.ExtraInfo, - } - } - HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData()) - return nil -} - -// DefaultAppComplete prints the list of subcommands as the default app completion method -func DefaultAppComplete(c *Context) { - for _, command := range c.App.Commands { - if command.Hidden { - continue - } - for _, name := range command.Names() { - fmt.Fprintln(c.App.Writer, name) - } - } -} - -// ShowCommandHelpAndExit - exits with code after showing help -func ShowCommandHelpAndExit(c *Context, command string, code int) { - ShowCommandHelp(c, command) - os.Exit(code) -} - -// ShowCommandHelp prints help for the given command -func ShowCommandHelp(ctx *Context, command string) error { - // show the subcommand help for a command with subcommands - if command == "" { - HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) - return nil - } - - for _, c := range ctx.App.Commands { - if c.HasName(command) { - if c.CustomHelpTemplate != "" { - HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil) - } else { - HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c) - } - return nil - } - } - - if ctx.App.CommandNotFound == nil { - return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3) - } - - ctx.App.CommandNotFound(ctx, command) - return nil -} - -// ShowSubcommandHelp prints help for the given subcommand -func ShowSubcommandHelp(c *Context) error { - return ShowCommandHelp(c, c.Command.Name) -} - -// ShowVersion prints the version number of the App -func ShowVersion(c *Context) { - VersionPrinter(c) -} - -func printVersion(c *Context) { - fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) -} - -// ShowCompletions prints the lists of commands within a given context -func ShowCompletions(c *Context) { - a := c.App - if a != nil && a.BashComplete != nil { - a.BashComplete(c) - } -} - -// ShowCommandCompletions prints the custom completions for a given command -func ShowCommandCompletions(ctx *Context, command string) { - c := ctx.App.Command(command) - if c != nil && c.BashComplete != nil { - c.BashComplete(ctx) - } -} - -func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) { - funcMap := template.FuncMap{ - "join": strings.Join, - } - if customFunc != nil { - for key, value := range customFunc { - funcMap[key] = value - } - } - - w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) - t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) - err := t.Execute(w, data) - if err != nil { - // If the writer is closed, t.Execute will fail, and there's nothing - // we can do to recover. - if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" { - fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) - } - return - } - w.Flush() -} - -func printHelp(out io.Writer, templ string, data interface{}) { - printHelpCustom(out, templ, data, nil) -} - -func checkVersion(c *Context) bool { - found := false - if VersionFlag.GetName() != "" { - eachName(VersionFlag.GetName(), func(name string) { - if c.GlobalBool(name) || c.Bool(name) { - found = true - } - }) - } - return found -} - -func checkHelp(c *Context) bool { - found := false - if HelpFlag.GetName() != "" { - eachName(HelpFlag.GetName(), func(name string) { - if c.GlobalBool(name) || c.Bool(name) { - found = true - } - }) - } - return found -} - -func checkCommandHelp(c *Context, name string) bool { - if c.Bool("h") || c.Bool("help") { - ShowCommandHelp(c, name) - return true - } - - return false -} - -func checkSubcommandHelp(c *Context) bool { - if c.Bool("h") || c.Bool("help") { - ShowSubcommandHelp(c) - return true - } - - return false -} - -func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { - if !a.EnableBashCompletion { - return false, arguments - } - - pos := len(arguments) - 1 - lastArg := arguments[pos] - - if lastArg != "--"+BashCompletionFlag.GetName() { - return false, arguments - } - - return true, arguments[:pos] -} - -func checkCompletions(c *Context) bool { - if !c.shellComplete { - return false - } - - if args := c.Args(); args.Present() { - name := args.First() - if cmd := c.App.Command(name); cmd != nil { - // let the command handle the completion - return false - } - } - - ShowCompletions(c) - return true -} - -func checkCommandCompletions(c *Context, name string) bool { - if !c.shellComplete { - return false - } - - ShowCommandCompletions(c, name) - return true -} diff --git a/vendor/github.com/urfave/cli/help_test.go b/vendor/github.com/urfave/cli/help_test.go deleted file mode 100644 index 70b6300..0000000 --- a/vendor/github.com/urfave/cli/help_test.go +++ /dev/null @@ -1,452 +0,0 @@ -package cli - -import ( - "bytes" - "flag" - "fmt" - "runtime" - "strings" - "testing" -) - -func Test_ShowAppHelp_NoAuthor(t *testing.T) { - output := new(bytes.Buffer) - app := NewApp() - app.Writer = output - - c := NewContext(app, nil, nil) - - ShowAppHelp(c) - - if bytes.Index(output.Bytes(), []byte("AUTHOR(S):")) != -1 { - t.Errorf("expected\n%snot to include %s", output.String(), "AUTHOR(S):") - } -} - -func Test_ShowAppHelp_NoVersion(t *testing.T) { - output := new(bytes.Buffer) - app := NewApp() - app.Writer = output - - app.Version = "" - - c := NewContext(app, nil, nil) - - ShowAppHelp(c) - - if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 { - t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:") - } -} - -func Test_ShowAppHelp_HideVersion(t *testing.T) { - output := new(bytes.Buffer) - app := NewApp() - app.Writer = output - - app.HideVersion = true - - c := NewContext(app, nil, nil) - - ShowAppHelp(c) - - if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 { - t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:") - } -} - -func Test_Help_Custom_Flags(t *testing.T) { - oldFlag := HelpFlag - defer func() { - HelpFlag = oldFlag - }() - - HelpFlag = BoolFlag{ - Name: "help, x", - Usage: "show help", - } - - app := App{ - Flags: []Flag{ - BoolFlag{Name: "foo, h"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("h") != true { - t.Errorf("custom help flag not set") - } - return nil - }, - } - output := new(bytes.Buffer) - app.Writer = output - app.Run([]string{"test", "-h"}) - if output.Len() > 0 { - t.Errorf("unexpected output: %s", output.String()) - } -} - -func Test_Version_Custom_Flags(t *testing.T) { - oldFlag := VersionFlag - defer func() { - VersionFlag = oldFlag - }() - - VersionFlag = BoolFlag{ - Name: "version, V", - Usage: "show version", - } - - app := App{ - Flags: []Flag{ - BoolFlag{Name: "foo, v"}, - }, - Action: func(ctx *Context) error { - if ctx.Bool("v") != true { - t.Errorf("custom version flag not set") - } - return nil - }, - } - output := new(bytes.Buffer) - app.Writer = output - app.Run([]string{"test", "-v"}) - if output.Len() > 0 { - t.Errorf("unexpected output: %s", output.String()) - } -} - -func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) { - app := NewApp() - - set := flag.NewFlagSet("test", 0) - set.Parse([]string{"foo"}) - - c := NewContext(app, set, nil) - - err := helpCommand.Action.(func(*Context) error)(c) - - if err == nil { - t.Fatalf("expected error from helpCommand.Action(), but got nil") - } - - exitErr, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error()) - } - - if !strings.HasPrefix(exitErr.Error(), "No help topic for") { - t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error()) - } - - if exitErr.exitCode != 3 { - t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode) - } -} - -func Test_helpCommand_InHelpOutput(t *testing.T) { - app := NewApp() - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"test", "--help"}) - - s := output.String() - - if strings.Contains(s, "\nCOMMANDS:\nGLOBAL OPTIONS:\n") { - t.Fatalf("empty COMMANDS section detected: %q", s) - } - - if !strings.Contains(s, "help, h") { - t.Fatalf("missing \"help, h\": %q", s) - } -} - -func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) { - app := NewApp() - - set := flag.NewFlagSet("test", 0) - set.Parse([]string{"foo"}) - - c := NewContext(app, set, nil) - - err := helpSubcommand.Action.(func(*Context) error)(c) - - if err == nil { - t.Fatalf("expected error from helpCommand.Action(), but got nil") - } - - exitErr, ok := err.(*ExitError) - if !ok { - t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error()) - } - - if !strings.HasPrefix(exitErr.Error(), "No help topic for") { - t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error()) - } - - if exitErr.exitCode != 3 { - t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode) - } -} - -func TestShowAppHelp_CommandAliases(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Aliases: []string{"fr", "frob"}, - Action: func(ctx *Context) error { - return nil - }, - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"foo", "--help"}) - - if !strings.Contains(output.String(), "frobbly, fr, frob") { - t.Errorf("expected output to include all command aliases; got: %q", output.String()) - } -} - -func TestShowCommandHelp_CommandAliases(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Aliases: []string{"fr", "frob", "bork"}, - Action: func(ctx *Context) error { - return nil - }, - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"foo", "help", "fr"}) - - if !strings.Contains(output.String(), "frobbly") { - t.Errorf("expected output to include command name; got: %q", output.String()) - } - - if strings.Contains(output.String(), "bork") { - t.Errorf("expected output to exclude command aliases; got: %q", output.String()) - } -} - -func TestShowSubcommandHelp_CommandAliases(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Aliases: []string{"fr", "frob", "bork"}, - Action: func(ctx *Context) error { - return nil - }, - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"foo", "help"}) - - if !strings.Contains(output.String(), "frobbly, fr, frob, bork") { - t.Errorf("expected output to include all command aliases; got: %q", output.String()) - } -} - -func TestShowCommandHelp_Customtemplate(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Action: func(ctx *Context) error { - return nil - }, - HelpName: "foo frobbly", - CustomHelpTemplate: `NAME: - {{.HelpName}} - {{.Usage}} - -USAGE: - {{.HelpName}} [FLAGS] TARGET [TARGET ...] - -FLAGS: - {{range .VisibleFlags}}{{.}} - {{end}} -EXAMPLES: - 1. Frobbly runs with this param locally. - $ {{.HelpName}} wobbly -`, - }, - }, - } - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"foo", "help", "frobbly"}) - - if strings.Contains(output.String(), "2. Frobbly runs without this param locally.") { - t.Errorf("expected output to exclude \"2. Frobbly runs without this param locally.\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "1. Frobbly runs with this param locally.") { - t.Errorf("expected output to include \"1. Frobbly runs with this param locally.\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "$ foo frobbly wobbly") { - t.Errorf("expected output to include \"$ foo frobbly wobbly\"; got: %q", output.String()) - } -} - -func TestShowSubcommandHelp_CommandUsageText(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - UsageText: "this is usage text", - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - - app.Run([]string{"foo", "frobbly", "--help"}) - - if !strings.Contains(output.String(), "this is usage text") { - t.Errorf("expected output to include usage text; got: %q", output.String()) - } -} - -func TestShowSubcommandHelp_SubcommandUsageText(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Subcommands: []Command{ - { - Name: "bobbly", - UsageText: "this is usage text", - }, - }, - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"foo", "frobbly", "bobbly", "--help"}) - - if !strings.Contains(output.String(), "this is usage text") { - t.Errorf("expected output to include usage text; got: %q", output.String()) - } -} - -func TestShowAppHelp_HiddenCommand(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Action: func(ctx *Context) error { - return nil - }, - }, - { - Name: "secretfrob", - Hidden: true, - Action: func(ctx *Context) error { - return nil - }, - }, - }, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"app", "--help"}) - - if strings.Contains(output.String(), "secretfrob") { - t.Errorf("expected output to exclude \"secretfrob\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "frobbly") { - t.Errorf("expected output to include \"frobbly\"; got: %q", output.String()) - } -} - -func TestShowAppHelp_CustomAppTemplate(t *testing.T) { - app := &App{ - Commands: []Command{ - { - Name: "frobbly", - Action: func(ctx *Context) error { - return nil - }, - }, - { - Name: "secretfrob", - Hidden: true, - Action: func(ctx *Context) error { - return nil - }, - }, - }, - ExtraInfo: func() map[string]string { - platform := fmt.Sprintf("OS: %s | Arch: %s", runtime.GOOS, runtime.GOARCH) - goruntime := fmt.Sprintf("Version: %s | CPUs: %d", runtime.Version(), runtime.NumCPU()) - return map[string]string{ - "PLATFORM": platform, - "RUNTIME": goruntime, - } - }, - CustomAppHelpTemplate: `NAME: - {{.Name}} - {{.Usage}} - -USAGE: - {{.Name}} {{if .VisibleFlags}}[FLAGS] {{end}}COMMAND{{if .VisibleFlags}} [COMMAND FLAGS | -h]{{end}} [ARGUMENTS...] - -COMMANDS: - {{range .VisibleCommands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} - {{end}}{{if .VisibleFlags}} -GLOBAL FLAGS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}} -VERSION: - 2.0.0 -{{"\n"}}{{range $key, $value := ExtraInfo}} -{{$key}}: - {{$value}} -{{end}}`, - } - - output := &bytes.Buffer{} - app.Writer = output - app.Run([]string{"app", "--help"}) - - if strings.Contains(output.String(), "secretfrob") { - t.Errorf("expected output to exclude \"secretfrob\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "frobbly") { - t.Errorf("expected output to include \"frobbly\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "PLATFORM:") || - !strings.Contains(output.String(), "OS:") || - !strings.Contains(output.String(), "Arch:") { - t.Errorf("expected output to include \"PLATFORM:, OS: and Arch:\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "RUNTIME:") || - !strings.Contains(output.String(), "Version:") || - !strings.Contains(output.String(), "CPUs:") { - t.Errorf("expected output to include \"RUNTIME:, Version: and CPUs:\"; got: %q", output.String()) - } - - if !strings.Contains(output.String(), "VERSION:") || - !strings.Contains(output.String(), "2.0.0") { - t.Errorf("expected output to include \"VERSION:, 2.0.0\"; got: %q", output.String()) - } -} diff --git a/vendor/github.com/urfave/cli/helpers_test.go b/vendor/github.com/urfave/cli/helpers_test.go deleted file mode 100644 index 109ea7a..0000000 --- a/vendor/github.com/urfave/cli/helpers_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package cli - -import ( - "os" - "reflect" - "runtime" - "strings" - "testing" -) - -var ( - wd, _ = os.Getwd() -) - -func expect(t *testing.T, a interface{}, b interface{}) { - _, fn, line, _ := runtime.Caller(1) - fn = strings.Replace(fn, wd+"/", "", -1) - - if !reflect.DeepEqual(a, b) { - t.Errorf("(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a)) - } -} - -func refute(t *testing.T, a interface{}, b interface{}) { - if reflect.DeepEqual(a, b) { - t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) - } -} diff --git a/vendor/github.com/urfave/cli/helpers_unix_test.go b/vendor/github.com/urfave/cli/helpers_unix_test.go deleted file mode 100644 index ae27fc5..0000000 --- a/vendor/github.com/urfave/cli/helpers_unix_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package cli - -import "os" - -func clearenv() { - os.Clearenv() -} diff --git a/vendor/github.com/urfave/cli/helpers_windows_test.go b/vendor/github.com/urfave/cli/helpers_windows_test.go deleted file mode 100644 index 4eb84f9..0000000 --- a/vendor/github.com/urfave/cli/helpers_windows_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package cli - -import ( - "os" - "syscall" -) - -// os.Clearenv() doesn't actually unset variables on Windows -// See: https://github.com/golang/go/issues/17902 -func clearenv() { - for _, s := range os.Environ() { - for j := 1; j < len(s); j++ { - if s[j] == '=' { - keyp, _ := syscall.UTF16PtrFromString(s[0:j]) - syscall.SetEnvironmentVariable(keyp, nil) - break - } - } - } -} diff --git a/vendor/github.com/urfave/cli/runtests b/vendor/github.com/urfave/cli/runtests deleted file mode 100755 index ee22bde..0000000 --- a/vendor/github.com/urfave/cli/runtests +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -import argparse -import os -import sys -import tempfile - -from subprocess import check_call, check_output - - -PACKAGE_NAME = os.environ.get( - 'CLI_PACKAGE_NAME', 'github.com/urfave/cli' -) - - -def main(sysargs=sys.argv[:]): - targets = { - 'vet': _vet, - 'test': _test, - 'gfmrun': _gfmrun, - 'toc': _toc, - 'gen': _gen, - } - - parser = argparse.ArgumentParser() - parser.add_argument( - 'target', nargs='?', choices=tuple(targets.keys()), default='test' - ) - args = parser.parse_args(sysargs[1:]) - - targets[args.target]() - return 0 - - -def _test(): - if check_output('go version'.split()).split()[2] < 'go1.2': - _run('go test -v .') - return - - coverprofiles = [] - for subpackage in ['', 'altsrc']: - coverprofile = 'cli.coverprofile' - if subpackage != '': - coverprofile = '{}.coverprofile'.format(subpackage) - - coverprofiles.append(coverprofile) - - _run('go test -v'.split() + [ - '-coverprofile={}'.format(coverprofile), - ('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/') - ]) - - combined_name = _combine_coverprofiles(coverprofiles) - _run('go tool cover -func={}'.format(combined_name)) - os.remove(combined_name) - - -def _gfmrun(): - go_version = check_output('go version'.split()).split()[2] - if go_version < 'go1.3': - print('runtests: skip on {}'.format(go_version), file=sys.stderr) - return - _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md']) - - -def _vet(): - _run('go vet ./...') - - -def _toc(): - _run('node_modules/.bin/markdown-toc -i README.md') - _run('git diff --exit-code') - - -def _gen(): - go_version = check_output('go version'.split()).split()[2] - if go_version < 'go1.5': - print('runtests: skip on {}'.format(go_version), file=sys.stderr) - return - - _run('go generate ./...') - _run('git diff --exit-code') - - -def _run(command): - if hasattr(command, 'split'): - command = command.split() - print('runtests: {}'.format(' '.join(command)), file=sys.stderr) - check_call(command) - - -def _gfmrun_count(): - with open('README.md') as infile: - lines = infile.read().splitlines() - return len(filter(_is_go_runnable, lines)) - - -def _is_go_runnable(line): - return line.startswith('package main') - - -def _combine_coverprofiles(coverprofiles): - combined = tempfile.NamedTemporaryFile( - suffix='.coverprofile', delete=False - ) - combined.write('mode: set\n') - - for coverprofile in coverprofiles: - with open(coverprofile, 'r') as infile: - for line in infile.readlines(): - if not line.startswith('mode: '): - combined.write(line) - - combined.flush() - name = combined.name - combined.close() - return name - - -if __name__ == '__main__': - sys.exit(main())