-
Notifications
You must be signed in to change notification settings - Fork 7
/
set.go
142 lines (118 loc) · 4.23 KB
/
set.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package set
import (
"fmt"
"strings"
"github.com/MakeNowJust/heredoc/v2"
"github.com/google/shlex"
"github.com/reubenmiller/go-c8y-cli/v2/pkg/cmdutil"
"github.com/reubenmiller/go-c8y-cli/v2/pkg/flags"
"github.com/reubenmiller/go-c8y-cli/v2/pkg/iostreams"
"github.com/spf13/cobra"
)
type SetOptions struct {
factory *cmdutil.Factory
IO *iostreams.IOStreams
Name string
Expansion string
IsShell bool
RootCmd *cobra.Command
}
func NewCmdSet(f *cmdutil.Factory, runF func(*SetOptions) error) *cobra.Command {
opts := &SetOptions{
IO: f.IOStreams,
factory: f,
}
cmd := &cobra.Command{
Use: "set <alias> <expansion>",
Short: "Create a shortcut for a c8y command",
Long: heredoc.Doc(`
Declare a word as a command alias that will expand to the specified command(s).
The expansion may specify additional arguments and flags. If the expansion
includes positional placeholders such as '$1', '$2', etc., any extra arguments
that follow the invocation of an alias will be inserted appropriately.
If '--shell' is specified, the alias will be run through a shell interpreter (sh). This allows you
to compose commands with "|" or redirect with ">". Note that extra arguments following the alias
will not be automatically passed to the expanded expression. To have a shell alias receive
arguments, you must explicitly accept them using "$1", "$2", etc., or "$@" to accept all of them.
Platform note: on Windows, shell aliases are executed via "sh" as installed by Git For Windows. If
you have installed git on Windows in some other way, shell aliases may not work for you.
Quotes must always be used when defining a command as in the examples.
`),
Example: heredoc.Doc(`
$ c8y alias set createTestDevice 'devices create --template test.device.json'
$ c8y createTestDevice
#=> c8y devices create --template test.device.json
$ c8y alias set listAlarmsByType 'alarms list --type="$1"'
$ c8y listAlarmsByType myType
#=> c8y alarms list --type="myType"
$ c8y alias set recentEvents 'operations list --dateFrom="-1h"'
$ c8y recentEvents
#=> c8y operations list --dateFrom="-1h"
$ c8y alias set --shell findInAudit 'c8y auditrecords list --dateFrom="-30d" --view auto --includeAll | grep $1'
$ c8y findInAudit deleted
#=> c8y auditrecords list --dateFrom="-30d" --output json --view auto --includeAll | grep deleted
`),
Args: flags.ExactArgsOrExample(2),
RunE: func(cmd *cobra.Command, args []string) error {
opts.RootCmd = cmd.Root()
opts.Name = args[0]
opts.Expansion = args[1]
if runF != nil {
return runF(opts)
}
return setRun(opts)
},
}
cmd.Flags().BoolVarP(&opts.IsShell, "shell", "s", false, "Declare an alias to be passed through a shell interpreter")
return cmd
}
func setRun(opts *SetOptions) error {
cfg, err := opts.factory.Config()
if err != nil {
return err
}
cs := opts.IO.ColorScheme()
aliasCfg := cfg.Aliases()
isTerminal := opts.IO.IsStdoutTTY()
if isTerminal {
fmt.Fprintf(opts.IO.ErrOut, "- Adding alias for %s: %s\n", cs.Bold(opts.Name), cs.Bold(opts.Expansion))
}
expansion := opts.Expansion
isShell := opts.IsShell
if isShell && !strings.HasPrefix(expansion, "!") {
expansion = "!" + expansion
}
isShell = strings.HasPrefix(expansion, "!")
if validCommand(opts.RootCmd, opts.Name) {
return fmt.Errorf("could not create alias: %q is already a c8y command", opts.Name)
}
if !isShell && !validCommand(opts.RootCmd, expansion) {
return fmt.Errorf("could not create alias: %s does not correspond to a c8y command", expansion)
}
successMsg := fmt.Sprintf("%s Added alias.", cs.SuccessIcon())
if oldExpansion, ok := aliasCfg[opts.Name]; ok {
successMsg = fmt.Sprintf("%s Changed alias %s from %s to %s",
cs.SuccessIcon(),
cs.Bold(opts.Name),
cs.Bold(oldExpansion),
cs.Bold(expansion),
)
}
aliasCfg[opts.Name] = expansion
cfg.SetAliases(aliasCfg)
if err := cfg.WritePersistentConfig(); err != nil {
return err
}
if isTerminal {
fmt.Fprintln(opts.IO.ErrOut, successMsg)
}
return nil
}
func validCommand(rootCmd *cobra.Command, expansion string) bool {
split, err := shlex.Split(expansion)
if err != nil {
return false
}
cmd, _, err := rootCmd.Traverse(split)
return err == nil && cmd != rootCmd
}