Commit 9e48fe7f authored by Alexandre Viau's avatar Alexandre Viau

New upstream version 0.0~git20171129.33edc47

parent 5df68a5d
......@@ -3,12 +3,11 @@ sudo: false
language: go
go:
- 1.2
- 1.3
- 1.4
- 1.5
- tip
matrix:
allow_failures:
- go: tip
- 1.8
- 1.9
branches:
only:
- master
script: make updatedeps test testrace
TEST?=./...
default: test
# test runs the test suite and vets the code
test:
go list $(TEST) | xargs -n1 go test -timeout=60s -parallel=10 $(TESTARGS)
# testrace runs the race checker
testrace:
go list $(TEST) | xargs -n1 go test -race $(TESTARGS)
# updatedeps installs all the dependencies to run and build
updatedeps:
go list ./... \
| xargs go list -f '{{ join .Deps "\n" }}{{ printf "\n" }}{{ join .TestImports "\n" }}' \
| grep -v github.com/mitchellh/cli \
| xargs go get -f -u -v
.PHONY: test testrace updatedeps
......@@ -3,8 +3,11 @@
cli is a library for implementing powerful command-line interfaces in Go.
cli is the library that powers the CLI for
[Packer](https://github.com/mitchellh/packer),
[Serf](https://github.com/hashicorp/serf), and
[Consul](https://github.com/hashicorp/consul).
[Serf](https://github.com/hashicorp/serf),
[Consul](https://github.com/hashicorp/consul),
[Vault](https://github.com/hashicorp/vault),
[Terraform](https://github.com/hashicorp/terraform), and
[Nomad](https://github.com/hashicorp/nomad).
## Features
......@@ -15,6 +18,9 @@ cli is the library that powers the CLI for
* Optional support for default subcommands so `cli` does something
other than error.
* Support for shell autocompletion of subcommands, flags, and arguments
with callbacks in Go. You don't need to write any shell code.
* Automatic help generation for listing subcommands
* Automatic help flag recognition of `-h`, `--help`, etc.
......
package cli
import (
"github.com/posener/complete/cmd/install"
)
// autocompleteInstaller is an interface to be implemented to perform the
// autocomplete installation and uninstallation with a CLI.
//
// This interface is not exported because it only exists for unit tests
// to be able to test that the installation is called properly.
type autocompleteInstaller interface {
Install(string) error
Uninstall(string) error
}
// realAutocompleteInstaller uses the real install package to do the
// install/uninstall.
type realAutocompleteInstaller struct{}
func (i *realAutocompleteInstaller) Install(cmd string) error {
return install.Install(cmd)
}
func (i *realAutocompleteInstaller) Uninstall(cmd string) error {
return install.Uninstall(cmd)
}
// mockAutocompleteInstaller is used for tests to record the install/uninstall.
type mockAutocompleteInstaller struct {
InstallCalled bool
UninstallCalled bool
}
func (i *mockAutocompleteInstaller) Install(cmd string) error {
i.InstallCalled = true
return nil
}
func (i *mockAutocompleteInstaller) Uninstall(cmd string) error {
i.UninstallCalled = true
return nil
}
This diff is collapsed.
This diff is collapsed.
package cli
import (
"github.com/posener/complete"
)
const (
// RunResultHelp is a value that can be returned from Run to signal
// to the CLI to render the help output.
......@@ -26,6 +30,22 @@ type Command interface {
Synopsis() string
}
// CommandAutocomplete is an extension of Command that enables fine-grained
// autocompletion. Subcommand autocompletion will work even if this interface
// is not implemented. By implementing this interface, more advanced
// autocompletion is enabled.
type CommandAutocomplete interface {
// AutocompleteArgs returns the argument predictor for this command.
// If argument completion is not supported, this should return
// complete.PredictNothing.
AutocompleteArgs() complete.Predictor
// AutocompleteFlags returns a mapping of supported flags and autocomplete
// options for this command. The map key for the Flags map should be the
// complete flag such as "-foo" or "--foo".
AutocompleteFlags() complete.Flags
}
// CommandHelpTemplate is an extension of Command that also has a function
// for returning a template for the help rather than the help itself. In
// this scenario, both Help and HelpTemplate should be implemented.
......
package cli
import (
"github.com/posener/complete"
)
// MockCommand is an implementation of Command that can be used for tests.
// It is publicly exported from this package in case you want to use it
// externally.
......@@ -29,6 +33,23 @@ func (c *MockCommand) Synopsis() string {
return c.SynopsisText
}
// MockCommandAutocomplete is an implementation of CommandAutocomplete.
type MockCommandAutocomplete struct {
MockCommand
// Settable
AutocompleteArgsValue complete.Predictor
AutocompleteFlagsValue complete.Flags
}
func (c *MockCommandAutocomplete) AutocompleteArgs() complete.Predictor {
return c.AutocompleteArgsValue
}
func (c *MockCommandAutocomplete) AutocompleteFlags() complete.Flags {
return c.AutocompleteFlagsValue
}
// MockCommandHelpTemplate is an implementation of CommandHelpTemplate.
type MockCommandHelpTemplate struct {
MockCommand
......
......@@ -18,7 +18,7 @@ func BasicHelpFunc(app string) HelpFunc {
return func(commands map[string]CommandFactory) string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf(
"usage: %s [--version] [--help] <command> [<args>]\n\n",
"Usage: %s [--version] [--help] <command> [<args>]\n\n",
app))
buf.WriteString("Available commands are:\n")
......@@ -26,7 +26,7 @@ func BasicHelpFunc(app string) HelpFunc {
// key length so they can be aligned properly.
keys := make([]string, 0, len(commands))
maxKeyLen := 0
for key, _ := range commands {
for key := range commands {
if len(key) > maxKeyLen {
maxKeyLen = len(key)
}
......
......@@ -43,7 +43,7 @@ func TestColoredUi_Info(t *testing.T) {
ui.Info("foo")
if mock.OutputWriter.String() != "\033[0;33mfoo\033[0m\n" {
t.Fatalf("bad: %#v %#v", mock.OutputWriter.String())
t.Fatalf("bad: %#v", mock.OutputWriter.String())
}
}
......@@ -56,7 +56,7 @@ func TestColoredUi_Output(t *testing.T) {
ui.Output("foo")
if mock.OutputWriter.String() != "\033[0;33mfoo\033[0m\n" {
t.Fatalf("bad: %#v %#v", mock.OutputWriter.String())
t.Fatalf("bad: %#v", mock.OutputWriter.String())
}
}
......@@ -69,6 +69,6 @@ func TestColoredUi_Warn(t *testing.T) {
ui.Warn("foo")
if mock.ErrorWriter.String() != "\033[0;33mfoo\033[0m\n" {
t.Fatalf("bad: %#v %#v", mock.ErrorWriter.String())
t.Fatalf("bad: %#v", mock.ErrorWriter.String())
}
}
......@@ -7,12 +7,25 @@ import (
"sync"
)
// MockUi is a mock UI that is used for tests and is exported publicly for
// use in external tests if needed as well.
// NewMockUi returns a fully initialized MockUi instance
// which is safe for concurrent use.
func NewMockUi() *MockUi {
m := new(MockUi)
m.once.Do(m.init)
return m
}
// MockUi is a mock UI that is used for tests and is exported publicly
// for use in external tests if needed as well. Do not instantite this
// directly since the buffers will be initialized on the first write. If
// there is no write then you will get a nil panic. Please use the
// NewMockUi() constructor function instead. You can fix your code with
//
// sed -i -e 's/new(cli.MockUi)/cli.NewMockUi()/g' *_test.go
type MockUi struct {
InputReader io.Reader
ErrorWriter *bytes.Buffer
OutputWriter *bytes.Buffer
ErrorWriter *syncBuffer
OutputWriter *syncBuffer
once sync.Once
}
......@@ -59,6 +72,40 @@ func (u *MockUi) Warn(message string) {
}
func (u *MockUi) init() {
u.ErrorWriter = new(bytes.Buffer)
u.OutputWriter = new(bytes.Buffer)
u.ErrorWriter = new(syncBuffer)
u.OutputWriter = new(syncBuffer)
}
type syncBuffer struct {
sync.RWMutex
b bytes.Buffer
}
func (b *syncBuffer) Write(data []byte) (int, error) {
b.Lock()
defer b.Unlock()
return b.b.Write(data)
}
func (b *syncBuffer) Read(data []byte) (int, error) {
b.RLock()
defer b.RUnlock()
return b.b.Read(data)
}
func (b *syncBuffer) Reset() {
b.Lock()
b.b.Reset()
b.Unlock()
}
func (b *syncBuffer) String() string {
return string(b.Bytes())
}
func (b *syncBuffer) Bytes() []byte {
b.RLock()
data := b.b.Bytes()
b.RUnlock()
return data
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment