cmdline: do not expand environment variables in default cmdline flags
values when printing help only for the godoc style
MultiPart: 1/3
Change-Id: I5ef5bbcddb586eac3ed613d49e96ddf7b11553e8
diff --git a/cmdline/cmdline.go b/cmdline/cmdline.go
index d10c76a..29da34a 100644
--- a/cmdline/cmdline.go
+++ b/cmdline/cmdline.go
@@ -103,15 +103,15 @@
type style int
const (
- styleText style = iota // Default style, good for cmdline output.
- styleGoDoc // Style good for godoc processing.
+ styleDefault style = iota // Default style, good for cmdline output.
+ styleGoDoc // Style good for godoc processing.
)
// String returns the human-readable representation of the style.
func (s *style) String() string {
switch *s {
- case styleText:
- return "text"
+ case styleDefault:
+ return "default"
case styleGoDoc:
return "godoc"
default:
@@ -122,8 +122,8 @@
// Set implements the flag.Value interface method.
func (s *style) Set(value string) error {
switch value {
- case "text":
- *s = styleText
+ case "default":
+ *s = styleDefault
case "godoc":
*s = styleGoDoc
default:
@@ -132,6 +132,14 @@
return nil
}
+// styleFromEnv returns the style value specified by the CMDLINE_STYLE
+// environment variable, falling back on the default style.
+func styleFromEnv() style {
+ style := styleDefault
+ style.Set(os.Getenv("CMDLINE_STYLE"))
+ return style
+}
+
// Stdout is where output goes. Typically os.Stdout.
func (cmd *Command) Stdout() io.Writer {
return cmd.stdout
@@ -168,14 +176,14 @@
func (cmd *Command) writeUsage(w io.Writer) {
lineWriter := textutil.NewUTF8LineWriter(w, outputWidth())
- cmd.usage(lineWriter, true)
+ cmd.usage(lineWriter, styleFromEnv(), true)
lineWriter.Flush()
}
// usage prints the usage of cmd to the writer. The firstCall boolean is set to
// false when printing usage for multiple commands, and is used to avoid
// printing redundant information (e.g. help command, global flags).
-func (cmd *Command) usage(w *textutil.LineWriter, firstCall bool) {
+func (cmd *Command) usage(w *textutil.LineWriter, style style, firstCall bool) {
fmt.Fprintln(w, cmd.Long)
fmt.Fprintln(w)
// Usage line.
@@ -255,13 +263,13 @@
if hasFlags {
fmt.Fprintln(w)
fmt.Fprintln(w, "The", path, "flags are:")
- printFlags(w, &cmd.Flags)
+ printFlags(w, &cmd.Flags, style)
}
// Global flags.
if numFlags(flag.CommandLine) > 0 && firstCall {
fmt.Fprintln(w)
fmt.Fprintln(w, "The global flags are:")
- printFlags(w, flag.CommandLine)
+ printFlags(w, flag.CommandLine, style)
}
}
@@ -281,9 +289,24 @@
return
}
-func printFlags(w *textutil.LineWriter, set *flag.FlagSet) {
+func printFlags(w *textutil.LineWriter, set *flag.FlagSet, style style) {
set.VisitAll(func(f *flag.Flag) {
- fmt.Fprintf(w, " -%s=%s", f.Name, f.DefValue)
+ var value interface{}
+ // When using styleDefault, we want the current value of the flag.
+ // But when using styleGoDoc, we want the default value. This
+ // logic ensures the godoc style prints out default values of
+ // VariableFlags without expanding variables.
+ switch style {
+ case styleDefault:
+ if getter, ok := f.Value.(flag.Getter); ok {
+ value = getter.Get()
+ } else {
+ value = f.Value.String()
+ }
+ case styleGoDoc:
+ value = f.DefValue
+ }
+ fmt.Fprintf(w, " -%s=%v", f.Name, value)
w.SetIndents(spaces(3))
fmt.Fprintln(w, f.Usage)
w.SetIndents()
@@ -297,7 +320,7 @@
// newDefaultHelp creates a new default help command. We need to create new
// instances since the parent for each help command is different.
func newDefaultHelp() *Command {
- helpStyle := styleText
+ helpStyle := styleFromEnv()
help := &Command{
Name: helpName,
Short: "Display help for commands or topics",
@@ -326,7 +349,7 @@
},
isDefaultHelp: true,
}
- help.Flags.Var(&helpStyle, "style", `The formatting style for help output, either "text" or "godoc".`)
+ help.Flags.Var(&helpStyle, "style", `The formatting style for help output, either "default" or "godoc".`)
return help
}
@@ -335,7 +358,7 @@
// runHelp runs the "help" command.
func runHelp(w *textutil.LineWriter, cmd *Command, args []string, style style) error {
if len(args) == 0 {
- cmd.usage(w, true)
+ cmd.usage(w, style, true)
return nil
}
if args[0] == "..." {
@@ -368,7 +391,7 @@
fmt.Fprintln(w, header)
fmt.Fprintln(w)
}
- cmd.usage(w, firstCall)
+ cmd.usage(w, style, firstCall)
for _, child := range cmd.Children {
// Don't repeatedly print default help command.
if !child.isDefaultHelp || firstCall {
@@ -388,7 +411,7 @@
func lineBreak(w *textutil.LineWriter, style style) {
w.Flush()
switch style {
- case styleText:
+ case styleDefault:
width := w.Width()
if width < 0 {
// If the user has chosen an "unlimited" word-wrapping width, we still
diff --git a/cmdline/cmdline_test.go b/cmdline/cmdline_test.go
index 6cf6b0e..8d36f62 100644
--- a/cmdline/cmdline_test.go
+++ b/cmdline/cmdline_test.go
@@ -270,8 +270,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The onecmd help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
The global flags are:
-global1=
@@ -327,8 +327,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The onecmd help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -534,8 +534,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The multi help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -918,8 +918,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The toplevelprog help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
================================================================================
Toplevelprog Topic1 - help topic
@@ -1037,8 +1037,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The toplevelprog echoprog help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
================================================================================
Toplevelprog Echoprog Topic3 - help topic
@@ -1465,8 +1465,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The prog1 help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -1556,8 +1556,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The prog1 prog2 help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -1617,8 +1617,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The prog1 prog2 prog3 help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -1678,8 +1678,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The prog1 prog2 prog3 help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -1799,8 +1799,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The prog1 help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
}
@@ -1927,8 +1927,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The cmdargs help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
@@ -2119,8 +2119,8 @@
[command/topic ...] optionally identifies a specific sub-command or help topic.
The cmdrun help flags are:
- -style=text
- The formatting style for help output, either "text" or "godoc".
+ -style=default
+ The formatting style for help output, either "default" or "godoc".
`,
},
{
diff --git a/cmdline/flag_test.go b/cmdline/flag_test.go
index c0d1281..b0318db 100644
--- a/cmdline/flag_test.go
+++ b/cmdline/flag_test.go
@@ -58,13 +58,26 @@
t.Fatalf("%v failed:\n%v", strings.Join(cmd.Args, " "), string(output))
}
}
- // Check that the substitution does not occur in the documentation.
+ // Check that the substitution occurs in the default documentation.
{
cmd := exec.Command("go", "run", filepath.Join("testdata", "flag.go"), "-help")
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("%v failed:\n%v", strings.Join(cmd.Args, " "), string(output))
}
+ if got, want := string(output), "-test=HELLO"; !strings.Contains(got, want) {
+ t.Fatalf("%q not found in:\n%v", want, got)
+ }
+ }
+ // Check that the substitution does not occur in the GoDoc
+ // documentation.
+ {
+ cmd := exec.Command("go", "run", filepath.Join("testdata", "flag.go"), "-help")
+ cmd.Env = append(os.Environ(), "CMDLINE_STYLE=godoc")
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("%v failed:\n%v", strings.Join(cmd.Args, " "), string(output))
+ }
if got, want := string(output), "-test=${TEST}"; !strings.Contains(got, want) {
t.Fatalf("%q not found in:\n%v", want, got)
}
diff --git a/cmdline/testdata/gendoc.go b/cmdline/testdata/gendoc.go
index 02ecc5c..f942ee3 100644
--- a/cmdline/testdata/gendoc.go
+++ b/cmdline/testdata/gendoc.go
@@ -56,13 +56,16 @@
// Use it to generate the documentation.
var out bytes.Buffer
+ env := os.Environ()
if len(os.Args) == 2 {
args = []string{"help", "-style=godoc", "..."}
} else {
args = os.Args[2:]
+ env = append(env, "CMDLINE_STYLE=godoc")
}
runCmd := exec.Command(gendocBin, args...)
runCmd.Stdout = &out
+ runCmd.Env = env
if err := runCmd.Run(); err != nil {
return fmt.Errorf("%q failed: %v\n%v\n", strings.Join(runCmd.Args, " "), err)
}