From aa7246311437facd235e6f1610632c89b02b3bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Mon, 14 Sep 2020 16:25:30 +0200 Subject: [PATCH 1/4] Extract `environment` as a separate help topic Co-authored-by: Sam Coe --- pkg/cmd/root/help.go | 5 +++++ pkg/cmd/root/help_topic.go | 41 ++++++++++++++++++++++++++++++++++++++ pkg/cmd/root/root.go | 26 +++--------------------- 3 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 pkg/cmd/root/help_topic.go diff --git a/pkg/cmd/root/help.go b/pkg/cmd/root/help.go index 019ec53cd..b2841ba9f 100644 --- a/pkg/cmd/root/help.go +++ b/pkg/cmd/root/help.go @@ -78,6 +78,11 @@ func rootHelpFunc(command *cobra.Command, args []string) { return } + if helpTopic := command.Annotations["helpTopic"]; helpTopic == "true" { + fmt.Fprint(command.OutOrStdout(), command.Long) + return + } + coreCommands := []string{} additionalCommands := []string{} for _, c := range command.Commands() { diff --git a/pkg/cmd/root/help_topic.go b/pkg/cmd/root/help_topic.go new file mode 100644 index 000000000..8e17685ae --- /dev/null +++ b/pkg/cmd/root/help_topic.go @@ -0,0 +1,41 @@ +package root + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" +) + +func NewHelpTopic(topic string) *cobra.Command { + return &cobra.Command{ + Use: "environment", + Long: heredoc.Doc(` + GITHUB_TOKEN: an authentication token for github.com API requests. Setting this avoids + being prompted to authenticate and takes precedence over previously stored credentials. + + GITHUB_ENTERPRISE_TOKEN: an authentication token for API requests to GitHub Enterprise. + + GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands + that otherwise operate on a local repository. + + GH_HOST: specify the GitHub hostname for commands that would otherwise assume + the "github.com" host when not in a context of an existing repository. + + GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use + for authoring text. + + BROWSER: the web browser to use for opening links. + + DEBUG: set to any value to enable verbose output to standard error. Include values "api" + or "oauth" to print detailed information about HTTP requests or authentication flow. + + GLAMOUR_STYLE: the style to use for rendering Markdown. See + https://github.com/charmbracelet/glamour#styles + + NO_COLOR: avoid printing ANSI escape sequences for color output. + `), + Hidden: true, + Annotations: map[string]string{ + "helpTopic": "true", + }, + } +} diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 0eadbd575..2c597352e 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -44,29 +44,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { Open an issue using “gh issue create -R cli/cli” `), "help:environment": heredoc.Doc(` - GITHUB_TOKEN: an authentication token for github.com API requests. Setting this avoids - being prompted to authenticate and takes precedence over previously stored credentials. - - GITHUB_ENTERPRISE_TOKEN: an authentication token for API requests to GitHub Enterprise. - - GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands - that otherwise operate on a local repository. - - GH_HOST: specify the GitHub hostname for commands that would otherwise assume - the "github.com" host when not in a context of an existing repository. - - GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use - for authoring text. - - BROWSER: the web browser to use for opening links. - - DEBUG: set to any value to enable verbose output to standard error. Include values "api" - or "oauth" to print detailed information about HTTP requests or authentication flow. - - GLAMOUR_STYLE: the style to use for rendering Markdown. See - https://github.com/charmbracelet/glamour#styles - - NO_COLOR: avoid printing ANSI escape sequences for color output. + See 'gh help environment' for the list of supported environment variables. `), }, } @@ -113,6 +91,8 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { cmd.AddCommand(gistCmd.NewCmdGist(f)) cmd.AddCommand(NewCmdCompletion(f.IOStreams)) + cmd.AddCommand(NewHelpTopic("environment")) + // the `api` command should not inherit any extra HTTP headers bareHTTPCmdFactory := *f bareHTTPCmdFactory.HttpClient = func() (*http.Client, error) { From 3c32507a1316ad38e82374a8bfa8cc126e5bc312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Mon, 14 Sep 2020 16:26:23 +0200 Subject: [PATCH 2/4] Consistent use of quotes to delineate commands to be run --- pkg/cmd/root/help.go | 2 +- pkg/cmd/root/root.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/root/help.go b/pkg/cmd/root/help.go index b2841ba9f..4f9a798fb 100644 --- a/pkg/cmd/root/help.go +++ b/pkg/cmd/root/help.go @@ -144,7 +144,7 @@ func rootHelpFunc(command *cobra.Command, args []string) { helpEntries = append(helpEntries, helpEntry{"ENVIRONMENT VARIABLES", command.Annotations["help:environment"]}) } helpEntries = append(helpEntries, helpEntry{"LEARN MORE", ` -Use "gh --help" for more information about a command. +Use 'gh --help' for more information about a command. Read the manual at https://cli.github.com/manual`}) if _, ok := command.Annotations["help:feedback"]; ok { helpEntries = append(helpEntries, helpEntry{"FEEDBACK", command.Annotations["help:feedback"]}) diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 2c597352e..f3319e456 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -41,7 +41,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { `), Annotations: map[string]string{ "help:feedback": heredoc.Doc(` - Open an issue using “gh issue create -R cli/cli” + Open an issue using 'gh issue create -R cli/cli' `), "help:environment": heredoc.Doc(` See 'gh help environment' for the list of supported environment variables. From 21449213e52b07f341e2b42d3fec9b6d144fcceb Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Mon, 14 Sep 2020 17:50:50 +0200 Subject: [PATCH 3/4] Expand help topic functionality --- pkg/cmd/root/help.go | 5 --- pkg/cmd/root/help_topic.go | 79 +++++++++++++++++++++++++++----------- pkg/cmd/root/root.go | 4 +- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/pkg/cmd/root/help.go b/pkg/cmd/root/help.go index 4f9a798fb..400be3834 100644 --- a/pkg/cmd/root/help.go +++ b/pkg/cmd/root/help.go @@ -78,11 +78,6 @@ func rootHelpFunc(command *cobra.Command, args []string) { return } - if helpTopic := command.Annotations["helpTopic"]; helpTopic == "true" { - fmt.Fprint(command.OutOrStdout(), command.Long) - return - } - coreCommands := []string{} additionalCommands := []string{} for _, c := range command.Commands() { diff --git a/pkg/cmd/root/help_topic.go b/pkg/cmd/root/help_topic.go index 8e17685ae..8a4e6f931 100644 --- a/pkg/cmd/root/help_topic.go +++ b/pkg/cmd/root/help_topic.go @@ -1,41 +1,76 @@ package root import ( + "fmt" + "github.com/MakeNowJust/heredoc" "github.com/spf13/cobra" ) func NewHelpTopic(topic string) *cobra.Command { - return &cobra.Command{ - Use: "environment", - Long: heredoc.Doc(` - GITHUB_TOKEN: an authentication token for github.com API requests. Setting this avoids - being prompted to authenticate and takes precedence over previously stored credentials. + topicContent := make(map[string]string) - GITHUB_ENTERPRISE_TOKEN: an authentication token for API requests to GitHub Enterprise. + topicContent["environment"] = heredoc.Doc(` + GITHUB_TOKEN: an authentication token for github.com API requests. Setting this avoids + being prompted to authenticate and takes precedence over previously stored credentials. - GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands - that otherwise operate on a local repository. + GITHUB_ENTERPRISE_TOKEN: an authentication token for API requests to GitHub Enterprise. - GH_HOST: specify the GitHub hostname for commands that would otherwise assume - the "github.com" host when not in a context of an existing repository. + GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands + that otherwise operate on a local repository. - GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use - for authoring text. + GH_HOST: specify the GitHub hostname for commands that would otherwise assume + the "github.com" host when not in a context of an existing repository. - BROWSER: the web browser to use for opening links. + GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use + for authoring text. - DEBUG: set to any value to enable verbose output to standard error. Include values "api" - or "oauth" to print detailed information about HTTP requests or authentication flow. + BROWSER: the web browser to use for opening links. - GLAMOUR_STYLE: the style to use for rendering Markdown. See - https://github.com/charmbracelet/glamour#styles + DEBUG: set to any value to enable verbose output to standard error. Include values "api" + or "oauth" to print detailed information about HTTP requests or authentication flow. - NO_COLOR: avoid printing ANSI escape sequences for color output. - `), + GLAMOUR_STYLE: the style to use for rendering Markdown. See + https://github.com/charmbracelet/glamour#styles + + NO_COLOR: avoid printing ANSI escape sequences for color output. + `) + + cmd := &cobra.Command{ + Use: topic, + Long: topicContent[topic], Hidden: true, - Annotations: map[string]string{ - "helpTopic": "true", - }, + Args: cobra.NoArgs, } + + cmd.SetHelpFunc(helpTopicHelpFunc) + cmd.SetUsageFunc(helpTopicUsageFunc) + + return cmd +} + +func helpTopicHelpFunc(command *cobra.Command, args []string) { + if len(args) >= 2 && args[1] != "--help" && args[1] != "-h" { + command.Printf("unknown command %q for %q\n", args[1], command.CommandPath()) + + if args[1] == "help" { + command.Print("\nDid you mean this?\n") + command.Printf("\t%s\n\n", "--help") + } else { + command.Printf("\n") + } + + helpTopicUsageFunc(command) + command.Printf("\n") + hasFailed = true + return + } + + fmt.Fprint(command.OutOrStdout(), command.Long) +} + +func helpTopicUsageFunc(command *cobra.Command) error { + command.Printf("Usage: gh help %s", command.Use) + + return nil } diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index f3319e456..7ad31fb68 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -82,8 +82,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { cmdutil.DisableAuthCheck(cmd) - // CHILD COMMANDS - + // Child commands cmd.AddCommand(aliasCmd.NewCmdAlias(f)) cmd.AddCommand(authCmd.NewCmdAuth(f)) cmd.AddCommand(configCmd.NewCmdConfig(f)) @@ -91,6 +90,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { cmd.AddCommand(gistCmd.NewCmdGist(f)) cmd.AddCommand(NewCmdCompletion(f.IOStreams)) + // Help Topics cmd.AddCommand(NewHelpTopic("environment")) // the `api` command should not inherit any extra HTTP headers From 7ecb6a413fe9663614f46b6837ca71012762de47 Mon Sep 17 00:00:00 2001 From: Sam Coe Date: Mon, 14 Sep 2020 22:21:05 +0200 Subject: [PATCH 4/4] Add tests for help topics --- pkg/cmd/root/help_topic.go | 24 ++-------- pkg/cmd/root/help_topic_test.go | 79 +++++++++++++++++++++++++++++++++ pkg/cmd/root/root.go | 2 +- 3 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 pkg/cmd/root/help_topic_test.go diff --git a/pkg/cmd/root/help_topic.go b/pkg/cmd/root/help_topic.go index 8a4e6f931..1357825a2 100644 --- a/pkg/cmd/root/help_topic.go +++ b/pkg/cmd/root/help_topic.go @@ -1,8 +1,6 @@ package root import ( - "fmt" - "github.com/MakeNowJust/heredoc" "github.com/spf13/cobra" ) @@ -41,6 +39,7 @@ func NewHelpTopic(topic string) *cobra.Command { Long: topicContent[topic], Hidden: true, Args: cobra.NoArgs, + Run: helpTopicHelpFunc, } cmd.SetHelpFunc(helpTopicHelpFunc) @@ -50,27 +49,10 @@ func NewHelpTopic(topic string) *cobra.Command { } func helpTopicHelpFunc(command *cobra.Command, args []string) { - if len(args) >= 2 && args[1] != "--help" && args[1] != "-h" { - command.Printf("unknown command %q for %q\n", args[1], command.CommandPath()) - - if args[1] == "help" { - command.Print("\nDid you mean this?\n") - command.Printf("\t%s\n\n", "--help") - } else { - command.Printf("\n") - } - - helpTopicUsageFunc(command) - command.Printf("\n") - hasFailed = true - return - } - - fmt.Fprint(command.OutOrStdout(), command.Long) + command.Print(command.Long) } func helpTopicUsageFunc(command *cobra.Command) error { - command.Printf("Usage: gh help %s", command.Use) - + command.Printf("Usage: gh help %s", command.Use) return nil } diff --git a/pkg/cmd/root/help_topic_test.go b/pkg/cmd/root/help_topic_test.go new file mode 100644 index 000000000..f194541ac --- /dev/null +++ b/pkg/cmd/root/help_topic_test.go @@ -0,0 +1,79 @@ +package root + +import ( + "testing" + + "github.com/cli/cli/pkg/iostreams" + "github.com/stretchr/testify/assert" +) + +func TestNewHelpTopic(t *testing.T) { + tests := []struct { + name string + topic string + args []string + flags []string + wantsErr bool + }{ + { + name: "valid topic", + topic: "environment", + args: []string{}, + flags: []string{}, + wantsErr: false, + }, + { + name: "invalid topic", + topic: "invalid", + args: []string{}, + flags: []string{}, + wantsErr: false, + }, + { + name: "more than zero args", + topic: "environment", + args: []string{"invalid"}, + flags: []string{}, + wantsErr: true, + }, + { + name: "more than zero flags", + topic: "environment", + args: []string{}, + flags: []string{"--invalid"}, + wantsErr: true, + }, + { + name: "help arg", + topic: "environment", + args: []string{"help"}, + flags: []string{}, + wantsErr: true, + }, + { + name: "help flag", + topic: "environment", + args: []string{}, + flags: []string{"--help"}, + wantsErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, _, stdout, stderr := iostreams.Test() + + cmd := NewHelpTopic(tt.topic) + cmd.SetArgs(append(tt.args, tt.flags...)) + cmd.SetOut(stdout) + cmd.SetErr(stderr) + + _, err := cmd.ExecuteC() + if tt.wantsErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + }) + } +} diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 7ad31fb68..e3257ed09 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -90,7 +90,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { cmd.AddCommand(gistCmd.NewCmdGist(f)) cmd.AddCommand(NewCmdCompletion(f.IOStreams)) - // Help Topics + // Help topics cmd.AddCommand(NewHelpTopic("environment")) // the `api` command should not inherit any extra HTTP headers