iOSDay 4

Xcodeの.pbxproj内のファイルをソートするSwift製コマンドラインツール - SortPbxproj

普段のiOS開発において、ファイルを追加するたびにProject Navigator上のファイルをソートしていると思います。

開発中、ファイル名が正しくソートされていないのを見つけてソートしてみるも、本筋と関係ない project.pbxproj の変更が含まれてレビュアーを困惑させることがあります。

これを解決させるためのスクリプトを作りました。


作ったもの



  • WorldDownTown/SortPbxproj


    • Swift Package Managerでコマンドラインツールを作りました

    • Homebrewからインストールすることができます




インストール

$ brew install WorldDownTown/taps/sort-pbxproj


使い方

$ sort-pbxproj $SRCROOT/Path/To/Project.xcodeproj

or
$ sort-pbxproj $SRCROOT/Path/To/Project.xcodeproj/project.pbxproj

このようにProject Navigator上のファイルやBuild Phase のCompile Sources 内のファイルもソートされます

before
after

file_inspector_before.png
file_inspector_after.png

compile_sources_before.png
compile_sources_after.png


自動化


  • XcodeのRun Script や .git/hooks/pre-commit などに書けば自動的にソートできるようになります

  • プロジェクトで共有する場合はコマンドの有無を確認すると優しいですね

if type sort-pbxproj > /dev/null 2>&1; then

sort-pbxproj $SRCROOT/Path/To/project.pbxproj
fi


ベースとなっているもの



  • webkit/sort-Xcode-project-file


    • WebKit の開発で使われている Perl スクリプト

    • WebKit 固有の要件に合わせたロジックも含まれています




実装について


ロジック

下記のようなシンプルな流れになっています


  1. pbxprojを一行一行読み込む

  2. 正規表現でソート対象行を特定

  3. ソート対象業ではファイルの名前を基準にソート並べ替える

  4. tmpファイルに書き込んで行く

  5. すべての行を読み込み終わったら、tmpファイルを project.pbxporj にリネームして終了


コマンドライン引数


--no-warnings オプション


  • デフォルトでは 与えられたパスに読み込み可能な project.pbxproj があるかチェックしており、見つからなかった場合には終了スクリプトを終了させます

  • 別名を使っている場合などを考慮して、そのチェックを省略するようなコマンドラインオプション --no-warnings を用意しています


    • 別名を使うことがあるのか正直よくわかりませんが、本家 WebKit版 を踏襲しました

    • コマンドラインオプションを実装したかっただけなので、将来消すかもしれません……




実装


  • コマンドラインの引数とオプションは CommandLine.arguments から取得できますが、型は [String] となっていて、スクリプト名や引数・オプションの区別はないためとても扱いやすいとは言えません


  • kylef/Commander を使うことで簡単に実装することができました


    • Swift Package Manager の dependencies に含めています



  • 引数やオプションを宣言的に書くだけで実装できるうえに、 --help も自動的に実装されるため実装コストがかなり抑えられました

// main.swift

import Commander

private func main(path: String, suppress: Bool) throws {
// ソート処理
}

command(
Argument<String>("path", description: "File path to *.xcodeproj or project.pbxproj"), // 引数
Flag("no-warnings", description: "ignore file path is valid or not"), // オプション
main).run()


まだやってないこと


  • ユニットテスト

  • ユーザーに優しいエラーメッセージ表示

  • Homebrew の Bottles 対応 (バイナリ形式の配布)

  • Project Navigator のグループの中のグループは上にソート並ぶようなオプション
    ダウンロード.png


追記


2018/12/05 00:10


Project Navigator のグループの中のグループは上にソート並ぶようなオプション


私の勘違いで webkit/sort-Xcode-project-file でも SortPbxProj でも、オプションではなくデフォルトの機能としてすでに実装されていました😅 (リンク先が該当の処理です)


参照