Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
swift-argument-parserで 簡単 CLI ツール作り
Search
ry-itto
July 18, 2020
Programming
170
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
swift-argument-parserで 簡単 CLI ツール作り
ry-itto
July 18, 2020
More Decks by ry-itto
See All by ry-itto
決定版!?OSSアプリプロジェクトでのBeta版アプリ配布の方法「Xcode Cloud + TestFlight」
ryitto
0
410
CA.swift#14
ryitto
3
5.9k
Data Essentials in SwiftUI
ryitto
1
540
Composable Architecture
ryitto
0
810
CollectionViewの 新しいレイアウトの作り方
ryitto
0
79
Swift5.1 SwiftUI
ryitto
0
150
Other Decks in Programming
See All in Programming
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
7
2.1k
PyConJP2026_wat_Python × Signal Processing: How to Draw Pictures with Sound Using Spectrogram Art
wat
0
360
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.8k
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
500
Dockerfile CMD for Node.js
grazie1999
0
120
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
390
How I Won Prize Money at a Hackathon Using Codex and Symphony Alpha
yasei_no_otoko
0
120
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
390
Pythonの実行はどこまで賢くなったのか? CPythonとPyPyから見る最適化のしくみ
curekoshimizu
3
1.9k
FastAPI の並行処理モデルを完全に理解する
hoto17296
8
3k
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
490
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
270
Featured
See All Featured
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.8k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
It's Worth the Effort
3n
188
29k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
300
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
670
The Invisible Side of Design
smashingmag
301
52k
Automating Front-end Workflow
addyosmani
1369
210k
How to Ace a Technical Interview
jacobian
281
24k
Transcript
swift-argument-parserͰ ؆୯ CLI πʔϧ࡞Γ Zli × DMM ߹ಉLT ry-itto 2020/07/18
1
ࣗݾհ • ҏ౻྇(@ry-itto) • iOS • B4 • Χϐόϥ͕͖ 2
͜Μͳ͜ͱͬͯ·ͨ͠ˠ
ࣗݾհʢଓ͖ʣ ʬ͋ͭ͠ʭChannel ΛΈΔ͜ͱΛ՝ʹͯ͠·͢ ༊͞ΕΔͷͰҰճΈͯ΄͍͠ ↑͓͢͢Ίͷಈը (https://www.youtube.com/watch?v=4tieUdeYHHY)
swift-argument-parser ͱʁʁ • Apple ެࣜͷϥΠϒϥϦ • CLI πʔϧΛ͏࣌ʹΑ͋͘ΔΦϓγϣϯͱ͔ɺίϚϯυͷαϒίϚ ϯυͱ͔Λѻ͏ͷ •
PropertyWrapper Λ͏·͍͜ͱ͍ͬͯΔ • help ͕͍͍ײ͡ʹͳΔ 4
ॾҙ • ࠓճ swift-argument-parser ʹ͍ͭͯͷΈઆ໌͠·͢ • SPM ͰίϚϯυϥΠϯ πʔϧΛ࡞Δํ๏ͳͲݴ͍·ͤΜ 5
ϛχϚϜͳ ͍ํ struct SampleCommand: ParsableCommand { func run() throws {
print("sample") } } SampleCommand.main() 1. ParsableCommand ʹ४ڌ ͨ͠Ϋϥε/ߏମΛ༻ҙ ͢Δ 2. run() ϝιουΛ࣮͢Δ 3. main() ΛݺͿ 6
ͪΐͬͱԠ༻ import ArgumentParser struct SampleCommand: ParsableCommand { @Argument() var context:
String @Flag() var upper: Bool = false @Option( name: .shortAndLong, help: "Repeating context" ) var repeatTimes: Int? mutating func run() throws { if upper { self.context = context.uppercased() } if let repeatTimes = repeatTimes { self.context = String(repeating: context, count: repeatTimes) } print(context) } } SampleCommand.main() echo ίϚϯυͷΑ͏ͳͷɻ • @Argument • @Flag • @Option ͕ग़͖ͯͨ 7
ͪΐͬͱԠ༻ @Argument • ίϚϯυʹର͢ΔҾ • σϑΥϧτΛ༩͓͑ͯ͘ͱࢦఆ ͠ͳͯ͘ಈ࡞͢Δ • ΠχγϟϥΠβҎԼ̎ͭͳͲ͕ ༻ҙ͞Ε͍ͯΔ
• @Argument(help:transform:) • @Argument(wrappedValue:parsing:help:trans form:) • ෳͷҾʹରԠ͍ͯ͠Δ 8
ͪΐͬͱԠ༻ @Flag • ϑϥάɻ (ls -a ͷ -a ͱ͔ͷΠϝʔ δ)
• ྫͷΑ͏ʹ Bool ͰͷΓସ͑ Ͱ͖Δ͕ɺenum Ͱ͍͚Δ • ↓ΠχγϟϥΠβͰΑ͍ͦ͘͏ • @Flag(name:help:) 9
@Flag (͓·͚) import ArgumentParser enum OutputCase: EnumerableFlag { case upper
case lower case natural } struct SampleCommand: ParsableCommand { @Argument() var context: String @Flag() var outputCase: OutputCase = .natural @Option( name: .shortAndLong, help: "Repeating context" ) var repeatTimes: Int? mutating func run() throws { switch outputCase { case .upper: self.context = context.uppercased() case .lower: self.context = context.lowercased() case .natural: break } if let repeatTimes = repeatTimes { self.context = String(repeating: context, count: repeatTimes) } print(context) } } SampleCommand.main() enum Ͱॻ͍ͨόʔδϣϯ (lower ͨͯ͠Έͨ) 10
ͪΐͬͱԠ༻ @Option • git commit -m <commit- message> ͷΠϝʔδ •
σϑΥϧτΛ༩͑Δ·ͨΦϓ γϣφϧܕʹ͠ͳ͍ͱඞਢͷΦϓ γϣϯʹͳͬͯ͠·͏ 11
ͪΐͬͱԠ༻ > ./.build/debug/SampleCommand --help USAGE: sample-command <context> [--upper] [--repeat- times
<repeat-times>] ARGUMENTS: <context> OPTIONS: --upper -r, --repeat-times <repeat-times> Repeating context -h, --help Show help information. —help
ͪΐͬͱԠ༻ ͬͯΈΔ :yosasou: 13
αϒίϚϯυ import ArgumentParser struct SampleSubCommands: ParsableCommand { static var configuration:
CommandConfiguration = .init( subcommands: [Sum.self, Average.self], defaultSubcommand: Sum.self ) } struct Sum: ParsableCommand { @Argument() var numbers: [Int] = [] mutating func run() throws { print(numbers.reduce(0, +)) } } struct Average: ParsableCommand { @Argument() var numbers: [Int] = [] func validate() throws { if numbers.count == 0 { throw ValidationError("Please specify numbers.") } } mutating func run() throws { print(numbers.reduce(0, +) / numbers.count) } } SampleSubCommands.main()
αϒίϚϯυ > ./.build/debug/SampleSubCommands --help USAGE: sample-sub-commands <subcommand> OPTIONS: -h, --help
Show help information. SUBCOMMANDS: sum (default) average See 'sample-sub-commands help <subcommand>' for detailed help. --help
αϒίϚϯυ ࡞Γํ • ParsableCommand ʹ४ڌͨ͠Ϋ ϥε/ߏମ Λ༻ҙ • configuration Λఆٛͯ͠ɺҾ
ͷ subcommands ʹ࡞ͬͨαϒί ϚϯυΛೖΕΔ • defaultSubcommand Λࢦఆ͢Δ ͜ͱͰɺsubcommand ໊Λࢦఆ ͠ͳͯ͘ྑ͘ͳΔ
αϒίϚϯυ ͬͯΈΔ
εϥΠυʹग़͖ͯͨιʔείʔυ ↓ʹஔ͍ͯ·͢ github.com/ry-itto-playground/SampleCommand
࡞ͬͯΈͨͷͷհ (⭐͍ͩ͘͞) AtCoderSwiftCLI (github.com/ry-itto/AtCoderSwiftCLI) • cargo-atcoder ͷ Swift ൛ΛΠϝʔδ •
ఏग़ػೳ࡞ͬͯΈͯΔ్த • brew ͰམͱͤΔΑ͏ʹͯ͠ͳ͍ͷͰ mint ͔ɺखಈϏϧυͰ 19