Skip to content

Commit

Permalink
Adds Markdown documentation command
Browse files Browse the repository at this point in the history
Introduces a new command to export Markdown documentation to a user-defined folder. Updates dependencies and integrates the new command into the CommandLineApplication workflow.
  • Loading branch information
matzefriedrich committed Nov 27, 2024
1 parent 4b66068 commit 0c2fbbd
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 3 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ require (
github.com/ProtonMail/go-crypto v1.1.0 // indirect
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/sys v0.16.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ github.com/ProtonMail/gopenpgp/v2 v2.8.0 h1:WvMv3CMcFsqKSM4/Qf8sf3tgyQkzDqQmoSE4
github.com/ProtonMail/gopenpgp/v2 v2.8.0/go.mod h1:qb2GUSnmA9ipBW5GVtCtEhkummSlqs2A8Ar3S0HBgSY=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -17,6 +18,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
Expand Down
74 changes: 74 additions & 0 deletions internal/commands/markdown_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package commands

import (
"github.com/matzefriedrich/cobra-extensions/internal/utils"
"github.com/matzefriedrich/cobra-extensions/pkg/commands"
"github.com/matzefriedrich/cobra-extensions/pkg/types"
"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
"log"
"os"
"path/filepath"
)

type markdownDocsCommand struct {
use types.CommandName `flag:"markdown" short:"Exports Markdown documentation to the specified folder" description:"Exports Markdown documentation to the specified folder"`
OutputFolderPath string `flag:"output" usage:"The output folder for markdown documentation" default:"."`
root *cobra.Command
}

func (m *markdownDocsCommand) Execute() {

outputPath, _ := filepath.Abs(m.OutputFolderPath)

ext := filepath.Ext(outputPath)
switch ext {
case ".md", ".markdown":
m.generateSingleMarkdownFile(outputPath)
default:
err := doc.GenMarkdownTree(m.root, outputPath)
if err != nil {
log.Fatalf("Error generating markdown documentation: %v", err)
}
}

}

func (m *markdownDocsCommand) generateSingleMarkdownFile(outputPath string) {

writer, _ := os.OpenFile(outputPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
defer func(writer *os.File) {
_ = writer.Close()
}(writer)

stack := utils.MakeStack[*cobra.Command]()
stack.Push(m.root)

for stack.Any() {
next := stack.Pop()
for _, c := range next.Commands() {
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
stack.Push(c)
}

_ = doc.GenMarkdownCustom(next, writer, func(s string) string {
return s
})

_, _ = writer.WriteString("\n")
}

_ = writer.Sync()
}

var _ types.TypedCommand = (*markdownDocsCommand)(nil)

// NewMarkdownDocsCommand creates a new Cobra command for exporting Markdown documentation to a specified folder.
func NewMarkdownDocsCommand(root *cobra.Command) *cobra.Command {
instance := &markdownDocsCommand{
root: root,
}
return commands.CreateTypedCommand(instance)
}
16 changes: 14 additions & 2 deletions pkg/charmer/command_line_application.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package charmer

import (
"github.com/matzefriedrich/cobra-extensions/internal/commands"
"github.com/matzefriedrich/cobra-extensions/pkg/types"
"github.com/spf13/cobra"
)
Expand All @@ -23,9 +24,12 @@ func NewRootCommand(name string, description string) *cobra.Command {

// NewCommandLineApplication Creates a new CommandLineApplication instance.
func NewCommandLineApplication(name string, description string) *CommandLineApplication {
return &CommandLineApplication{
root: NewRootCommand(name, description),
rootCommand := NewRootCommand(name, description)
app := &CommandLineApplication{
root: rootCommand,
}
app.AddCommand(commands.NewMarkdownDocsCommand(rootCommand))
return app
}

// Execute executes the root command of the CommandLineApplication.
Expand All @@ -42,9 +46,17 @@ func (a *CommandLineApplication) AddCommand(c ...*cobra.Command) *CommandLineApp
// AddGroupCommand Adds a sub-command to the root command and configures it using the provided setup function.
func (a *CommandLineApplication) AddGroupCommand(c *cobra.Command, setup types.CommandsSetupFunc) *CommandLineApplication {
a.root.AddCommand(c)

makeNonRunnable(c)

if setup != nil {
wrapper := newCommandSetup(c)
setup(wrapper)
}
return a
}

func makeNonRunnable(c *cobra.Command) {
c.Run = nil
c.RunE = nil
}
9 changes: 8 additions & 1 deletion pkg/commands/typed_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type commandContextValue struct {
descriptor types.CommandDescriptor
}

type CommandOption func(cmd *cobra.Command)

// run Binds argument and flag values and executes the command.
func (c *commandContextValue) run(target *cobra.Command, args ...string) {
c.descriptor.UnmarshalFlagValues(target)
Expand All @@ -20,20 +22,25 @@ func (c *commandContextValue) run(target *cobra.Command, args ...string) {
}

// CreateTypedCommand Creates a new typed command from the given handler instance.
func CreateTypedCommand[T types.TypedCommand](instance T) *cobra.Command {
func CreateTypedCommand[T types.TypedCommand](instance T, options ...CommandOption) *cobra.Command {

reflector := reflection.NewCommandReflector[T]()
desc := reflector.ReflectCommandDescriptor(instance)

commandKey := desc.Key()

cmd := &cobra.Command{
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
v := cmd.Context().Value(commandKey).(*commandContextValue)
v.run(cmd, args...)
},
}

for _, option := range options {
option(cmd)
}

desc.BindArguments(cmd)
desc.BindFlags(cmd)

Expand Down

0 comments on commit 0c2fbbd

Please sign in to comment.