vendor/github.com/spf13/cobra/flag_groups.go
author Mikael Berthe <mikael@lilotux.net>
Sat, 04 Feb 2023 12:58:35 +0100
changeset 265 05c40b36d3b2
parent 260 445e01aede7e
permissions -rw-r--r--
Bump to version 3.0.0-dev, using madon v3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
265
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents: 260
diff changeset
     1
// Copyright 2013-2022 The Cobra Authors
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     2
//
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
// Licensed under the Apache License, Version 2.0 (the "License");
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
// you may not use this file except in compliance with the License.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
// You may obtain a copy of the License at
265
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents: 260
diff changeset
     6
//
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents: 260
diff changeset
     7
//      http://www.apache.org/licenses/LICENSE-2.0
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
//
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
// Unless required by applicable law or agreed to in writing, software
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
// distributed under the License is distributed on an "AS IS" BASIS,
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
// See the License for the specific language governing permissions and
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
// limitations under the License.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    15
package cobra
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    16
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    17
import (
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
	"fmt"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
	"sort"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
	"strings"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    22
	flag "github.com/spf13/pflag"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
const (
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    26
	requiredAsGroup   = "cobra_annotation_required_if_others_set"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
	mutuallyExclusive = "cobra_annotation_mutually_exclusive"
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
// MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
// if the command is invoked with a subset (but not all) of the given flags.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
func (c *Command) MarkFlagsRequiredTogether(flagNames ...string) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
	c.mergePersistentFlags()
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
	for _, v := range flagNames {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
		f := c.Flags().Lookup(v)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
		if f == nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
			panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v))
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
		if err := c.Flags().SetAnnotation(v, requiredAsGroup, append(f.Annotations[requiredAsGroup], strings.Join(flagNames, " "))); err != nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
			// Only errs if the flag isn't found.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
			panic(err)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
// MarkFlagsMutuallyExclusive marks the given flags with annotations so that Cobra errors
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
// if the command is invoked with more than one flag from the given set of flags.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
func (c *Command) MarkFlagsMutuallyExclusive(flagNames ...string) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
	c.mergePersistentFlags()
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
	for _, v := range flagNames {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
		f := c.Flags().Lookup(v)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    52
		if f == nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    53
			panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v))
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    54
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    55
		// Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
		if err := c.Flags().SetAnnotation(v, mutuallyExclusive, append(f.Annotations[mutuallyExclusive], strings.Join(flagNames, " "))); err != nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
			panic(err)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
265
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents: 260
diff changeset
    62
// ValidateFlagGroups validates the mutuallyExclusive/requiredAsGroup logic and returns the
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
// first error encountered.
265
05c40b36d3b2 Bump to version 3.0.0-dev, using madon v3
Mikael Berthe <mikael@lilotux.net>
parents: 260
diff changeset
    64
func (c *Command) ValidateFlagGroups() error {
260
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
	if c.DisableFlagParsing {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
		return nil
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
	flags := c.Flags()
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
	// groupStatus format is the list of flags as a unique ID,
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
	// then a map of each flag name and whether it is set or not.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
	groupStatus := map[string]map[string]bool{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
	mutuallyExclusiveGroupStatus := map[string]map[string]bool{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
	flags.VisitAll(func(pflag *flag.Flag) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
		processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
		processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    78
	})
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    79
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    80
	if err := validateRequiredFlagGroups(groupStatus); err != nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    81
		return err
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    82
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    83
	if err := validateExclusiveFlagGroups(mutuallyExclusiveGroupStatus); err != nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    84
		return err
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    85
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    86
	return nil
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    87
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    88
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    89
func hasAllFlags(fs *flag.FlagSet, flagnames ...string) bool {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    90
	for _, fname := range flagnames {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    91
		f := fs.Lookup(fname)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    92
		if f == nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    93
			return false
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    94
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    95
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    96
	return true
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    97
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
func processFlagForGroupAnnotation(flags *flag.FlagSet, pflag *flag.Flag, annotation string, groupStatus map[string]map[string]bool) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
	groupInfo, found := pflag.Annotations[annotation]
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
	if found {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   102
		for _, group := range groupInfo {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   103
			if groupStatus[group] == nil {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   104
				flagnames := strings.Split(group, " ")
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   105
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   106
				// Only consider this flag group at all if all the flags are defined.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
				if !hasAllFlags(flags, flagnames...) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
					continue
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
				}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
				groupStatus[group] = map[string]bool{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
				for _, name := range flagnames {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
					groupStatus[group][name] = false
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
				}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
			}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
			groupStatus[group][pflag.Name] = pflag.Changed
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   118
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   119
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   120
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   121
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   122
func validateRequiredFlagGroups(data map[string]map[string]bool) error {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   123
	keys := sortedKeys(data)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   124
	for _, flagList := range keys {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   125
		flagnameAndStatus := data[flagList]
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   126
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   127
		unset := []string{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   128
		for flagname, isSet := range flagnameAndStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   129
			if !isSet {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   130
				unset = append(unset, flagname)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   131
			}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   132
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   133
		if len(unset) == len(flagnameAndStatus) || len(unset) == 0 {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   134
			continue
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   135
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   136
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   137
		// Sort values, so they can be tested/scripted against consistently.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   138
		sort.Strings(unset)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   139
		return fmt.Errorf("if any flags in the group [%v] are set they must all be set; missing %v", flagList, unset)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   140
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   141
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   142
	return nil
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   143
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   144
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   145
func validateExclusiveFlagGroups(data map[string]map[string]bool) error {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   146
	keys := sortedKeys(data)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   147
	for _, flagList := range keys {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   148
		flagnameAndStatus := data[flagList]
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   149
		var set []string
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   150
		for flagname, isSet := range flagnameAndStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   151
			if isSet {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   152
				set = append(set, flagname)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   153
			}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   154
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   155
		if len(set) == 0 || len(set) == 1 {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   156
			continue
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   157
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   158
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   159
		// Sort values, so they can be tested/scripted against consistently.
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   160
		sort.Strings(set)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   161
		return fmt.Errorf("if any flags in the group [%v] are set none of the others can be; %v were all set", flagList, set)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   162
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   163
	return nil
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   164
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   165
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   166
func sortedKeys(m map[string]map[string]bool) []string {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   167
	keys := make([]string, len(m))
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   168
	i := 0
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   169
	for k := range m {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   170
		keys[i] = k
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   171
		i++
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   172
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   173
	sort.Strings(keys)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   174
	return keys
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   175
}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   176
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   177
// enforceFlagGroupsForCompletion will do the following:
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   178
// - when a flag in a group is present, other flags in the group will be marked required
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   179
// - when a flag in a mutually exclusive group is present, other flags in the group will be marked as hidden
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   180
// This allows the standard completion logic to behave appropriately for flag groups
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   181
func (c *Command) enforceFlagGroupsForCompletion() {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   182
	if c.DisableFlagParsing {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   183
		return
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   184
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   185
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   186
	flags := c.Flags()
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   187
	groupStatus := map[string]map[string]bool{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   188
	mutuallyExclusiveGroupStatus := map[string]map[string]bool{}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   189
	c.Flags().VisitAll(func(pflag *flag.Flag) {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   190
		processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   191
		processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   192
	})
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   193
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   194
	// If a flag that is part of a group is present, we make all the other flags
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   195
	// of that group required so that the shell completion suggests them automatically
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   196
	for flagList, flagnameAndStatus := range groupStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   197
		for _, isSet := range flagnameAndStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   198
			if isSet {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   199
				// One of the flags of the group is set, mark the other ones as required
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   200
				for _, fName := range strings.Split(flagList, " ") {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   201
					_ = c.MarkFlagRequired(fName)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   202
				}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   203
			}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   204
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   205
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   206
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   207
	// If a flag that is mutually exclusive to others is present, we hide the other
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   208
	// flags of that group so the shell completion does not suggest them
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   209
	for flagList, flagnameAndStatus := range mutuallyExclusiveGroupStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   210
		for flagName, isSet := range flagnameAndStatus {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   211
			if isSet {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   212
				// One of the flags of the mutually exclusive group is set, mark the other ones as hidden
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   213
				// Don't mark the flag that is already set as hidden because it may be an
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   214
				// array or slice flag and therefore must continue being suggested
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   215
				for _, fName := range strings.Split(flagList, " ") {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   216
					if fName != flagName {
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   217
						flag := c.Flags().Lookup(fName)
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   218
						flag.Hidden = true
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   219
					}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   220
				}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   221
			}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   222
		}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   223
	}
445e01aede7e Update vendor directory
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   224
}