Fix subcommand locations with NoOptDefValue flags (#391)
If one ran a command like ./root --boolFlag subcmd1 subcmd2 Thing worked fine. The code recognized that --boolFlag followed by a space meant the next word was not the argument to --boolFlag. But other flag types with a NoOptDefValue (like a Count flag) would not ignore the "argument". On a command like: ./root --countflag subcmd1 subcmd2 The processor, when looking for a subcommand, would first throw out the `--countflag subcmd1` and then look for subcmd2 under root. The fix is to ignore the next word after any NoOptDefVal flag, not just boolean flags.
This commit is contained in:
		
							
								
								
									
										16
									
								
								command.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								command.go
									
									
									
									
									
								
							@ -384,20 +384,18 @@ func (c *Command) resetChildrensParents() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Test if the named flag is a boolean flag.
 | 
					func hasNoOptDefVal(name string, f *flag.FlagSet) bool {
 | 
				
			||||||
func isBooleanFlag(name string, f *flag.FlagSet) bool {
 | 
					 | 
				
			||||||
	flag := f.Lookup(name)
 | 
						flag := f.Lookup(name)
 | 
				
			||||||
	if flag == nil {
 | 
						if flag == nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return flag.Value.Type() == "bool"
 | 
						return len(flag.NoOptDefVal) > 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Test if the named flag is a boolean flag.
 | 
					func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool {
 | 
				
			||||||
func isBooleanShortFlag(name string, f *flag.FlagSet) bool {
 | 
					 | 
				
			||||||
	result := false
 | 
						result := false
 | 
				
			||||||
	f.VisitAll(func(f *flag.Flag) {
 | 
						fs.VisitAll(func(flag *flag.Flag) {
 | 
				
			||||||
		if f.Shorthand == name && f.Value.Type() == "bool" {
 | 
							if flag.Shorthand == name && len(flag.NoOptDefVal) > 0 {
 | 
				
			||||||
			result = true
 | 
								result = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@ -423,8 +421,8 @@ func stripFlags(args []string, c *Command) []string {
 | 
				
			|||||||
				inQuote = true
 | 
									inQuote = true
 | 
				
			||||||
			case strings.HasPrefix(y, "--") && !strings.Contains(y, "="):
 | 
								case strings.HasPrefix(y, "--") && !strings.Contains(y, "="):
 | 
				
			||||||
				// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
 | 
									// TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
 | 
				
			||||||
				inFlag = !isBooleanFlag(y[2:], c.Flags())
 | 
									inFlag = !hasNoOptDefVal(y[2:], c.Flags())
 | 
				
			||||||
			case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()):
 | 
								case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !shortHasNoOptDefVal(y[1:], c.Flags()):
 | 
				
			||||||
				inFlag = true
 | 
									inFlag = true
 | 
				
			||||||
			case inFlag:
 | 
								case inFlag:
 | 
				
			||||||
				inFlag = false
 | 
									inFlag = false
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user