Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
swift-argument-parserで 簡単 CLI ツール作り
Search
ry-itto
July 18, 2020
Programming
180
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
420
CA.swift#14
ryitto
3
5.9k
Data Essentials in SwiftUI
ryitto
1
550
Composable Architecture
ryitto
0
820
CollectionViewの 新しいレイアウトの作り方
ryitto
0
88
Swift5.1 SwiftUI
ryitto
0
160
Other Decks in Programming
See All in Programming
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
2
210
Performance Optimization With LLMs
xleitix
0
220
contenteditable と日本語入力に向き合う
colorful12
0
230
あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期
hasutosasaki
1
1.6k
Web Framework Benchmark Battle 2026, Any%
a_matsuda
3
3k
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
4.8k
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
200
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
290
Apple Intelligenceとオンデバイス時代の到来
yahir0
0
160
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
120
Event is what happens
moro
2
1.8k
AI Augmentation Techniques with Liberty
ivargrimstad
0
120
Featured
See All Featured
The Language of Interfaces
destraynor
162
27k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Unsuck your backbone
ammeep
672
58k
Navigating Team Friction
lara
192
16k
Color Theory Basics | Prateek | Gurzu
gurzu
1
500
The World Runs on Bad Software
bkeepers
PRO
72
12k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
Everyday Curiosity
cassininazir
0
370
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
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