Ulysses for Mac の .Ulysses-Group.plist がイカン構造をしている件

Ulyssesのファイルはプレーンテキストだから

さんざんウダウダ言った挙句、Scrivenerを捨ててUlyssesで原稿を書いている現状。

最大の理由は、やはりUlyssesが(外部フォルダにおいて)プレーンテキストファイルを扱えることです。

私は原稿執筆時に青空文庫フォーマットを利用しており、プレースホルダを置いておいて後で置換したりします。

{hoge}hoge[#「hoge」に傍点]に置換したり。最初から青空文庫フォーマットにすると、リッチテキストほどではないにせよ編集が大変)

元データがプレーンテキストであれば、このような処理をスクリプトで自動化することができます。それ以外にも、ファイル名を連番化したり、分割されたファイルを統合したり。

Ulysses自体にもフォーマット変換して出力する機能はありますが、青空文庫フォーマットには対応していないので、自前のスクリプトで処理する必要があるとも言えます。

外部フォルダの文書構造はどこに保存されているのか?

Ulyssesはシート(個々の文書)を任意に並べ替える機能を持ちます。この際、順序情報はどこに保存されているのでしょうか。

Ulyssesに連携したフォルダには、「.UlyssesRoot」「.Ulysses-Group.plist」というファイルが自動生成されます。ここに、フォルダごとのコンフィグ情報や、シートの順序等の情報が格納されています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>childOrder</key>
<array>
<string>オープニング</string>
<string>紹介</string>
</array>
<key>createMarkedFile</key>
<false/>
<key>sheetClusters</key>
<array>
<array>
<string>序文.txt</string>
</array>
<array>
<string>書誌情報.txt</string>
</array>
</array>
</dict>
</plist>

<key>childOrder</key>下にある<array>はサブフォルダの順序、<key>sheetClusters</key>下にある<array>には直下のシートの順序を、それぞれ子要素として持ちます。

例えばファイル名の連番化をするには、.Ulysses-Group.plistの書き換えとファイルのリネームを同時に行えばよいわけです。

XML構造上の問題

問題は、これが完全なツリー構造ではない点にあります。

<key>childOrder</key>下にある<array>と、<key>sheetClusters</key>下にある<array>を、データ的に区別することは困難です。例えば、XPathで表現すれば、どちらも//plist/dict/arrayとなります。

実用上は、

  • 取得したいのは<string>要素の値と順序のみである
  • childOrdersheetClustersでは階層数が異なる

ということから、例えばxmlstarletでいずれかを選択的に取得することは可能です。

1
2
3
4
5
6
7
8
9
$ xml sel -I -t -v //plist/dict/array/string .Ulysses-Group.plist
Attempt to load network entity http://www.apple.com/DTDs/PropertyList-1.0.dtd
オープニング
紹介
$ xml sel -I -t -v //plist/dict/array/array/string .Ulysses-Group.plist
Attempt to load network entity http://www.apple.com/DTDs/PropertyList-1.0.dtd
序文.txt
書誌情報.txt

なかなかに気持ち悪い。sedで処理することも考えましたが、結局のところ暗黙的な記述ルールに依存したバッドプラクティス臭いスクリプトにならざるを得ません。

plistのルールセットはよく知りませんが、XML的には<key><array>の子要素にすれば済む話でしょう。それか、<array type="childOrder">とかでもいいよ。

なんとかしてほしいのですが、受けが狭すぎて改善要望として投げるのもどうか、ともにょっている次第。