in Sources/ArgumentParser/Parsing/CommandParser.swift [277:334]
func handleCustomCompletion(_ arguments: [String]) throws {
// Completion functions use a custom format:
//
// <command> ---completion [<subcommand> ...] -- <argument-name> [<completion-text>]
//
// The triple-dash prefix makes '---completion' invalid syntax for regular
// arguments, so it's safe to use for this internal purpose.
guard arguments.first == "---completion"
else { return }
var args = arguments.dropFirst()
var current = commandTree
while let subcommandName = args.popFirst() {
// A double dash separates the subcommands from the argument information
if subcommandName == "--" { break }
guard let nextCommandNode = current.firstChild(withName: subcommandName)
else { throw ParserError.invalidState }
current = nextCommandNode
}
// Some kind of argument name is the next required element
guard let argToMatch = args.popFirst() else {
throw ParserError.invalidState
}
// Completion text is optional here
let completionValues = Array(args)
// Generate the argument set and parse the argument to find in the set
let argset = ArgumentSet(current.element)
let parsedArgument = try! parseIndividualArg(argToMatch, at: 0).first!
// Look up the specified argument and retrieve its custom completion function
let completionFunction: ([String]) -> [String]
switch parsedArgument.value {
case .option(let parsed):
guard let matchedArgument = argset.first(matching: parsed),
case .custom(let f) = matchedArgument.completion.kind
else { throw ParserError.invalidState }
completionFunction = f
case .value(let str):
guard let matchedArgument = argset.firstPositional(named: str),
case .custom(let f) = matchedArgument.completion.kind
else { throw ParserError.invalidState }
completionFunction = f
case .terminator:
throw ParserError.invalidState
}
// Parsing and retrieval successful! We don't want to continue with any
// other parsing here, so after printing the result of the completion
// function, exit with a success code.
let output = completionFunction(completionValues).joined(separator: "\n")
throw ParserError.completionScriptCustomResponse(output)
}