Tuzuru開発の知見
前の記事の続きで、SwiftでCLIを開発していた中で実装していて面白かった箇所を最後に紹介する。
swift-markdown
swiftlang/swift-markdownはかなり便利でよく出来ていた。ASTをVisitorパターンで操作できて、HTMLへの変換もVisitorパターンで実装されている https://github.com/swiftlang/swift-markdown/blob/c281baa59e2b0d3ddc72848741217af811f66d39/Sources/Markdown/Walker/Walkers/HTMLFormatter.swift
これのためにSwift使ってよかったというぐらい良い感じだった。唯一の不満点としては、標準のHTMLFormatterではリストの要素がpタグでラップされてしまうので正規表現で後から消す必要があった点。
https://github.com/swiftlang/swift-markdown/issues/197#issuecomment-2351568887
Swift Testing Traits
単体テストでGit依存の処理をテストするためにswift-testingのTraitを活用してFixtureを生成した。Swift Testingは標準で並列に実行されるので、Fixtureのセットアップも丁寧にやらないといけないけど、@TaskLocal というマクロで Task ごとのFixtureデータをラップしたオブジェクトを安全にテストケースから参照できた。
apple/container
apple/containerでローカルでLinux上の動作環境を用意してみた https://github.com/ainame/tuzuru/blob/4b186a46e9c9a6a5726237753b9a1370c48a9af9/scripts/test-linux-static.sh
Dockerファイルで普通に動くので、とりあえずこれでいいじゃんって気持ちになった。
組み込みHTTPサーバー
プレビュー用のHTTPサーバーは、Linuxでも動作させる+SwiftNIOのような既存のような巨大な依存を避けるために、システムコールを使ってClaude Codeに実装してもらって勉強になった(socket, bind, listen, acceptなどなど昔読んだ本の通りになった)。
FileManager
FileManagerを扱うときの知見を得た。
以下のような理由からラッパークラスを作ったらいい感じになった。
- swift-systemの
FilePathをcurrency typeとして利用したい FileManagerはSendableではない- 一方でほとんどのインスタンスメソッド自体はスレッドセーフらしいの機能を絞れば @unchecked Sendableには出来そう?
 FileManager.currentDirectoryPathはインスタンス単位ではなく、プロセス単位の値らしいので、並列なテストでは利用できない- AIが不必要に 
FileManager.defaultを直接参照してくるので、機能を絞ったラッパーのクラスを使ってDIするように指示すること治安が保てた 
新たに作った FileManagerWrapper を @unchecked Sendable として運用して、TaskGroupで並列化するときに利用している。
swift-system と swift-subprocess
Foundation.URL よりも使いやすい FilePath が使いたくて apple/swift-sytem を採用して、Gitを呼ぶためにswiftlang/swift-subprocessも採用したが、swift-subprocess が macOS上ではXcodeのSDKの System framework (swift-systemと同等だけど別物として存在) がimport出来る時には利用していて、Linux前提で swift-systemの FilePath を先に使っていた自分は swift-subprocess にFilePath を渡せずに混乱していた。
Appleの中の人々が議論しているissueがあって、みんな意見が分かれていそうなので早く終息してほしいと願っている。 https://github.com/swiftlang/swift-subprocess/issues/141
swift-subprocessのやり方に寄り添った typealias を書いて解決。 https://github.com/ainame/tuzuru/blob/85317a53e71acfed7daf30cace3797a23d699b8b/Sources/TuzuruLib/SystemPackageCompat.swift
まとめ
Swiftの普段使わない要素を試せて面白かった。 Claude Codeなどのおかげで趣味開発は捗るようになって楽しい。