Skip to content

Commit

Permalink
feat: config package revamp (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
ravisuhag authored Dec 11, 2024
1 parent 34cdbab commit 33b514f
Show file tree
Hide file tree
Showing 16 changed files with 605 additions and 313 deletions.
34 changes: 17 additions & 17 deletions cli/cmdx/cmdx.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"github.com/spf13/cobra"
)

// Manager manages and configures features for a CLI tool.
type Manager struct {
// Commander manages and configures features for a CLI tool.
type Commander struct {
RootCmd *cobra.Command
Help bool // Enable custom help.
Reference bool // Enable reference command.
Expand All @@ -32,19 +32,19 @@ type HookBehavior struct {
Behavior func(cmd *cobra.Command) // Function to apply to commands.
}

// NewManager creates a new CLI Manager using the provided root command and optional configurations.
// NewCommander creates a new CLI Commander using the provided root command and optional configurations.
//
// Parameters:
// - rootCmd: The root Cobra command for the CLI.
// - options: Functional options for configuring the Manager.
// - options: Functional options for configuring the Commander.
//
// Example:
//
// rootCmd := &cobra.Command{Use: "mycli"}
// manager := cmdx.NewManager(rootCmd, cmdx.WithTopics(...), cmdx.WithHooks(...))
func NewManager(rootCmd *cobra.Command, options ...func(*Manager)) *Manager {
// Create Manager with defaults
manager := &Manager{
// manager := cmdx.NewCommander(rootCmd, cmdx.WithTopics(...), cmdx.WithHooks(...))
func NewCommander(rootCmd *cobra.Command, options ...func(*Commander)) *Commander {
// Create Commander with defaults
manager := &Commander{
RootCmd: rootCmd,
Help: true, // Default enabled
Reference: true, // Default enabled
Expand All @@ -62,11 +62,11 @@ func NewManager(rootCmd *cobra.Command, options ...func(*Manager)) *Manager {
return manager
}

// Init sets up the CLI features based on the Manager's configuration.
// Init sets up the CLI features based on the Commander's configuration.
//
// It enables or disables features like custom help, reference documentation,
// shell completion, help topics, and client hooks based on the Manager's settings.
func (m *Manager) Init() {
// shell completion, help topics, and client hooks based on the Commander's settings.
func (m *Commander) Init() {
if m.Help {
m.SetCustomHelp()
}
Expand All @@ -88,16 +88,16 @@ func (m *Manager) Init() {
}
}

// WithTopics sets the help topics for the Manager.
func WithTopics(topics []HelpTopic) func(*Manager) {
return func(m *Manager) {
// WithTopics sets the help topics for the Commander.
func WithTopics(topics []HelpTopic) func(*Commander) {
return func(m *Commander) {
m.Topics = topics
}
}

// WithHooks sets the hook behaviors for the Manager.
func WithHooks(hooks []HookBehavior) func(*Manager) {
return func(m *Manager) {
// WithHooks sets the hook behaviors for the Commander.
func WithHooks(hooks []HookBehavior) func(*Commander) {
return func(m *Commander) {
m.Hooks = hooks
}
}
Expand Down
8 changes: 4 additions & 4 deletions cli/cmdx/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import (
//
// Example:
//
// manager := cmdx.NewManager(rootCmd)
// manager := cmdx.NewCommander(rootCmd)
// manager.AddCompletionCommand()
//
// Usage:
//
// $ mycli completion bash
// $ mycli completion zsh
func (m *Manager) AddCompletionCommand() {
func (m *Commander) AddCompletionCommand() {
summary := m.generateCompletionSummary(m.RootCmd.Use)

completionCmd := &cobra.Command{
Expand All @@ -38,7 +38,7 @@ func (m *Manager) AddCompletionCommand() {
}

// runCompletionCommand executes the appropriate shell completion generation logic.
func (m *Manager) runCompletionCommand(cmd *cobra.Command, args []string) {
func (m *Commander) runCompletionCommand(cmd *cobra.Command, args []string) {
switch args[0] {
case "bash":
cmd.Root().GenBashCompletion(os.Stdout)
Expand All @@ -52,7 +52,7 @@ func (m *Manager) runCompletionCommand(cmd *cobra.Command, args []string) {
}

// generateCompletionSummary creates the long description for the `completion` command.
func (m *Manager) generateCompletionSummary(exec string) string {
func (m *Commander) generateCompletionSummary(exec string) string {
var execs []interface{}
for i := 0; i < 12; i++ {
execs = append(execs, exec)
Expand Down
4 changes: 2 additions & 2 deletions cli/cmdx/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
// },
// }
//
// // Create the Manager with configurations
// manager := cmdx.NewManager(
// // Create the Commander with configurations
// manager := cmdx.NewCommander(
// rootCmd,
// cmdx.WithTopics(helpTopics),
// cmdx.WithHooks(hooks),
Expand Down
48 changes: 24 additions & 24 deletions cli/cmdx/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ import (

// Section Titles for Help Output
const (
USAGE = "Usage"
CORECMD = "Core commands"
OTHERCMD = "Other commands"
HELPCMD = "Help topics"
FLAGS = "Flags"
IFLAGS = "Inherited flags"
ARGUMENTS = "Arguments"
EXAMPLES = "Examples"
ENVS = "Environment variables"
LEARN = "Learn more"
FEEDBACK = "Feedback"
usage = "Usage"
corecmd = "Core commands"
othercmd = "Other commands"
helpcmd = "Help topics"
flags = "Flags"
iflags = "Inherited flags"
arguments = "Arguments"
examples = "Examples"
envs = "Environment variables"
learn = "Learn more"
feedback = "Feedback"
)

// SetCustomHelp configures a custom help function for the CLI.
Expand All @@ -31,9 +31,9 @@ const (
//
// Example:
//
// manager := cmdx.NewManager(rootCmd)
// manager := cmdx.NewCommander(rootCmd)
// manager.SetCustomHelp()
func (m *Manager) SetCustomHelp() {
func (m *Commander) SetCustomHelp() {
m.RootCmd.PersistentFlags().Bool("help", false, "Show help for command")

m.RootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -120,39 +120,39 @@ func buildHelpEntries(cmd *cobra.Command) []helpEntry {
helpEntries = append(helpEntries, helpEntry{"", text})
}

helpEntries = append(helpEntries, helpEntry{USAGE, cmd.UseLine()})
helpEntries = append(helpEntries, helpEntry{usage, cmd.UseLine()})
if len(coreCommands) > 0 {
helpEntries = append(helpEntries, helpEntry{CORECMD, strings.Join(coreCommands, "\n")})
helpEntries = append(helpEntries, helpEntry{corecmd, strings.Join(coreCommands, "\n")})
}
for group, cmds := range groupCommands {
helpEntries = append(helpEntries, helpEntry{fmt.Sprintf("%s commands", toTitle(group)), strings.Join(cmds, "\n")})
}
if len(otherCommands) > 0 {
helpEntries = append(helpEntries, helpEntry{OTHERCMD, strings.Join(otherCommands, "\n")})
helpEntries = append(helpEntries, helpEntry{othercmd, strings.Join(otherCommands, "\n")})
}
if len(helpCommands) > 0 {
helpEntries = append(helpEntries, helpEntry{HELPCMD, strings.Join(helpCommands, "\n")})
helpEntries = append(helpEntries, helpEntry{helpcmd, strings.Join(helpCommands, "\n")})
}
if flagUsages := cmd.LocalFlags().FlagUsages(); flagUsages != "" {
helpEntries = append(helpEntries, helpEntry{FLAGS, dedent(flagUsages)})
helpEntries = append(helpEntries, helpEntry{flags, dedent(flagUsages)})
}
if inheritedFlagUsages := cmd.InheritedFlags().FlagUsages(); inheritedFlagUsages != "" {
helpEntries = append(helpEntries, helpEntry{IFLAGS, dedent(inheritedFlagUsages)})
helpEntries = append(helpEntries, helpEntry{iflags, dedent(inheritedFlagUsages)})
}
if argsAnnotation, ok := cmd.Annotations["help:arguments"]; ok {
helpEntries = append(helpEntries, helpEntry{ARGUMENTS, argsAnnotation})
helpEntries = append(helpEntries, helpEntry{arguments, argsAnnotation})
}
if cmd.Example != "" {
helpEntries = append(helpEntries, helpEntry{EXAMPLES, cmd.Example})
helpEntries = append(helpEntries, helpEntry{examples, cmd.Example})
}
if argsAnnotation, ok := cmd.Annotations["help:environment"]; ok {
helpEntries = append(helpEntries, helpEntry{ENVS, argsAnnotation})
helpEntries = append(helpEntries, helpEntry{envs, argsAnnotation})
}
if argsAnnotation, ok := cmd.Annotations["help:learn"]; ok {
helpEntries = append(helpEntries, helpEntry{LEARN, argsAnnotation})
helpEntries = append(helpEntries, helpEntry{learn, argsAnnotation})
}
if argsAnnotation, ok := cmd.Annotations["help:feedback"]; ok {
helpEntries = append(helpEntries, helpEntry{FEEDBACK, argsAnnotation})
helpEntries = append(helpEntries, helpEntry{feedback, argsAnnotation})
}
return helpEntries
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmdx/hooks.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package cmdx

// AddClientHooks applies all configured hooks to commands annotated with `client:true`.
func (m *Manager) AddClientHooks() {
func (m *Commander) AddClientHooks() {
for _, cmd := range m.RootCmd.Commands() {
for _, hook := range m.Hooks {
if cmd.Annotations["client"] == "true" {
Expand Down
4 changes: 2 additions & 2 deletions cli/cmdx/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

// AddMarkdownCommand integrates a hidden `markdown` command into the root command.
// This command generates a Markdown documentation tree for all commands in the hierarchy.
func (m *Manager) AddMarkdownCommand(outputPath string) {
func (m *Commander) AddMarkdownCommand(outputPath string) {
markdownCmd := &cobra.Command{
Use: "markdown",
Short: "Generate Markdown documentation for all commands",
Expand All @@ -35,7 +35,7 @@ func (m *Manager) AddMarkdownCommand(outputPath string) {
//
// Returns:
// - An error if any part of the process (file creation, directory creation) fails.
func (m *Manager) generateMarkdownTree(rootOutputPath string, cmd *cobra.Command) error {
func (m *Commander) generateMarkdownTree(rootOutputPath string, cmd *cobra.Command) error {
dirFilePath := filepath.Join(rootOutputPath, cmd.Name())

// Handle subcommands by creating a directory and iterating through subcommands.
Expand Down
10 changes: 5 additions & 5 deletions cli/cmdx/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
//
// Example:
//
// manager := cmdx.NewManager(rootCmd)
// manager := cmdx.NewCommander(rootCmd)
// manager.AddReferenceCommand()
func (m *Manager) AddReferenceCommand() {
func (m *Commander) AddReferenceCommand() {
var isPlain bool
refCmd := &cobra.Command{
Use: "reference",
Expand All @@ -39,7 +39,7 @@ func (m *Manager) AddReferenceCommand() {

// runReferenceCommand handles the output generation for the `reference` command.
// It renders the documentation either as plain markdown or with ANSI color.
func (m *Manager) runReferenceCommand(isPlain *bool) func(cmd *cobra.Command, args []string) {
func (m *Commander) runReferenceCommand(isPlain *bool) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
var (
output string
Expand All @@ -62,7 +62,7 @@ func (m *Manager) runReferenceCommand(isPlain *bool) func(cmd *cobra.Command, ar

// generateReferenceMarkdown generates a complete markdown representation
// of the command tree for the `reference` command.
func (m *Manager) generateReferenceMarkdown() string {
func (m *Commander) generateReferenceMarkdown() string {
buf := bytes.NewBufferString(fmt.Sprintf("# %s reference\n\n", m.RootCmd.Name()))
for _, c := range m.RootCmd.Commands() {
if c.Hidden {
Expand All @@ -75,7 +75,7 @@ func (m *Manager) generateReferenceMarkdown() string {

// generateCommandReference recursively generates markdown for a given command
// and its subcommands.
func (m *Manager) generateCommandReference(w io.Writer, cmd *cobra.Command, depth int) {
func (m *Commander) generateCommandReference(w io.Writer, cmd *cobra.Command, depth int) {
// Name + Description
fmt.Fprintf(w, "%s `%s`\n\n", strings.Repeat("#", depth), cmd.UseLine())
fmt.Fprintf(w, "%s\n\n", cmd.Short)
Expand Down
4 changes: 2 additions & 2 deletions cli/cmdx/topics.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import (
//
// Help topics provide detailed information about specific subjects,
// such as environment variables or configuration.
func (m *Manager) AddHelpTopics() {
func (m *Commander) AddHelpTopics() {
for _, topic := range m.Topics {
m.addHelpTopicCommand(topic)
}
}

// addHelpTopicCommand adds a single help topic command to the CLI.
func (m *Manager) addHelpTopicCommand(topic HelpTopic) {
func (m *Commander) addHelpTopicCommand(topic HelpTopic) {
helpCmd := &cobra.Command{
Use: topic.Name,
Short: topic.Short,
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions cli/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ func WithFlags(pfs *pflag.FlagSet) Opts {

// Load reads the configuration file into the Config's Data map.
func (c *Config) Load(cfg interface{}) error {
loaderOpts := []config.LoaderOption{config.WithFile(c.path)}
loaderOpts := []config.Option{config.WithFile(c.path)}

if c.flags != nil {
loaderOpts = append(loaderOpts, config.WithBindPFlags(c.flags, cfg))
loaderOpts = append(loaderOpts, config.WithFlags(c.flags))
}

loader := config.NewLoader(loaderOpts...)
Expand Down
Loading

0 comments on commit 33b514f

Please sign in to comment.