1package completion
2
3import (
4 "fmt"
5 "sort"
6 "strings"
7
8 "github.com/spf13/cobra"
9
10 "github.com/MichaelMure/git-bug/bridge"
11 "github.com/MichaelMure/git-bug/bridge/core/auth"
12 "github.com/MichaelMure/git-bug/commands/execenv"
13)
14
15type ValidArgsFunction func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective)
16
17func HandleError(err error) (completions []string, directives cobra.ShellCompDirective) {
18 return nil, cobra.ShellCompDirectiveError
19}
20
21func Bridge(env *execenv.Env) ValidArgsFunction {
22 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
23 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
24 return HandleError(err)
25 }
26 defer func() {
27 _ = env.Backend.Close()
28 }()
29
30 bridges, err := bridge.ConfiguredBridges(env.Backend)
31 if err != nil {
32 return HandleError(err)
33 }
34
35 completions = make([]string, len(bridges))
36 for i, bridge := range bridges {
37 completions[i] = bridge + "\t" + "Bridge"
38 }
39
40 return completions, cobra.ShellCompDirectiveNoFileComp
41 }
42}
43
44func BridgeAuth(env *execenv.Env) ValidArgsFunction {
45 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
46 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
47 return HandleError(err)
48 }
49 defer func() {
50 _ = env.Backend.Close()
51 }()
52
53 creds, err := auth.List(env.Backend)
54 if err != nil {
55 return HandleError(err)
56 }
57
58 completions = make([]string, len(creds))
59 for i, cred := range creds {
60 meta := make([]string, 0, len(cred.Metadata()))
61 for k, v := range cred.Metadata() {
62 meta = append(meta, k+":"+v)
63 }
64 sort.Strings(meta)
65 metaFmt := strings.Join(meta, ",")
66
67 completions[i] = cred.ID().Human() + "\t" + cred.Target() + " " + string(cred.Kind()) + " " + metaFmt
68 }
69
70 return completions, cobra.ShellCompDirectiveNoFileComp
71 }
72}
73
74func From(choices []string) ValidArgsFunction {
75 return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
76 return choices, cobra.ShellCompDirectiveNoFileComp
77 }
78}
79
80func GitRemote(env *execenv.Env) ValidArgsFunction {
81 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
82 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
83 return HandleError(err)
84 }
85 defer func() {
86 _ = env.Backend.Close()
87 }()
88
89 remoteMap, err := env.Backend.GetRemotes()
90 if err != nil {
91 return HandleError(err)
92 }
93 completions = make([]string, 0, len(remoteMap))
94 for remote, url := range remoteMap {
95 completions = append(completions, remote+"\t"+"Remote: "+url)
96 }
97 sort.Strings(completions)
98 return completions, cobra.ShellCompDirectiveNoFileComp
99 }
100}
101
102func Label(env *execenv.Env) ValidArgsFunction {
103 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
104 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
105 return HandleError(err)
106 }
107 defer func() {
108 _ = env.Backend.Close()
109 }()
110
111 labels := env.Backend.Bugs().ValidLabels()
112 completions = make([]string, len(labels))
113 for i, label := range labels {
114 if strings.Contains(label.String(), " ") {
115 completions[i] = fmt.Sprintf("\"%s\"\tLabel", label.String())
116 } else {
117 completions[i] = fmt.Sprintf("%s\tLabel", label.String())
118 }
119 }
120 return completions, cobra.ShellCompDirectiveNoFileComp
121 }
122}
123
124func Ls(env *execenv.Env) ValidArgsFunction {
125 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
126 if strings.HasPrefix(toComplete, "status:") {
127 completions = append(completions, "status:open\tOpen bugs")
128 completions = append(completions, "status:closed\tClosed bugs")
129 return completions, cobra.ShellCompDirectiveDefault
130 }
131
132 byPerson := []string{"author:", "participant:", "actor:"}
133 byLabel := []string{"label:", "no:"}
134 needBackend := false
135 for _, key := range append(byPerson, byLabel...) {
136 if strings.HasPrefix(toComplete, key) {
137 needBackend = true
138 }
139 }
140
141 if needBackend {
142 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
143 return HandleError(err)
144 }
145 defer func() {
146 _ = env.Backend.Close()
147 }()
148 }
149
150 for _, key := range byPerson {
151 if !strings.HasPrefix(toComplete, key) {
152 continue
153 }
154 ids := env.Backend.Identities().AllIds()
155 completions = make([]string, len(ids))
156 for i, id := range ids {
157 user, err := env.Backend.Identities().ResolveExcerpt(id)
158 if err != nil {
159 return HandleError(err)
160 }
161 var handle string
162 if user.Login != "" {
163 handle = user.Login
164 } else {
165 // "author:John Doe" does not work yet, so use the first name.
166 handle = strings.Split(user.Name, " ")[0]
167 }
168 completions[i] = key + handle + "\t" + user.DisplayName()
169 }
170 return completions, cobra.ShellCompDirectiveNoFileComp
171 }
172
173 for _, key := range byLabel {
174 if !strings.HasPrefix(toComplete, key) {
175 continue
176 }
177 labels := env.Backend.Bugs().ValidLabels()
178 completions = make([]string, len(labels))
179 for i, label := range labels {
180 if strings.Contains(label.String(), " ") {
181 completions[i] = key + "\"" + string(label) + "\""
182 } else {
183 completions[i] = key + string(label)
184 }
185 }
186 return completions, cobra.ShellCompDirectiveNoFileComp
187 }
188
189 completions = []string{
190 "actor:\tFilter by actor",
191 "author:\tFilter by author",
192 "label:\tFilter by label",
193 "no:\tExclude bugs by label",
194 "participant:\tFilter by participant",
195 "status:\tFilter by open/close status",
196 "title:\tFilter by title",
197 }
198 return completions, cobra.ShellCompDirectiveNoSpace
199 }
200}
201
202func User(env *execenv.Env) ValidArgsFunction {
203 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
204 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
205 return HandleError(err)
206 }
207 defer func() {
208 _ = env.Backend.Close()
209 }()
210
211 ids := env.Backend.Identities().AllIds()
212 completions = make([]string, len(ids))
213 for i, id := range ids {
214 user, err := env.Backend.Identities().ResolveExcerpt(id)
215 if err != nil {
216 return HandleError(err)
217 }
218 completions[i] = user.Id().Human() + "\t" + user.DisplayName()
219 }
220 return completions, cobra.ShellCompDirectiveNoFileComp
221 }
222}
223
224func UserForQuery(env *execenv.Env) ValidArgsFunction {
225 return func(cmd *cobra.Command, args []string, toComplete string) (completions []string, directives cobra.ShellCompDirective) {
226 if err := execenv.LoadBackend(env)(cmd, args); err != nil {
227 return HandleError(err)
228 }
229 defer func() {
230 _ = env.Backend.Close()
231 }()
232
233 ids := env.Backend.Identities().AllIds()
234 completions = make([]string, len(ids))
235 for i, id := range ids {
236 user, err := env.Backend.Identities().ResolveExcerpt(id)
237 if err != nil {
238 return HandleError(err)
239 }
240 var handle string
241 if user.Login != "" {
242 handle = user.Login
243 } else {
244 // "author:John Doe" does not work yet, so use the first name.
245 handle = strings.Split(user.Name, " ")[0]
246 }
247 completions[i] = handle + "\t" + user.DisplayName()
248 }
249 return completions, cobra.ShellCompDirectiveNoFileComp
250 }
251}