apple / apple/swift-argument-parser
Zsh shell completion is broken when short flags exist
- Dominant language
- Swift
- Stars
- 3.8k
- Forks
- 411
- Avg merge
- 7d 14h
- Merged PRs (30d)
- 15
Description
Hi,
This is my first issue in this repository. Thank you for creating and maintaining this great package!
Now onto the problem: I discovered a bug with shell completions. Please see video below:
https://github.com/apple/swift-argument-parser/assets/40357511/6cdeeb81-0ed8-43ee-b0a3-e26780f56540
**ArgumentParser version:**
```
1.3.1
```
**Swift version:**
```
$ swift --version
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
```
### Checklist
- [x] If possible, I've reproduced the issue using the `main` branch of this package
- [x] I've searched for [existing GitHub issues](https://github.com/apple/swift-argument-parser/issues)
### Steps to Reproduce
Use `Zsh` with shell completion enabled.
Then create a simple Swift command line app that uses `swift-argument-parser`.
```
├── Package.resolved
├── Package.swift
├── Sources
│ ├── Example.swift
│ └── Root.swift
```
Package.swift
```swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "SAPbug",
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
],
targets: [
.executableTarget(
name: "SAPbug",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
],
path: "Sources"),
]
)
```
Sources/Root.swift
```swift
import ArgumentParser
@main
struct Root: ParsableCommand {
static var configuration = CommandConfiguration(
commandName: "SAPbug",
version: "1.0.0",
subcommands: [Example.self]
)
@Option(help: ArgumentHelp("Some caches option"))
var entries: String = "caches"
mutating func run() throws {
print("Root run")
}
}
```
Sources/Example.swift
```swift
import ArgumentParser
struct Example: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Some example command to demo bug.",
helpNames: [.long, .customShort("h")]
)
@Option(
help: ArgumentHelp(
"Entries to remove: \"caches\" targets OCI and IPSW caches and \"vms\" targets local VMs."
)
)
var entries: String = "caches"
@Option(
help: ArgumentHelp(
"Remove entries that were last accessed more than n days ago",
valueName: "n"
)
)
var olderThan: UInt?
@Option(help: .hidden)
var cacheBudget: UInt?
@Option(
help: ArgumentHelp(
"Remove the least recently used entries that do not fit the specified space size budget n, expressed in gigabytes",
valueName: "n"
)
)
var spaceBudget: UInt?
@Flag()
var gc: Bool = false
mutating func run() throws {
print("Example run")
}
}
```
Then build the executable:
```console
swift build
```
Then source shell completions into FPATH. In my case I do:
```console
./.build/debug/SAPbug --generate-completion-script zsh > /opt/homebrew/share/zsh/site-functions/_SAPbug && exec zsh
```
Then run `./.build/debug/SAPbug` and try triggering various shell completions
(see video).
### Expected behavior
```
$ ./.build/debug/SAPbug example [tab]
--entries -- Entries to remove: "caches" targets OCI and IPSW caches and "vms" targets local VMs.
--help -- Show help information.
--older-than -- Remove entries that were last accessed more than n days ago
--space-budget -- Remove the least recently used entries that do not fit the specified space size budget n, expressed
--version -- Show the version.
--gc
```
Short options should not be suggested, or alternatively, they should not break
in such a bad way.
### Actual behavior
Completions are broken.
Command invocation
```
$ ./.build/debug/SAPbug example [tab]
--entries
--help
--older-than
--space-budget
--version
-h
-- Entries to remove: "caches" targets OCI and IPSW caches and "vms" targets local VMs.
-- Show help information.
-- Remove entries that were last accessed more than n days ago
-- Remove the least recently used entries that do not fit the specified space size budget n, express
-- Show the version.
--entries
--help
--older-than
--space-budget
--version
-h
-- Entries to remove: "caches" targets OCI and IPSW caches and "vms" targets local VMs.
-- Show help information.
-- Remove entries that were last accessed more than n days ago
-- Remove the least recently used entries that do not fit the specified space size budget n, express
-- Show the version.
--gc
```
Contributor guide
Research direction
Reproduce the issue with Sources/Root.swift and Sources/Example.swift, then run swift build and generate the Zsh completion script with --generate-completion-script zsh. Inspect the generated _SAPbug behavior when short flags exist; done means Zsh suggestions remain usable and match the expected long-option output without duplicated descriptions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift, zsh
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100