[GSoC] Interactive mode for swift CLI tool ArgumentParser
メンテナーはふだん 3 日以内に返信
@KthKuang がすでに取り組んでいます。
2022年6月15日 から。
評価
この issue はまだ評価されていません。
説明
Introduction
ArgumentParser provides a straightforward way to declare command-line interfaces in Swift, with the dual goals of making it (1) fast and easy to create (2) high-quality, user-friendly CLI tools.
In order to further achieve these two goals, for this project, we designed and implemented an interactive mode for tools built using ArgumentParser. This mode can prompt for required arguments not given in the initial command, suggest possible corrections when user input is invalid, help users learn to use unfamiliar command line tools by trial and error.
This project was also done as a GSoC (Google Summer of Code) project for which you can find here.
Motivation
With server side swift gaining more and more traction, command line apps built with ArgumentParser can be very useful for automating common tasks to boost developer productivity. But there are still many developers don’t want to bother with the command line, because the help text came in the form of thick manuals and error messages were opaque.
For example, in the past, users would get lengthy error messages when required arguments are not initialized:
$ repeat
Error: Missing expected argument '<phrase>'
USAGE: repeat [--count <count>] [--include-counter] <phrase>
ARGUMENTS:
<phrase> The phrase to repeat.
OPTIONS:
--count <count> The number of times to repeat 'phrase'.
--include-counter Include a counter with each repetition.
-h, --help Show help information.
$ repeat hello world
hello world
hello world
Introducing the conversational nature of interactive mode will be very helpful, it can reduce duplication and provide a conversational CLI which is both easier to write and easier to read:
$ repeat
? Please enter 'phrase': hello world
hello world
hello world
Achievements
Ask prompt the user for input
let age = ask("? Please enter your age: ", type: Int.self)
The above code will generate the following dialog:
? Please enter your age: keith
Error: The type of 'keith' is not Int.
? Please enter your age: 18
Check verifies key directives
guard
check("Are you sure you want to delete all?")
else { return }
print("---DELETE---")
The above code will generate the following dialog:
Are you sure you want to delete all?
? Please enter [y]es or [n]o: y
---DELETE---
Choose provides possible input for the user to choose from
let selected = choose("Please pick your favorite colors: ",
from: ["pink", "purple", "silver"])
The above code will generate the following dialog:
1. pink
2. purple
3. silver
Please pick your favorite colors: pink
Error: 'pink' is not a serial number.
Please pick your favorite colors: 0 1
Error: '0' is not in the range 1 - 3.
Please pick your favorite colors: 1 2
Ask for required @Argument
When parameters similar to the following are not initialized:
@Argument var values: [Int]
The following dialog will be generated automatically:
? Please enter 'values': 1 2 3
Ask for required @Option
When parameters similar to the following are not initialized:
@Option var userName: String
The following dialog will be generated automatically:
? Please enter 'userName': keith
Ask for required @Flag: EnumerableFlag
When parameters similar to the following are not initialized:
enum ColorFlag: EnumerableFlag {
case pink, purple, silver
}
@Flag var color: ColorFlag
The following dialog will be generated automatically:
1. --pink
2. --purple
3. --silver
? Please select 'color': --silver
Error: '--silver' is not a serial number.
? Please select 'color': 4
Error: '4' is not in the range 1 - 3.
? Please select 'color': 3
You select '--silver'.
Asking to retype an invalid value
When parameters similar to the following are not initialized:
@Argument var values: [Int]
The following dialog will be generated automatically:
Please enter 'values': a
Error: The value 'a' is invalid for '<values>'.
? Please replace 'a': 0.1
Error: The value '0.1' is invalid for '<values>'.
? Please replace '0.1': 2
The above is just a partial display of the interfaces. For more details, please click the links in the implementation section.
Implementation
This project is implemented by the following subtasks, you can click to see more detailed API design:
-
#448
-
#450
-
#453
-
#467
-
#469
-
#459
-
#462
Future Work
Fixing misspelled arguments
If a user mistypes an option, flag, or command, the interactive mode should suggest possible correction:
% example --indx 5
Error: Unexpected argument '--indx', did you mean '--index'?
? Please enter [y]es or [n]o: y
Merge two canInteract() functions
Since the two canInteract() one modifies the SplitArguments and the other modifies the ParsedValues, it's not a good idea to merge them for now. But it could make more sense if there's only one path for interactively collecting additional input. So we need find a way to handle .missingValueForOption error without modifying the the original input, which is surely going to be more error prone than operating on the more structured parsed value data.
The discussion under the #451 provides more details.
Related Links
- 主要言語
- Swift
- スター
- 3.8k
- フォーク
- 436
- 平均マージ
- 4日 11時間
- マージ済み PR(30日)
- 2
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
apple/swift-argument-parser のほかの issue
-
documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
apple/swift-argument-parser#1007 ·
メンテナーはふだん 3 日以内に返信
-
Tool tests fail under the Swift Build build system because `generate-manual` & `generate-docc-reference` are not built対応中かも @rgoldberg が 23 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
apple/swift-argument-parser#995 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Consider making `String.wrapped()` and `Platform.terminalWidth` public対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
apple/swift-argument-parser#973 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Include hidden args in completion scripts対応中かも @Galileo927 が 181 日前に担当しました。 オープンgood first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
apple/swift-argument-parser#733 · コメント 7 件 ·
メンテナーはふだん 3 日以内に返信
-
Shared `@OptionGroup` flag is rejected after a subcommand when the root has a passthrough `defaultSubcommand`対応中かも @sean0407 が 22 日前に担当しました。 オープン
難易度 4/5 1〜2日 初心者へのやさしさ 48/100
apple/swift-argument-parser#994 ·
メンテナーはふだん 3 日以内に返信
apple/swift-argument-parser の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
Ebullioscopic/Atoll#930 ·
メンテナーはふだん 2 日以内に返信
-
area:development bug triage:needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
vburojevic/hermes#123 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 70/100
jaywcjlove/awesome-mac#4631 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
Muesli-HQ/muesli#764 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Dynamic Island: "Tools" and "Files" are the Quick panel and the Shelf under other names対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
vorssaint/vorssaint-utils#4162 ·
メンテナーはふだん 2 日以内に返信