Commit 2dfeb7130a8fb97d927a55efa738f110f46cb688

Parents: faa879f9a84d44f9b251410fc923a827a44df1a7

From: Robin Jarry <robin@jarry.cc>
Date: Mon Oct 30 21:05:56 2023 +0700

completion: refactor filter list api
Remove CompletionFromList which is a trivial wrapper around FilterList.

Remove the prefix, suffix and isFuzzy arguments from FilterList.

Replace prefix, suffix by an optional callback to allow post processing
of completion results before presenting them to the user.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Inwit <inwit@sindominio.net>

Stats

commands/account/mkdir.go +7/-3
commands/account/recover.go +1/-1
commands/account/search.go +3/-3
commands/account/sort.go +1/-1
commands/commands.go +6/-12
commands/compose/detach.go +1/-1
commands/compose/header.go +1/-1
commands/compose/multipart.go +1/-1
commands/compose/send.go +1/-1
commands/compose/switch.go +1/-1
commands/ct.go +1/-1
commands/help.go +1/-1
commands/msg/archive.go +1/-1
commands/msg/read.go +1/-1
commands/msgview/open-link.go +1/-1
commands/prompt.go +1/-1
commands/util.go +16/-5

Changeset

  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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
diff --git a/commands/account/mkdir.go b/commands/account/mkdir.go
index 3e546acea4be670f340c7fb33cb130117fe78b1e..af3d1045aaf0b1222b6fe60a7bb25a33ffe9370d 100644
--- a/commands/account/mkdir.go
+++ b/commands/account/mkdir.go
@@ -7,6 +7,7 @@
 	"git.sr.ht/~rjarry/aerc/app"
 	"git.sr.ht/~rjarry/aerc/commands"
 	"git.sr.ht/~rjarry/aerc/worker/types"
+	"git.sr.ht/~rjarry/go-opt"
 )
 
 type MakeDir struct {
@@ -26,10 +27,13 @@ 	acct := app.SelectedAccount()
 	if acct == nil {
 		return nil
 	}
+	sep := app.SelectedAccount().Worker().PathSeparator()
 	return commands.FilterList(
-		acct.Directories().List(), arg, "",
-		app.SelectedAccount().Worker().PathSeparator(),
-		app.SelectedAccountUiConfig().FuzzyComplete)
+		acct.Directories().List(), arg,
+		func(s string) string {
+			return opt.QuoteArg(s) + sep
+		},
+	)
 }
 
 func (m MakeDir) Execute(args []string) error {
diff --git a/commands/account/recover.go b/commands/account/recover.go
index cba6e0cb68cb5b4143ad2307c3bf903ae2720662..a2170edd17ccd953845d8197f06e94ff0407a77b 100644
--- a/commands/account/recover.go
+++ b/commands/account/recover.go
@@ -39,7 +39,7 @@ 	)
 	if err != nil {
 		return nil
 	}
-	return commands.CompletionFromList(files, arg)
+	return commands.FilterList(files, arg, nil)
 }
 
 func (r Recover) Execute(args []string) error {
diff --git a/commands/account/search.go b/commands/account/search.go
index ca1b9684a5de2c11ae8a4f40af9f9e7954791510..10481e8ec30ff13509e9196c6e2e011aeeb0e345 100644
--- a/commands/account/search.go
+++ b/commands/account/search.go
@@ -42,15 +42,15 @@ 	return []string{"search", "filter"}
 }
 
 func (*SearchFilter) CompleteFlag(arg string) []string {
-	return commands.CompletionFromList(commands.GetFlagList(), arg)
+	return commands.FilterList(commands.GetFlagList(), arg, commands.QuoteSpace)
 }
 
 func (*SearchFilter) CompleteAddress(arg string) []string {
-	return commands.CompletionFromList(commands.GetAddress(arg), arg)
+	return commands.FilterList(commands.GetAddress(arg), arg, commands.QuoteSpace)
 }
 
 func (*SearchFilter) CompleteDate(arg string) []string {
-	return commands.CompletionFromList(commands.GetDateList(), arg)
+	return commands.FilterList(commands.GetDateList(), arg, commands.QuoteSpace)
 }
 
 func (s *SearchFilter) ParseRead(arg string) error {
diff --git a/commands/account/sort.go b/commands/account/sort.go
index ccccab25137434b84f3681a3b5ceb272eb813160..3103a3884a22d43881bb5d7eacbc658d881c5a6f 100644
--- a/commands/account/sort.go
+++ b/commands/account/sort.go
@@ -38,7 +38,7 @@ 	"flagged",
 }
 
 func (*Sort) CompleteCriteria(arg string) []string {
-	return commands.CompletionFromList(supportedCriteria, arg)
+	return commands.FilterList(supportedCriteria, arg, commands.QuoteSpace)
 }
 
 func (Sort) Execute(args []string) error {
diff --git a/commands/commands.go b/commands/commands.go
index 9c193018c0a07143c4e0dd546d9e937536f72406..2893aa8257675a46d6a4dd2ac0619afe204cf1b3 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -163,9 +163,7 @@ 			len(search)-len(strings.TrimLeft(search, " ")))
 		options := FilterList(
 			templates.Terms(),
 			strings.TrimSpace(search),
-			"",
-			"",
-			app.SelectedAccountUiConfig().FuzzyComplete,
+			nil,
 		)
 		return options, prefix + padding, true
 	case countLeft == countRight:
@@ -196,7 +194,7 @@ 	acct := app.SelectedAccount()
 	if acct == nil {
 		return make([]string, 0)
 	}
-	return CompletionFromList(acct.Directories().List(), arg)
+	return FilterList(acct.Directories().List(), arg, nil)
 }
 
 func GetTemplates(arg string) []string {
@@ -213,13 +211,7 @@ 	for n := range templates {
 		names = append(names, n)
 	}
 	sort.Strings(names)
-	return CompletionFromList(names, arg)
-}
-
-// CompletionFromList provides a convenience wrapper for commands to use in a
-// complete callback. It simply matches the items provided in valid
-func CompletionFromList(valid []string, arg string) []string {
-	return FilterList(valid, arg, "", "", app.SelectedAccountUiConfig().FuzzyComplete)
+	return FilterList(names, arg, nil)
 }
 
 func GetLabels(arg string) []string {
@@ -240,7 +232,9 @@ 			prefix = "-"
 		}
 		arg = strings.TrimLeft(arg, "+-")
 	}
-	return FilterList(acct.Labels(), arg, prefix, " ", acct.UiConfig().FuzzyComplete)
+	return FilterList(acct.Labels(), arg, func(s string) string {
+		return opt.QuoteArg(prefix+s) + " "
+	})
 }
 
 // hasCaseSmartPrefix checks whether s starts with prefix, using a case
diff --git a/commands/compose/detach.go b/commands/compose/detach.go
index 91cf2a58c8495f9cb6cb46bdaa019d3d160aa26f..0ac3334e6568858fe53c0fbd523f08779ae41d18 100644
--- a/commands/compose/detach.go
+++ b/commands/compose/detach.go
@@ -21,7 +21,7 @@ }
 
 func (*Detach) CompletePath(arg string) []string {
 	composer, _ := app.SelectedTabContent().(*app.Composer)
-	return commands.CompletionFromList(composer.GetAttachments(), arg)
+	return commands.FilterList(composer.GetAttachments(), arg, nil)
 }
 
 func (d Detach) Execute(args []string) error {
diff --git a/commands/compose/header.go b/commands/compose/header.go
index afc27e9257778481989b2eeca3f166d1efdedc03..3283d4e3f73df76f8a66c7675ebe4ec6ab8d0164 100644
--- a/commands/compose/header.go
+++ b/commands/compose/header.go
@@ -38,7 +38,7 @@ 	return "fd"
 }
 
 func (*Header) CompleteHeaders(arg string) []string {
-	return commands.CompletionFromList(headers, arg)
+	return commands.FilterList(headers, arg, commands.QuoteSpace)
 }
 
 func (h Header) Execute(args []string) error {
diff --git a/commands/compose/multipart.go b/commands/compose/multipart.go
index 5b70134264064f3a615c553d13d64d98a7c73636..a004ea2b0d8889a948806da39b30058d33bdf823 100644
--- a/commands/compose/multipart.go
+++ b/commands/compose/multipart.go
@@ -27,7 +27,7 @@ 	var completions []string
 	for mime := range config.Converters {
 		completions = append(completions, mime)
 	}
-	return commands.CompletionFromList(completions, arg)
+	return commands.FilterList(completions, arg, nil)
 }
 
 func (m Multipart) Execute(args []string) error {
diff --git a/commands/compose/send.go b/commands/compose/send.go
index 91fd42bdff98d2f60fbab469f1b8a1a9f34579a6..315b6915f01a9b196680e8946c14da6f00a0b3b1 100644
--- a/commands/compose/send.go
+++ b/commands/compose/send.go
@@ -41,7 +41,7 @@ 	return []string{"send"}
 }
 
 func (*Send) CompleteArchive(arg string) []string {
-	return commands.CompletionFromList(msg.ARCHIVE_TYPES, arg)
+	return commands.FilterList(msg.ARCHIVE_TYPES, arg, nil)
 }
 
 func (*Send) CompleteFolders(arg string) []string {
diff --git a/commands/compose/switch.go b/commands/compose/switch.go
index 637099b593ad928bdf20ad9d9aaae347ea10d466..c71716e07ea7002a38b9232eded480224f0edb9f 100644
--- a/commands/compose/switch.go
+++ b/commands/compose/switch.go
@@ -26,7 +26,7 @@ 	return []string{"switch-account"}
 }
 
 func (*SwitchAccount) CompleteAccount(arg string) []string {
-	return commands.CompletionFromList(app.AccountNames(), arg)
+	return commands.FilterList(app.AccountNames(), arg, nil)
 }
 
 func (s SwitchAccount) Execute(args []string) error {
diff --git a/commands/ct.go b/commands/ct.go
index 2d057b4fc89f02f08cb105ccedb6fc0cce0c1bbc..9948e691bc62428f8d027f5f583cf65a38ba10c4 100644
--- a/commands/ct.go
+++ b/commands/ct.go
@@ -21,7 +21,7 @@ 	return []string{"ct", "change-tab"}
 }
 
 func (*ChangeTab) CompleteTab(arg string) []string {
-	return CompletionFromList(app.TabNames(), arg)
+	return FilterList(app.TabNames(), arg, nil)
 }
 
 func (c ChangeTab) Execute(args []string) error {
diff --git a/commands/help.go b/commands/help.go
index 0733230358d58bf8f9bd87f777143f2b5ec6977c..a3cfff4085af0293a2503754d0d18b3261e21d31 100644
--- a/commands/help.go
+++ b/commands/help.go
@@ -36,7 +36,7 @@ 	return []string{"help"}
 }
 
 func (*Help) CompleteTopic(arg string) []string {
-	return CompletionFromList(pages, arg)
+	return FilterList(pages, arg, nil)
 }
 
 func (h *Help) ParseTopic(arg string) error {
diff --git a/commands/msg/archive.go b/commands/msg/archive.go
index 34cba8b8fbdc50a6f634e178890eca9d7432c7af..5c97e2dac922c97570cb5b713fb11f95ac2e540b 100644
--- a/commands/msg/archive.go
+++ b/commands/msg/archive.go
@@ -43,7 +43,7 @@ 	return []string{"archive"}
 }
 
 func (*Archive) CompleteType(arg string) []string {
-	return commands.CompletionFromList(ARCHIVE_TYPES, arg)
+	return commands.FilterList(ARCHIVE_TYPES, arg, nil)
 }
 
 func (a Archive) Execute(args []string) error {
diff --git a/commands/msg/read.go b/commands/msg/read.go
index 72159a53fb929fbb8640609795852f9c3eb145f1..a92a4d0afef8c3f1e04deb9e5a42a6708375d61c 100644
--- a/commands/msg/read.go
+++ b/commands/msg/read.go
@@ -46,7 +46,7 @@
 var validFlags = []string{"seen", "answered", "flagged"}
 
 func (*FlagMsg) CompleteFlag(arg string) []string {
-	return commands.CompletionFromList(validFlags, arg)
+	return commands.FilterList(validFlags, arg, nil)
 }
 
 // If this was called as 'flag' or 'unflag', without the toggle (-t)
diff --git a/commands/msgview/open-link.go b/commands/msgview/open-link.go
index eceb42321bf17ad238cfc124e597d8c8caebc93b..b13f5d4f82cb7b3a3f06bdb5d17099c501f59b68 100644
--- a/commands/msgview/open-link.go
+++ b/commands/msgview/open-link.go
@@ -27,7 +27,7 @@ func (*OpenLink) CompleteUrl(arg string) []string {
 	mv := app.SelectedTabContent().(*app.MessageViewer)
 	if mv != nil {
 		if p := mv.SelectedMessagePart(); p != nil {
-			return commands.CompletionFromList(p.Links, arg)
+			return commands.FilterList(p.Links, arg, nil)
 		}
 	}
 	return nil
diff --git a/commands/prompt.go b/commands/prompt.go
index d791f7a9f1c86045ce1eb64fbc94b1f8b57d23cf..4fcf8a80c2251c24e73ab7c0ca9f3331d80edc74 100644
--- a/commands/prompt.go
+++ b/commands/prompt.go
@@ -20,7 +20,7 @@ 	return []string{"prompt"}
 }
 
 func (*Prompt) CompleteCommand(arg string) []string {
-	return CompletionFromList(GlobalCommands.Names(), arg)
+	return FilterList(GlobalCommands.Names(), arg, nil)
 }
 
 func (p Prompt) Execute(args []string) error {
diff --git a/commands/util.go b/commands/util.go
index 726669afecc86b8d96a6a2abf40312cfbbb27645..c2c530da8abb7912d716ede64385586d636fb60e 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -228,18 +228,29 @@ 	}
 	return infos, nil
 }
 
+func QuoteSpace(s string) string {
+	return opt.QuoteArg(s) + " "
+}
+
 // FilterList takes a list of valid completions and filters it, either
-// by case smart prefix, or by fuzzy matching, prepending "prefix" to each completion
-func FilterList(valid []string, search, prefix, suffix string, isFuzzy bool) []string {
+// by case smart prefix, or by fuzzy matching
+// An optional post processing function can be passed to prepend, append or
+// quote each value.
+func FilterList(
+	valid []string, search string, postProc func(string) string,
+) []string {
+	if postProc == nil {
+		postProc = opt.QuoteArg
+	}
 	out := make([]string, 0, len(valid))
-	if isFuzzy {
+	if app.SelectedAccountUiConfig().FuzzyComplete {
 		for _, v := range fuzzy.RankFindFold(search, valid) {
-			out = append(out, opt.QuoteArg(prefix+v.Target)+suffix)
+			out = append(out, postProc(v.Target))
 		}
 	} else {
 		for _, v := range valid {
 			if hasCaseSmartPrefix(v, search) {
-				out = append(out, opt.QuoteArg(prefix+v)+suffix)
+				out = append(out, postProc(v))
 			}
 		}
 	}