code.cestus.io/tools/fabricator@v0.4.3/pkg/cmd/cmd.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"code.cestus.io/tools/fabricator/pkg/cmd/help"
    10  	"code.cestus.io/tools/fabricator/pkg/cmd/plugin"
    11  	"code.cestus.io/tools/fabricator/pkg/cmd/version"
    12  	"code.cestus.io/tools/fabricator/pkg/fabricator"
    13  	"github.com/spf13/cobra"
    14  	"github.com/spf13/pflag"
    15  )
    16  
    17  // NewDefaultFabricatorCommand creates the `fabricator` command with default arguments
    18  func NewDefaultFabricatorCommand(ctx context.Context, io fabricator.IOStreams, flagParser fabricator.FlagParser) *cobra.Command {
    19  	return NewDefaultFabricatorCommandWithArgs(ctx, NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes, io), os.Args, io, flagParser)
    20  }
    21  
    22  // NewDefaultFabricatorCommandWithArgs creates the `fabricator` command with arguments
    23  func NewDefaultFabricatorCommandWithArgs(ctx context.Context, pluginHandler plugin.PluginHandler, args []string, io fabricator.IOStreams, flagparser fabricator.FlagParser) *cobra.Command {
    24  	cmd := NewFabricatorCommand(io, flagparser)
    25  
    26  	if pluginHandler == nil {
    27  		return cmd
    28  	}
    29  
    30  	if len(args) > 1 {
    31  		cmdPathPieces := args[1:]
    32  
    33  		// only look for suitable extension executables if
    34  		// the specified command does not already exist
    35  		if _, _, err := cmd.Find(cmdPathPieces); err != nil {
    36  			cmd.AddCommand(plugin.NewPluginWrapper(ctx, io, pluginHandler, flagparser, cmdPathPieces))
    37  		}
    38  	}
    39  
    40  	return cmd
    41  }
    42  
    43  type options struct {
    44  	fabricator.RootOptions
    45  	fabricator.IOStreams
    46  }
    47  
    48  // NewOptions returns initialized Options
    49  func NewOptions(ioStreams fabricator.IOStreams, flagset *pflag.FlagSet) *options {
    50  	o := options{
    51  		IOStreams: ioStreams,
    52  	}
    53  	o.RootOptions.RegisterOptions(flagset)
    54  	return &o
    55  }
    56  
    57  // NewFabricatorCommand creates the `fabricator` command and its nested children.
    58  func NewFabricatorCommand(io fabricator.IOStreams, flagparser fabricator.FlagParser) *cobra.Command {
    59  	// Parent command to which all subcommands are added.
    60  	cmds := &cobra.Command{
    61  		Use:   "fabricator",
    62  		Short: "fabricator is the swiss army knive for code generation",
    63  		Long:  `"fabricator is the swiss army knive for code generation"`,
    64  		Run:   runHelp,
    65  		// Hook before and after Run
    66  		PersistentPreRunE: func(*cobra.Command, []string) error {
    67  			return nil
    68  		},
    69  		PersistentPostRunE: func(*cobra.Command, []string) error {
    70  			return nil
    71  		},
    72  	}
    73  
    74  	flags := cmds.PersistentFlags()
    75  	_ = NewOptions(io, cmds.LocalFlags())
    76  	flags.SetNormalizeFunc(WarnWordSepNormalizeFunc) // Warn for "_" flags
    77  
    78  	// Normalize all flags that are coming from other packages or pre-configurations
    79  	// a.k.a. change all "_" to "-". e.g. glog package
    80  	flags.SetNormalizeFunc(WordSepNormalizeFunc)
    81  
    82  	//cmds.PersistentFlags().AddGoFlagSet(flagset)
    83  
    84  	// From this point and forward we get warnings on flags that contain "_" separators
    85  	cmds.SetGlobalNormalizationFunc(WarnWordSepNormalizeFunc)
    86  
    87  	cmds.AddCommand(plugin.NewCmdPlugin(io, flagparser))
    88  	cmds.AddCommand(version.NewCmdVersion(io))
    89  	help := help.NewHelpCommand(io)
    90  	cmds.AddCommand(help)
    91  	cmds.SetHelpCommand(help)
    92  
    93  	return cmds
    94  }
    95  
    96  func runHelp(cmd *cobra.Command, args []string) {
    97  	cmd.Help()
    98  }
    99  
   100  // WarnWordSepNormalizeFunc changes and warns for flags that contain "_" separators
   101  func WarnWordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
   102  	if strings.Contains(name, "_") {
   103  		nname := strings.Replace(name, "_", "-", -1)
   104  		if _, alreadyWarned := underscoreWarnings[name]; !alreadyWarned {
   105  			fmt.Printf("using an underscore in a flag name is not supported. %s has been converted to %s.", name, nname)
   106  			underscoreWarnings[name] = true
   107  		}
   108  
   109  		return pflag.NormalizedName(nname)
   110  	}
   111  	return pflag.NormalizedName(name)
   112  }
   113  
   114  // WordSepNormalizeFunc changes all flags that contain "_" separators
   115  func WordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
   116  	if strings.Contains(name, "_") {
   117  		return pflag.NormalizedName(strings.Replace(name, "_", "-", -1))
   118  	}
   119  	return pflag.NormalizedName(name)
   120  }
   121  
   122  var underscoreWarnings = make(map[string]bool)