エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

AppleScrptでCotEditorのドキュメントをsaveするときにエラーがでる原因を探っているがまだ解明できていない

一時撤退。


今月のはじめにCotEditorからEvernoteへテキストを送るスクリプトを書きました。
このエントリにもあるようにそのままだとエラーが発生します。こんなの。

まずは使えるもになるようにと先を急ぎ、tryブロックで無効化して一応かっこうを付けたわけですが、10日ほど前から原因を特定しようと再度取り組んでいました。現在のところ連敗中。手持ちの弾倉の解析のためのアイディアが尽きたので一時撤退です。

のちの自分のために戦歴を記録。

まずスクリプトを疑う

AppleScriptの経験がほぼ皆無である以上、真っ先に疑うは自分が書いたスクリプト
とはいえ、ネットの中ぐらいしか情報を探す先がなく、しばらく情報集めにさまようことに。

ちなみに最初に気がついたのは。保存のスクリプトを前回はこのように書きましたが、

front document save

本当はこう書くのが正しいようだということ。

save front document

まあ、英文法的にはたしかに後者が普通なわけで。ふだんからオブジェクト指向言語を主に使っているので無意識に「操作対象 操作内容」の順に書いてしまった模様。
どっちで書いても動くAppleScriptは、柔軟というのかなんというのか。このあたりがAppleScriptに対するわたしの苦手意識の原因のような気がします。


それはそれとして。


スクリプトを書いては動作を確かめるということをしている中で妙なことに気がつきました。
まず次のようなスクリプトスクリプトエディタで書いておきます。

set tmpdir to system attribute "TMPDIR"
set filename to tmpdir & "test.txt"
tell application "CotEditor"
     save front document in filename
end tell

次にCotEditorで新しいウィンドウを開き文字を入力、保存せず名称未設定のままにしおいて、このスクリプトスクリプトエディタから実行します。

そのときのイベントログがこう。

tell current application
     system attribute "TMPDIR"
          "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/"
end tell
tell application "CotEditor"
     save document 1 in "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/test.txt"
          missing value
end tell

CotEditorから実行したときのようなエラーはなぜか発生せず、saveコマンドのあとのmissing valueの文字。これはsaveを実行した結果の値がmissing valueということのようなのですが、なにか妙。


ためしに対象となるアプリケーションをテキストエディット(application "TextEdit")に書き換えて、同じようにテキストエディットで文字を入力してスクリプトを実行してみました。

そのときの結果がこう。

tell current application
     system attribute "TMPDIR"
          "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/"
end tell
tell application "TextEdit"
     save document 1 in "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/test.txt"
end tell

missing valueはありません。ここにきて、脇に置いておいたCotEditorの実装への疑いを持ち出すことにしました。


あとこれは今日のことなのですが。定番エディタであるmiでもAppleScriptを扱えることを知りました。

以前はmiを使っていたのですが、わたしには重く感じて、軽いCotEditorへ乗り換えた経緯があります。余談。

改めてmiをダウンロード。

上のスクリプトの対象アプリケーションをmi(application "mi")に書き換え、miで文字を入力してスクリプトを実行。結果はこう。

tell current application
     system attribute "TMPDIR"
          "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/"
end tell
tell application "mi"
     save document 1 in "/var/folders/YO/YOfSz7Ko2RWnf++87vF0WU+++TM/-Tmp-/test.txt"
end tell

missing valueはありません。

やはりCotEditorの動作が妙なようです。

次にCotEditorを疑う

CotEditorを解析すべくソースコードを入手します。
リポジトリはここ。

ここからリポジトリをコピーします。

git clone git://git.sourceforge.jp/gitroot/coteditor/CotEditor.git

これらの中で、NSDocumentから派生したCEDocumentにドキュメントを保存するコードを見つけたので、プロジェクトをビルドしブレイクポイントを仕掛けてみました。


この保存のコード、予想外にいろんなことをやっています。

  • Undoの範囲が保存の時点で区切りがつくように細工しています(194行目付近)
  • 編集中のファイルがほかから変更されたときにそのことを通知するしくみを仕込んであるのですが、自分がファイルを保存するときにもそのしくみが動いてしまうらしく、自分が保存するときにはフラグを使ってそのしくみが機能しないようにしています。ただそのフラグを戻す処理が時間差を付けて実行されるように、一定時間後にメッセージを送信するようになっています(215行目付近)
  • 自分でファイルハンドルを操作せず、authopenコマンドを起動しパイプを使ってテキストデータを送りauthopenがファイルを保存するということをしています(2141行目〜2152行目付近)

ほかにもクリエイタの設定とか、想像していたよりずっと複雑なことをしていました。

で、肝腎の当該メソッドの動作状況なのですが。動作に異常らしい異常は見つからず。エラーを返している処理もなく。普通に動いているようです。でも件のスクリプトを実行すると変わらずエラーになる。上記のスクリプトスクリプトエディタから実行すると変わらず値としてmissing valueを返してくる。

影響がありそうなコードをひとつひとつ無効にしていったもののそれでも状況は変わらず。

最終的に。スクリプトsaveコマンドが実行されたときに、それをハンドリングするhandleSaveScriptCommand:を実装し、保存処理をそっくり無効化してみました。

結果は。変わらず。missing value発生。orz 。


比較のために開発ツールのExamplesに入っているテキストエディットを自前でビルド、同じようにhandleSaveScriptCommand:を実装して保存処理を無効化して実行。missing valueでません。orz orz 。


ここにきて一旦ギブアップ。
CotEditorは、編集中のファイルが外部から変更されていないか監視するなど、いろいろな処理がいろいろなタイミングで動いていて、これらを把握するには今回のようなスポット的な解析でなく俯瞰して調査する必要がありそうです。


そんなわけで。
再開することを誓いつつ、一時撤退。

いつか読むはずっと読まない:[再]

…。

「『再』ってなんだよ『再』って!」


1月のことですけど。本屋で発見して、心の中でツッコミを入れてしまいました。

第一巻が出たのが1987年。

二巻はいつ出るんだ?…という思いも忘れていた頃に出たのが「1と2/5」。

第一巻の5編にプラス2編で「1と2/5」。頭を抱えました。
頭を抱えて購入見送り。

そうしたら。


「再」


ついかっとなって購入してしまいました。

昔からの疑問なんですが。
本当にこの人は、新作も書かずに、なにで食いつないでいるんだろう?

トリガーマン![再] (朝日ノベルズ)

トリガーマン![再] (朝日ノベルズ)


ものすごい余談ですが。
火浦作品とのファーストコンタクトはNHKのラジオドラマ「タイムトンネルを掘る」(みのりちゃんシリーズ「日曜日には宇宙人とお茶を (ハヤカワ文庫 JA 190)」収録の一編)。それからだから、けっこう長いなー。
いつのまにか「みのりちゃん」も再版されてるし…。

みのりちゃんの実験室 世界征服のすゝめ (朝日ノベルズ)

みのりちゃんの実験室 世界征服のすゝめ (朝日ノベルズ)