-
Notifications
You must be signed in to change notification settings - Fork 4
/
alias.go
112 lines (101 loc) · 3.89 KB
/
alias.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package cmds
import (
"context"
"fmt"
"github.com/go-go-golems/glazed/pkg/cmds/layers"
"github.com/go-go-golems/glazed/pkg/cmds/parameters"
"github.com/pkg/errors"
)
// CommandAlias defines a struct that should be able to define generic aliases
// for any kind of command line applications, by providing overrides for certain
// flags (prepopulating them with certain flags and arguments, basically)
type CommandAlias struct {
Name string `yaml:"name"`
AliasFor string `yaml:"aliasFor"`
Flags map[string]string `yaml:"flags,omitempty"`
Arguments []string `yaml:"arguments,omitempty"`
AliasedCommand Command `yaml:",omitempty"`
Parents []string `yaml:",omitempty"`
Source string `yaml:",omitempty"`
}
func (a *CommandAlias) String() string {
return fmt.Sprintf("CommandAlias{Name: %s, AliasFor: %s, Parents: %v, Source: %s}",
a.Name, a.AliasFor, a.Parents, a.Source)
}
func (a *CommandAlias) Run(
ctx context.Context,
parsedLayers map[string]*layers.ParsedParameterLayer,
ps map[string]interface{},
gp Processor,
) error {
if a.AliasedCommand == nil {
return errors.New("no aliased command")
}
glazeCommand, ok := a.AliasedCommand.(GlazeCommand)
if !ok {
return errors.New("aliased command is not a GlazeCommand")
}
return glazeCommand.Run(ctx, parsedLayers, ps, gp)
}
func (a *CommandAlias) IsValid() bool {
return a.Name != "" && a.AliasFor != ""
}
// Description returns the CommandDescription of an alias.
// It computes it at runtime by loading the aliased command's Description() and
// making copies of its flags and arguments.
// This is necessary because they get mutated at runtime with various defaults,
// depending on where they come from.
func (a *CommandAlias) Description() *CommandDescription {
s := a.AliasedCommand.Description()
ret := &CommandDescription{
Name: a.Name,
Short: s.Short,
Long: s.Long,
Flags: []*parameters.ParameterDefinition{},
Arguments: []*parameters.ParameterDefinition{},
Layers: s.Layers,
}
for _, flag := range s.Flags {
newFlag := flag.Copy()
// newFlag.Required = false
ret.Flags = append(ret.Flags, newFlag)
}
for _, argument := range s.Arguments {
newArgument := argument.Copy()
// NOTE(2023-02-07, manuel) I don't fully understand what this is referring to anymore,
// but I remember struggling with this in the context of setting and overriding default values.
// Say, if an alias defines --fields id,name and then the user passes in --fields foo,bla
// on top, I remember there being some kind of conflict.
//
// See also the note in glazed_layer.go about checking the argument count. This might all
// refer to overloading arguments, and not just flags. This seems to make sense given the
// talk about argument counts.
//
// ---
//
// TODO(2022-12-22, manuel) this needs to be handled, overriding arguments and figuring out which order
// is a bitch
//
// so iN command.go in cobra, prerun is run before the arg validation is done
// so that we could potentially override the args here
//
// the args are gotten from c.Flags().Args()
//
// it looks like in prerun, we could check if args is empty,
// and if so, pass in our arguments by calling Parse() a second time,
// and then going over the newly set arg?
//
// It's of course going to be relying on cobra internals a bit,
// by assuming that calling parse a second time is not going to interfere with already set flags
// so maybe the best solution is really just to interleave the flags at the outset
// by doing our own little scanning, which is probably useful anyway if done in glazed
// so that we can handle different types of arg parsing.
//
// if defaultValue, ok := a.ArgumentDefaults[argument.Name]; ok {
// newArgument.Default = defaultValue
// }
// newArgument.Required = false
ret.Arguments = append(ret.Arguments, newArgument)
}
return ret
}