Skip to content

Commit bfd1d17

Browse files
authored
Improve CompletionKind DocC (#740)
* Fix DocC one-line summary for CompletionKind.file(extensions:). * Use descriptions instead of argument names in DocC for CompletionKind cases. * Improve DocC for CompletionKind.custom(_:). * Update zsh option settings for generated completion scripts. * Separate shell-specific CompletionKind DocC notes under separate subheadings.
1 parent 91af755 commit bfd1d17

File tree

4 files changed

+116
-21
lines changed

4 files changed

+116
-21
lines changed

Sources/ArgumentParser/Completions/ZshCompletionsGenerator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ extension [ParsableCommand.Type] {
9494
\(isRootCommand
9595
? """
9696
emulate -RL zsh -G
97-
setopt extendedglob
97+
setopt extendedglob nullglob numericglobsort
9898
unsetopt aliases banghist
9999
100100
local -xr \(CompletionShell.shellEnvironmentVariableName)=zsh

Sources/ArgumentParser/Parsable Properties/CompletionKind.swift

Lines changed: 113 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,56 +9,151 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12-
/// The type of completion to use for an argument or option.
12+
/// The type of completion to use for an argument or option value.
13+
///
14+
/// For all `CompletionKind`s, the completion shell script is configured with
15+
/// the following settings, which will not affect the requesting shell outside
16+
/// the completion script:
17+
///
18+
/// ### bash
19+
///
20+
/// ```shell
21+
/// shopt -s extglob
22+
/// set +o history +o posix
23+
/// ```
24+
///
25+
/// ### fish
26+
///
27+
/// no settings
28+
///
29+
/// ### zsh
30+
///
31+
/// ```shell
32+
/// emulate -RL zsh -G
33+
/// setopt extendedglob nullglob numericglobsort
34+
/// unsetopt aliases banghist
35+
/// ```
1336
public struct CompletionKind {
1437
internal enum Kind {
15-
/// Use the default completion kind for the value's type.
1638
case `default`
17-
18-
/// Use the specified list of completion strings.
1939
case list([String])
20-
21-
/// Complete file names with the specified extensions.
2240
case file(extensions: [String])
23-
24-
/// Complete directory names that match the specified pattern.
2541
case directory
26-
27-
/// Call the given shell command to generate completions.
2842
case shellCommand(String)
29-
30-
/// Generate completions using the given closure.
3143
case custom(@Sendable ([String]) -> [String])
3244
}
3345

3446
internal var kind: Kind
3547

36-
/// Use the default completion kind for the value's type.
48+
/// Use the default completion kind for the argument's or option value's type.
3749
public static var `default`: CompletionKind {
3850
CompletionKind(kind: .default)
3951
}
4052

41-
/// Use the specified list of completion strings.
53+
/// The completion candidates are the strings in the given array.
54+
///
55+
/// Completion candidates are interpreted by the requesting shell as literals.
56+
/// They must be neither escaped nor quoted; Swift Argument Parser escapes or
57+
/// quotes them as necessary for the requesting shell.
58+
///
59+
/// The completion candidates are included in a completion script when it is
60+
/// generated.
4261
public static func list(_ words: [String]) -> CompletionKind {
4362
CompletionKind(kind: .list(words))
4463
}
4564

46-
/// Complete file names.
65+
/// The completion candidates include directory and file names, the latter
66+
/// filtered by the given list of extensions.
67+
///
68+
/// If the given list of extensions is empty, then file names are not
69+
/// filtered.
70+
///
71+
/// Given file extensions must not include the `.` initial extension
72+
/// separator.
73+
///
74+
/// Given file extensions are parsed by the requesting shell as globs; Swift
75+
/// Argument Parser does not perform any escaping or quoting.
76+
///
77+
/// The directory/file filter and the given list of extensions are included in
78+
/// a completion script when it is generated.
4779
public static func file(extensions: [String] = []) -> CompletionKind {
4880
CompletionKind(kind: .file(extensions: extensions))
4981
}
5082

51-
/// Complete directory names.
83+
/// The completion candidates are directory names.
84+
///
85+
/// The directory filter is included in a completion script when it is
86+
/// generated.
5287
public static var directory: CompletionKind {
5388
CompletionKind(kind: .directory)
5489
}
5590

56-
/// Call the given shell command to generate completions.
91+
/// The completion candidates are specified by the `stdout` output of the
92+
/// given string run as a shell command when a user requests completions.
93+
///
94+
/// Swift Argument Parser does not perform any escaping or quoting on the
95+
/// given shell command.
96+
///
97+
/// The given shell command is included in a completion script when it is
98+
/// generated.
5799
public static func shellCommand(_ command: String) -> CompletionKind {
58100
CompletionKind(kind: .shellCommand(command))
59101
}
60102

61-
/// Generate completions using the given closure.
103+
/// The completion candidates are the strings in the array returned by the
104+
/// given closure when it is executed in response to a user's request for
105+
/// completions.
106+
///
107+
/// Completion candidates are interpreted by the requesting shell as literals.
108+
/// They must be neither escaped nor quoted; Swift Argument Parser escapes or
109+
/// quotes them as necessary for the requesting shell.
110+
///
111+
/// The given closure is evaluated after a user invokes completion in their
112+
/// shell (normally by pressing TAB); it is not evaluated when a completion
113+
/// script is generated.
114+
///
115+
/// The array of strings passed to the given closure contains all the shell
116+
/// words in the command line for the current command at completion
117+
/// invocation; this is exclusive of words for prior or subsequent commands or
118+
/// pipes, but inclusive of redirects and any other command line elements.
119+
/// Each word is its own element in the argument array; they appear in the
120+
/// same order as in the command line. Note that shell words may contain
121+
/// spaces if they are escaped or quoted.
122+
///
123+
/// Shell words are passed to Swift verbatim, without processing or removing
124+
/// any quotes or escapes. For example, the shell word `"abc\\""def"` would be
125+
/// passed to Swift as `"abc\\""def"` (i.e. the Swift String's contents would
126+
/// include all 4 of the double quotes and the 2 consecutive backslashes).
127+
///
128+
/// ### bash
129+
///
130+
/// In bash 3-, a process substitution (`<(…)`) in the command line prevents
131+
/// Swift custom completion functions from being called.
132+
///
133+
/// In bash 4+, a process substitution (`<(…)`) is split into multiple
134+
/// elements in the argument array: one for the starting `<(`, and one for
135+
/// each unescaped/unquoted-space-separated token through the closing `)`.
136+
///
137+
/// In bash, if the cursor is between the backslash and the single quote for
138+
/// the last escaped single quote in a word, all subsequent pipes or other
139+
/// commands are included in the words passed to Swift. This oddity might
140+
/// occur only when additional constraints are met. This or similar oddities
141+
/// might occur in other circumstances.
142+
///
143+
/// ### fish
144+
///
145+
/// In fish 3-, due to a bug, the argument array includes the fish words only
146+
/// through the word being completed. This is fixed in fish 4+.
147+
///
148+
/// In fish, a redirect's symbol is not included, but its source/target is.
149+
///
150+
/// In fish 3-, due to limitations, words are passed to Swift unquoted. For
151+
/// example, the shell word `"abc\\""def"` would be passed to Swift as
152+
/// `abc\def`. This is fixed in fish 4+.
153+
///
154+
/// ### zsh
155+
///
156+
/// In zsh, redirects (both their symbol and source/target) are omitted.
62157
@preconcurrency
63158
public static func custom(
64159
_ completion: @Sendable @escaping ([String]) -> [String]

Tests/ArgumentParserExampleTests/Snapshots/testMathZshCompletionScript().zsh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ __math_custom_complete() {
1616

1717
_math() {
1818
emulate -RL zsh -G
19-
setopt extendedglob
19+
setopt extendedglob nullglob numericglobsort
2020
unsetopt aliases banghist
2121

2222
local -xr SAP_SHELL=zsh

Tests/ArgumentParserUnitTests/Snapshots/testBase_Zsh().zsh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ __base-test_custom_complete() {
1616

1717
_base-test() {
1818
emulate -RL zsh -G
19-
setopt extendedglob
19+
setopt extendedglob nullglob numericglobsort
2020
unsetopt aliases banghist
2121

2222
local -xr SAP_SHELL=zsh

0 commit comments

Comments
 (0)