You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/04/11 00:21:43 UTC

[cloudstack-cloudmonkey] branch master updated: vendor: introduce vendoring and build system

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack-cloudmonkey.git


The following commit(s) were added to refs/heads/master by this push:
     new c4ff588  vendor: introduce vendoring and build system
c4ff588 is described below

commit c4ff588f4efddb1cf3b0bee3109cb0ee043391a0
Author: Rohit Yadav <ro...@apache.org>
AuthorDate: Wed Apr 11 05:49:09 2018 +0530

    vendor: introduce vendoring and build system
    
    - Adds vendor and dependencies
    - Improved build system (Makefile based from
      https://github.com/vincentbernat/hellogopher)
    - GOPATH free, no need to have source put in $GOPATH run/build from
      anywhere
    
    Signed-off-by: Rohit Yadav <ro...@apache.org>
---
 .gitignore                                         |   2 +
 Makefile                                           | 158 +++-
 README.md                                          |  33 +-
 cli/completer.go                                   |   4 +-
 cli/exec.go                                        |   4 +-
 cli/selector.go                                    |  12 +-
 cli/shell.go                                       |   2 +-
 cmd/api.go                                         |   1 -
 cmd/network.go                                     |   1 -
 cmd/request.go                                     |   2 +-
 cmd/sync.go                                        |   1 -
 cmk.go                                             |   4 +-
 vendor/github.com/chzyer/readline/ansi_windows.go  | 249 ++++++
 vendor/github.com/chzyer/readline/complete.go      | 285 ++++++
 .../github.com/chzyer/readline/complete_helper.go  | 165 ++++
 .../github.com/chzyer/readline/complete_segment.go |  82 ++
 vendor/github.com/chzyer/readline/history.go       | 330 +++++++
 vendor/github.com/chzyer/readline/operation.go     | 531 +++++++++++
 vendor/github.com/chzyer/readline/password.go      |  33 +
 .../chzyer/readline/rawreader_windows.go           | 125 +++
 vendor/github.com/chzyer/readline/readline.go      | 326 +++++++
 vendor/github.com/chzyer/readline/remote.go        | 475 ++++++++++
 vendor/github.com/chzyer/readline/runebuf.go       | 629 +++++++++++++
 vendor/github.com/chzyer/readline/runes.go         | 223 +++++
 vendor/github.com/chzyer/readline/runes/runes.go   | 155 ++++
 vendor/github.com/chzyer/readline/search.go        | 164 ++++
 vendor/github.com/chzyer/readline/std.go           | 197 +++++
 vendor/github.com/chzyer/readline/std_windows.go   |   9 +
 vendor/github.com/chzyer/readline/term.go          | 123 +++
 vendor/github.com/chzyer/readline/term_bsd.go      |  29 +
 vendor/github.com/chzyer/readline/term_linux.go    |  33 +
 vendor/github.com/chzyer/readline/term_solaris.go  |  32 +
 vendor/github.com/chzyer/readline/term_unix.go     |  24 +
 vendor/github.com/chzyer/readline/term_windows.go  | 171 ++++
 vendor/github.com/chzyer/readline/terminal.go      | 238 +++++
 vendor/github.com/chzyer/readline/utils.go         | 277 ++++++
 vendor/github.com/chzyer/readline/utils_unix.go    |  83 ++
 vendor/github.com/chzyer/readline/utils_windows.go |  41 +
 vendor/github.com/chzyer/readline/vim.go           | 176 ++++
 vendor/github.com/chzyer/readline/windows_api.go   | 152 ++++
 vendor/github.com/juju/ansiterm/attribute.go       |  50 ++
 vendor/github.com/juju/ansiterm/color.go           | 119 +++
 vendor/github.com/juju/ansiterm/context.go         |  95 ++
 vendor/github.com/juju/ansiterm/doc.go             |   6 +
 vendor/github.com/juju/ansiterm/style.go           |  72 ++
 vendor/github.com/juju/ansiterm/tabwriter.go       |  64 ++
 .../juju/ansiterm/tabwriter/tabwriter.go           | 587 ++++++++++++
 vendor/github.com/juju/ansiterm/terminal.go        |  32 +
 vendor/github.com/juju/ansiterm/writer.go          |  74 ++
 vendor/github.com/lunixbochs/vtclean/io.go         |  93 ++
 vendor/github.com/lunixbochs/vtclean/line.go       | 113 +++
 vendor/github.com/lunixbochs/vtclean/vtclean.go    |  88 ++
 .../lunixbochs/vtclean/vtclean/vtclean.go          |  17 +
 vendor/github.com/manifoldco/promptui/codes.go     | 108 +++
 vendor/github.com/manifoldco/promptui/keycodes.go  |  25 +
 .../manifoldco/promptui/keycodes_windows.go        |  25 +
 vendor/github.com/manifoldco/promptui/list/list.go | 197 +++++
 vendor/github.com/manifoldco/promptui/prompt.go    | 338 +++++++
 vendor/github.com/manifoldco/promptui/promptui.go  |  18 +
 .../manifoldco/promptui/screenbuf/screenbuf.go     | 138 +++
 vendor/github.com/manifoldco/promptui/select.go    | 503 +++++++++++
 vendor/github.com/manifoldco/promptui/styles.go    |  12 +
 .../manifoldco/promptui/styles_windows.go          |  10 +
 vendor/github.com/mattn/go-colorable/.travis.yml   |   9 +
 vendor/github.com/mattn/go-colorable/LICENSE       |  21 +
 vendor/github.com/mattn/go-colorable/README.md     |  48 +
 .../mattn/go-colorable/cmd/colorable/colorable.go  |  12 +
 .../mattn/go-colorable/colorable_appengine.go      |  29 +
 .../mattn/go-colorable/colorable_others.go         |  30 +
 .../mattn/go-colorable/colorable_windows.go        | 980 +++++++++++++++++++++
 .../github.com/mattn/go-colorable/noncolorable.go  |  55 ++
 vendor/github.com/mattn/go-isatty/.travis.yml      |  13 +
 vendor/github.com/mattn/go-isatty/LICENSE          |   9 +
 vendor/github.com/mattn/go-isatty/README.md        |  50 ++
 vendor/github.com/mattn/go-isatty/doc.go           |   2 +
 .../github.com/mattn/go-isatty/isatty_appengine.go |  15 +
 vendor/github.com/mattn/go-isatty/isatty_bsd.go    |  18 +
 vendor/github.com/mattn/go-isatty/isatty_linux.go  |  18 +
 .../mattn/go-isatty/isatty_linux_ppc64x.go         |  19 +
 vendor/github.com/mattn/go-isatty/isatty_others.go |  10 +
 .../github.com/mattn/go-isatty/isatty_solaris.go   |  16 +
 .../github.com/mattn/go-isatty/isatty_windows.go   |  94 ++
 vendor/github.com/mattn/go-shellwords/.travis.yml  |   8 +
 vendor/github.com/mattn/go-shellwords/LICENSE      |  21 +
 vendor/github.com/mattn/go-shellwords/README.md    |  47 +
 .../github.com/mattn/go-shellwords/shellwords.go   | 178 ++++
 vendor/github.com/mattn/go-shellwords/util_go15.go |  24 +
 .../github.com/mattn/go-shellwords/util_posix.go   |  22 +
 .../github.com/mattn/go-shellwords/util_windows.go |  22 +
 vendor/github.com/mitchellh/go-homedir/LICENSE     |  21 +
 vendor/github.com/mitchellh/go-homedir/README.md   |  14 +
 vendor/github.com/mitchellh/go-homedir/homedir.go  | 137 +++
 vendor/github.com/rhtyd/readline/ansi_windows.go   | 249 ++++++
 vendor/github.com/rhtyd/readline/complete.go       | 285 ++++++
 .../github.com/rhtyd/readline/complete_helper.go   | 165 ++++
 .../github.com/rhtyd/readline/complete_segment.go  |  82 ++
 vendor/github.com/rhtyd/readline/history.go        | 330 +++++++
 vendor/github.com/rhtyd/readline/operation.go      | 531 +++++++++++
 vendor/github.com/rhtyd/readline/password.go       |  33 +
 .../github.com/rhtyd/readline/rawreader_windows.go | 125 +++
 vendor/github.com/rhtyd/readline/readline.go       | 326 +++++++
 vendor/github.com/rhtyd/readline/remote.go         | 475 ++++++++++
 vendor/github.com/rhtyd/readline/runebuf.go        | 629 +++++++++++++
 vendor/github.com/rhtyd/readline/runes.go          | 224 +++++
 vendor/github.com/rhtyd/readline/runes/runes.go    | 155 ++++
 vendor/github.com/rhtyd/readline/search.go         | 164 ++++
 vendor/github.com/rhtyd/readline/std.go            | 197 +++++
 vendor/github.com/rhtyd/readline/std_windows.go    |   9 +
 vendor/github.com/rhtyd/readline/term.go           | 123 +++
 vendor/github.com/rhtyd/readline/term_bsd.go       |  29 +
 vendor/github.com/rhtyd/readline/term_linux.go     |  33 +
 vendor/github.com/rhtyd/readline/term_solaris.go   |  32 +
 vendor/github.com/rhtyd/readline/term_unix.go      |  24 +
 vendor/github.com/rhtyd/readline/term_windows.go   | 171 ++++
 vendor/github.com/rhtyd/readline/terminal.go       | 238 +++++
 vendor/github.com/rhtyd/readline/utils.go          | 277 ++++++
 vendor/github.com/rhtyd/readline/utils_unix.go     |  83 ++
 vendor/github.com/rhtyd/readline/utils_windows.go  |  41 +
 vendor/github.com/rhtyd/readline/vim.go            | 176 ++++
 vendor/github.com/rhtyd/readline/windows_api.go    | 152 ++++
 120 files changed, 15606 insertions(+), 59 deletions(-)

diff --git a/.gitignore b/.gitignore
index bdce524..0cbfde4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,9 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
+bin
 cmk
 dist
 *.exe
 *.test
 *.out
+.gopath~
 .idea
diff --git a/Makefile b/Makefile
index fda6cce..41184d9 100644
--- a/Makefile
+++ b/Makefile
@@ -15,41 +15,141 @@
 # specific language governing permissions and limitations
 # under the License.
 
-build:
-	go build -ldflags='-s -w' -o cmk cmk.go
+# Makefile referenced from github.com/vincentbernat/hellogopher
+PACKAGE  = cloudmonkey
+DATE    ?= $(shell date +%FT%T%z)
+VERSION ?= $(shell git describe --tags --always --dirty --match=v* 2> /dev/null || \
+			cat $(CURDIR)/.version 2> /dev/null || echo v0)
+GOPATH   = $(CURDIR)/.gopath~
+BIN      = $(GOPATH)/bin
+BASE     = $(GOPATH)/src/$(PACKAGE)
+PKGS     = $(or $(PKG),$(shell cd $(BASE) && env GOPATH=$(GOPATH) $(GO) list ./... | grep -v "^$(PACKAGE)/vendor/"))
+TESTPKGS = $(shell env GOPATH=$(GOPATH) $(GO) list -f '{{ if or .TestGoFiles .XTestGoFiles }}{{ .ImportPath }}{{ end }}' $(PKGS))
 
-run:
-	go run cmk.go
+GO      = go
+GODOC   = godoc
+GOFMT   = gofmt
+TIMEOUT = 15
+V = 0
+Q = $(if $(filter 1,$V),,@)
+M = $(shell printf "\033[34;1m▶\033[0m ")
 
-test:
-	go test
+.PHONY: all
+all: fmt vendor | $(BASE) ; $(info $(M) Building executable…) @ ## Build program binary
+	$Q cd $(BASE) && $(GO) build \
+		-tags release \
+		-ldflags '-s -w -X $(PACKAGE)/cmd.Version=$(VERSION) -X $(PACKAGE)/cmd.BuildDate=$(DATE)' \
+		-o bin/$(PACKAGE) cmk.go
+	$(info $(M) Done!) @
 
-install: build
-	@echo Copied to ~/bin
-	@cp cmk ~/bin
+$(BASE): ; $(info $(M) Setting GOPATH…)
+	@mkdir -p $(dir $@)
+	@ln -sf $(CURDIR) $@
 
-debug:
-	go build -gcflags='-N -l' -o cmk cmk.go &&  dlv --listen=:2345 --headless=true --api-version=2 exec ./cmk
+run: all
+	./bin/cloudmonkey
+
+debug: all
+	$(GO) build -gcflags='-N -l' -o cmk cmk.go &&  dlv --listen=:2345 --headless=true --api-version=2 exec ./bin/cloudmonkey
 
 dist:
+	cd $(BASE)
 	rm -fr dist
 	mkdir -p dist
-	GOOS=linux   GOARCH=amd64 go build -ldflags='-s -w' -o dist/cmk-linux-amd64 cmk.go
-	GOOS=linux   GOARCH=386   go build -ldflags='-s -w' -o dist/cmk-linux-i386 cmk.go
-	GOOS=linux   GOARCH=arm64 go build -ldflags='-s -w' -o dist/cmk-linux-arm64 cmk.go
-	GOOS=linux   GOARCH=arm   go build -ldflags='-s -w' -o dist/cmk-linux-arm cmk.go
-	GOOS=windows GOARCH=amd64 go build -ldflags='-s -w' -o dist/cmk-x64.exe cmk.go
-	GOOS=windows GOARCH=386   go build -ldflags='-s -w' -o dist/cmk-x32.exe cmk.go
-	GOOS=darwin  GOARCH=amd64 go build -ldflags='-s -w' -o dist/cmk-mac64.bin cmk.go
-	GOOS=darwin  GOARCH=386   go build -ldflags='-s -w' -o dist/cmk-mac32.bin cmk.go
-
-clean:
-	@rm -f cmk
-	@rm -fr dist
-
-deps:
-	go get -u github.com/rhtyd/readline
-	go get -u github.com/mitchellh/go-homedir
-	go get -u github.com/mattn/go-shellwords
-	go get -u github.com/manifoldco/promptui
+	GOOS=linux   GOARCH=amd64 $(GO) build -ldflags='-s -w' -o dist/cmk-linux-amd64 cmk.go
+	GOOS=linux   GOARCH=386   $(GO) build -ldflags='-s -w' -o dist/cmk-linux-i386 cmk.go
+	GOOS=linux   GOARCH=arm64 $(GO) build -ldflags='-s -w' -o dist/cmk-linux-arm64 cmk.go
+	GOOS=linux   GOARCH=arm   $(GO) build -ldflags='-s -w' -o dist/cmk-linux-arm cmk.go
+	GOOS=windows GOARCH=amd64 $(GO) build -ldflags='-s -w' -o dist/cmk-x64.exe cmk.go
+	GOOS=windows GOARCH=386   $(GO) build -ldflags='-s -w' -o dist/cmk-x32.exe cmk.go
+	GOOS=darwin  GOARCH=amd64 $(GO) build -ldflags='-s -w' -o dist/cmk-mac64.bin cmk.go
+	GOOS=darwin  GOARCH=386   $(GO) build -ldflags='-s -w' -o dist/cmk-mac32.bin cmk.go
+
+# Tools
+
+GOLINT = $(BIN)/golint
+$(BIN)/golint: | $(BASE) ; $(info $(M) Building golint…)
+	$Q go get github.com/golang/lint/golint
+
+GOCOVMERGE = $(BIN)/gocovmerge
+$(BIN)/gocovmerge: | $(BASE) ; $(info $(M) building gocovmerge…)
+	$Q go get github.com/wadey/gocovmerge
+
+GOCOV = $(BIN)/gocov
+$(BIN)/gocov: | $(BASE) ; $(info $(M) building gocov…)
+	$Q go get github.com/axw/gocov/...
+
+GOCOVXML = $(BIN)/gocov-xml
+$(BIN)/gocov-xml: | $(BASE) ; $(info $(M) building gocov-xml…)
+	$Q go get github.com/AlekSi/gocov-xml
+
+GO2XUNIT = $(BIN)/go2xunit
+$(BIN)/go2xunit: | $(BASE) ; $(info $(M) Building go2xunit…)
+	$Q go get github.com/tebeka/go2xunit
+
+# Tests
+
+TEST_TARGETS := test-default test-bench test-short test-verbose test-race
+.PHONY: $(TEST_TARGETS) test-xml check test tests
+test-bench:   ARGS=-run=__absolutelynothing__ -bench=. ## Run benchmarks
+test-short:   ARGS=-short        ## Run only short tests
+test-verbose: ARGS=-v            ## Run tests in verbose mode with coverage reporting
+test-race:    ARGS=-race         ## Run tests with race detector
+$(TEST_TARGETS): NAME=$(MAKECMDGOALS:test-%=%)
+$(TEST_TARGETS): test
+check test tests: fmt lint vendor | $(BASE) ; $(info $(M) Running $(NAME:%=% )tests…) @ ## Run tests
+	$Q cd $(BASE) && $(GO) test -timeout $(TIMEOUT)s $(ARGS) $(TESTPKGS)
+
+test-xml: fmt lint vendor | $(BASE) $(GO2XUNIT) ; $(info $(M) Running $(NAME:%=% )tests…) @ ## Run tests with xUnit output
+	$Q cd $(BASE) && 2>&1 $(GO) test -timeout 20s -v $(TESTPKGS) | tee test/tests.output
+	$(GO2XUNIT) -fail -input test/tests.output -output test/tests.xml
+
+COVERAGE_MODE = atomic
+COVERAGE_PROFILE = $(COVERAGE_DIR)/profile.out
+COVERAGE_XML = $(COVERAGE_DIR)/coverage.xml
+COVERAGE_HTML = $(COVERAGE_DIR)/index.html
+.PHONY: test-coverage test-coverage-tools
+test-coverage-tools: | $(GOCOVMERGE) $(GOCOV) $(GOCOVXML)
+test-coverage: COVERAGE_DIR := $(CURDIR)/test/coverage.$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
+test-coverage: fmt lint vendor test-coverage-tools | $(BASE) ; $(info $(M) Running coverage tests…) @ ## Run coverage tests
+	$Q mkdir -p $(COVERAGE_DIR)/coverage
+	$Q cd $(BASE) && for pkg in $(TESTPKGS); do \
+		$(GO) test \
+			-coverpkg=$$($(GO) list -f '{{ join .Deps "\n" }}' $$pkg | \
+					grep '^$(PACKAGE)/' | grep -v '^$(PACKAGE)/vendor/' | \
+					tr '\n' ',')$$pkg \
+			-covermode=$(COVERAGE_MODE) \
+			-coverprofile="$(COVERAGE_DIR)/coverage/`echo $$pkg | tr "/" "-"`.cover" $$pkg ;\
+	 done
+	$Q $(GOCOVMERGE) $(COVERAGE_DIR)/coverage/*.cover > $(COVERAGE_PROFILE)
+	$Q $(GO) tool cover -html=$(COVERAGE_PROFILE) -o $(COVERAGE_HTML)
+	$Q $(GOCOV) convert $(COVERAGE_PROFILE) | $(GOCOVXML) > $(COVERAGE_XML)
+
+.PHONY: lint
+lint: vendor | $(BASE) $(GOLINT) ; $(info $(M) Running golint…) @ ## Run golint
+	$Q cd $(BASE) && ret=0 && for pkg in $(PKGS); do \
+		test -z "$$($(GOLINT) $$pkg | tee /dev/stderr)" || ret=1 ; \
+	 done ; exit $$ret
+
+.PHONY: fmt
+fmt: ; $(info $(M) Running gofmt…) @ ## Run gofmt on all source files
+	@ret=0 && for d in $$($(GO) list -f '{{.Dir}}' ./... | grep -v /vendor/); do \
+		$(GOFMT) -l -w $$d/*.go || ret=$$? ; \
+	 done ; exit $$ret
+
+# Misc
+
+.PHONY: clean
+clean: ; $(info $(M) Cleaning…)	@
+	@rm -rf $(GOPATH)
+	@rm -rf bin dist
+	@rm -rf test/tests.* test/coverage.*
+
+.PHONY: help
+help:
+	@grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
+		awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
 
+.PHONY: version
+version:
+	@echo cloudmonkey-$(VERSION)
diff --git a/README.md b/README.md
index 9f76029..6a4d002 100644
--- a/README.md
+++ b/README.md
@@ -20,25 +20,32 @@ For legacy cloudmonkey, please see the [cwiki usage page](https://cwiki.apache.o
 
 ### Development
 
-Build:
-
-    $ make build
-
-Run:
-
-    $ ./cmk
+The following are various make targets you can run:
+
+    $ make help
+
+      all               Build program binary
+      run               Builds and runs cloudmonkey
+      dist              Builds release for various targets
+      clean             Cleans build artifacts
+      lint              Run golint
+      fmt               Run gofmt on all source files
+      check test tests  Run tests
+      test-bench        Run benchmarks
+      test-short        Run only short tests
+      test-verbose      Run tests in verbose mode with coverage reporting
+      test-race         Run tests with race detector
+      test-xml          Run tests with xUnit output
+      test-coverage     Run coverage tests
 
 Build and run:
 
     $ make run
 
-Clean:
-
-    $ make clean
-
-Install:
+Build and run manually:
 
-    $ make install
+    $ make all
+    $ ./bin/cloudmonkey
 
 ### Community
 
diff --git a/cli/completer.go b/cli/completer.go
index ced72f4..ba45391 100644
--- a/cli/completer.go
+++ b/cli/completer.go
@@ -23,8 +23,8 @@ import (
 	"strings"
 	"unicode"
 
-	"../cmd"
-	"../config"
+	"cloudmonkey/cmd"
+	"cloudmonkey/config"
 
 	"github.com/rhtyd/readline/runes"
 )
diff --git a/cli/exec.go b/cli/exec.go
index 99b1735..ab06f0d 100644
--- a/cli/exec.go
+++ b/cli/exec.go
@@ -18,8 +18,8 @@
 package cli
 
 import (
-	"../cmd"
-	"../config"
+	"cloudmonkey/cmd"
+	"cloudmonkey/config"
 	"github.com/rhtyd/readline"
 )
 
diff --git a/cli/selector.go b/cli/selector.go
index 209cb56..5cf35af 100644
--- a/cli/selector.go
+++ b/cli/selector.go
@@ -64,11 +64,11 @@ func ShowSelector() string {
 	}
 
 	prompt := promptui.Select{
-		Label:     "Use the arrow keys to navigate: ↓ ↑ → ←  and / toggles search",
-		Items:     options,
-		Templates: templates,
-		Size:      5,
-		Searcher:  searcher,
+		Label:             "Use the arrow keys to navigate: ↓ ↑ → ←  and / toggles search",
+		Items:             options,
+		Templates:         templates,
+		Size:              5,
+		Searcher:          searcher,
 		StartInSearchMode: true,
 		Keys: &promptui.SelectKeys{
 			Prev:     promptui.Key{Code: readline.CharPrev, Display: "↑"},
@@ -87,4 +87,4 @@ func ShowSelector() string {
 	}
 
 	return options[i].Id
-}
\ No newline at end of file
+}
diff --git a/cli/shell.go b/cli/shell.go
index 9477db6..593c13d 100644
--- a/cli/shell.go
+++ b/cli/shell.go
@@ -22,7 +22,7 @@ import (
 	"io"
 	"strings"
 
-	"../config"
+	"cloudmonkey/config"
 	"github.com/mattn/go-shellwords"
 
 	"github.com/rhtyd/readline"
diff --git a/cmd/api.go b/cmd/api.go
index 57a34e0..4be24e3 100644
--- a/cmd/api.go
+++ b/cmd/api.go
@@ -22,7 +22,6 @@ import (
 	"errors"
 	"fmt"
 	"strings"
-
 )
 
 var apiCommand *Command
diff --git a/cmd/network.go b/cmd/network.go
index 97ccc42..352afd9 100644
--- a/cmd/network.go
+++ b/cmd/network.go
@@ -30,7 +30,6 @@ import (
 	"net/url"
 	"sort"
 	"strings"
-
 )
 
 func encodeRequestParams(params url.Values) string {
diff --git a/cmd/request.go b/cmd/request.go
index 294dfd7..70b7023 100644
--- a/cmd/request.go
+++ b/cmd/request.go
@@ -18,7 +18,7 @@
 package cmd
 
 import (
-	"../config"
+	"cloudmonkey/config"
 	"github.com/rhtyd/readline"
 )
 
diff --git a/cmd/sync.go b/cmd/sync.go
index 599d304..3bad31e 100644
--- a/cmd/sync.go
+++ b/cmd/sync.go
@@ -19,7 +19,6 @@ package cmd
 
 import (
 	"fmt"
-
 )
 
 func init() {
diff --git a/cmk.go b/cmk.go
index 0febd0f..68fcb3d 100644
--- a/cmk.go
+++ b/cmk.go
@@ -20,8 +20,8 @@ package main
 import (
 	"os"
 
-	"./config"
-	"./cli"
+	"cloudmonkey/cli"
+	"cloudmonkey/config"
 )
 
 func main() {
diff --git a/vendor/github.com/chzyer/readline/ansi_windows.go b/vendor/github.com/chzyer/readline/ansi_windows.go
new file mode 100644
index 0000000..63b908c
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/ansi_windows.go
@@ -0,0 +1,249 @@
+// +build windows
+
+package readline
+
+import (
+	"bufio"
+	"io"
+	"strconv"
+	"strings"
+	"sync"
+	"unicode/utf8"
+	"unsafe"
+)
+
+const (
+	_                = uint16(0)
+	COLOR_FBLUE      = 0x0001
+	COLOR_FGREEN     = 0x0002
+	COLOR_FRED       = 0x0004
+	COLOR_FINTENSITY = 0x0008
+
+	COLOR_BBLUE      = 0x0010
+	COLOR_BGREEN     = 0x0020
+	COLOR_BRED       = 0x0040
+	COLOR_BINTENSITY = 0x0080
+
+	COMMON_LVB_UNDERSCORE = 0x8000
+	COMMON_LVB_BOLD       = 0x0007
+)
+
+var ColorTableFg = []word{
+	0,                                       // 30: Black
+	COLOR_FRED,                              // 31: Red
+	COLOR_FGREEN,                            // 32: Green
+	COLOR_FRED | COLOR_FGREEN,               // 33: Yellow
+	COLOR_FBLUE,                             // 34: Blue
+	COLOR_FRED | COLOR_FBLUE,                // 35: Magenta
+	COLOR_FGREEN | COLOR_FBLUE,              // 36: Cyan
+	COLOR_FRED | COLOR_FBLUE | COLOR_FGREEN, // 37: White
+}
+
+var ColorTableBg = []word{
+	0,                                       // 40: Black
+	COLOR_BRED,                              // 41: Red
+	COLOR_BGREEN,                            // 42: Green
+	COLOR_BRED | COLOR_BGREEN,               // 43: Yellow
+	COLOR_BBLUE,                             // 44: Blue
+	COLOR_BRED | COLOR_BBLUE,                // 45: Magenta
+	COLOR_BGREEN | COLOR_BBLUE,              // 46: Cyan
+	COLOR_BRED | COLOR_BBLUE | COLOR_BGREEN, // 47: White
+}
+
+type ANSIWriter struct {
+	target io.Writer
+	wg     sync.WaitGroup
+	ctx    *ANSIWriterCtx
+	sync.Mutex
+}
+
+func NewANSIWriter(w io.Writer) *ANSIWriter {
+	a := &ANSIWriter{
+		target: w,
+		ctx:    NewANSIWriterCtx(w),
+	}
+	return a
+}
+
+func (a *ANSIWriter) Close() error {
+	a.wg.Wait()
+	return nil
+}
+
+type ANSIWriterCtx struct {
+	isEsc     bool
+	isEscSeq  bool
+	arg       []string
+	target    *bufio.Writer
+	wantFlush bool
+}
+
+func NewANSIWriterCtx(target io.Writer) *ANSIWriterCtx {
+	return &ANSIWriterCtx{
+		target: bufio.NewWriter(target),
+	}
+}
+
+func (a *ANSIWriterCtx) Flush() {
+	a.target.Flush()
+}
+
+func (a *ANSIWriterCtx) process(r rune) bool {
+	if a.wantFlush {
+		if r == 0 || r == CharEsc {
+			a.wantFlush = false
+			a.target.Flush()
+		}
+	}
+	if a.isEscSeq {
+		a.isEscSeq = a.ioloopEscSeq(a.target, r, &a.arg)
+		return true
+	}
+
+	switch r {
+	case CharEsc:
+		a.isEsc = true
+	case '[':
+		if a.isEsc {
+			a.arg = nil
+			a.isEscSeq = true
+			a.isEsc = false
+			break
+		}
+		fallthrough
+	default:
+		a.target.WriteRune(r)
+		a.wantFlush = true
+	}
+	return true
+}
+
+func (a *ANSIWriterCtx) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) bool {
+	arg := *argptr
+	var err error
+
+	if r >= 'A' && r <= 'D' {
+		count := short(GetInt(arg, 1))
+		info, err := GetConsoleScreenBufferInfo()
+		if err != nil {
+			return false
+		}
+		switch r {
+		case 'A': // up
+			info.dwCursorPosition.y -= count
+		case 'B': // down
+			info.dwCursorPosition.y += count
+		case 'C': // right
+			info.dwCursorPosition.x += count
+		case 'D': // left
+			info.dwCursorPosition.x -= count
+		}
+		SetConsoleCursorPosition(&info.dwCursorPosition)
+		return false
+	}
+
+	switch r {
+	case 'J':
+		killLines()
+	case 'K':
+		eraseLine()
+	case 'm':
+		color := word(0)
+		for _, item := range arg {
+			var c int
+			c, err = strconv.Atoi(item)
+			if err != nil {
+				w.WriteString("[" + strings.Join(arg, ";") + "m")
+				break
+			}
+			if c >= 30 && c < 40 {
+				color ^= COLOR_FINTENSITY
+				color |= ColorTableFg[c-30]
+			} else if c >= 40 && c < 50 {
+				color ^= COLOR_BINTENSITY
+				color |= ColorTableBg[c-40]
+			} else if c == 4 {
+				color |= COMMON_LVB_UNDERSCORE | ColorTableFg[7]
+			} else if c == 1 {
+				color |= COMMON_LVB_BOLD | COLOR_FINTENSITY
+			} else { // unknown code treat as reset
+				color = ColorTableFg[7]
+			}
+		}
+		if err != nil {
+			break
+		}
+		kernel.SetConsoleTextAttribute(stdout, uintptr(color))
+	case '\007': // set title
+	case ';':
+		if len(arg) == 0 || arg[len(arg)-1] != "" {
+			arg = append(arg, "")
+			*argptr = arg
+		}
+		return true
+	default:
+		if len(arg) == 0 {
+			arg = append(arg, "")
+		}
+		arg[len(arg)-1] += string(r)
+		*argptr = arg
+		return true
+	}
+	*argptr = nil
+	return false
+}
+
+func (a *ANSIWriter) Write(b []byte) (int, error) {
+	a.Lock()
+	defer a.Unlock()
+
+	off := 0
+	for len(b) > off {
+		r, size := utf8.DecodeRune(b[off:])
+		if size == 0 {
+			return off, io.ErrShortWrite
+		}
+		off += size
+		a.ctx.process(r)
+	}
+	a.ctx.Flush()
+	return off, nil
+}
+
+func killLines() error {
+	sbi, err := GetConsoleScreenBufferInfo()
+	if err != nil {
+		return err
+	}
+
+	size := (sbi.dwCursorPosition.y - sbi.dwSize.y) * sbi.dwSize.x
+	size += sbi.dwCursorPosition.x
+
+	var written int
+	kernel.FillConsoleOutputAttribute(stdout, uintptr(ColorTableFg[7]),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+}
+
+func eraseLine() error {
+	sbi, err := GetConsoleScreenBufferInfo()
+	if err != nil {
+		return err
+	}
+
+	size := sbi.dwSize.x
+	sbi.dwCursorPosition.x = 0
+	var written int
+	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+}
diff --git a/vendor/github.com/chzyer/readline/complete.go b/vendor/github.com/chzyer/readline/complete.go
new file mode 100644
index 0000000..d1351f7
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/complete.go
@@ -0,0 +1,285 @@
+package readline
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+)
+
+type AutoCompleter interface {
+	// Readline will pass the whole line and current offset to it
+	// Completer need to pass all the candidates, and how long they shared the same characters in line
+	// Example:
+	//   [go, git, git-shell, grep]
+	//   Do("g", 1) => ["o", "it", "it-shell", "rep"], 1
+	//   Do("gi", 2) => ["t", "t-shell"], 2
+	//   Do("git", 3) => ["", "-shell"], 3
+	Do(line []rune, pos int) (newLine [][]rune, length int)
+}
+
+type TabCompleter struct{}
+
+func (t *TabCompleter) Do([]rune, int) ([][]rune, int) {
+	return [][]rune{[]rune("\t")}, 0
+}
+
+type opCompleter struct {
+	w     io.Writer
+	op    *Operation
+	width int
+
+	inCompleteMode  bool
+	inSelectMode    bool
+	candidate       [][]rune
+	candidateSource []rune
+	candidateOff    int
+	candidateChoise int
+	candidateColNum int
+}
+
+func newOpCompleter(w io.Writer, op *Operation, width int) *opCompleter {
+	return &opCompleter{
+		w:     w,
+		op:    op,
+		width: width,
+	}
+}
+
+func (o *opCompleter) doSelect() {
+	if len(o.candidate) == 1 {
+		o.op.buf.WriteRunes(o.candidate[0])
+		o.ExitCompleteMode(false)
+		return
+	}
+	o.nextCandidate(1)
+	o.CompleteRefresh()
+}
+
+func (o *opCompleter) nextCandidate(i int) {
+	o.candidateChoise += i
+	o.candidateChoise = o.candidateChoise % len(o.candidate)
+	if o.candidateChoise < 0 {
+		o.candidateChoise = len(o.candidate) + o.candidateChoise
+	}
+}
+
+func (o *opCompleter) OnComplete() bool {
+	if o.width == 0 {
+		return false
+	}
+	if o.IsInCompleteSelectMode() {
+		o.doSelect()
+		return true
+	}
+
+	buf := o.op.buf
+	rs := buf.Runes()
+
+	if o.IsInCompleteMode() && o.candidateSource != nil && runes.Equal(rs, o.candidateSource) {
+		o.EnterCompleteSelectMode()
+		o.doSelect()
+		return true
+	}
+
+	o.ExitCompleteSelectMode()
+	o.candidateSource = rs
+	newLines, offset := o.op.cfg.AutoComplete.Do(rs, buf.idx)
+	if len(newLines) == 0 {
+		o.ExitCompleteMode(false)
+		return true
+	}
+
+	// only Aggregate candidates in non-complete mode
+	if !o.IsInCompleteMode() {
+		if len(newLines) == 1 {
+			buf.WriteRunes(newLines[0])
+			o.ExitCompleteMode(false)
+			return true
+		}
+
+		same, size := runes.Aggregate(newLines)
+		if size > 0 {
+			buf.WriteRunes(same)
+			o.ExitCompleteMode(false)
+			return true
+		}
+	}
+
+	o.EnterCompleteMode(offset, newLines)
+	return true
+}
+
+func (o *opCompleter) IsInCompleteSelectMode() bool {
+	return o.inSelectMode
+}
+
+func (o *opCompleter) IsInCompleteMode() bool {
+	return o.inCompleteMode
+}
+
+func (o *opCompleter) HandleCompleteSelect(r rune) bool {
+	next := true
+	switch r {
+	case CharEnter, CharCtrlJ:
+		next = false
+		o.op.buf.WriteRunes(o.op.candidate[o.op.candidateChoise])
+		o.ExitCompleteMode(false)
+	case CharLineStart:
+		num := o.candidateChoise % o.candidateColNum
+		o.nextCandidate(-num)
+	case CharLineEnd:
+		num := o.candidateColNum - o.candidateChoise%o.candidateColNum - 1
+		o.candidateChoise += num
+		if o.candidateChoise >= len(o.candidate) {
+			o.candidateChoise = len(o.candidate) - 1
+		}
+	case CharBackspace:
+		o.ExitCompleteSelectMode()
+		next = false
+	case CharTab, CharForward:
+		o.doSelect()
+	case CharBell, CharInterrupt:
+		o.ExitCompleteMode(true)
+		next = false
+	case CharNext:
+		tmpChoise := o.candidateChoise + o.candidateColNum
+		if tmpChoise >= o.getMatrixSize() {
+			tmpChoise -= o.getMatrixSize()
+		} else if tmpChoise >= len(o.candidate) {
+			tmpChoise += o.candidateColNum
+			tmpChoise -= o.getMatrixSize()
+		}
+		o.candidateChoise = tmpChoise
+	case CharBackward:
+		o.nextCandidate(-1)
+	case CharPrev:
+		tmpChoise := o.candidateChoise - o.candidateColNum
+		if tmpChoise < 0 {
+			tmpChoise += o.getMatrixSize()
+			if tmpChoise >= len(o.candidate) {
+				tmpChoise -= o.candidateColNum
+			}
+		}
+		o.candidateChoise = tmpChoise
+	default:
+		next = false
+		o.ExitCompleteSelectMode()
+	}
+	if next {
+		o.CompleteRefresh()
+		return true
+	}
+	return false
+}
+
+func (o *opCompleter) getMatrixSize() int {
+	line := len(o.candidate) / o.candidateColNum
+	if len(o.candidate)%o.candidateColNum != 0 {
+		line++
+	}
+	return line * o.candidateColNum
+}
+
+func (o *opCompleter) OnWidthChange(newWidth int) {
+	o.width = newWidth
+}
+
+func (o *opCompleter) CompleteRefresh() {
+	if !o.inCompleteMode {
+		return
+	}
+	lineCnt := o.op.buf.CursorLineCount()
+	colWidth := 0
+	for _, c := range o.candidate {
+		w := runes.WidthAll(c)
+		if w > colWidth {
+			colWidth = w
+		}
+	}
+	colWidth += o.candidateOff + 1
+	same := o.op.buf.RuneSlice(-o.candidateOff)
+
+	// -1 to avoid reach the end of line
+	width := o.width - 1
+	colNum := width / colWidth
+	if colNum != 0 {
+		colWidth += (width - (colWidth * colNum)) / colNum
+	}
+
+	o.candidateColNum = colNum
+	buf := bufio.NewWriter(o.w)
+	buf.Write(bytes.Repeat([]byte("\n"), lineCnt))
+
+	colIdx := 0
+	lines := 1
+	buf.WriteString("\033[J")
+	for idx, c := range o.candidate {
+		inSelect := idx == o.candidateChoise && o.IsInCompleteSelectMode()
+		if inSelect {
+			buf.WriteString("\033[30;47m")
+		}
+		buf.WriteString(string(same))
+		buf.WriteString(string(c))
+		buf.Write(bytes.Repeat([]byte(" "), colWidth-len(c)-len(same)))
+
+		if inSelect {
+			buf.WriteString("\033[0m")
+		}
+
+		colIdx++
+		if colIdx == colNum {
+			buf.WriteString("\n")
+			lines++
+			colIdx = 0
+		}
+	}
+
+	// move back
+	fmt.Fprintf(buf, "\033[%dA\r", lineCnt-1+lines)
+	fmt.Fprintf(buf, "\033[%dC", o.op.buf.idx+o.op.buf.PromptLen())
+	buf.Flush()
+}
+
+func (o *opCompleter) aggCandidate(candidate [][]rune) int {
+	offset := 0
+	for i := 0; i < len(candidate[0]); i++ {
+		for j := 0; j < len(candidate)-1; j++ {
+			if i > len(candidate[j]) {
+				goto aggregate
+			}
+			if candidate[j][i] != candidate[j+1][i] {
+				goto aggregate
+			}
+		}
+		offset = i
+	}
+aggregate:
+	return offset
+}
+
+func (o *opCompleter) EnterCompleteSelectMode() {
+	o.inSelectMode = true
+	o.candidateChoise = -1
+	o.CompleteRefresh()
+}
+
+func (o *opCompleter) EnterCompleteMode(offset int, candidate [][]rune) {
+	o.inCompleteMode = true
+	o.candidate = candidate
+	o.candidateOff = offset
+	o.CompleteRefresh()
+}
+
+func (o *opCompleter) ExitCompleteSelectMode() {
+	o.inSelectMode = false
+	o.candidate = nil
+	o.candidateChoise = -1
+	o.candidateOff = -1
+	o.candidateSource = nil
+}
+
+func (o *opCompleter) ExitCompleteMode(revent bool) {
+	o.inCompleteMode = false
+	o.ExitCompleteSelectMode()
+}
diff --git a/vendor/github.com/chzyer/readline/complete_helper.go b/vendor/github.com/chzyer/readline/complete_helper.go
new file mode 100644
index 0000000..58d7248
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/complete_helper.go
@@ -0,0 +1,165 @@
+package readline
+
+import (
+	"bytes"
+	"strings"
+)
+
+// Caller type for dynamic completion
+type DynamicCompleteFunc func(string) []string
+
+type PrefixCompleterInterface interface {
+	Print(prefix string, level int, buf *bytes.Buffer)
+	Do(line []rune, pos int) (newLine [][]rune, length int)
+	GetName() []rune
+	GetChildren() []PrefixCompleterInterface
+	SetChildren(children []PrefixCompleterInterface)
+}
+
+type DynamicPrefixCompleterInterface interface {
+	PrefixCompleterInterface
+	IsDynamic() bool
+	GetDynamicNames(line []rune) [][]rune
+}
+
+type PrefixCompleter struct {
+	Name     []rune
+	Dynamic  bool
+	Callback DynamicCompleteFunc
+	Children []PrefixCompleterInterface
+}
+
+func (p *PrefixCompleter) Tree(prefix string) string {
+	buf := bytes.NewBuffer(nil)
+	p.Print(prefix, 0, buf)
+	return buf.String()
+}
+
+func Print(p PrefixCompleterInterface, prefix string, level int, buf *bytes.Buffer) {
+	if strings.TrimSpace(string(p.GetName())) != "" {
+		buf.WriteString(prefix)
+		if level > 0 {
+			buf.WriteString("├")
+			buf.WriteString(strings.Repeat("─", (level*4)-2))
+			buf.WriteString(" ")
+		}
+		buf.WriteString(string(p.GetName()) + "\n")
+		level++
+	}
+	for _, ch := range p.GetChildren() {
+		ch.Print(prefix, level, buf)
+	}
+}
+
+func (p *PrefixCompleter) Print(prefix string, level int, buf *bytes.Buffer) {
+	Print(p, prefix, level, buf)
+}
+
+func (p *PrefixCompleter) IsDynamic() bool {
+	return p.Dynamic
+}
+
+func (p *PrefixCompleter) GetName() []rune {
+	return p.Name
+}
+
+func (p *PrefixCompleter) GetDynamicNames(line []rune) [][]rune {
+	var names = [][]rune{}
+	for _, name := range p.Callback(string(line)) {
+		names = append(names, []rune(name+" "))
+	}
+	return names
+}
+
+func (p *PrefixCompleter) GetChildren() []PrefixCompleterInterface {
+	return p.Children
+}
+
+func (p *PrefixCompleter) SetChildren(children []PrefixCompleterInterface) {
+	p.Children = children
+}
+
+func NewPrefixCompleter(pc ...PrefixCompleterInterface) *PrefixCompleter {
+	return PcItem("", pc...)
+}
+
+func PcItem(name string, pc ...PrefixCompleterInterface) *PrefixCompleter {
+	name += " "
+	return &PrefixCompleter{
+		Name:     []rune(name),
+		Dynamic:  false,
+		Children: pc,
+	}
+}
+
+func PcItemDynamic(callback DynamicCompleteFunc, pc ...PrefixCompleterInterface) *PrefixCompleter {
+	return &PrefixCompleter{
+		Callback: callback,
+		Dynamic:  true,
+		Children: pc,
+	}
+}
+
+func (p *PrefixCompleter) Do(line []rune, pos int) (newLine [][]rune, offset int) {
+	return doInternal(p, line, pos, line)
+}
+
+func Do(p PrefixCompleterInterface, line []rune, pos int) (newLine [][]rune, offset int) {
+	return doInternal(p, line, pos, line)
+}
+
+func doInternal(p PrefixCompleterInterface, line []rune, pos int, origLine []rune) (newLine [][]rune, offset int) {
+	line = runes.TrimSpaceLeft(line[:pos])
+	goNext := false
+	var lineCompleter PrefixCompleterInterface
+	for _, child := range p.GetChildren() {
+		childNames := make([][]rune, 1)
+
+		childDynamic, ok := child.(DynamicPrefixCompleterInterface)
+		if ok && childDynamic.IsDynamic() {
+			childNames = childDynamic.GetDynamicNames(origLine)
+		} else {
+			childNames[0] = child.GetName()
+		}
+
+		for _, childName := range childNames {
+			if len(line) >= len(childName) {
+				if runes.HasPrefix(line, childName) {
+					if len(line) == len(childName) {
+						newLine = append(newLine, []rune{' '})
+					} else {
+						newLine = append(newLine, childName)
+					}
+					offset = len(childName)
+					lineCompleter = child
+					goNext = true
+				}
+			} else {
+				if runes.HasPrefix(childName, line) {
+					newLine = append(newLine, childName[len(line):])
+					offset = len(line)
+					lineCompleter = child
+				}
+			}
+		}
+	}
+
+	if len(newLine) != 1 {
+		return
+	}
+
+	tmpLine := make([]rune, 0, len(line))
+	for i := offset; i < len(line); i++ {
+		if line[i] == ' ' {
+			continue
+		}
+
+		tmpLine = append(tmpLine, line[i:]...)
+		return doInternal(lineCompleter, tmpLine, len(tmpLine), origLine)
+	}
+
+	if goNext {
+		return doInternal(lineCompleter, nil, 0, origLine)
+	}
+	return
+}
diff --git a/vendor/github.com/chzyer/readline/complete_segment.go b/vendor/github.com/chzyer/readline/complete_segment.go
new file mode 100644
index 0000000..5ceadd8
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/complete_segment.go
@@ -0,0 +1,82 @@
+package readline
+
+type SegmentCompleter interface {
+	// a
+	// |- a1
+	// |--- a11
+	// |- a2
+	// b
+	// input:
+	//   DoTree([], 0) [a, b]
+	//   DoTree([a], 1) [a]
+	//   DoTree([a, ], 0) [a1, a2]
+	//   DoTree([a, a], 1) [a1, a2]
+	//   DoTree([a, a1], 2) [a1]
+	//   DoTree([a, a1, ], 0) [a11]
+	//   DoTree([a, a1, a], 1) [a11]
+	DoSegment([][]rune, int) [][]rune
+}
+
+type dumpSegmentCompleter struct {
+	f func([][]rune, int) [][]rune
+}
+
+func (d *dumpSegmentCompleter) DoSegment(segment [][]rune, n int) [][]rune {
+	return d.f(segment, n)
+}
+
+func SegmentFunc(f func([][]rune, int) [][]rune) AutoCompleter {
+	return &SegmentComplete{&dumpSegmentCompleter{f}}
+}
+
+func SegmentAutoComplete(completer SegmentCompleter) *SegmentComplete {
+	return &SegmentComplete{
+		SegmentCompleter: completer,
+	}
+}
+
+type SegmentComplete struct {
+	SegmentCompleter
+}
+
+func RetSegment(segments [][]rune, cands [][]rune, idx int) ([][]rune, int) {
+	ret := make([][]rune, 0, len(cands))
+	lastSegment := segments[len(segments)-1]
+	for _, cand := range cands {
+		if !runes.HasPrefix(cand, lastSegment) {
+			continue
+		}
+		ret = append(ret, cand[len(lastSegment):])
+	}
+	return ret, idx
+}
+
+func SplitSegment(line []rune, pos int) ([][]rune, int) {
+	segs := [][]rune{}
+	lastIdx := -1
+	line = line[:pos]
+	pos = 0
+	for idx, l := range line {
+		if l == ' ' {
+			pos = 0
+			segs = append(segs, line[lastIdx+1:idx])
+			lastIdx = idx
+		} else {
+			pos++
+		}
+	}
+	segs = append(segs, line[lastIdx+1:])
+	return segs, pos
+}
+
+func (c *SegmentComplete) Do(line []rune, pos int) (newLine [][]rune, offset int) {
+
+	segment, idx := SplitSegment(line, pos)
+
+	cands := c.DoSegment(segment, idx)
+	newLine, offset = RetSegment(segment, cands, idx)
+	for idx := range newLine {
+		newLine[idx] = append(newLine[idx], ' ')
+	}
+	return newLine, offset
+}
diff --git a/vendor/github.com/chzyer/readline/history.go b/vendor/github.com/chzyer/readline/history.go
new file mode 100644
index 0000000..6b17c46
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/history.go
@@ -0,0 +1,330 @@
+package readline
+
+import (
+	"bufio"
+	"container/list"
+	"fmt"
+	"os"
+	"strings"
+	"sync"
+)
+
+type hisItem struct {
+	Source  []rune
+	Version int64
+	Tmp     []rune
+}
+
+func (h *hisItem) Clean() {
+	h.Source = nil
+	h.Tmp = nil
+}
+
+type opHistory struct {
+	cfg        *Config
+	history    *list.List
+	historyVer int64
+	current    *list.Element
+	fd         *os.File
+	fdLock     sync.Mutex
+	enable     bool
+}
+
+func newOpHistory(cfg *Config) (o *opHistory) {
+	o = &opHistory{
+		cfg:     cfg,
+		history: list.New(),
+		enable:  true,
+	}
+	return o
+}
+
+func (o *opHistory) Reset() {
+	o.history = list.New()
+	o.current = nil
+}
+
+func (o *opHistory) IsHistoryClosed() bool {
+	o.fdLock.Lock()
+	defer o.fdLock.Unlock()
+	return o.fd.Fd() == ^(uintptr(0))
+}
+
+func (o *opHistory) Init() {
+	if o.IsHistoryClosed() {
+		o.initHistory()
+	}
+}
+
+func (o *opHistory) initHistory() {
+	if o.cfg.HistoryFile != "" {
+		o.historyUpdatePath(o.cfg.HistoryFile)
+	}
+}
+
+// only called by newOpHistory
+func (o *opHistory) historyUpdatePath(path string) {
+	o.fdLock.Lock()
+	defer o.fdLock.Unlock()
+	f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
+	if err != nil {
+		return
+	}
+	o.fd = f
+	r := bufio.NewReader(o.fd)
+	total := 0
+	for ; ; total++ {
+		line, err := r.ReadString('\n')
+		if err != nil {
+			break
+		}
+		// ignore the empty line
+		line = strings.TrimSpace(line)
+		if len(line) == 0 {
+			continue
+		}
+		o.Push([]rune(line))
+		o.Compact()
+	}
+	if total > o.cfg.HistoryLimit {
+		o.rewriteLocked()
+	}
+	o.historyVer++
+	o.Push(nil)
+	return
+}
+
+func (o *opHistory) Compact() {
+	for o.history.Len() > o.cfg.HistoryLimit && o.history.Len() > 0 {
+		o.history.Remove(o.history.Front())
+	}
+}
+
+func (o *opHistory) Rewrite() {
+	o.fdLock.Lock()
+	defer o.fdLock.Unlock()
+	o.rewriteLocked()
+}
+
+func (o *opHistory) rewriteLocked() {
+	if o.cfg.HistoryFile == "" {
+		return
+	}
+
+	tmpFile := o.cfg.HistoryFile + ".tmp"
+	fd, err := os.OpenFile(tmpFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC|os.O_APPEND, 0666)
+	if err != nil {
+		return
+	}
+
+	buf := bufio.NewWriter(fd)
+	for elem := o.history.Front(); elem != nil; elem = elem.Next() {
+		buf.WriteString(string(elem.Value.(*hisItem).Source) + "\n")
+	}
+	buf.Flush()
+
+	// replace history file
+	if err = os.Rename(tmpFile, o.cfg.HistoryFile); err != nil {
+		fd.Close()
+		return
+	}
+
+	if o.fd != nil {
+		o.fd.Close()
+	}
+	// fd is write only, just satisfy what we need.
+	o.fd = fd
+}
+
+func (o *opHistory) Close() {
+	o.fdLock.Lock()
+	defer o.fdLock.Unlock()
+	if o.fd != nil {
+		o.fd.Close()
+	}
+}
+
+func (o *opHistory) FindBck(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
+	for elem := o.current; elem != nil; elem = elem.Prev() {
+		item := o.showItem(elem.Value)
+		if isNewSearch {
+			start += len(rs)
+		}
+		if elem == o.current {
+			if len(item) >= start {
+				item = item[:start]
+			}
+		}
+		idx := runes.IndexAllBckEx(item, rs, o.cfg.HistorySearchFold)
+		if idx < 0 {
+			continue
+		}
+		return idx, elem
+	}
+	return -1, nil
+}
+
+func (o *opHistory) FindFwd(isNewSearch bool, rs []rune, start int) (int, *list.Element) {
+	for elem := o.current; elem != nil; elem = elem.Next() {
+		item := o.showItem(elem.Value)
+		if isNewSearch {
+			start -= len(rs)
+			if start < 0 {
+				start = 0
+			}
+		}
+		if elem == o.current {
+			if len(item)-1 >= start {
+				item = item[start:]
+			} else {
+				continue
+			}
+		}
+		idx := runes.IndexAllEx(item, rs, o.cfg.HistorySearchFold)
+		if idx < 0 {
+			continue
+		}
+		if elem == o.current {
+			idx += start
+		}
+		return idx, elem
+	}
+	return -1, nil
+}
+
+func (o *opHistory) showItem(obj interface{}) []rune {
+	item := obj.(*hisItem)
+	if item.Version == o.historyVer {
+		return item.Tmp
+	}
+	return item.Source
+}
+
+func (o *opHistory) Prev() []rune {
+	if o.current == nil {
+		return nil
+	}
+	current := o.current.Prev()
+	if current == nil {
+		return nil
+	}
+	o.current = current
+	return runes.Copy(o.showItem(current.Value))
+}
+
+func (o *opHistory) Next() ([]rune, bool) {
+	if o.current == nil {
+		return nil, false
+	}
+	current := o.current.Next()
+	if current == nil {
+		return nil, false
+	}
+
+	o.current = current
+	return runes.Copy(o.showItem(current.Value)), true
+}
+
+// Disable the current history
+func (o *opHistory) Disable() {
+	o.enable = false
+}
+
+// Enable the current history
+func (o *opHistory) Enable() {
+	o.enable = true
+}
+
+func (o *opHistory) debug() {
+	Debug("-------")
+	for item := o.history.Front(); item != nil; item = item.Next() {
+		Debug(fmt.Sprintf("%+v", item.Value))
+	}
+}
+
+// save history
+func (o *opHistory) New(current []rune) (err error) {
+
+	// history deactivated
+	if !o.enable {
+		return nil
+	}
+
+	current = runes.Copy(current)
+
+	// if just use last command without modify
+	// just clean lastest history
+	if back := o.history.Back(); back != nil {
+		prev := back.Prev()
+		if prev != nil {
+			if runes.Equal(current, prev.Value.(*hisItem).Source) {
+				o.current = o.history.Back()
+				o.current.Value.(*hisItem).Clean()
+				o.historyVer++
+				return nil
+			}
+		}
+	}
+
+	if len(current) == 0 {
+		o.current = o.history.Back()
+		if o.current != nil {
+			o.current.Value.(*hisItem).Clean()
+			o.historyVer++
+			return nil
+		}
+	}
+
+	if o.current != o.history.Back() {
+		// move history item to current command
+		currentItem := o.current.Value.(*hisItem)
+		// set current to last item
+		o.current = o.history.Back()
+
+		current = runes.Copy(currentItem.Tmp)
+	}
+
+	// err only can be a IO error, just report
+	err = o.Update(current, true)
+
+	// push a new one to commit current command
+	o.historyVer++
+	o.Push(nil)
+	return
+}
+
+func (o *opHistory) Revert() {
+	o.historyVer++
+	o.current = o.history.Back()
+}
+
+func (o *opHistory) Update(s []rune, commit bool) (err error) {
+	o.fdLock.Lock()
+	defer o.fdLock.Unlock()
+	s = runes.Copy(s)
+	if o.current == nil {
+		o.Push(s)
+		o.Compact()
+		return
+	}
+	r := o.current.Value.(*hisItem)
+	r.Version = o.historyVer
+	if commit {
+		r.Source = s
+		if o.fd != nil {
+			// just report the error
+			_, err = o.fd.Write([]byte(string(r.Source) + "\n"))
+		}
+	} else {
+		r.Tmp = append(r.Tmp[:0], s...)
+	}
+	o.current.Value = r
+	o.Compact()
+	return
+}
+
+func (o *opHistory) Push(s []rune) {
+	s = runes.Copy(s)
+	elem := o.history.PushBack(&hisItem{Source: s})
+	o.current = elem
+}
diff --git a/vendor/github.com/chzyer/readline/operation.go b/vendor/github.com/chzyer/readline/operation.go
new file mode 100644
index 0000000..4c31624
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/operation.go
@@ -0,0 +1,531 @@
+package readline
+
+import (
+	"errors"
+	"io"
+	"sync"
+)
+
+var (
+	ErrInterrupt = errors.New("Interrupt")
+)
+
+type InterruptError struct {
+	Line []rune
+}
+
+func (*InterruptError) Error() string {
+	return "Interrupted"
+}
+
+type Operation struct {
+	m       sync.Mutex
+	cfg     *Config
+	t       *Terminal
+	buf     *RuneBuffer
+	outchan chan []rune
+	errchan chan error
+	w       io.Writer
+
+	history *opHistory
+	*opSearch
+	*opCompleter
+	*opPassword
+	*opVim
+}
+
+func (o *Operation) SetBuffer(what string) {
+	o.buf.Set([]rune(what))
+}
+
+type wrapWriter struct {
+	r      *Operation
+	t      *Terminal
+	target io.Writer
+}
+
+func (w *wrapWriter) Write(b []byte) (int, error) {
+	if !w.t.IsReading() {
+		return w.target.Write(b)
+	}
+
+	var (
+		n   int
+		err error
+	)
+	w.r.buf.Refresh(func() {
+		n, err = w.target.Write(b)
+	})
+
+	if w.r.IsSearchMode() {
+		w.r.SearchRefresh(-1)
+	}
+	if w.r.IsInCompleteMode() {
+		w.r.CompleteRefresh()
+	}
+	return n, err
+}
+
+func NewOperation(t *Terminal, cfg *Config) *Operation {
+	width := cfg.FuncGetWidth()
+	op := &Operation{
+		t:       t,
+		buf:     NewRuneBuffer(t, cfg.Prompt, cfg, width),
+		outchan: make(chan []rune),
+		errchan: make(chan error, 1),
+	}
+	op.w = op.buf.w
+	op.SetConfig(cfg)
+	op.opVim = newVimMode(op)
+	op.opCompleter = newOpCompleter(op.buf.w, op, width)
+	op.opPassword = newOpPassword(op)
+	op.cfg.FuncOnWidthChanged(func() {
+		newWidth := cfg.FuncGetWidth()
+		op.opCompleter.OnWidthChange(newWidth)
+		op.opSearch.OnWidthChange(newWidth)
+		op.buf.OnWidthChange(newWidth)
+	})
+	go op.ioloop()
+	return op
+}
+
+func (o *Operation) SetPrompt(s string) {
+	o.buf.SetPrompt(s)
+}
+
+func (o *Operation) SetMaskRune(r rune) {
+	o.buf.SetMask(r)
+}
+
+func (o *Operation) GetConfig() *Config {
+	o.m.Lock()
+	cfg := *o.cfg
+	o.m.Unlock()
+	return &cfg
+}
+
+func (o *Operation) ioloop() {
+	for {
+		keepInSearchMode := false
+		keepInCompleteMode := false
+		r := o.t.ReadRune()
+		if o.GetConfig().FuncFilterInputRune != nil {
+			var process bool
+			r, process = o.GetConfig().FuncFilterInputRune(r)
+			if !process {
+				o.buf.Refresh(nil) // to refresh the line
+				continue           // ignore this rune
+			}
+		}
+
+		if r == 0 { // io.EOF
+			if o.buf.Len() == 0 {
+				o.buf.Clean()
+				select {
+				case o.errchan <- io.EOF:
+				}
+				break
+			} else {
+				// if stdin got io.EOF and there is something left in buffer,
+				// let's flush them by sending CharEnter.
+				// And we will got io.EOF int next loop.
+				r = CharEnter
+			}
+		}
+		isUpdateHistory := true
+
+		if o.IsInCompleteSelectMode() {
+			keepInCompleteMode = o.HandleCompleteSelect(r)
+			if keepInCompleteMode {
+				continue
+			}
+
+			o.buf.Refresh(nil)
+			switch r {
+			case CharEnter, CharCtrlJ:
+				o.history.Update(o.buf.Runes(), false)
+				fallthrough
+			case CharInterrupt:
+				o.t.KickRead()
+				fallthrough
+			case CharBell:
+				continue
+			}
+		}
+
+		if o.IsEnableVimMode() {
+			r = o.HandleVim(r, o.t.ReadRune)
+			if r == 0 {
+				continue
+			}
+		}
+
+		switch r {
+		case CharBell:
+			if o.IsSearchMode() {
+				o.ExitSearchMode(true)
+				o.buf.Refresh(nil)
+			}
+			if o.IsInCompleteMode() {
+				o.ExitCompleteMode(true)
+				o.buf.Refresh(nil)
+			}
+		case CharTab:
+			if o.GetConfig().AutoComplete == nil {
+				o.t.Bell()
+				break
+			}
+			if o.OnComplete() {
+				keepInCompleteMode = true
+			} else {
+				o.t.Bell()
+				break
+			}
+
+		case CharBckSearch:
+			if !o.SearchMode(S_DIR_BCK) {
+				o.t.Bell()
+				break
+			}
+			keepInSearchMode = true
+		case CharCtrlU:
+			o.buf.KillFront()
+		case CharFwdSearch:
+			if !o.SearchMode(S_DIR_FWD) {
+				o.t.Bell()
+				break
+			}
+			keepInSearchMode = true
+		case CharKill:
+			o.buf.Kill()
+			keepInCompleteMode = true
+		case MetaForward:
+			o.buf.MoveToNextWord()
+		case CharTranspose:
+			o.buf.Transpose()
+		case MetaBackward:
+			o.buf.MoveToPrevWord()
+		case MetaDelete:
+			o.buf.DeleteWord()
+		case CharLineStart:
+			o.buf.MoveToLineStart()
+		case CharLineEnd:
+			o.buf.MoveToLineEnd()
+		case CharBackspace, CharCtrlH:
+			if o.IsSearchMode() {
+				o.SearchBackspace()
+				keepInSearchMode = true
+				break
+			}
+
+			if o.buf.Len() == 0 {
+				o.t.Bell()
+				break
+			}
+			o.buf.Backspace()
+			if o.IsInCompleteMode() {
+				o.OnComplete()
+			}
+		case CharCtrlZ:
+			o.buf.Clean()
+			o.t.SleepToResume()
+			o.Refresh()
+		case CharCtrlL:
+			ClearScreen(o.w)
+			o.Refresh()
+		case MetaBackspace, CharCtrlW:
+			o.buf.BackEscapeWord()
+		case CharCtrlY:
+			o.buf.Yank()
+		case CharEnter, CharCtrlJ:
+			if o.IsSearchMode() {
+				o.ExitSearchMode(false)
+			}
+			o.buf.MoveToLineEnd()
+			var data []rune
+			if !o.GetConfig().UniqueEditLine {
+				o.buf.WriteRune('\n')
+				data = o.buf.Reset()
+				data = data[:len(data)-1] // trim \n
+			} else {
+				o.buf.Clean()
+				data = o.buf.Reset()
+			}
+			o.outchan <- data
+			if !o.GetConfig().DisableAutoSaveHistory {
+				// ignore IO error
+				_ = o.history.New(data)
+			} else {
+				isUpdateHistory = false
+			}
+		case CharBackward:
+			o.buf.MoveBackward()
+		case CharForward:
+			o.buf.MoveForward()
+		case CharPrev:
+			buf := o.history.Prev()
+			if buf != nil {
+				o.buf.Set(buf)
+			} else {
+				o.t.Bell()
+			}
+		case CharNext:
+			buf, ok := o.history.Next()
+			if ok {
+				o.buf.Set(buf)
+			} else {
+				o.t.Bell()
+			}
+		case CharDelete:
+			if o.buf.Len() > 0 || !o.IsNormalMode() {
+				o.t.KickRead()
+				if !o.buf.Delete() {
+					o.t.Bell()
+				}
+				break
+			}
+
+			// treat as EOF
+			if !o.GetConfig().UniqueEditLine {
+				o.buf.WriteString(o.GetConfig().EOFPrompt + "\n")
+			}
+			o.buf.Reset()
+			isUpdateHistory = false
+			o.history.Revert()
+			o.errchan <- io.EOF
+			if o.GetConfig().UniqueEditLine {
+				o.buf.Clean()
+			}
+		case CharInterrupt:
+			if o.IsSearchMode() {
+				o.t.KickRead()
+				o.ExitSearchMode(true)
+				break
+			}
+			if o.IsInCompleteMode() {
+				o.t.KickRead()
+				o.ExitCompleteMode(true)
+				o.buf.Refresh(nil)
+				break
+			}
+			o.buf.MoveToLineEnd()
+			o.buf.Refresh(nil)
+			hint := o.GetConfig().InterruptPrompt + "\n"
+			if !o.GetConfig().UniqueEditLine {
+				o.buf.WriteString(hint)
+			}
+			remain := o.buf.Reset()
+			if !o.GetConfig().UniqueEditLine {
+				remain = remain[:len(remain)-len([]rune(hint))]
+			}
+			isUpdateHistory = false
+			o.history.Revert()
+			o.errchan <- &InterruptError{remain}
+		default:
+			if o.IsSearchMode() {
+				o.SearchChar(r)
+				keepInSearchMode = true
+				break
+			}
+			o.buf.WriteRune(r)
+			if o.IsInCompleteMode() {
+				o.OnComplete()
+				keepInCompleteMode = true
+			}
+		}
+
+		listener := o.GetConfig().Listener
+		if listener != nil {
+			newLine, newPos, ok := listener.OnChange(o.buf.Runes(), o.buf.Pos(), r)
+			if ok {
+				o.buf.SetWithIdx(newPos, newLine)
+			}
+		}
+
+		o.m.Lock()
+		if !keepInSearchMode && o.IsSearchMode() {
+			o.ExitSearchMode(false)
+			o.buf.Refresh(nil)
+		} else if o.IsInCompleteMode() {
+			if !keepInCompleteMode {
+				o.ExitCompleteMode(false)
+				o.Refresh()
+			} else {
+				o.buf.Refresh(nil)
+				o.CompleteRefresh()
+			}
+		}
+		if isUpdateHistory && !o.IsSearchMode() {
+			// it will cause null history
+			o.history.Update(o.buf.Runes(), false)
+		}
+		o.m.Unlock()
+	}
+}
+
+func (o *Operation) Stderr() io.Writer {
+	return &wrapWriter{target: o.GetConfig().Stderr, r: o, t: o.t}
+}
+
+func (o *Operation) Stdout() io.Writer {
+	return &wrapWriter{target: o.GetConfig().Stdout, r: o, t: o.t}
+}
+
+func (o *Operation) String() (string, error) {
+	r, err := o.Runes()
+	return string(r), err
+}
+
+func (o *Operation) Runes() ([]rune, error) {
+	o.t.EnterRawMode()
+	defer o.t.ExitRawMode()
+
+	listener := o.GetConfig().Listener
+	if listener != nil {
+		listener.OnChange(nil, 0, 0)
+	}
+
+	o.buf.Refresh(nil) // print prompt
+	o.t.KickRead()
+	select {
+	case r := <-o.outchan:
+		return r, nil
+	case err := <-o.errchan:
+		if e, ok := err.(*InterruptError); ok {
+			return e.Line, ErrInterrupt
+		}
+		return nil, err
+	}
+}
+
+func (o *Operation) PasswordEx(prompt string, l Listener) ([]byte, error) {
+	cfg := o.GenPasswordConfig()
+	cfg.Prompt = prompt
+	cfg.Listener = l
+	return o.PasswordWithConfig(cfg)
+}
+
+func (o *Operation) GenPasswordConfig() *Config {
+	return o.opPassword.PasswordConfig()
+}
+
+func (o *Operation) PasswordWithConfig(cfg *Config) ([]byte, error) {
+	if err := o.opPassword.EnterPasswordMode(cfg); err != nil {
+		return nil, err
+	}
+	defer o.opPassword.ExitPasswordMode()
+	return o.Slice()
+}
+
+func (o *Operation) Password(prompt string) ([]byte, error) {
+	return o.PasswordEx(prompt, nil)
+}
+
+func (o *Operation) SetTitle(t string) {
+	o.w.Write([]byte("\033[2;" + t + "\007"))
+}
+
+func (o *Operation) Slice() ([]byte, error) {
+	r, err := o.Runes()
+	if err != nil {
+		return nil, err
+	}
+	return []byte(string(r)), nil
+}
+
+func (o *Operation) Close() {
+	o.history.Close()
+}
+
+func (o *Operation) SetHistoryPath(path string) {
+	if o.history != nil {
+		o.history.Close()
+	}
+	o.cfg.HistoryFile = path
+	o.history = newOpHistory(o.cfg)
+}
+
+func (o *Operation) IsNormalMode() bool {
+	return !o.IsInCompleteMode() && !o.IsSearchMode()
+}
+
+func (op *Operation) SetConfig(cfg *Config) (*Config, error) {
+	op.m.Lock()
+	defer op.m.Unlock()
+	if op.cfg == cfg {
+		return op.cfg, nil
+	}
+	if err := cfg.Init(); err != nil {
+		return op.cfg, err
+	}
+	old := op.cfg
+	op.cfg = cfg
+	op.SetPrompt(cfg.Prompt)
+	op.SetMaskRune(cfg.MaskRune)
+	op.buf.SetConfig(cfg)
+	width := op.cfg.FuncGetWidth()
+
+	if cfg.opHistory == nil {
+		op.SetHistoryPath(cfg.HistoryFile)
+		cfg.opHistory = op.history
+		cfg.opSearch = newOpSearch(op.buf.w, op.buf, op.history, cfg, width)
+	}
+	op.history = cfg.opHistory
+
+	// SetHistoryPath will close opHistory which already exists
+	// so if we use it next time, we need to reopen it by `InitHistory()`
+	op.history.Init()
+
+	if op.cfg.AutoComplete != nil {
+		op.opCompleter = newOpCompleter(op.buf.w, op, width)
+	}
+
+	op.opSearch = cfg.opSearch
+	return old, nil
+}
+
+func (o *Operation) ResetHistory() {
+	o.history.Reset()
+}
+
+// if err is not nil, it just mean it fail to write to file
+// other things goes fine.
+func (o *Operation) SaveHistory(content string) error {
+	return o.history.New([]rune(content))
+}
+
+func (o *Operation) Refresh() {
+	if o.t.IsReading() {
+		o.buf.Refresh(nil)
+	}
+}
+
+func (o *Operation) Clean() {
+	o.buf.Clean()
+}
+
+func FuncListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)) Listener {
+	return &DumpListener{f: f}
+}
+
+type DumpListener struct {
+	f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)
+}
+
+func (d *DumpListener) OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
+	return d.f(line, pos, key)
+}
+
+type Listener interface {
+	OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)
+}
+
+type Painter interface {
+	Paint(line []rune, pos int) []rune
+}
+
+type defaultPainter struct{}
+
+func (p *defaultPainter) Paint(line []rune, _ int) []rune {
+	return line
+}
diff --git a/vendor/github.com/chzyer/readline/password.go b/vendor/github.com/chzyer/readline/password.go
new file mode 100644
index 0000000..414288c
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/password.go
@@ -0,0 +1,33 @@
+package readline
+
+type opPassword struct {
+	o         *Operation
+	backupCfg *Config
+}
+
+func newOpPassword(o *Operation) *opPassword {
+	return &opPassword{o: o}
+}
+
+func (o *opPassword) ExitPasswordMode() {
+	o.o.SetConfig(o.backupCfg)
+	o.backupCfg = nil
+}
+
+func (o *opPassword) EnterPasswordMode(cfg *Config) (err error) {
+	o.backupCfg, err = o.o.SetConfig(cfg)
+	return
+}
+
+func (o *opPassword) PasswordConfig() *Config {
+	return &Config{
+		EnableMask:      true,
+		InterruptPrompt: "\n",
+		EOFPrompt:       "\n",
+		HistoryLimit:    -1,
+		Painter:         &defaultPainter{},
+
+		Stdout: o.o.cfg.Stdout,
+		Stderr: o.o.cfg.Stderr,
+	}
+}
diff --git a/vendor/github.com/chzyer/readline/rawreader_windows.go b/vendor/github.com/chzyer/readline/rawreader_windows.go
new file mode 100644
index 0000000..073ef15
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/rawreader_windows.go
@@ -0,0 +1,125 @@
+// +build windows
+
+package readline
+
+import "unsafe"
+
+const (
+	VK_CANCEL   = 0x03
+	VK_BACK     = 0x08
+	VK_TAB      = 0x09
+	VK_RETURN   = 0x0D
+	VK_SHIFT    = 0x10
+	VK_CONTROL  = 0x11
+	VK_MENU     = 0x12
+	VK_ESCAPE   = 0x1B
+	VK_LEFT     = 0x25
+	VK_UP       = 0x26
+	VK_RIGHT    = 0x27
+	VK_DOWN     = 0x28
+	VK_DELETE   = 0x2E
+	VK_LSHIFT   = 0xA0
+	VK_RSHIFT   = 0xA1
+	VK_LCONTROL = 0xA2
+	VK_RCONTROL = 0xA3
+)
+
+// RawReader translate input record to ANSI escape sequence.
+// To provides same behavior as unix terminal.
+type RawReader struct {
+	ctrlKey bool
+	altKey  bool
+}
+
+func NewRawReader() *RawReader {
+	r := new(RawReader)
+	return r
+}
+
+// only process one action in one read
+func (r *RawReader) Read(buf []byte) (int, error) {
+	ir := new(_INPUT_RECORD)
+	var read int
+	var err error
+next:
+	err = kernel.ReadConsoleInputW(stdin,
+		uintptr(unsafe.Pointer(ir)),
+		1,
+		uintptr(unsafe.Pointer(&read)),
+	)
+	if err != nil {
+		return 0, err
+	}
+	if ir.EventType != EVENT_KEY {
+		goto next
+	}
+	ker := (*_KEY_EVENT_RECORD)(unsafe.Pointer(&ir.Event[0]))
+	if ker.bKeyDown == 0 { // keyup
+		if r.ctrlKey || r.altKey {
+			switch ker.wVirtualKeyCode {
+			case VK_RCONTROL, VK_LCONTROL:
+				r.ctrlKey = false
+			case VK_MENU: //alt
+				r.altKey = false
+			}
+		}
+		goto next
+	}
+
+	if ker.unicodeChar == 0 {
+		var target rune
+		switch ker.wVirtualKeyCode {
+		case VK_RCONTROL, VK_LCONTROL:
+			r.ctrlKey = true
+		case VK_MENU: //alt
+			r.altKey = true
+		case VK_LEFT:
+			target = CharBackward
+		case VK_RIGHT:
+			target = CharForward
+		case VK_UP:
+			target = CharPrev
+		case VK_DOWN:
+			target = CharNext
+		}
+		if target != 0 {
+			return r.write(buf, target)
+		}
+		goto next
+	}
+	char := rune(ker.unicodeChar)
+	if r.ctrlKey {
+		switch char {
+		case 'A':
+			char = CharLineStart
+		case 'E':
+			char = CharLineEnd
+		case 'R':
+			char = CharBckSearch
+		case 'S':
+			char = CharFwdSearch
+		}
+	} else if r.altKey {
+		switch char {
+		case VK_BACK:
+			char = CharBackspace
+		}
+		return r.writeEsc(buf, char)
+	}
+	return r.write(buf, char)
+}
+
+func (r *RawReader) writeEsc(b []byte, char rune) (int, error) {
+	b[0] = '\033'
+	n := copy(b[1:], []byte(string(char)))
+	return n + 1, nil
+}
+
+func (r *RawReader) write(b []byte, char rune) (int, error) {
+	n := copy(b, []byte(string(char)))
+	return n, nil
+}
+
+func (r *RawReader) Close() error {
+	return nil
+}
diff --git a/vendor/github.com/chzyer/readline/readline.go b/vendor/github.com/chzyer/readline/readline.go
new file mode 100644
index 0000000..0e7aca0
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/readline.go
@@ -0,0 +1,326 @@
+// Readline is a pure go implementation for GNU-Readline kind library.
+//
+// example:
+// 	rl, err := readline.New("> ")
+// 	if err != nil {
+// 		panic(err)
+// 	}
+// 	defer rl.Close()
+//
+// 	for {
+// 		line, err := rl.Readline()
+// 		if err != nil { // io.EOF
+// 			break
+// 		}
+// 		println(line)
+// 	}
+//
+package readline
+
+import "io"
+
+type Instance struct {
+	Config    *Config
+	Terminal  *Terminal
+	Operation *Operation
+}
+
+type Config struct {
+	// prompt supports ANSI escape sequence, so we can color some characters even in windows
+	Prompt string
+
+	// readline will persist historys to file where HistoryFile specified
+	HistoryFile string
+	// specify the max length of historys, it's 500 by default, set it to -1 to disable history
+	HistoryLimit           int
+	DisableAutoSaveHistory bool
+	// enable case-insensitive history searching
+	HistorySearchFold bool
+
+	// AutoCompleter will called once user press TAB
+	AutoComplete AutoCompleter
+
+	// Any key press will pass to Listener
+	// NOTE: Listener will be triggered by (nil, 0, 0) immediately
+	Listener Listener
+
+	Painter Painter
+
+	// If VimMode is true, readline will in vim.insert mode by default
+	VimMode bool
+
+	InterruptPrompt string
+	EOFPrompt       string
+
+	FuncGetWidth func() int
+
+	Stdin       io.ReadCloser
+	StdinWriter io.Writer
+	Stdout      io.Writer
+	Stderr      io.Writer
+
+	EnableMask bool
+	MaskRune   rune
+
+	// erase the editing line after user submited it
+	// it use in IM usually.
+	UniqueEditLine bool
+
+	// filter input runes (may be used to disable CtrlZ or for translating some keys to different actions)
+	// -> output = new (translated) rune and true/false if continue with processing this one
+	FuncFilterInputRune func(rune) (rune, bool)
+
+	// force use interactive even stdout is not a tty
+	FuncIsTerminal      func() bool
+	FuncMakeRaw         func() error
+	FuncExitRaw         func() error
+	FuncOnWidthChanged  func(func())
+	ForceUseInteractive bool
+
+	// private fields
+	inited    bool
+	opHistory *opHistory
+	opSearch  *opSearch
+}
+
+func (c *Config) useInteractive() bool {
+	if c.ForceUseInteractive {
+		return true
+	}
+	return c.FuncIsTerminal()
+}
+
+func (c *Config) Init() error {
+	if c.inited {
+		return nil
+	}
+	c.inited = true
+	if c.Stdin == nil {
+		c.Stdin = NewCancelableStdin(Stdin)
+	}
+
+	c.Stdin, c.StdinWriter = NewFillableStdin(c.Stdin)
+
+	if c.Stdout == nil {
+		c.Stdout = Stdout
+	}
+	if c.Stderr == nil {
+		c.Stderr = Stderr
+	}
+	if c.HistoryLimit == 0 {
+		c.HistoryLimit = 500
+	}
+
+	if c.InterruptPrompt == "" {
+		c.InterruptPrompt = "^C"
+	} else if c.InterruptPrompt == "\n" {
+		c.InterruptPrompt = ""
+	}
+	if c.EOFPrompt == "" {
+		c.EOFPrompt = "^D"
+	} else if c.EOFPrompt == "\n" {
+		c.EOFPrompt = ""
+	}
+
+	if c.AutoComplete == nil {
+		c.AutoComplete = &TabCompleter{}
+	}
+	if c.FuncGetWidth == nil {
+		c.FuncGetWidth = GetScreenWidth
+	}
+	if c.FuncIsTerminal == nil {
+		c.FuncIsTerminal = DefaultIsTerminal
+	}
+	rm := new(RawMode)
+	if c.FuncMakeRaw == nil {
+		c.FuncMakeRaw = rm.Enter
+	}
+	if c.FuncExitRaw == nil {
+		c.FuncExitRaw = rm.Exit
+	}
+	if c.FuncOnWidthChanged == nil {
+		c.FuncOnWidthChanged = DefaultOnWidthChanged
+	}
+
+	return nil
+}
+
+func (c Config) Clone() *Config {
+	c.opHistory = nil
+	c.opSearch = nil
+	return &c
+}
+
+func (c *Config) SetListener(f func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)) {
+	c.Listener = FuncListener(f)
+}
+
+func (c *Config) SetPainter(p Painter) {
+	c.Painter = p
+}
+
+func NewEx(cfg *Config) (*Instance, error) {
+	t, err := NewTerminal(cfg)
+	if err != nil {
+		return nil, err
+	}
+	rl := t.Readline()
+	if cfg.Painter == nil {
+		cfg.Painter = &defaultPainter{}
+	}
+	return &Instance{
+		Config:    cfg,
+		Terminal:  t,
+		Operation: rl,
+	}, nil
+}
+
+func New(prompt string) (*Instance, error) {
+	return NewEx(&Config{Prompt: prompt})
+}
+
+func (i *Instance) ResetHistory() {
+	i.Operation.ResetHistory()
+}
+
+func (i *Instance) SetPrompt(s string) {
+	i.Operation.SetPrompt(s)
+}
+
+func (i *Instance) SetMaskRune(r rune) {
+	i.Operation.SetMaskRune(r)
+}
+
+// change history persistence in runtime
+func (i *Instance) SetHistoryPath(p string) {
+	i.Operation.SetHistoryPath(p)
+}
+
+// readline will refresh automatic when write through Stdout()
+func (i *Instance) Stdout() io.Writer {
+	return i.Operation.Stdout()
+}
+
+// readline will refresh automatic when write through Stdout()
+func (i *Instance) Stderr() io.Writer {
+	return i.Operation.Stderr()
+}
+
+// switch VimMode in runtime
+func (i *Instance) SetVimMode(on bool) {
+	i.Operation.SetVimMode(on)
+}
+
+func (i *Instance) IsVimMode() bool {
+	return i.Operation.IsEnableVimMode()
+}
+
+func (i *Instance) GenPasswordConfig() *Config {
+	return i.Operation.GenPasswordConfig()
+}
+
+// we can generate a config by `i.GenPasswordConfig()`
+func (i *Instance) ReadPasswordWithConfig(cfg *Config) ([]byte, error) {
+	return i.Operation.PasswordWithConfig(cfg)
+}
+
+func (i *Instance) ReadPasswordEx(prompt string, l Listener) ([]byte, error) {
+	return i.Operation.PasswordEx(prompt, l)
+}
+
+func (i *Instance) ReadPassword(prompt string) ([]byte, error) {
+	return i.Operation.Password(prompt)
+}
+
+type Result struct {
+	Line  string
+	Error error
+}
+
+func (l *Result) CanContinue() bool {
+	return len(l.Line) != 0 && l.Error == ErrInterrupt
+}
+
+func (l *Result) CanBreak() bool {
+	return !l.CanContinue() && l.Error != nil
+}
+
+func (i *Instance) Line() *Result {
+	ret, err := i.Readline()
+	return &Result{ret, err}
+}
+
+// err is one of (nil, io.EOF, readline.ErrInterrupt)
+func (i *Instance) Readline() (string, error) {
+	return i.Operation.String()
+}
+
+func (i *Instance) ReadlineWithDefault(what string) (string, error) {
+	i.Operation.SetBuffer(what)
+	return i.Operation.String()
+}
+
+func (i *Instance) SaveHistory(content string) error {
+	return i.Operation.SaveHistory(content)
+}
+
+// same as readline
+func (i *Instance) ReadSlice() ([]byte, error) {
+	return i.Operation.Slice()
+}
+
+// we must make sure that call Close() before process exit.
+func (i *Instance) Close() error {
+	if err := i.Terminal.Close(); err != nil {
+		return err
+	}
+	i.Config.Stdin.Close()
+	i.Operation.Close()
+	return nil
+}
+func (i *Instance) Clean() {
+	i.Operation.Clean()
+}
+
+func (i *Instance) Write(b []byte) (int, error) {
+	return i.Stdout().Write(b)
+}
+
+// WriteStdin prefill the next Stdin fetch
+// Next time you call ReadLine() this value will be writen before the user input
+// ie :
+//  i := readline.New()
+//  i.WriteStdin([]byte("test"))
+//  _, _= i.Readline()
+//
+// gives
+//
+// > test[cursor]
+func (i *Instance) WriteStdin(val []byte) (int, error) {
+	return i.Terminal.WriteStdin(val)
+}
+
+func (i *Instance) SetConfig(cfg *Config) *Config {
+	if i.Config == cfg {
+		return cfg
+	}
+	old := i.Config
+	i.Config = cfg
+	i.Operation.SetConfig(cfg)
+	i.Terminal.SetConfig(cfg)
+	return old
+}
+
+func (i *Instance) Refresh() {
+	i.Operation.Refresh()
+}
+
+// HistoryDisable the save of the commands into the history
+func (i *Instance) HistoryDisable() {
+	i.Operation.history.Disable()
+}
+
+// HistoryEnable the save of the commands into the history (default on)
+func (i *Instance) HistoryEnable() {
+	i.Operation.history.Enable()
+}
diff --git a/vendor/github.com/chzyer/readline/remote.go b/vendor/github.com/chzyer/readline/remote.go
new file mode 100644
index 0000000..74dbf56
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/remote.go
@@ -0,0 +1,475 @@
+package readline
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"net"
+	"os"
+	"sync"
+	"sync/atomic"
+)
+
+type MsgType int16
+
+const (
+	T_DATA = MsgType(iota)
+	T_WIDTH
+	T_WIDTH_REPORT
+	T_ISTTY_REPORT
+	T_RAW
+	T_ERAW // exit raw
+	T_EOF
+)
+
+type RemoteSvr struct {
+	eof           int32
+	closed        int32
+	width         int32
+	reciveChan    chan struct{}
+	writeChan     chan *writeCtx
+	conn          net.Conn
+	isTerminal    bool
+	funcWidthChan func()
+	stopChan      chan struct{}
+
+	dataBufM sync.Mutex
+	dataBuf  bytes.Buffer
+}
+
+type writeReply struct {
+	n   int
+	err error
+}
+
+type writeCtx struct {
+	msg   *Message
+	reply chan *writeReply
+}
+
+func newWriteCtx(msg *Message) *writeCtx {
+	return &writeCtx{
+		msg:   msg,
+		reply: make(chan *writeReply),
+	}
+}
+
+func NewRemoteSvr(conn net.Conn) (*RemoteSvr, error) {
+	rs := &RemoteSvr{
+		width:      -1,
+		conn:       conn,
+		writeChan:  make(chan *writeCtx),
+		reciveChan: make(chan struct{}),
+		stopChan:   make(chan struct{}),
+	}
+	buf := bufio.NewReader(rs.conn)
+
+	if err := rs.init(buf); err != nil {
+		return nil, err
+	}
+
+	go rs.readLoop(buf)
+	go rs.writeLoop()
+	return rs, nil
+}
+
+func (r *RemoteSvr) init(buf *bufio.Reader) error {
+	m, err := ReadMessage(buf)
+	if err != nil {
+		return err
+	}
+	// receive isTerminal
+	if m.Type != T_ISTTY_REPORT {
+		return fmt.Errorf("unexpected init message")
+	}
+	r.GotIsTerminal(m.Data)
+
+	// receive width
+	m, err = ReadMessage(buf)
+	if err != nil {
+		return err
+	}
+	if m.Type != T_WIDTH_REPORT {
+		return fmt.Errorf("unexpected init message")
+	}
+	r.GotReportWidth(m.Data)
+
+	return nil
+}
+
+func (r *RemoteSvr) HandleConfig(cfg *Config) {
+	cfg.Stderr = r
+	cfg.Stdout = r
+	cfg.Stdin = r
+	cfg.FuncExitRaw = r.ExitRawMode
+	cfg.FuncIsTerminal = r.IsTerminal
+	cfg.FuncMakeRaw = r.EnterRawMode
+	cfg.FuncExitRaw = r.ExitRawMode
+	cfg.FuncGetWidth = r.GetWidth
+	cfg.FuncOnWidthChanged = func(f func()) {
+		r.funcWidthChan = f
+	}
+}
+
+func (r *RemoteSvr) IsTerminal() bool {
+	return r.isTerminal
+}
+
+func (r *RemoteSvr) checkEOF() error {
+	if atomic.LoadInt32(&r.eof) == 1 {
+		return io.EOF
+	}
+	return nil
+}
+
+func (r *RemoteSvr) Read(b []byte) (int, error) {
+	r.dataBufM.Lock()
+	n, err := r.dataBuf.Read(b)
+	r.dataBufM.Unlock()
+	if n == 0 {
+		if err := r.checkEOF(); err != nil {
+			return 0, err
+		}
+	}
+
+	if n == 0 && err == io.EOF {
+		<-r.reciveChan
+		r.dataBufM.Lock()
+		n, err = r.dataBuf.Read(b)
+		r.dataBufM.Unlock()
+	}
+	if n == 0 {
+		if err := r.checkEOF(); err != nil {
+			return 0, err
+		}
+	}
+
+	return n, err
+}
+
+func (r *RemoteSvr) writeMsg(m *Message) error {
+	ctx := newWriteCtx(m)
+	r.writeChan <- ctx
+	reply := <-ctx.reply
+	return reply.err
+}
+
+func (r *RemoteSvr) Write(b []byte) (int, error) {
+	ctx := newWriteCtx(NewMessage(T_DATA, b))
+	r.writeChan <- ctx
+	reply := <-ctx.reply
+	return reply.n, reply.err
+}
+
+func (r *RemoteSvr) EnterRawMode() error {
+	return r.writeMsg(NewMessage(T_RAW, nil))
+}
+
+func (r *RemoteSvr) ExitRawMode() error {
+	return r.writeMsg(NewMessage(T_ERAW, nil))
+}
+
+func (r *RemoteSvr) writeLoop() {
+	defer r.Close()
+
+loop:
+	for {
+		select {
+		case ctx, ok := <-r.writeChan:
+			if !ok {
+				break
+			}
+			n, err := ctx.msg.WriteTo(r.conn)
+			ctx.reply <- &writeReply{n, err}
+		case <-r.stopChan:
+			break loop
+		}
+	}
+}
+
+func (r *RemoteSvr) Close() error {
+	if atomic.CompareAndSwapInt32(&r.closed, 0, 1) {
+		close(r.stopChan)
+		r.conn.Close()
+	}
+	return nil
+}
+
+func (r *RemoteSvr) readLoop(buf *bufio.Reader) {
+	defer r.Close()
+	for {
+		m, err := ReadMessage(buf)
+		if err != nil {
+			break
+		}
+		switch m.Type {
+		case T_EOF:
+			atomic.StoreInt32(&r.eof, 1)
+			select {
+			case r.reciveChan <- struct{}{}:
+			default:
+			}
+		case T_DATA:
+			r.dataBufM.Lock()
+			r.dataBuf.Write(m.Data)
+			r.dataBufM.Unlock()
+			select {
+			case r.reciveChan <- struct{}{}:
+			default:
+			}
+		case T_WIDTH_REPORT:
+			r.GotReportWidth(m.Data)
+		case T_ISTTY_REPORT:
+			r.GotIsTerminal(m.Data)
+		}
+	}
+}
+
+func (r *RemoteSvr) GotIsTerminal(data []byte) {
+	if binary.BigEndian.Uint16(data) == 0 {
+		r.isTerminal = false
+	} else {
+		r.isTerminal = true
+	}
+}
+
+func (r *RemoteSvr) GotReportWidth(data []byte) {
+	atomic.StoreInt32(&r.width, int32(binary.BigEndian.Uint16(data)))
+	if r.funcWidthChan != nil {
+		r.funcWidthChan()
+	}
+}
+
+func (r *RemoteSvr) GetWidth() int {
+	return int(atomic.LoadInt32(&r.width))
+}
+
+// -----------------------------------------------------------------------------
+
+type Message struct {
+	Type MsgType
+	Data []byte
+}
+
+func ReadMessage(r io.Reader) (*Message, error) {
+	m := new(Message)
+	var length int32
+	if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+		return nil, err
+	}
+	if err := binary.Read(r, binary.BigEndian, &m.Type); err != nil {
+		return nil, err
+	}
+	m.Data = make([]byte, int(length)-2)
+	if _, err := io.ReadFull(r, m.Data); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+func NewMessage(t MsgType, data []byte) *Message {
+	return &Message{t, data}
+}
+
+func (m *Message) WriteTo(w io.Writer) (int, error) {
+	buf := bytes.NewBuffer(make([]byte, 0, len(m.Data)+2+4))
+	binary.Write(buf, binary.BigEndian, int32(len(m.Data)+2))
+	binary.Write(buf, binary.BigEndian, m.Type)
+	buf.Write(m.Data)
+	n, err := buf.WriteTo(w)
+	return int(n), err
+}
+
+// -----------------------------------------------------------------------------
+
+type RemoteCli struct {
+	conn        net.Conn
+	raw         RawMode
+	receiveChan chan struct{}
+	inited      int32
+	isTerminal  *bool
+
+	data  bytes.Buffer
+	dataM sync.Mutex
+}
+
+func NewRemoteCli(conn net.Conn) (*RemoteCli, error) {
+	r := &RemoteCli{
+		conn:        conn,
+		receiveChan: make(chan struct{}),
+	}
+	return r, nil
+}
+
+func (r *RemoteCli) MarkIsTerminal(is bool) {
+	r.isTerminal = &is
+}
+
+func (r *RemoteCli) init() error {
+	if !atomic.CompareAndSwapInt32(&r.inited, 0, 1) {
+		return nil
+	}
+
+	if err := r.reportIsTerminal(); err != nil {
+		return err
+	}
+
+	if err := r.reportWidth(); err != nil {
+		return err
+	}
+
+	// register sig for width changed
+	DefaultOnWidthChanged(func() {
+		r.reportWidth()
+	})
+	return nil
+}
+
+func (r *RemoteCli) writeMsg(m *Message) error {
+	r.dataM.Lock()
+	_, err := m.WriteTo(r.conn)
+	r.dataM.Unlock()
+	return err
+}
+
+func (r *RemoteCli) Write(b []byte) (int, error) {
+	m := NewMessage(T_DATA, b)
+	r.dataM.Lock()
+	_, err := m.WriteTo(r.conn)
+	r.dataM.Unlock()
+	return len(b), err
+}
+
+func (r *RemoteCli) reportWidth() error {
+	screenWidth := GetScreenWidth()
+	data := make([]byte, 2)
+	binary.BigEndian.PutUint16(data, uint16(screenWidth))
+	msg := NewMessage(T_WIDTH_REPORT, data)
+
+	if err := r.writeMsg(msg); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *RemoteCli) reportIsTerminal() error {
+	var isTerminal bool
+	if r.isTerminal != nil {
+		isTerminal = *r.isTerminal
+	} else {
+		isTerminal = DefaultIsTerminal()
+	}
+	data := make([]byte, 2)
+	if isTerminal {
+		binary.BigEndian.PutUint16(data, 1)
+	} else {
+		binary.BigEndian.PutUint16(data, 0)
+	}
+	msg := NewMessage(T_ISTTY_REPORT, data)
+	if err := r.writeMsg(msg); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *RemoteCli) readLoop() {
+	buf := bufio.NewReader(r.conn)
+	for {
+		msg, err := ReadMessage(buf)
+		if err != nil {
+			break
+		}
+		switch msg.Type {
+		case T_ERAW:
+			r.raw.Exit()
+		case T_RAW:
+			r.raw.Enter()
+		case T_DATA:
+			os.Stdout.Write(msg.Data)
+		}
+	}
+}
+
+func (r *RemoteCli) ServeBy(source io.Reader) error {
+	if err := r.init(); err != nil {
+		return err
+	}
+
+	go func() {
+		defer r.Close()
+		for {
+			n, _ := io.Copy(r, source)
+			if n == 0 {
+				break
+			}
+		}
+	}()
+	defer r.raw.Exit()
+	r.readLoop()
+	return nil
+}
+
+func (r *RemoteCli) Close() {
+	r.writeMsg(NewMessage(T_EOF, nil))
+}
+
+func (r *RemoteCli) Serve() error {
+	return r.ServeBy(os.Stdin)
+}
+
+func ListenRemote(n, addr string, cfg *Config, h func(*Instance), onListen ...func(net.Listener) error) error {
+	ln, err := net.Listen(n, addr)
+	if err != nil {
+		return err
+	}
+	if len(onListen) > 0 {
+		if err := onListen[0](ln); err != nil {
+			return err
+		}
+	}
+	for {
+		conn, err := ln.Accept()
+		if err != nil {
+			break
+		}
+		go func() {
+			defer conn.Close()
+			rl, err := HandleConn(*cfg, conn)
+			if err != nil {
+				return
+			}
+			h(rl)
+		}()
+	}
+	return nil
+}
+
+func HandleConn(cfg Config, conn net.Conn) (*Instance, error) {
+	r, err := NewRemoteSvr(conn)
+	if err != nil {
+		return nil, err
+	}
+	r.HandleConfig(&cfg)
+
+	rl, err := NewEx(&cfg)
+	if err != nil {
+		return nil, err
+	}
+	return rl, nil
+}
+
+func DialRemote(n, addr string) error {
+	conn, err := net.Dial(n, addr)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+
+	cli, err := NewRemoteCli(conn)
+	if err != nil {
+		return err
+	}
+	return cli.Serve()
+}
diff --git a/vendor/github.com/chzyer/readline/runebuf.go b/vendor/github.com/chzyer/readline/runebuf.go
new file mode 100644
index 0000000..81d2da5
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/runebuf.go
@@ -0,0 +1,629 @@
+package readline
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+type runeBufferBck struct {
+	buf []rune
+	idx int
+}
+
+type RuneBuffer struct {
+	buf    []rune
+	idx    int
+	prompt []rune
+	w      io.Writer
+
+	hadClean    bool
+	interactive bool
+	cfg         *Config
+
+	width int
+
+	bck *runeBufferBck
+
+	offset string
+
+	lastKill []rune
+
+	sync.Mutex
+}
+
+func (r* RuneBuffer) pushKill(text []rune) {
+	r.lastKill = append([]rune{}, text...)
+}
+
+func (r *RuneBuffer) OnWidthChange(newWidth int) {
+	r.Lock()
+	r.width = newWidth
+	r.Unlock()
+}
+
+func (r *RuneBuffer) Backup() {
+	r.Lock()
+	r.bck = &runeBufferBck{r.buf, r.idx}
+	r.Unlock()
+}
+
+func (r *RuneBuffer) Restore() {
+	r.Refresh(func() {
+		if r.bck == nil {
+			return
+		}
+		r.buf = r.bck.buf
+		r.idx = r.bck.idx
+	})
+}
+
+func NewRuneBuffer(w io.Writer, prompt string, cfg *Config, width int) *RuneBuffer {
+	rb := &RuneBuffer{
+		w:           w,
+		interactive: cfg.useInteractive(),
+		cfg:         cfg,
+		width:       width,
+	}
+	rb.SetPrompt(prompt)
+	return rb
+}
+
+func (r *RuneBuffer) SetConfig(cfg *Config) {
+	r.Lock()
+	r.cfg = cfg
+	r.interactive = cfg.useInteractive()
+	r.Unlock()
+}
+
+func (r *RuneBuffer) SetMask(m rune) {
+	r.Lock()
+	r.cfg.MaskRune = m
+	r.Unlock()
+}
+
+func (r *RuneBuffer) CurrentWidth(x int) int {
+	r.Lock()
+	defer r.Unlock()
+	return runes.WidthAll(r.buf[:x])
+}
+
+func (r *RuneBuffer) PromptLen() int {
+	r.Lock()
+	width := r.promptLen()
+	r.Unlock()
+	return width
+}
+
+func (r *RuneBuffer) promptLen() int {
+	return runes.WidthAll(runes.ColorFilter(r.prompt))
+}
+
+func (r *RuneBuffer) RuneSlice(i int) []rune {
+	r.Lock()
+	defer r.Unlock()
+
+	if i > 0 {
+		rs := make([]rune, i)
+		copy(rs, r.buf[r.idx:r.idx+i])
+		return rs
+	}
+	rs := make([]rune, -i)
+	copy(rs, r.buf[r.idx+i:r.idx])
+	return rs
+}
+
+func (r *RuneBuffer) Runes() []rune {
+	r.Lock()
+	newr := make([]rune, len(r.buf))
+	copy(newr, r.buf)
+	r.Unlock()
+	return newr
+}
+
+func (r *RuneBuffer) Pos() int {
+	r.Lock()
+	defer r.Unlock()
+	return r.idx
+}
+
+func (r *RuneBuffer) Len() int {
+	r.Lock()
+	defer r.Unlock()
+	return len(r.buf)
+}
+
+func (r *RuneBuffer) MoveToLineStart() {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+		r.idx = 0
+	})
+}
+
+func (r *RuneBuffer) MoveBackward() {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+		r.idx--
+	})
+}
+
+func (r *RuneBuffer) WriteString(s string) {
+	r.WriteRunes([]rune(s))
+}
+
+func (r *RuneBuffer) WriteRune(s rune) {
+	r.WriteRunes([]rune{s})
+}
+
+func (r *RuneBuffer) WriteRunes(s []rune) {
+	r.Refresh(func() {
+		tail := append(s, r.buf[r.idx:]...)
+		r.buf = append(r.buf[:r.idx], tail...)
+		r.idx += len(s)
+	})
+}
+
+func (r *RuneBuffer) MoveForward() {
+	r.Refresh(func() {
+		if r.idx == len(r.buf) {
+			return
+		}
+		r.idx++
+	})
+}
+
+func (r *RuneBuffer) IsCursorInEnd() bool {
+	r.Lock()
+	defer r.Unlock()
+	return r.idx == len(r.buf)
+}
+
+func (r *RuneBuffer) Replace(ch rune) {
+	r.Refresh(func() {
+		r.buf[r.idx] = ch
+	})
+}
+
+func (r *RuneBuffer) Erase() {
+	r.Refresh(func() {
+		r.idx = 0
+		r.pushKill(r.buf[:])
+		r.buf = r.buf[:0]
+	})
+}
+
+func (r *RuneBuffer) Delete() (success bool) {
+	r.Refresh(func() {
+		if r.idx == len(r.buf) {
+			return
+		}
+		r.pushKill(r.buf[r.idx : r.idx+1])
+		r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
+		success = true
+	})
+	return
+}
+
+func (r *RuneBuffer) DeleteWord() {
+	if r.idx == len(r.buf) {
+		return
+	}
+	init := r.idx
+	for init < len(r.buf) && IsWordBreak(r.buf[init]) {
+		init++
+	}
+	for i := init + 1; i < len(r.buf); i++ {
+		if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
+			r.pushKill(r.buf[r.idx:i-1])
+			r.Refresh(func() {
+				r.buf = append(r.buf[:r.idx], r.buf[i-1:]...)
+			})
+			return
+		}
+	}
+	r.Kill()
+}
+
+func (r *RuneBuffer) MoveToPrevWord() (success bool) {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+
+		for i := r.idx - 1; i > 0; i-- {
+			if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
+				r.idx = i
+				success = true
+				return
+			}
+		}
+		r.idx = 0
+		success = true
+	})
+	return
+}
+
+func (r *RuneBuffer) KillFront() {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+
+		length := len(r.buf) - r.idx
+		r.pushKill(r.buf[:r.idx])
+		copy(r.buf[:length], r.buf[r.idx:])
+		r.idx = 0
+		r.buf = r.buf[:length]
+	})
+}
+
+func (r *RuneBuffer) Kill() {
+	r.Refresh(func() {
+		r.pushKill(r.buf[r.idx:])
+		r.buf = r.buf[:r.idx]
+	})
+}
+
+func (r *RuneBuffer) Transpose() {
+	r.Refresh(func() {
+		if len(r.buf) == 1 {
+			r.idx++
+		}
+
+		if len(r.buf) < 2 {
+			return
+		}
+
+		if r.idx == 0 {
+			r.idx = 1
+		} else if r.idx >= len(r.buf) {
+			r.idx = len(r.buf) - 1
+		}
+		r.buf[r.idx], r.buf[r.idx-1] = r.buf[r.idx-1], r.buf[r.idx]
+		r.idx++
+	})
+}
+
+func (r *RuneBuffer) MoveToNextWord() {
+	r.Refresh(func() {
+		for i := r.idx + 1; i < len(r.buf); i++ {
+			if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
+				r.idx = i
+				return
+			}
+		}
+
+		r.idx = len(r.buf)
+	})
+}
+
+func (r *RuneBuffer) MoveToEndWord() {
+	r.Refresh(func() {
+		// already at the end, so do nothing
+		if r.idx == len(r.buf) {
+			return
+		}
+		// if we are at the end of a word already, go to next
+		if !IsWordBreak(r.buf[r.idx]) && IsWordBreak(r.buf[r.idx+1]) {
+			r.idx++
+		}
+
+		// keep going until at the end of a word
+		for i := r.idx + 1; i < len(r.buf); i++ {
+			if IsWordBreak(r.buf[i]) && !IsWordBreak(r.buf[i-1]) {
+				r.idx = i - 1
+				return
+			}
+		}
+		r.idx = len(r.buf)
+	})
+}
+
+func (r *RuneBuffer) BackEscapeWord() {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+		for i := r.idx - 1; i > 0; i-- {
+			if !IsWordBreak(r.buf[i]) && IsWordBreak(r.buf[i-1]) {
+				r.pushKill(r.buf[i:r.idx])
+				r.buf = append(r.buf[:i], r.buf[r.idx:]...)
+				r.idx = i
+				return
+			}
+		}
+
+		r.buf = r.buf[:0]
+		r.idx = 0
+	})
+}
+
+func (r *RuneBuffer) Yank() {
+	if len(r.lastKill) == 0 {
+		return
+	}
+	r.Refresh(func() {
+		buf := make([]rune, 0, len(r.buf) + len(r.lastKill))
+		buf = append(buf, r.buf[:r.idx]...)
+		buf = append(buf, r.lastKill...)
+		buf = append(buf, r.buf[r.idx:]...)
+		r.buf = buf
+		r.idx += len(r.lastKill)
+	})
+}
+
+func (r *RuneBuffer) Backspace() {
+	r.Refresh(func() {
+		if r.idx == 0 {
+			return
+		}
+
+		r.idx--
+		r.buf = append(r.buf[:r.idx], r.buf[r.idx+1:]...)
+	})
+}
+
+func (r *RuneBuffer) MoveToLineEnd() {
+	r.Refresh(func() {
+		if r.idx == len(r.buf) {
+			return
+		}
+
+		r.idx = len(r.buf)
+	})
+}
+
+func (r *RuneBuffer) LineCount(width int) int {
+	if width == -1 {
+		width = r.width
+	}
+	return LineCount(width,
+		runes.WidthAll(r.buf)+r.PromptLen())
+}
+
+func (r *RuneBuffer) MoveTo(ch rune, prevChar, reverse bool) (success bool) {
+	r.Refresh(func() {
+		if reverse {
+			for i := r.idx - 1; i >= 0; i-- {
+				if r.buf[i] == ch {
+					r.idx = i
+					if prevChar {
+						r.idx++
+					}
+					success = true
+					return
+				}
+			}
+			return
+		}
+		for i := r.idx + 1; i < len(r.buf); i++ {
+			if r.buf[i] == ch {
+				r.idx = i
+				if prevChar {
+					r.idx--
+				}
+				success = true
+				return
+			}
+		}
+	})
+	return
+}
+
+func (r *RuneBuffer) isInLineEdge() bool {
+	if isWindows {
+		return false
+	}
+	sp := r.getSplitByLine(r.buf)
+	return len(sp[len(sp)-1]) == 0
+}
+
+func (r *RuneBuffer) getSplitByLine(rs []rune) []string {
+	return SplitByLine(r.promptLen(), r.width, rs)
+}
+
+func (r *RuneBuffer) IdxLine(width int) int {
+	r.Lock()
+	defer r.Unlock()
+	return r.idxLine(width)
+}
+
+func (r *RuneBuffer) idxLine(width int) int {
+	if width == 0 {
+		return 0
+	}
+	sp := r.getSplitByLine(r.buf[:r.idx])
+	return len(sp) - 1
+}
+
+func (r *RuneBuffer) CursorLineCount() int {
+	return r.LineCount(r.width) - r.IdxLine(r.width)
+}
+
+func (r *RuneBuffer) Refresh(f func()) {
+	r.Lock()
+	defer r.Unlock()
+
+	if !r.interactive {
+		if f != nil {
+			f()
+		}
+		return
+	}
+
+	r.clean()
+	if f != nil {
+		f()
+	}
+	r.print()
+}
+
+func (r *RuneBuffer) SetOffset(offset string) {
+	r.Lock()
+	r.offset = offset
+	r.Unlock()
+}
+
+func (r *RuneBuffer) print() {
+	r.w.Write(r.output())
+	r.hadClean = false
+}
+
+func (r *RuneBuffer) output() []byte {
+	buf := bytes.NewBuffer(nil)
+	buf.WriteString(string(r.prompt))
+	if r.cfg.EnableMask && len(r.buf) > 0 {
+		buf.Write([]byte(strings.Repeat(string(r.cfg.MaskRune), len(r.buf)-1)))
+		if r.buf[len(r.buf)-1] == '\n' {
+			buf.Write([]byte{'\n'})
+		} else {
+			buf.Write([]byte(string(r.cfg.MaskRune)))
+		}
+		if len(r.buf) > r.idx {
+			buf.Write(r.getBackspaceSequence())
+		}
+
+	} else {
+		for _, e := range r.cfg.Painter.Paint(r.buf, r.idx) {
+			if e == '\t' {
+				buf.WriteString(strings.Repeat(" ", TabWidth))
+			} else {
+				buf.WriteRune(e)
+			}
+		}
+		if r.isInLineEdge() {
+			buf.Write([]byte(" \b"))
+		}
+	}
+	// cursor position
+	if len(r.buf) > r.idx {
+		buf.Write(r.getBackspaceSequence())
+	}
+	return buf.Bytes()
+}
+
+func (r *RuneBuffer) getBackspaceSequence() []byte {
+	var sep = map[int]bool{}
+
+	var i int
+	for {
+		if i >= runes.WidthAll(r.buf) {
+			break
+		}
+
+		if i == 0 {
+			i -= r.promptLen()
+		}
+		i += r.width
+
+		sep[i] = true
+	}
+	var buf []byte
+	for i := len(r.buf); i > r.idx; i-- {
+		// move input to the left of one
+		buf = append(buf, '\b')
+		if sep[i] {
+			// up one line, go to the start of the line and move cursor right to the end (r.width)
+			buf = append(buf, "\033[A\r"+"\033["+strconv.Itoa(r.width)+"C"...)
+		}
+	}
+
+	return buf
+
+}
+
+func (r *RuneBuffer) Reset() []rune {
+	ret := runes.Copy(r.buf)
+	r.buf = r.buf[:0]
+	r.idx = 0
+	return ret
+}
+
+func (r *RuneBuffer) calWidth(m int) int {
+	if m > 0 {
+		return runes.WidthAll(r.buf[r.idx : r.idx+m])
+	}
+	return runes.WidthAll(r.buf[r.idx+m : r.idx])
+}
+
+func (r *RuneBuffer) SetStyle(start, end int, style string) {
+	if end < start {
+		panic("end < start")
+	}
+
+	// goto start
+	move := start - r.idx
+	if move > 0 {
+		r.w.Write([]byte(string(r.buf[r.idx : r.idx+move])))
+	} else {
+		r.w.Write(bytes.Repeat([]byte("\b"), r.calWidth(move)))
+	}
+	r.w.Write([]byte("\033[" + style + "m"))
+	r.w.Write([]byte(string(r.buf[start:end])))
+	r.w.Write([]byte("\033[0m"))
+	// TODO: move back
+}
+
+func (r *RuneBuffer) SetWithIdx(idx int, buf []rune) {
+	r.Refresh(func() {
+		r.buf = buf
+		r.idx = idx
+	})
+}
+
+func (r *RuneBuffer) Set(buf []rune) {
+	r.SetWithIdx(len(buf), buf)
+}
+
+func (r *RuneBuffer) SetPrompt(prompt string) {
+	r.Lock()
+	r.prompt = []rune(prompt)
+	r.Unlock()
+}
+
+func (r *RuneBuffer) cleanOutput(w io.Writer, idxLine int) {
+	buf := bufio.NewWriter(w)
+
+	if r.width == 0 {
+		buf.WriteString(strings.Repeat("\r\b", len(r.buf)+r.promptLen()))
+		buf.Write([]byte("\033[J"))
+	} else {
+		buf.Write([]byte("\033[J")) // just like ^k :)
+		if idxLine == 0 {
+			buf.WriteString("\033[2K")
+			buf.WriteString("\r")
+		} else {
+			for i := 0; i < idxLine; i++ {
+				io.WriteString(buf, "\033[2K\r\033[A")
+			}
+			io.WriteString(buf, "\033[2K\r")
+		}
+	}
+	buf.Flush()
+	return
+}
+
+func (r *RuneBuffer) Clean() {
+	r.Lock()
+	r.clean()
+	r.Unlock()
+}
+
+func (r *RuneBuffer) clean() {
+	r.cleanWithIdxLine(r.idxLine(r.width))
+}
+
+func (r *RuneBuffer) cleanWithIdxLine(idxLine int) {
+	if r.hadClean || !r.interactive {
+		return
+	}
+	r.hadClean = true
+	r.cleanOutput(r.w, idxLine)
+}
diff --git a/vendor/github.com/chzyer/readline/runes.go b/vendor/github.com/chzyer/readline/runes.go
new file mode 100644
index 0000000..a669bc4
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/runes.go
@@ -0,0 +1,223 @@
+package readline
+
+import (
+	"bytes"
+	"unicode"
+	"unicode/utf8"
+)
+
+var runes = Runes{}
+var TabWidth = 4
+
+type Runes struct{}
+
+func (Runes) EqualRune(a, b rune, fold bool) bool {
+	if a == b {
+		return true
+	}
+	if !fold {
+		return false
+	}
+	if a > b {
+		a, b = b, a
+	}
+	if b < utf8.RuneSelf && 'A' <= a && a <= 'Z' {
+		if b == a+'a'-'A' {
+			return true
+		}
+	}
+	return false
+}
+
+func (r Runes) EqualRuneFold(a, b rune) bool {
+	return r.EqualRune(a, b, true)
+}
+
+func (r Runes) EqualFold(a, b []rune) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := 0; i < len(a); i++ {
+		if r.EqualRuneFold(a[i], b[i]) {
+			continue
+		}
+		return false
+	}
+
+	return true
+}
+
+func (Runes) Equal(a, b []rune) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int {
+	for i := len(r) - len(sub); i >= 0; i-- {
+		found := true
+		for j := 0; j < len(sub); j++ {
+			if !rs.EqualRune(r[i+j], sub[j], fold) {
+				found = false
+				break
+			}
+		}
+		if found {
+			return i
+		}
+	}
+	return -1
+}
+
+// Search in runes from end to front
+func (rs Runes) IndexAllBck(r, sub []rune) int {
+	return rs.IndexAllBckEx(r, sub, false)
+}
+
+// Search in runes from front to end
+func (rs Runes) IndexAll(r, sub []rune) int {
+	return rs.IndexAllEx(r, sub, false)
+}
+
+func (rs Runes) IndexAllEx(r, sub []rune, fold bool) int {
+	for i := 0; i < len(r); i++ {
+		found := true
+		if len(r[i:]) < len(sub) {
+			return -1
+		}
+		for j := 0; j < len(sub); j++ {
+			if !rs.EqualRune(r[i+j], sub[j], fold) {
+				found = false
+				break
+			}
+		}
+		if found {
+			return i
+		}
+	}
+	return -1
+}
+
+func (Runes) Index(r rune, rs []rune) int {
+	for i := 0; i < len(rs); i++ {
+		if rs[i] == r {
+			return i
+		}
+	}
+	return -1
+}
+
+func (Runes) ColorFilter(r []rune) []rune {
+	newr := make([]rune, 0, len(r))
+	for pos := 0; pos < len(r); pos++ {
+		if r[pos] == '\033' && r[pos+1] == '[' {
+			idx := runes.Index('m', r[pos+2:])
+			if idx == -1 {
+				continue
+			}
+			pos += idx + 2
+			continue
+		}
+		newr = append(newr, r[pos])
+	}
+	return newr
+}
+
+var zeroWidth = []*unicode.RangeTable{
+	unicode.Mn,
+	unicode.Me,
+	unicode.Cc,
+	unicode.Cf,
+}
+
+var doubleWidth = []*unicode.RangeTable{
+	unicode.Han,
+	unicode.Hangul,
+	unicode.Hiragana,
+	unicode.Katakana,
+}
+
+func (Runes) Width(r rune) int {
+	if r == '\t' {
+		return TabWidth
+	}
+	if unicode.IsOneOf(zeroWidth, r) {
+		return 0
+	}
+	if unicode.IsOneOf(doubleWidth, r) {
+		return 2
+	}
+	return 1
+}
+
+func (Runes) WidthAll(r []rune) (length int) {
+	for i := 0; i < len(r); i++ {
+		length += runes.Width(r[i])
+	}
+	return
+}
+
+func (Runes) Backspace(r []rune) []byte {
+	return bytes.Repeat([]byte{'\b'}, runes.WidthAll(r))
+}
+
+func (Runes) Copy(r []rune) []rune {
+	n := make([]rune, len(r))
+	copy(n, r)
+	return n
+}
+
+func (Runes) HasPrefixFold(r, prefix []rune) bool {
+	if len(r) < len(prefix) {
+		return false
+	}
+	return runes.EqualFold(r[:len(prefix)], prefix)
+}
+
+func (Runes) HasPrefix(r, prefix []rune) bool {
+	if len(r) < len(prefix) {
+		return false
+	}
+	return runes.Equal(r[:len(prefix)], prefix)
+}
+
+func (Runes) Aggregate(candicate [][]rune) (same []rune, size int) {
+	for i := 0; i < len(candicate[0]); i++ {
+		for j := 0; j < len(candicate)-1; j++ {
+			if i >= len(candicate[j]) || i >= len(candicate[j+1]) {
+				goto aggregate
+			}
+			if candicate[j][i] != candicate[j+1][i] {
+				goto aggregate
+			}
+		}
+		size = i + 1
+	}
+aggregate:
+	if size > 0 {
+		same = runes.Copy(candicate[0][:size])
+		for i := 0; i < len(candicate); i++ {
+			n := runes.Copy(candicate[i])
+			copy(n, n[size:])
+			candicate[i] = n[:len(n)-size]
+		}
+	}
+	return
+}
+
+func (Runes) TrimSpaceLeft(in []rune) []rune {
+	firstIndex := len(in)
+	for i, r := range in {
+		if unicode.IsSpace(r) == false {
+			firstIndex = i
+			break
+		}
+	}
+	return in[firstIndex:]
+}
diff --git a/vendor/github.com/chzyer/readline/runes/runes.go b/vendor/github.com/chzyer/readline/runes/runes.go
new file mode 100644
index 0000000..b069440
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/runes/runes.go
@@ -0,0 +1,155 @@
+// deprecated.
+// see https://github.com/chzyer/readline/issues/43
+// use github.com/chzyer/readline/runes.go
+package runes
+
+import (
+	"bytes"
+	"unicode"
+)
+
+func Equal(a, b []rune) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := 0; i < len(a); i++ {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// Search in runes from end to front
+func IndexAllBck(r, sub []rune) int {
+	for i := len(r) - len(sub); i >= 0; i-- {
+		found := true
+		for j := 0; j < len(sub); j++ {
+			if r[i+j] != sub[j] {
+				found = false
+				break
+			}
+		}
+		if found {
+			return i
+		}
+	}
+	return -1
+}
+
+// Search in runes from front to end
+func IndexAll(r, sub []rune) int {
+	for i := 0; i < len(r); i++ {
+		found := true
+		if len(r[i:]) < len(sub) {
+			return -1
+		}
+		for j := 0; j < len(sub); j++ {
+			if r[i+j] != sub[j] {
+				found = false
+				break
+			}
+		}
+		if found {
+			return i
+		}
+	}
+	return -1
+}
+
+func Index(r rune, rs []rune) int {
+	for i := 0; i < len(rs); i++ {
+		if rs[i] == r {
+			return i
+		}
+	}
+	return -1
+}
+
+func ColorFilter(r []rune) []rune {
+	newr := make([]rune, 0, len(r))
+	for pos := 0; pos < len(r); pos++ {
+		if r[pos] == '\033' && r[pos+1] == '[' {
+			idx := Index('m', r[pos+2:])
+			if idx == -1 {
+				continue
+			}
+			pos += idx + 2
+			continue
+		}
+		newr = append(newr, r[pos])
+	}
+	return newr
+}
+
+var zeroWidth = []*unicode.RangeTable{
+	unicode.Mn,
+	unicode.Me,
+	unicode.Cc,
+	unicode.Cf,
+}
+
+var doubleWidth = []*unicode.RangeTable{
+	unicode.Han,
+	unicode.Hangul,
+	unicode.Hiragana,
+	unicode.Katakana,
+}
+
+func Width(r rune) int {
+	if unicode.IsOneOf(zeroWidth, r) {
+		return 0
+	}
+	if unicode.IsOneOf(doubleWidth, r) {
+		return 2
+	}
+	return 1
+}
+
+func WidthAll(r []rune) (length int) {
+	for i := 0; i < len(r); i++ {
+		length += Width(r[i])
+	}
+	return
+}
+
+func Backspace(r []rune) []byte {
+	return bytes.Repeat([]byte{'\b'}, WidthAll(r))
+}
+
+func Copy(r []rune) []rune {
+	n := make([]rune, len(r))
+	copy(n, r)
+	return n
+}
+
+func HasPrefix(r, prefix []rune) bool {
+	if len(r) < len(prefix) {
+		return false
+	}
+	return Equal(r[:len(prefix)], prefix)
+}
+
+func Aggregate(candicate [][]rune) (same []rune, size int) {
+	for i := 0; i < len(candicate[0]); i++ {
+		for j := 0; j < len(candicate)-1; j++ {
+			if i >= len(candicate[j]) || i >= len(candicate[j+1]) {
+				goto aggregate
+			}
+			if candicate[j][i] != candicate[j+1][i] {
+				goto aggregate
+			}
+		}
+		size = i + 1
+	}
+aggregate:
+	if size > 0 {
+		same = Copy(candicate[0][:size])
+		for i := 0; i < len(candicate); i++ {
+			n := Copy(candicate[i])
+			copy(n, n[size:])
+			candicate[i] = n[:len(n)-size]
+		}
+	}
+	return
+}
diff --git a/vendor/github.com/chzyer/readline/search.go b/vendor/github.com/chzyer/readline/search.go
new file mode 100644
index 0000000..52e8ff0
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/search.go
@@ -0,0 +1,164 @@
+package readline
+
+import (
+	"bytes"
+	"container/list"
+	"fmt"
+	"io"
+)
+
+const (
+	S_STATE_FOUND = iota
+	S_STATE_FAILING
+)
+
+const (
+	S_DIR_BCK = iota
+	S_DIR_FWD
+)
+
+type opSearch struct {
+	inMode    bool
+	state     int
+	dir       int
+	source    *list.Element
+	w         io.Writer
+	buf       *RuneBuffer
+	data      []rune
+	history   *opHistory
+	cfg       *Config
+	markStart int
+	markEnd   int
+	width     int
+}
+
+func newOpSearch(w io.Writer, buf *RuneBuffer, history *opHistory, cfg *Config, width int) *opSearch {
+	return &opSearch{
+		w:       w,
+		buf:     buf,
+		cfg:     cfg,
+		history: history,
+		width:   width,
+	}
+}
+
+func (o *opSearch) OnWidthChange(newWidth int) {
+	o.width = newWidth
+}
+
+func (o *opSearch) IsSearchMode() bool {
+	return o.inMode
+}
+
+func (o *opSearch) SearchBackspace() {
+	if len(o.data) > 0 {
+		o.data = o.data[:len(o.data)-1]
+		o.search(true)
+	}
+}
+
+func (o *opSearch) findHistoryBy(isNewSearch bool) (int, *list.Element) {
+	if o.dir == S_DIR_BCK {
+		return o.history.FindBck(isNewSearch, o.data, o.buf.idx)
+	}
+	return o.history.FindFwd(isNewSearch, o.data, o.buf.idx)
+}
+
+func (o *opSearch) search(isChange bool) bool {
+	if len(o.data) == 0 {
+		o.state = S_STATE_FOUND
+		o.SearchRefresh(-1)
+		return true
+	}
+	idx, elem := o.findHistoryBy(isChange)
+	if elem == nil {
+		o.SearchRefresh(-2)
+		return false
+	}
+	o.history.current = elem
+
+	item := o.history.showItem(o.history.current.Value)
+	start, end := 0, 0
+	if o.dir == S_DIR_BCK {
+		start, end = idx, idx+len(o.data)
+	} else {
+		start, end = idx, idx+len(o.data)
+		idx += len(o.data)
+	}
+	o.buf.SetWithIdx(idx, item)
+	o.markStart, o.markEnd = start, end
+	o.SearchRefresh(idx)
+	return true
+}
+
+func (o *opSearch) SearchChar(r rune) {
+	o.data = append(o.data, r)
+	o.search(true)
+}
+
+func (o *opSearch) SearchMode(dir int) bool {
+	if o.width == 0 {
+		return false
+	}
+	alreadyInMode := o.inMode
+	o.inMode = true
+	o.dir = dir
+	o.source = o.history.current
+	if alreadyInMode {
+		o.search(false)
+	} else {
+		o.SearchRefresh(-1)
+	}
+	return true
+}
+
+func (o *opSearch) ExitSearchMode(revert bool) {
+	if revert {
+		o.history.current = o.source
+		o.buf.Set(o.history.showItem(o.history.current.Value))
+	}
+	o.markStart, o.markEnd = 0, 0
+	o.state = S_STATE_FOUND
+	o.inMode = false
+	o.source = nil
+	o.data = nil
+}
+
+func (o *opSearch) SearchRefresh(x int) {
+	if x == -2 {
+		o.state = S_STATE_FAILING
+	} else if x >= 0 {
+		o.state = S_STATE_FOUND
+	}
+	if x < 0 {
+		x = o.buf.idx
+	}
+	x = o.buf.CurrentWidth(x)
+	x += o.buf.PromptLen()
+	x = x % o.width
+
+	if o.markStart > 0 {
+		o.buf.SetStyle(o.markStart, o.markEnd, "4")
+	}
+
+	lineCnt := o.buf.CursorLineCount()
+	buf := bytes.NewBuffer(nil)
+	buf.Write(bytes.Repeat([]byte("\n"), lineCnt))
+	buf.WriteString("\033[J")
+	if o.state == S_STATE_FAILING {
+		buf.WriteString("failing ")
+	}
+	if o.dir == S_DIR_BCK {
+		buf.WriteString("bck")
+	} else if o.dir == S_DIR_FWD {
+		buf.WriteString("fwd")
+	}
+	buf.WriteString("-i-search: ")
+	buf.WriteString(string(o.data))         // keyword
+	buf.WriteString("\033[4m \033[0m")      // _
+	fmt.Fprintf(buf, "\r\033[%dA", lineCnt) // move prev
+	if x > 0 {
+		fmt.Fprintf(buf, "\033[%dC", x) // move forward
+	}
+	o.w.Write(buf.Bytes())
+}
diff --git a/vendor/github.com/chzyer/readline/std.go b/vendor/github.com/chzyer/readline/std.go
new file mode 100644
index 0000000..61d44b7
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/std.go
@@ -0,0 +1,197 @@
+package readline
+
+import (
+	"io"
+	"os"
+	"sync"
+	"sync/atomic"
+)
+
+var (
+	Stdin  io.ReadCloser  = os.Stdin
+	Stdout io.WriteCloser = os.Stdout
+	Stderr io.WriteCloser = os.Stderr
+)
+
+var (
+	std     *Instance
+	stdOnce sync.Once
+)
+
+// global instance will not submit history automatic
+func getInstance() *Instance {
+	stdOnce.Do(func() {
+		std, _ = NewEx(&Config{
+			DisableAutoSaveHistory: true,
+		})
+	})
+	return std
+}
+
+// let readline load history from filepath
+// and try to persist history into disk
+// set fp to "" to prevent readline persisting history to disk
+// so the `AddHistory` will return nil error forever.
+func SetHistoryPath(fp string) {
+	ins := getInstance()
+	cfg := ins.Config.Clone()
+	cfg.HistoryFile = fp
+	ins.SetConfig(cfg)
+}
+
+// set auto completer to global instance
+func SetAutoComplete(completer AutoCompleter) {
+	ins := getInstance()
+	cfg := ins.Config.Clone()
+	cfg.AutoComplete = completer
+	ins.SetConfig(cfg)
+}
+
+// add history to global instance manually
+// raise error only if `SetHistoryPath` is set with a non-empty path
+func AddHistory(content string) error {
+	ins := getInstance()
+	return ins.SaveHistory(content)
+}
+
+func Password(prompt string) ([]byte, error) {
+	ins := getInstance()
+	return ins.ReadPassword(prompt)
+}
+
+// readline with global configs
+func Line(prompt string) (string, error) {
+	ins := getInstance()
+	ins.SetPrompt(prompt)
+	return ins.Readline()
+}
+
+type CancelableStdin struct {
+	r      io.Reader
+	mutex  sync.Mutex
+	stop   chan struct{}
+	closed int32
+	notify chan struct{}
+	data   []byte
+	read   int
+	err    error
+}
+
+func NewCancelableStdin(r io.Reader) *CancelableStdin {
+	c := &CancelableStdin{
+		r:      r,
+		notify: make(chan struct{}),
+		stop:   make(chan struct{}),
+	}
+	go c.ioloop()
+	return c
+}
+
+func (c *CancelableStdin) ioloop() {
+loop:
+	for {
+		select {
+		case <-c.notify:
+			c.read, c.err = c.r.Read(c.data)
+			select {
+			case c.notify <- struct{}{}:
+			case <-c.stop:
+				break loop
+			}
+		case <-c.stop:
+			break loop
+		}
+	}
+}
+
+func (c *CancelableStdin) Read(b []byte) (n int, err error) {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	if atomic.LoadInt32(&c.closed) == 1 {
+		return 0, io.EOF
+	}
+
+	c.data = b
+	select {
+	case c.notify <- struct{}{}:
+	case <-c.stop:
+		return 0, io.EOF
+	}
+	select {
+	case <-c.notify:
+		return c.read, c.err
+	case <-c.stop:
+		return 0, io.EOF
+	}
+}
+
+func (c *CancelableStdin) Close() error {
+	if atomic.CompareAndSwapInt32(&c.closed, 0, 1) {
+		close(c.stop)
+	}
+	return nil
+}
+
+// FillableStdin is a stdin reader which can prepend some data before
+// reading into the real stdin
+type FillableStdin struct {
+	sync.Mutex
+	stdin       io.Reader
+	stdinBuffer io.ReadCloser
+	buf         []byte
+	bufErr      error
+}
+
+// NewFillableStdin gives you FillableStdin
+func NewFillableStdin(stdin io.Reader) (io.ReadCloser, io.Writer) {
+	r, w := io.Pipe()
+	s := &FillableStdin{
+		stdinBuffer: r,
+		stdin:       stdin,
+	}
+	s.ioloop()
+	return s, w
+}
+
+func (s *FillableStdin) ioloop() {
+	go func() {
+		for {
+			bufR := make([]byte, 100)
+			var n int
+			n, s.bufErr = s.stdinBuffer.Read(bufR)
+			if s.bufErr != nil {
+				if s.bufErr == io.ErrClosedPipe {
+					break
+				}
+			}
+			s.Lock()
+			s.buf = append(s.buf, bufR[:n]...)
+			s.Unlock()
+		}
+	}()
+}
+
+// Read will read from the local buffer and if no data, read from stdin
+func (s *FillableStdin) Read(p []byte) (n int, err error) {
+	s.Lock()
+	i := len(s.buf)
+	if len(p) < i {
+		i = len(p)
+	}
+	if i > 0 {
+		n := copy(p, s.buf)
+		s.buf = s.buf[:0]
+		cerr := s.bufErr
+		s.bufErr = nil
+		s.Unlock()
+		return n, cerr
+	}
+	s.Unlock()
+	n, err = s.stdin.Read(p)
+	return n, err
+}
+
+func (s *FillableStdin) Close() error {
+	s.stdinBuffer.Close()
+	return nil
+}
diff --git a/vendor/github.com/chzyer/readline/std_windows.go b/vendor/github.com/chzyer/readline/std_windows.go
new file mode 100644
index 0000000..b10f91b
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/std_windows.go
@@ -0,0 +1,9 @@
+// +build windows
+
+package readline
+
+func init() {
+	Stdin = NewRawReader()
+	Stdout = NewANSIWriter(Stdout)
+	Stderr = NewANSIWriter(Stderr)
+}
diff --git a/vendor/github.com/chzyer/readline/term.go b/vendor/github.com/chzyer/readline/term.go
new file mode 100644
index 0000000..133993c
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term.go
@@ -0,0 +1,123 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd solaris
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// 	oldState, err := terminal.MakeRaw(0)
+// 	if err != nil {
+// 	        panic(err)
+// 	}
+// 	defer terminal.Restore(0, oldState)
+package readline
+
+import (
+	"io"
+	"syscall"
+)
+
+// State contains the state of a terminal.
+type State struct {
+	termios Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+	_, err := getTermios(fd)
+	return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+	var oldState State
+
+	if termios, err := getTermios(fd); err != nil {
+		return nil, err
+	} else {
+		oldState.termios = *termios
+	}
+
+	newState := oldState.termios
+	// This attempts to replicate the behaviour documented for cfmakeraw in
+	// the termios(3) manpage.
+	newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+	// newState.Oflag &^= syscall.OPOST
+	newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+	newState.Cflag &^= syscall.CSIZE | syscall.PARENB
+	newState.Cflag |= syscall.CS8
+
+	newState.Cc[syscall.VMIN] = 1
+	newState.Cc[syscall.VTIME] = 0
+
+	return &oldState, setTermios(fd, &newState)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+	termios, err := getTermios(fd)
+	if err != nil {
+		return nil, err
+	}
+
+	return &State{termios: *termios}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func restoreTerm(fd int, state *State) error {
+	return setTermios(fd, &state.termios)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo.  This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+	oldState, err := getTermios(fd)
+	if err != nil {
+		return nil, err
+	}
+
+	newState := oldState
+	newState.Lflag &^= syscall.ECHO
+	newState.Lflag |= syscall.ICANON | syscall.ISIG
+	newState.Iflag |= syscall.ICRNL
+	if err := setTermios(fd, newState); err != nil {
+		return nil, err
+	}
+
+	defer func() {
+		setTermios(fd, oldState)
+	}()
+
+	var buf [16]byte
+	var ret []byte
+	for {
+		n, err := syscall.Read(fd, buf[:])
+		if err != nil {
+			return nil, err
+		}
+		if n == 0 {
+			if len(ret) == 0 {
+				return nil, io.EOF
+			}
+			break
+		}
+		if buf[n-1] == '\n' {
+			n--
+		}
+		ret = append(ret, buf[:n]...)
+		if n < len(buf) {
+			break
+		}
+	}
+
+	return ret, nil
+}
diff --git a/vendor/github.com/chzyer/readline/term_bsd.go b/vendor/github.com/chzyer/readline/term_bsd.go
new file mode 100644
index 0000000..68b56ea
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term_bsd.go
@@ -0,0 +1,29 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package readline
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+func getTermios(fd int) (*Termios, error) {
+	termios := new(Termios)
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TIOCGETA, uintptr(unsafe.Pointer(termios)), 0, 0, 0)
+	if err != 0 {
+		return nil, err
+	}
+	return termios, nil
+}
+
+func setTermios(fd int, termios *Termios) error {
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TIOCSETA, uintptr(unsafe.Pointer(termios)), 0, 0, 0)
+	if err != 0 {
+		return err
+	}
+	return nil
+}
diff --git a/vendor/github.com/chzyer/readline/term_linux.go b/vendor/github.com/chzyer/readline/term_linux.go
new file mode 100644
index 0000000..e3392b4
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term_linux.go
@@ -0,0 +1,33 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package readline
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+// These constants are declared here, rather than importing
+// them from the syscall package as some syscall packages, even
+// on linux, for example gccgo, do not declare them.
+const ioctlReadTermios = 0x5401  // syscall.TCGETS
+const ioctlWriteTermios = 0x5402 // syscall.TCSETS
+
+func getTermios(fd int) (*Termios, error) {
+	termios := new(Termios)
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(termios)), 0, 0, 0)
+	if err != 0 {
+		return nil, err
+	}
+	return termios, nil
+}
+
+func setTermios(fd int, termios *Termios) error {
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(termios)), 0, 0, 0)
+	if err != 0 {
+		return err
+	}
+	return nil
+}
diff --git a/vendor/github.com/chzyer/readline/term_solaris.go b/vendor/github.com/chzyer/readline/term_solaris.go
new file mode 100644
index 0000000..4c27273
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term_solaris.go
@@ -0,0 +1,32 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package readline
+
+import "golang.org/x/sys/unix"
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (int, int, error) {
+	ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+	if err != nil {
+		return 0, 0, err
+	}
+	return int(ws.Col), int(ws.Row), nil
+}
+
+type Termios unix.Termios
+
+func getTermios(fd int) (*Termios, error) {
+	termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+	if err != nil {
+		return nil, err
+	}
+	return (*Termios)(termios), nil
+}
+
+func setTermios(fd int, termios *Termios) error {
+	return unix.IoctlSetTermios(fd, unix.TCSETSF, (*unix.Termios)(termios))
+}
diff --git a/vendor/github.com/chzyer/readline/term_unix.go b/vendor/github.com/chzyer/readline/term_unix.go
new file mode 100644
index 0000000..d3ea242
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term_unix.go
@@ -0,0 +1,24 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
+
+package readline
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+type Termios syscall.Termios
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (int, int, error) {
+	var dimensions [4]uint16
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0)
+	if err != 0 {
+		return 0, 0, err
+	}
+	return int(dimensions[1]), int(dimensions[0]), nil
+}
diff --git a/vendor/github.com/chzyer/readline/term_windows.go b/vendor/github.com/chzyer/readline/term_windows.go
new file mode 100644
index 0000000..1290e00
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/term_windows.go
@@ -0,0 +1,171 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// 	oldState, err := terminal.MakeRaw(0)
+// 	if err != nil {
+// 	        panic(err)
+// 	}
+// 	defer terminal.Restore(0, oldState)
+package readline
+
+import (
+	"io"
+	"syscall"
+	"unsafe"
+)
+
+const (
+	enableLineInput       = 2
+	enableEchoInput       = 4
+	enableProcessedInput  = 1
+	enableWindowInput     = 8
+	enableMouseInput      = 16
+	enableInsertMode      = 32
+	enableQuickEditMode   = 64
+	enableExtendedFlags   = 128
+	enableAutoPosition    = 256
+	enableProcessedOutput = 1
+	enableWrapAtEolOutput = 2
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+var (
+	procGetConsoleMode             = kernel32.NewProc("GetConsoleMode")
+	procSetConsoleMode             = kernel32.NewProc("SetConsoleMode")
+	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+)
+
+type (
+	coord struct {
+		x short
+		y short
+	}
+	smallRect struct {
+		left   short
+		top    short
+		right  short
+		bottom short
+	}
+	consoleScreenBufferInfo struct {
+		size              coord
+		cursorPosition    coord
+		attributes        word
+		window            smallRect
+		maximumWindowSize coord
+	}
+)
+
+type State struct {
+	mode uint32
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+	var st uint32
+	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
+	return r != 0 && e == 0
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+	var st uint32
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
+	if e != 0 {
+		return nil, error(e)
+	}
+	raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
+	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0)
+	if e != 0 {
+		return nil, error(e)
+	}
+	return &State{st}, nil
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+	var st uint32
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
+	if e != 0 {
+		return nil, error(e)
+	}
+	return &State{st}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func restoreTerm(fd int, state *State) error {
+	_, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0)
+	return err
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+	var info consoleScreenBufferInfo
+	_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0)
+	if e != 0 {
+		return 0, 0, error(e)
+	}
+	return int(info.size.x), int(info.size.y), nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo.  This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+	var st uint32
+	_, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
+	if e != 0 {
+		return nil, error(e)
+	}
+	old := st
+
+	st &^= (enableEchoInput)
+	st |= (enableProcessedInput | enableLineInput | enableProcessedOutput)
+	_, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0)
+	if e != 0 {
+		return nil, error(e)
+	}
+
+	defer func() {
+		syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0)
+	}()
+
+	var buf [16]byte
+	var ret []byte
+	for {
+		n, err := syscall.Read(syscall.Handle(fd), buf[:])
+		if err != nil {
+			return nil, err
+		}
+		if n == 0 {
+			if len(ret) == 0 {
+				return nil, io.EOF
+			}
+			break
+		}
+		if buf[n-1] == '\n' {
+			n--
+		}
+		if n > 0 && buf[n-1] == '\r' {
+			n--
+		}
+		ret = append(ret, buf[:n]...)
+		if n < len(buf) {
+			break
+		}
+	}
+
+	return ret, nil
+}
diff --git a/vendor/github.com/chzyer/readline/terminal.go b/vendor/github.com/chzyer/readline/terminal.go
new file mode 100644
index 0000000..1078631
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/terminal.go
@@ -0,0 +1,238 @@
+package readline
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"strings"
+	"sync"
+	"sync/atomic"
+)
+
+type Terminal struct {
+	m         sync.Mutex
+	cfg       *Config
+	outchan   chan rune
+	closed    int32
+	stopChan  chan struct{}
+	kickChan  chan struct{}
+	wg        sync.WaitGroup
+	isReading int32
+	sleeping  int32
+
+	sizeChan chan string
+}
+
+func NewTerminal(cfg *Config) (*Terminal, error) {
+	if err := cfg.Init(); err != nil {
+		return nil, err
+	}
+	t := &Terminal{
+		cfg:      cfg,
+		kickChan: make(chan struct{}, 1),
+		outchan:  make(chan rune),
+		stopChan: make(chan struct{}, 1),
+		sizeChan: make(chan string, 1),
+	}
+
+	go t.ioloop()
+	return t, nil
+}
+
+// SleepToResume will sleep myself, and return only if I'm resumed.
+func (t *Terminal) SleepToResume() {
+	if !atomic.CompareAndSwapInt32(&t.sleeping, 0, 1) {
+		return
+	}
+	defer atomic.StoreInt32(&t.sleeping, 0)
+
+	t.ExitRawMode()
+	ch := WaitForResume()
+	SuspendMe()
+	<-ch
+	t.EnterRawMode()
+}
+
+func (t *Terminal) EnterRawMode() (err error) {
+	return t.cfg.FuncMakeRaw()
+}
+
+func (t *Terminal) ExitRawMode() (err error) {
+	return t.cfg.FuncExitRaw()
+}
+
+func (t *Terminal) Write(b []byte) (int, error) {
+	return t.cfg.Stdout.Write(b)
+}
+
+// WriteStdin prefill the next Stdin fetch
+// Next time you call ReadLine() this value will be writen before the user input
+func (t *Terminal) WriteStdin(b []byte) (int, error) {
+	return t.cfg.StdinWriter.Write(b)
+}
+
+type termSize struct {
+	left int
+	top  int
+}
+
+func (t *Terminal) GetOffset(f func(offset string)) {
+	go func() {
+		f(<-t.sizeChan)
+	}()
+	t.Write([]byte("\033[6n"))
+}
+
+func (t *Terminal) Print(s string) {
+	fmt.Fprintf(t.cfg.Stdout, "%s", s)
+}
+
+func (t *Terminal) PrintRune(r rune) {
+	fmt.Fprintf(t.cfg.Stdout, "%c", r)
+}
+
+func (t *Terminal) Readline() *Operation {
+	return NewOperation(t, t.cfg)
+}
+
+// return rune(0) if meet EOF
+func (t *Terminal) ReadRune() rune {
+	ch, ok := <-t.outchan
+	if !ok {
+		return rune(0)
+	}
+	return ch
+}
+
+func (t *Terminal) IsReading() bool {
+	return atomic.LoadInt32(&t.isReading) == 1
+}
+
+func (t *Terminal) KickRead() {
+	select {
+	case t.kickChan <- struct{}{}:
+	default:
+	}
+}
+
+func (t *Terminal) ioloop() {
+	t.wg.Add(1)
+	defer func() {
+		t.wg.Done()
+		close(t.outchan)
+	}()
+
+	var (
+		isEscape       bool
+		isEscapeEx     bool
+		expectNextChar bool
+	)
+
+	buf := bufio.NewReader(t.getStdin())
+	for {
+		if !expectNextChar {
+			atomic.StoreInt32(&t.isReading, 0)
+			select {
+			case <-t.kickChan:
+				atomic.StoreInt32(&t.isReading, 1)
+			case <-t.stopChan:
+				return
+			}
+		}
+		expectNextChar = false
+		r, _, err := buf.ReadRune()
+		if err != nil {
+			if strings.Contains(err.Error(), "interrupted system call") {
+				expectNextChar = true
+				continue
+			}
+			break
+		}
+
+		if isEscape {
+			isEscape = false
+			if r == CharEscapeEx {
+				expectNextChar = true
+				isEscapeEx = true
+				continue
+			}
+			r = escapeKey(r, buf)
+		} else if isEscapeEx {
+			isEscapeEx = false
+			if key := readEscKey(r, buf); key != nil {
+				r = escapeExKey(key)
+				// offset
+				if key.typ == 'R' {
+					if _, _, ok := key.Get2(); ok {
+						select {
+						case t.sizeChan <- key.attr:
+						default:
+						}
+					}
+					expectNextChar = true
+					continue
+				}
+			}
+			if r == 0 {
+				expectNextChar = true
+				continue
+			}
+		}
+
+		expectNextChar = true
+		switch r {
+		case CharEsc:
+			if t.cfg.VimMode {
+				t.outchan <- r
+				break
+			}
+			isEscape = true
+		case CharInterrupt, CharEnter, CharCtrlJ, CharDelete:
+			expectNextChar = false
+			fallthrough
+		default:
+			t.outchan <- r
+		}
+	}
+
+}
+
+func (t *Terminal) Bell() {
+	fmt.Fprintf(t, "%c", CharBell)
+}
+
+func (t *Terminal) Close() error {
+	if atomic.SwapInt32(&t.closed, 1) != 0 {
+		return nil
+	}
+	if closer, ok := t.cfg.Stdin.(io.Closer); ok {
+		closer.Close()
+	}
+	close(t.stopChan)
+	t.wg.Wait()
+	return t.ExitRawMode()
+}
+
+func (t *Terminal) GetConfig() *Config {
+	t.m.Lock()
+	cfg := *t.cfg
+	t.m.Unlock()
+	return &cfg
+}
+
+func (t *Terminal) getStdin() io.Reader {
+	t.m.Lock()
+	r := t.cfg.Stdin
+	t.m.Unlock()
+	return r
+}
+
+func (t *Terminal) SetConfig(c *Config) error {
+	if err := c.Init(); err != nil {
+		return err
+	}
+	t.m.Lock()
+	t.cfg = c
+	t.m.Unlock()
+	return nil
+}
diff --git a/vendor/github.com/chzyer/readline/utils.go b/vendor/github.com/chzyer/readline/utils.go
new file mode 100644
index 0000000..af4e005
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/utils.go
@@ -0,0 +1,277 @@
+package readline
+
+import (
+	"bufio"
+	"bytes"
+	"container/list"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"unicode"
+)
+
+var (
+	isWindows = false
+)
+
+const (
+	CharLineStart = 1
+	CharBackward  = 2
+	CharInterrupt = 3
+	CharDelete    = 4
+	CharLineEnd   = 5
+	CharForward   = 6
+	CharBell      = 7
+	CharCtrlH     = 8
+	CharTab       = 9
+	CharCtrlJ     = 10
+	CharKill      = 11
+	CharCtrlL     = 12
+	CharEnter     = 13
+	CharNext      = 14
+	CharPrev      = 16
+	CharBckSearch = 18
+	CharFwdSearch = 19
+	CharTranspose = 20
+	CharCtrlU     = 21
+	CharCtrlW     = 23
+	CharCtrlY     = 25
+	CharCtrlZ     = 26
+	CharEsc       = 27
+	CharEscapeEx  = 91
+	CharBackspace = 127
+)
+
+const (
+	MetaBackward rune = -iota - 1
+	MetaForward
+	MetaDelete
+	MetaBackspace
+	MetaTranspose
+)
+
+// WaitForResume need to call before current process got suspend.
+// It will run a ticker until a long duration is occurs,
+// which means this process is resumed.
+func WaitForResume() chan struct{} {
+	ch := make(chan struct{})
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		ticker := time.NewTicker(10 * time.Millisecond)
+		t := time.Now()
+		wg.Done()
+		for {
+			now := <-ticker.C
+			if now.Sub(t) > 100*time.Millisecond {
+				break
+			}
+			t = now
+		}
+		ticker.Stop()
+		ch <- struct{}{}
+	}()
+	wg.Wait()
+	return ch
+}
+
+func Restore(fd int, state *State) error {
+	err := restoreTerm(fd, state)
+	if err != nil {
+		// errno 0 means everything is ok :)
+		if err.Error() == "errno 0" {
+			return nil
+		} else {
+			return err
+		}
+	}
+	return nil
+}
+
+func IsPrintable(key rune) bool {
+	isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
+	return key >= 32 && !isInSurrogateArea
+}
+
+// translate Esc[X
+func escapeExKey(key *escapeKeyPair) rune {
+	var r rune
+	switch key.typ {
+	case 'D':
+		r = CharBackward
+	case 'C':
+		r = CharForward
+	case 'A':
+		r = CharPrev
+	case 'B':
+		r = CharNext
+	case 'H':
+		r = CharLineStart
+	case 'F':
+		r = CharLineEnd
+	case '~':
+		if key.attr == "3" {
+			r = CharDelete
+		}
+	default:
+	}
+	return r
+}
+
+type escapeKeyPair struct {
+	attr string
+	typ  rune
+}
+
+func (e *escapeKeyPair) Get2() (int, int, bool) {
+	sp := strings.Split(e.attr, ";")
+	if len(sp) < 2 {
+		return -1, -1, false
+	}
+	s1, err := strconv.Atoi(sp[0])
+	if err != nil {
+		return -1, -1, false
+	}
+	s2, err := strconv.Atoi(sp[1])
+	if err != nil {
+		return -1, -1, false
+	}
+	return s1, s2, true
+}
+
+func readEscKey(r rune, reader *bufio.Reader) *escapeKeyPair {
+	p := escapeKeyPair{}
+	buf := bytes.NewBuffer(nil)
+	for {
+		if r == ';' {
+		} else if unicode.IsNumber(r) {
+		} else {
+			p.typ = r
+			break
+		}
+		buf.WriteRune(r)
+		r, _, _ = reader.ReadRune()
+	}
+	p.attr = buf.String()
+	return &p
+}
+
+// translate EscX to Meta+X
+func escapeKey(r rune, reader *bufio.Reader) rune {
+	switch r {
+	case 'b':
+		r = MetaBackward
+	case 'f':
+		r = MetaForward
+	case 'd':
+		r = MetaDelete
+	case CharTranspose:
+		r = MetaTranspose
+	case CharBackspace:
+		r = MetaBackspace
+	case 'O':
+		d, _, _ := reader.ReadRune()
+		switch d {
+		case 'H':
+			r = CharLineStart
+		case 'F':
+			r = CharLineEnd
+		default:
+			reader.UnreadRune()
+		}
+	case CharEsc:
+
+	}
+	return r
+}
+
+func SplitByLine(start, screenWidth int, rs []rune) []string {
+	var ret []string
+	buf := bytes.NewBuffer(nil)
+	currentWidth := start
+	for _, r := range rs {
+		w := runes.Width(r)
+		currentWidth += w
+		buf.WriteRune(r)
+		if currentWidth >= screenWidth {
+			ret = append(ret, buf.String())
+			buf.Reset()
+			currentWidth = 0
+		}
+	}
+	ret = append(ret, buf.String())
+	return ret
+}
+
+// calculate how many lines for N character
+func LineCount(screenWidth, w int) int {
+	r := w / screenWidth
+	if w%screenWidth != 0 {
+		r++
+	}
+	return r
+}
+
+func IsWordBreak(i rune) bool {
+	switch {
+	case i >= 'a' && i <= 'z':
+	case i >= 'A' && i <= 'Z':
+	case i >= '0' && i <= '9':
+	default:
+		return true
+	}
+	return false
+}
+
+func GetInt(s []string, def int) int {
+	if len(s) == 0 {
+		return def
+	}
+	c, err := strconv.Atoi(s[0])
+	if err != nil {
+		return def
+	}
+	return c
+}
+
+type RawMode struct {
+	state *State
+}
+
+func (r *RawMode) Enter() (err error) {
+	r.state, err = MakeRaw(GetStdin())
+	return err
+}
+
+func (r *RawMode) Exit() error {
+	if r.state == nil {
+		return nil
+	}
+	return Restore(GetStdin(), r.state)
+}
+
+// -----------------------------------------------------------------------------
+
+func sleep(n int) {
+	Debug(n)
+	time.Sleep(2000 * time.Millisecond)
+}
+
+// print a linked list to Debug()
+func debugList(l *list.List) {
+	idx := 0
+	for e := l.Front(); e != nil; e = e.Next() {
+		Debug(idx, fmt.Sprintf("%+v", e.Value))
+		idx++
+	}
+}
+
+// append log info to another file
+func Debug(o ...interface{}) {
+	f, _ := os.OpenFile("debug.tmp", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
+	fmt.Fprintln(f, o...)
+	f.Close()
+}
diff --git a/vendor/github.com/chzyer/readline/utils_unix.go b/vendor/github.com/chzyer/readline/utils_unix.go
new file mode 100644
index 0000000..f88dac9
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/utils_unix.go
@@ -0,0 +1,83 @@
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd solaris
+
+package readline
+
+import (
+	"io"
+	"os"
+	"os/signal"
+	"sync"
+	"syscall"
+)
+
+type winsize struct {
+	Row    uint16
+	Col    uint16
+	Xpixel uint16
+	Ypixel uint16
+}
+
+// SuspendMe use to send suspend signal to myself, when we in the raw mode.
+// For OSX it need to send to parent's pid
+// For Linux it need to send to myself
+func SuspendMe() {
+	p, _ := os.FindProcess(os.Getppid())
+	p.Signal(syscall.SIGTSTP)
+	p, _ = os.FindProcess(os.Getpid())
+	p.Signal(syscall.SIGTSTP)
+}
+
+// get width of the terminal
+func getWidth(stdoutFd int) int {
+	cols, _, err := GetSize(stdoutFd)
+	if err != nil {
+		return -1
+	}
+	return cols
+}
+
+func GetScreenWidth() int {
+	w := getWidth(syscall.Stdout)
+	if w < 0 {
+		w = getWidth(syscall.Stderr)
+	}
+	return w
+}
+
+// ClearScreen clears the console screen
+func ClearScreen(w io.Writer) (int, error) {
+	return w.Write([]byte("\033[H"))
+}
+
+func DefaultIsTerminal() bool {
+	return IsTerminal(syscall.Stdin) && (IsTerminal(syscall.Stdout) || IsTerminal(syscall.Stderr))
+}
+
+func GetStdin() int {
+	return syscall.Stdin
+}
+
+// -----------------------------------------------------------------------------
+
+var (
+	widthChange         sync.Once
+	widthChangeCallback func()
+)
+
+func DefaultOnWidthChanged(f func()) {
+	widthChangeCallback = f
+	widthChange.Do(func() {
+		ch := make(chan os.Signal, 1)
+		signal.Notify(ch, syscall.SIGWINCH)
+
+		go func() {
+			for {
+				_, ok := <-ch
+				if !ok {
+					break
+				}
+				widthChangeCallback()
+			}
+		}()
+	})
+}
diff --git a/vendor/github.com/chzyer/readline/utils_windows.go b/vendor/github.com/chzyer/readline/utils_windows.go
new file mode 100644
index 0000000..5bfa55d
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/utils_windows.go
@@ -0,0 +1,41 @@
+// +build windows
+
+package readline
+
+import (
+	"io"
+	"syscall"
+)
+
+func SuspendMe() {
+}
+
+func GetStdin() int {
+	return int(syscall.Stdin)
+}
+
+func init() {
+	isWindows = true
+}
+
+// get width of the terminal
+func GetScreenWidth() int {
+	info, _ := GetConsoleScreenBufferInfo()
+	if info == nil {
+		return -1
+	}
+	return int(info.dwSize.x)
+}
+
+// ClearScreen clears the console screen
+func ClearScreen(_ io.Writer) error {
+	return SetConsoleCursorPosition(&_COORD{0, 0})
+}
+
+func DefaultIsTerminal() bool {
+	return true
+}
+
+func DefaultOnWidthChanged(func()) {
+
+}
diff --git a/vendor/github.com/chzyer/readline/vim.go b/vendor/github.com/chzyer/readline/vim.go
new file mode 100644
index 0000000..bedf2c1
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/vim.go
@@ -0,0 +1,176 @@
+package readline
+
+const (
+	VIM_NORMAL = iota
+	VIM_INSERT
+	VIM_VISUAL
+)
+
+type opVim struct {
+	cfg     *Config
+	op      *Operation
+	vimMode int
+}
+
+func newVimMode(op *Operation) *opVim {
+	ov := &opVim{
+		cfg: op.cfg,
+		op:  op,
+	}
+	ov.SetVimMode(ov.cfg.VimMode)
+	return ov
+}
+
+func (o *opVim) SetVimMode(on bool) {
+	if o.cfg.VimMode && !on { // turn off
+		o.ExitVimMode()
+	}
+	o.cfg.VimMode = on
+	o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) ExitVimMode() {
+	o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) IsEnableVimMode() bool {
+	return o.cfg.VimMode
+}
+
+func (o *opVim) handleVimNormalMovement(r rune, readNext func() rune) (t rune, handled bool) {
+	rb := o.op.buf
+	handled = true
+	switch r {
+	case 'h':
+		t = CharBackward
+	case 'j':
+		t = CharNext
+	case 'k':
+		t = CharPrev
+	case 'l':
+		t = CharForward
+	case '0', '^':
+		rb.MoveToLineStart()
+	case '$':
+		rb.MoveToLineEnd()
+	case 'x':
+		rb.Delete()
+		if rb.IsCursorInEnd() {
+			rb.MoveBackward()
+		}
+	case 'r':
+		rb.Replace(readNext())
+	case 'd':
+		next := readNext()
+		switch next {
+		case 'd':
+			rb.Erase()
+		case 'w':
+			rb.DeleteWord()
+		case 'h':
+			rb.Backspace()
+		case 'l':
+			rb.Delete()
+		}
+	case 'p':
+		rb.Yank()
+	case 'b', 'B':
+		rb.MoveToPrevWord()
+	case 'w', 'W':
+		rb.MoveToNextWord()
+	case 'e', 'E':
+		rb.MoveToEndWord()
+	case 'f', 'F', 't', 'T':
+		next := readNext()
+		prevChar := r == 't' || r == 'T'
+		reverse := r == 'F' || r == 'T'
+		switch next {
+		case CharEsc:
+		default:
+			rb.MoveTo(next, prevChar, reverse)
+		}
+	default:
+		return r, false
+	}
+	return t, true
+}
+
+func (o *opVim) handleVimNormalEnterInsert(r rune, readNext func() rune) (t rune, handled bool) {
+	rb := o.op.buf
+	handled = true
+	switch r {
+	case 'i':
+	case 'I':
+		rb.MoveToLineStart()
+	case 'a':
+		rb.MoveForward()
+	case 'A':
+		rb.MoveToLineEnd()
+	case 's':
+		rb.Delete()
+	case 'S':
+		rb.Erase()
+	case 'c':
+		next := readNext()
+		switch next {
+		case 'c':
+			rb.Erase()
+		case 'w':
+			rb.DeleteWord()
+		case 'h':
+			rb.Backspace()
+		case 'l':
+			rb.Delete()
+		}
+	default:
+		return r, false
+	}
+
+	o.EnterVimInsertMode()
+	return
+}
+
+func (o *opVim) HandleVimNormal(r rune, readNext func() rune) (t rune) {
+	switch r {
+	case CharEnter, CharInterrupt:
+		o.ExitVimMode()
+		return r
+	}
+
+	if r, handled := o.handleVimNormalMovement(r, readNext); handled {
+		return r
+	}
+
+	if r, handled := o.handleVimNormalEnterInsert(r, readNext); handled {
+		return r
+	}
+
+	// invalid operation
+	o.op.t.Bell()
+	return 0
+}
+
+func (o *opVim) EnterVimInsertMode() {
+	o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) ExitVimInsertMode() {
+	o.vimMode = VIM_NORMAL
+}
+
+func (o *opVim) HandleVim(r rune, readNext func() rune) rune {
+	if o.vimMode == VIM_NORMAL {
+		return o.HandleVimNormal(r, readNext)
+	}
+	if r == CharEsc {
+		o.ExitVimInsertMode()
+		return 0
+	}
+
+	switch o.vimMode {
+	case VIM_INSERT:
+		return r
+	case VIM_VISUAL:
+	}
+	return r
+}
diff --git a/vendor/github.com/chzyer/readline/windows_api.go b/vendor/github.com/chzyer/readline/windows_api.go
new file mode 100644
index 0000000..63f4f7b
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/windows_api.go
@@ -0,0 +1,152 @@
+// +build windows
+
+package readline
+
+import (
+	"reflect"
+	"syscall"
+	"unsafe"
+)
+
+var (
+	kernel = NewKernel()
+	stdout = uintptr(syscall.Stdout)
+	stdin  = uintptr(syscall.Stdin)
+)
+
+type Kernel struct {
+	SetConsoleCursorPosition,
+	SetConsoleTextAttribute,
+	FillConsoleOutputCharacterW,
+	FillConsoleOutputAttribute,
+	ReadConsoleInputW,
+	GetConsoleScreenBufferInfo,
+	GetConsoleCursorInfo,
+	GetStdHandle CallFunc
+}
+
+type short int16
+type word uint16
+type dword uint32
+type wchar uint16
+
+type _COORD struct {
+	x short
+	y short
+}
+
+func (c *_COORD) ptr() uintptr {
+	return uintptr(*(*int32)(unsafe.Pointer(c)))
+}
+
+const (
+	EVENT_KEY                = 0x0001
+	EVENT_MOUSE              = 0x0002
+	EVENT_WINDOW_BUFFER_SIZE = 0x0004
+	EVENT_MENU               = 0x0008
+	EVENT_FOCUS              = 0x0010
+)
+
+type _KEY_EVENT_RECORD struct {
+	bKeyDown          int32
+	wRepeatCount      word
+	wVirtualKeyCode   word
+	wVirtualScanCode  word
+	unicodeChar       wchar
+	dwControlKeyState dword
+}
+
+// KEY_EVENT_RECORD          KeyEvent;
+// MOUSE_EVENT_RECORD        MouseEvent;
+// WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+// MENU_EVENT_RECORD         MenuEvent;
+// FOCUS_EVENT_RECORD        FocusEvent;
+type _INPUT_RECORD struct {
+	EventType word
+	Padding   uint16
+	Event     [16]byte
+}
+
+type _CONSOLE_SCREEN_BUFFER_INFO struct {
+	dwSize              _COORD
+	dwCursorPosition    _COORD
+	wAttributes         word
+	srWindow            _SMALL_RECT
+	dwMaximumWindowSize _COORD
+}
+
+type _SMALL_RECT struct {
+	left   short
+	top    short
+	right  short
+	bottom short
+}
+
+type _CONSOLE_CURSOR_INFO struct {
+	dwSize   dword
+	bVisible bool
+}
+
+type CallFunc func(u ...uintptr) error
+
+func NewKernel() *Kernel {
+	k := &Kernel{}
+	kernel32 := syscall.NewLazyDLL("kernel32.dll")
+	v := reflect.ValueOf(k).Elem()
+	t := v.Type()
+	for i := 0; i < t.NumField(); i++ {
+		name := t.Field(i).Name
+		f := kernel32.NewProc(name)
+		v.Field(i).Set(reflect.ValueOf(k.Wrap(f)))
+	}
+	return k
+}
+
+func (k *Kernel) Wrap(p *syscall.LazyProc) CallFunc {
+	return func(args ...uintptr) error {
+		var r0 uintptr
+		var e1 syscall.Errno
+		size := uintptr(len(args))
+		if len(args) <= 3 {
+			buf := make([]uintptr, 3)
+			copy(buf, args)
+			r0, _, e1 = syscall.Syscall(p.Addr(), size,
+				buf[0], buf[1], buf[2])
+		} else {
+			buf := make([]uintptr, 6)
+			copy(buf, args)
+			r0, _, e1 = syscall.Syscall6(p.Addr(), size,
+				buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
+			)
+		}
+
+		if int(r0) == 0 {
+			if e1 != 0 {
+				return error(e1)
+			} else {
+				return syscall.EINVAL
+			}
+		}
+		return nil
+	}
+
+}
+
+func GetConsoleScreenBufferInfo() (*_CONSOLE_SCREEN_BUFFER_INFO, error) {
+	t := new(_CONSOLE_SCREEN_BUFFER_INFO)
+	err := kernel.GetConsoleScreenBufferInfo(
+		stdout,
+		uintptr(unsafe.Pointer(t)),
+	)
+	return t, err
+}
+
+func GetConsoleCursorInfo() (*_CONSOLE_CURSOR_INFO, error) {
+	t := new(_CONSOLE_CURSOR_INFO)
+	err := kernel.GetConsoleCursorInfo(stdout, uintptr(unsafe.Pointer(t)))
+	return t, err
+}
+
+func SetConsoleCursorPosition(c *_COORD) error {
+	return kernel.SetConsoleCursorPosition(stdout, c.ptr())
+}
diff --git a/vendor/github.com/juju/ansiterm/attribute.go b/vendor/github.com/juju/ansiterm/attribute.go
new file mode 100644
index 0000000..f2daa48
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/attribute.go
@@ -0,0 +1,50 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+)
+
+type attribute int
+
+const (
+	unknownAttribute attribute = -1
+	reset            attribute = 0
+)
+
+// sgr returns the escape sequence for the Select Graphic Rendition
+// for the attribute.
+func (a attribute) sgr() string {
+	if a < 0 {
+		return ""
+	}
+	return fmt.Sprintf("\x1b[%dm", a)
+}
+
+type attributes []attribute
+
+func (a attributes) Len() int           { return len(a) }
+func (a attributes) Less(i, j int) bool { return a[i] < a[j] }
+func (a attributes) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// sgr returns the combined escape sequence for the Select Graphic Rendition
+// for the sequence of attributes.
+func (a attributes) sgr() string {
+	switch len(a) {
+	case 0:
+		return ""
+	case 1:
+		return a[0].sgr()
+	default:
+		sort.Sort(a)
+		var values []string
+		for _, attr := range a {
+			values = append(values, fmt.Sprint(attr))
+		}
+		return fmt.Sprintf("\x1b[%sm", strings.Join(values, ";"))
+	}
+}
diff --git a/vendor/github.com/juju/ansiterm/color.go b/vendor/github.com/juju/ansiterm/color.go
new file mode 100644
index 0000000..0a97de3
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/color.go
@@ -0,0 +1,119 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+const (
+	_ Color = iota
+	Default
+	Black
+	Red
+	Green
+	Yellow
+	Blue
+	Magenta
+	Cyan
+	Gray
+	DarkGray
+	BrightRed
+	BrightGreen
+	BrightYellow
+	BrightBlue
+	BrightMagenta
+	BrightCyan
+	White
+)
+
+// Color represents one of the standard 16 ANSI colors.
+type Color int
+
+// String returns the name of the color.
+func (c Color) String() string {
+	switch c {
+	case Default:
+		return "default"
+	case Black:
+		return "black"
+	case Red:
+		return "red"
+	case Green:
+		return "green"
+	case Yellow:
+		return "yellow"
+	case Blue:
+		return "blue"
+	case Magenta:
+		return "magenta"
+	case Cyan:
+		return "cyan"
+	case Gray:
+		return "gray"
+	case DarkGray:
+		return "darkgray"
+	case BrightRed:
+		return "brightred"
+	case BrightGreen:
+		return "brightgreen"
+	case BrightYellow:
+		return "brightyellow"
+	case BrightBlue:
+		return "brightblue"
+	case BrightMagenta:
+		return "brightmagenta"
+	case BrightCyan:
+		return "brightcyan"
+	case White:
+		return "white"
+	default:
+		return ""
+	}
+}
+
+func (c Color) foreground() attribute {
+	switch c {
+	case Default:
+		return 39
+	case Black:
+		return 30
+	case Red:
+		return 31
+	case Green:
+		return 32
+	case Yellow:
+		return 33
+	case Blue:
+		return 34
+	case Magenta:
+		return 35
+	case Cyan:
+		return 36
+	case Gray:
+		return 37
+	case DarkGray:
+		return 90
+	case BrightRed:
+		return 91
+	case BrightGreen:
+		return 92
+	case BrightYellow:
+		return 93
+	case BrightBlue:
+		return 94
+	case BrightMagenta:
+		return 95
+	case BrightCyan:
+		return 96
+	case White:
+		return 97
+	default:
+		return unknownAttribute
+	}
+}
+
+func (c Color) background() attribute {
+	value := c.foreground()
+	if value != unknownAttribute {
+		return value + 10
+	}
+	return value
+}
diff --git a/vendor/github.com/juju/ansiterm/context.go b/vendor/github.com/juju/ansiterm/context.go
new file mode 100644
index 0000000..e61a867
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/context.go
@@ -0,0 +1,95 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+import (
+	"fmt"
+	"io"
+)
+
+// Context provides a way to specify both foreground and background colors
+// along with other styles and write text to a Writer with those colors and
+// styles.
+type Context struct {
+	Foreground Color
+	Background Color
+	Styles     []Style
+}
+
+// Foreground is a convenience function that creates a Context with the
+// specified color as the foreground color.
+func Foreground(color Color) *Context {
+	return &Context{Foreground: color}
+}
+
+// Background is a convenience function that creates a Context with the
+// specified color as the background color.
+func Background(color Color) *Context {
+	return &Context{Background: color}
+}
+
+// Styles is a convenience function that creates a Context with the
+// specified styles set.
+func Styles(styles ...Style) *Context {
+	return &Context{Styles: styles}
+}
+
+// SetForeground sets the foreground to the specified color.
+func (c *Context) SetForeground(color Color) *Context {
+	c.Foreground = color
+	return c
+}
+
+// SetBackground sets the background to the specified color.
+func (c *Context) SetBackground(color Color) *Context {
+	c.Background = color
+	return c
+}
+
+// SetStyle replaces the styles with the new values.
+func (c *Context) SetStyle(styles ...Style) *Context {
+	c.Styles = styles
+	return c
+}
+
+type sgrWriter interface {
+	io.Writer
+	writeSGR(value sgr)
+}
+
+// Fprintf will set the sgr values of the writer to the specified
+// foreground, background and styles, then write the formatted string,
+// then reset the writer.
+func (c *Context) Fprintf(w sgrWriter, format string, args ...interface{}) {
+	w.writeSGR(c)
+	fmt.Fprintf(w, format, args...)
+	w.writeSGR(reset)
+}
+
+// Fprint will set the sgr values of the writer to the specified foreground,
+// background and styles, then formats using the default formats for its
+// operands and writes to w. Spaces are added between operands when neither is
+// a string. It returns the number of bytes written and any write error
+// encountered.
+func (c *Context) Fprint(w sgrWriter, args ...interface{}) {
+	w.writeSGR(c)
+	fmt.Fprint(w, args...)
+	w.writeSGR(reset)
+}
+
+func (c *Context) sgr() string {
+	var values attributes
+	if foreground := c.Foreground.foreground(); foreground != unknownAttribute {
+		values = append(values, foreground)
+	}
+	if background := c.Background.background(); background != unknownAttribute {
+		values = append(values, background)
+	}
+	for _, style := range c.Styles {
+		if value := style.enable(); value != unknownAttribute {
+			values = append(values, value)
+		}
+	}
+	return values.sgr()
+}
diff --git a/vendor/github.com/juju/ansiterm/doc.go b/vendor/github.com/juju/ansiterm/doc.go
new file mode 100644
index 0000000..7827007
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/doc.go
@@ -0,0 +1,6 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+// Package ansiterm provides a Writer that writes out the ANSI escape
+// codes for color and styles.
+package ansiterm
diff --git a/vendor/github.com/juju/ansiterm/style.go b/vendor/github.com/juju/ansiterm/style.go
new file mode 100644
index 0000000..0be42da
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/style.go
@@ -0,0 +1,72 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+const (
+	_ Style = iota
+	Bold
+	Faint
+	Italic
+	Underline
+	Blink
+	Reverse
+	Strikethrough
+	Conceal
+)
+
+type Style int
+
+func (s Style) String() string {
+	switch s {
+	case Bold:
+		return "bold"
+	case Faint:
+		return "faint"
+	case Italic:
+		return "italic"
+	case Underline:
+		return "underline"
+	case Blink:
+		return "blink"
+	case Reverse:
+		return "reverse"
+	case Strikethrough:
+		return "strikethrough"
+	case Conceal:
+		return "conceal"
+	default:
+		return ""
+	}
+}
+
+func (s Style) enable() attribute {
+	switch s {
+	case Bold:
+		return 1
+	case Faint:
+		return 2
+	case Italic:
+		return 3
+	case Underline:
+		return 4
+	case Blink:
+		return 5
+	case Reverse:
+		return 7
+	case Conceal:
+		return 8
+	case Strikethrough:
+		return 9
+	default:
+		return unknownAttribute
+	}
+}
+
+func (s Style) disable() attribute {
+	value := s.enable()
+	if value != unknownAttribute {
+		return value + 20
+	}
+	return value
+}
diff --git a/vendor/github.com/juju/ansiterm/tabwriter.go b/vendor/github.com/juju/ansiterm/tabwriter.go
new file mode 100644
index 0000000..1ff6faa
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/tabwriter.go
@@ -0,0 +1,64 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+import (
+	"io"
+
+	"github.com/juju/ansiterm/tabwriter"
+)
+
+// NewTabWriter returns a writer that is able to set colors and styels.
+// The ansi escape codes are stripped for width calculations.
+func NewTabWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *TabWriter {
+	return new(TabWriter).Init(output, minwidth, tabwidth, padding, padchar, flags)
+}
+
+// TabWriter is a filter that inserts padding around tab-delimited
+// columns in its input to align them in the output.
+//
+// It also setting of colors and styles over and above the standard
+// tabwriter package.
+type TabWriter struct {
+	Writer
+	tw tabwriter.Writer
+}
+
+// Flush should be called after the last call to Write to ensure
+// that any data buffered in the Writer is written to output. Any
+// incomplete escape sequence at the end is considered
+// complete for formatting purposes.
+//
+func (t *TabWriter) Flush() error {
+	return t.tw.Flush()
+}
+
+// SetColumnAlignRight will mark a particular column as align right.
+// This is reset on the next flush.
+func (t *TabWriter) SetColumnAlignRight(column int) {
+	t.tw.SetColumnAlignRight(column)
+}
+
+// A Writer must be initialized with a call to Init. The first parameter (output)
+// specifies the filter output. The remaining parameters control the formatting:
+//
+//	minwidth	minimal cell width including any padding
+//	tabwidth	width of tab characters (equivalent number of spaces)
+//	padding		padding added to a cell before computing its width
+//	padchar		ASCII char used for padding
+//			if padchar == '\t', the Writer will assume that the
+//			width of a '\t' in the formatted output is tabwidth,
+//			and cells are left-aligned independent of align_left
+//			(for correct-looking results, tabwidth must correspond
+//			to the tab width in the viewer displaying the result)
+//	flags		formatting control
+//
+func (t *TabWriter) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *TabWriter {
+	writer, colorCapable := colorEnabledWriter(output)
+	t.Writer = Writer{
+		Writer:  t.tw.Init(writer, minwidth, tabwidth, padding, padchar, flags),
+		noColor: !colorCapable,
+	}
+	return t
+}
diff --git a/vendor/github.com/juju/ansiterm/tabwriter/tabwriter.go b/vendor/github.com/juju/ansiterm/tabwriter/tabwriter.go
new file mode 100644
index 0000000..98949d0
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/tabwriter/tabwriter.go
@@ -0,0 +1,587 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is mostly a copy of the go standard library text/tabwriter. With
+// the additional stripping of ansi control characters for width calculations.
+
+// Package tabwriter implements a write filter (tabwriter.Writer) that
+// translates tabbed columns in input into properly aligned text.
+//
+// The package is using the Elastic Tabstops algorithm described at
+// http://nickgravgaard.com/elastictabstops/index.html.
+//
+package tabwriter
+
+import (
+	"bytes"
+	"io"
+	"unicode/utf8"
+
+	"github.com/lunixbochs/vtclean"
+)
+
+// ----------------------------------------------------------------------------
+// Filter implementation
+
+// A cell represents a segment of text terminated by tabs or line breaks.
+// The text itself is stored in a separate buffer; cell only describes the
+// segment's size in bytes, its width in runes, and whether it's an htab
+// ('\t') terminated cell.
+//
+type cell struct {
+	size  int  // cell size in bytes
+	width int  // cell width in runes
+	htab  bool // true if the cell is terminated by an htab ('\t')
+}
+
+// A Writer is a filter that inserts padding around tab-delimited
+// columns in its input to align them in the output.
+//
+// The Writer treats incoming bytes as UTF-8 encoded text consisting
+// of cells terminated by (horizontal or vertical) tabs or line
+// breaks (newline or formfeed characters). Cells in adjacent lines
+// constitute a column. The Writer inserts padding as needed to
+// make all cells in a column have the same width, effectively
+// aligning the columns. It assumes that all characters have the
+// same width except for tabs for which a tabwidth must be specified.
+// Note that cells are tab-terminated, not tab-separated: trailing
+// non-tab text at the end of a line does not form a column cell.
+//
+// The Writer assumes that all Unicode code points have the same width;
+// this may not be true in some fonts.
+//
+// If DiscardEmptyColumns is set, empty columns that are terminated
+// entirely by vertical (or "soft") tabs are discarded. Columns
+// terminated by horizontal (or "hard") tabs are not affected by
+// this flag.
+//
+// If a Writer is configured to filter HTML, HTML tags and entities
+// are passed through. The widths of tags and entities are
+// assumed to be zero (tags) and one (entities) for formatting purposes.
+//
+// A segment of text may be escaped by bracketing it with Escape
+// characters. The tabwriter passes escaped text segments through
+// unchanged. In particular, it does not interpret any tabs or line
+// breaks within the segment. If the StripEscape flag is set, the
+// Escape characters are stripped from the output; otherwise they
+// are passed through as well. For the purpose of formatting, the
+// width of the escaped text is always computed excluding the Escape
+// characters.
+//
+// The formfeed character ('\f') acts like a newline but it also
+// terminates all columns in the current line (effectively calling
+// Flush). Cells in the next line start new columns. Unless found
+// inside an HTML tag or inside an escaped text segment, formfeed
+// characters appear as newlines in the output.
+//
+// The Writer must buffer input internally, because proper spacing
+// of one line may depend on the cells in future lines. Clients must
+// call Flush when done calling Write.
+//
+type Writer struct {
+	// configuration
+	output   io.Writer
+	minwidth int
+	tabwidth int
+	padding  int
+	padbytes [8]byte
+	flags    uint
+
+	// current state
+	buf       bytes.Buffer // collected text excluding tabs or line breaks
+	pos       int          // buffer position up to which cell.width of incomplete cell has been computed
+	cell      cell         // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
+	endChar   byte         // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
+	lines     [][]cell     // list of lines; each line is a list of cells
+	widths    []int        // list of column widths in runes - re-used during formatting
+	alignment map[int]uint // column alignment
+}
+
+func (b *Writer) addLine() { b.lines = append(b.lines, []cell{}) }
+
+// Reset the current state.
+func (b *Writer) reset() {
+	b.buf.Reset()
+	b.pos = 0
+	b.cell = cell{}
+	b.endChar = 0
+	b.lines = b.lines[0:0]
+	b.widths = b.widths[0:0]
+	b.alignment = make(map[int]uint)
+	b.addLine()
+}
+
+// Internal representation (current state):
+//
+// - all text written is appended to buf; tabs and line breaks are stripped away
+// - at any given time there is a (possibly empty) incomplete cell at the end
+//   (the cell starts after a tab or line break)
+// - cell.size is the number of bytes belonging to the cell so far
+// - cell.width is text width in runes of that cell from the start of the cell to
+//   position pos; html tags and entities are excluded from this width if html
+//   filtering is enabled
+// - the sizes and widths of processed text are kept in the lines list
+//   which contains a list of cells for each line
+// - the widths list is a temporary list with current widths used during
+//   formatting; it is kept in Writer because it's re-used
+//
+//                    |<---------- size ---------->|
+//                    |                            |
+//                    |<- width ->|<- ignored ->|  |
+//                    |           |             |  |
+// [---processed---tab------------<tag>...</tag>...]
+// ^                  ^                         ^
+// |                  |                         |
+// buf                start of incomplete cell  pos
+
+// Formatting can be controlled with these flags.
+const (
+	// Ignore html tags and treat entities (starting with '&'
+	// and ending in ';') as single characters (width = 1).
+	FilterHTML uint = 1 << iota
+
+	// Strip Escape characters bracketing escaped text segments
+	// instead of passing them through unchanged with the text.
+	StripEscape
+
+	// Force right-alignment of cell content.
+	// Default is left-alignment.
+	AlignRight
+
+	// Handle empty columns as if they were not present in
+	// the input in the first place.
+	DiscardEmptyColumns
+
+	// Always use tabs for indentation columns (i.e., padding of
+	// leading empty cells on the left) independent of padchar.
+	TabIndent
+
+	// Print a vertical bar ('|') between columns (after formatting).
+	// Discarded columns appear as zero-width columns ("||").
+	Debug
+)
+
+// A Writer must be initialized with a call to Init. The first parameter (output)
+// specifies the filter output. The remaining parameters control the formatting:
+//
+//	minwidth	minimal cell width including any padding
+//	tabwidth	width of tab characters (equivalent number of spaces)
+//	padding		padding added to a cell before computing its width
+//	padchar		ASCII char used for padding
+//			if padchar == '\t', the Writer will assume that the
+//			width of a '\t' in the formatted output is tabwidth,
+//			and cells are left-aligned independent of align_left
+//			(for correct-looking results, tabwidth must correspond
+//			to the tab width in the viewer displaying the result)
+//	flags		formatting control
+//
+func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	if minwidth < 0 || tabwidth < 0 || padding < 0 {
+		panic("negative minwidth, tabwidth, or padding")
+	}
+	b.output = output
+	b.minwidth = minwidth
+	b.tabwidth = tabwidth
+	b.padding = padding
+	for i := range b.padbytes {
+		b.padbytes[i] = padchar
+	}
+	if padchar == '\t' {
+		// tab padding enforces left-alignment
+		flags &^= AlignRight
+	}
+	b.flags = flags
+
+	b.reset()
+
+	return b
+}
+
+// debugging support (keep code around)
+func (b *Writer) dump() {
+	pos := 0
+	for i, line := range b.lines {
+		print("(", i, ") ")
+		for _, c := range line {
+			print("[", string(b.buf.Bytes()[pos:pos+c.size]), "]")
+			pos += c.size
+		}
+		print("\n")
+	}
+	print("\n")
+}
+
+// local error wrapper so we can distinguish errors we want to return
+// as errors from genuine panics (which we don't want to return as errors)
+type osError struct {
+	err error
+}
+
+func (b *Writer) write0(buf []byte) {
+	n, err := b.output.Write(buf)
+	if n != len(buf) && err == nil {
+		err = io.ErrShortWrite
+	}
+	if err != nil {
+		panic(osError{err})
+	}
+}
+
+func (b *Writer) writeN(src []byte, n int) {
+	for n > len(src) {
+		b.write0(src)
+		n -= len(src)
+	}
+	b.write0(src[0:n])
+}
+
+var (
+	newline = []byte{'\n'}
+	tabs    = []byte("\t\t\t\t\t\t\t\t")
+)
+
+func (b *Writer) writePadding(textw, cellw int, useTabs bool) {
+	if b.padbytes[0] == '\t' || useTabs {
+		// padding is done with tabs
+		if b.tabwidth == 0 {
+			return // tabs have no width - can't do any padding
+		}
+		// make cellw the smallest multiple of b.tabwidth
+		cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth
+		n := cellw - textw // amount of padding
+		if n < 0 {
+			panic("internal error")
+		}
+		b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth)
+		return
+	}
+
+	// padding is done with non-tab characters
+	b.writeN(b.padbytes[0:], cellw-textw)
+}
+
+var vbar = []byte{'|'}
+
+func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	for i := line0; i < line1; i++ {
+		line := b.lines[i]
+
+		// if TabIndent is set, use tabs to pad leading empty cells
+		useTabs := b.flags&TabIndent != 0
+
+		for j, c := range line {
+			if j > 0 && b.flags&Debug != 0 {
+				// indicate column break
+				b.write0(vbar)
+			}
+
+			if c.size == 0 {
+				// empty cell
+				if j < len(b.widths) {
+					b.writePadding(c.width, b.widths[j], useTabs)
+				}
+			} else {
+				// non-empty cell
+				useTabs = false
+				alignColumnRight := b.alignment[j] == AlignRight
+				if (b.flags&AlignRight == 0) && !alignColumnRight { // align left
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+				} else if alignColumnRight && j < len(b.widths) {
+					// just this column
+					internalSize := b.widths[j] - b.padding
+					if j < len(b.widths) {
+						b.writePadding(c.width, internalSize, false)
+					}
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					if b.padding > 0 {
+						b.writePadding(0, b.padding, false)
+					}
+					pos += c.size
+				} else { // align right
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+				}
+			}
+		}
+
+		if i+1 == len(b.lines) {
+			// last buffered line - we don't have a newline, so just write
+			// any outstanding buffered data
+			b.write0(b.buf.Bytes()[pos : pos+b.cell.size])
+			pos += b.cell.size
+		} else {
+			// not the last line - write newline
+			b.write0(newline)
+		}
+	}
+	return
+}
+
+// Format the text between line0 and line1 (excluding line1); pos
+// is the buffer position corresponding to the beginning of line0.
+// Returns the buffer position corresponding to the beginning of
+// line1 and an error, if any.
+//
+func (b *Writer) format(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	column := len(b.widths)
+	for this := line0; this < line1; this++ {
+		line := b.lines[this]
+
+		if column < len(line)-1 {
+			// cell exists in this column => this line
+			// has more cells than the previous line
+			// (the last cell per line is ignored because cells are
+			// tab-terminated; the last cell per line describes the
+			// text before the newline/formfeed and does not belong
+			// to a column)
+
+			// print unprinted lines until beginning of block
+			pos = b.writeLines(pos, line0, this)
+			line0 = this
+
+			// column block begin
+			width := b.minwidth // minimal column width
+			discardable := true // true if all cells in this column are empty and "soft"
+			for ; this < line1; this++ {
+				line = b.lines[this]
+				if column < len(line)-1 {
+					// cell exists in this column
+					c := line[column]
+					// update width
+					if w := c.width + b.padding; w > width {
+						width = w
+					}
+					// update discardable
+					if c.width > 0 || c.htab {
+						discardable = false
+					}
+				} else {
+					break
+				}
+			}
+			// column block end
+
+			// discard empty columns if necessary
+			if discardable && b.flags&DiscardEmptyColumns != 0 {
+				width = 0
+			}
+
+			// format and print all columns to the right of this column
+			// (we know the widths of this column and all columns to the left)
+			b.widths = append(b.widths, width) // push width
+			pos = b.format(pos, line0, this)
+			b.widths = b.widths[0 : len(b.widths)-1] // pop width
+			line0 = this
+		}
+	}
+
+	// print unprinted lines until end
+	return b.writeLines(pos, line0, line1)
+}
+
+// Append text to current cell.
+func (b *Writer) append(text []byte) {
+	b.buf.Write(text)
+	b.cell.size += len(text)
+}
+
+// Update the cell width.
+func (b *Writer) updateWidth() {
+	// ---- Changes here -----
+	newChars := b.buf.Bytes()[b.pos:b.buf.Len()]
+	cleaned := vtclean.Clean(string(newChars), false) // false to strip colors
+	b.cell.width += utf8.RuneCount([]byte(cleaned))
+	// --- end of changes ----
+	b.pos = b.buf.Len()
+}
+
+// To escape a text segment, bracket it with Escape characters.
+// For instance, the tab in this string "Ignore this tab: \xff\t\xff"
+// does not terminate a cell and constitutes a single character of
+// width one for formatting purposes.
+//
+// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence.
+//
+const Escape = '\xff'
+
+// Start escaped mode.
+func (b *Writer) startEscape(ch byte) {
+	switch ch {
+	case Escape:
+		b.endChar = Escape
+	case '<':
+		b.endChar = '>'
+	case '&':
+		b.endChar = ';'
+	}
+}
+
+// Terminate escaped mode. If the escaped text was an HTML tag, its width
+// is assumed to be zero for formatting purposes; if it was an HTML entity,
+// its width is assumed to be one. In all other cases, the width is the
+// unicode width of the text.
+//
+func (b *Writer) endEscape() {
+	switch b.endChar {
+	case Escape:
+		b.updateWidth()
+		if b.flags&StripEscape == 0 {
+			b.cell.width -= 2 // don't count the Escape chars
+		}
+	case '>': // tag of zero width
+	case ';':
+		b.cell.width++ // entity, count as one rune
+	}
+	b.pos = b.buf.Len()
+	b.endChar = 0
+}
+
+// Terminate the current cell by adding it to the list of cells of the
+// current line. Returns the number of cells in that line.
+//
+func (b *Writer) terminateCell(htab bool) int {
+	b.cell.htab = htab
+	line := &b.lines[len(b.lines)-1]
+	*line = append(*line, b.cell)
+	b.cell = cell{}
+	return len(*line)
+}
+
+func handlePanic(err *error, op string) {
+	if e := recover(); e != nil {
+		if nerr, ok := e.(osError); ok {
+			*err = nerr.err
+			return
+		}
+		panic("tabwriter: panic during " + op)
+	}
+}
+
+// Flush should be called after the last call to Write to ensure
+// that any data buffered in the Writer is written to output. Any
+// incomplete escape sequence at the end is considered
+// complete for formatting purposes.
+//
+func (b *Writer) Flush() (err error) {
+	defer b.reset() // even in the presence of errors
+	defer handlePanic(&err, "Flush")
+
+	// add current cell if not empty
+	if b.cell.size > 0 {
+		if b.endChar != 0 {
+			// inside escape - terminate it even if incomplete
+			b.endEscape()
+		}
+		b.terminateCell(false)
+	}
+
+	// format contents of buffer
+	b.format(0, 0, len(b.lines))
+
+	return
+}
+
+var hbar = []byte("---\n")
+
+// SetColumnAlignRight will mark a particular column as align right.
+// This is reset on the next flush.
+func (b *Writer) SetColumnAlignRight(column int) {
+	b.alignment[column] = AlignRight
+}
+
+// Write writes buf to the writer b.
+// The only errors returned are ones encountered
+// while writing to the underlying output stream.
+//
+func (b *Writer) Write(buf []byte) (n int, err error) {
+	defer handlePanic(&err, "Write")
+
+	// split text into cells
+	n = 0
+	for i, ch := range buf {
+		if b.endChar == 0 {
+			// outside escape
+			switch ch {
+			case '\t', '\v', '\n', '\f':
+				// end of cell
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i + 1 // ch consumed
+				ncells := b.terminateCell(ch == '\t')
+				if ch == '\n' || ch == '\f' {
+					// terminate line
+					b.addLine()
+					if ch == '\f' || ncells == 1 {
+						// A '\f' always forces a flush. Otherwise, if the previous
+						// line has only one cell which does not have an impact on
+						// the formatting of the following lines (the last cell per
+						// line is ignored by format()), thus we can flush the
+						// Writer contents.
+						if err = b.Flush(); err != nil {
+							return
+						}
+						if ch == '\f' && b.flags&Debug != 0 {
+							// indicate section break
+							b.write0(hbar)
+						}
+					}
+				}
+
+			case Escape:
+				// start of escaped sequence
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i
+				if b.flags&StripEscape != 0 {
+					n++ // strip Escape
+				}
+				b.startEscape(Escape)
+
+			case '<', '&':
+				// possibly an html tag/entity
+				if b.flags&FilterHTML != 0 {
+					// begin of tag/entity
+					b.append(buf[n:i])
+					b.updateWidth()
+					n = i
+					b.startEscape(ch)
+				}
+			}
+
+		} else {
+			// inside escape
+			if ch == b.endChar {
+				// end of tag/entity
+				j := i + 1
+				if ch == Escape && b.flags&StripEscape != 0 {
+					j = i // strip Escape
+				}
+				b.append(buf[n:j])
+				n = i + 1 // ch consumed
+				b.endEscape()
+			}
+		}
+	}
+
+	// append leftover text
+	b.append(buf[n:])
+	n = len(buf)
+	return
+}
+
+// NewWriter allocates and initializes a new tabwriter.Writer.
+// The parameters are the same as for the Init function.
+//
+func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
+}
diff --git a/vendor/github.com/juju/ansiterm/terminal.go b/vendor/github.com/juju/ansiterm/terminal.go
new file mode 100644
index 0000000..96fd11c
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/terminal.go
@@ -0,0 +1,32 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+import (
+	"io"
+	"os"
+
+	"github.com/mattn/go-colorable"
+	"github.com/mattn/go-isatty"
+)
+
+// colorEnabledWriter returns a writer that can handle the ansi color codes
+// and true if the writer passed in is a terminal capable of color. If the
+// TERM environment variable is set to "dumb", the terminal is not considered
+// color capable.
+func colorEnabledWriter(w io.Writer) (io.Writer, bool) {
+	f, ok := w.(*os.File)
+	if !ok {
+		return w, false
+	}
+	// Check the TERM environment variable specifically
+	// to check for "dumb" terminals.
+	if os.Getenv("TERM") == "dumb" {
+		return w, false
+	}
+	if !isatty.IsTerminal(f.Fd()) {
+		return w, false
+	}
+	return colorable.NewColorable(f), true
+}
diff --git a/vendor/github.com/juju/ansiterm/writer.go b/vendor/github.com/juju/ansiterm/writer.go
new file mode 100644
index 0000000..32437bb
--- /dev/null
+++ b/vendor/github.com/juju/ansiterm/writer.go
@@ -0,0 +1,74 @@
+// Copyright 2016 Canonical Ltd.
+// Licensed under the LGPLv3, see LICENCE file for details.
+
+package ansiterm
+
+import (
+	"fmt"
+	"io"
+)
+
+// Writer allows colors and styles to be specified. If the io.Writer
+// is not a terminal capable of color, all attempts to set colors or
+// styles are no-ops.
+type Writer struct {
+	io.Writer
+
+	noColor bool
+}
+
+// NewWriter returns a Writer that allows the caller to specify colors and
+// styles. If the io.Writer is not a terminal capable of color, all attempts
+// to set colors or styles are no-ops.
+func NewWriter(w io.Writer) *Writer {
+	writer, colorCapable := colorEnabledWriter(w)
+	return &Writer{
+		Writer:  writer,
+		noColor: !colorCapable,
+	}
+}
+
+// SetColorCapable forces the writer to either write the ANSI escape color
+// if capable is true, or to not write them if capable is false.
+func (w *Writer) SetColorCapable(capable bool) {
+	w.noColor = !capable
+}
+
+// SetForeground sets the foreground color.
+func (w *Writer) SetForeground(c Color) {
+	w.writeSGR(c.foreground())
+}
+
+// SetBackground sets the background color.
+func (w *Writer) SetBackground(c Color) {
+	w.writeSGR(c.background())
+}
+
+// SetStyle sets the text style.
+func (w *Writer) SetStyle(s Style) {
+	w.writeSGR(s.enable())
+}
+
+// ClearStyle clears the text style.
+func (w *Writer) ClearStyle(s Style) {
+	w.writeSGR(s.disable())
+}
+
+// Reset returns the default foreground and background colors with no styles.
+func (w *Writer) Reset() {
+	w.writeSGR(reset)
+}
+
+type sgr interface {
+	// sgr returns the combined escape sequence for the Select Graphic Rendition.
+	sgr() string
+}
+
+// writeSGR takes the appropriate integer SGR parameters
+// and writes out the ANIS escape code.
+func (w *Writer) writeSGR(value sgr) {
+	if w.noColor {
+		return
+	}
+	fmt.Fprint(w, value.sgr())
+}
diff --git a/vendor/github.com/lunixbochs/vtclean/io.go b/vendor/github.com/lunixbochs/vtclean/io.go
new file mode 100644
index 0000000..31be007
--- /dev/null
+++ b/vendor/github.com/lunixbochs/vtclean/io.go
@@ -0,0 +1,93 @@
+package vtclean
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+)
+
+type reader struct {
+	io.Reader
+	scanner *bufio.Scanner
+	buf     []byte
+
+	color bool
+}
+
+func NewReader(r io.Reader, color bool) io.Reader {
+	return &reader{Reader: r, color: color}
+}
+
+func (r *reader) scan() bool {
+	if r.scanner == nil {
+		r.scanner = bufio.NewScanner(r.Reader)
+	}
+	if len(r.buf) > 0 {
+		return true
+	}
+	if r.scanner.Scan() {
+		r.buf = []byte(Clean(r.scanner.Text(), r.color) + "\n")
+		return true
+	}
+	return false
+}
+
+func (r *reader) fill(p []byte) int {
+	n := len(r.buf)
+	copy(p, r.buf)
+	if len(p) < len(r.buf) {
+		r.buf = r.buf[len(p):]
+		n = len(p)
+	} else {
+		r.buf = nil
+	}
+	return n
+}
+
+func (r *reader) Read(p []byte) (int, error) {
+	n := r.fill(p)
+	if n < len(p) {
+		if !r.scan() {
+			if n == 0 {
+				return 0, io.EOF
+			}
+			return n, nil
+		}
+		n += r.fill(p[n:])
+	}
+	return n, nil
+}
+
+type writer struct {
+	io.Writer
+	buf   []byte
+	color bool
+}
+
+func NewWriter(w io.Writer, color bool) io.WriteCloser {
+	return &writer{Writer: w, color: color}
+}
+
+func (w *writer) Write(p []byte) (int, error) {
+	buf := append(w.buf, p...)
+	lines := bytes.Split(buf, []byte("\n"))
+	if len(lines) > 0 {
+		last := len(lines) - 1
+		w.buf = lines[last]
+		count := 0
+		for _, line := range lines[:last] {
+			n, err := w.Writer.Write([]byte(Clean(string(line), w.color) + "\n"))
+			count += n
+			if err != nil {
+				return count, err
+			}
+		}
+	}
+	return len(p), nil
+}
+
+func (w *writer) Close() error {
+	cl := Clean(string(w.buf), w.color)
+	_, err := w.Writer.Write([]byte(cl))
+	return err
+}
diff --git a/vendor/github.com/lunixbochs/vtclean/line.go b/vendor/github.com/lunixbochs/vtclean/line.go
new file mode 100644
index 0000000..66ee990
--- /dev/null
+++ b/vendor/github.com/lunixbochs/vtclean/line.go
@@ -0,0 +1,113 @@
+package vtclean
+
+type char struct {
+	char  byte
+	vt100 []byte
+}
+
+func chars(p []byte) []char {
+	tmp := make([]char, len(p))
+	for i, v := range p {
+		tmp[i].char = v
+	}
+	return tmp
+}
+
+type lineEdit struct {
+	buf       []char
+	pos, size int
+	vt100     []byte
+}
+
+func newLineEdit(length int) *lineEdit {
+	return &lineEdit{buf: make([]char, length)}
+}
+
+func (l *lineEdit) Vt100(p []byte) {
+	l.vt100 = p
+}
+
+func (l *lineEdit) Move(x int) {
+	if x < 0 && l.pos <= -x {
+		l.pos = 0
+	} else if x > 0 && l.pos+x > l.size {
+		l.pos = l.size
+	} else {
+		l.pos += x
+	}
+}
+
+func (l *lineEdit) MoveAbs(x int) {
+	if x < l.size {
+		l.pos = x
+	}
+}
+
+func (l *lineEdit) Write(p []byte) {
+	c := chars(p)
+	if len(c) > 0 {
+		c[0].vt100 = l.vt100
+		l.vt100 = nil
+	}
+	if len(l.buf)-l.pos < len(c) {
+		l.buf = append(l.buf[:l.pos], c...)
+	} else {
+		copy(l.buf[l.pos:], c)
+	}
+	l.pos += len(c)
+	if l.pos > l.size {
+		l.size = l.pos
+	}
+}
+
+func (l *lineEdit) Insert(p []byte) {
+	c := chars(p)
+	if len(c) > 0 {
+		c[0].vt100 = l.vt100
+		l.vt100 = nil
+	}
+	l.size += len(c)
+	c = append(c, l.buf[l.pos:]...)
+	l.buf = append(l.buf[:l.pos], c...)
+}
+
+func (l *lineEdit) Delete(n int) {
+	most := l.size - l.pos
+	if n > most {
+		n = most
+	}
+	copy(l.buf[l.pos:], l.buf[l.pos+n:])
+	l.size -= n
+}
+
+func (l *lineEdit) Clear() {
+	for i := 0; i < len(l.buf); i++ {
+		l.buf[i].char = ' '
+	}
+}
+func (l *lineEdit) ClearLeft() {
+	for i := 0; i < l.pos+1; i++ {
+		l.buf[i].char = ' '
+	}
+}
+func (l *lineEdit) ClearRight() {
+	l.size = l.pos
+}
+
+func (l *lineEdit) Bytes() []byte {
+	length := 0
+	buf := l.buf[:l.size]
+	for _, v := range buf {
+		length += 1 + len(v.vt100)
+	}
+	tmp := make([]byte, 0, length)
+	for _, v := range buf {
+		tmp = append(tmp, v.vt100...)
+		tmp = append(tmp, v.char)
+	}
+	return tmp
+}
+
+func (l *lineEdit) String() string {
+	return string(l.Bytes())
+}
diff --git a/vendor/github.com/lunixbochs/vtclean/vtclean.go b/vendor/github.com/lunixbochs/vtclean/vtclean.go
new file mode 100644
index 0000000..fec492c
--- /dev/null
+++ b/vendor/github.com/lunixbochs/vtclean/vtclean.go
@@ -0,0 +1,88 @@
+package vtclean
+
+import (
+	"bytes"
+	"regexp"
+	"strconv"
+)
+
+// see regex.txt for a slightly separated version of this regex
+var vt100re = regexp.MustCompile(`^\033([\[\]]([\d\?]+)?(;[\d\?]+)*)?(.)`)
+var vt100exc = regexp.MustCompile(`^\033(\[[^a-zA-Z0-9@\?]+|[\(\)]).`)
+
+// this is to handle the RGB escape generated by `tput initc 1 500 500 500`
+var vt100long = regexp.MustCompile(`^\033](\d+);([^\033]+)\033\\`)
+
+func Clean(line string, color bool) string {
+	var edit = newLineEdit(len(line))
+	lineb := []byte(line)
+
+	hadColor := false
+	for i := 0; i < len(lineb); {
+		c := lineb[i]
+		switch c {
+		case '\b':
+			edit.Move(-1)
+		case '\033':
+			// set terminal title
+			if bytes.HasPrefix(lineb[i:], []byte("\x1b]0;")) {
+				pos := bytes.Index(lineb[i:], []byte("\a"))
+				if pos != -1 {
+					i += pos + 1
+					continue
+				}
+			}
+			if m := vt100long.Find(lineb[i:]); m != nil {
+				i += len(m)
+			} else if m := vt100exc.Find(lineb[i:]); m != nil {
+				i += len(m)
+			} else if m := vt100re.FindSubmatch(lineb[i:]); m != nil {
+				i += len(m[0])
+				num := string(m[2])
+				n, err := strconv.Atoi(num)
+				if err != nil || n > 10000 {
+					n = 1
+				}
+				switch m[4][0] {
+				case 'm':
+					if color {
+						hadColor = true
+						edit.Vt100(m[0])
+					}
+				case '@':
+					edit.Insert(bytes.Repeat([]byte{' '}, n))
+				case 'G':
+					edit.MoveAbs(n)
+				case 'C':
+					edit.Move(n)
+				case 'D':
+					edit.Move(-n)
+				case 'P':
+					edit.Delete(n)
+				case 'K':
+					switch num {
+					case "", "0":
+						edit.ClearRight()
+					case "1":
+						edit.ClearLeft()
+					case "2":
+						edit.Clear()
+					}
+				}
+			} else {
+				i += 1
+			}
+			continue
+		default:
+			if c == '\n' || c >= ' ' {
+				edit.Write([]byte{c})
+			}
+		}
+		i += 1
+	}
+	out := edit.Bytes()
+	if hadColor {
+		out = append(out, []byte("\033[0m")...)
+	}
+	return string(out)
+}
diff --git a/vendor/github.com/lunixbochs/vtclean/vtclean/vtclean.go b/vendor/github.com/lunixbochs/vtclean/vtclean/vtclean.go
new file mode 100644
index 0000000..2c4f177
--- /dev/null
+++ b/vendor/github.com/lunixbochs/vtclean/vtclean/vtclean.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+	"flag"
+	"github.com/lunixbochs/vtclean"
+	"io"
+	"os"
+)
+
+func main() {
+	color := flag.Bool("color", false, "enable color")
+	flag.Parse()
+
+	stdout := vtclean.NewWriter(os.Stdout, *color)
+	defer stdout.Close()
+	io.Copy(stdout, os.Stdin)
+}
diff --git a/vendor/github.com/manifoldco/promptui/codes.go b/vendor/github.com/manifoldco/promptui/codes.go
new file mode 100644
index 0000000..de3f086
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/codes.go
@@ -0,0 +1,108 @@
+package promptui
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"text/template"
+)
+
+const esc = "\033["
+
+type attribute int
+
+// Foreground weight/decoration attributes.
+const (
+	reset attribute = iota
+
+	FGBold
+	FGFaint
+	FGItalic
+	FGUnderline
+)
+
+// Foreground color attributes
+const (
+	FGBlack attribute = iota + 30
+	FGRed
+	FGGreen
+	FGYellow
+	FGBlue
+	FGMagenta
+	FGCyan
+	FGWhite
+)
+
+// Background color attributes
+const (
+	BGBlack attribute = iota + 40
+	BGRed
+	BGGreen
+	BGYellow
+	BGBlue
+	BGMagenta
+	BGCyan
+	BGWhite
+)
+
+// ResetCode is the character code used to reset the terminal formatting
+var ResetCode = fmt.Sprintf("%s%dm", esc, reset)
+
+const (
+	hideCursor = esc + "?25l"
+	showCursor = esc + "?25h"
+	clearLine  = esc + "2K"
+)
+
+// FuncMap defines template helpers for the output. It can be extended as a
+// regular map.
+var FuncMap = template.FuncMap{
+	"black":     Styler(FGBlack),
+	"red":       Styler(FGRed),
+	"green":     Styler(FGGreen),
+	"yellow":    Styler(FGYellow),
+	"blue":      Styler(FGBlue),
+	"magenta":   Styler(FGMagenta),
+	"cyan":      Styler(FGCyan),
+	"white":     Styler(FGWhite),
+	"bgBlack":   Styler(BGBlack),
+	"bgRed":     Styler(BGRed),
+	"bgGreen":   Styler(BGGreen),
+	"bgYellow":  Styler(BGYellow),
+	"bgBlue":    Styler(BGBlue),
+	"bgMagenta": Styler(BGMagenta),
+	"bgCyan":    Styler(BGCyan),
+	"bgWhite":   Styler(BGWhite),
+	"bold":      Styler(FGBold),
+	"faint":     Styler(FGFaint),
+	"italic":    Styler(FGItalic),
+	"underline": Styler(FGUnderline),
+}
+
+func upLine(n uint) string {
+	return movementCode(n, 'A')
+}
+
+func movementCode(n uint, code rune) string {
+	return esc + strconv.FormatUint(uint64(n), 10) + string(code)
+}
+
+// Styler returns a func that applies the attributes given in the Styler call
+// to the provided string.
+func Styler(attrs ...attribute) func(interface{}) string {
+	attrstrs := make([]string, len(attrs))
+	for i, v := range attrs {
+		attrstrs[i] = strconv.Itoa(int(v))
+	}
+
+	seq := strings.Join(attrstrs, ";")
+
+	return func(v interface{}) string {
+		end := ""
+		s, ok := v.(string)
+		if !ok || !strings.HasSuffix(s, ResetCode) {
+			end = ResetCode
+		}
+		return fmt.Sprintf("%s%sm%v%s", esc, seq, v, end)
+	}
+}
diff --git a/vendor/github.com/manifoldco/promptui/keycodes.go b/vendor/github.com/manifoldco/promptui/keycodes.go
new file mode 100644
index 0000000..c1f8491
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/keycodes.go
@@ -0,0 +1,25 @@
+// +build !windows
+
+package promptui
+
+import "github.com/chzyer/readline"
+
+var (
+	// KeyEnter is the default key for submission/selection
+	KeyEnter rune = readline.CharEnter
+
+	// KeyBackspace is the default key for deleting input text
+	KeyBackspace rune = readline.CharBackspace
+
+	// KeyPrev is the default key to go up during selection
+	KeyPrev rune = readline.CharPrev
+
+	// KeyNext is the default key to go down during selection
+	KeyNext rune = readline.CharNext
+
+	// KeyBackward is the default key to page up during selection
+	KeyBackward rune = readline.CharBackward
+
+	// KeyForward is the default key to page down during selection
+	KeyForward rune = readline.CharForward
+)
diff --git a/vendor/github.com/manifoldco/promptui/keycodes_windows.go b/vendor/github.com/manifoldco/promptui/keycodes_windows.go
new file mode 100644
index 0000000..fa4709c
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/keycodes_windows.go
@@ -0,0 +1,25 @@
+package promptui
+
+// source: https://msdn.microsoft.com/en-us/library/aa243025(v=vs.60).aspx
+
+var (
+	// KeyEnter is the default key for submission/selection
+	KeyEnter rune = 13
+
+	// KeyBackspace is the default key for deleting input text
+	KeyBackspace rune = 8
+
+	// FIXME: keys below are not triggered by readline, not working on Windows
+
+	// KeyPrev is the default key to go up during selection
+	KeyPrev rune = 38
+
+	// KeyNext is the default key to go down during selection
+	KeyNext rune = 40
+
+	// KeyBackward is the default key to page up during selection
+	KeyBackward rune = 37
+
+	// KeyForward is the default key to page down during selection
+	KeyForward rune = 39
+)
diff --git a/vendor/github.com/manifoldco/promptui/list/list.go b/vendor/github.com/manifoldco/promptui/list/list.go
new file mode 100644
index 0000000..b1cc8be
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/list/list.go
@@ -0,0 +1,197 @@
+package list
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+)
+
+// Searcher can be implemented to allow the list to search for results.
+type Searcher func(input string, index int) bool
+
+// NotFound is an index returned when no item was selected. This could
+// happen due to a search without results.
+const NotFound = -1
+
+// List holds a collection of items that can be displayed with an N number of
+// visible items. The list can be moved up, down by one item of time or an
+// entire page (ie: visible size). It keeps track of the current selected item.
+type List struct {
+	items    []*interface{}
+	scope    []*interface{}
+	cursor   int // cursor holds the index of the current selected item
+	size     int // size is the number of visible options
+	start    int
+	Searcher Searcher
+}
+
+// New creates and initializes a list. Items must be a slice type and size must
+// be greater than 0.
+func New(items interface{}, size int) (*List, error) {
+	if size < 1 {
+		return nil, fmt.Errorf("list size %d must be greater than 0", size)
+	}
+
+	if items == nil || reflect.TypeOf(items).Kind() != reflect.Slice {
+		return nil, fmt.Errorf("items %v is not a slice", items)
+	}
+
+	slice := reflect.ValueOf(items)
+	values := make([]*interface{}, slice.Len())
+
+	for i := range values {
+		item := slice.Index(i).Interface()
+		values[i] = &item
+	}
+
+	return &List{size: size, items: values, scope: values}, nil
+}
+
+// Prev moves the visible list back one item. If the selected item is out of
+// view, the new select item becomes the last visible item. If the list is
+// already at the top, nothing happens.
+func (l *List) Prev() {
+	if l.cursor > 0 {
+		l.cursor--
+	}
+
+	if l.start > l.cursor {
+		l.start = l.cursor
+	}
+}
+
+// Search allows the list to be filtered by a given term. The list must
+// implement the searcher method for that.
+func (l *List) Search(term string) {
+	term = strings.Trim(term, " ")
+	l.cursor = 0
+	l.start = 0
+	l.search(term)
+}
+
+// CancelSearch stops the current search and returns the list to its
+// original order.
+func (l *List) CancelSearch() {
+	l.cursor = 0
+	l.start = 0
+	l.scope = l.items
+}
+
+func (l *List) search(term string) {
+	var scope []*interface{}
+
+	for i, item := range l.items {
+		if l.Searcher(term, i) {
+			scope = append(scope, item)
+		}
+	}
+
+	l.scope = scope
+}
+
+// Next moves the visible list forward one item. If the selected item is out of
+// view, the new select item becomes the first visible item. If the list is
+// already at the bottom, nothing happens.
+func (l *List) Next() {
+	max := len(l.scope) - 1
+
+	if l.cursor < max {
+		l.cursor++
+	}
+
+	if l.start+l.size <= l.cursor {
+		l.start = l.cursor - l.size + 1
+	}
+}
+
+// PageUp moves the visible list backward by x items. Where x is the size of the
+// visible items on the list. The selected item becomes the first visible item.
+// If the list is already at the bottom, the selected item becomes the last
+// visible item.
+func (l *List) PageUp() {
+	start := l.start - l.size
+	if start < 0 {
+		l.start = 0
+	} else {
+		l.start = start
+	}
+
+	cursor := l.start
+
+	if cursor < l.cursor {
+		l.cursor = cursor
+	}
+}
+
+// PageDown moves the visible list forward by x items. Where x is the size of
+// the visible items on the list. The selected item becomes the first visible
+// item.
+func (l *List) PageDown() {
+	start := l.start + l.size
+	max := len(l.scope) - l.size
+
+	switch {
+	case len(l.scope) < l.size:
+		l.start = 0
+	case start > max:
+		l.start = max
+	default:
+		l.start = start
+	}
+
+	cursor := l.start
+
+	if cursor == l.cursor {
+		l.cursor = len(l.scope) - 1
+	} else if cursor > l.cursor {
+		l.cursor = cursor
+	}
+}
+
+// CanPageDown returns whether a list can still PageDown().
+func (l *List) CanPageDown() bool {
+	max := len(l.scope)
+	return l.start+l.size < max
+}
+
+// CanPageUp returns whether a list can still PageUp().
+func (l *List) CanPageUp() bool {
+	return l.start > 0
+}
+
+// Index returns the index of the item currently selected.
+func (l *List) Index() int {
+	selected := l.scope[l.cursor]
+
+	for i, item := range l.items {
+		if item == selected {
+			return i
+		}
+	}
+
+	return NotFound
+}
+
+// Items returns a slice equal to the size of the list with the current visible
+// items and the index of the active item in this list.
+func (l *List) Items() ([]interface{}, int) {
+	var result []interface{}
+	max := len(l.scope)
+	end := l.start + l.size
+
+	if end > max {
+		end = max
+	}
+
+	active := NotFound
+
+	for i, j := l.start, 0; i < end; i, j = i+1, j+1 {
+		if l.cursor == i {
+			active = j
+		}
+
+		result = append(result, *l.scope[i])
+	}
+
+	return result, active
+}
diff --git a/vendor/github.com/manifoldco/promptui/prompt.go b/vendor/github.com/manifoldco/promptui/prompt.go
new file mode 100644
index 0000000..9fdfcb6
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/prompt.go
@@ -0,0 +1,338 @@
+package promptui
+
+import (
+	"fmt"
+	"io"
+	"strings"
+	"text/template"
+
+	"github.com/chzyer/readline"
+	"github.com/manifoldco/promptui/screenbuf"
+)
+
+const cursor = "\u2588"
+
+// Prompt represents a single line text field input.
+type Prompt struct {
+	// Label is the value displayed on the command line prompt. It can be any
+	// value one would pass to a text/template Execute(), including just a string.
+	Label interface{}
+
+	Default string // Default is the initial value to populate in the prompt
+
+	// AllowEdit lets the user edit the default value. If false, any key press
+	// other than <Enter> automatically clears the default value.
+	AllowEdit bool
+
+	// Validate is optional. If set, this function is used to validate the input
+	// after each character entry.
+	Validate ValidateFunc
+
+	// If mask is set, this value is displayed instead of the actual input
+	// characters.
+	Mask rune
+
+	// Templates can be used to customize the prompt output. If nil is passed, the
+	// default templates are used.
+	Templates *PromptTemplates
+
+	// IsConfirm sets the prompt to be a [y/N] question.
+	IsConfirm bool
+
+	// IsVimMode enables vi-like movements (hjkl) and editing.
+	IsVimMode bool
+
+	stdin  io.ReadCloser
+	stdout io.WriteCloser
+}
+
+// PromptTemplates allow a prompt to be customized following stdlib
+// text/template syntax. If any field is blank a default template is used.
+type PromptTemplates struct {
+	// Prompt is a text/template for the initial prompt question.
+	Prompt string
+
+	// Prompt is a text/template if the prompt is a confirmation.
+	Confirm string
+
+	// Valid is a text/template for when the current input is valid.
+	Valid string
+
+	// Invalid is a text/template for when the current input is invalid.
+	Invalid string
+
+	// Success is a text/template for the successful result.
+	Success string
+
+	// Prompt is a text/template when there is a validation error.
+	ValidationError string
+
+	// FuncMap is a map of helpers for the templates. If nil, the default helpers
+	// are used.
+	FuncMap template.FuncMap
+
+	prompt     *template.Template
+	valid      *template.Template
+	invalid    *template.Template
+	validation *template.Template
+	success    *template.Template
+}
+
+// Run runs the prompt, returning the validated input.
+func (p *Prompt) Run() (string, error) {
+	c := &readline.Config{}
+	err := c.Init()
+	if err != nil {
+		return "", err
+	}
+
+	err = p.prepareTemplates()
+	if err != nil {
+		return "", err
+	}
+
+	if p.stdin != nil {
+		c.Stdin = p.stdin
+	}
+
+	if p.stdout != nil {
+		c.Stdout = p.stdout
+	}
+
+	if p.Mask != 0 {
+		c.EnableMask = true
+		c.MaskRune = p.Mask
+	}
+
+	if p.IsVimMode {
+		c.VimMode = true
+	}
+
+	c.HistoryLimit = -1
+	c.UniqueEditLine = true
+
+	rl, err := readline.NewEx(c)
+	if err != nil {
+		return "", err
+	}
+
+	rl.Write([]byte(hideCursor))
+	sb := screenbuf.New(rl)
+
+	validFn := func(x string) error {
+		return nil
+	}
+
+	if p.Validate != nil {
+		validFn = p.Validate
+	}
+
+	var inputErr error
+	input := p.Default
+	if p.IsConfirm {
+		input = ""
+	}
+	eraseDefault := input != "" && !p.AllowEdit
+
+	c.SetListener(func(line []rune, pos int, key rune) ([]rune, int, bool) {
+		if line != nil {
+			input += string(line)
+		}
+
+		switch key {
+		case 0: // empty
+		case KeyEnter:
+			return nil, 0, false
+		case KeyBackspace:
+			if eraseDefault {
+				eraseDefault = false
+				input = ""
+			}
+			if len(input) > 0 {
+				r := []rune(input)
+				input = string(r[:len(r)-1])
+			}
+		default:
+			if eraseDefault {
+				eraseDefault = false
+				input = string(line)
+			}
+		}
+
+		err := validFn(input)
+		var prompt []byte
+
+		if err != nil {
+			prompt = render(p.Templates.invalid, p.Label)
+		} else {
+			prompt = render(p.Templates.valid, p.Label)
+			if p.IsConfirm {
+				prompt = render(p.Templates.prompt, p.Label)
+			}
+		}
+
+		echo := input
+		if p.Mask != 0 {
+			echo = strings.Repeat(string(p.Mask), len(echo))
+		}
+
+		prompt = append(prompt, []byte(echo+cursor)...)
+
+		sb.Reset()
+		sb.Write(prompt)
+
+		if inputErr != nil {
+			validation := render(p.Templates.validation, inputErr)
+			sb.Write(validation)
+			inputErr = nil
+		}
+
+		sb.Flush()
+
+		return nil, 0, true
+	})
+
+	for {
+		_, err = rl.Readline()
+
+		inputErr = validFn(input)
+		if inputErr == nil {
+			break
+		}
+
+		if err != nil {
+			switch err {
+			case readline.ErrInterrupt:
+				err = ErrInterrupt
+			case io.EOF:
+				err = ErrEOF
+			}
+			break
+		}
+	}
+
+	if err != nil {
+		if err.Error() == "Interrupt" {
+			err = ErrInterrupt
+		}
+		sb.Reset()
+		sb.WriteString("")
+		sb.Flush()
+		rl.Write([]byte(showCursor))
+		rl.Close()
+		return "", err
+	}
+
+	echo := input
+	if p.Mask != 0 {
+		echo = strings.Repeat(string(p.Mask), len(echo))
+	}
+
+	prompt := render(p.Templates.valid, p.Label)
+	prompt = append(prompt, []byte(echo)...)
+
+	if p.IsConfirm {
+		lowerDefault := strings.ToLower(p.Default)
+		if strings.ToLower(echo) != "y" && (lowerDefault != "y" || (lowerDefault == "y" && echo != "")) {
+			prompt = render(p.Templates.invalid, p.Label)
+			err = ErrAbort
+		}
+	}
+
+	sb.Reset()
+	sb.Write(prompt)
+	sb.Flush()
+	rl.Write([]byte(showCursor))
+	rl.Close()
+
+	return input, err
+}
+
+func (p *Prompt) prepareTemplates() error {
+	tpls := p.Templates
+	if tpls == nil {
+		tpls = &PromptTemplates{}
+	}
+
+	if tpls.FuncMap == nil {
+		tpls.FuncMap = FuncMap
+	}
+
+	bold := Styler(FGBold)
+
+	if p.IsConfirm {
+		if tpls.Confirm == "" {
+			confirm := "y/N"
+			if strings.ToLower(p.Default) == "y" {
+				confirm = "Y/n"
+			}
+			tpls.Confirm = fmt.Sprintf(`{{ "%s" | bold }} {{ . | bold }}? {{ "[%s]" | faint }} `, IconInitial, confirm)
+		}
+
+		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Confirm)
+		if err != nil {
+			return err
+		}
+
+		tpls.prompt = tpl
+	} else {
+		if tpls.Prompt == "" {
+			tpls.Prompt = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconInitial), bold(":"))
+		}
+
+		tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Prompt)
+		if err != nil {
+			return err
+		}
+
+		tpls.prompt = tpl
+	}
+
+	if tpls.Valid == "" {
+		tpls.Valid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconGood), bold(":"))
+	}
+
+	tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Valid)
+	if err != nil {
+		return err
+	}
+
+	tpls.valid = tpl
+
+	if tpls.Invalid == "" {
+		tpls.Invalid = fmt.Sprintf("%s {{ . | bold }}%s ", bold(IconBad), bold(":"))
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Invalid)
+	if err != nil {
+		return err
+	}
+
+	tpls.invalid = tpl
+
+	if tpls.ValidationError == "" {
+		tpls.ValidationError = `{{ ">>" | red }} {{ . | red }}`
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.ValidationError)
+	if err != nil {
+		return err
+	}
+
+	tpls.validation = tpl
+
+	if tpls.Success == "" {
+		tpls.Success = `{{ . | faint }}`
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Success)
+	if err != nil {
+		return err
+	}
+
+	tpls.success = tpl
+
+	p.Templates = tpls
+
+	return nil
+}
diff --git a/vendor/github.com/manifoldco/promptui/promptui.go b/vendor/github.com/manifoldco/promptui/promptui.go
new file mode 100644
index 0000000..4faa68d
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/promptui.go
@@ -0,0 +1,18 @@
+// Package promptui provides ui elements for the command line prompt.
+package promptui
+
+import "errors"
+
+// ErrEOF is returned from prompts when EOF is encountered.
+var ErrEOF = errors.New("^D")
+
+// ErrInterrupt is returned from prompts when an interrupt (ctrl-c) is
+// encountered.
+var ErrInterrupt = errors.New("^C")
+
+// ErrAbort is returned when confirm prompts are supplied "n"
+var ErrAbort = errors.New("")
+
+// ValidateFunc validates the given input. It should return a ValidationError
+// if the input is not valid.
+type ValidateFunc func(string) error
diff --git a/vendor/github.com/manifoldco/promptui/screenbuf/screenbuf.go b/vendor/github.com/manifoldco/promptui/screenbuf/screenbuf.go
new file mode 100644
index 0000000..f9dd24c
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/screenbuf/screenbuf.go
@@ -0,0 +1,138 @@
+package screenbuf
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+)
+
+const esc = "\033["
+
+var (
+	clearLine = []byte(esc + "2K\r")
+	moveUp    = []byte(esc + "1A")
+	moveDown  = []byte(esc + "1B")
+)
+
+// ScreenBuf is a convenient way to write to terminal screens. It creates,
+// clears and, moves up or down lines as needed to write the output to the
+// terminal using ANSI escape codes.
+type ScreenBuf struct {
+	w      io.Writer
+	buf    *bytes.Buffer
+	reset  bool
+	flush  bool
+	cursor int
+	height int
+}
+
+// New creates and initializes a new ScreenBuf.
+func New(w io.Writer) *ScreenBuf {
+	return &ScreenBuf{buf: &bytes.Buffer{}, w: w}
+}
+
+// Reset truncates the underlining buffer and marks all its previous lines to be
+// cleared during the next Write.
+func (s *ScreenBuf) Reset() {
+	s.buf.Reset()
+	s.reset = true
+}
+
+// Write writes a single line to the underlining buffer. If the ScreenBuf was
+// previously reset, all previous lines are cleared and the output starts from
+// the top. Lines with \r or \n will fail since they can interfere with the
+// terminal ability to move between lines.
+func (s *ScreenBuf) Write(b []byte) (int, error) {
+	if bytes.ContainsAny(b, "\r\n") {
+		return 0, fmt.Errorf("%q should not contain either \\r or \\n", b)
+	}
+
+	if s.reset {
+		for i := 0; i < s.height; i++ {
+			_, err := s.buf.Write(moveUp)
+			if err != nil {
+				return 0, err
+			}
+			_, err = s.buf.Write(clearLine)
+			if err != nil {
+				return 0, err
+			}
+		}
+		s.cursor = 0
+		s.height = 0
+		s.reset = false
+	}
+
+	switch {
+	case s.cursor == s.height:
+		n, err := s.buf.Write(clearLine)
+		if err != nil {
+			return n, err
+		}
+		line := append(b, []byte("\n")...)
+		n, err = s.buf.Write(line)
+		if err != nil {
+			return n, err
+		}
+		s.height++
+		s.cursor++
+		return n, nil
+	case s.cursor < s.height:
+		n, err := s.buf.Write(clearLine)
+		if err != nil {
+			return n, err
+		}
+		n, err = s.buf.Write(b)
+		if err != nil {
+			return n, err
+		}
+		n, err = s.buf.Write(moveDown)
+		if err != nil {
+			return n, err
+		}
+		s.cursor++
+		return n, nil
+	default:
+		return 0, fmt.Errorf("Invalid write cursor position (%d) exceeded line height: %d", s.cursor, s.height)
+	}
+}
+
+// Flush writes any buffered data to the underlying io.Writer.
+func (s *ScreenBuf) Flush() error {
+	for i := s.cursor; i < s.height; i++ {
+		if i < s.height {
+			_, err := s.buf.Write(clearLine)
+			if err != nil {
+				return err
+			}
+		}
+		_, err := s.buf.Write(moveDown)
+		if err != nil {
+			return err
+		}
+	}
+
+	_, err := s.buf.WriteTo(s.w)
+	if err != nil {
+		return err
+	}
+
+	s.buf.Reset()
+
+	for i := 0; i < s.height; i++ {
+		_, err := s.buf.Write(moveUp)
+		if err != nil {
+			return err
+		}
+	}
+
+	s.cursor = 0
+
+	return nil
+}
+
+// WriteString is a convenient function to write a new line passing a string.
+// Check ScreenBuf.Write() for a detailed explanation of the function behaviour.
+func (s *ScreenBuf) WriteString(str string) (int, error) {
+	return s.Write([]byte(str))
+}
diff --git a/vendor/github.com/manifoldco/promptui/select.go b/vendor/github.com/manifoldco/promptui/select.go
new file mode 100644
index 0000000..165b969
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/select.go
@@ -0,0 +1,503 @@
+package promptui
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"text/template"
+
+	"github.com/chzyer/readline"
+	"github.com/juju/ansiterm"
+	"github.com/manifoldco/promptui/list"
+	"github.com/manifoldco/promptui/screenbuf"
+)
+
+// SelectedAdd is returned from SelectWithAdd when add is selected.
+const SelectedAdd = -1
+
+// Select represents a list for selecting a single item
+type Select struct {
+	// Label is the value displayed on the command line prompt. It can be any
+	// value one would pass to a text/template Execute(), including just a string.
+	Label interface{}
+
+	// Items are the items to use in the list. It can be any slice type one would
+	// pass to a text/template execute, including a string slice.
+	Items interface{}
+
+	// Size is the number of items that should appear on the select before
+	// scrolling. If it is 0, defaults to 5.
+	Size int
+
+	// IsVimMode sets whether readline is using Vim mode.
+	IsVimMode bool
+
+	// Templates can be used to customize the select output. If nil is passed, the
+	// default templates are used.
+	Templates *SelectTemplates
+
+	// Keys can be used to change movement and search keys.
+	Keys *SelectKeys
+
+	// Searcher can be implemented to teach the select how to search for items.
+	Searcher list.Searcher
+
+	// Starts the prompt in search mode.
+	StartInSearchMode bool
+
+	label string
+
+	list *list.List
+}
+
+// SelectKeys defines which keys can be used for movement and search.
+type SelectKeys struct {
+	Next     Key // Next defaults to down arrow key
+	Prev     Key // Prev defaults to up arrow key
+	PageUp   Key // PageUp defaults to left arrow key
+	PageDown Key // PageDown defaults to right arrow key
+	Search   Key // Search defaults to '/' key
+}
+
+// Key defines a keyboard code and a display representation for the help
+// Check https://github.com/chzyer/readline for a list of codes
+type Key struct {
+	Code    rune
+	Display string
+}
+
+// SelectTemplates allow a select prompt to be customized following stdlib
+// text/template syntax. If any field is blank a default template is used.
+type SelectTemplates struct {
+	// Active is a text/template for the label.
+	Label string
+
+	// Active is a text/template for when an item is current active.
+	Active string
+
+	// Inactive is a text/template for when an item is not current active.
+	Inactive string
+
+	// Selected is a text/template for when an item was successfully selected.
+	Selected string
+
+	// Details is a text/template for when an item current active to show
+	// additional information. It can have multiple lines.
+	Details string
+
+	// Help is a text/template for displaying instructions at the top. By default
+	// it shows keys for movement and search.
+	Help string
+
+	// FuncMap is a map of helpers for the templates. If nil, the default helpers
+	// are used.
+	FuncMap template.FuncMap
+
+	label    *template.Template
+	active   *template.Template
+	inactive *template.Template
+	selected *template.Template
+	details  *template.Template
+	help     *template.Template
+}
+
+// Run runs the Select list. It returns the index of the selected element,
+// and its value.
+func (s *Select) Run() (int, string, error) {
+	if s.Size == 0 {
+		s.Size = 5
+	}
+
+	l, err := list.New(s.Items, s.Size)
+	if err != nil {
+		return 0, "", err
+	}
+	l.Searcher = s.Searcher
+
+	s.list = l
+
+	s.setKeys()
+
+	err = s.prepareTemplates()
+	if err != nil {
+		return 0, "", err
+	}
+	return s.innerRun(0, ' ')
+}
+
+func (s *Select) innerRun(starting int, top rune) (int, string, error) {
+	stdin := readline.NewCancelableStdin(os.Stdin)
+	c := &readline.Config{}
+	err := c.Init()
+	if err != nil {
+		return 0, "", err
+	}
+
+	c.Stdin = stdin
+
+	if s.IsVimMode {
+		c.VimMode = true
+	}
+
+	c.HistoryLimit = -1
+	c.UniqueEditLine = true
+
+	rl, err := readline.NewEx(c)
+	if err != nil {
+		return 0, "", err
+	}
+
+	rl.Write([]byte(hideCursor))
+	sb := screenbuf.New(rl)
+
+	var searchInput []rune
+	canSearch := s.Searcher != nil
+	searchMode := s.StartInSearchMode
+
+	c.SetListener(func(line []rune, pos int, key rune) ([]rune, int, bool) {
+		switch {
+		case key == KeyEnter:
+			return nil, 0, true
+		case key == s.Keys.Next.Code || (key == 'j' && !searchMode):
+			s.list.Next()
+		case key == s.Keys.Prev.Code || (key == 'k' && !searchMode):
+			s.list.Prev()
+		case key == s.Keys.Search.Code:
+			if !canSearch {
+				break
+			}
+
+			if searchMode {
+				searchMode = false
+				searchInput = nil
+				s.list.CancelSearch()
+			} else {
+				searchMode = true
+			}
+		case key == KeyBackspace:
+			if !canSearch || !searchMode {
+				break
+			}
+
+			if len(searchInput) > 1 {
+				searchInput = searchInput[:len(searchInput)-1]
+				s.list.Search(string(searchInput))
+			} else {
+				searchInput = nil
+				s.list.CancelSearch()
+			}
+		case key == s.Keys.PageUp.Code || (key == 'h' && !searchMode):
+			s.list.PageUp()
+		case key == s.Keys.PageDown.Code || (key == 'l' && !searchMode):
+			s.list.PageDown()
+		default:
+			if canSearch && searchMode {
+				searchInput = append(searchInput, line...)
+				s.list.Search(string(searchInput))
+			}
+		}
+
+		if searchMode {
+			header := fmt.Sprintf("Search: %s%s", string(searchInput), cursor)
+			sb.WriteString(header)
+		} else {
+			help := s.renderHelp(canSearch)
+			sb.Write(help)
+		}
+
+		label := render(s.Templates.label, s.Label)
+		sb.Write(label)
+
+		items, idx := s.list.Items()
+		last := len(items) - 1
+
+		for i, item := range items {
+			page := " "
+
+			switch i {
+			case 0:
+				if s.list.CanPageUp() {
+					page = "↑"
+				} else {
+					page = string(top)
+				}
+			case last:
+				if s.list.CanPageDown() {
+					page = "↓"
+				}
+			}
+
+			output := []byte(page + " ")
+
+			if i == idx {
+				output = append(output, render(s.Templates.active, item)...)
+			} else {
+				output = append(output, render(s.Templates.inactive, item)...)
+			}
+
+			sb.Write(output)
+		}
+
+		if idx == list.NotFound {
+			sb.WriteString("")
+			sb.WriteString("No results")
+		} else {
+			active := items[idx]
+
+			details := s.renderDetails(active)
+			for _, d := range details {
+				sb.Write(d)
+			}
+		}
+
+		sb.Flush()
+
+		return nil, 0, true
+	})
+
+	for {
+		_, err = rl.Readline()
+
+		if err != nil {
+			switch {
+			case err == readline.ErrInterrupt, err.Error() == "Interrupt":
+				err = ErrInterrupt
+			case err == io.EOF:
+				err = ErrEOF
+			}
+			break
+		}
+
+		_, idx := s.list.Items()
+		if idx != list.NotFound {
+			break
+		}
+
+	}
+
+	if err != nil {
+		if err.Error() == "Interrupt" {
+			err = ErrInterrupt
+		}
+		sb.Reset()
+		sb.WriteString("")
+		sb.Flush()
+		rl.Write([]byte(showCursor))
+		rl.Close()
+		return 0, "", err
+	}
+
+	items, idx := s.list.Items()
+	item := items[idx]
+
+	output := render(s.Templates.selected, item)
+
+	sb.Reset()
+	sb.Write(output)
+	sb.Flush()
+	rl.Write([]byte(showCursor))
+	rl.Close()
+
+	return s.list.Index(), fmt.Sprintf("%v", item), err
+}
+
+func (s *Select) prepareTemplates() error {
+	tpls := s.Templates
+	if tpls == nil {
+		tpls = &SelectTemplates{}
+	}
+
+	if tpls.FuncMap == nil {
+		tpls.FuncMap = FuncMap
+	}
+
+	if tpls.Label == "" {
+		tpls.Label = fmt.Sprintf("%s {{.}}: ", IconInitial)
+	}
+
+	tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Label)
+	if err != nil {
+		return err
+	}
+
+	tpls.label = tpl
+
+	if tpls.Active == "" {
+		tpls.Active = fmt.Sprintf("%s {{ . | underline }}", IconSelect)
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Active)
+	if err != nil {
+		return err
+	}
+
+	tpls.active = tpl
+
+	if tpls.Inactive == "" {
+		tpls.Inactive = "  {{.}}"
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Inactive)
+	if err != nil {
+		return err
+	}
+
+	tpls.inactive = tpl
+
+	if tpls.Selected == "" {
+		tpls.Selected = fmt.Sprintf(`{{ "%s" | green }} {{ . | faint }}`, IconGood)
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Selected)
+	if err != nil {
+		return err
+	}
+	tpls.selected = tpl
+
+	if tpls.Details != "" {
+		tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Details)
+		if err != nil {
+			return err
+		}
+
+		tpls.details = tpl
+	}
+
+	if tpls.Help == "" {
+		tpls.Help = fmt.Sprintf(`{{ "Use the arrow keys to navigate:" | faint }} {{ .NextKey | faint }} ` +
+			`{{ .PrevKey | faint }} {{ .PageDownKey | faint }} {{ .PageUpKey | faint }} ` +
+			`{{ if .Search }} {{ "and" | faint }} {{ .SearchKey | faint }} {{ "toggles search" | faint }}{{ end }}`)
+	}
+
+	tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Help)
+	if err != nil {
+		return err
+	}
+
+	tpls.help = tpl
+
+	s.Templates = tpls
+
+	return nil
+}
+
+// SelectWithAdd represents a list for selecting a single item, or selecting
+// a newly created item.
+type SelectWithAdd struct {
+	Label string   // Label is the value displayed on the command line prompt.
+	Items []string // Items are the items to use in the list.
+
+	AddLabel string // The label used in the item list for creating a new item.
+
+	// Validate is optional. If set, this function is used to validate the input
+	// after each character entry.
+	Validate ValidateFunc
+
+	IsVimMode bool // Whether readline is using Vim mode.
+}
+
+// Run runs the Select list. It returns the index of the selected element,
+// and its value. If a new element is created, -1 is returned as the index.
+func (sa *SelectWithAdd) Run() (int, string, error) {
+	if len(sa.Items) > 0 {
+		newItems := append([]string{sa.AddLabel}, sa.Items...)
+
+		list, err := list.New(newItems, 5)
+		if err != nil {
+			return 0, "", err
+		}
+
+		s := Select{
+			Label:     sa.Label,
+			Items:     newItems,
+			IsVimMode: sa.IsVimMode,
+			Size:      5,
+			list:      list,
+		}
+		s.setKeys()
+
+		err = s.prepareTemplates()
+		if err != nil {
+			return 0, "", err
+		}
+
+		selected, value, err := s.innerRun(1, '+')
+		if err != nil || selected != 0 {
+			return selected - 1, value, err
+		}
+
+		// XXX run through terminal for windows
+		os.Stdout.Write([]byte(upLine(1) + "\r" + clearLine))
+	}
+
+	p := Prompt{
+		Label:     sa.AddLabel,
+		Validate:  sa.Validate,
+		IsVimMode: sa.IsVimMode,
+	}
+	value, err := p.Run()
+	return SelectedAdd, value, err
+}
+
+func (s *Select) setKeys() {
+	if s.Keys != nil {
+		return
+	}
+	s.Keys = &SelectKeys{
+		Prev:     Key{Code: KeyPrev, Display: "↑"},
+		Next:     Key{Code: KeyNext, Display: "↓"},
+		PageUp:   Key{Code: KeyBackward, Display: "←"},
+		PageDown: Key{Code: KeyForward, Display: "→"},
+		Search:   Key{Code: '/', Display: "/"},
+	}
+}
+
+func (s *Select) renderDetails(item interface{}) [][]byte {
+	if s.Templates.details == nil {
+		return nil
+	}
+
+	var buf bytes.Buffer
+	w := ansiterm.NewTabWriter(&buf, 0, 0, 8, ' ', 0)
+
+	err := s.Templates.details.Execute(w, item)
+	if err != nil {
+		fmt.Fprintf(w, "%v", item)
+	}
+
+	w.Flush()
+
+	output := buf.Bytes()
+
+	return bytes.Split(output, []byte("\n"))
+}
+
+func (s *Select) renderHelp(b bool) []byte {
+	keys := struct {
+		NextKey     string
+		PrevKey     string
+		PageDownKey string
+		PageUpKey   string
+		Search      bool
+		SearchKey   string
+	}{
+		NextKey:     s.Keys.Next.Display,
+		PrevKey:     s.Keys.Prev.Display,
+		PageDownKey: s.Keys.PageDown.Display,
+		PageUpKey:   s.Keys.PageUp.Display,
+		SearchKey:   s.Keys.Search.Display,
+		Search:      b,
+	}
+
+	return render(s.Templates.help, keys)
+}
+
+func render(tpl *template.Template, data interface{}) []byte {
+	var buf bytes.Buffer
+	err := tpl.Execute(&buf, data)
+	if err != nil {
+		return []byte(fmt.Sprintf("%v", data))
+	}
+	return buf.Bytes()
+}
diff --git a/vendor/github.com/manifoldco/promptui/styles.go b/vendor/github.com/manifoldco/promptui/styles.go
new file mode 100644
index 0000000..7decdd8
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/styles.go
@@ -0,0 +1,12 @@
+// +build !windows
+
+package promptui
+
+// Icons used for displaying prompts or status
+var (
+	IconInitial = Styler(FGBlue)("?")
+	IconGood    = Styler(FGGreen)("✔")
+	IconWarn    = Styler(FGYellow)("⚠")
+	IconBad     = Styler(FGRed)("✗")
+	IconSelect  = Styler(FGBold)("▸")
+)
diff --git a/vendor/github.com/manifoldco/promptui/styles_windows.go b/vendor/github.com/manifoldco/promptui/styles_windows.go
new file mode 100644
index 0000000..d48dfdd
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/styles_windows.go
@@ -0,0 +1,10 @@
+package promptui
+
+// Icons used for displaying prompts or status
+var (
+	IconInitial = Styler(FGBlue)("?")
+	IconGood    = Styler(FGGreen)("v")
+	IconWarn    = Styler(FGYellow)("!")
+	IconBad     = Styler(FGRed)("x")
+	IconSelect  = Styler(FGBold)(">")
+)
diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml
new file mode 100644
index 0000000..98db8f0
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/.travis.yml
@@ -0,0 +1,9 @@
+language: go
+go:
+  - tip
+
+before_install:
+  - go get github.com/mattn/goveralls
+  - go get golang.org/x/tools/cmd/cover
+script:
+  - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw
diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE
new file mode 100644
index 0000000..91b5cef
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Yasuhiro Matsumoto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md
new file mode 100644
index 0000000..56729a9
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/README.md
@@ -0,0 +1,48 @@
+# go-colorable
+
+[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
+[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
+[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master)
+[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
+
+Colorable writer for windows.
+
+For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
+This package is possible to handle escape sequence for ansi color on windows.
+
+## Too Bad!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
+
+
+## So Good!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
+
+## Usage
+
+```go
+logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
+logrus.SetOutput(colorable.NewColorableStdout())
+
+logrus.Info("succeeded")
+logrus.Warn("not correct")
+logrus.Error("something error")
+logrus.Fatal("panic")
+```
+
+You can compile above code on non-windows OSs.
+
+## Installation
+
+```
+$ go get github.com/mattn/go-colorable
+```
+
+# License
+
+MIT
+
+# Author
+
+Yasuhiro Matsumoto (a.k.a mattn)
diff --git a/vendor/github.com/mattn/go-colorable/cmd/colorable/colorable.go b/vendor/github.com/mattn/go-colorable/cmd/colorable/colorable.go
new file mode 100644
index 0000000..8790477
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/cmd/colorable/colorable.go
@@ -0,0 +1,12 @@
+package main
+
+import (
+	"io"
+	"os"
+
+	"github.com/mattn/go-colorable"
+)
+
+func main() {
+	io.Copy(colorable.NewColorableStdout(), os.Stdin)
+}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
new file mode 100644
index 0000000..1f28d77
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
@@ -0,0 +1,29 @@
+// +build appengine
+
+package colorable
+
+import (
+	"io"
+	"os"
+
+	_ "github.com/mattn/go-isatty"
+)
+
+// NewColorable return new instance of Writer which handle escape sequence.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	return file
+}
+
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return os.Stdout
+}
+
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return os.Stderr
+}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go
new file mode 100644
index 0000000..887f203
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_others.go
@@ -0,0 +1,30 @@
+// +build !windows
+// +build !appengine
+
+package colorable
+
+import (
+	"io"
+	"os"
+
+	_ "github.com/mattn/go-isatty"
+)
+
+// NewColorable return new instance of Writer which handle escape sequence.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	return file
+}
+
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return os.Stdout
+}
+
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return os.Stderr
+}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go
new file mode 100644
index 0000000..404e10c
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go
@@ -0,0 +1,980 @@
+// +build windows
+// +build !appengine
+
+package colorable
+
+import (
+	"bytes"
+	"io"
+	"math"
+	"os"
+	"strconv"
+	"strings"
+	"syscall"
+	"unsafe"
+
+	"github.com/mattn/go-isatty"
+)
+
+const (
+	foregroundBlue      = 0x1
+	foregroundGreen     = 0x2
+	foregroundRed       = 0x4
+	foregroundIntensity = 0x8
+	foregroundMask      = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
+	backgroundBlue      = 0x10
+	backgroundGreen     = 0x20
+	backgroundRed       = 0x40
+	backgroundIntensity = 0x80
+	backgroundMask      = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
+)
+
+const (
+	genericRead  = 0x80000000
+	genericWrite = 0x40000000
+)
+
+const (
+	consoleTextmodeBuffer = 0x1
+)
+
+type wchar uint16
+type short int16
+type dword uint32
+type word uint16
+
+type coord struct {
+	x short
+	y short
+}
+
+type smallRect struct {
+	left   short
+	top    short
+	right  short
+	bottom short
+}
+
+type consoleScreenBufferInfo struct {
+	size              coord
+	cursorPosition    coord
+	attributes        word
+	window            smallRect
+	maximumWindowSize coord
+}
+
+type consoleCursorInfo struct {
+	size    dword
+	visible int32
+}
+
+var (
+	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
+	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
+	procSetConsoleCursorPosition   = kernel32.NewProc("SetConsoleCursorPosition")
+	procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
+	procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
+	procGetConsoleCursorInfo       = kernel32.NewProc("GetConsoleCursorInfo")
+	procSetConsoleCursorInfo       = kernel32.NewProc("SetConsoleCursorInfo")
+	procSetConsoleTitle            = kernel32.NewProc("SetConsoleTitleW")
+	procCreateConsoleScreenBuffer  = kernel32.NewProc("CreateConsoleScreenBuffer")
+)
+
+// Writer provide colorable Writer to the console
+type Writer struct {
+	out       io.Writer
+	handle    syscall.Handle
+	althandle syscall.Handle
+	oldattr   word
+	oldpos    coord
+	rest      bytes.Buffer
+}
+
+// NewColorable return new instance of Writer which handle escape sequence from File.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	if isatty.IsTerminal(file.Fd()) {
+		var csbi consoleScreenBufferInfo
+		handle := syscall.Handle(file.Fd())
+		procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+		return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
+	}
+	return file
+}
+
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return NewColorable(os.Stdout)
+}
+
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return NewColorable(os.Stderr)
+}
+
+var color256 = map[int]int{
+	0:   0x000000,
+	1:   0x800000,
+	2:   0x008000,
+	3:   0x808000,
+	4:   0x000080,
+	5:   0x800080,
+	6:   0x008080,
+	7:   0xc0c0c0,
+	8:   0x808080,
+	9:   0xff0000,
+	10:  0x00ff00,
+	11:  0xffff00,
+	12:  0x0000ff,
+	13:  0xff00ff,
+	14:  0x00ffff,
+	15:  0xffffff,
+	16:  0x000000,
+	17:  0x00005f,
+	18:  0x000087,
+	19:  0x0000af,
+	20:  0x0000d7,
+	21:  0x0000ff,
+	22:  0x005f00,
+	23:  0x005f5f,
+	24:  0x005f87,
+	25:  0x005faf,
+	26:  0x005fd7,
+	27:  0x005fff,
+	28:  0x008700,
+	29:  0x00875f,
+	30:  0x008787,
+	31:  0x0087af,
+	32:  0x0087d7,
+	33:  0x0087ff,
+	34:  0x00af00,
+	35:  0x00af5f,
+	36:  0x00af87,
+	37:  0x00afaf,
+	38:  0x00afd7,
+	39:  0x00afff,
+	40:  0x00d700,
+	41:  0x00d75f,
+	42:  0x00d787,
+	43:  0x00d7af,
+	44:  0x00d7d7,
+	45:  0x00d7ff,
+	46:  0x00ff00,
+	47:  0x00ff5f,
+	48:  0x00ff87,
+	49:  0x00ffaf,
+	50:  0x00ffd7,
+	51:  0x00ffff,
+	52:  0x5f0000,
+	53:  0x5f005f,
+	54:  0x5f0087,
+	55:  0x5f00af,
+	56:  0x5f00d7,
+	57:  0x5f00ff,
+	58:  0x5f5f00,
+	59:  0x5f5f5f,
+	60:  0x5f5f87,
+	61:  0x5f5faf,
+	62:  0x5f5fd7,
+	63:  0x5f5fff,
+	64:  0x5f8700,
+	65:  0x5f875f,
+	66:  0x5f8787,
+	67:  0x5f87af,
+	68:  0x5f87d7,
+	69:  0x5f87ff,
+	70:  0x5faf00,
+	71:  0x5faf5f,
+	72:  0x5faf87,
+	73:  0x5fafaf,
+	74:  0x5fafd7,
+	75:  0x5fafff,
+	76:  0x5fd700,
+	77:  0x5fd75f,
+	78:  0x5fd787,
+	79:  0x5fd7af,
+	80:  0x5fd7d7,
+	81:  0x5fd7ff,
+	82:  0x5fff00,
+	83:  0x5fff5f,
+	84:  0x5fff87,
+	85:  0x5fffaf,
+	86:  0x5fffd7,
+	87:  0x5fffff,
+	88:  0x870000,
+	89:  0x87005f,
+	90:  0x870087,
+	91:  0x8700af,
+	92:  0x8700d7,
+	93:  0x8700ff,
+	94:  0x875f00,
+	95:  0x875f5f,
+	96:  0x875f87,
+	97:  0x875faf,
+	98:  0x875fd7,
+	99:  0x875fff,
+	100: 0x878700,
+	101: 0x87875f,
+	102: 0x878787,
+	103: 0x8787af,
+	104: 0x8787d7,
+	105: 0x8787ff,
+	106: 0x87af00,
+	107: 0x87af5f,
+	108: 0x87af87,
+	109: 0x87afaf,
+	110: 0x87afd7,
+	111: 0x87afff,
+	112: 0x87d700,
+	113: 0x87d75f,
+	114: 0x87d787,
+	115: 0x87d7af,
+	116: 0x87d7d7,
+	117: 0x87d7ff,
+	118: 0x87ff00,
+	119: 0x87ff5f,
+	120: 0x87ff87,
+	121: 0x87ffaf,
+	122: 0x87ffd7,
+	123: 0x87ffff,
+	124: 0xaf0000,
+	125: 0xaf005f,
+	126: 0xaf0087,
+	127: 0xaf00af,
+	128: 0xaf00d7,
+	129: 0xaf00ff,
+	130: 0xaf5f00,
+	131: 0xaf5f5f,
+	132: 0xaf5f87,
+	133: 0xaf5faf,
+	134: 0xaf5fd7,
+	135: 0xaf5fff,
+	136: 0xaf8700,
+	137: 0xaf875f,
+	138: 0xaf8787,
+	139: 0xaf87af,
+	140: 0xaf87d7,
+	141: 0xaf87ff,
+	142: 0xafaf00,
+	143: 0xafaf5f,
+	144: 0xafaf87,
+	145: 0xafafaf,
+	146: 0xafafd7,
+	147: 0xafafff,
+	148: 0xafd700,
+	149: 0xafd75f,
+	150: 0xafd787,
+	151: 0xafd7af,
+	152: 0xafd7d7,
+	153: 0xafd7ff,
+	154: 0xafff00,
+	155: 0xafff5f,
+	156: 0xafff87,
+	157: 0xafffaf,
+	158: 0xafffd7,
+	159: 0xafffff,
+	160: 0xd70000,
+	161: 0xd7005f,
+	162: 0xd70087,
+	163: 0xd700af,
+	164: 0xd700d7,
+	165: 0xd700ff,
+	166: 0xd75f00,
+	167: 0xd75f5f,
+	168: 0xd75f87,
+	169: 0xd75faf,
+	170: 0xd75fd7,
+	171: 0xd75fff,
+	172: 0xd78700,
+	173: 0xd7875f,
+	174: 0xd78787,
+	175: 0xd787af,
+	176: 0xd787d7,
+	177: 0xd787ff,
+	178: 0xd7af00,
+	179: 0xd7af5f,
+	180: 0xd7af87,
+	181: 0xd7afaf,
+	182: 0xd7afd7,
+	183: 0xd7afff,
+	184: 0xd7d700,
+	185: 0xd7d75f,
+	186: 0xd7d787,
+	187: 0xd7d7af,
+	188: 0xd7d7d7,
+	189: 0xd7d7ff,
+	190: 0xd7ff00,
+	191: 0xd7ff5f,
+	192: 0xd7ff87,
+	193: 0xd7ffaf,
+	194: 0xd7ffd7,
+	195: 0xd7ffff,
+	196: 0xff0000,
+	197: 0xff005f,
+	198: 0xff0087,
+	199: 0xff00af,
+	200: 0xff00d7,
+	201: 0xff00ff,
+	202: 0xff5f00,
+	203: 0xff5f5f,
+	204: 0xff5f87,
+	205: 0xff5faf,
+	206: 0xff5fd7,
+	207: 0xff5fff,
+	208: 0xff8700,
+	209: 0xff875f,
+	210: 0xff8787,
+	211: 0xff87af,
+	212: 0xff87d7,
+	213: 0xff87ff,
+	214: 0xffaf00,
+	215: 0xffaf5f,
+	216: 0xffaf87,
+	217: 0xffafaf,
+	218: 0xffafd7,
+	219: 0xffafff,
+	220: 0xffd700,
+	221: 0xffd75f,
+	222: 0xffd787,
+	223: 0xffd7af,
+	224: 0xffd7d7,
+	225: 0xffd7ff,
+	226: 0xffff00,
+	227: 0xffff5f,
+	228: 0xffff87,
+	229: 0xffffaf,
+	230: 0xffffd7,
+	231: 0xffffff,
+	232: 0x080808,
+	233: 0x121212,
+	234: 0x1c1c1c,
+	235: 0x262626,
+	236: 0x303030,
+	237: 0x3a3a3a,
+	238: 0x444444,
+	239: 0x4e4e4e,
+	240: 0x585858,
+	241: 0x626262,
+	242: 0x6c6c6c,
+	243: 0x767676,
+	244: 0x808080,
+	245: 0x8a8a8a,
+	246: 0x949494,
+	247: 0x9e9e9e,
+	248: 0xa8a8a8,
+	249: 0xb2b2b2,
+	250: 0xbcbcbc,
+	251: 0xc6c6c6,
+	252: 0xd0d0d0,
+	253: 0xdadada,
+	254: 0xe4e4e4,
+	255: 0xeeeeee,
+}
+
+// `\033]0;TITLESTR\007`
+func doTitleSequence(er *bytes.Reader) error {
+	var c byte
+	var err error
+
+	c, err = er.ReadByte()
+	if err != nil {
+		return err
+	}
+	if c != '0' && c != '2' {
+		return nil
+	}
+	c, err = er.ReadByte()
+	if err != nil {
+		return err
+	}
+	if c != ';' {
+		return nil
+	}
+	title := make([]byte, 0, 80)
+	for {
+		c, err = er.ReadByte()
+		if err != nil {
+			return err
+		}
+		if c == 0x07 || c == '\n' {
+			break
+		}
+		title = append(title, c)
+	}
+	if len(title) > 0 {
+		title8, err := syscall.UTF16PtrFromString(string(title))
+		if err == nil {
+			procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8)))
+		}
+	}
+	return nil
+}
+
+// Write write data on console
+func (w *Writer) Write(data []byte) (n int, err error) {
+	var csbi consoleScreenBufferInfo
+	procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
+
+	handle := w.handle
+
+	var er *bytes.Reader
+	if w.rest.Len() > 0 {
+		var rest bytes.Buffer
+		w.rest.WriteTo(&rest)
+		w.rest.Reset()
+		rest.Write(data)
+		er = bytes.NewReader(rest.Bytes())
+	} else {
+		er = bytes.NewReader(data)
+	}
+	var bw [1]byte
+loop:
+	for {
+		c1, err := er.ReadByte()
+		if err != nil {
+			break loop
+		}
+		if c1 != 0x1b {
+			bw[0] = c1
+			w.out.Write(bw[:])
+			continue
+		}
+		c2, err := er.ReadByte()
+		if err != nil {
+			break loop
+		}
+
+		switch c2 {
+		case '>':
+			continue
+		case ']':
+			w.rest.WriteByte(c1)
+			w.rest.WriteByte(c2)
+			er.WriteTo(&w.rest)
+			if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
+				break loop
+			}
+			er = bytes.NewReader(w.rest.Bytes()[2:])
+			err := doTitleSequence(er)
+			if err != nil {
+				break loop
+			}
+			w.rest.Reset()
+			continue
+		// https://github.com/mattn/go-colorable/issues/27
+		case '7':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			w.oldpos = csbi.cursorPosition
+			continue
+		case '8':
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
+			continue
+		case 0x5b:
+			// execute part after switch
+		default:
+			continue
+		}
+
+		w.rest.WriteByte(c1)
+		w.rest.WriteByte(c2)
+		er.WriteTo(&w.rest)
+
+		var buf bytes.Buffer
+		var m byte
+		for i, c := range w.rest.Bytes()[2:] {
+			if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
+				m = c
+				er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
+				w.rest.Reset()
+				break
+			}
+			buf.Write([]byte(string(c)))
+		}
+		if m == 0 {
+			break loop
+		}
+
+		switch m {
+		case 'A':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.y -= short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'B':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.y += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'C':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'D':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x -= short(n)
+			if csbi.cursorPosition.x < 0 {
+				csbi.cursorPosition.x = 0
+			}
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'E':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = 0
+			csbi.cursorPosition.y += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'F':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = 0
+			csbi.cursorPosition.y -= short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'G':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = short(n - 1)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'H', 'f':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			if buf.Len() > 0 {
+				token := strings.Split(buf.String(), ";")
+				switch len(token) {
+				case 1:
+					n1, err := strconv.Atoi(token[0])
+					if err != nil {
+						continue
+					}
+					csbi.cursorPosition.y = short(n1 - 1)
+				case 2:
+					n1, err := strconv.Atoi(token[0])
+					if err != nil {
+						continue
+					}
+					n2, err := strconv.Atoi(token[1])
+					if err != nil {
+						continue
+					}
+					csbi.cursorPosition.x = short(n2 - 1)
+					csbi.cursorPosition.y = short(n1 - 1)
+				}
+			} else {
+				csbi.cursorPosition.y = 0
+			}
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'J':
+			n := 0
+			if buf.Len() > 0 {
+				n, err = strconv.Atoi(buf.String())
+				if err != nil {
+					continue
+				}
+			}
+			var count, written dword
+			var cursor coord
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			switch n {
+			case 0:
+				cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
+			case 1:
+				cursor = coord{x: csbi.window.left, y: csbi.window.top}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
+			case 2:
+				cursor = coord{x: csbi.window.left, y: csbi.window.top}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
+			}
+			procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+			procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+		case 'K':
+			n := 0
+			if buf.Len() > 0 {
+				n, err = strconv.Atoi(buf.String())
+				if err != nil {
+					continue
+				}
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			var cursor coord
+			var count, written dword
+			switch n {
+			case 0:
+				cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x - csbi.cursorPosition.x)
+			case 1:
+				cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x - csbi.cursorPosition.x)
+			case 2:
+				cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x)
+			}
+			procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+			procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+		case 'm':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			attr := csbi.attributes
+			cs := buf.String()
+			if cs == "" {
+				procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
+				continue
+			}
+			token := strings.Split(cs, ";")
+			for i := 0; i < len(token); i++ {
+				ns := token[i]
+				if n, err = strconv.Atoi(ns); err == nil {
+					switch {
+					case n == 0 || n == 100:
+						attr = w.oldattr
+					case 1 <= n && n <= 5:
+						attr |= foregroundIntensity
+					case n == 7:
+						attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
+					case n == 22 || n == 25:
+						attr |= foregroundIntensity
+					case n == 27:
+						attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
+					case 30 <= n && n <= 37:
+						attr &= backgroundMask
+						if (n-30)&1 != 0 {
+							attr |= foregroundRed
+						}
+						if (n-30)&2 != 0 {
+							attr |= foregroundGreen
+						}
+						if (n-30)&4 != 0 {
+							attr |= foregroundBlue
+						}
+					case n == 38: // set foreground color.
+						if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") {
+							if n256, err := strconv.Atoi(token[i+2]); err == nil {
+								if n256foreAttr == nil {
+									n256setup()
+								}
+								attr &= backgroundMask
+								attr |= n256foreAttr[n256]
+								i += 2
+							}
+						} else if len(token) == 5 && token[i+1] == "2" {
+							var r, g, b int
+							r, _ = strconv.Atoi(token[i+2])
+							g, _ = strconv.Atoi(token[i+3])
+							b, _ = strconv.Atoi(token[i+4])
+							i += 4
+							if r > 127 {
+								attr |= foregroundRed
+							}
+							if g > 127 {
+								attr |= foregroundGreen
+							}
+							if b > 127 {
+								attr |= foregroundBlue
+							}
+						} else {
+							attr = attr & (w.oldattr & backgroundMask)
+						}
+					case n == 39: // reset foreground color.
+						attr &= backgroundMask
+						attr |= w.oldattr & foregroundMask
+					case 40 <= n && n <= 47:
+						attr &= foregroundMask
+						if (n-40)&1 != 0 {
+							attr |= backgroundRed
+						}
+						if (n-40)&2 != 0 {
+							attr |= backgroundGreen
+						}
+						if (n-40)&4 != 0 {
+							attr |= backgroundBlue
+						}
+					case n == 48: // set background color.
+						if i < len(token)-2 && token[i+1] == "5" {
+							if n256, err := strconv.Atoi(token[i+2]); err == nil {
+								if n256backAttr == nil {
+									n256setup()
+								}
+								attr &= foregroundMask
+								attr |= n256backAttr[n256]
+								i += 2
+							}
+						} else if len(token) == 5 && token[i+1] == "2" {
+							var r, g, b int
+							r, _ = strconv.Atoi(token[i+2])
+							g, _ = strconv.Atoi(token[i+3])
+							b, _ = strconv.Atoi(token[i+4])
+							i += 4
+							if r > 127 {
+								attr |= backgroundRed
+							}
+							if g > 127 {
+								attr |= backgroundGreen
+							}
+							if b > 127 {
+								attr |= backgroundBlue
+							}
+						} else {
+							attr = attr & (w.oldattr & foregroundMask)
+						}
+					case n == 49: // reset foreground color.
+						attr &= foregroundMask
+						attr |= w.oldattr & backgroundMask
+					case 90 <= n && n <= 97:
+						attr = (attr & backgroundMask)
+						attr |= foregroundIntensity
+						if (n-90)&1 != 0 {
+							attr |= foregroundRed
+						}
+						if (n-90)&2 != 0 {
+							attr |= foregroundGreen
+						}
+						if (n-90)&4 != 0 {
+							attr |= foregroundBlue
+						}
+					case 100 <= n && n <= 107:
+						attr = (attr & foregroundMask)
+						attr |= backgroundIntensity
+						if (n-100)&1 != 0 {
+							attr |= backgroundRed
+						}
+						if (n-100)&2 != 0 {
+							attr |= backgroundGreen
+						}
+						if (n-100)&4 != 0 {
+							attr |= backgroundBlue
+						}
+					}
+					procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
+				}
+			}
+		case 'h':
+			var ci consoleCursorInfo
+			cs := buf.String()
+			if cs == "5>" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 0
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?25" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 1
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?1049" {
+				if w.althandle == 0 {
+					h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
+					w.althandle = syscall.Handle(h)
+					if w.althandle != 0 {
+						handle = w.althandle
+					}
+				}
+			}
+		case 'l':
+			var ci consoleCursorInfo
+			cs := buf.String()
+			if cs == "5>" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 1
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?25" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 0
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?1049" {
+				if w.althandle != 0 {
+					syscall.CloseHandle(w.althandle)
+					w.althandle = 0
+					handle = w.handle
+				}
+			}
+		case 's':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			w.oldpos = csbi.cursorPosition
+		case 'u':
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
+		}
+	}
+
+	return len(data), nil
+}
+
+type consoleColor struct {
+	rgb       int
+	red       bool
+	green     bool
+	blue      bool
+	intensity bool
+}
+
+func (c consoleColor) foregroundAttr() (attr word) {
+	if c.red {
+		attr |= foregroundRed
+	}
+	if c.green {
+		attr |= foregroundGreen
+	}
+	if c.blue {
+		attr |= foregroundBlue
+	}
+	if c.intensity {
+		attr |= foregroundIntensity
+	}
+	return
+}
+
+func (c consoleColor) backgroundAttr() (attr word) {
... 6605 lines suppressed ...

-- 
To stop receiving notification emails like this one, please contact
rohit@apache.org.