From 6c3b7f193222b264583436d02e06adf7fe8b561f Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Wed, 15 Oct 2014 17:14:12 -0400 Subject: [PATCH] --help option and help command should print to stdout not stderr --help and help are successful commands so output should not go to error. QE teams have requested this change, also users doing docker help | less or docker run --help | less would expect this to work. Usage statement should only be printed when the user asks for it. Errors should print error message and then suggest the docker COMMAND --help command to see usage information. The current behaviour causes the user to have to search for the error message and sometimes scrolls right off the screen. For example a error on a "docker run" command is very difficult to diagnose. Finally erros should always exit with a non 0 exit code, if the user makes a CLI error. Docker-DCO-1.1-Signed-off-by: Dan Walsh (github: rhatdan) --- mflag/flag.go | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/mflag/flag.go b/mflag/flag.go index a30c41b..ffc509a 100644 --- a/mflag/flag.go +++ b/mflag/flag.go @@ -410,6 +410,47 @@ func IsSet(name string) bool { return CommandLine.IsSet(name) } +// Indicator used to pass to BadArgs function +const ( + Exact = 1 + Max = 2 + Min = 3 +) + +// Bad Args takes two arguments. +// The first one indicates whether the number of arguments should, be +// A Minimal number of arguments, a maximum number of arguments or +// The exact number of arguments required +// If the actuall number of arguments is not valid and error message +// prints and true is returned, otherwise false is returned +func (f *FlagSet) BadArgs(arg_type, nargs int) bool { + if arg_type == Max && f.NArg() > nargs { + if nargs == 1 { + fmt.Fprintf(f.out(), "docker: '%s' requires a maximum of 1 argument. See 'docker %s --help'.\n", f.name, f.name) + } else { + fmt.Fprintf(f.out(), "docker: '%s' requires a maximum of %d arguments. See 'docker %s --help'.\n", f.name, nargs, f.name) + } + return true + } + if arg_type == Exact && f.NArg() != nargs { + if nargs == 1 { + fmt.Fprintf(f.out(), "docker: '%s' requires 1 argument. See 'docker %s --help'.\n", f.name, f.name) + } else { + fmt.Fprintf(f.out(), "docker: '%s' requires %d arguments. See 'docker %s --help'.\n", f.name, nargs, f.name) + } + return true + } + if arg_type == Min && f.NArg() < nargs { + if nargs == 1 { + fmt.Fprintf(f.out(), "docker: '%s' requires a minimum of 1 argument. See 'docker %s --help'.\n", f.name, f.name) + } else { + fmt.Fprintf(f.out(), "docker: '%s' requires a minimum of %d arguments. See 'docker %s --help'.\n", f.name, nargs, f.name) + } + return true + } + return false +} + // Set sets the value of the named flag. func (f *FlagSet) Set(name, value string) error { flag, ok := f.formal[name] @@ -483,7 +524,7 @@ func defaultUsage(f *FlagSet) { // Usage prints to standard error a usage message documenting all defined command-line flags. // The function is a variable that may be changed to point to a custom function. var Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0]) PrintDefaults() } @@ -789,7 +830,7 @@ func Var(value Value, names []string, usage string) { func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) fmt.Fprintln(f.out(), err) - f.usage() + fmt.Fprintf(f.out(), "See 'docker %s --help'.\n", f.name) return err }