func handleCustomCompletion()

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)
  }