26
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSAdvent Calendar 2018

Day 4

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

Last updated at Posted at 2018-12-03

普段の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 でも、オプションではなくデフォルトの機能としてすでに実装されていました😅 (リンク先が該当の処理です)

参照

26
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?