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
メールのエイリアス機能を履き違えない
isshinfunada
0
230
ルールを書いて終わらせないハーネスエンジニアリング
yug1224
4
1.9k
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
3.6k
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
180
Foundation Models frameworkで画像分析
ryodeveloper
1
600
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
460
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
380
Go 1.27 における memory allocation の高速化
andpad
0
110
継続モナドとリアクティブプログラミング
yukikurage
3
690
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
450
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
180
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
590
Featured
See All Featured
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
380
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
730
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
410
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
160
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
370
Why Our Code Smells
bkeepers
PRO
340
58k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
790
Skip the Path - Find Your Career Trail
mkilby
1
180
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
540
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