cli: send requested help text to stdout
This behaviour matches the GNU CLI standard: http://www.gnu.org/prep/standards/html_node/_002d_002dhelp.html
This commit is contained in:
parent
ce81e026de
commit
b7ff6424f5
2
go.mod
2
go.mod
|
@ -57,7 +57,7 @@ require (
|
||||||
github.com/imdario/mergo v0.3.6
|
github.com/imdario/mergo v0.3.6
|
||||||
github.com/kr/text v0.1.0
|
github.com/kr/text v0.1.0
|
||||||
github.com/miekg/dns v1.1.26
|
github.com/miekg/dns v1.1.26
|
||||||
github.com/mitchellh/cli v1.0.0
|
github.com/mitchellh/cli v1.1.0
|
||||||
github.com/mitchellh/copystructure v1.0.0
|
github.com/mitchellh/copystructure v1.0.0
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0
|
github.com/mitchellh/go-testing-interface v1.0.0
|
||||||
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452
|
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -259,6 +259,8 @@ github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
|
||||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||||
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
|
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
|
github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg=
|
||||||
|
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||||
|
|
2
main.go
2
main.go
|
@ -48,6 +48,8 @@ func realMain() int {
|
||||||
Autocomplete: true,
|
Autocomplete: true,
|
||||||
Name: "consul",
|
Name: "consul",
|
||||||
HelpFunc: cli.FilteredHelpFunc(names, cli.BasicHelpFunc("consul")),
|
HelpFunc: cli.FilteredHelpFunc(names, cli.BasicHelpFunc("consul")),
|
||||||
|
HelpWriter: os.Stdout,
|
||||||
|
ErrorWriter: os.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
exitCode, err := cli.Run()
|
exitCode, err := cli.Run()
|
||||||
|
|
|
@ -2,10 +2,14 @@ sudo: false
|
||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
|
env:
|
||||||
|
- GO111MODULE=on
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.8"
|
- "1.11"
|
||||||
- "1.9"
|
- "1.12"
|
||||||
- "1.10"
|
- "1.13"
|
||||||
|
- "1.14"
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
|
|
@ -12,9 +12,6 @@ testrace:
|
||||||
|
|
||||||
# updatedeps installs all the dependencies to run and build
|
# updatedeps installs all the dependencies to run and build
|
||||||
updatedeps:
|
updatedeps:
|
||||||
go list ./... \
|
go mod download
|
||||||
| 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
|
.PHONY: test testrace updatedeps
|
||||||
|
|
|
@ -109,18 +109,23 @@ type CLI struct {
|
||||||
AutocompleteGlobalFlags complete.Flags
|
AutocompleteGlobalFlags complete.Flags
|
||||||
autocompleteInstaller autocompleteInstaller // For tests
|
autocompleteInstaller autocompleteInstaller // For tests
|
||||||
|
|
||||||
// HelpFunc and HelpWriter are used to output help information, if
|
|
||||||
// requested.
|
|
||||||
//
|
|
||||||
// HelpFunc is the function called to generate the generic help
|
// HelpFunc is the function called to generate the generic help
|
||||||
// text that is shown if help must be shown for the CLI that doesn't
|
// text that is shown if help must be shown for the CLI that doesn't
|
||||||
// pertain to a specific command.
|
// pertain to a specific command.
|
||||||
//
|
HelpFunc HelpFunc
|
||||||
// HelpWriter is the Writer where the help text is outputted to. If
|
|
||||||
// not specified, it will default to Stderr.
|
// HelpWriter is used to print help text and version when requested.
|
||||||
HelpFunc HelpFunc
|
// Defaults to os.Stderr for backwards compatibility.
|
||||||
|
// It is recommended that you set HelpWriter to os.Stdout, and
|
||||||
|
// ErrorWriter to os.Stderr.
|
||||||
HelpWriter io.Writer
|
HelpWriter io.Writer
|
||||||
|
|
||||||
|
// ErrorWriter used to output errors when a command can not be run.
|
||||||
|
// Defaults to the value of HelpWriter for backwards compatibility.
|
||||||
|
// It is recommended that you set HelpWriter to os.Stdout, and
|
||||||
|
// ErrorWriter to os.Stderr.
|
||||||
|
ErrorWriter io.Writer
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Internal fields set automatically
|
// Internal fields set automatically
|
||||||
|
|
||||||
|
@ -228,7 +233,7 @@ func (c *CLI) Run() (int, error) {
|
||||||
// implementation. If the command is invalid or blank, it is an error.
|
// implementation. If the command is invalid or blank, it is an error.
|
||||||
raw, ok := c.commandTree.Get(c.Subcommand())
|
raw, ok := c.commandTree.Get(c.Subcommand())
|
||||||
if !ok {
|
if !ok {
|
||||||
c.HelpWriter.Write([]byte(c.HelpFunc(c.helpCommands(c.subcommandParent())) + "\n"))
|
c.ErrorWriter.Write([]byte(c.HelpFunc(c.helpCommands(c.subcommandParent())) + "\n"))
|
||||||
return 127, nil
|
return 127, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,23 +244,23 @@ func (c *CLI) Run() (int, error) {
|
||||||
|
|
||||||
// If we've been instructed to just print the help, then print it
|
// If we've been instructed to just print the help, then print it
|
||||||
if c.IsHelp() {
|
if c.IsHelp() {
|
||||||
c.commandHelp(command)
|
c.commandHelp(c.HelpWriter, command)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an invalid flag, then error
|
// If there is an invalid flag, then error
|
||||||
if len(c.topFlags) > 0 {
|
if len(c.topFlags) > 0 {
|
||||||
c.HelpWriter.Write([]byte(
|
c.ErrorWriter.Write([]byte(
|
||||||
"Invalid flags before the subcommand. If these flags are for\n" +
|
"Invalid flags before the subcommand. If these flags are for\n" +
|
||||||
"the subcommand, please put them after the subcommand.\n\n"))
|
"the subcommand, please put them after the subcommand.\n\n"))
|
||||||
c.commandHelp(command)
|
c.commandHelp(c.ErrorWriter, command)
|
||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
code := command.Run(c.SubcommandArgs())
|
code := command.Run(c.SubcommandArgs())
|
||||||
if code == RunResultHelp {
|
if code == RunResultHelp {
|
||||||
// Requesting help
|
// Requesting help
|
||||||
c.commandHelp(command)
|
c.commandHelp(c.ErrorWriter, command)
|
||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +315,9 @@ func (c *CLI) init() {
|
||||||
if c.HelpWriter == nil {
|
if c.HelpWriter == nil {
|
||||||
c.HelpWriter = os.Stderr
|
c.HelpWriter = os.Stderr
|
||||||
}
|
}
|
||||||
|
if c.ErrorWriter == nil {
|
||||||
|
c.ErrorWriter = c.HelpWriter
|
||||||
|
}
|
||||||
|
|
||||||
// Build our hidden commands
|
// Build our hidden commands
|
||||||
if len(c.HiddenCommands) > 0 {
|
if len(c.HiddenCommands) > 0 {
|
||||||
|
@ -404,8 +412,8 @@ func (c *CLI) initAutocomplete() {
|
||||||
cmd.Flags = map[string]complete.Predictor{
|
cmd.Flags = map[string]complete.Predictor{
|
||||||
"-" + c.AutocompleteInstall: complete.PredictNothing,
|
"-" + c.AutocompleteInstall: complete.PredictNothing,
|
||||||
"-" + c.AutocompleteUninstall: complete.PredictNothing,
|
"-" + c.AutocompleteUninstall: complete.PredictNothing,
|
||||||
"-help": complete.PredictNothing,
|
"-help": complete.PredictNothing,
|
||||||
"-version": complete.PredictNothing,
|
"-version": complete.PredictNothing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.GlobalFlags = c.AutocompleteGlobalFlags
|
cmd.GlobalFlags = c.AutocompleteGlobalFlags
|
||||||
|
@ -483,7 +491,7 @@ func (c *CLI) initAutocompleteSub(prefix string) complete.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CLI) commandHelp(command Command) {
|
func (c *CLI) commandHelp(out io.Writer, command Command) {
|
||||||
// Get the template to use
|
// Get the template to use
|
||||||
tpl := strings.TrimSpace(defaultHelpTemplate)
|
tpl := strings.TrimSpace(defaultHelpTemplate)
|
||||||
if t, ok := command.(CommandHelpTemplate); ok {
|
if t, ok := command.(CommandHelpTemplate); ok {
|
||||||
|
@ -533,12 +541,12 @@ func (c *CLI) commandHelp(command Command) {
|
||||||
// Get the command
|
// Get the command
|
||||||
raw, ok := subcommands[k]
|
raw, ok := subcommands[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.HelpWriter.Write([]byte(fmt.Sprintf(
|
c.ErrorWriter.Write([]byte(fmt.Sprintf(
|
||||||
"Error getting subcommand %q", k)))
|
"Error getting subcommand %q", k)))
|
||||||
}
|
}
|
||||||
sub, err := raw()
|
sub, err := raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.HelpWriter.Write([]byte(fmt.Sprintf(
|
c.ErrorWriter.Write([]byte(fmt.Sprintf(
|
||||||
"Error instantiating %q: %s", k, err)))
|
"Error instantiating %q: %s", k, err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,13 +567,13 @@ func (c *CLI) commandHelp(command Command) {
|
||||||
data["Subcommands"] = subcommandsTpl
|
data["Subcommands"] = subcommandsTpl
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
err = t.Execute(c.HelpWriter, data)
|
err = t.Execute(out, data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// An error, just output...
|
// An error, just output...
|
||||||
c.HelpWriter.Write([]byte(fmt.Sprintf(
|
c.ErrorWriter.Write([]byte(fmt.Sprintf(
|
||||||
"Internal error rendering help: %s", err)))
|
"Internal error rendering help: %s", err)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module github.com/mitchellh/cli
|
module github.com/mitchellh/cli
|
||||||
|
|
||||||
|
go 1.11
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310
|
||||||
github.com/bgentry/speakeasy v0.1.0
|
github.com/bgentry/speakeasy v0.1.0
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,9 +37,12 @@ func (u *MockUi) Ask(query string) (string, error) {
|
||||||
|
|
||||||
var result string
|
var result string
|
||||||
fmt.Fprint(u.OutputWriter, query)
|
fmt.Fprint(u.OutputWriter, query)
|
||||||
if _, err := fmt.Fscanln(u.InputReader, &result); err != nil {
|
r := bufio.NewReader(u.InputReader)
|
||||||
|
line, err := r.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
result = strings.TrimRight(line, "\r\n")
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,7 @@ github.com/mattn/go-isatty
|
||||||
github.com/matttproud/golang_protobuf_extensions/pbutil
|
github.com/matttproud/golang_protobuf_extensions/pbutil
|
||||||
# github.com/miekg/dns v1.1.26
|
# github.com/miekg/dns v1.1.26
|
||||||
github.com/miekg/dns
|
github.com/miekg/dns
|
||||||
# github.com/mitchellh/cli v1.0.0
|
# github.com/mitchellh/cli v1.1.0
|
||||||
github.com/mitchellh/cli
|
github.com/mitchellh/cli
|
||||||
# github.com/mitchellh/copystructure v1.0.0
|
# github.com/mitchellh/copystructure v1.0.0
|
||||||
github.com/mitchellh/copystructure
|
github.com/mitchellh/copystructure
|
||||||
|
|
Loading…
Reference in New Issue