X Tutup
Skip to content

Commit e87b5bc

Browse files
rista404vilmibmvilmibmmislav
authored
Add "reference" help topic (cli#2223)
* Add "reference" help topic * Only print reference as a help topic * fix for color fns, slightly generalize * WIP for switching to markdown * escape gt/lt * minor * higher wrap point * detect terminal theme * futz with angle brackets once more * minor cleanup * prepend parent commands * rename help topic fns and add test * Simplify reference help generation - the `<...>` characters from command usage line are now preserved by enclosing the entire usage synopsis in a code span - hard breaks in flag usage lines are preserved by enclosing flag usage in a code block - TTY detection and Markdown rendering are now delayed until the user explicitly requests `gh help reference` - `gh help reference` output is now pager-enabled Co-authored-by: vilmibm <vilmibm@github.com> Co-authored-by: vilmibm <vilmibm@neongrid.space> Co-authored-by: Mislav Marohnić <mislav@github.com>
1 parent ee48274 commit e87b5bc

File tree

5 files changed

+96
-4
lines changed

5 files changed

+96
-4
lines changed

pkg/cmd/root/help_reference.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package root
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"strings"
8+
9+
"github.com/cli/cli/pkg/iostreams"
10+
"github.com/cli/cli/pkg/markdown"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
func referenceHelpFn(io *iostreams.IOStreams) func(*cobra.Command, []string) {
15+
return func(cmd *cobra.Command, args []string) {
16+
wrapWidth := 0
17+
style := "notty"
18+
if io.IsStdoutTTY() {
19+
wrapWidth = io.TerminalWidth()
20+
style = markdown.GetStyle(io.DetectTerminalTheme())
21+
}
22+
23+
md, err := markdown.RenderWrap(cmd.Long, style, wrapWidth)
24+
if err != nil {
25+
fmt.Fprintln(io.ErrOut, err)
26+
return
27+
}
28+
29+
if !io.IsStdoutTTY() {
30+
fmt.Fprint(io.Out, dedent(md))
31+
return
32+
}
33+
34+
_ = io.StartPager()
35+
defer io.StopPager()
36+
fmt.Fprint(io.Out, md)
37+
}
38+
}
39+
40+
func referenceLong(cmd *cobra.Command) string {
41+
buf := bytes.NewBufferString("# gh reference\n\n")
42+
for _, c := range cmd.Commands() {
43+
if c.Hidden {
44+
continue
45+
}
46+
cmdRef(buf, c, 2)
47+
}
48+
return buf.String()
49+
}
50+
51+
func cmdRef(w io.Writer, cmd *cobra.Command, depth int) {
52+
// Name + Description
53+
fmt.Fprintf(w, "%s `%s`\n\n", strings.Repeat("#", depth), cmd.UseLine())
54+
fmt.Fprintf(w, "%s\n\n", cmd.Short)
55+
56+
// Flags
57+
// TODO: fold in InheritedFlags/PersistentFlags, but omit `--help` due to repetitiveness
58+
if flagUsages := cmd.Flags().FlagUsages(); flagUsages != "" {
59+
fmt.Fprintf(w, "```\n%s````\n\n", dedent(flagUsages))
60+
}
61+
62+
// Subcommands
63+
for _, c := range cmd.Commands() {
64+
if c.Hidden {
65+
continue
66+
}
67+
cmdRef(w, c, depth+1)
68+
}
69+
}

pkg/cmd/root/help_topic.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ var HelpTopics = map[string]map[string]string{
4747
error if a newer version was found.
4848
`),
4949
},
50+
"reference": {
51+
"short": "A comprehensive reference of all gh commands",
52+
},
5053
}
5154

5255
func NewHelpTopic(topic string) *cobra.Command {
@@ -55,8 +58,6 @@ func NewHelpTopic(topic string) *cobra.Command {
5558
Short: HelpTopics[topic]["short"],
5659
Long: HelpTopics[topic]["long"],
5760
Hidden: true,
58-
Args: cobra.NoArgs,
59-
Run: helpTopicHelpFunc,
6061
Annotations: map[string]string{
6162
"markdown:generate": "true",
6263
"markdown:basename": "gh_help_" + topic,

pkg/cmd/root/help_topic_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestNewHelpTopic(t *testing.T) {
3434
topic: "environment",
3535
args: []string{"invalid"},
3636
flags: []string{},
37-
wantsErr: true,
37+
wantsErr: false,
3838
},
3939
{
4040
name: "more than zero flags",
@@ -48,7 +48,7 @@ func TestNewHelpTopic(t *testing.T) {
4848
topic: "environment",
4949
args: []string{"help"},
5050
flags: []string{},
51-
wantsErr: true,
51+
wantsErr: false,
5252
},
5353
{
5454
name: "help flag",

pkg/cmd/root/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,14 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command {
9292

9393
// Help topics
9494
cmd.AddCommand(NewHelpTopic("environment"))
95+
referenceCmd := NewHelpTopic("reference")
96+
referenceCmd.SetHelpFunc(referenceHelpFn(f.IOStreams))
97+
cmd.AddCommand(referenceCmd)
9598

9699
cmdutil.DisableAuthCheck(cmd)
97100

101+
// this needs to appear last:
102+
referenceCmd.Long = referenceLong(cmd)
98103
return cmd
99104
}
100105

pkg/markdown/markdown.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ func Render(text, style string, baseURL string) (string, error) {
2424
return tr.Render(text)
2525
}
2626

27+
func RenderWrap(text, style string, wrap int) (string, error) {
28+
// Glamour rendering preserves carriage return characters in code blocks, but
29+
// we need to ensure that no such characters are present in the output.
30+
text = strings.ReplaceAll(text, "\r\n", "\n")
31+
32+
tr, err := glamour.NewTermRenderer(
33+
glamour.WithStylePath(style),
34+
// glamour.WithBaseURL(""), // TODO: make configurable
35+
glamour.WithWordWrap(wrap),
36+
)
37+
if err != nil {
38+
return "", err
39+
}
40+
41+
return tr.Render(text)
42+
}
43+
2744
func GetStyle(defaultStyle string) string {
2845
style := fromEnv()
2946
if style != "" && style != "auto" {

0 commit comments

Comments
 (0)
X Tutup