Developer's Blog

Xcode のファイルツリーを名前順に並べたいという話

Xcode の左側のファイルツリー表示は、何故かファイル名が名前順に並んでおらず、並べ替える機能もありません。なのでファイル数が多くなってくると、探したいファイルが全く探せなくてイライラしますね。このファイルツリーを名前順に並べたいというのが今回の課題です。

最初は以前に書いた記事と同じように、AppleScript で Xcode 内のファイルツリーを操作しようとしたのですが、残念ながら現行の Xcode はアイテムやグループの並べ替えに対応していませんでした。

次に考えたのは、Xcode のプロジェクトファイルを直接編集するという事です。調べてみると、Xcode 内の foo.xcodeproj の中に project.pbxproj というファイルが存在し、そこにファイルツリーの親子関係や並び順などが記述されていました。このファイルを編集すれば、Xcode 内のファイルツリーを並べ替えられるのですが、さらに問題がありました。このファイルは古い plist 形式になっていて、読み書きが大変やりにくいわけです。

そこでさらに調べ見ると、plutil というコマンドがある事を知りました。このコマンドを使用すると古い plist を新しい XML 形式の plist に変換できます。これで project.pbxproj の読み書きが可能になります。

前置きが長くなりましたが、今回行う処理は以下のようになります。

  1. plutil コマンドで project.pbxproj ファイルを、新しい plist 形式に変換
  2. 1で作成したファイルを編集して、ファイルツリーを並べ替える
  3. 2で作成したデータを project.pbxproj に上書きして Xcode で開き直す

今回も2のメインの処理は python で書きました。以下がそのスクリプトになります。plistlib というモジュールが標準で含まれているので、1で作成したファイルの読み書きが簡単に記述できますね。

#!/usr/bin/python
# -*- coding: utf-8 -*-
# sort_xcode.py

import sys
import os
import plistlib

# arg check
if len(sys.argv) != 2:
  print 'Usage: python sort_xcode.py foo.xcodeproj'
  sys.exit(0)

# target project check
filepath = './%s/project.pbxproj' % (sys.argv[1],)
if not os.path.exists(filepath):
  print '%s is not found' % (filepath,)
  sys.exit(0)

# make backup
backup_path = '%s.bak' % (filepath,)
if not os.path.exists(backup_path):
  os.popen('cp %s %s' % (filepath, backup_path))

# convert pbxproj to xml plist format
os.popen('plutil -convert xml1 %s' % (filepath))

# sort items
proj = plistlib.readPlist(filepath)
objects = proj['objects']
for key, item_data in objects.items():
  if 'children' in item_data:
    work = {}
    for child in item_data['children']:
      target = objects[child]
      work[child] = 'name' in target and 
                    target['name'] or target['path']
    result = []
    for key, val in sorted(work.iteritems(), key=lambda(k,v): (v,k)):
      result.append(key)
    item_data['children'] = result
    
plistlib.writePlist(proj, filepath)

# result
print 'sort completed.'

以下のように実行するとグループやファイルがすべて名前順にソートされます。ソート条件の部分を書き換えれば、好きなようにファイルツリーをいじれますので、お好みに合わせてアルゴリズムを修正して下さい。

[注意]
Xcode プロジェクトが開けなくなる可能性がありますので、使用は自己責任でお願いします。もし何かおかしな事があった場合は、バックアップファイルが foo.xcodeproj/project.pbxproj.bak に作成されているので、それを foo.xcodeproj/project.pbxproj に上書きして下さい。

$ python sort_xcode.py foo.xcodeproj

これで Xcode のファイルツリーが名前順に並びました。ちょっとしたイライラを取り除いて、できるだけコーディングに集中できるよう小さな改善を積み重ねていきたいですね。

[おまけ]
plutil コマンドは結構便利です。Mac では様々なところで plist が使われているので、覚えておくとちょっとした時に役に立ちそうです。以下のような使い方ができます。詳細は man を参照して下さい。

$ plutil -convert xml1 foo.plist         # foo.plist を XML 形式に変換
$ plutil -convert xml1 -o - foo.plist    # 上書きせずに標準出力に出力
$ plutil -lint foo.plist                 # plist 形式のファイルの validation

Copyright © 2019 Fenrir Inc. All rights reserved.