Skip to content

Commit

Permalink
(#33) Improve handling of optional flags and other plugin fixes
Browse files Browse the repository at this point in the history
Signed-off-by: R.I.Pienaar <[email protected]>
  • Loading branch information
ripienaar committed May 9, 2023
1 parent 85bd32e commit ae31f87
Showing 1 changed file with 104 additions and 58 deletions.
162 changes: 104 additions & 58 deletions app_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ type pluginDelegator struct {
cumuArgs map[string]*[]string
proxyGlobals []string
globalFlags *flagGroup
flagsIsSet map[string]*bool
parent string
name string
}

func (a *Application) introspectModel() *ApplicationModel {
Expand Down Expand Up @@ -101,6 +104,9 @@ func (c *CmdClause) addFlagsFromModel(model *FlagGroupModel, appFlags *FlagGroup
f.required = flag.Required
f.hidden = flag.Hidden

c.pluginDelegator.flagsIsSet[flag.Name] = func() *bool { v := false; return &v }()
f.setByUser = c.pluginDelegator.flagsIsSet[flag.Name]

switch {
case flag.Boolean && flag.Negatable:
c.pluginDelegator.boolFlags[flag.Name] = f.Bool()
Expand All @@ -117,91 +123,131 @@ func (c *CmdClause) addFlagsFromModel(model *FlagGroupModel, appFlags *FlagGroup
}
}

func (c *CmdClause) addCommandsFromModel(model *CmdGroupModel) {
if model == nil {
return
}
func (c *CmdClause) pluginAction(pd *pluginDelegator) Action {
return func(pc *ParseContext) error {
parts := strings.Split(pc.SelectedCommand.FullCommand(), " ")
args := parts[1:]

for _, cmd := range model.Commands {
cm := c.Command(cmd.Name, cmd.Help)
cm.pluginDelegator = c.pluginDelegator
cm.aliases = cmd.Aliases
cm.helpLong = cmd.HelpLong
cm.hidden = cmd.Hidden
cm.isDefault = cmd.Default

cm.addArgsFromModel(cmd.ArgGroupModel)
cm.addFlagsFromModel(cmd.FlagGroupModel, nil)
cm.addCommandsFromModel(cmd.CmdGroupModel)
cm.Action(func(pc *ParseContext) error {
parts := strings.Split(pc.SelectedCommand.FullCommand(), " ")
args := parts[1:]

for k, v := range cm.pluginDelegator.args {
if v != nil {
args = append(args, fmt.Sprintf("%s=%s", k, *v))
}
for k, v := range pd.args {
if v != nil && *v != "" {
args = append(args, fmt.Sprintf("%s=%s", k, *v))
}
}

for k, v := range cm.pluginDelegator.flags {
if v != nil {
args = append(args, fmt.Sprintf("--%s=%s", k, *v))
}
for k, v := range pd.flags {
if v != nil && *pd.flagsIsSet[k] {
args = append(args, fmt.Sprintf("--%s=%s", k, *v))
}
}

for k, v := range cm.pluginDelegator.cumuFlags {
if v == nil {
continue
}
for k, v := range pd.cumuFlags {
if v == nil {
continue
}

for _, cv := range *v {
for _, cv := range *v {
if v != nil && *pd.flagsIsSet[k] {
args = append(args, fmt.Sprintf("--%s=%s", k, cv))
}
}
}

for k, v := range cm.pluginDelegator.boolFlags {
if *v {
args = append(args, fmt.Sprintf("--%s", k))
} else {
args = append(args, fmt.Sprintf("--no-%s", k))
}
for k, v := range pd.boolFlags {
if !*pd.flagsIsSet[k] {
continue
}

for k, v := range cm.pluginDelegator.unNegBoolFlags {
if *v {
args = append(args, fmt.Sprintf("--%s", k))
}
if *v {
args = append(args, fmt.Sprintf("--%s", k))
} else {
args = append(args, fmt.Sprintf("--no-%s", k))
}
}

for _, f := range cm.pluginDelegator.proxyGlobals {
args = append(args, fmt.Sprintf("--%s=%s", f, cm.pluginDelegator.globalFlags.long[f].value.String()))
for k, v := range pd.unNegBoolFlags {
if !*pd.flagsIsSet[k] {
continue
}

// must be last
for _, v := range cm.pluginDelegator.cumuArgs {
if v != nil {
args = append(args, *v...)
}
if *v {
args = append(args, fmt.Sprintf("--%s", k))
}
}

for _, f := range pd.proxyGlobals {
args = append(args, fmt.Sprintf("--%s=%s", f, pd.globalFlags.long[f].value.String()))
}

if os.Getenv("FISK_DEBUG") != "" {
fmt.Printf("Fisk Plugin Running: %s %s\n", cm.pluginDelegator.command, strings.Join(args, " "))
// must be last
for _, v := range pd.cumuArgs {
if v != nil {
for _, i := range *v {
if i != "" {
args = append(args, i)
}
}
}
cmd := exec.Command(cm.pluginDelegator.command, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Env = os.Environ()
return cmd.Run()
})
}

if os.Getenv("FISK_DEBUG") != "" {
fmt.Printf("Fisk Plugin Running: %s %s\n", pd.command, strings.Join(args, " "))
fmt.Printf("PD: %#v\n", pd)
}

cmd := exec.Command(pd.command, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Env = os.Environ()
return cmd.Run()
}
}

func (c *CmdClause) addCommandsFromModel(model *CmdGroupModel) {
if model == nil {
return
}

for _, cmd := range model.Commands {
pd := pluginDelegator{
parent: c.name,
name: cmd.Name,
command: c.pluginDelegator.command,
flags: map[string]*string{},
flagsIsSet: map[string]*bool{},
cumuFlags: map[string]*[]string{},
args: map[string]*string{},
cumuArgs: map[string]*[]string{},
boolFlags: map[string]*bool{},
unNegBoolFlags: map[string]*bool{},
globalFlags: c.pluginDelegator.globalFlags,
}

cm := c.Command(cmd.Name, cmd.Help)
cm.pluginDelegator = &pd

cm.aliases = cmd.Aliases
cm.helpLong = cmd.HelpLong
cm.hidden = cmd.Hidden
cm.isDefault = cmd.Default

if cmd.CmdGroupModel == nil || len(cmd.CmdGroupModel.Commands) == 0 {
cm.Action(cm.pluginAction(&pd))
}

cm.addArgsFromModel(cmd.ArgGroupModel)
cm.addFlagsFromModel(cmd.FlagGroupModel, nil)
cm.addCommandsFromModel(cmd.CmdGroupModel)
}
}

func (a *Application) registerPluginModel(command string, model *ApplicationModel) (*CmdClause, error) {
cmd := a.Command(model.Name, model.Help)
cmd.pluginDelegator = &pluginDelegator{
parent: a.Name,
command: command,
flags: map[string]*string{},
flagsIsSet: map[string]*bool{},
cumuFlags: map[string]*[]string{},
args: map[string]*string{},
cumuArgs: map[string]*[]string{},
Expand Down

0 comments on commit ae31f87

Please sign in to comment.