Migrate from urfave/cli to cobra (#1385)

This commit is contained in:
Ta-Ching Chen
2019-11-08 21:22:00 +08:00
committed by GitHub
parent 4b456db517
commit 1888cd2ac7
66 changed files with 2901 additions and 1130 deletions
@@ -0,0 +1,286 @@
/*
Copyright 2019 The Fission Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cobra
import (
"fmt"
"strings"
"time"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
wCli "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate"
cmd "github.com/fission/fission/pkg/fission-cli/cmd"
"github.com/fission/fission/pkg/fission-cli/flag"
)
var _ wCli.Input = &Cli{}
type (
Cli struct {
c *cobra.Command
args []string
}
)
// Parse is only for converting urfave *cli.Context to Input and will be removed in future.
func Parse(cmd *cobra.Command, args []string) wCli.Input {
return Cli{c: cmd, args: args}
}
func Wrapper(action cmd.CommandAction) func(*cobra.Command, []string) error {
return func(c *cobra.Command, args []string) error {
return action(Cli{c: c, args: args})
}
}
func SetFlags(cmd *cobra.Command, flagSet flag.FlagSet) {
aliases := make(map[string]string)
// set required flags
for _, f := range flagSet.Required {
requiredFlags(cmd, f)
for _, alias := range f.Aliases {
aliases[alias] = f.Name
}
}
// set optional flags
for _, f := range flagSet.Optional {
optionalFlags(cmd, f)
for _, alias := range f.Aliases {
aliases[alias] = f.Name
}
}
// set flag alias normalize function
cmd.Flags().SetNormalizeFunc(
func(f *pflag.FlagSet, name string) pflag.NormalizedName {
n, ok := aliases[name]
if ok {
name = n
}
return pflag.NormalizedName(name)
},
)
cmd.Flags().SortFlags = false
}
func optionalFlags(cmd *cobra.Command, flags ...flag.Flag) {
for _, f := range flags {
toCobraFlag(cmd, f)
if f.Deprecated {
usage := fmt.Sprintf("Use --%v instead. The flag still works for now and will be removed in future", f.Substitute)
cmd.Flags().MarkDeprecated(f.Name, usage)
} else if f.Hidden {
cmd.Flags().MarkHidden(f.Name)
}
}
}
func requiredFlags(cmd *cobra.Command, flags ...flag.Flag) {
for _, f := range flags {
toCobraFlag(cmd, f)
cmd.MarkFlagRequired(f.Name)
}
}
func toCobraFlag(cmd *cobra.Command, f flag.Flag) {
// Workaround to pass aliases to templater for generating flag aliases.
if len(f.Aliases) > 0 {
var aliases []string
for _, alias := range f.Aliases {
dash := "--"
if len(alias) == 1 {
dash = "-"
f.Short = alias
}
aliases = append(aliases, dash+alias)
}
// Use separator to separator aliases and usage text.
f.Usage = fmt.Sprintf("%s%s%s",
strings.Join(aliases, helptemplate.AliasSeparator),
helptemplate.AliasSeparator, f.Usage)
}
switch f.Type {
case flag.Bool:
val, ok := f.DefaultValue.(bool)
if !ok {
val = false
}
cmd.Flags().BoolP(f.Name, f.Short, val, f.Usage)
case flag.String:
val, ok := f.DefaultValue.(string)
if !ok {
val = ""
}
cmd.Flags().StringP(f.Name, f.Short, val, f.Usage)
case flag.StringSlice:
val, ok := f.DefaultValue.([]string)
if !ok {
val = []string{}
}
cmd.Flags().StringArrayP(f.Name, f.Short, val, f.Usage)
case flag.Int:
val, ok := f.DefaultValue.(int)
if !ok {
val = 0
}
cmd.Flags().IntP(f.Name, f.Short, val, f.Usage)
case flag.IntSlice:
val, ok := f.DefaultValue.([]int)
if !ok {
val = []int{}
}
cmd.Flags().IntSliceP(f.Name, f.Short, val, f.Usage)
case flag.Int64:
val, ok := f.DefaultValue.(int64)
if !ok {
val = 0
}
cmd.Flags().Int64P(f.Name, f.Short, val, f.Usage)
case flag.Int64Slice:
val, ok := f.DefaultValue.([]int64)
if !ok {
val = []int64{}
}
cmd.Flags().Int64SliceP(f.Name, f.Short, val, f.Usage)
case flag.Float32:
val, ok := f.DefaultValue.(float32)
if !ok {
val = 0
}
cmd.Flags().Float32P(f.Name, f.Short, val, f.Usage)
case flag.Float64:
val, ok := f.DefaultValue.(float64)
if !ok {
val = 0
}
cmd.Flags().Float64P(f.Name, f.Short, val, f.Usage)
case flag.Duration:
val, ok := f.DefaultValue.(time.Duration)
if !ok {
val = 0
}
cmd.Flags().DurationP(f.Name, f.Short, val, f.Usage)
}
}
func WrapperChain(actions ...cmd.CommandAction) func(*cobra.Command, []string) error {
return func(c *cobra.Command, args []string) error {
for _, action := range actions {
err := action(Cli{c: c, args: args})
if err != nil {
return err
}
}
return nil
}
}
func (u Cli) IsSet(key string) bool {
return u.c.Flags().Changed(key)
}
func (u Cli) Bool(key string) bool {
// TODO: ignore the error here, but we should handle it properly in some ways.
v, _ := u.c.Flags().GetBool(key)
return v
}
func (u Cli) String(key string) string {
v, _ := u.c.Flags().GetString(key)
return v
}
func (u Cli) StringSlice(key string) []string {
// difference between StringSlice and StringArray
// --ss="one" --ss="two,three"
// StringSlice* - will result in []string{"one", "two", "three"}
// StringArray* - will result in []s
// https://github.com/spf13/cobra/issues/661#issuecomment-377684634
// Use StringArray here to fit our use case.
v, _ := u.c.Flags().GetStringArray(key)
return v
}
func (u Cli) Int(key string) int {
v, _ := u.c.Flags().GetInt(key)
return v
}
func (u Cli) IntSlice(key string) []int {
v, _ := u.c.Flags().GetIntSlice(key)
return v
}
func (u Cli) Int64(key string) int64 {
v, _ := u.c.Flags().GetInt64(key)
return v
}
func (u Cli) Int64Slice(key string) []int64 {
v, _ := u.c.Flags().GetIntSlice(key)
vals := make([]int64, len(v))
for _, i := range v {
vals = append(vals, int64(i))
}
return vals
}
func (u Cli) GlobalBool(key string) bool {
v, _ := u.c.Flags().GetBool(key)
return v
}
func (u Cli) GlobalString(key string) string {
v, _ := u.c.Flags().GetString(key)
return v
}
func (u Cli) GlobalStringSlice(key string) []string {
v, _ := u.c.Flags().GetStringArray(key)
return v
}
func (u Cli) GlobalInt(key string) int {
v, _ := u.c.Flags().GetInt(key)
return v
}
func (u Cli) GlobalIntSlice(key string) []int {
v, _ := u.c.Flags().GetIntSlice(key)
return v
}
func (u Cli) GlobalInt64(key string) int64 {
v, _ := u.c.Flags().GetInt64(key)
return v
}
func (u Cli) GlobalInt64Slice(key string) []int64 {
v, _ := u.c.Flags().GetInt64Slice(key)
return v
}
func (u Cli) Duration(key string) time.Duration {
v, _ := u.c.Flags().GetDuration(key)
return v
}
@@ -0,0 +1,61 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Original file location: https://github.com/kubernetes/kubectl/tree/master/pkg/util/templates
package helptemplate
import (
"github.com/spf13/cobra"
)
type CommandGroup struct {
Message string
Commands []*cobra.Command
}
type CommandGroups []CommandGroup
func (g CommandGroups) Add(c *cobra.Command) {
for _, group := range g {
c.AddCommand(group.Commands...)
}
}
func (g CommandGroups) Has(c *cobra.Command) bool {
for _, group := range g {
for _, command := range group.Commands {
if command == c {
return true
}
}
}
return false
}
func AddAdditionalCommands(g CommandGroups, message string, cmds []*cobra.Command) CommandGroups {
group := CommandGroup{Message: message}
for _, c := range cmds {
// Don't show commands that have no short description
if !g.Has(c) && len(c.Short) != 0 {
group.Commands = append(group.Commands, c)
}
}
if len(group.Commands) == 0 {
return g
}
return append(g, group)
}
@@ -0,0 +1,28 @@
/*
Copyright 2019 The Fission Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package helptemplate
import (
"github.com/spf13/cobra"
)
func CreateCmdGroup(msg string, cmds ...*cobra.Command) CommandGroup {
return CommandGroup{
Message: msg,
Commands: cmds,
}
}
@@ -0,0 +1,347 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Original file location: https://github.com/kubernetes/kubectl/tree/master/pkg/util/templates
package helptemplate
import (
"bytes"
"fmt"
"os"
"strings"
"text/template"
"unicode"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
)
const AliasSeparator = " |:|: "
type FlagExposer interface {
ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer
}
func ActsAsRootCommand(cmd *cobra.Command, filters []string, groups ...CommandGroup) FlagExposer {
if cmd == nil {
panic("nil root command")
}
templater := &templater{
RootCmd: cmd,
UsageTemplate: MainUsageTemplate(),
HelpTemplate: MainHelpTemplate(),
CommandGroups: groups,
Filtered: filters,
}
cmd.SetFlagErrorFunc(templater.FlagErrorFunc())
cmd.SetUsageFunc(templater.UsageFunc())
cmd.SetHelpFunc(templater.HelpFunc())
return templater
}
func UseOptionsTemplates(cmd *cobra.Command) {
templater := &templater{
UsageTemplate: OptionsUsageTemplate(),
HelpTemplate: OptionsHelpTemplate(),
}
cmd.SetUsageFunc(templater.UsageFunc())
cmd.SetHelpFunc(templater.HelpFunc())
}
type templater struct {
UsageTemplate string
HelpTemplate string
RootCmd *cobra.Command
CommandGroups
Filtered []string
}
func (templater *templater) FlagErrorFunc(exposedFlags ...string) func(*cobra.Command, error) error {
return func(c *cobra.Command, err error) error {
c.SilenceUsage = true
switch c.CalledAs() {
case "options":
return fmt.Errorf("%s\nRun '%s' without flags", err, c.CommandPath())
default:
return fmt.Errorf("%s\nSee '%s --help' for usage", err, c.CommandPath())
}
}
}
func (templater *templater) ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer {
cmd.SetUsageFunc(templater.UsageFunc(flags...))
return templater
}
func (templater *templater) HelpFunc() func(*cobra.Command, []string) {
return func(c *cobra.Command, s []string) {
t := template.New("help")
t.Funcs(templater.templateFuncs())
template.Must(t.Parse(templater.HelpTemplate))
err := t.Execute(os.Stdout, c)
if err != nil {
c.Println(err)
}
}
}
func (templater *templater) UsageFunc(exposedFlags ...string) func(*cobra.Command) error {
return func(c *cobra.Command) error {
t := template.New("usage")
t.Funcs(templater.templateFuncs(exposedFlags...))
template.Must(t.Parse(templater.UsageTemplate))
return t.Execute(os.Stdout, c)
}
}
func (templater *templater) templateFuncs(exposedFlags ...string) template.FuncMap {
return template.FuncMap{
"trim": strings.TrimSpace,
"trimRight": func(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) },
"trimLeft": func(s string) string { return strings.TrimLeftFunc(s, unicode.IsSpace) },
"gt": cobra.Gt,
"eq": cobra.Eq,
"rpad": rpad,
"appendIfNotPresent": appendIfNotPresent,
"flagsNotIntersected": flagsNotIntersected,
"visibleFlags": visibleFlags,
"flagsUsages": flagsUsages,
"cmdGroups": templater.cmdGroups,
"cmdGroupsString": templater.cmdGroupsString,
"rootCmd": templater.rootCmdName,
"isRootCmd": templater.isRootCmd,
"optionsCmdFor": templater.optionsCmdFor,
"usageLine": templater.usageLine,
"exposed": func(c *cobra.Command) *flag.FlagSet {
exposed := flag.NewFlagSet("exposed", flag.ContinueOnError)
exposed.SortFlags = false
if len(exposedFlags) > 0 {
for _, name := range exposedFlags {
if flag := c.Flags().Lookup(name); flag != nil {
exposed.AddFlag(flag)
}
}
}
return exposed
},
}
}
func (templater *templater) cmdGroups(c *cobra.Command, all []*cobra.Command) []CommandGroup {
if len(templater.CommandGroups) > 0 && c == templater.RootCmd {
all = filter(all, templater.Filtered...)
return AddAdditionalCommands(templater.CommandGroups, "Other Commands:", all)
}
all = filter(all, "options")
return []CommandGroup{
{
Message: "Available Commands:",
Commands: all,
},
}
}
func (t *templater) cmdGroupsString(c *cobra.Command) string {
groups := []string{}
for _, cmdGroup := range t.cmdGroups(c, c.Commands()) {
cmds := []string{cmdGroup.Message}
for _, cmd := range cmdGroup.Commands {
if cmd.IsAvailableCommand() {
cmds = append(cmds, " "+rpad(cmd.Name(), cmd.NamePadding())+" "+cmd.Short)
}
}
groups = append(groups, strings.Join(cmds, "\n"))
}
return strings.Join(groups, "\n\n")
}
func (t *templater) rootCmdName(c *cobra.Command) string {
return t.rootCmd(c).CommandPath()
}
func (t *templater) isRootCmd(c *cobra.Command) bool {
return t.rootCmd(c) == c
}
func (t *templater) parents(c *cobra.Command) []*cobra.Command {
parents := []*cobra.Command{c}
for current := c; !t.isRootCmd(current) && current.HasParent(); {
current = current.Parent()
parents = append(parents, current)
}
return parents
}
func (t *templater) rootCmd(c *cobra.Command) *cobra.Command {
if c != nil && !c.HasParent() {
return c
}
if t.RootCmd == nil {
panic("nil root cmd")
}
return t.RootCmd
}
func (t *templater) optionsCmdFor(c *cobra.Command) string {
if !c.Runnable() {
return ""
}
rootCmdStructure := t.parents(c)
for i := len(rootCmdStructure) - 1; i >= 0; i-- {
cmd := rootCmdStructure[i]
if _, _, err := cmd.Find([]string{"options"}); err == nil {
return cmd.CommandPath() + " options"
}
}
return ""
}
func (t *templater) usageLine(c *cobra.Command) string {
usage := c.UseLine()
suffix := "[options]"
if c.HasFlags() && !strings.Contains(usage, suffix) {
usage += " " + suffix
}
return usage
}
func flagsUsages(f *flag.FlagSet) string {
x := new(bytes.Buffer)
var flags [][]string
var maxPadLength int
f.VisitAll(func(flag *flag.Flag) {
if flag.Hidden {
return
}
format := "--%s=%s"
if flag.Value.Type() == "string" {
format = "--%s='%s'"
}
var usage string
var aliases []string
// extract aliases from usage text
u := strings.Split(flag.Usage, AliasSeparator)
if len(u) == 1 {
// means the flag has no aliases
usage = u[0]
format = format + " %s"
} else {
usage = u[len(u)-1]
aliases = u[0 : len(u)-1]
format = format + " (%s)"
}
aliasesStr := strings.Join(aliases, ", ")
flagName := fmt.Sprintf(format, flag.Name, flag.DefValue, aliasesStr)
flags = append(flags, []string{flagName, usage})
if len(flagName) > maxPadLength {
maxPadLength = len(flagName)
}
})
for _, v := range flags {
name := rpad(v[0], maxPadLength)
fmt.Fprintf(x, " %s %s\n", name, toFitUsagePadding(v[1], maxPadLength))
}
return x.String()
}
func toFitUsagePadding(u string, pad int) (usage string) {
us := strings.Split(u, " ")
length := pad
for _, chunk := range us {
if length+len(chunk) > 100 {
usage = usage + "\n" + lpad(chunk, pad+len(chunk)+4) // 4 for whitespace in format
length = pad
continue
}
usage = usage + " " + chunk
length += len(chunk) + 1 // 1 is for whitespace
}
return usage
}
func rpad(s string, padding int) string {
template := fmt.Sprintf("%%-%ds", padding)
return fmt.Sprintf(template, s)
}
func lpad(s string, padding int) string {
template := fmt.Sprintf("%%%ds", padding)
return fmt.Sprintf(template, s)
}
func appendIfNotPresent(s, stringToAppend string) string {
if strings.Contains(s, stringToAppend) {
return s
}
return s + " " + stringToAppend
}
func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet {
f := flag.NewFlagSet("notIntersected", flag.ContinueOnError)
f.SortFlags = false // disable sorting flags
l.VisitAll(func(flag *flag.Flag) {
if r.Lookup(flag.Name) == nil {
f.AddFlag(flag)
}
})
return f
}
func visibleFlags(l *flag.FlagSet) *flag.FlagSet {
hidden := "help"
f := flag.NewFlagSet("visible", flag.ContinueOnError)
f.SortFlags = false // disable sorting flags
l.VisitAll(func(flag *flag.Flag) {
if flag.Name != hidden {
f.AddFlag(flag)
}
})
return f
}
func filter(cmds []*cobra.Command, names ...string) []*cobra.Command {
out := []*cobra.Command{}
for _, c := range cmds {
if c.Hidden {
continue
}
skip := false
for _, name := range names {
if name == c.Name() {
skip = true
break
}
}
if skip {
continue
}
out = append(out, c)
}
return out
}
@@ -0,0 +1,104 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Original file location: https://github.com/kubernetes/kubectl/tree/master/pkg/util/templates
package helptemplate
import (
"strings"
"unicode"
)
const (
// SectionVars is the help template section that declares variables to be used in the template.
SectionVars = `{{$isRootCmd := isRootCmd .}}` +
`{{$rootCmd := rootCmd .}}` +
`{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` +
`{{$explicitlyExposedFlags := exposed .}}` +
`{{$optionsCmdFor := optionsCmdFor .}}` +
`{{$usageLine := usageLine .}}`
// SectionAliases is the help template section that displays command aliases.
SectionAliases = `{{if gt .Aliases 0}}Aliases:
{{.NameAndAliases}}
{{end}}`
// SectionExamples is the help template section that displays command examples.
SectionExamples = `{{if .HasExample}}Examples:
{{trimRight .Example}}
{{end}}`
// SectionSubcommands is the help template section that displays the command's subcommands.
SectionSubcommands = `{{if .HasAvailableSubCommands}}{{cmdGroupsString .}}
{{end}}`
// SectionFlags is the help template section that displays the command's flags.
SectionFlags = `{{ if or $visibleFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options:
{{ if $visibleFlags.HasFlags}}{{trimRight (flagsUsages $visibleFlags)}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{ if $visibleFlags.HasFlags}}
{{end}}{{trimRight (flagsUsages $explicitlyExposedFlags)}}{{end}}
{{end}}`
// SectionUsage is the help template section that displays the command's usage.
SectionUsage = `{{if and .Runnable (ne .UseLine "") (ne .UseLine $rootCmd)}}Usage:
{{$usageLine}}
{{end}}`
// SectionTipsHelp is the help template section that displays the '--help' hint.
SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} <command> --help" for more information about a given command.{{end}}`
// SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags.
SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands).{{end}}`
)
// MainHelpTemplate if the template for 'help' used by most commands.
func MainHelpTemplate() string {
return `{{with or .Long .Short }}{{. | trimRight}}
{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
}
// MainUsageTemplate if the template for 'usage' used by most commands.
func MainUsageTemplate() string {
sections := []string{
"\n",
SectionVars,
SectionAliases,
SectionExamples,
SectionSubcommands,
SectionFlags,
SectionUsage,
SectionTipsHelp,
SectionTipsGlobalOptions,
}
return strings.TrimRightFunc(strings.Join(sections, ""), unicode.IsSpace)
}
// OptionsHelpTemplate if the template for 'help' used by the 'options' command.
func OptionsHelpTemplate() string {
return ""
}
// OptionsUsageTemplate if the template for 'usage' used by the 'options' command.
func OptionsUsageTemplate() string {
return `{{ if .HasInheritedFlags}}The following options can be passed to any command:
{{flagsUsages .InheritedFlags}}{{end}}`
}
@@ -1,107 +0,0 @@
/*
Copyright 2019 The Fission Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package urfavecli
import (
"time"
"github.com/urfave/cli"
fCli "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
"github.com/fission/fission/pkg/fission-cli/cmd"
)
var _ fCli.Input = &Cli{}
type Cli struct {
c *cli.Context
}
// Parse is only for converting urfave *cli.Context to Input and will be removed in future.
func Parse(c *cli.Context) fCli.Input {
return Cli{c: c}
}
func Wrapper(action cmd.CommandAction) func(*cli.Context) error {
return func(c *cli.Context) error {
return action(Cli{c: c})
}
}
func (u Cli) IsSet(key string) bool {
return u.c.IsSet(key)
}
func (u Cli) Bool(key string) bool {
return u.c.Bool(key)
}
func (u Cli) String(key string) string {
return u.c.String(key)
}
func (u Cli) StringSlice(key string) []string {
return u.c.StringSlice(key)
}
func (u Cli) Int(key string) int {
return u.c.Int(key)
}
func (u Cli) IntSlice(key string) []int {
return u.c.IntSlice(key)
}
func (u Cli) Int64(key string) int64 {
return u.c.Int64(key)
}
func (u Cli) Int64Slice(key string) []int64 {
return u.c.Int64Slice(key)
}
func (u Cli) GlobalBool(key string) bool {
return u.c.GlobalBool(key)
}
func (u Cli) GlobalString(key string) string {
return u.c.GlobalString(key)
}
func (u Cli) GlobalStringSlice(key string) []string {
return u.c.GlobalStringSlice(key)
}
func (u Cli) GlobalInt(key string) int {
return u.c.GlobalInt(key)
}
func (u Cli) GlobalIntSlice(key string) []int {
return u.c.GlobalIntSlice(key)
}
func (u Cli) GlobalInt64(key string) int64 {
return u.c.GlobalInt64(key)
}
func (u Cli) GlobalInt64Slice(key string) []int64 {
return u.c.GlobalInt64Slice(key)
}
func (u Cli) Duration(key string) time.Duration {
return u.c.Duration(key)
}