mirror of
https://github.com/spf13/cobra
synced 2025-05-02 11:27:21 +00:00
Generated Documentation
This commit is contained in:
parent
16f7019823
commit
ea92b272f6
2 changed files with 66 additions and 173 deletions
|
@ -30,11 +30,15 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// GenManTree will generate a man page for this command and all descendants
|
||||
// in the directory given. The header may be nil. This function may not work
|
||||
// correctly if your command names have `-` in them. If you have `cmd` with two
|
||||
// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third`
|
||||
// it is undefined which help output will be in the file `cmd-sub-third.1`.
|
||||
// GenManTree generates a man page for the provided command and all its descendants in the specified directory.
|
||||
//
|
||||
// It takes a cobra.Command pointer representing the root command, an optional GenManHeader pointer to customize the header information, and a string specifying the output directory.
|
||||
//
|
||||
// The function assumes that command names do not contain hyphens (`-`). If they do, unexpected behavior may occur.
|
||||
//
|
||||
// Note: If a command named `cmd` has subcommands `sub` and `sub-third`, and `sub` itself has a subcommand called `third`, it is undefined which help output will be written to the file `cmd-sub-third.1`.
|
||||
//
|
||||
// Returns an error if the generation process encounters any issues, such as invalid input or permission errors when writing files to the specified directory.
|
||||
func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
|
||||
return GenManTreeFromOpts(cmd, GenManTreeOptions{
|
||||
Header: header,
|
||||
|
@ -44,7 +48,15 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error {
|
|||
}
|
||||
|
||||
// GenManTreeFromOpts generates a man page for the command and all descendants.
|
||||
// The pages are written to the opts.Path directory.
|
||||
// The pages are written to the opts.Path directory. It recursively processes each command in the tree,
|
||||
// skipping non-available or additional help topic commands. Each man page is saved with a filename based on the command path and section.
|
||||
|
||||
// Parameters:
|
||||
// - cmd: A pointer to the root cobra.Command for which man pages need to be generated.
|
||||
// - opts: A GenManTreeOptions struct containing options for generating the man pages, such as header details, output directory, and separators.
|
||||
|
||||
// Returns:
|
||||
// - error: If any error occurs during the generation of the man pages, it is returned.
|
||||
func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error {
|
||||
header := opts.Header
|
||||
if header == nil {
|
||||
|
@ -100,8 +112,15 @@ type GenManHeader struct {
|
|||
Manual string
|
||||
}
|
||||
|
||||
// GenMan will generate a man page for the given command and write it to
|
||||
// w. The header argument may be nil, however obviously w may not.
|
||||
// GenMan generates a man page for the given command and writes it to the specified writer.
|
||||
//
|
||||
// Parameters:
|
||||
// cmd - The cobra.Command for which to generate the man page.
|
||||
// header - A pointer to a GenManHeader that contains additional information for the man page. If nil, a default header will be used.
|
||||
// w - The io.Writer to which the generated man page will be written.
|
||||
//
|
||||
// Returns:
|
||||
// error - If an error occurs during the generation of the man page, it will be returned here.
|
||||
func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
|
||||
if header == nil {
|
||||
header = &GenManHeader{}
|
||||
|
@ -115,6 +134,15 @@ func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// fillHeader populates the GenManHeader with default values if they are not already set.
|
||||
//
|
||||
// It sets the title to the uppercase version of `name`, replacing spaces with hyphens.
|
||||
// If the section is empty, it defaults to "1".
|
||||
// If the date is nil, it sets the date to the current time or a time specified by the SOURCE_DATE_EPOCH environment variable.
|
||||
// The formatted date is stored in header.date.
|
||||
// If source is empty and auto-generation is not disabled, it sets the source to "Auto generated by spf13/cobra".
|
||||
//
|
||||
// It returns an error if there is an issue parsing the SOURCE_DATE_EPOCH environment variable.
|
||||
func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error {
|
||||
if header.Title == "" {
|
||||
header.Title = strings.ToUpper(strings.ReplaceAll(name, " ", "\\-"))
|
||||
|
@ -140,6 +168,17 @@ func fillHeader(header *GenManHeader, name string, disableAutoGen bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// manPreamble writes the preamble for a manual page to the given buffer.
|
||||
//
|
||||
// Parameters:
|
||||
// buf - the io.StringWriter to write the preamble to.
|
||||
// header - a pointer to a GenManHeader containing metadata for the manual page.
|
||||
// cmd - a pointer to a cobra.Command representing the command being documented.
|
||||
// dashedName - the dash-separated name of the command.
|
||||
//
|
||||
// This function constructs the preamble section of a man page, including
|
||||
// the title, section, date, source, and manual. It also includes the command's
|
||||
// short description and synopsis.
|
||||
func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command, dashedName string) {
|
||||
description := cmd.Long
|
||||
if len(description) == 0 {
|
||||
|
@ -156,6 +195,12 @@ func manPreamble(buf io.StringWriter, header *GenManHeader, cmd *cobra.Command,
|
|||
cobra.WriteStringAndCheck(buf, description+"\n\n")
|
||||
}
|
||||
|
||||
// manPrintFlags prints the flags in a format suitable for a man page.
|
||||
//
|
||||
// It takes an io.StringWriter to write to and a pflag.FlagSet containing the flags to print.
|
||||
// For each flag, it checks if it is deprecated or hidden. If not, it formats the flag name,
|
||||
// shorthand, and usage information according to its type (string or other) and whether it has
|
||||
// a default value. The formatted string is then written to the provided writer.
|
||||
func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) {
|
||||
flags.VisitAll(func(flag *pflag.Flag) {
|
||||
if len(flag.Deprecated) > 0 || flag.Hidden {
|
||||
|
@ -184,6 +229,8 @@ func manPrintFlags(buf io.StringWriter, flags *pflag.FlagSet) {
|
|||
})
|
||||
}
|
||||
|
||||
// manPrintOptions writes the options for a command to a StringWriter.
|
||||
// It includes both non-inherited and inherited flags, if available.
|
||||
func manPrintOptions(buf io.StringWriter, command *cobra.Command) {
|
||||
flags := command.NonInheritedFlags()
|
||||
if flags.HasAvailableFlags() {
|
||||
|
@ -199,6 +246,17 @@ func manPrintOptions(buf io.StringWriter, command *cobra.Command) {
|
|||
}
|
||||
}
|
||||
|
||||
// genMan generates a man page for the given Cobra command and header.
|
||||
// It initializes default help commands and flags, processes the command path,
|
||||
// and constructs the man page content including preamble, options, examples,
|
||||
// see also sections, and history.
|
||||
//
|
||||
// Parameters:
|
||||
// - cmd: The Cobra command for which to generate the man page.
|
||||
// - header: Header information for the man page, such as section and date.
|
||||
//
|
||||
// Returns:
|
||||
// - A byte slice containing the generated man page content.
|
||||
func genMan(cmd *cobra.Command, header *GenManHeader) []byte {
|
||||
cmd.InitDefaultHelpCmd()
|
||||
cmd.InitDefaultHelpFlag()
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cobra
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCompleteNoDesCmdInFishScript tests the completion functionality for a command without descriptions in a Fish shell script.
|
||||
//
|
||||
// It sets up a root command and a child command, adds the child to the root, generates Fish completion script,
|
||||
// and checks if the output contains the expected completion information without descriptions.
|
||||
func TestCompleteNoDesCmdInFishScript(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
|
||||
child := &Command{
|
||||
Use: "child",
|
||||
ValidArgsFunction: validArgsFunc,
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(child)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||
output := buf.String()
|
||||
|
||||
check(t, output, ShellCompNoDescRequestCmd)
|
||||
}
|
||||
|
||||
// TestCompleteCmdInFishScript tests the generation of fish completion script for a command.
|
||||
func TestCompleteCmdInFishScript(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
|
||||
child := &Command{
|
||||
Use: "child",
|
||||
ValidArgsFunction: validArgsFunc,
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(child)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assertNoErr(t, rootCmd.GenFishCompletion(buf, true))
|
||||
output := buf.String()
|
||||
|
||||
check(t, output, ShellCompRequestCmd)
|
||||
checkOmit(t, output, ShellCompNoDescRequestCmd)
|
||||
}
|
||||
|
||||
// TestProgWithDash tests the generation of fish completion for a command with a hyphen in its name.
|
||||
// It verifies that the hyphen is replaced in function names but remains intact in the command name.
|
||||
func TestProgWithDash(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root-dash", Args: NoArgs, Run: emptyRun}
|
||||
buf := new(bytes.Buffer)
|
||||
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||
output := buf.String()
|
||||
|
||||
// Functions name should have replace the '-'
|
||||
check(t, output, "__root_dash_perform_completion")
|
||||
checkOmit(t, output, "__root-dash_perform_completion")
|
||||
|
||||
// The command name should not have replaced the '-'
|
||||
check(t, output, "-c root-dash")
|
||||
checkOmit(t, output, "-c root_dash")
|
||||
}
|
||||
|
||||
// TestProgWithColon tests the generation of Fish completion for a command with a colon in its name.
|
||||
func TestProgWithColon(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root:colon", Args: NoArgs, Run: emptyRun}
|
||||
buf := new(bytes.Buffer)
|
||||
assertNoErr(t, rootCmd.GenFishCompletion(buf, false))
|
||||
output := buf.String()
|
||||
|
||||
// Functions name should have replace the ':'
|
||||
check(t, output, "__root_colon_perform_completion")
|
||||
checkOmit(t, output, "__root:colon_perform_completion")
|
||||
|
||||
// The command name should not have replaced the ':'
|
||||
check(t, output, "-c root:colon")
|
||||
checkOmit(t, output, "-c root_colon")
|
||||
}
|
||||
|
||||
// TestFishCompletionNoActiveHelp tests the generation of Fish completion script without active help enabled.
|
||||
//
|
||||
// Parameters:
|
||||
// - t: A testing.T instance for assertions and logging.
|
||||
//
|
||||
// The function creates a new Command, generates its Fish completion script with active help disabled,
|
||||
// and asserts that the output does not include an active help variable set to 1.
|
||||
func TestFishCompletionNoActiveHelp(t *testing.T) {
|
||||
c := &Command{Use: "c", Run: emptyRun}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
assertNoErr(t, c.GenFishCompletion(buf, true))
|
||||
output := buf.String()
|
||||
|
||||
// check that active help is being disabled
|
||||
activeHelpVar := activeHelpEnvVar(c.Name())
|
||||
check(t, output, fmt.Sprintf("%s=0", activeHelpVar))
|
||||
}
|
||||
|
||||
// TestGenFishCompletionFile tests the generation of a Fish completion file for a Cobra command.
|
||||
// It creates a temporary file, sets up a Cobra command hierarchy, and asserts that no errors occur during the completion file generation process.
|
||||
func TestGenFishCompletionFile(t *testing.T) {
|
||||
tmpFile, err := os.CreateTemp("", "cobra-test")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
|
||||
child := &Command{
|
||||
Use: "child",
|
||||
ValidArgsFunction: validArgsFunc,
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(child)
|
||||
|
||||
assertNoErr(t, rootCmd.GenFishCompletionFile(tmpFile.Name(), false))
|
||||
}
|
||||
|
||||
// TestFailGenFishCompletionFile tests the GenFishCompletionFile method for permission errors.
|
||||
//
|
||||
// It creates a temporary directory and file, sets up a command structure,
|
||||
// and attempts to generate Fish completion file. It checks if the error returned
|
||||
// matches os.ErrPermission as expected. If not, it fails the test with an error message.
|
||||
func TestFailGenFishCompletionFile(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "cobra-test")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
f, _ := os.OpenFile(filepath.Join(tmpDir, "test"), os.O_CREATE, 0400)
|
||||
defer f.Close()
|
||||
|
||||
rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
|
||||
child := &Command{
|
||||
Use: "child",
|
||||
ValidArgsFunction: validArgsFunc,
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(child)
|
||||
|
||||
got := rootCmd.GenFishCompletionFile(f.Name(), false)
|
||||
if !errors.Is(got, os.ErrPermission) {
|
||||
t.Errorf("got: %s, want: %s", got.Error(), os.ErrPermission.Error())
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue