XcodeのProperty List Type

Xcodeのプロパティリスト編集画面では、辞書のKeyに名前がついていたり、値の型が固定されていたり、取りうる値を選択肢の中から選ぶことが出来る。

これの定義を独自に出来ないだろうか？　というかどうやってるんだ？

ということで、少し調べてみる。
- - -
Info.plistの編集画面で、右クリックでコンテキストメニューを開くと"Property List Type"という項目があり、その中に色々と項目がリストされている。これがあるということは、おそらくどこかに設定ファイルがあるはずだ。
そこで、Xcode.appのバンドル内を漁っていると、Pluginsの中に"~PlistStructDefs.dvtplugin"というファイルがいくつかある。もしやと思い、これをバイナリ形式のプロパティリストファイルだと思って文字列に展開してみる。すると、出た。

```
                    ...
                                        {
                        class = String;
                        default = "6.0";
                        name = InfoDictVersion;
                    },
                    ...
```

こういった調子で、様々な定義が書いてある。これの真似をしていけば独自のプロパティリストのフォーマットが作れるのではないか。

ここでGitHubに[xcpc](https://github.com/AliSoftware/xcodeplugin)というスクリプトを見つけた。このスクリプトを使うと、xml形式のファイルをdvtplugin形式に変換してくれるらしい。xmlのXSLとかいうのを使って何かするようだ。あまり詳しくないので良く解らないが。

肝心の文法、というかタグの書き方はどうなっているんだろう？　xcpcのREADMEにも「文書化されていないので推測するしかない」と書いてある。という訳で、推測から得た文法をいくつかメモしよう。
\<plugin>
-
一番外側の要素（ルート要素）。

|属性 |説明  |
|:-----------|:------------|
|name  |プラグインの名前。 |
|id    |逆ドメイン記法を用いて、com._yourcompany_.plist-plugin._yourformat_ などとする。|
|version|とりあえず1.0とやっておけばいい。
|xmlns:xc|xcpcを利用するため、urn:X-AliSoftware:xcodeplugin:preprocessorとする。

\<extention>を子に持つ。

\<extention>
-
プラグインファイルの機能拡張の内容を表す要素だと思われる。

|属性|説明  |
|:-----------|:------------|
|point|プラグインファイルが何の機能を拡張するものか明示するためのもの？　com.apple.xcode.plist.structure-definition.info-plistとする。|
|id|逆ドメイン記法を用いて、com._yourcompany_.plist.structure-definition._yourformat_ などとする。|
|name|プロパティリスト編集画面のProperty List Typeメニューに表示される名前になる。

\<filename>や\<definition>をそれぞれ複数子に持つ。

\<filename>
-
Xcodeは標準ではplistファイルの名前の形式によってどのProperty List Typeか判別する。それを指定するためのもの。

|属性|説明|
|:-----------|:------------|
|pattern|シェルスクリプトと同じようにワイルドカードが使える？　Info.plistではそれぞれ"Info\*.plist"と"\*Info.plist"の値を持つ二つのタグが指定されている。

\<definition>
-
このタグに定義をごりごり書いていくことになる。

|属性|説明|
|:-----------|:------------|
|name|定義の名前。"InfoDictVersion"や"CFBundleIdentifier"など、関数名と同じ様に命名するようだ。プロパティリストのルートオブジェクトの定義を書くときは"\_root\_"と入力する。|
|class|定義の型。"String"、"Number"、"Boolean"、"Array"、"Dictionary"などの基本型の他、他の定義に書かれているname属性を指定することも出来る。"*"を指定すると、編集画面で自由に選べるようになる。|
|localizedString|nameが"\_root\_"のタグ専用？　編集画面で表示される文字列。|
|default|多分String、Number、Booleanクラス専用。デフォルト値を指定する。|
|placeholder|多分String、Number、Booleanクラス専用。プレースホルダの文字列を指定する。
|arrayElementClass|Arrayクラス専用。基本型か、他の定義のnameを設定する。|
|defaultDictionaryValueClass|Dictionaryクラス専用。デフォルトで使用される値のクラスを指定する。|
|defaultKeyName|Dictionaryクラス専用。デフォルトで使用されるキー値を指定する。
|identifyingKey|Dictionaryクラス専用。子孫の\<key>のnameを指定するようだが、よくわからない……|

\<allowablevalues>（String、Number専用？）や\<dictionarykeys>（Dictionary専用）を子に持つ。

\<allowablevalues>
-
読んだ通り、許される値を書いていく。多分String、Numberクラス専用。
\<value>を複数子に持つ。

\<value>
-
このタグで設定した値はポップアップで選択できるようになる。

|属性|説明|
|:-----------|:------------|
|name|値の名前であり、実際の値そのもの。|
|localizedString|編集画面で"Show Raw Keys/Values"をオフにしているときに表示される名前。|

\<dictionarykeys>
-
Dictionaryクラスの定義が持つことが出来る。
\<key>を複数子に持つ。

\<key>
-
辞書がとれる値やキーを設定する。このタグで設定したキーはポップアップで選択できるようになる。

|属性|説明|
|:-----------|:------------|
|name|タグの名前であり、実際に辞書のキーとして使用される文字列。|
|class|値の型。基本型のほか、他の定義で使用されたnameも使用できる。これにallowablevaluesを設定した定義を指定するのが特徴的な使い方。|
|localizedString|編集画面で"Show Raw Keys/Values"をオフにしているときに表示される名前。|
|use|設定が必須か、任意かなどを指定する。可能な値は"required"、"optional"、"default"の三種。"default"は作成時に含まれているが、削除可という意味？|

-
疲れた。長い。誰得？　だが、好奇心から調べたものなので、まぁいいか。
この機能を使いたいと思うのは余程大きなプロジェクトとかだろうか。しかも文書化されていないのでXcodeのバージョンによっては使えないだろう。
何か間違いを発見したり、良い情報を持っている人は教えてください。

こういったタグを記述し終えたら、Terminalでxcpcを

```Terminal.app
$ xcpc -install <input-file>
```

と実行すると、dvtplugin形式に変換され、~/Library/Developer/Xcode/Plug-Ins下に書き出される。
その後は、Xcodeの次回起動時から有効になる。

参照：[AliSoftware/xcodeplugin - GitHub](https://github.com/AliSoftware/xcodeplugin)