forgejo/vendor/github.com/urfave/cli/fish.go
6543 12a1f914f4
Vendor Update Go Libs (#13166)
* update github.com/alecthomas/chroma v0.8.0 -> v0.8.1

* github.com/blevesearch/bleve v1.0.10 -> v1.0.12

* editorconfig-core-go v2.1.1 -> v2.3.7

* github.com/gliderlabs/ssh v0.2.2 -> v0.3.1

* migrate editorconfig.ParseBytes to Parse

* github.com/shurcooL/vfsgen to 0d455de96546

* github.com/go-git/go-git/v5 v5.1.0 -> v5.2.0

* github.com/google/uuid v1.1.1 -> v1.1.2

* github.com/huandu/xstrings v1.3.0 -> v1.3.2

* github.com/klauspost/compress v1.10.11 -> v1.11.1

* github.com/markbates/goth v1.61.2 -> v1.65.0

* github.com/mattn/go-sqlite3 v1.14.0 -> v1.14.4

* github.com/mholt/archiver v3.3.0 -> v3.3.2

* github.com/microcosm-cc/bluemonday 4f7140c49acb -> v1.0.4

* github.com/minio/minio-go v7.0.4 -> v7.0.5

* github.com/olivere/elastic v7.0.9 -> v7.0.20

* github.com/urfave/cli v1.20.0 -> v1.22.4

* github.com/prometheus/client_golang v1.1.0 -> v1.8.0

* github.com/xanzy/go-gitlab v0.37.0 -> v0.38.1

* mvdan.cc/xurls v2.1.0 -> v2.2.0

Co-authored-by: Lauris BH <lauris@nix.lv>
2020-10-16 01:06:27 -04:00

194 lines
4.1 KiB
Go
Vendored

package cli
import (
"bytes"
"fmt"
"io"
"strings"
"text/template"
)
// ToFishCompletion creates a fish completion string for the `*App`
// The function errors if either parsing or writing of the string fails.
func (a *App) ToFishCompletion() (string, error) {
var w bytes.Buffer
if err := a.writeFishCompletionTemplate(&w); err != nil {
return "", err
}
return w.String(), nil
}
type fishCompletionTemplate struct {
App *App
Completions []string
AllCommands []string
}
func (a *App) writeFishCompletionTemplate(w io.Writer) error {
const name = "cli"
t, err := template.New(name).Parse(FishCompletionTemplate)
if err != nil {
return err
}
allCommands := []string{}
// Add global flags
completions := a.prepareFishFlags(a.VisibleFlags(), allCommands)
// Add help flag
if !a.HideHelp {
completions = append(
completions,
a.prepareFishFlags([]Flag{HelpFlag}, allCommands)...,
)
}
// Add version flag
if !a.HideVersion {
completions = append(
completions,
a.prepareFishFlags([]Flag{VersionFlag}, allCommands)...,
)
}
// Add commands and their flags
completions = append(
completions,
a.prepareFishCommands(a.VisibleCommands(), &allCommands, []string{})...,
)
return t.ExecuteTemplate(w, name, &fishCompletionTemplate{
App: a,
Completions: completions,
AllCommands: allCommands,
})
}
func (a *App) prepareFishCommands(commands []Command, allCommands *[]string, previousCommands []string) []string {
completions := []string{}
for i := range commands {
command := &commands[i]
if command.Hidden {
continue
}
var completion strings.Builder
completion.WriteString(fmt.Sprintf(
"complete -r -c %s -n '%s' -a '%s'",
a.Name,
a.fishSubcommandHelper(previousCommands),
strings.Join(command.Names(), " "),
))
if command.Usage != "" {
completion.WriteString(fmt.Sprintf(" -d '%s'",
escapeSingleQuotes(command.Usage)))
}
if !command.HideHelp {
completions = append(
completions,
a.prepareFishFlags([]Flag{HelpFlag}, command.Names())...,
)
}
*allCommands = append(*allCommands, command.Names()...)
completions = append(completions, completion.String())
completions = append(
completions,
a.prepareFishFlags(command.Flags, command.Names())...,
)
// recursevly iterate subcommands
if len(command.Subcommands) > 0 {
completions = append(
completions,
a.prepareFishCommands(
command.Subcommands, allCommands, command.Names(),
)...,
)
}
}
return completions
}
func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string {
completions := []string{}
for _, f := range flags {
flag, ok := f.(DocGenerationFlag)
if !ok {
continue
}
completion := &strings.Builder{}
completion.WriteString(fmt.Sprintf(
"complete -c %s -n '%s'",
a.Name,
a.fishSubcommandHelper(previousCommands),
))
fishAddFileFlag(f, completion)
for idx, opt := range strings.Split(flag.GetName(), ",") {
if idx == 0 {
completion.WriteString(fmt.Sprintf(
" -l %s", strings.TrimSpace(opt),
))
} else {
completion.WriteString(fmt.Sprintf(
" -s %s", strings.TrimSpace(opt),
))
}
}
if flag.TakesValue() {
completion.WriteString(" -r")
}
if flag.GetUsage() != "" {
completion.WriteString(fmt.Sprintf(" -d '%s'",
escapeSingleQuotes(flag.GetUsage())))
}
completions = append(completions, completion.String())
}
return completions
}
func fishAddFileFlag(flag Flag, completion *strings.Builder) {
switch f := flag.(type) {
case GenericFlag:
if f.TakesFile {
return
}
case StringFlag:
if f.TakesFile {
return
}
case StringSliceFlag:
if f.TakesFile {
return
}
}
completion.WriteString(" -f")
}
func (a *App) fishSubcommandHelper(allCommands []string) string {
fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name)
if len(allCommands) > 0 {
fishHelper = fmt.Sprintf(
"__fish_seen_subcommand_from %s",
strings.Join(allCommands, " "),
)
}
return fishHelper
}
func escapeSingleQuotes(input string) string {
return strings.Replace(input, `'`, `\'`, -1)
}