Compare commits

...

64 Commits

Author SHA1 Message Date
Cory Bennett 4dea068113 version bump 2017-09-18 00:44:55 -07:00
Cory Bennett 28e4554fe3 Updated Changelog 2017-09-18 00:44:55 -07:00
Cory Bennett 065f9c8d77 Updated Usage 2017-09-18 00:44:55 -07:00
Cory Bennett 9f433acaa0 clean up usage formatting, print aliases 2017-09-18 00:44:08 -07:00
Cory Bennett e4c10be811 add jira edit tests 2017-09-17 20:33:40 -07:00
Cory Bennett 4c6b36c83a fix edit 2017-09-17 20:32:50 -07:00
Cory Bennett a8eaa97de1 fix named query template expansion 2017-09-17 20:31:14 -07:00
Cory Bennett cd3cfd820f fix usage message 2017-09-17 20:30:44 -07:00
Cory Bennett a04c3a4c61 add test using named query 2017-09-17 18:11:57 -07:00
Cory Bennett bb66e58dfd use svg rather than png for godoc badge 2017-09-17 16:36:22 -07:00
Cory Bennett e21f18e987 Updated Changelog 2017-09-17 16:30:41 -07:00
Cory Bennett 96bbbd7ce3 fix table tests for issuetype addition 2017-09-17 16:15:28 -07:00
Cory Bennett 3e8b9bd9f5 need issuetype to use the default list table template now 2017-09-17 16:15:00 -07:00
Cory Bennett 8fe0d98d54 version bump 2017-09-17 15:53:46 -07:00
Cory Bennett 1a3eaf340c Updated Changelog 2017-09-17 15:53:46 -07:00
Cory Bennett 96b4658dcb fix logic for detecting changes in README.md 2017-09-17 15:53:30 -07:00
Cory Bennett c9d8dfbe55 [#102] add issuetype into the default queryfields and add it to the default table list template 2017-09-17 15:49:05 -07:00
Cory Bennett 238e16fc09 version bump 2017-09-17 15:38:25 -07:00
Cory Bennett 22a354ce42 Updated Changelog 2017-09-17 15:38:24 -07:00
Cory Bennett d9736919bb Updated Usage 2017-09-17 15:38:24 -07:00
Cory Bennett 3c16e1754a fix whitespace, --help-long always returns non-zero exit 2017-09-17 15:38:16 -07:00
Cory Bennett 650bc4b50d fix whitespace 2017-09-17 15:33:10 -07:00
Cory Bennett b1c9bf5ae5 automatically update usage in README.md 2017-09-17 15:32:24 -07:00
Cory Bennett 66eb7bff38 [#100] add support for posting, fetching, listing and removing attachments 2017-09-17 15:18:06 -07:00
Cory Bennett abc82b909e version bump 2017-09-15 00:33:12 -07:00
Cory Bennett dabf4cf034 Updated Changelog 2017-09-15 00:33:12 -07:00
Cory Bennett 79a6381307 update usage 2017-09-15 00:31:43 -07:00
Cory Bennett 893454fc69 [#87] add various commands for interacting with epics 2017-09-15 00:28:56 -07:00
Cory Bennett d5b9631cf4 make test less error prone 2017-09-13 13:38:55 -07:00
Cory Bennett e841270b83 version bump 2017-09-13 12:31:16 -07:00
Cory Bennett 2ededeeaf7 Updated Changelog 2017-09-13 12:31:16 -07:00
Cory Bennett 00cba793ad tweaks for templates in named queries to work better 2017-09-13 12:17:59 -07:00
Cory Bennett fb43753c31 [#99] add support for named queries to be stored in configs 2017-09-13 11:12:58 -07:00
Cory Bennett 5085a14494 add license badge 2017-09-13 00:15:09 -07:00
Cory Bennett 5da04c1f86 [#98] add --status option for JQL filter on status with list command 2017-09-13 00:12:20 -07:00
Cory Bennett 052e038d73 version bump 2017-09-11 00:16:10 -07:00
Cory Bennett a7f1323f34 Updated Changelog 2017-09-11 00:16:10 -07:00
Cory Bennett 8d27b736ca track *.lock 2017-09-11 00:16:01 -07:00
Cory Bennett c3c008e53d running dep prune 2017-09-11 00:11:56 -07:00
Cory Bennett 608e586d1c use --gjq for GJson Query to filter json response data, remove --jq option 2017-09-10 22:48:40 -07:00
Cory Bennett 2c552ac530 fix field tag syntax 2017-09-09 19:13:58 -07:00
Cory Bennett 1d269183c3 add --jq option to run a json query against Jira service response json 2017-09-09 19:02:23 -07:00
Cory Bennett e0e1e5b941 use {{jira}} in custom-command docs 2017-09-09 17:44:56 -07:00
Cory Bennett 941824d7f8 add '{{jira}}' template macro to refer to path of currently running jira command 2017-09-09 17:40:26 -07:00
Cory Bennett c585244f3e add basic tests for custom-commands 2017-09-09 17:20:57 -07:00
Cory Bennett 29b95a52cb version bump 2017-09-08 18:54:34 -07:00
Cory Bennett f556375242 Updated Changelog 2017-09-08 18:54:34 -07:00
Cory Bennett 86b963bdb5 update deps for kingpeon update
use os.exec instead of syscall.exec for windows
2017-09-08 18:53:21 -07:00
Cory Bennett 036ebb4bf7 make custom-commands example copy/pasteable 2017-09-07 08:39:37 -07:00
Cory Bennett 7d481fe965 version bump 2017-09-06 23:23:47 -07:00
Cory Bennett 4709bbbe38 Updated Changelog 2017-09-06 23:23:47 -07:00
Cory Bennett 1c79a80389 add COLUMNS back in for jira ls --template table testing 2017-09-06 23:07:48 -07:00
Cory Bennett 6a879959be fix perms for test .gnupg directory 2017-09-06 22:34:15 -07:00
Cory Bennett d46f9495e7 assume tests always run in jira cloud 2017-09-06 22:30:59 -07:00
Cory Bennett e6faee1573 [#66] add --started option to jira worklog add to change the start time for worklog 2017-09-06 22:30:15 -07:00
Cory Bennett c4be59cae3 [#45] automatically add comment to issue even if transition does not support comment updates during transtion 2017-09-06 21:28:57 -07:00
Cory Bennett 9cc91f7108 use xgo tool rather than docker image directly 2017-09-06 12:29:06 -07:00
Cory Bennett da8ee59ebb version bump 2017-09-06 12:07:51 -07:00
Cory Bennett 4386b9c541 Updated Changelog 2017-09-06 12:06:37 -07:00
Cory Bennett aa876cd588 update dependencies 2017-09-06 11:35:00 -07:00
Cory Bennett 9453179251 update for github.com/AlecAivazis/survey => gopkg.in/AlecAivazis/survey.v1 package 2017-09-06 08:40:34 -07:00
Cory Bennett 4d79af4f5e use stdout to determin output terminal size 2017-09-06 00:33:53 -07:00
Cory Bennett 2cb6bbb10d Updated Changelog 2017-09-06 00:06:31 -07:00
Cory Bennett 1106558703 [#13] change default input syntax to not require escaping for special characters 2017-09-06 00:04:54 -07:00
775 changed files with 52566 additions and 102499 deletions
+6
View File
@@ -2,3 +2,9 @@ jira
schemas/*.json
t/.gnupg/random_seed
t/issue.props
t/attach.props
t/garbage.bin
t/attach1.txt
t/binary.out
t/foobar.bin
dist
+11
View File
@@ -0,0 +1,11 @@
config:
stop: true
password-source: pass
endpoint: https://go-jira.atlassian.net
user: admin
queries:
todo: |
resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do'
open: |
resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'Open'
+51
View File
@@ -1,5 +1,56 @@
# Changelog
## 1.0.10 - 2017-09-18
* clean up usage formatting, print aliases [Cory Bennett] [[9f433ac](https://github.com/Netflix-Skunkworks/go-jira/commit/9f433ac)]
* fix edit [Cory Bennett] [[4c6b36c](https://github.com/Netflix-Skunkworks/go-jira/commit/4c6b36c)]
* fix named query template expansion [Cory Bennett] [[a8eaa97](https://github.com/Netflix-Skunkworks/go-jira/commit/a8eaa97)]
* fix usage message [Cory Bennett] [[cd3cfd8](https://github.com/Netflix-Skunkworks/go-jira/commit/cd3cfd8)]
## 1.0.9 - 2017-09-17
* need issuetype to use the default list table template now [Cory Bennett] [[3e8b9bd](https://github.com/Netflix-Skunkworks/go-jira/commit/3e8b9bd)]
* [[#102](https://github.com/Netflix-Skunkworks/go-jira/issues/102)] add issuetype into the default queryfields and add it to the default `table` list template [Cory Bennett] [[c9d8dfb](https://github.com/Netflix-Skunkworks/go-jira/commit/c9d8dfb)]
## 1.0.8 - 2017-09-17
* [[#100](https://github.com/Netflix-Skunkworks/go-jira/issues/100)] add support for posting, fetching, listing and removing attachments [Cory Bennett] [[66eb7bf](https://github.com/Netflix-Skunkworks/go-jira/commit/66eb7bf)]
## 1.0.7 - 2017-09-15
* [[#87](https://github.com/Netflix-Skunkworks/go-jira/issues/87)] add various commands for interacting with epics [Cory Bennett] [[893454f](https://github.com/Netflix-Skunkworks/go-jira/commit/893454f)]
## 1.0.6 - 2017-09-13
* tweaks for templates in named queries to work better [Cory Bennett] [[00cba79](https://github.com/Netflix-Skunkworks/go-jira/commit/00cba79)]
* [[#99](https://github.com/Netflix-Skunkworks/go-jira/issues/99)] add support for named queries to be stored in configs [Cory Bennett] [[fb43753](https://github.com/Netflix-Skunkworks/go-jira/commit/fb43753)]
* [[#98](https://github.com/Netflix-Skunkworks/go-jira/issues/98)] add `--status` option for JQL filter on status with `list` command [Cory Bennett] [[5da04c1](https://github.com/Netflix-Skunkworks/go-jira/commit/5da04c1)]
## 1.0.5 - 2017-09-11
* use --gjq for GJson Query to filter json response data [Cory Bennett] [[608e586](https://github.com/Netflix-Skunkworks/go-jira/commit/608e586)]
* fix field tag syntax [Cory Bennett] [[2c552ac](https://github.com/Netflix-Skunkworks/go-jira/commit/2c552ac)]
* add '{{jira}}' template macro to refer to path of currently running jira command [Cory Bennett] [[941824d](https://github.com/Netflix-Skunkworks/go-jira/commit/941824d)]
## 1.0.4 - 2017-09-08
* update deps for kingpeon update use os.exec instead of syscall.exec for windows [Cory Bennett] [[86b963b](https://github.com/Netflix-Skunkworks/go-jira/commit/86b963b)]
## 1.0.3 - 2017-09-06
* [[#66](https://github.com/Netflix-Skunkworks/go-jira/issues/66)] add --started option to `jira worklog add` to change the start time for worklog [Cory Bennett] [[e6faee1](https://github.com/Netflix-Skunkworks/go-jira/commit/e6faee1)]
* [[#45](https://github.com/Netflix-Skunkworks/go-jira/issues/45)] automatically add comment to issue even if transition does not support comment updates during transtion [Cory Bennett] [[c4be59c](https://github.com/Netflix-Skunkworks/go-jira/commit/c4be59c)]
## 1.0.2 - 2017-09-06
* update dependencies [Cory Bennett] [[aa876cd](https://github.com/Netflix-Skunkworks/go-jira/commit/aa876cd)]
* update for github.com/AlecAivazis/survey => gopkg.in/AlecAivazis/survey.v1 package [Cory Bennett] [[9453179](https://github.com/Netflix-Skunkworks/go-jira/commit/9453179)]
* use stdout to determin output terminal size [Cory Bennett] [[4d79af4](https://github.com/Netflix-Skunkworks/go-jira/commit/4d79af4)]
## 1.0.1 - 2017-09-06
* [[#13](https://github.com/Netflix-Skunkworks/go-jira/issues/13)] change default input syntax to not require escaping for special characters [Cory Bennett] [[1106558](https://github.com/Netflix-Skunkworks/go-jira/commit/1106558)]
## 1.0.0 - 2017-09-05
* fix build for windows [Cory Bennett] [[1b854da](https://github.com/Netflix-Skunkworks/go-jira/commit/1b854da)]
Generated
+165
View File
@@ -0,0 +1,165 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "github.com/alecthomas/template"
packages = [".","parse"]
revision = "a0175ee3bccc567396460bf5acd36800cb10c49c"
[[projects]]
branch = "master"
name = "github.com/alecthomas/units"
packages = ["."]
revision = "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a"
[[projects]]
branch = "master"
name = "github.com/cheekybits/genny"
packages = ["generic"]
revision = "9127e812e1e9e501ce899a18121d316ecb52e4ba"
[[projects]]
branch = "master"
name = "github.com/coryb/figtree"
packages = ["."]
revision = "c7d8fbf1d7746b5864b8262fabffec813b5a43fa"
[[projects]]
branch = "master"
name = "github.com/coryb/kingpeon"
packages = ["."]
revision = "64b561ae2d0f895b94719c486bed798f4236a4b3"
[[projects]]
branch = "master"
name = "github.com/coryb/oreo"
packages = ["."]
revision = "95687d61c95ee1522c1140e2af59b0c1846abfc1"
[[projects]]
branch = "master"
name = "github.com/fatih/camelcase"
packages = ["."]
revision = "f6a740d52f961c60348ebb109adde9f4635d7540"
[[projects]]
branch = "master"
name = "github.com/guelfey/go.dbus"
packages = ["."]
revision = "f6a3a2366cc39b8479cadc499d3c735fb10fbdda"
[[projects]]
branch = "master"
name = "github.com/jinzhu/copier"
packages = ["."]
revision = "32e0d0db1dcd4373fb9eb0f9d727b1fe1a723e54"
[[projects]]
branch = "master"
name = "github.com/kballard/go-shellquote"
packages = ["."]
revision = "cd60e84ee657ff3dc51de0b4f55dd299a3e136f2"
[[projects]]
branch = "master"
name = "github.com/mattn/go-colorable"
packages = ["."]
revision = "ad5389df28cdac544c99bd7b9161a0b5b6ca9d1b"
[[projects]]
name = "github.com/mattn/go-isatty"
packages = ["."]
revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe"
version = "v0.0.2"
[[projects]]
branch = "master"
name = "github.com/mgutz/ansi"
packages = ["."]
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
[[projects]]
branch = "master"
name = "github.com/pkg/browser"
packages = ["."]
revision = "c90ca0c84f15f81c982e32665bffd8d7aac8f097"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
branch = "master"
name = "github.com/sethgrid/pester"
packages = ["."]
revision = "a86a2d88f4dc3c7dbf3a6a6bbbfb095690b834b6"
[[projects]]
branch = "master"
name = "github.com/theckman/go-flock"
packages = ["."]
revision = "6de226b0d5f040ed85b88c82c381709b98277f3d"
[[projects]]
branch = "master"
name = "github.com/tidwall/gjson"
packages = ["."]
revision = "be96719f990978a867f52c48f29d43f6b591da28"
[[projects]]
branch = "master"
name = "github.com/tidwall/match"
packages = ["."]
revision = "173748da739a410c5b0b813b956f89ff94730b4c"
[[projects]]
branch = "master"
name = "github.com/tmc/keyring"
packages = ["."]
revision = "06e6283d50adc5f8fcdb3cdf33ee1244d4400ae1"
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["ssh/terminal"]
revision = "9ba3862cf6a5452ae579de98f9364dd2e544844c"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix","windows"]
revision = "a5054c7c1385fd50d9394475365355a87a7873ec"
[[projects]]
name = "gopkg.in/AlecAivazis/survey.v1"
packages = [".","core","terminal"]
revision = "9d910423e24aa6d7c7950160658c295e0734c7e0"
version = "1.3.1"
[[projects]]
name = "gopkg.in/alecthomas/kingpin.v2"
packages = ["."]
revision = "1087e65c9441605df944fb12c33f0fe7072d18ca"
version = "v2.2.5"
[[projects]]
branch = "v2"
name = "gopkg.in/coryb/yaml.v2"
packages = ["."]
revision = "fb7cb9628c6e3bdd76c29fb91798d51a09832470"
[[projects]]
name = "gopkg.in/op/go-logging.v1"
packages = ["."]
revision = "b2cb9fa56473e98db8caba80237377e83fe44db5"
version = "v1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "1f4b97fcf898a5ef03af5e222686a09328b393e71797d21bf0c37b74d1e74a8e"
solver-name = "gps-cdcl"
solver-version = 1
+75
View File
@@ -0,0 +1,75 @@
# 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/coryb/figtree"
[[constraint]]
name = "github.com/coryb/kingpeon"
[[constraint]]
name = "github.com/coryb/oreo"
[[constraint]]
name = "github.com/jinzhu/copier"
[[constraint]]
name = "github.com/kballard/go-shellquote"
[[constraint]]
name = "github.com/mgutz/ansi"
[[constraint]]
name = "github.com/pkg/browser"
[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.0"
[[constraint]]
name = "github.com/savaki/jq"
[[constraint]]
name = "github.com/tmc/keyring"
[[constraint]]
name = "golang.org/x/crypto"
[[constraint]]
name = "gopkg.in/AlecAivazis/survey.v1"
version = "1.3.1"
[[constraint]]
name = "gopkg.in/alecthomas/kingpin.v2"
version = "2.2.5"
[[constraint]]
name = "gopkg.in/coryb/yaml.v2"
[[constraint]]
name = "gopkg.in/op/go-logging.v1"
version = "1.0.0"
[[constraint]]
branch = "master"
name = "github.com/tidwall/gjson"
+13 -27
View File
@@ -1,19 +1,3 @@
PLATFORMS= \
freebsd/amd64 \
linux/386 \
linux/amd64 \
windows/386 \
windows/amd64 \
darwin/amd64 \
$(NULL)
# freebsd-386 \
# freebsd-arm \
# linux-arm \
# openbsd-386 \
# openbsd-amd64 \
# darwin-386
NAME=jira
OS=$(shell uname -s)
@@ -36,7 +20,7 @@ CURVER ?= $(patsubst v%,%,$(shell [ -d .git ] && git describe --abbrev=0 --tags
LDFLAGS:= -w
build:
go build -gcflags="-e -complete" -v -ldflags "$(LDFLAGS) -s" -o '$(BIN)' cmd/jira/main.go
go build -gcflags="-e" -v -ldflags "$(LDFLAGS) -s" -o '$(BIN)' cmd/jira/main.go
vet:
@go vet .
@@ -53,11 +37,11 @@ lint:
@golint ./jiradata
@golint ./cmd/jira
all:
docker pull karalabe/xgo-latest
all:
go get -u github.com/karalabe/xgo
rm -rf dist
mkdir -p dist
docker run --rm -e EXT_GOPATH=/gopath -v $$(pwd):/gopath/src/gopkg.in/Netflix-Skunkworks/go-jira.v1 -e TARGETS="$(PLATFORMS)" -v $$(pwd)/dist:/build karalabe/xgo-latest gopkg.in/Netflix-Skunkworks/go-jira.v1/cmd/jira
xgo --targets="freebsd/amd64,linux/386,linux/amd64,windows/386,windows/amd64,darwin/amd64" -dest ./dist -ldflags="-w -s" ./cmd/jira
install:
${MAKE} GOBIN=$$HOME/bin build
@@ -66,7 +50,7 @@ NEWVER ?= $(shell echo $(CURVER) | awk -F. '{print $$1"."$$2"."$$3+1}')
TODAY := $(shell date +%Y-%m-%d)
changes:
@git log --pretty=format:"* %s [%cn] [%h]" --no-merges ^v$(CURVER) HEAD *.go jiracli/*.go jiradata/*.go jiracmd/*.go cmd/*/*.go | grep -vE 'gofmt|go fmt'
@git log --pretty=format:"* %s [%cn] [%h]" --no-merges ^v$(CURVER) HEAD *.go jiracli/*.go jiradata/*.go jiracmd/*.go cmd/*/*.go *.lock | grep -vE 'gofmt|go fmt|version bump'
update-changelog:
@echo "# Changelog" > CHANGELOG.md.new; \
@@ -82,7 +66,13 @@ update-changelog:
$(NULL)
release:
git commit -m "Updated Changelog" CHANGELOG.md; \
perl -pi -e 'undef $$/; s/\n```\nusage.*```//sg' README.md
echo '```' >> README.md
./jira --help >> README.md || true
echo '```' >> README.md
git diff --exit-code --quiet README.md || git commit -m "Updated Usage" README.md
git commit -m "Updated Changelog" CHANGELOG.md
git commit -m "version bump" jira.go
git tag v$(NEWVER)
git push --tags
@@ -92,12 +82,8 @@ version:
clean:
rm -rf ./$(NAME)
export GNUPGHOME=$(CWD)/t/.gnupg
export PASSWORD_STORE_DIR=$(CWD)/t/.password-store
export JIRACLOUD=1
prove:
chmod -R g-rwx,o-rwx $(GNUPGHOME)
chmod -R g-rwx,o-rwx $(CWD)/t/.gnupg
OSHT_VERBOSE=1 prove -v
generate:
+8 -371
View File
@@ -1,7 +1,7 @@
[![Join the chat at https://gitter.im/go-jira-cli/help](https://badges.gitter.im/go-jira-cli/help.svg)](https://gitter.im/go-jira-cli/help?utm_source=badge&utm_medium=badge&utm_content=badge)
[![Build Status](https://travis-ci.org/Netflix-Skunkworks/go-jira.svg?branch=master)](https://travis-ci.org/Netflix-Skunkworks/go-jira)
[![GoDoc](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1?status.png)](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1)
[![GoDoc](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1?status.svg)](https://godoc.org/gopkg.in/Netflix-Skunkworks/go-jira.v1)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
# go-jira
simple command line client for Atlassian's Jira service written in Go
@@ -56,7 +56,7 @@ custom-commands:
- name: mine
help: display issues assigned to me
script: |-
jira list --query "resolution = unresolved and assignee=currentuser() ORDER BY created"
{{jira}} list --query "resolution = unresolved and assignee=currentuser() ORDER BY created"
```
Then the next time you run `jira help` you will see your usage:
```
@@ -267,25 +267,27 @@ custom-commands:
* `jira mine` for listing issues assigned to you
```
custom-commands:
- name: mine
help: display issues assigned to me
script: |-
if [ -n "$JIRA_PROJECT" ]; then
# if `project: ...` configured just list the issues for current project
jira list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created"
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created"
else
# otherwise list issues for all project
jira list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created"
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created"
fi
```
* `jira sprint` for listing issues in your current sprint
```
custom-commands:
- name: sprint
help: display issues for active sprint
script: |-
if [ -n "$JIRA_PROJECT" ]; then
# if `project: ...` configured just list the issues for current project
jira list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved and project=$JIRA_PROJECT ORDER BY rank asc, created"
{{jira}} list --template table --query "sprint in openSprints() and type != epic and resolution = unresolved and project=$JIRA_PROJECT ORDER BY rank asc, created"
else
# otherwise list issues for all project
echo "\"project: ...\" configuration missing from .jira.d/config.yml"
@@ -393,369 +395,4 @@ export GPG_TTY=$(tty)
## Usage
```
usage: jira [<flags>] <command> [<args> ...]
Jira Command Line Interface
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
-v, --verbose ... Increase verbosity for debugging
-e, --endpoint=ENDPOINT Base URI to use for Jira
-k, --insecure Disable TLS certificate verification
-Q, --quiet Suppress output to console
--unixproxy=UNIXPROXY Path for a unix-socket proxy
-u, --user=USER Login name used for authentication with Jira service
Commands:
help [<command>...]
Show help.
version
Prints version
login
Attempt to login into jira server
logout
Deactivate sesssion with Jira server
list [<flags>]
Prints list of issues for given search criteria
-t, --template=TEMPLATE Template to use for output
-a, --assignee=ASSIGNEE User assigned the issue
-c, --component=COMPONENT Component to search for
-i, --issuetype=ISSUETYPE Issue type to search for
-l, --limit=LIMIT Maximum number of results to return in search
-p, --project=PROJECT Project to search for
-q, --query=QUERY Jira Query Language (JQL) expression for the search
-f, --queryfields=QUERYFIELDS Fields that are used in "list" template
-r, --reporter=REPORTER Reporter to search for
-s, --sort=SORT Sort order to return
-w, --watcher=WATCHER Watcher to search for
view [<flags>] <ISSUE>
Prints issue details
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--expand=EXPAND ... field to expand for the issue
--field=FIELD ... field to return for the issue
--property=PROPERTY ... property to return for issue
create [<flags>]
Create issue
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-p, --project=PROJECT project to create issue in
-i, --issuetype=ISSUETYPE issuetype in to create
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
--saveFile=SAVEFILE Write issue as yaml to file
edit [<flags>] [<ISSUE>]
Edit issue details
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-q, --query=QUERY Jira Query Language (JQL) expression for the search to edit multiple issues
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
comment [<flags>] [<ISSUE>]
Add comment to issue
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
worklog list [<flags>] <ISSUE>
Prints the worklog data for given issue
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
worklog add [<flags>] <ISSUE>
Add a worklog to an issue
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for worklog
-T, --time-spent=TIME-SPENT Time spent working on issue
fields [<flags>]
Prints all fields, both System and Custom
-t, --template=TEMPLATE Template to use for output
createmeta [<flags>]
View 'create' metadata
-t, --template=TEMPLATE Template to use for output
-p, --project=PROJECT project to fetch create metadata
-i, --issuetype=ISSUETYPE issuetype in project to fetch create metadata
editmeta [<flags>] <ISSUE>
View 'edit' metadata
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
subtask [<flags>] [<ISSUE>]
Subtask issue
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-p, --project=PROJECT project to subtask issue in
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
dup [<flags>] <DUPLICATE> <ISSUE>
Mark issues as duplicate
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
-m, --comment=COMMENT Comment message when marking issue as duplicate
block [<flags>] <BLOCKER> <ISSUE>
Mark issues as blocker
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
-m, --comment=COMMENT Comment message when marking issue as blocker
issuelink [<flags>] <OUTWARDISSUE> <ISSUELINKTYPE> <INWARDISSUE>
Link two issues
-b, --browse Open issue(s) in browser after operation
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
-m, --comment=COMMENT Comment message when linking issue
issuelinktypes [<flags>]
Show the issue link types
-t, --template=TEMPLATE Template to use for output
transition [<flags>] <TRANSITION> <ISSUE>
Transition issue to given state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
transitions [<flags>] <ISSUE>
List valid issue transitions
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
transmeta [<flags>] <ISSUE>
List valid issue transitions
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
close [<flags>] <ISSUE>
Transition issue to close state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
acknowledge [<flags>] <ISSUE>
Transition issue to acknowledge state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
reopen [<flags>] <ISSUE>
Transition issue to reopen state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
resolve [<flags>] <ISSUE>
Transition issue to resolve state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
start [<flags>] <ISSUE>
Transition issue to start state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
stop [<flags>] <ISSUE>
Transition issue to stop state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
todo [<flags>] <ISSUE>
Transition issue to To Do state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
backlog [<flags>] <ISSUE>
Transition issue to Backlog state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
done [<flags>] <ISSUE>
Transition issue to Done state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
in-progress [<flags>] <ISSUE>
Transition issue to Progress state
-b, --browse Open issue(s) in browser after operation
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-m, --comment=COMMENT Comment message for issue
-o, --override=OVERRIDE ... Set issue property
vote [<flags>] [<ISSUE>]
Vote up/down an issue
-b, --browse Open issue(s) in browser after operation
-d, --down downvote the issue
rank [<flags>] <FIRST-ISSUE> <after|before> <SECOND-ISSUE>
Mark issues as blocker
-b, --browse Open issue(s) in browser after operation
watch [<flags>] <ISSUE> [<WATCHER>]
Add/Remove watcher to issue
-b, --browse Open issue(s) in browser after operation
-r, --remove remove watcher from issue
labels add [<flags>] <ISSUE> <LABEL>...
Add labels to an issue
-b, --browse Open issue(s) in browser after operation
labels set [<flags>] <ISSUE> <LABEL>...
Set labels on an issue
-b, --browse Open issue(s) in browser after operation
labels remove [<flags>] <ISSUE> <LABEL>...
Remove labels from an issue
-b, --browse Open issue(s) in browser after operation
take [<flags>] <ISSUE> [<ASSIGNEE>]
Assign issue to yourself
-b, --browse Open issue(s) in browser after operation
--default use default user for assignee
assign [<flags>] <ISSUE> [<ASSIGNEE>]
Assign user to issue
-b, --browse Open issue(s) in browser after operation
--default use default user for assignee
unassign [<flags>] <ISSUE> [<ASSIGNEE>]
Unassign an issue
-b, --browse Open issue(s) in browser after operation
--default use default user for assignee
component add [<flags>]
Add component
--editor=EDITOR Editor to use
-t, --template=TEMPLATE Template to use for output
--noedit Disable opening the editor
-p, --project=PROJECT project to create component in
-n, --name=NAME name of component
-d, --description=DESCRIPTION description of component
-l, --lead=LEAD person that acts as lead for component
components [<flags>]
Show components for a project
-t, --template=TEMPLATE Template to use for output
-p, --project=PROJECT project to list components
issuetypes [<flags>]
Show issue types for a project
-t, --template=TEMPLATE Template to use for output
-p, --project=PROJECT project to list issueTypes
export-templates [<flags>]
Export templates for customizations
-t, --template=TEMPLATE Template to export
-d, --dir=DIR directory to write tempates to
unexport-templates [<flags>]
Remove unmodified exported templates
-t, --template=TEMPLATE Template to export
-d, --dir=DIR directory to write tempates to
browse <ISSUE>
Open issue in browser
request [<flags>] <API> [<JSON>]
Open issue in requestr
-M, --method=METHOD HTTP request method to use
```
+46
View File
@@ -0,0 +1,46 @@
package jira
import (
"fmt"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
// https://docs.atlassian.com/jira/REST/cloud/#api/2/attachment-getAttachment
func (j *Jira) GetAttachment(id string) (*jiradata.Attachment, error) {
return GetAttachment(j.UA, j.Endpoint, id)
}
func GetAttachment(ua HttpClient, endpoint string, id string) (*jiradata.Attachment, error) {
uri := fmt.Sprintf("%s/rest/api/2/attachment/%s", endpoint, id)
resp, err := ua.GetJSON(uri)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.Attachment{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/attachment-removeAttachment
func (j *Jira) RemoveAttachment(id string) error {
return RemoveAttachment(j.UA, j.Endpoint, id)
}
func RemoveAttachment(ua HttpClient, endpoint string, id string) error {
uri := fmt.Sprintf("%s/rest/api/2/attachment/%s", endpoint, id)
resp, err := ua.Delete(uri)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 204 {
return nil
}
return responseError(resp)
}
+270 -127
View File
@@ -3,10 +3,13 @@ package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"strconv"
"syscall"
"github.com/coryb/figtree"
"github.com/coryb/kingpeon"
@@ -49,6 +52,92 @@ func increaseLogLevel(verbosity int) {
}
}
var usage = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
{{end}}\
{{define "FormatBriefCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
{{ print .FullCommand ":" | printf "%-20s"}} {{.Help}}
{{end}}\
{{end}}\
{{end}}\
{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
{{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
{{end}}\
{{end}}\
{{end}}\
{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\
{{end}}\
{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatCommand" .Context.SelectedCommand}}
{{if .Context.SelectedCommand.Aliases }}\
{{range $top := .App.Commands}}\
{{if eq $top.FullCommand $.Context.SelectedCommand.FullCommand}}\
{{range $alias := $.Context.SelectedCommand.Aliases}}\
alias: {{$.App.Name}} {{$alias}}{{template "FormatCommand" $.Context.SelectedCommand}}
{{end}}\
{{else}}\
{{range $sub := $top.Commands}}\
{{if eq $sub.FullCommand $.Context.SelectedCommand.FullCommand}}\
{{range $alias := $.Context.SelectedCommand.Aliases}}\
alias: {{$.App.Name}} {{$top.Name}} {{$alias}}{{template "FormatCommand" $.Context.SelectedCommand}}
{{end}}\
{{end}}\
{{end}}\
{{end}}\
{{end}}\
{{end}}
{{if .Context.SelectedCommand.Help}}\
{{.Context.SelectedCommand.Help|Wrap 0}}
{{end}}\
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\
{{if .App.Flags}}\
Global flags:
{{.App.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if and .Context.SelectedCommand.Flags|RequiredFlags}}\
Required flags:
{{.Context.SelectedCommand.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand.Flags|OptionalFlags}}\
Optional flags:
{{.Context.SelectedCommand.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if .Context.SelectedCommand.Commands}}\
Subcommands:
{{template "FormatCommands" .Context.SelectedCommand}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatBriefCommands" .App}}
{{end}}\
`
func main() {
defer handleExit()
logBackend := logging.NewLogBackend(os.Stderr, "", 0)
@@ -73,6 +162,7 @@ func main() {
fmt.Println(jira.VERSION)
panic(jiracli.Exit{Code: 0})
})
app.UsageTemplate(usage)
var verbosity int
app.Flag("verbose", "Increase verbosity for debugging").Short('v').PreAction(func(_ *kingpin.ParseContext) error {
@@ -100,66 +190,116 @@ func main() {
registry := []jiracli.CommandRegistry{
jiracli.CommandRegistry{
Command: "login",
Entry: jiracmd.CmdLoginRegistry(),
Command: "acknowledge",
Aliases: []string{"ack"},
Entry: jiracmd.CmdTransitionRegistry("acknowledge"),
},
jiracli.CommandRegistry{
Command: "logout",
Entry: jiracmd.CmdLogoutRegistry(),
Command: "assign",
Entry: jiracmd.CmdAssignRegistry(),
Aliases: []string{"give"},
},
jiracli.CommandRegistry{
Command: "list",
Command: "attach create",
Entry: jiracmd.CmdAttachCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "attach get",
Entry: jiracmd.CmdAttachGetRegistry(),
},
jiracli.CommandRegistry{
Command: "attach list",
Entry: jiracmd.CmdAttachListRegistry(),
Aliases: []string{"ls"},
Entry: jiracmd.CmdListRegistry(),
},
jiracli.CommandRegistry{
Command: "view",
Entry: jiracmd.CmdViewRegistry(),
Command: "attach remove",
Entry: jiracmd.CmdAttachRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "create",
Entry: jiracmd.CmdCreateRegistry(),
Command: "backlog",
Entry: jiracmd.CmdTransitionRegistry("Backlog"),
},
jiracli.CommandRegistry{
Command: "edit",
Entry: jiracmd.CmdEditRegistry(),
Command: "block",
Entry: jiracmd.CmdBlockRegistry(),
},
jiracli.CommandRegistry{
Command: "browse",
Entry: jiracmd.CmdBrowseRegistry(),
Aliases: []string{"b"},
},
jiracli.CommandRegistry{
Command: "close",
Entry: jiracmd.CmdTransitionRegistry("close"),
},
jiracli.CommandRegistry{
Command: "comment",
Entry: jiracmd.CmdCommentRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog list",
Entry: jiracmd.CmdWorklogListRegistry(),
Default: true,
Command: "component add",
Entry: jiracmd.CmdComponentAddRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog add",
Entry: jiracmd.CmdWorklogAddRegistry(),
Command: "components",
Entry: jiracmd.CmdComponentsRegistry(),
},
jiracli.CommandRegistry{
Command: "fields",
Entry: jiracmd.CmdFieldsRegistry(),
Command: "create",
Entry: jiracmd.CmdCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "createmeta",
Entry: jiracmd.CmdCreateMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "editmeta",
Entry: jiracmd.CmdEditMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "subtask",
Entry: jiracmd.CmdSubtaskRegistry(),
Command: "done",
Entry: jiracmd.CmdTransitionRegistry("Done"),
},
jiracli.CommandRegistry{
Command: "dup",
Entry: jiracmd.CmdDupRegistry(),
},
jiracli.CommandRegistry{
Command: "block",
Entry: jiracmd.CmdBlockRegistry(),
Command: "edit",
Entry: jiracmd.CmdEditRegistry(),
},
jiracli.CommandRegistry{
Command: "editmeta",
Entry: jiracmd.CmdEditMetaRegistry(),
},
jiracli.CommandRegistry{
Command: "epic add",
Entry: jiracmd.CmdEpicAddRegistry(),
},
jiracli.CommandRegistry{
Command: "epic create",
Entry: jiracmd.CmdEpicCreateRegistry(),
},
jiracli.CommandRegistry{
Command: "epic list",
Entry: jiracmd.CmdEpicListRegistry(),
Aliases: []string{"ls"},
},
jiracli.CommandRegistry{
Command: "epic remove",
Entry: jiracmd.CmdEpicRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "export-templates",
Entry: jiracmd.CmdExportTemplatesRegistry(),
},
jiracli.CommandRegistry{
Command: "fields",
Entry: jiracmd.CmdFieldsRegistry(),
},
jiracli.CommandRegistry{
Command: "in-progress",
Aliases: []string{"prog", "progress"},
Entry: jiracmd.CmdTransitionRegistry("Progress"),
},
jiracli.CommandRegistry{
Command: "issuelink",
@@ -169,6 +309,73 @@ func main() {
Command: "issuelinktypes",
Entry: jiracmd.CmdIssueLinkTypesRegistry(),
},
jiracli.CommandRegistry{
Command: "issuetypes",
Entry: jiracmd.CmdIssueTypesRegistry(),
},
jiracli.CommandRegistry{
Command: "labels add",
Entry: jiracmd.CmdLabelsAddRegistry(),
},
jiracli.CommandRegistry{
Command: "labels remove",
Entry: jiracmd.CmdLabelsRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "labels set",
Entry: jiracmd.CmdLabelsSetRegistry(),
},
jiracli.CommandRegistry{
Command: "list",
Aliases: []string{"ls"},
Entry: jiracmd.CmdListRegistry(),
},
jiracli.CommandRegistry{
Command: "login",
Entry: jiracmd.CmdLoginRegistry(),
},
jiracli.CommandRegistry{
Command: "logout",
Entry: jiracmd.CmdLogoutRegistry(),
},
jiracli.CommandRegistry{
Command: "rank",
Entry: jiracmd.CmdRankRegistry(),
},
jiracli.CommandRegistry{
Command: "reopen",
Entry: jiracmd.CmdTransitionRegistry("reopen"),
},
jiracli.CommandRegistry{
Command: "request",
Entry: jiracmd.CmdRequestRegistry(),
Aliases: []string{"req"},
},
jiracli.CommandRegistry{
Command: "resolve",
Entry: jiracmd.CmdTransitionRegistry("resolve"),
},
jiracli.CommandRegistry{
Command: "start",
Entry: jiracmd.CmdTransitionRegistry("start"),
},
jiracli.CommandRegistry{
Command: "stop",
Entry: jiracmd.CmdTransitionRegistry("stop"),
},
jiracli.CommandRegistry{
Command: "subtask",
Entry: jiracmd.CmdSubtaskRegistry(),
},
jiracli.CommandRegistry{
Command: "take",
Entry: jiracmd.CmdTakeRegistry(),
},
jiracli.CommandRegistry{
Command: "todo",
Entry: jiracmd.CmdTransitionRegistry("To Do"),
},
jiracli.CommandRegistry{
Command: "transition",
Aliases: []string{"trans"},
@@ -182,115 +389,34 @@ func main() {
Command: "transmeta",
Entry: jiracmd.CmdTransitionsRegistry("debug"),
},
jiracli.CommandRegistry{
Command: "close",
Entry: jiracmd.CmdTransitionRegistry("close"),
},
jiracli.CommandRegistry{
Command: "acknowledge",
Aliases: []string{"ack"},
Entry: jiracmd.CmdTransitionRegistry("acknowledge"),
},
jiracli.CommandRegistry{
Command: "reopen",
Entry: jiracmd.CmdTransitionRegistry("reopen"),
},
jiracli.CommandRegistry{
Command: "resolve",
Entry: jiracmd.CmdTransitionRegistry("resolve"),
},
jiracli.CommandRegistry{
Command: "start",
Entry: jiracmd.CmdTransitionRegistry("start"),
},
jiracli.CommandRegistry{
Command: "stop",
Entry: jiracmd.CmdTransitionRegistry("stop"),
},
jiracli.CommandRegistry{
Command: "todo",
Entry: jiracmd.CmdTransitionRegistry("To Do"),
},
jiracli.CommandRegistry{
Command: "backlog",
Entry: jiracmd.CmdTransitionRegistry("Backlog"),
},
jiracli.CommandRegistry{
Command: "done",
Entry: jiracmd.CmdTransitionRegistry("Done"),
},
jiracli.CommandRegistry{
Command: "in-progress",
Aliases: []string{"prog", "progress"},
Entry: jiracmd.CmdTransitionRegistry("Progress"),
},
jiracli.CommandRegistry{
Command: "vote",
Entry: jiracmd.CmdVoteRegistry(),
},
jiracli.CommandRegistry{
Command: "rank",
Entry: jiracmd.CmdRankRegistry(),
},
jiracli.CommandRegistry{
Command: "watch",
Entry: jiracmd.CmdWatchRegistry(),
},
jiracli.CommandRegistry{
Command: "labels add",
Entry: jiracmd.CmdLabelsAddRegistry(),
},
jiracli.CommandRegistry{
Command: "labels set",
Entry: jiracmd.CmdLabelsSetRegistry(),
},
jiracli.CommandRegistry{
Command: "labels remove",
Entry: jiracmd.CmdLabelsRemoveRegistry(),
Aliases: []string{"rm"},
},
jiracli.CommandRegistry{
Command: "take",
Entry: jiracmd.CmdTakeRegistry(),
},
jiracli.CommandRegistry{
Command: "assign",
Entry: jiracmd.CmdAssignRegistry(),
Aliases: []string{"give"},
},
jiracli.CommandRegistry{
Command: "unassign",
Entry: jiracmd.CmdUnassignRegistry(),
},
jiracli.CommandRegistry{
Command: "component add",
Entry: jiracmd.CmdComponentAddRegistry(),
},
jiracli.CommandRegistry{
Command: "components",
Entry: jiracmd.CmdComponentsRegistry(),
},
jiracli.CommandRegistry{
Command: "issuetypes",
Entry: jiracmd.CmdIssueTypesRegistry(),
},
jiracli.CommandRegistry{
Command: "export-templates",
Entry: jiracmd.CmdExportTemplatesRegistry(),
},
jiracli.CommandRegistry{
Command: "unexport-templates",
Entry: jiracmd.CmdUnexportTemplatesRegistry(),
},
jiracli.CommandRegistry{
Command: "browse",
Entry: jiracmd.CmdBrowseRegistry(),
Aliases: []string{"b"},
Command: "view",
Entry: jiracmd.CmdViewRegistry(),
},
jiracli.CommandRegistry{
Command: "request",
Entry: jiracmd.CmdRequestRegistry(),
Aliases: []string{"req"},
Command: "vote",
Entry: jiracmd.CmdVoteRegistry(),
},
jiracli.CommandRegistry{
Command: "watch",
Entry: jiracmd.CmdWatchRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog add",
Entry: jiracmd.CmdWorklogAddRegistry(),
},
jiracli.CommandRegistry{
Command: "worklog list",
Entry: jiracmd.CmdWorklogListRegistry(),
Default: true,
},
}
@@ -307,9 +433,21 @@ func main() {
}
if len(data.CustomCommands) > 0 {
runner := syscall.Exec
if runtime.GOOS == "windows" {
runner = func(binary string, cmd []string, env []string) error {
command := exec.Command(binary, cmd[1:]...)
command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Env = env
return command.Run()
}
}
tmp := map[string]interface{}{}
fig.LoadAllConfigs("config.yml", &tmp)
kingpeon.RegisterDynamicCommands(app, data.CustomCommands, jiracli.TemplateProcessor())
kingpeon.RegisterDynamicCommandsWithRunner(runner, app, data.CustomCommands, jiracli.TemplateProcessor())
}
app.Terminate(func(status int) {
@@ -323,7 +461,12 @@ func main() {
// checking for default usage of `jira ISSUE-123` but need to allow
// for global options first like: `jira --user mothra ISSUE-123`
ctx, _ := app.ParseContext(os.Args[1:])
ctx, err := app.ParseContext(os.Args[1:])
if err != nil && ctx == nil {
// This is an internal kingpin usage error, duplicate options/commands
log.Fatalf("error: %s, ctx: %v", err, ctx)
}
if ctx != nil {
if ctx.SelectedCommand == nil {
next := ctx.Next()
+113
View File
@@ -0,0 +1,113 @@
package jira
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strings"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-getIssuesForEpic
func (j *Jira) EpicSearch(epic string, sp SearchProvider) (*jiradata.SearchResults, error) {
return EpicSearch(j.UA, j.Endpoint, epic, sp)
}
func EpicSearch(ua HttpClient, endpoint string, epic string, sp SearchProvider) (*jiradata.SearchResults, error) {
req := sp.ProvideSearchRequest()
// encoded, err := json.Marshal(req)
// if err != nil {
// return nil, err
// }
uri, err := url.Parse(fmt.Sprintf("%s/rest/agile/1.0/epic/%s/issue", endpoint, epic))
if err != nil {
return nil, err
}
params := url.Values{}
if len(req.Fields) > 0 {
params.Add("fields", strings.Join(req.Fields, ","))
}
if req.JQL != "" {
params.Add("jql", req.JQL)
}
if req.MaxResults != 0 {
params.Add("maxResults", fmt.Sprintf("%d", req.MaxResults))
}
if req.StartAt != 0 {
params.Add("startAt", fmt.Sprintf("%d", req.StartAt))
}
if req.ValidateQuery != "" {
params.Add("validateQuery", req.ValidateQuery)
}
uri.RawQuery = params.Encode()
resp, err := ua.Do(oreo.RequestBuilder(uri).WithHeader("Accept", "application/json").Build())
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
results := &jiradata.SearchResults{}
return results, readJSON(resp.Body, results)
}
return nil, responseError(resp)
}
type EpicIssuesProvider interface {
ProvideEpicIssues() *jiradata.EpicIssues
}
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-moveIssuesToEpic
func (j *Jira) EpicAddIssues(epic string, eip EpicIssuesProvider) error {
return EpicAddIssues(j.UA, j.Endpoint, epic, eip)
}
func EpicAddIssues(ua HttpClient, endpoint string, epic string, eip EpicIssuesProvider) error {
req := eip.ProvideEpicIssues()
encoded, err := json.Marshal(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/agile/1.0/epic/%s/issue", endpoint, epic)
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 204 {
return nil
}
return responseError(resp)
}
// https://docs.atlassian.com/jira-software/REST/latest/#agile/1.0/epic-removeIssuesFromEpic
func (j *Jira) EpicRemoveIssues(eip EpicIssuesProvider) error {
return EpicRemoveIssues(j.UA, j.Endpoint, eip)
}
func EpicRemoveIssues(ua HttpClient, endpoint string, eip EpicIssuesProvider) error {
req := eip.ProvideEpicIssues()
encoded, err := json.Marshal(req)
if err != nil {
return err
}
uri := fmt.Sprintf("%s/rest/agile/1.0/epic/none/issue", endpoint)
resp, err := ua.Post(uri, "application/json", bytes.NewBuffer(encoded))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 204 {
return nil
}
return responseError(resp)
}
Generated
-65
View File
@@ -1,65 +0,0 @@
hash: 3e4ada7ae3922b18b3492a45f1f31cdaaf68fa708327ce9b4f9730c3f0b3ca90
updated: 2017-08-30T18:15:39.909557691-07:00
imports:
- name: github.com/AlecAivazis/survey
version: 73fd4d7829877a72e03dbb42f84ed383fbbc5fa0
subpackages:
- core
- terminal
- name: github.com/alecthomas/template
version: a0175ee3bccc567396460bf5acd36800cb10c49c
subpackages:
- parse
- name: github.com/alecthomas/units
version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a
- name: github.com/cheekybits/genny
version: 9127e812e1e9e501ce899a18121d316ecb52e4ba
subpackages:
- generic
- name: github.com/coryb/figtree
version: 48d3afc6118a0c353dc7d41ff77a3e0b75e14c07
- name: github.com/coryb/kingpeon
version: 3ca9749293339b932167921f92ce7a55207ad34e
- name: github.com/coryb/oreo
version: 95687d61c95ee1522c1140e2af59b0c1846abfc1
- name: github.com/fatih/camelcase
version: f6a740d52f961c60348ebb109adde9f4635d7540
- name: github.com/guelfey/go.dbus
version: f6a3a2366cc39b8479cadc499d3c735fb10fbdda
- name: github.com/jinzhu/copier
version: 8bfca8a02a0ce12119cdc4974143c834ca589257
- name: github.com/kballard/go-shellquote
version: d8ec1a69a250a17bb0e419c386eac1f3711dc142
- name: github.com/mattn/go-isatty
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
- name: github.com/mgutz/ansi
version: c286dcecd19ff979eeb73ea444e479b903f2cfcb
- name: github.com/pkg/browser
version: c90ca0c84f15f81c982e32665bffd8d7aac8f097
- name: github.com/pkg/errors
version: 645ef00459ed84a119197bfb8d8205042c6df63d
- name: github.com/sethgrid/pester
version: 8053687f99650573b28fb75cddf3f295082704d7
- name: github.com/theckman/go-flock
version: 6de226b0d5f040ed85b88c82c381709b98277f3d
- name: github.com/tmc/keyring
version: 39227cc0349f1b69956c23aa1f679eefd17ebae0
- name: golang.org/x/crypto
version: 7f7c0c2d75ebb4e32a21396ce36e87b6dadc91c9
subpackages:
- ssh/terminal
- name: golang.org/x/sys
version: e24f485414aeafb646f6fca458b0bf869c0880a1
subpackages:
- unix
- name: gopkg.in/alecthomas/kingpin.v2
version: 1087e65c9441605df944fb12c33f0fe7072d18ca
- name: gopkg.in/coryb/yaml.v2
version: fb7cb9628c6e3bdd76c29fb91798d51a09832470
- name: gopkg.in/op/go-logging.v1
version: b2cb9fa56473e98db8caba80237377e83fe44db5
testImports:
- name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages:
- assert
-28
View File
@@ -1,28 +0,0 @@
package: gopkg.in/Netflix-Skunkworks/go-jira.v1
import:
- package: github.com/coryb/figtree
- package: github.com/coryb/oreo
- package: github.com/mgutz/ansi
- package: github.com/pkg/errors
version: ^0.8.0
- package: github.com/sethgrid/pester
- package: github.com/theckman/go-flock
- package: gopkg.in/alecthomas/kingpin.v2
version: ^2.2.4
- package: gopkg.in/op/go-logging.v1
version: ^1.0.0
- package: github.com/AlecAivazis/survey
version: ^1.2.4
- package: github.com/tmc/keyring
- package: github.com/kballard/go-shellquote
- package: github.com/jinzhu/copier
- package: github.com/pkg/browser
- package: github.com/coryb/kingpeon
- package: golang.org/x/crypto
subpackages:
- ssh/terminal
testImport:
- package: github.com/stretchr/testify
version: ^1.1.4
subpackages:
- assert
+52
View File
@@ -4,8 +4,13 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/url"
"strings"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
@@ -533,3 +538,50 @@ func IssueAssign(ua HttpClient, endpoint string, issue, name string) error {
}
return responseError(resp)
}
// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/attachments-addAttachment
func (j *Jira) IssueAttachFile(issue, filename string, contents io.Reader) (*jiradata.ListOfAttachment, error) {
return IssueAttachFile(j.UA, j.Endpoint, issue, filename, contents)
}
func IssueAttachFile(ua HttpClient, endpoint string, issue, filename string, contents io.Reader) (*jiradata.ListOfAttachment, error) {
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
formFile, err := w.CreateFormFile("file", filename)
if err != nil {
return nil, err
}
_, err = io.Copy(formFile, contents)
if err != nil {
return nil, err
}
uri, err := url.Parse(fmt.Sprintf("%s/rest/api/2/issue/%s/attachments", endpoint, issue))
req := oreo.RequestBuilder(uri).WithMethod("POST").WithHeader(
"X-Atlassian-Token", "no-check",
).WithHeader(
"Accept", "application/json",
).WithContentType(w.FormDataContentType()).WithBody(&buf).Build()
w.Close()
resp, err := ua.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
// FIXME move this to a test, and run go tests as part of our regression
if false {
// this is because schema is wrong, defaults to type `int`, so we manually change it
// to `string`. If the jiradata is regenerated we need to manually make the change
// again.
log.Debugf("Assert Attachment.ID is a string, rather than int: %v", &jiradata.Attachment{
ID: jiradata.IntOrString(0),
})
}
results := jiradata.ListOfAttachment{}
return &results, readJSON(resp.Body, &results)
}
return nil, responseError(resp)
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var log = logging.MustGetLogger("jira")
const VERSION = "1.0.0"
const VERSION = "1.0.10"
type Jira struct {
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
+19 -1
View File
@@ -12,11 +12,12 @@ import (
"reflect"
"strings"
"github.com/AlecAivazis/survey"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"github.com/jinzhu/copier"
shellquote "github.com/kballard/go-shellquote"
"github.com/tidwall/gjson"
"gopkg.in/AlecAivazis/survey.v1"
kingpin "gopkg.in/alecthomas/kingpin.v2"
yaml "gopkg.in/coryb/yaml.v2"
logging "gopkg.in/op/go-logging.v1"
@@ -40,6 +41,7 @@ type GlobalOptions struct {
type CommonOptions struct {
Browse figtree.BoolOption `yaml:"browse,omitempty" json:"browse,omitempty"`
Editor figtree.StringOption `yaml:"editor,omitempty" json:"editor,omitempty"`
GJsonQuery figtree.StringOption `yaml:"gjq,omitempty" json:"gjq,omitempty"`
SkipEditing figtree.BoolOption `yaml:"noedit,omitempty" json:"noedit,omitempty"`
Template figtree.StringOption `yaml:"template,omitempty" json:"template,omitempty"`
}
@@ -169,6 +171,22 @@ func TemplateUsage(cmd *kingpin.CmdClause, opts *CommonOptions) {
cmd.Flag("template", "Template to use for output").Short('t').SetValue(&opts.Template)
}
func GJsonQueryUsage(cmd *kingpin.CmdClause, opts *CommonOptions) {
cmd.Flag("gjq", "GJSON Query to filter output, see https://goo.gl/iaYwJ5").SetValue(&opts.GJsonQuery)
}
func (o *CommonOptions) PrintTemplate(data interface{}) error {
if o.GJsonQuery.Value != "" {
buf := bytes.NewBufferString("")
RunTemplate("json", data, buf)
results := gjson.GetBytes(buf.Bytes(), o.GJsonQuery.Value)
_, err := os.Stdout.Write([]byte(results.String()))
os.Stdout.Write([]byte{'\n'})
return err
}
return RunTemplate(o.Template.Value, data, nil)
}
func (o *CommonOptions) editFile(fileName string) (changes bool, err error) {
var editor string
for _, ed := range []string{o.Editor.Value, os.Getenv("JIRA_EDITOR"), os.Getenv("EDITOR"), "vim"} {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"os/exec"
"strings"
"github.com/AlecAivazis/survey"
"gopkg.in/AlecAivazis/survey.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
)
+122 -44
View File
@@ -13,9 +13,11 @@ import (
"strings"
"text/template"
yaml "gopkg.in/coryb/yaml.v2"
"github.com/coryb/figtree"
"github.com/mgutz/ansi"
"golang.org/x/crypto/ssh/terminal"
yaml "gopkg.in/coryb/yaml.v2"
)
func findTemplate(name string) ([]byte, error) {
@@ -60,6 +62,9 @@ func tmpTemplate(templateName string, data interface{}) (string, error) {
func TemplateProcessor() *template.Template {
funcs := map[string]interface{}{
"jira": func() string {
return os.Args[0]
},
"toJson": func(content interface{}) (string, error) {
bytes, err := json.MarshalIndent(content, "", " ")
if err != nil {
@@ -68,7 +73,7 @@ func TemplateProcessor() *template.Template {
return string(bytes), nil
},
"termWidth": func() int {
w, _, err := terminal.GetSize(int(os.Stdin.Fd()))
w, _, err := terminal.GetSize(int(os.Stdout.Fd()))
if err == nil {
return w
}
@@ -154,6 +159,48 @@ func TemplateProcessor() *template.Template {
return template.New("gojira").Funcs(funcs)
}
func ConfigTemplate(fig *figtree.FigTree, template, command string, opts interface{}) (string, error) {
var tmp map[string]interface{}
err := ConvertType(opts, &tmp)
if err != nil {
return "", err
}
fig.LoadAllConfigs(command+".yml", &tmp)
fig.LoadAllConfigs("config.yml", &tmp)
tmpl, err := TemplateProcessor().Parse(template)
if err != nil {
return "", err
}
buf := bytes.NewBufferString("")
if err := tmpl.Execute(buf, &tmp); err != nil {
return "", err
}
return buf.String(), nil
}
func ConvertType(input interface{}, output interface{}) error {
// HACK HACK HACK: convert data formats to json for backwards compatibilty with templates
jsonData, err := json.Marshal(input)
if err != nil {
return err
}
defer func(mapType, iface reflect.Type) {
yaml.DefaultMapType = mapType
yaml.IfaceType = iface
}(yaml.DefaultMapType, yaml.IfaceType)
yaml.DefaultMapType = reflect.TypeOf(map[string]interface{}{})
yaml.IfaceType = yaml.DefaultMapType.Elem()
if err := yaml.Unmarshal(jsonData, output); err != nil {
return err
}
return nil
}
func RunTemplate(templateName string, data interface{}, out io.Writer) error {
templateContent, err := getTemplate(templateName)
@@ -165,22 +212,10 @@ func RunTemplate(templateName string, data interface{}, out io.Writer) error {
out = os.Stdout
}
// HACK HACK HACK: convert data formats to json for backwards compatibilty with templates
var rawData interface{}
if jsonData, err := json.Marshal(data); err != nil {
err = ConvertType(data, &rawData)
if err != nil {
return err
} else {
defer func(mapType, iface reflect.Type) {
yaml.DefaultMapType = mapType
yaml.IfaceType = iface
}(yaml.DefaultMapType, yaml.IfaceType)
yaml.DefaultMapType = reflect.TypeOf(map[string]interface{}{})
yaml.IfaceType = yaml.DefaultMapType.Elem()
if err := yaml.Unmarshal(jsonData, &rawData); err != nil {
return err
}
}
tmpl, err := TemplateProcessor().Parse(templateContent)
@@ -194,25 +229,29 @@ func RunTemplate(templateName string, data interface{}, out io.Writer) error {
}
var AllTemplates = map[string]string{
"component-add": defaultComponentAddTemplate,
"debug": defaultDebugTemplate,
"fields": defaultDebugTemplate,
"editmeta": defaultDebugTemplate,
"transmeta": defaultDebugTemplate,
"createmeta": defaultDebugTemplate,
"issuelinktypes": defaultDebugTemplate,
"list": defaultListTemplate,
"table": defaultTableTemplate,
"view": defaultViewTemplate,
"edit": defaultEditTemplate,
"transitions": defaultTransitionsTemplate,
"components": defaultComponentsTemplate,
"issuetypes": defaultIssuetypesTemplate,
"create": defaultCreateTemplate,
"subtask": defaultSubtaskTemplate,
"attach-list": defaultAttachListTemplate,
"comment": defaultCommentTemplate,
"transition": defaultTransitionTemplate,
"component-add": defaultComponentAddTemplate,
"components": defaultComponentsTemplate,
"create": defaultCreateTemplate,
"createmeta": defaultDebugTemplate,
"debug": defaultDebugTemplate,
"edit": defaultEditTemplate,
"editmeta": defaultDebugTemplate,
"epic-create": defaultEpicCreateTemplate,
"epic-list": defaultTableTemplate,
"fields": defaultDebugTemplate,
"issuelinktypes": defaultDebugTemplate,
"issuetypes": defaultIssuetypesTemplate,
"json": defaultDebugTemplate,
"list": defaultListTemplate,
"request": defaultDebugTemplate,
"subtask": defaultSubtaskTemplate,
"table": defaultTableTemplate,
"transition": defaultTransitionTemplate,
"transitions": defaultTransitionsTemplate,
"transmeta": defaultDebugTemplate,
"view": defaultViewTemplate,
"worklog": defaultWorklogTemplate,
"worklogs": defaultWorklogsTemplate,
}
@@ -222,14 +261,23 @@ const defaultDebugTemplate = "{{ . | toJson}}\n"
const defaultListTemplate = "{{ range .issues }}{{ .key | append \":\" | printf \"%-12s\"}} {{ .fields.summary }}\n{{ end }}"
const defaultTableTemplate = `{{/* table template */ -}}
{{$w := sub termWidth 92 -}}
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
| {{ "Issue" | printf "%-14s" }} | {{ "Summary" | printf (printf "%%-%ds" (sub $w 2)) }} | {{ "Priority" | printf "%-12s" }} | {{ "Status" | printf "%-12s" }} | {{ "Age" | printf "%-10s" }} | {{ "Reporter" | printf "%-12s" }} | {{ "Assignee" | printf "%-12s" }} |
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
{{$w := sub termWidth 107 -}}
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
| {{ "Issue" | printf "%-14s" }} | {{ "Summary" | printf (printf "%%-%ds" (sub $w 2)) }} | {{ "Type" | printf "%-12s"}} | {{ "Priority" | printf "%-12s" }} | {{ "Status" | printf "%-12s" }} | {{ "Age" | printf "%-10s" }} | {{ "Reporter" | printf "%-12s" }} | {{ "Assignee" | printf "%-12s" }} |
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
{{ range .issues -}}
| {{ .key | printf "%-14s"}} | {{ .fields.summary | abbrev (sub $w 2) | printf (printf "%%-%ds" (sub $w 2)) }} | {{.fields.priority.name | printf "%-12s" }} | {{.fields.status.name | printf "%-12s" }} | {{.fields.created | age | printf "%-10s" }} | {{if .fields.reporter}}{{ .fields.reporter.name | printf "%-12s"}}{{else}}<unassigned>{{end}} | {{if .fields.assignee }}{{.fields.assignee.name | printf "%-12s" }}{{else}}<unassigned>{{end}} |
| {{ .key | printf "%-14s"}} | {{ .fields.summary | abbrev (sub $w 2) | printf (printf "%%-%ds" (sub $w 2)) }} | {{.fields.issuetype.name | printf "%-12s" }} | {{.fields.priority.name | printf "%-12s" }} | {{.fields.status.name | printf "%-12s" }} | {{.fields.created | age | printf "%-10s" }} | {{if .fields.reporter}}{{ .fields.reporter.name | printf "%-12s"}}{{else}}<unassigned>{{end}} | {{if .fields.assignee }}{{.fields.assignee.name | printf "%-12s" }}{{else}}<unassigned>{{end}} |
{{ end -}}
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
+{{ "-" | rep 16 }}+{{ "-" | rep $w }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
`
const defaultAttachListTemplate = `{{/* table template */ -}}
+{{ "-" | rep 12 }}+{{ "-" | rep 30 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
| {{printf "%-10s" "id"}} | {{printf "%-28s" "filename"}} | {{printf "%-10s" "bytes"}} | {{printf "%-12s" "user"}} | {{printf "%-12s" "created"}} |
+{{ "-" | rep 12 }}+{{ "-" | rep 30 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
{{range . -}}
| {{.id | printf "%10d" }} | {{.filename | printf "%-28s"}} | {{.size | printf "%10d"}} | {{.author.name | printf "%-12s"}} | {{.created | age | printf "%-12s"}} |
{{end -}}
+{{ "-" | rep 12 }}+{{ "-" | rep 30 }}+{{ "-" | rep 12 }}+{{ "-" | rep 14 }}+{{ "-" | rep 14 }}+
`
const defaultViewTemplate = `{{/* view template */ -}}
@@ -285,7 +333,8 @@ update:
body: |~
{{ or .overrides.comment "" | indent 10 }}
fields:
summary: {{ or .overrides.summary .fields.summary }}
summary: >-
{{ or .overrides.summary .fields.summary }}
{{- if and .meta.fields.components .meta.fields.components.allowedValues }}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{if .overrides.components }}{{ range (split "," .overrides.components)}}
- name: {{.}}{{end}}{{else}}{{ range .fields.components }}
@@ -334,7 +383,8 @@ fields:
key: {{ or .overrides.project "" }}
issuetype:
name: {{ or .overrides.issuetype "" }}
summary: {{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
summary: >-
{{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority ""}}{{end}}{{if .meta.fields.components.allowedValues}}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{ range split "," (or .overrides.components "")}}
@@ -350,11 +400,37 @@ fields:
- name: {{.}}{{end}}
- name:{{end}}`
const defaultEpicCreateTemplate = `{{/* epic create template */ -}}
fields:
project:
key: {{ or .overrides.project "" }}
# Epic Name
customfield_10120: {{ or (index .overrides "epic-name") "" }}
summary: >-
{{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority ""}}{{end}}{{if .meta.fields.components.allowedValues}}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{ range split "," (or .overrides.components "")}}
- name: {{ . }}{{end}}{{end}}
description: |~
{{ or .overrides.description "" | indent 4 }}{{if .meta.fields.assignee}}
assignee:
name: {{ or .overrides.assignee "" }}{{end}}{{if .meta.fields.reporter}}
reporter:
name: {{ or .overrides.reporter .overrides.user }}{{end}}{{if .meta.fields.customfield_10110}}
# watchers
customfield_10110: {{ range split "," (or .overrides.watchers "")}}
- name: {{.}}{{end}}
- name:{{end}}
issuetype:
name: Epic`
const defaultSubtaskTemplate = `{{/* create subtask template */ -}}
fields:
project:
key: {{ .parent.fields.project.key }}
summary: {{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
summary: >-
{{ or .overrides.summary "" }}{{if .meta.fields.priority.allowedValues}}
priority: # Values: {{ range .meta.fields.priority.allowedValues }}{{.name}}, {{end}}
name: {{ or .overrides.priority ""}}{{end}}{{if .meta.fields.components.allowedValues}}
components: # Values: {{ range .meta.fields.components.allowedValues }}{{.name}}, {{end}}{{ range split "," (or .overrides.components "")}}
@@ -428,7 +504,8 @@ fields:
name: {{if .overrides.resolution}}{{.overrides.resolution}}{{else if .fields.resolution}}{{.fields.resolution.name}}{{else}}{{or .overrides.defaultResolution "Fixed"}}{{end}}
{{- end -}}
{{if .meta.fields.summary}}
summary: {{or .overrides.summary .fields.summary}}
summary: >-
{{or .overrides.summary .fields.summary}}
{{- end -}}
{{if .meta.fields.versions.allowedValues}}
versions: # Values: {{ range .meta.fields.versions.allowedValues }}{{.name}}, {{end}}{{if .overrides.versions}}{{ range (split "," .overrides.versions)}}
@@ -445,12 +522,13 @@ const defaultWorklogTemplate = `{{/* worklog template */ -}}
comment: |~
{{ or .comment "" }}
timeSpent: {{ or .timeSpent "" }}
started:
started: {{ or .started "" }}
`
const defaultWorklogsTemplate = `{{/* worklogs template */ -}}
{{ range .worklogs }}- # {{.author.name}}, {{.created | age}} ago
comment: {{ or .comment "" }}
started: {{ .started }}
timeSpent: {{ .timeSpent }}
{{end}}`
+99
View File
@@ -0,0 +1,99 @@
package jiracmd
import (
"fmt"
"os"
"sort"
"golang.org/x/crypto/ssh/terminal"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
yaml "gopkg.in/coryb/yaml.v2"
)
type AttachCreateOptions struct {
jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"`
Issue string `yaml:"issue,omitempty" json:"issue,omitempty"`
Attachment string `yaml:"attachment,omitempty" json:"attachment,omitempty"`
Filename string `yaml:"filename,omitempty" json:"filename,omitempty"`
SaveFile string `yaml:"savefile,omitempty" json:"savefile,omitempty"`
}
func CmdAttachCreateRegistry() *jiracli.CommandRegistryEntry {
opts := AttachCreateOptions{}
return &jiracli.CommandRegistryEntry{
"Attach file to issue",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdAttachCreateUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdAttachCreate(o, globals, &opts)
},
}
}
func CmdAttachCreateUsage(cmd *kingpin.CmdClause, opts *AttachCreateOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
cmd.Flag("saveFile", "Write attachment information as yaml to file").StringVar(&opts.SaveFile)
cmd.Flag("filename", "Filename to use for attachment").Short('f').StringVar(&opts.Filename)
cmd.Arg("ISSUE", "issue to assign").Required().StringVar(&opts.Issue)
cmd.Arg("ATTACHMENT", "File to attach to issue, if not provided read from stdin").StringVar(&opts.Attachment)
return nil
}
func CmdAttachCreate(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AttachCreateOptions) error {
var contents *os.File
var err error
if opts.Attachment == "" {
if terminal.IsTerminal(int(os.Stdin.Fd())) {
return fmt.Errorf("ATTACHMENT argument required or redirect from STDIN")
}
contents = os.Stdin
if opts.Filename == "" {
return fmt.Errorf("--filename required when reading from stdin")
}
} else {
contents, err = os.Open(opts.Attachment)
if err != nil {
return err
}
if opts.Filename == "" {
opts.Filename = opts.Attachment
}
}
attachments, err := jira.IssueAttachFile(o, globals.Endpoint.Value, opts.Issue, opts.Filename, contents)
if err != nil {
return err
}
sort.Sort(sort.Reverse(attachments))
if opts.SaveFile != "" {
fh, err := os.Create(opts.SaveFile)
if err != nil {
return err
}
defer fh.Close()
out, err := yaml.Marshal((*attachments)[0])
if err != nil {
return err
}
fh.Write(out)
}
if !globals.Quiet.Value {
fmt.Printf("OK %d %s\n", (*attachments)[0].ID, (*attachments)[0].Content)
}
if opts.Browse.Value {
return CmdBrowse(globals, opts.Issue)
}
return nil
}
+79
View File
@@ -0,0 +1,79 @@
package jiracmd
import (
"fmt"
"io"
"os"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type AttachGetOptions struct {
AttachmentID string `yaml:"attachment-id,omitempty" json:"attachment-id,omitempty"`
OutputFile string `yaml:"output-file,omitempty" json:"output-file,omitempty"`
}
func CmdAttachGetRegistry() *jiracli.CommandRegistryEntry {
opts := AttachGetOptions{}
return &jiracli.CommandRegistryEntry{
"Fetch attachment",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdAttachGetUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdAttachGet(o, globals, &opts)
},
}
}
func CmdAttachGetUsage(cmd *kingpin.CmdClause, opts *AttachGetOptions) error {
cmd.Flag("output", "Write attachment to specified file name, '-' for stdout").Short('o').StringVar(&opts.OutputFile)
cmd.Arg("ATTACHMENT-ID", "Attachment id to fetch").StringVar(&opts.AttachmentID)
return nil
}
func CmdAttachGet(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AttachGetOptions) error {
attachment, err := jira.GetAttachment(o, globals.Endpoint.Value, opts.AttachmentID)
if err != nil {
return err
}
resp, err := o.Get(attachment.Content)
if err != nil {
return err
}
defer resp.Body.Close()
var output *os.File
if opts.OutputFile == "-" {
output = os.Stdout
} else if opts.OutputFile != "" {
output, err = os.Create(opts.OutputFile)
if err != nil {
return err
}
defer output.Close()
} else {
output, err = os.Create(attachment.Filename)
if err != nil {
return err
}
defer output.Close()
}
_, err = io.Copy(output, resp.Body)
if err != nil {
return err
}
output.Close()
if opts.OutputFile != "-" && !globals.Quiet.Value {
fmt.Printf("OK Wrote %s\n", output.Name())
}
return nil
}
+67
View File
@@ -0,0 +1,67 @@
package jiracmd
import (
"sort"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type AttachListOptions struct {
jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"`
Issue string `yaml:"issue,omitempty" json:"issue,omitempty"`
}
func CmdAttachListRegistry() *jiracli.CommandRegistryEntry {
opts := AttachListOptions{
CommonOptions: jiracli.CommonOptions{
Template: figtree.NewStringOption("attach-list"),
},
}
return &jiracli.CommandRegistryEntry{
"Prints attachment details for issue",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdAttachListUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdAttachList(o, globals, &opts)
},
}
}
func CmdAttachListUsage(cmd *kingpin.CmdClause, opts *AttachListOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
cmd.Arg("ISSUE", "Issue id to lookup attachments").Required().StringVar(&opts.Issue)
return nil
}
func CmdAttachList(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AttachListOptions) error {
data, err := jira.GetIssue(o, globals.Endpoint.Value, opts.Issue, nil)
if err != nil {
return err
}
// need to conver the interface{} "attachment" field to an actual
// ListOfAttachment object so we can sort it
var attachments jiradata.ListOfAttachment
err = jiracli.ConvertType(data.Fields["attachment"], &attachments)
if err != nil {
return err
}
sort.Sort(&attachments)
if err := opts.PrintTemplate(attachments); err != nil {
return err
}
if opts.Browse.Value {
return CmdBrowse(globals, opts.Issue)
}
return nil
}
+46
View File
@@ -0,0 +1,46 @@
package jiracmd
import (
"fmt"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
jira "gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type AttachRemoveOptions struct {
AttachmentID string `yaml:"attachment-id,omitempty" json:"attachment-id,omitempty"`
}
func CmdAttachRemoveRegistry() *jiracli.CommandRegistryEntry {
opts := AttachRemoveOptions{}
return &jiracli.CommandRegistryEntry{
"Delete attachment",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdAttachRemoveUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdAttachRemove(o, globals, &opts)
},
}
}
func CmdAttachRemoveUsage(cmd *kingpin.CmdClause, opts *AttachRemoveOptions) error {
cmd.Arg("ATTACHMENT-ID", "Attachment id to fetch").StringVar(&opts.AttachmentID)
return nil
}
func CmdAttachRemove(o *oreo.Client, globals *jiracli.GlobalOptions, opts *AttachRemoveOptions) error {
if err := jira.RemoveAttachment(o, globals.Endpoint.Value, opts.AttachmentID); err != nil {
return err
}
if !globals.Quiet.Value {
fmt.Printf("OK Deleted Attachment %s\n", opts.AttachmentID)
}
return nil
}
+2 -1
View File
@@ -37,6 +37,7 @@ func CmdComponentsRegistry() *jiracli.CommandRegistryEntry {
func CmdComponentsUsage(cmd *kingpin.CmdClause, opts *ComponentsOptions) error {
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Flag("project", "project to list components").Short('p').StringVar(&opts.Project)
return nil
@@ -51,5 +52,5 @@ func CmdComponents(o *oreo.Client, globals *jiracli.GlobalOptions, opts *Compone
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, data, nil)
return opts.PrintTemplate(data)
}
+2 -1
View File
@@ -35,6 +35,7 @@ func CmdCreateMetaRegistry() *jiracli.CommandRegistryEntry {
func CmdCreateMetaUsage(cmd *kingpin.CmdClause, opts *CreateMetaOptions) error {
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Flag("project", "project to fetch create metadata").Short('p').StringVar(&opts.Project)
cmd.Flag("issuetype", "issuetype in project to fetch create metadata").Short('i').StringVar(&opts.IssueType)
return nil
@@ -49,5 +50,5 @@ func CmdCreateMeta(o *oreo.Client, globals *jiracli.GlobalOptions, opts *CreateM
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, createMeta, nil)
return opts.PrintTemplate(createMeta)
}
+16 -4
View File
@@ -18,6 +18,7 @@ type EditOptions struct {
jira.SearchOptions `yaml:",inline" json:",inline" figtree:",inline"`
Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"`
Issue string `yaml:"issue,omitempty" json:"issue,omitempty"`
Queries map[string]string `yaml:"queries,omitempty" json:"queries,omitempty"`
}
func CmdEditRegistry() *jiracli.CommandRegistryEntry {
@@ -32,7 +33,7 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry {
"Edit issue details",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdEditUsage(cmd, &opts)
return CmdEditUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdEdit(o, globals, &opts)
@@ -40,11 +41,20 @@ func CmdEditRegistry() *jiracli.CommandRegistryEntry {
}
}
func CmdEditUsage(cmd *kingpin.CmdClause, opts *EditOptions) error {
func CmdEditUsage(cmd *kingpin.CmdClause, opts *EditOptions, fig *figtree.FigTree) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.EditorUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
cmd.Flag("noedit", "Disable opening the editor").SetValue(&opts.SkipEditing)
cmd.Flag("named-query", "The name of a query in the `queries` configuration").Short('n').PreAction(func(ctx *kingpin.ParseContext) error {
name := jiracli.FlagValue(ctx, "named-query")
if query, ok := opts.Queries[name]; ok && query != "" {
var err error
opts.Query, err = jiracli.ConfigTemplate(fig, query, cmd.FullCommand(), opts)
return err
}
return fmt.Errorf("A valid named-query %q not found in `queries` configuration", name)
}).String()
cmd.Flag("query", "Jira Query Language (JQL) expression for the search to edit multiple issues").Short('q').StringVar(&opts.Query)
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = jiracli.FlagValue(ctx, "comment")
@@ -90,6 +100,7 @@ func CmdEdit(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EditOptions)
if opts.Browse.Value {
return CmdBrowse(globals, opts.Issue)
}
return nil
}
results, err := jira.Search(o, globals.Endpoint.Value, opts)
if err != nil {
@@ -103,8 +114,9 @@ func CmdEdit(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EditOptions)
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Issue: issueData,
Meta: editMeta,
Issue: issueData,
Meta: editMeta,
Overrides: opts.Overrides,
}
err = jiracli.EditLoop(&opts.CommonOptions, &input, &issueUpdate, func() error {
return jira.EditIssue(o, globals.Endpoint.Value, issueData.Key, &issueUpdate)
+2 -1
View File
@@ -36,6 +36,7 @@ func CmdEditMetaRegistry() *jiracli.CommandRegistryEntry {
func CmdEditMetaUsage(cmd *kingpin.CmdClause, opts *EditMetaOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Arg("ISSUE", "edit metadata for issue id").Required().StringVar(&opts.Issue)
return nil
}
@@ -46,7 +47,7 @@ func CmdEditMeta(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EditMetaO
if err != nil {
return err
}
if err := jiracli.RunTemplate(opts.Template.Value, editMeta, nil); err != nil {
if err := opts.PrintTemplate(editMeta); err != nil {
return err
}
if opts.Browse.Value {
+54
View File
@@ -0,0 +1,54 @@
package jiracmd
import (
"fmt"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type EpicAddOptions struct {
jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"`
Epic string `yaml:"epic,omitempty" json:"epic,omitempty"`
}
func CmdEpicAddRegistry() *jiracli.CommandRegistryEntry {
opts := EpicAddOptions{}
return &jiracli.CommandRegistryEntry{
"Add issues to Epic",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdEpicAddUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdEpicAdd(o, globals, &opts)
},
}
}
func CmdEpicAddUsage(cmd *kingpin.CmdClause, opts *EpicAddOptions) error {
cmd.Arg("EPIC", "Epic Key or ID to add issues to").Required().StringVar(&opts.Epic)
cmd.Arg("ISSUE", "Issues to add to epic").Required().StringsVar(&opts.Issues)
return nil
}
func CmdEpicAdd(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicAddOptions) error {
if err := jira.EpicAddIssues(o, globals.Endpoint.Value, opts.Epic, &opts.EpicIssues); err != nil {
return err
}
if !globals.Quiet.Value {
fmt.Printf("OK %s %s/browse/%s\n", opts.Epic, globals.Endpoint.Value, opts.Epic)
for _, issue := range opts.Issues {
fmt.Printf("OK %s %s/browse/%s\n", issue, globals.Endpoint.Value, issue)
}
}
return nil
}
+48
View File
@@ -0,0 +1,48 @@
package jiracmd
import (
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
func CmdEpicCreateRegistry() *jiracli.CommandRegistryEntry {
opts := CreateOptions{
CommonOptions: jiracli.CommonOptions{
Template: figtree.NewStringOption("epic-create"),
},
Overrides: map[string]string{},
}
return &jiracli.CommandRegistryEntry{
"Create Epic",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdEpicCreateUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdCreate(o, globals, &opts)
},
}
}
func CmdEpicCreateUsage(cmd *kingpin.CmdClause, opts *CreateOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.EditorUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
cmd.Flag("noedit", "Disable opening the editor").SetValue(&opts.SkipEditing)
cmd.Flag("project", "project to create epic in").Short('p').StringVar(&opts.Project)
cmd.Flag("epic-name", "Epic Name").Short('n').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["epic-name"] = jiracli.FlagValue(ctx, "epic-name")
return nil
}).String()
cmd.Flag("comment", "Comment message for epic").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
opts.Overrides["comment"] = jiracli.FlagValue(ctx, "comment")
return nil
}).String()
cmd.Flag("override", "Set epic property").Short('o').StringMapVar(&opts.Overrides)
cmd.Flag("saveFile", "Write epic as yaml to file").StringVar(&opts.SaveFile)
return nil
}
+58
View File
@@ -0,0 +1,58 @@
package jiracmd
import (
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type EpicListOptions struct {
ListOptions `yaml:",inline" json:",inline" figtree:",inline"`
Epic string `yaml:"epic,omitempty" json:"epic,omitempty"`
}
func CmdEpicListRegistry() *jiracli.CommandRegistryEntry {
opts := EpicListOptions{
ListOptions: ListOptions{
CommonOptions: jiracli.CommonOptions{
Template: figtree.NewStringOption("epic-list"),
},
},
}
return &jiracli.CommandRegistryEntry{
"Prints list of issues for an epic with optional search criteria",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
if opts.MaxResults == 0 {
opts.MaxResults = 500
}
if opts.QueryFields == "" {
opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated,issuetype"
}
if opts.Sort == "" {
opts.Sort = "priority asc, key"
}
return CmdEpicListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdEpicList(o, globals, &opts)
},
}
}
func CmdEpicListUsage(cmd *kingpin.CmdClause, opts *EpicListOptions, fig *figtree.FigTree) error {
CmdListUsage(cmd, &opts.ListOptions, fig)
cmd.Arg("EPIC", "Epic Key or ID to list").Required().StringVar(&opts.Epic)
return nil
}
func CmdEpicList(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicListOptions) error {
data, err := jira.EpicSearch(o, globals.Endpoint.Value, opts.Epic, opts)
if err != nil {
return err
}
return opts.PrintTemplate(data)
}
+51
View File
@@ -0,0 +1,51 @@
package jiracmd
import (
"fmt"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiracli"
"gopkg.in/Netflix-Skunkworks/go-jira.v1/jiradata"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type EpicRemoveOptions struct {
jiradata.EpicIssues `yaml:",inline" json:",inline" figtree:",inline"`
}
func CmdEpicRemoveRegistry() *jiracli.CommandRegistryEntry {
opts := EpicRemoveOptions{}
return &jiracli.CommandRegistryEntry{
"Remove issues from Epic",
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
return CmdEpicRemoveUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdEpicRemove(o, globals, &opts)
},
}
}
func CmdEpicRemoveUsage(cmd *kingpin.CmdClause, opts *EpicRemoveOptions) error {
cmd.Arg("ISSUE", "Issues to remove from any epic").Required().StringsVar(&opts.Issues)
return nil
}
func CmdEpicRemove(o *oreo.Client, globals *jiracli.GlobalOptions, opts *EpicRemoveOptions) error {
if err := jira.EpicRemoveIssues(o, globals.Endpoint.Value, &opts.EpicIssues); err != nil {
return err
}
if !globals.Quiet.Value {
for _, issue := range opts.Issues {
fmt.Printf("OK %s %s/browse/%s\n", issue, globals.Endpoint.Value, issue)
}
}
return nil
}
+2 -1
View File
@@ -17,6 +17,7 @@ func CmdFieldsRegistry() *jiracli.CommandRegistryEntry {
func(fig *figtree.FigTree, cmd *kingpin.CmdClause) error {
jiracli.LoadConfigs(cmd, fig, &opts)
jiracli.TemplateUsage(cmd, &opts)
jiracli.GJsonQueryUsage(cmd, &opts)
return nil
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
@@ -31,5 +32,5 @@ func CmdFields(o *oreo.Client, globals *jiracli.GlobalOptions, opts *jiracli.Com
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, data, nil)
return opts.PrintTemplate(data)
}
+2 -1
View File
@@ -27,6 +27,7 @@ func CmdIssueLinkTypesRegistry() *jiracli.CommandRegistryEntry {
func CmdIssueLinkTypesUsage(cmd *kingpin.CmdClause, opts *jiracli.CommonOptions) error {
jiracli.TemplateUsage(cmd, opts)
jiracli.GJsonQueryUsage(cmd, opts)
return nil
}
@@ -36,5 +37,5 @@ func CmdIssueLinkTypes(o *oreo.Client, globals *jiracli.GlobalOptions, opts *jir
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, data, nil)
return opts.PrintTemplate(data)
}
+2 -1
View File
@@ -37,6 +37,7 @@ func CmdIssueTypesRegistry() *jiracli.CommandRegistryEntry {
func CmdIssueTypesUsage(cmd *kingpin.CmdClause, opts *IssueTypesOptions) error {
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Flag("project", "project to list issueTypes").Short('p').StringVar(&opts.Project)
return nil
@@ -51,5 +52,5 @@ func CmdIssueTypes(o *oreo.Client, globals *jiracli.GlobalOptions, opts *IssueTy
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, data, nil)
return opts.PrintTemplate(data)
}
+18 -4
View File
@@ -1,6 +1,8 @@
package jiracmd
import (
"fmt"
"github.com/coryb/figtree"
"github.com/coryb/oreo"
"gopkg.in/Netflix-Skunkworks/go-jira.v1"
@@ -11,6 +13,7 @@ import (
type ListOptions struct {
jiracli.CommonOptions `yaml:",inline" json:",inline" figtree:",inline"`
jira.SearchOptions `yaml:",inline" json:",inline" figtree:",inline"`
Queries map[string]string `yaml:"queries,omitempty" json:"queries,omitempty"`
}
func CmdListRegistry() *jiracli.CommandRegistryEntry {
@@ -28,12 +31,12 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry {
opts.MaxResults = 500
}
if opts.QueryFields == "" {
opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated"
opts.QueryFields = "assignee,created,priority,reporter,status,summary,updated,issuetype"
}
if opts.Sort == "" {
opts.Sort = "priority asc, key"
}
return CmdListUsage(cmd, &opts)
return CmdListUsage(cmd, &opts, fig)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
return CmdList(o, globals, &opts)
@@ -41,16 +44,27 @@ func CmdListRegistry() *jiracli.CommandRegistryEntry {
}
}
func CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions) error {
func CmdListUsage(cmd *kingpin.CmdClause, opts *ListOptions, fig *figtree.FigTree) error {
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Flag("assignee", "User assigned the issue").Short('a').StringVar(&opts.Assignee)
cmd.Flag("component", "Component to search for").Short('c').StringVar(&opts.Component)
cmd.Flag("issuetype", "Issue type to search for").Short('i').StringVar(&opts.IssueType)
cmd.Flag("limit", "Maximum number of results to return in search").Short('l').IntVar(&opts.MaxResults)
cmd.Flag("project", "Project to search for").Short('p').StringVar(&opts.Project)
cmd.Flag("named-query", "The name of a query in the `queries` configuration").Short('n').PreAction(func(ctx *kingpin.ParseContext) error {
name := jiracli.FlagValue(ctx, "named-query")
if query, ok := opts.Queries[name]; ok && query != "" {
var err error
opts.Query, err = jiracli.ConfigTemplate(fig, query, cmd.FullCommand(), opts)
return err
}
return fmt.Errorf("A valid named-query %q not found in `queries` configuration", name)
}).String()
cmd.Flag("query", "Jira Query Language (JQL) expression for the search").Short('q').StringVar(&opts.Query)
cmd.Flag("queryfields", "Fields that are used in \"list\" template").Short('f').StringVar(&opts.QueryFields)
cmd.Flag("reporter", "Reporter to search for").Short('r').StringVar(&opts.Reporter)
cmd.Flag("status", "Filter on issue status").Short('S').StringVar(&opts.Status)
cmd.Flag("sort", "Sort order to return").Short('s').StringVar(&opts.Sort)
cmd.Flag("watcher", "Watcher to search for").Short('w').StringVar(&opts.Watcher)
return nil
@@ -62,5 +76,5 @@ func CmdList(o *oreo.Client, globals *jiracli.GlobalOptions, opts *ListOptions)
if err != nil {
return err
}
return jiracli.RunTemplate(opts.Template.Value, data, nil)
return opts.PrintTemplate(data)
}
+3 -1
View File
@@ -35,6 +35,8 @@ func CmdRequestRegistry() *jiracli.CommandRegistryEntry {
if opts.Method == "" {
opts.Method = "GET"
}
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
return CmdRequestUsage(cmd, &opts)
},
func(o *oreo.Client, globals *jiracli.GlobalOptions) error {
@@ -89,5 +91,5 @@ func CmdRequest(o *oreo.Client, globals *jiracli.GlobalOptions, opts *RequestOpt
return fmt.Errorf("JSON Parse Error: %s from %q", err, content)
}
return jiracli.RunTemplate(opts.Template.Value, &data, nil)
return opts.PrintTemplate(&data)
}
+9
View File
@@ -133,6 +133,15 @@ func CmdTransition(o *oreo.Client, globals *jiracli.GlobalOptions, opts *Transit
Overrides map[string]string `yaml:"overrides,omitempty" json:"overrides,omitempty"`
}
if _, ok := transMeta.Fields["comment"]; !ok && opts.Overrides["comment"] != "" {
comment := jiradata.Comment{
Body: opts.Overrides["comment"],
}
if _, err := jira.IssueAddComment(o, globals.Endpoint.Value, opts.Issue, &comment); err != nil {
return err
}
}
issueUpdate := jiradata.IssueUpdate{}
input := templateInput{
Issue: issueData,
+2 -1
View File
@@ -35,6 +35,7 @@ func CmdTransitionsRegistry(defaultTemplate string) *jiracli.CommandRegistryEntr
func CmdTransitionsUsage(cmd *kingpin.CmdClause, opts *TransitionsOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Arg("ISSUE", "issue to list valid transitions").Required().StringVar(&opts.Issue)
return nil
}
@@ -45,7 +46,7 @@ func CmdTransitions(o *oreo.Client, globals *jiracli.GlobalOptions, opts *Transi
if err != nil {
return err
}
if err := jiracli.RunTemplate(opts.Template.Value, editMeta, nil); err != nil {
if err := opts.PrintTemplate(editMeta); err != nil {
return err
}
if opts.Browse.Value {
+2 -1
View File
@@ -36,6 +36,7 @@ func CmdViewRegistry() *jiracli.CommandRegistryEntry {
func CmdViewUsage(cmd *kingpin.CmdClause, opts *ViewOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Flag("expand", "field to expand for the issue").StringsVar(&opts.Expand)
cmd.Flag("field", "field to return for the issue").StringsVar(&opts.Fields)
cmd.Flag("property", "property to return for issue").StringsVar(&opts.Properties)
@@ -49,7 +50,7 @@ func CmdView(o *oreo.Client, globals *jiracli.GlobalOptions, opts *ViewOptions)
if err != nil {
return err
}
if err := jiracli.RunTemplate(opts.Template.Value, data, nil); err != nil {
if err := opts.PrintTemplate(data); err != nil {
return err
}
if opts.Browse.Value {
+1
View File
@@ -42,6 +42,7 @@ func CmdWorklogAddUsage(cmd *kingpin.CmdClause, opts *WorklogAddOptions) error {
cmd.Flag("noedit", "Disable opening the editor").SetValue(&opts.SkipEditing)
cmd.Flag("comment", "Comment message for worklog").Short('m').StringVar(&opts.Comment)
cmd.Flag("time-spent", "Time spent working on issue").Short('T').StringVar(&opts.TimeSpent)
cmd.Flag("started", "Time you started work").Short('S').StringVar(&opts.Started)
cmd.Arg("ISSUE", "issue id to fetch worklogs").Required().StringVar(&opts.Issue)
return nil
}
+3 -2
View File
@@ -35,6 +35,7 @@ func CmdWorklogListRegistry() *jiracli.CommandRegistryEntry {
func CmdWorklogListUsage(cmd *kingpin.CmdClause, opts *WorklogListOptions) error {
jiracli.BrowseUsage(cmd, &opts.CommonOptions)
jiracli.TemplateUsage(cmd, &opts.CommonOptions)
jiracli.GJsonQueryUsage(cmd, &opts.CommonOptions)
cmd.Arg("ISSUE", "issue id to fetch worklogs").Required().StringVar(&opts.Issue)
return nil
}
@@ -45,9 +46,9 @@ func CmdWorklogList(o *oreo.Client, globals *jiracli.GlobalOptions, opts *Worklo
if err != nil {
return err
}
if err := jiracli.RunTemplate(opts.Template.Value, struct {
if err := opts.PrintTemplate(struct {
Worklogs *jiradata.Worklogs `json:"worklogs,omitempty" yaml:"worklogs,omitempty"`
}{data}, nil); err != nil {
}{data}); err != nil {
return err
}
if opts.Browse.Value {
+179
View File
@@ -0,0 +1,179 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Attachment defined from schema:
// {
// "title": "Attachment",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "applicationRoles": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "groups": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "locale": {
// "title": "locale",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "content": {
// "title": "content",
// "type": "string"
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "filename": {
// "title": "filename",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "integer"
// },
// "mimeType": {
// "title": "mimeType",
// "type": "string"
// },
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "size": {
// "title": "size",
// "type": "integer"
// },
// "thumbnail": {
// "title": "thumbnail",
// "type": "string"
// }
// }
// }
type Attachment struct {
Author *User `json:"author,omitempty" yaml:"author,omitempty"`
Content string `json:"content,omitempty" yaml:"content,omitempty"`
Created string `json:"created,omitempty" yaml:"created,omitempty"`
Filename string `json:"filename,omitempty" yaml:"filename,omitempty"`
ID IntOrString `json:"id,omitempty" yaml:"id,omitempty"`
MimeType string `json:"mimeType,omitempty" yaml:"mimeType,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty" yaml:"properties,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
Size int `json:"size,omitempty" yaml:"size,omitempty"`
Thumbnail string `json:"thumbnail,omitempty" yaml:"thumbnail,omitempty"`
}
+5
View File
@@ -0,0 +1,5 @@
package jiradata
type EpicIssues struct {
Issues []string `json:"issues,omitempty" yaml:"issues,omitempty"`
}
+29
View File
@@ -0,0 +1,29 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Group defined from schema:
// {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
type Group struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
}
+29
View File
@@ -0,0 +1,29 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// Groups defined from schema:
// {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// }
type Groups []*Group
+202
View File
@@ -0,0 +1,202 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// ListOfAttachment defined from schema:
// {
// "title": "List of Attachment",
// "id": "https://docs.atlassian.com/jira/REST/schema/list-of-attachment#",
// "type": "array",
// "definitions": {
// "simple-list-wrapper": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// }
// },
// "items": {
// "title": "Attachment",
// "type": "object",
// "properties": {
// "author": {
// "title": "User",
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "applicationRoles": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
// "type": "string"
// }
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "groups": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "locale": {
// "title": "locale",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// },
// "content": {
// "title": "content",
// "type": "string"
// },
// "created": {
// "title": "created",
// "type": "string"
// },
// "filename": {
// "title": "filename",
// "type": "string"
// },
// "id": {
// "title": "id",
// "type": "integer"
// },
// "mimeType": {
// "title": "mimeType",
// "type": "string"
// },
// "properties": {
// "title": "properties",
// "type": "object",
// "patternProperties": {
// ".+": {}
// }
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "size": {
// "title": "size",
// "type": "integer"
// },
// "thumbnail": {
// "title": "thumbnail",
// "type": "string"
// }
// }
// }
// }
type ListOfAttachment []*Attachment
+13
View File
@@ -0,0 +1,13 @@
package jiradata
func (l *ListOfAttachment) Len() int {
return len(*l)
}
func (l *ListOfAttachment) Less(i, j int) bool {
return (*l)[i].ID < (*l)[j].ID
}
func (l *ListOfAttachment) Swap(i, j int) {
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
}
+45
View File
@@ -0,0 +1,45 @@
package jiradata
/////////////////////////////////////////////////////////////////////////
// This Code is Generated by SlipScheme Project:
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
// SimpleListWrapper defined from schema:
// {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// }
type SimpleListWrapper struct {
Items Groups `json:"items,omitempty" yaml:"items,omitempty"`
MaxResults int `json:"max-results,omitempty" yaml:"max-results,omitempty"`
Size int `json:"size,omitempty" yaml:"size,omitempty"`
}
+85 -10
View File
@@ -5,7 +5,7 @@ package jiradata
// https://github.com/coryb/slipscheme
//
// Generated with command:
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/WorklogWithPagination.json
// slipscheme -dir jiradata -pkg jiradata -overwrite schemas/ListofAttachment.json
/////////////////////////////////////////////////////////////////////////
// DO NOT EDIT //
/////////////////////////////////////////////////////////////////////////
@@ -16,12 +16,42 @@ package jiradata
// "type": "object",
// "properties": {
// "accountId": {
// "title": "accountId",
// "type": "string"
// },
// "active": {
// "title": "active",
// "type": "boolean"
// },
// "applicationRoles": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "avatarUrls": {
// "title": "avatarUrls",
// "type": "object",
// "patternProperties": {
// ".+": {
@@ -30,33 +60,78 @@ package jiradata
// }
// },
// "displayName": {
// "title": "displayName",
// "type": "string"
// },
// "emailAddress": {
// "title": "emailAddress",
// "type": "string"
// },
// "expand": {
// "title": "expand",
// "type": "string"
// },
// "groups": {
// "title": "Simple List Wrapper",
// "type": "object",
// "properties": {
// "items": {
// "type": "array",
// "items": {
// "title": "Group",
// "type": "object",
// "properties": {
// "name": {
// "type": "string"
// },
// "self": {
// "type": "string"
// }
// }
// }
// },
// "max-results": {
// "type": "integer"
// },
// "size": {
// "type": "integer"
// }
// }
// },
// "key": {
// "title": "key",
// "type": "string"
// },
// "locale": {
// "title": "locale",
// "type": "string"
// },
// "name": {
// "title": "name",
// "type": "string"
// },
// "self": {
// "title": "self",
// "type": "string"
// },
// "timeZone": {
// "title": "timeZone",
// "type": "string"
// }
// }
// }
type User struct {
AccountID string `json:"accountId,omitempty" yaml:"accountId,omitempty"`
Active bool `json:"active,omitempty" yaml:"active,omitempty"`
AvatarUrls map[string]string `json:"avatarUrls,omitempty" yaml:"avatarUrls,omitempty"`
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
EmailAddress string `json:"emailAddress,omitempty" yaml:"emailAddress,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
TimeZone string `json:"timeZone,omitempty" yaml:"timeZone,omitempty"`
AccountID string `json:"accountId,omitempty" yaml:"accountId,omitempty"`
Active bool `json:"active,omitempty" yaml:"active,omitempty"`
ApplicationRoles *SimpleListWrapper `json:"applicationRoles,omitempty" yaml:"applicationRoles,omitempty"`
AvatarUrls map[string]string `json:"avatarUrls,omitempty" yaml:"avatarUrls,omitempty"`
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
EmailAddress string `json:"emailAddress,omitempty" yaml:"emailAddress,omitempty"`
Expand string `json:"expand,omitempty" yaml:"expand,omitempty"`
Groups *SimpleListWrapper `json:"groups,omitempty" yaml:"groups,omitempty"`
Key string `json:"key,omitempty" yaml:"key,omitempty"`
Locale string `json:"locale,omitempty" yaml:"locale,omitempty"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Self string `json:"self,omitempty" yaml:"self,omitempty"`
TimeZone string `json:"timeZone,omitempty" yaml:"timeZone,omitempty"`
}
+29
View File
@@ -0,0 +1,29 @@
package jiradata
import (
"encoding/json"
"strconv"
)
// this is for some bad schemas like Attachments.ID where in some api's it is an `int` and some it is a `string`
type IntOrString int
func (i *IntOrString) UnmarshalYAML(unmarshal func(interface{}) error) error {
var tmp string
if err := unmarshal(&tmp); err != nil {
return unmarshal((*int)(i))
}
tmpInt, err := strconv.Atoi(tmp)
*i = IntOrString(tmpInt)
return err
}
func (i *IntOrString) UnmarshalJSON(b []byte) error {
var tmp string
if err := json.Unmarshal(b, &tmp); err != nil {
return json.Unmarshal(b, (*int)(i))
}
tmpInt, err := strconv.Atoi(tmp)
*i = IntOrString(tmpInt)
return err
}
+4
View File
@@ -25,3 +25,7 @@ func (c *Comment) ProvideComment() *Comment {
func (c *Component) ProvideComponent() *Component {
return c
}
func (e *EpicIssues) ProvideEpicIssues() *EpicIssues {
return e
}
+14 -10
View File
@@ -14,16 +14,17 @@ type SearchProvider interface {
}
type SearchOptions struct {
Assignee string
Query string
QueryFields string
Project string
Component string
IssueType string
Watcher string
Reporter string
Sort string
MaxResults int
Assignee string `yaml:"assignee,omitempty" json:"assignee,omitempty"`
Query string `yaml:"query,omitempty" json:"query,omitempty"`
QueryFields string `yaml:"query-fields,omitempty" json:"query-fields,omitempty"`
Project string `yaml:"project,omitempty" json:"project,omitempty"`
Component string `yaml:"component,omitempty" json:"component,omitempty"`
IssueType string `yaml:"issue-type,omitempty" json:"issue-type,omitempty"`
Watcher string `yaml:"watcher,omitempty" json:"watcher,omitempty"`
Reporter string `yaml:"reporter,omitempty" json:"reporter,omitempty"`
Status string `yaml:"status,omitempty" json:"status,omitempty"`
Sort string `yaml:"sort,omitempty" json:"sort,omitempty"`
MaxResults int `yaml:"max-results,omitempty" json:"max-results,omitempty"`
}
func (o *SearchOptions) ProvideSearchRequest() *jiradata.SearchRequest {
@@ -49,6 +50,9 @@ func (o *SearchOptions) ProvideSearchRequest() *jiradata.SearchRequest {
if o.Reporter != "" {
qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", o.Reporter))
}
if o.Status != "" {
qbuff.WriteString(fmt.Sprintf(" AND status = '%s'", o.Status))
}
if o.Sort != "" {
qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", o.Sort))
}
+43
View File
@@ -3,3 +3,46 @@ config:
password-source: pass
endpoint: https://go-jira.atlassian.net
user: gojira
project: BASIC
queries:
todo: >-
resolution = unresolved {{if .project}}AND project = '{{.project}}'{{end}} AND status = 'To Do'
custom-commands:
- name: env
help: print the JIRA environment variables available to custom commands
script: |-
env | sort | grep JIRA
- name: print-project
help: print the name of the configured project
script: "echo $JIRA_PROJECT"
- name: jira-path
help: print the path the jira command that is running this alias
script: |-
echo {{jira}}
- name: mine
help: display issues assigned to me
script: |-
if [ -n "$JIRA_PROJECT" ]; then
# if `project: ...` configured just list the issues for current project
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() and project = $JIRA_PROJECT ORDER BY priority asc, created"
else
# otherwise list issues for all project
{{jira}} list --template table --query "resolution = unresolved and assignee=currentuser() ORDER BY priority asc, created"
fi
- name: argtest
help: testing passing args
script: |-
echo {{args.ARG}}
args:
- name: ARG
help: string to echo for testing
- name: opttest
help: testing passing option flags
script: |-
echo {{options.OPT}}
options:
- name: OPT
help: string to echo for testing
+2
View File
@@ -3,6 +3,8 @@ eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira --user admin"
. env.sh
SKIP test -n "$JIRACLOUD" # using Jira Cloud at go-jira.atlassian.net
PLAN 15
+1
View File
@@ -2,6 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira=../jira
. env.sh
SKIP test -n "$JIRACLOUD" # using Jira Cloud at go-jira.atlassian.net
+54 -13
View File
@@ -2,15 +2,9 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
. env.sh
export COLUMNS=149
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
PLAN 86
PLAN 94
# reset login
RUNS $jira logout
@@ -58,17 +52,64 @@ DIFF <<EOF
$(printf %-12s $issue:) summary
EOF
###############################################################################
## List issues using a named query
###############################################################################
RUNS $jira ls --project BASIC -n todo
DIFF <<EOF
$(printf %-12s $issue:) summary
EOF
###############################################################################
## List all issues, using the table template
###############################################################################
RUNS $jira ls --project BASIC --template table
DIFF <<EOF
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Priority | Status | Age | Reporter | Assignee |
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue) | summary | Medium | To Do | a minute | gojira | gojira |
+----------------+---------------------------------------------------------+--------------+--------------+------------+--------------+--------------+
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue) | summary | Bug | Medium | To Do | a minute | gojira | gojira |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
###############################################################################
## Edit an issue
###############################################################################
RUNS $jira edit $issue -m "edit comment" --override priority=High --noedit
DIFF <<EOF
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
## Edit multiple issues with query
###############################################################################
RUNS $jira edit -m "bulk edit comment" --override priority=High --noedit --query "resolution = unresolved AND project = 'BASIC' AND status = 'To Do'"
DIFF <<EOF
OK $issue $ENDPOINT/browse/$issue
EOF
RUNS $jira $issue
DIFF <<EOF
issue: $issue
created: a minute ago
status: To Do
summary: summary
project: BASIC
issuetype: Bug
assignee: gojira
reporter: gojira
priority: High
votes: 0
description: |
description
comments:
- | # gojira, a minute ago
edit comment
- | # gojira, a minute ago
bulk edit comment
EOF
###############################################################################
+3 -7
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 8
@@ -31,7 +26,7 @@ EOF
###############################################################################
## Add a worklog to an issue
###############################################################################
RUNS $jira worklog add $issue --comment "work is hard" --time-spent "1h 12m" --noedit
RUNS $jira worklog add $issue --comment "work is hard" --time-spent "1h 12m" -S "2017-01-29T09:17:00.000-0500" --noedit
DIFF <<EOF
OK $issue $ENDPOINT/browse/$issue
EOF
@@ -43,6 +38,7 @@ RUNS $jira worklog $issue
DIFF <<EOF
- # gojira, a minute ago
comment: work is hard
started: 2017-01-29T06:17:00.000-0800
timeSpent: 1h 12m
EOF
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
. env.sh
PLAN 16
# reset login
RUNS $jira logout
RUNS $jira login
# cleanup from previous failed test executions
($jira ls --project BASIC | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g'
###############################################################################
## Create an issue
###############################################################################
RUNS $jira create --project BASIC -o summary=summary -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
## Testing the example custom commands, print-project
###############################################################################
RUNS $jira print-project
DIFF <<EOF
BASIC
EOF
###############################################################################
## Testing the example custom commands, jira-path
###############################################################################
RUNS $jira jira-path
DIFF <<EOF
../jira
EOF
###############################################################################
## Testing the example custom commands, env
###############################################################################
RUNS $jira env
GREP ^JIRA_PROJECT=BASIC
###############################################################################
## Testing the example custom commands, argtest
###############################################################################
RUNS $jira argtest TEST
DIFF <<EOF
TEST
EOF
###############################################################################
## Testing the example custom commands, opttest
###############################################################################
RUNS $jira opttest --OPT TEST
DIFF <<EOF
TEST
EOF
###############################################################################
## Use the "mine" alias to list issues assigned to self
###############################################################################
RUNS $jira mine
DIFF <<EOF
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue) | summary | Bug | Medium | To Do | a minute | gojira | gojira |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
+121
View File
@@ -0,0 +1,121 @@
#!/bin/bash
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
. env.sh
PLAN 22
# reset login
RUNS $jira logout
RUNS $jira login
# cleanup from previous failed test executions
($jira ls --project BASIC | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g'
###############################################################################
## Create an epic
###############################################################################
RUNS $jira epic create --project BASIC -o summary="Totally Epic" -o description=description --epic-name "Basic Epic" --noedit --saveFile issue.props
epic=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $epic $ENDPOINT/browse/$epic
EOF
###############################################################################
## Create issues we can assign to epic
###############################################################################
RUNS $jira create --project BASIC -o summary="summary" -o description=description --noedit --saveFile issue.props
issue1=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue1 $ENDPOINT/browse/$issue1
EOF
RUNS $jira create --project BASIC -o summary="summary" -o description=description --noedit --saveFile issue.props
issue2=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue2 $ENDPOINT/browse/$issue2
EOF
###############################################################################
## List the issues for the epic
###############################################################################
RUNS $jira epic list $epic
DIFF<<EOF
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
###############################################################################
## Add issues to an epic
###############################################################################
RUNS $jira epic add $epic $issue1 $issue2
DIFF<<EOF
OK $epic $ENDPOINT/browse/$epic
OK $issue1 $ENDPOINT/browse/$issue1
OK $issue2 $ENDPOINT/browse/$issue2
EOF
###############################################################################
## List the issues for the epic
###############################################################################
RUNS $jira epic list $epic
DIFF<<EOF
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue1) | summary | Bug | Medium | To Do | a minute | gojira | gojira |
| $(printf %-14s $issue2) | summary | Bug | Medium | To Do | a minute | gojira | gojira |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
###############################################################################
## Remove an issue from an Epic
###############################################################################
RUNS $jira epic remove $issue1
DIFF<<EOF
OK $issue1 $ENDPOINT/browse/$issue1
EOF
###############################################################################
## List the issues for the epic
###############################################################################
RUNS $jira epic list $epic
DIFF<<EOF
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| $(printf %-14s $issue2) | summary | Bug | Medium | To Do | a minute | gojira | gojira |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
###############################################################################
## Remove last issue from an Epic
###############################################################################
RUNS $jira epic remove $issue2
DIFF<<EOF
OK $issue2 $ENDPOINT/browse/$issue2
EOF
###############################################################################
## List the issues for the epic
###############################################################################
RUNS $jira epic list $epic
DIFF<<EOF
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
| Issue | Summary | Type | Priority | Status | Age | Reporter | Assignee |
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
+----------------+------------------------------------------+--------------+--------------+--------------+------------+--------------+--------------+
EOF
+189
View File
@@ -0,0 +1,189 @@
#!/bin/bash
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
. env.sh
PLAN 43
# reset login
RUNS $jira logout
RUNS $jira login
# cleanup from previous failed test executions
($jira ls --project BASIC | awk -F: '{print $1}' | while read issue; do ../jira done $issue; done) | sed 's/^/# CLEANUP: /g'
###############################################################################
## Create an issue
###############################################################################
RUNS $jira create --project BASIC -o summary="Attach To Me" -o description=description --noedit --saveFile issue.props
issue=$(awk '/issue/{print $2}' issue.props)
DIFF <<EOF
OK $issue $ENDPOINT/browse/$issue
EOF
###############################################################################
## Attach via stdin
###############################################################################
RUNS $jira attach create $issue --filename README.md --saveFile attach.props < ./README.md
attach1=$(awk '/^id:/{print $2}' attach.props)
DIFF <<EOF
OK $attach1 $ENDPOINT/secure/attachment/$attach1/README.md
EOF
###############################################################################
## Attach binary file
###############################################################################
RUNS dd of=garbage.bin if=/dev/urandom count=1k bs=1k
RUNS $jira attach create $issue garbage.bin --saveFile attach.props
attach2=$(awk '/^id:/{print $2}' attach.props)
DIFF <<EOF
OK $attach2 $ENDPOINT/secure/attachment/$attach2/garbage.bin
EOF
###############################################################################
## Attach binary file with different name
###############################################################################
RUNS $jira attach create $issue garbage.bin --filename foobar.bin --saveFile attach.props
attach3=$(awk '/^id:/{print $2}' attach.props)
DIFF <<EOF
OK $attach3 $ENDPOINT/secure/attachment/$attach3/foobar.bin
EOF
###############################################################################
## List attachments
###############################################################################
RUNS $jira attach list $issue
DIFF <<EOF
+------------+------------------------------+------------+--------------+--------------+
| id | filename | bytes | user | created |
+------------+------------------------------+------------+--------------+--------------+
| $(printf %10s $attach1) | README.md | 1238 | gojira | a minute |
| $(printf %10s $attach2) | garbage.bin | 1048576 | gojira | a minute |
| $(printf %10s $attach3) | foobar.bin | 1048576 | gojira | a minute |
+------------+------------------------------+------------+--------------+--------------+
EOF
###############################################################################
## Fetch text attachment
###############################################################################
RUNS $jira attach get $attach1 -o attach1.txt
DIFF <<EOF
OK Wrote attach1.txt
EOF
# verify no diffs
RUNS diff -q README.md attach1.txt
###############################################################################
## Fetch text attachment to stdout
###############################################################################
RUNS sh -c "$jira attach get $attach1 -o- > attach1.txt"
# verify no diffs
RUNS diff -q README.md attach1.txt
###############################################################################
## Fetch text attachment as same name
###############################################################################
RUNS $jira attach get $attach1
DIFF <<EOF
OK Wrote README.md
EOF
# verify no diffs
RUNS git diff README.md
###############################################################################
## Fetch binary attachment
###############################################################################
RUNS $jira attach get $attach2 --output binary.out
DIFF <<EOF
OK Wrote binary.out
EOF
# verify no diffs
RUNS diff -q garbage.bin binary.out
###############################################################################
## Fetch binary attachment to stdout
###############################################################################
RUNS sh -c "$jira attach get $attach2 -o- > binary.out"
# verify no diffs
RUNS diff -q garbage.bin binary.out
###############################################################################
## Fetch binary attachment
###############################################################################
RUNS $jira attach get $attach3
DIFF <<EOF
OK Wrote foobar.bin
EOF
# verify no diffs
RUNS diff -q garbage.bin foobar.bin
###############################################################################
## Fetch binary attachment to stdout
###############################################################################
RUNS sh -c "$jira attach get $attach3 --output=- > binary.out"
# verify no diffs
RUNS diff -q garbage.bin binary.out
###############################################################################
## Delete attachment
###############################################################################
RUNS $jira attach remove $attach1
DIFF <<EOF
OK Deleted Attachment $attach1
EOF
RUNS $jira attach list $issue
DIFF <<EOF
+------------+------------------------------+------------+--------------+--------------+
| id | filename | bytes | user | created |
+------------+------------------------------+------------+--------------+--------------+
| $(printf %10s $attach2) | garbage.bin | 1048576 | gojira | a minute |
| $(printf %10s $attach3) | foobar.bin | 1048576 | gojira | a minute |
+------------+------------------------------+------------+--------------+--------------+
EOF
###############################################################################
## Delete attachment
###############################################################################
RUNS $jira attach rm $attach2
DIFF <<EOF
OK Deleted Attachment $attach2
EOF
RUNS $jira attach list $issue
DIFF <<EOF
+------------+------------------------------+------------+--------------+--------------+
| id | filename | bytes | user | created |
+------------+------------------------------+------------+--------------+--------------+
| $(printf %10s $attach3) | foobar.bin | 1048576 | gojira | a minute |
+------------+------------------------------+------------+--------------+--------------+
EOF
###############################################################################
## Delete last
###############################################################################
RUNS $jira attach rm $attach3
DIFF <<EOF
OK Deleted Attachment $attach3
EOF
RUNS $jira attach list $issue
DIFF <<EOF
+------------+------------------------------+------------+--------------+--------------+
| id | filename | bytes | user | created |
+------------+------------------------------+------------+--------------+--------------+
+------------+------------------------------+------------+--------------+--------------+
EOF
+1 -6
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 84
+1 -6
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 86
+1 -6
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 84
+1 -6
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 84
+1 -6
View File
@@ -2,12 +2,7 @@
eval "$(curl -q -s https://raw.githubusercontent.com/coryb/osht/master/osht.sh)"
cd $(dirname $0)
jira="../jira"
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
ENDPOINT="http://localhost:8080"
if [ -n "$JIRACLOUD" ]; then
ENDPOINT="https://go-jira.atlassian.net"
fi
. env.sh
PLAN 82
+7
View File
@@ -0,0 +1,7 @@
export COLUMNS=149
export JIRA_LOG_FORMAT="%{level:-5s} %{message}"
export ENDPOINT="https://go-jira.atlassian.net"
export GNUPGHOME=$(pwd)/.gnupg
export PASSWORD_STORE_DIR=$(pwd)/.password-store
export JIRACLOUD=1
-46
View File
@@ -1,46 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var simpleQs = []*survey.Question{
{
Name: "letter",
Prompt: &survey.Select{
Message: "Choose a letter:",
Options: []string{
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
},
},
Validate: survey.Required,
},
}
func main() {
answers := struct {
Letter string
}{}
// ask the question
err := survey.Ask(simpleQs, &answers)
if err != nil {
fmt.Println(err.Error())
return
}
// print the answers
fmt.Printf("you chose %s.\n", answers.Letter)
}
-40
View File
@@ -1,40 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var simpleQs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "What is your name?",
},
Validate: survey.Required,
},
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
},
Validate: survey.Required,
},
}
func main() {
ansmap := make(map[string]string)
// ask the question
err := survey.Ask(simpleQs, &ansmap)
if err != nil {
fmt.Println(err.Error())
return
}
// print the answers
fmt.Printf("%s chose %s.\n", ansmap["name"], ansmap["color"])
}
-43
View File
@@ -1,43 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var simpleQs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "What is your name?",
},
Validate: survey.Required,
},
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
},
Validate: survey.Required,
},
}
func main() {
answers := struct {
Name string
Color string
}{}
// ask the question
err := survey.Ask(simpleQs, &answers)
if err != nil {
fmt.Println(err.Error())
return
}
// print the answers
fmt.Printf("%s chose %s.\n", answers.Name, answers.Color)
}
-41
View File
@@ -1,41 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var validationQs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "What is your name?"},
Validate: survey.Required,
},
{
Name: "valid",
Prompt: &survey.Input{Message: "Enter 'foo':", Default: "not foo"},
Validate: func(val interface{}) error {
// if the input matches the expectation
if str := val.(string); str != "foo" {
return fmt.Errorf("You entered %s, not 'foo'.", str)
}
// nothing was wrong
return nil
},
},
}
func main() {
// the place to hold the answers
answers := struct {
Name string
Valid string
}{}
err := survey.Ask(validationQs, &answers)
if err != nil {
fmt.Println("\n", err.Error())
}
}
-6
View File
@@ -1,6 +0,0 @@
# survey/tests
Because of the nature of this library, I was having a hard time finding a reliable
way to run unit tests, therefore I decided to try to create a suite
of integration tests which must be run successfully before a PR can be merged.
I will try to add to this suite as new edge cases are known.
-60
View File
@@ -1,60 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var simpleQs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "What is your name?",
Default: "Johnny Appleseed",
},
},
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green", "yellow"},
Default: "yellow",
},
Validate: survey.Required,
},
}
func main() {
fmt.Println("Asking many.")
// a place to store the answers
ans := struct {
Name string
Color string
}{}
err := survey.Ask(simpleQs, &ans)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Asking one.")
answer := ""
err = survey.AskOne(simpleQs[0].Prompt, &answer, nil)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("Answered with %v.\n", answer)
fmt.Println("Asking one with validation.")
vAns := ""
err = survey.AskOne(&survey.Input{Message: "What is your name?"}, &vAns, survey.Required)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("Answered with %v.\n", vAns)
}
-180
View File
@@ -1,180 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/ask.go go run ask.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "ask.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("Asking many.\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
fh.Write([]byte("L"))
expect("L", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte(" "))
expect(" ", buf)
fh.Write([]byte("B"))
expect("B", buf)
fh.Write([]byte("i"))
expect("i", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("d"))
expect("d", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Bird\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[1;36m yellow\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("A"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;36m green\x1b[0m\r\n", buf)
expect("\x1b[1;99m yellow\x1b[0m\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("A"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[1;99m yellow\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("Asking one.\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[37m(Johnny Appleseed) \x1b[0m", buf)
fh.Write([]byte("L"))
expect("L", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte(" "))
expect(" ", buf)
fh.Write([]byte("K"))
expect("K", buf)
fh.Write([]byte("i"))
expect("i", buf)
fh.Write([]byte("n"))
expect("n", buf)
fh.Write([]byte("g"))
expect("g", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry King\x1b[0m\r\n", buf)
expect("Answered with Larry King.\r\n", buf)
expect("Asking one with validation.\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[31m✘ Sorry, your reply was invalid: Value is required\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
fh.Write([]byte("L"))
expect("L", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte(" "))
expect(" ", buf)
fh.Write([]byte("W"))
expect("W", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Wall\x1b[0m\r\n", buf)
expect("Answered with Larry Wall.\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-132
View File
@@ -1,132 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/confirm.go go run confirm.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "confirm.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("Enter 'yes'\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(y/N) \x1b[0m", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte("e"))
expect("e", buf)
fh.Write([]byte("s"))
expect("s", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[36mYes\x1b[0m\r\n", buf)
expect("Answered true.\r\n", buf)
expect("---------------------\r\n", buf)
expect("Enter 'no'\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(y/N) \x1b[0m", buf)
fh.Write([]byte("n"))
expect("n", buf)
fh.Write([]byte("o"))
expect("o", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[36mNo\x1b[0m\r\n", buf)
expect("Answered false.\r\n", buf)
expect("---------------------\r\n", buf)
expect("default\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(Y/n) \x1b[0m", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[36mYes\x1b[0m\r\n", buf)
expect("Answered true.\r\n", buf)
expect("---------------------\r\n", buf)
expect("not recognized (enter random letter)\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(Y/n) \x1b[0m", buf)
fh.Write([]byte("x"))
expect("x", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[31m✘ Sorry, your reply was invalid: \"x\" is not a valid answer, please try again.\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(Y/n) \x1b[0m", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[36mYes\x1b[0m\r\n", buf)
expect("Answered true.\r\n", buf)
expect("---------------------\r\n", buf)
expect("no help - type '?'\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(Y/n) \x1b[0m", buf)
fh.Write([]byte("?"))
expect("?", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[31m✘ Sorry, your reply was invalid: \"?\" is not a valid answer, please try again.\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[37m(Y/n) \x1b[0m", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99myes: \x1b[0m\x1b[36mYes\x1b[0m\r\n", buf)
expect("Answered true.\r\n", buf)
expect("---------------------\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-104
View File
@@ -1,104 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/doubleSelect.go go run doubleSelect.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "doubleSelect.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect1:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect1:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect1:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect2:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect2:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mselect2:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("blue and blue.\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-236
View File
@@ -1,236 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/help.go go run help.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "help.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("confirm\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mIs it raining? \x1b[0m\x1b[36m[? for help]\x1b[0m \x1b[37m(y/N) \x1b[0m", buf)
fh.Write([]byte("?"))
expect("?", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[36mⓘ Go outside, if your head becomes wet the answer is probably 'yes'\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mIs it raining? \x1b[0m\x1b[37m(y/N) \x1b[0m", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte("e"))
expect("e", buf)
fh.Write([]byte("s"))
expect("s", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mIs it raining? \x1b[0m\x1b[36mYes\x1b[0m\r\n", buf)
expect("Answered true.\r\n", buf)
expect("---------------------\r\n", buf)
expect("input\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your phone number: \x1b[0m\x1b[36m[? for help]\x1b[0m ", buf)
fh.Write([]byte("?"))
expect("?", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[36mⓘ Phone number should include the area code, parentheses optional\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your phone number: \x1b[0m", buf)
fh.Write([]byte("1"))
expect("1", buf)
fh.Write([]byte("2"))
expect("2", buf)
fh.Write([]byte("3"))
expect("3", buf)
fh.Write([]byte("-"))
expect("-", buf)
fh.Write([]byte("1"))
expect("1", buf)
fh.Write([]byte("2"))
expect("2", buf)
fh.Write([]byte("3"))
expect("3", buf)
fh.Write([]byte("-"))
expect("-", buf)
fh.Write([]byte("1"))
expect("1", buf)
fh.Write([]byte("2"))
expect("2", buf)
fh.Write([]byte("3"))
expect("3", buf)
fh.Write([]byte("4"))
expect("4", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your phone number: \x1b[0m\x1b[36m123-123-1234\x1b[0m\r\n", buf)
expect("Answered 123-123-1234.\r\n", buf)
expect("---------------------\r\n", buf)
expect("select\r\n", buf)
expect("\x1b[?25l\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m \x1b[36m[? for help]\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte("?"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ We are closed weekends and avaibility is limited on Wednesday\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Friday\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days are you available:\x1b[0m\x1b[36m Monday, Friday\x1b[0m\r\n", buf)
expect("Answered [Monday Friday].\r\n", buf)
expect("---------------------\r\n", buf)
expect("select\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m \x1b[36m[? for help]\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("?"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[36mⓘ Blue is the best color, but it is your choice\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("Answered blue.\r\n", buf)
expect("---------------------\r\n", buf)
expect("password\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mEnter a secret: \x1b[0m\x1b[36m[? for help]\x1b[0m ", buf)
fh.Write([]byte("?"))
expect("*", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[36mⓘ Don't really enter a secret, this is just for testing\x1b[0m\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mEnter a secret: \x1b[0m", buf)
fh.Write([]byte("f"))
expect("*", buf)
fh.Write([]byte("o"))
expect("*", buf)
fh.Write([]byte("o"))
expect("*", buf)
fh.Write([]byte("b"))
expect("*", buf)
fh.Write([]byte("a"))
expect("*", buf)
fh.Write([]byte("r"))
expect("*", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("Answered foobar.\r\n", buf)
expect("---------------------\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-176
View File
@@ -1,176 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/input.go go run input.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "input.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("no default\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("e"))
expect("e", buf)
fh.Write([]byte("c"))
expect("c", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m\x1b[36malec\x1b[0m\r\n", buf)
expect("Answered alec.\r\n", buf)
expect("---------------------\r\n", buf)
expect("default\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m\x1b[37m(default) \x1b[0m", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m\x1b[36mdefault\x1b[0m\r\n", buf)
expect("Answered default.\r\n", buf)
expect("---------------------\r\n", buf)
expect("no help, send '?'\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m", buf)
fh.Write([]byte("?"))
expect("?", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello world \x1b[0m\x1b[36m?\x1b[0m\r\n", buf)
expect("Answered ?.\r\n", buf)
expect("---------------------\r\n", buf)
expect("input text in random location\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello \x1b[0m", buf)
fh.Write([]byte("h"))
expect("h", buf)
fh.Write([]byte("e"))
expect("e", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("o"))
expect("o", buf)
fh.Write([]byte(" "))
expect(" ", buf)
fh.Write([]byte("w"))
expect("w", buf)
fh.Write([]byte("o"))
expect("o", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("d"))
expect("d", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
fh.Write([]byte("a"))
expect("\x1b[0Kad\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("a"))
expect("\x1b[0Kalad\x1b[3D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("D"))
expect("\x1b[1D", buf)
fh.Write([]byte("\u007f"))
expect("\x1b[1D\x1b[0Kworalad\x1b[7D", buf)
fh.Write([]byte("\u007f"))
expect("\x1b[1D\x1b[0Kworalad\x1b[7D", buf)
fh.Write([]byte("\u007f"))
expect("\x1b[1D\x1b[0Kworalad\x1b[7D", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mHello \x1b[0m\x1b[36mhelworalad\x1b[0m\r\n", buf)
expect("Answered helworalad.\r\n", buf)
expect("---------------------\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-446
View File
@@ -1,446 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/multiselect.go go run multiselect.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "multiselect.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("standard\r\n", buf)
expect("\x1b[?25l\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\x1b[36m Monday, Friday\x1b[0m\r\n", buf)
expect("Answered [Monday Friday].\r\n", buf)
expect("---------------------\r\n", buf)
expect("default (sunday, tuesday)\r\n", buf)
expect("\x1b[?25l\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\x1b[36m Monday, Friday\x1b[0m\r\n", buf)
expect("Answered [Monday Friday].\r\n", buf)
expect("---------------------\r\n", buf)
expect("default not found\r\n", buf)
expect("\x1b[?25l\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\x1b[36m Monday, Friday\x1b[0m\r\n", buf)
expect("Answered [Monday Friday].\r\n", buf)
expect("---------------------\r\n", buf)
expect("no help - type ?\r\n", buf)
expect("\x1b[?25l\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("?"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[1;99m ◯ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte(" "))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Sunday\r\n", buf)
expect(" \x1b[32m ◉ \x1b[0m Monday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Tuesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Wednesday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Thursday\r\n", buf)
expect("\x1b[36m\x1b[0m\x1b[32m ◉ \x1b[0m Friday\r\n", buf)
expect(" \x1b[1;99m ◯ \x1b[0m Saturday\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat days do you prefer:\x1b[0m\x1b[36m Monday, Friday\x1b[0m\r\n", buf)
expect("Answered [Monday Friday].\r\n", buf)
expect("---------------------\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-114
View File
@@ -1,114 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/password.go go run password.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "password.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("standard\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mPlease type your password: \x1b[0m", buf)
fh.Write([]byte("f"))
expect("*", buf)
fh.Write([]byte("o"))
expect("*", buf)
fh.Write([]byte("o"))
expect("*", buf)
fh.Write([]byte("b"))
expect("*", buf)
fh.Write([]byte("a"))
expect("*", buf)
fh.Write([]byte("r"))
expect("*", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("Answered foobar.\r\n", buf)
expect("---------------------\r\n", buf)
expect("please make sure paste works\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mPlease paste your password: \x1b[0m", buf)
fh.Write([]byte("f"))
fh.Write([]byte("o"))
fh.Write([]byte("o"))
fh.Write([]byte("b"))
fh.Write([]byte("a"))
fh.Write([]byte("r"))
expect("******", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("Answered foobar.\r\n", buf)
expect("---------------------\r\n", buf)
expect("no help, send '?'\r\n", buf)
expect("\x1b[1;92m? \x1b[0m\x1b[1;99mPlease type your password: \x1b[0m", buf)
fh.Write([]byte("?"))
expect("*", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("Answered ?.\r\n", buf)
expect("---------------------\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-158
View File
@@ -1,158 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/select.go go run select.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "select.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("standard\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m red\x1b[0m\r\n", buf)
expect("Answered red.\r\n", buf)
expect("---------------------\r\n", buf)
expect("short\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m red\x1b[0m\r\n", buf)
expect("Answered red.\r\n", buf)
expect("---------------------\r\n", buf)
expect("default\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color (should default blue):\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color (should default blue):\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("Answered blue.\r\n", buf)
expect("---------------------\r\n", buf)
expect("one\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;36m hello\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\x1b[36m hello\x1b[0m\r\n", buf)
expect("Answered hello.\r\n", buf)
expect("---------------------\r\n", buf)
expect("no help, type ?\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m red\x1b[0m\r\n", buf)
expect("Answered red.\r\n", buf)
expect("---------------------\r\n", buf)
expect("passes through bottom\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\x1b[36m red\x1b[0m\r\n", buf)
expect("Answered red.\r\n", buf)
expect("---------------------\r\n", buf)
expect("passes through top\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("A"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose one:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("Answered blue.\r\n", buf)
expect("---------------------\r\n", buf)
expect("no options\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-114
View File
@@ -1,114 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// DO NOT MODIFY THIS FILE!
//
// This file was automatically generated via the commands:
//
// go get github.com/coryb/autoplay
// autoplay -n autoplay/selectThenInput.go go run selectThenInput.go
//
////////////////////////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"github.com/kr/pty"
"os"
"os/exec"
"strconv"
"strings"
)
const (
RED = "\033[31m"
RESET = "\033[0m"
)
func main() {
fh, tty, _ := pty.Open()
defer tty.Close()
defer fh.Close()
c := exec.Command("go", "run", "selectThenInput.go")
c.Stdin = tty
c.Stdout = tty
c.Stderr = tty
c.Start()
buf := bufio.NewReaderSize(fh, 1024)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;36m red\x1b[0m\r\n", buf)
expect("\x1b[1;99m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
expect("\x1b[?25l", buf)
fh.Write([]byte("\x1b"))
fh.Write([]byte("["))
fh.Write([]byte("B"))
expect("\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\r\n", buf)
expect("\x1b[1;99m red\x1b[0m\r\n", buf)
expect("\x1b[1;36m blue\x1b[0m\r\n", buf)
expect("\x1b[1;99m green\x1b[0m\r\n", buf)
fh.Write([]byte("\r"))
expect("\x1b[?25h\x1b[0G\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1F\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mChoose a color:\x1b[0m\x1b[36m blue\x1b[0m\r\n", buf)
expect("\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m", buf)
fh.Write([]byte("L"))
expect("L", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("r"))
expect("r", buf)
fh.Write([]byte("y"))
expect("y", buf)
fh.Write([]byte(" "))
expect(" ", buf)
fh.Write([]byte("W"))
expect("W", buf)
fh.Write([]byte("a"))
expect("a", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("l"))
expect("l", buf)
fh.Write([]byte("\r"))
expect("\r\r\n", buf)
expect("\x1b[1F\x1b[0G\x1b[2K\x1b[1;92m? \x1b[0m\x1b[1;99mWhat is your name? \x1b[0m\x1b[36mLarry Wall\x1b[0m\r\n", buf)
expect("Larry Wall chose blue.\r\n", buf)
c.Wait()
tty.Close()
fh.Close()
}
func expect(expected string, buf *bufio.Reader) {
sofar := []rune{}
for _, r := range expected {
got, _, _ := buf.ReadRune()
sofar = append(sofar, got)
if got != r {
fmt.Fprintln(os.Stderr, RESET)
// we want to quote the string but we also want to make the unexpected character RED
// so we use the strconv.Quote function but trim off the quoted characters so we can
// merge multiple quoted strings into one.
expStart := strings.TrimSuffix(strconv.Quote(expected[:len(sofar)-1]), "\"")
expMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(expected[len(sofar)-1])), "\""), "\"")
expEnd := strings.TrimPrefix(strconv.Quote(expected[len(sofar):]), "\"")
fmt.Fprintf(os.Stderr, "Expected: %s%s%s%s%s\n", expStart, RED, expMiss, RESET, expEnd)
// read the rest of the buffer
p := make([]byte, buf.Buffered())
buf.Read(p)
gotStart := strings.TrimSuffix(strconv.Quote(string(sofar[:len(sofar)-1])), "\"")
gotMiss := strings.TrimSuffix(strings.TrimPrefix(strconv.Quote(string(sofar[len(sofar)-1])), "\""), "\"")
gotEnd := strings.TrimPrefix(strconv.Quote(string(p)), "\"")
fmt.Fprintf(os.Stderr, "Got: %s%s%s%s%s\n", gotStart, RED, gotMiss, RESET, gotEnd)
panic(fmt.Errorf("Unexpected Rune %q, Expected %q\n", got, r))
} else {
fmt.Printf("%c", r)
}
}
}
-43
View File
@@ -1,43 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var answer = false
var goodTable = []TestUtil.TestTableEntry{
{
"Enter 'yes'", &survey.Confirm{
Message: "yes:",
}, &answer,
},
{
"Enter 'no'", &survey.Confirm{
Message: "yes:",
}, &answer,
},
{
"default", &survey.Confirm{
Message: "yes:",
Default: true,
}, &answer,
},
{
"not recognized (enter random letter)", &survey.Confirm{
Message: "yes:",
Default: true,
}, &answer,
},
{
"no help - type '?'", &survey.Confirm{
Message: "yes:",
Default: true,
}, &answer,
},
}
func main() {
TestUtil.RunTable(goodTable)
}
-42
View File
@@ -1,42 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
var simpleQs = []*survey.Question{
{
Name: "color",
Prompt: &survey.Select{
Message: "select1:",
Options: []string{"red", "blue", "green"},
},
Validate: survey.Required,
},
{
Name: "color2",
Prompt: &survey.Select{
Message: "select2:",
Options: []string{"red", "blue", "green"},
},
Validate: survey.Required,
},
}
func main() {
answers := struct {
Color string
Color2 string
}{}
// ask the question
err := survey.Ask(simpleQs, &answers)
if err != nil {
fmt.Println(err.Error())
return
}
// print the answers
fmt.Printf("%s and %s.\n", answers.Color, answers.Color2)
}
-55
View File
@@ -1,55 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var (
confirmAns = false
inputAns = ""
multiselectAns = []string{}
selectAns = ""
passwordAns = ""
)
var goodTable = []TestUtil.TestTableEntry{
{
"confirm", &survey.Confirm{
Message: "Is it raining?",
Help: "Go outside, if your head becomes wet the answer is probably 'yes'",
}, &confirmAns,
},
{
"input", &survey.Input{
Message: "What is your phone number:",
Help: "Phone number should include the area code, parentheses optional",
}, &inputAns,
},
{
"select", &survey.MultiSelect{
Message: "What days are you available:",
Help: "We are closed weekends and avaibility is limited on Wednesday",
Options: []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"},
Default: []string{"Monday", "Tuesday", "Thursday", "Friday"},
}, &multiselectAns,
},
{
"select", &survey.Select{
Message: "Choose a color:",
Help: "Blue is the best color, but it is your choice",
Options: []string{"red", "blue", "green"},
Default: "blue",
}, &selectAns,
},
{
"password", &survey.Password{
Message: "Enter a secret:",
Help: "Don't really enter a secret, this is just for testing",
}, &passwordAns,
},
}
func main() {
TestUtil.RunTable(goodTable)
}
-27
View File
@@ -1,27 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var val = ""
var table = []TestUtil.TestTableEntry{
{
"no default", &survey.Input{Message: "Hello world"}, &val,
},
{
"default", &survey.Input{Message: "Hello world", Default: "default"}, &val,
},
{
"no help, send '?'", &survey.Input{Message: "Hello world"}, &val,
},
{
"input text in random location", &survey.Input{Message: "Hello"}, &val,
},
}
func main() {
TestUtil.RunTable(table)
}
-23
View File
@@ -1,23 +0,0 @@
package main
import "github.com/AlecAivazis/survey"
func main() {
color := ""
prompt := &survey.Select{
Message: "Choose a color:",
Options: []string{
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
},
}
survey.AskOne(prompt, &color, nil)
}
-42
View File
@@ -1,42 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var answer = []string{}
var table = []TestUtil.TestTableEntry{
{
"standard", &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
}, &answer,
},
{
"default (sunday, tuesday)", &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
Default: []string{"Sunday", "Tuesday"},
}, &answer,
},
{
"default not found", &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
Default: []string{"Sundayaa"},
}, &answer,
},
{
"no help - type ?", &survey.MultiSelect{
Message: "What days do you prefer:",
Options: []string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
Default: []string{"Sundayaa"},
}, &answer,
},
}
func main() {
TestUtil.RunTable(table)
}
-24
View File
@@ -1,24 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var value = ""
var table = []TestUtil.TestTableEntry{
{
"standard", &survey.Password{Message: "Please type your password:"}, &value,
},
{
"please make sure paste works", &survey.Password{Message: "Please paste your password:"}, &value,
},
{
"no help, send '?'", &survey.Password{Message: "Please type your password:"}, &value,
},
}
func main() {
TestUtil.RunTable(table)
}
-67
View File
@@ -1,67 +0,0 @@
package main
import (
"github.com/AlecAivazis/survey"
"github.com/AlecAivazis/survey/tests/util"
)
var answer = ""
var goodTable = []TestUtil.TestTableEntry{
{
"standard", &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
}, &answer,
},
{
"short", &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue"},
}, &answer,
},
{
"default", &survey.Select{
Message: "Choose a color (should default blue):",
Options: []string{"red", "blue", "green"},
Default: "blue",
}, &answer,
},
{
"one", &survey.Select{
Message: "Choose one:",
Options: []string{"hello"},
}, &answer,
},
{
"no help, type ?", &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue"},
}, &answer,
},
{
"passes through bottom", &survey.Select{
Message: "Choose one:",
Options: []string{"red", "blue"},
}, &answer,
},
{
"passes through top", &survey.Select{
Message: "Choose one:",
Options: []string{"red", "blue"},
}, &answer,
},
}
var badTable = []TestUtil.TestTableEntry{
{
"no options", &survey.Select{
Message: "Choose one:",
}, &answer,
},
}
func main() {
TestUtil.RunTable(goodTable)
TestUtil.RunErrorTable(badTable)
}
-42
View File
@@ -1,42 +0,0 @@
package main
import (
"fmt"
"github.com/AlecAivazis/survey"
)
// the questions to ask
var simpleQs = []*survey.Question{
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
},
Validate: survey.Required,
},
{
Name: "name",
Prompt: &survey.Input{
Message: "What is your name?",
},
Validate: survey.Required,
},
}
func main() {
answers := struct {
Color string
Name string
}{}
// ask the question
err := survey.Ask(simpleQs, &answers)
if err != nil {
fmt.Println(err.Error())
return
}
// print the answers
fmt.Printf("%s chose %s.\n", answers.Name, answers.Color)
}
-50
View File
@@ -1,50 +0,0 @@
package TestUtil
import (
"fmt"
"reflect"
"github.com/AlecAivazis/survey"
)
type TestTableEntry struct {
Name string
Prompt survey.Prompt
Value interface{}
}
func formatAnswer(ans interface{}) {
// show the answer to the user
fmt.Printf("Answered %v.\n", reflect.ValueOf(ans).Elem())
fmt.Println("---------------------")
}
func RunTable(table []TestTableEntry) {
// go over every entry in the table
for _, entry := range table {
// tell the user what we are going to ask them
fmt.Println(entry.Name)
// perform the ask
err := survey.AskOne(entry.Prompt, entry.Value, nil)
if err != nil {
fmt.Printf("AskOne on %v's prompt failed: %v.", entry.Name, err.Error())
break
}
// show the answer to the user
formatAnswer(entry.Value)
}
}
func RunErrorTable(table []TestTableEntry) {
// go over every entry in the table
for _, entry := range table {
// tell the user what we are going to ask them
fmt.Println(entry.Name)
// perform the ask
err := survey.AskOne(entry.Prompt, entry.Value, nil)
if err == nil {
fmt.Printf("AskOne on %v's prompt didn't fail.", entry.Name)
break
}
}
}
-2
View File
@@ -1,2 +0,0 @@
{{define "x"}}TEXT{{end}}
{{define "dotV"}}{{.V}}{{end}}
-2
View File
@@ -1,2 +0,0 @@
{{define "dot"}}{{.}}{{end}}
{{define "nested"}}{{template "dot" .}}{{end}}
-3
View File
@@ -1,3 +0,0 @@
template1
{{define "x"}}x{{end}}
{{template "y"}}
-3
View File
@@ -1,3 +0,0 @@
template2
{{define "y"}}y{{end}}
{{template "x"}}
-12
View File
@@ -1,12 +0,0 @@
package math
import "github.com/cheekybits/genny/generic"
type ThisNumberType generic.Number
func ThisNumberTypeMax(fn func(a, b ThisNumberType) bool, a, b ThisNumberType) ThisNumberType {
if fn(a, b) {
return a
}
return b
}
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
cat ./generic_max.go | ../../genny gen "NumberType=NUMBERS" > numbers_max_get.go
cat ./func_thing.go | ../../genny gen "ThisNumberType=NUMBERS" > numbers_func_thing.go
-14
View File
@@ -1,14 +0,0 @@
package math
import "github.com/cheekybits/genny/generic"
type NumberType generic.Number
// NumberTypeMax gets the maximum number from the
// two specified.
func NumberTypeMax(a, b NumberType) NumberType {
if a > b {
return a
}
return b
}
-27
View File
@@ -1,27 +0,0 @@
package math_test
import (
"testing"
"github.com/cheekybits/genny/examples/davechaney"
)
func TestNumberTypeMax(t *testing.T) {
var v math.NumberType
v = math.NumberTypeMax(10, 20)
if v != 20 {
t.Errorf("Max of 10 and 20 is 20")
}
v = math.NumberTypeMax(20, 20)
if v != 20 {
t.Errorf("Max of 20 and 20 is 20")
}
v = math.NumberTypeMax(25, 20)
if v != 25 {
t.Errorf("Max of 25 and 20 is 25")
}
}
@@ -1,89 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package math
func Float32Max(fn func(a, b float32) bool, a, b float32) float32 {
if fn(a, b) {
return a
}
return b
}
func Float64Max(fn func(a, b float64) bool, a, b float64) float64 {
if fn(a, b) {
return a
}
return b
}
func IntMax(fn func(a, b int) bool, a, b int) int {
if fn(a, b) {
return a
}
return b
}
func Int16Max(fn func(a, b int16) bool, a, b int16) int16 {
if fn(a, b) {
return a
}
return b
}
func Int32Max(fn func(a, b int32) bool, a, b int32) int32 {
if fn(a, b) {
return a
}
return b
}
func Int64Max(fn func(a, b int64) bool, a, b int64) int64 {
if fn(a, b) {
return a
}
return b
}
func Int8Max(fn func(a, b int8) bool, a, b int8) int8 {
if fn(a, b) {
return a
}
return b
}
func UintMax(fn func(a, b uint) bool, a, b uint) uint {
if fn(a, b) {
return a
}
return b
}
func Uint16Max(fn func(a, b uint16) bool, a, b uint16) uint16 {
if fn(a, b) {
return a
}
return b
}
func Uint32Max(fn func(a, b uint32) bool, a, b uint32) uint32 {
if fn(a, b) {
return a
}
return b
}
func Uint64Max(fn func(a, b uint64) bool, a, b uint64) uint64 {
if fn(a, b) {
return a
}
return b
}
func Uint8Max(fn func(a, b uint8) bool, a, b uint8) uint8 {
if fn(a, b) {
return a
}
return b
}
@@ -1,29 +0,0 @@
// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny
package gogenerate
type StringStringMap map[string]string
func NewStringStringMap() map[string]string {
return make(map[string]string)
}
type StringIntMap map[string]int
func NewStringIntMap() map[string]int {
return make(map[string]int)
}
type IntStringMap map[int]string
func NewIntStringMap() map[int]string {
return make(map[int]string)
}
type IntIntMap map[int]int
func NewIntIntMap() map[int]int {
return make(map[int]int)
}
-14
View File
@@ -1,14 +0,0 @@
package gogenerate
import "github.com/cheekybits/genny/generic"
//go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "KeyType=string,int ValueType=string,int"
type KeyType generic.Type
type ValueType generic.Type
type KeyTypeValueTypeMap map[KeyType]ValueType
func NewKeyTypeValueTypeMap() map[KeyType]ValueType {
return make(map[KeyType]ValueType)
}

Some files were not shown because too many files have changed in this diff Show More