Skip to content

Commit 87d6faf

Browse files
committed
Replace the cursor index within the completing word parameter of custom-completion closures with a String completionPrefix parameter.
Signed-off-by: Ross Goldberg <[email protected]>
1 parent fd0db17 commit 87d6faf

File tree

4 files changed

+31
-15
lines changed

4 files changed

+31
-15
lines changed

Examples/math/Math.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ extension Math.Statistics {
259259
}
260260
}
261261

262-
func customCompletion(_ s: [String], _: Int, _: Int) -> [String] {
262+
func customCompletion(_ s: [String], _: Int, _: String) -> [String] {
263263
(s.last ?? "").starts(with: "a")
264264
? ["aardvark", "aaaaalbert"]
265265
: ["hello", "helicopter", "heliotrope"]

Sources/ArgumentParser/Parsable Properties/CompletionKind.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public struct CompletionKind {
4040
case file(extensions: [String])
4141
case directory
4242
case shellCommand(String)
43-
case custom(@Sendable ([String], Int, Int) -> [String])
43+
case custom(@Sendable ([String], Int, String) -> [String])
4444
case customDeprecated(@Sendable ([String]) -> [String])
4545
}
4646

@@ -126,11 +126,11 @@ public struct CompletionKind {
126126
/// passed to Swift as `"abc\\""def"` (i.e. the Swift String's contents would
127127
/// include all 4 of the double quotes and the 2 consecutive backslashes).
128128
///
129-
/// The first of the two `Int` arguments is the 0-based index of the word
130-
/// for which completions are being requested within the given `[String]`.
129+
/// The second argument (an `Int`) is the 0-based index of the word for which
130+
/// completions are being requested within the given `[String]`.
131131
///
132-
/// The second of the two `Int` arguments is the 0-based index of the shell
133-
/// cursor within the word for which completions are being requested.
132+
/// The third argument (a `String`) is the prefix of the word for which
133+
/// completions are being requested that precedes the cursor.
134134
///
135135
/// ### bash
136136
///
@@ -171,21 +171,21 @@ public struct CompletionKind {
171171
/// character, not as after the backslash.
172172
@preconcurrency
173173
public static func custom(
174-
_ completion: @Sendable @escaping ([String], Int, Int) -> [String]
174+
_ completion: @Sendable @escaping ([String], Int, String) -> [String]
175175
) -> CompletionKind {
176176
CompletionKind(kind: .custom(completion))
177177
}
178178

179179
/// Deprecated; only kept for backwards compatibility.
180180
///
181-
/// The same as `custom(@Sendable @escaping ([String], Int, Int) -> [String])`,
182-
/// except that index arguments are not supplied.
181+
/// The same as `custom(@Sendable @escaping ([String], Int, String) -> [String])`,
182+
/// except that the last two closure arguments are not supplied.
183183
@preconcurrency
184184
@available(
185185
*,
186186
deprecated,
187187
message:
188-
"Provide a three-parameter closure instead. See custom(@Sendable @escaping ([String], Int, Int) -> [String])."
188+
"Provide a three-parameter closure instead. See custom(@Sendable @escaping ([String], Int, String) -> [String])."
189189
)
190190
public static func custom(
191191
_ completion: @Sendable @escaping ([String]) -> [String]

Sources/ArgumentParser/Parsing/CommandParser.swift

+19-3
Original file line numberDiff line numberDiff line change
@@ -456,16 +456,32 @@ extension CommandParser {
456456
}
457457

458458
guard
459-
let s = args.popFirst(),
460-
let cursorIndexWithinCompletingArgument = Int(s)
459+
let arg = args.popFirst(),
460+
let cursorIndexWithinCompletingArgument = Int(arg)
461461
else {
462462
throw ParserError.invalidState
463463
}
464464

465+
let completingPrefix: String
466+
if let completingArgument = args.last {
467+
completingPrefix = String(
468+
completingArgument.prefix(
469+
upTo: completingArgument.index(
470+
completingArgument.startIndex,
471+
offsetBy: cursorIndexWithinCompletingArgument
472+
)
473+
)
474+
)
475+
} else if cursorIndexWithinCompletingArgument == 0 {
476+
completingPrefix = ""
477+
} else {
478+
throw ParserError.invalidState
479+
}
480+
465481
completions = complete(
466482
Array(args),
467483
completingArgumentIndex,
468-
cursorIndexWithinCompletingArgument
484+
completingPrefix
469485
)
470486
case .customDeprecated(let complete):
471487
completions = complete(args)

Sources/ArgumentParserToolInfo/ToolInfo.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ public struct ArgumentInfoV0: Codable, Hashable {
149149
case directory
150150
/// Call the given shell command to generate completions.
151151
case shellCommand(command: String)
152-
/// Generate completions using the given closure including index arguments.
152+
/// Generate completions using the given three-parameter closure.
153153
case custom
154-
/// Generate completions using the given closure without index arguments.
154+
/// Generate completions using the given one-parameter closure.
155155
@available(*, deprecated, message: "Use custom instead.")
156156
case customDeprecated
157157
}

0 commit comments

Comments
 (0)