Add default completion on commands, test cases, refactor code
This commit is contained in:
parent
fb1421d903
commit
1d7a2b08d6
54
app_test.go
54
app_test.go
@ -221,6 +221,60 @@ func ExampleApp_Run_subcommandNoAction() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleApp_Run_bashComplete_withShortFlag() {
|
||||||
|
os.Args = []string{"greet", "-", "--generate-bash-completion"}
|
||||||
|
|
||||||
|
app := NewApp()
|
||||||
|
app.Name = "greet"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Flags = []Flag{
|
||||||
|
IntFlag{
|
||||||
|
Name: "other,o",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "xyz,x",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
// Output:
|
||||||
|
// --other
|
||||||
|
// -o
|
||||||
|
// --xyz
|
||||||
|
// -x
|
||||||
|
// --help
|
||||||
|
// -h
|
||||||
|
// --version
|
||||||
|
// -v
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleApp_Run_bashComplete_withLongFlag() {
|
||||||
|
os.Args = []string{"greet", "--s", "--generate-bash-completion"}
|
||||||
|
|
||||||
|
app := NewApp()
|
||||||
|
app.Name = "greet"
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
app.Flags = []Flag{
|
||||||
|
IntFlag{
|
||||||
|
Name: "other,o",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "xyz,x",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "some-flag,s",
|
||||||
|
},
|
||||||
|
StringFlag{
|
||||||
|
Name: "similar-flag",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
// Output:
|
||||||
|
// --some-flag
|
||||||
|
// --similar-flag
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleApp_Run_bashComplete() {
|
func ExampleApp_Run_bashComplete() {
|
||||||
// set args for examples sake
|
// set args for examples sake
|
||||||
os.Args = []string{"greet", "--generate-bash-completion"}
|
os.Args = []string{"greet", "--generate-bash-completion"}
|
||||||
|
130
help.go
130
help.go
@ -158,95 +158,80 @@ var shortFlagRegex = regexp.MustCompile(`^-`)
|
|||||||
|
|
||||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||||
func DefaultAppComplete(c *Context) {
|
func DefaultAppComplete(c *Context) {
|
||||||
DefaultAppCompleteWithFlags(nil)(c)
|
DefaultCompleteWithFlags(nil)(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultAppCompleteWithFlags(cmd *Command) func(c *Context) {
|
func printCommandSuggestions(commands []Command, writer io.Writer) {
|
||||||
cliArgContains := func(flagName string) bool {
|
for _, command := range commands {
|
||||||
for _, name := range strings.Split(flagName, ",") {
|
if command.Hidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
|
||||||
|
for _, name := range command.Names() {
|
||||||
|
fmt.Fprintf(writer, "%s:%s\n", name, command.Usage)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, name := range command.Names() {
|
||||||
|
fmt.Fprintf(writer, "%s\n", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cliArgContains(flagName string) bool {
|
||||||
|
for _, name := range strings.Split(flagName, ",") {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
count := utf8.RuneCountInString(name)
|
||||||
|
if count > 2 {
|
||||||
|
count = 2
|
||||||
|
}
|
||||||
|
flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
||||||
|
for _, a := range os.Args {
|
||||||
|
if a == flag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) {
|
||||||
|
cur := shortFlagRegex.ReplaceAllString(lastArg, "")
|
||||||
|
cur = shortFlagRegex.ReplaceAllString(cur, "")
|
||||||
|
for _, flag := range flags {
|
||||||
|
for _, name := range strings.Split(flag.GetName(), ",") {
|
||||||
name = strings.Trim(name, " ")
|
name = strings.Trim(name, " ")
|
||||||
count := utf8.RuneCountInString(name)
|
count := utf8.RuneCountInString(name)
|
||||||
if count > 2 {
|
if count > 2 {
|
||||||
count = 2
|
count = 2
|
||||||
}
|
}
|
||||||
flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
if strings.HasPrefix(lastArg, "--") && count == 1 {
|
||||||
for _, a := range os.Args {
|
continue
|
||||||
if a == flag {
|
}
|
||||||
return true
|
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
||||||
}
|
if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(flag.GetName()) {
|
||||||
|
fmt.Fprintln(writer, flagCompletion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultCompleteWithFlags(cmd *Command) func(c *Context) {
|
||||||
return func(c *Context) {
|
return func(c *Context) {
|
||||||
if len(os.Args) > 2 {
|
if len(os.Args) > 2 {
|
||||||
lastArg := os.Args[len(os.Args)-2]
|
lastArg := os.Args[len(os.Args)-2]
|
||||||
if strings.HasPrefix(lastArg, "-") {
|
if strings.HasPrefix(lastArg, "-") {
|
||||||
lastArg = shortFlagRegex.ReplaceAllString(lastArg, "")
|
printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer)
|
||||||
lastArg = shortFlagRegex.ReplaceAllString(lastArg, "")
|
|
||||||
for _, flag := range c.App.Flags {
|
|
||||||
for _, name := range strings.Split(flag.GetName(), ",") {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
count := utf8.RuneCountInString(name)
|
|
||||||
if count > 2 {
|
|
||||||
count = 2
|
|
||||||
}
|
|
||||||
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
|
||||||
if strings.HasPrefix(name, lastArg) && lastArg != name && !cliArgContains(flag.GetName()) {
|
|
||||||
fmt.Fprintln(c.App.Writer, flagCompletion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
for _, flag := range cmd.Flags {
|
printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer)
|
||||||
for _, name := range strings.Split(flag.GetName(), ",") {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
count := utf8.RuneCountInString(name)
|
|
||||||
if count > 2 {
|
|
||||||
count = 2
|
|
||||||
}
|
|
||||||
flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name)
|
|
||||||
if strings.HasPrefix(name, lastArg) && lastArg != name && !cliArgContains(flag.GetName()) {
|
|
||||||
fmt.Fprintln(c.App.Writer, flagCompletion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
for _, command := range cmd.Subcommands {
|
printCommandSuggestions(cmd.Subcommands, c.App.Writer)
|
||||||
if command.Hidden {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
|
|
||||||
for _, name := range command.Names() {
|
|
||||||
fmt.Fprintf(c.App.Writer, "%s:%s\n", name, command.Usage)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, name := range command.Names() {
|
|
||||||
if name != "h" {
|
|
||||||
fmt.Fprintf(c.App.Writer, "%s\n", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for _, command := range c.App.Commands {
|
printCommandSuggestions(c.App.Commands, c.App.Writer)
|
||||||
if command.Hidden {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" {
|
|
||||||
for _, name := range command.Names() {
|
|
||||||
fmt.Fprintf(c.App.Writer, "%s:%s\n", name, command.Usage)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, name := range command.Names() {
|
|
||||||
fmt.Fprintf(c.App.Writer, "%s\n", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,9 +294,14 @@ func ShowCompletions(c *Context) {
|
|||||||
// ShowCommandCompletions prints the custom completions for a given command
|
// ShowCommandCompletions prints the custom completions for a given command
|
||||||
func ShowCommandCompletions(ctx *Context, command string) {
|
func ShowCommandCompletions(ctx *Context, command string) {
|
||||||
c := ctx.App.Command(command)
|
c := ctx.App.Command(command)
|
||||||
if c != nil && c.BashComplete != nil {
|
if c != nil {
|
||||||
c.BashComplete(ctx)
|
if c.BashComplete != nil {
|
||||||
|
c.BashComplete(ctx)
|
||||||
|
} else {
|
||||||
|
DefaultCompleteWithFlags(c)(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) {
|
||||||
|
Loading…
Reference in New Issue
Block a user