Adobe ExtendScript Debuggerを使ってみる
アートボードを100枚以上含むファイルがあり、各アートボードのテキストボックスの内容をまとめてテキストファイルとして取得したくなったので、久しぶりにAdobe ExtendScriptでスクリプトを書きました。やりたいことの要件は以下の通りです。
- 各アートボードはそれぞれ1つのテキストボックスを持つ
- もしくは対象の1つ以外のテキストボックスはレイヤーのロックなどで選択できないようにしておく
- 各テキストボックスの内容が1行ごとに書かれたファイルを出力する
本物のデータは載せられないので、簡略化した例で示すと
のようなIllustratorのファイルに対して
テキストA テキストB テキストC ...
というデータが書き込まれたファイルを出力してくれるスクリプトが欲しい、ということになります。
開発環境はVS Codeを使い、途中でデバッグが辛くなったのでAdobe謹製のExtendScript Debuggerという拡張機能を入れました。 最終的に完成したスクリプトは以下のものです。
var CONFIG = { outFile: '~/Desktop/descs.txt', } function map(items, fn) { var res = [] for (var i = 0; i < items.length; i++) res[i] = fn(items[i], i) return res } function filter(items, fn) { var res = [] for (var i = 0; i < items.length; i++) { if (fn(items[i], i)) res.push(items[i]) } return res } function log(input) { var now = new Date(); var output = now.toTimeString() + ": " + input; $.writeln(output) } try { var texts = [] log('Start script') for (var i = 0; i < app.activeDocument.artboards.length; i++) { app.activeDocument.selection = null; app.activeDocument.artboards.setActiveArtboardIndex(i); app.activeDocument.selectObjectsOnActiveArtboard(); var textFrames = filter(app.activeDocument.selection, function(item) { return item instanceof TextFrame }) texts.concat(map(textFrames, function(tf) { log('Artboard' + i + ': ' + tf.contents) return tf.contents })) } log('Detect ' + texts.length + ' textFrames total') texts = map(texts, function(text) { return text.replace(/\r\n|\r|\n/g, '\\n') }) var output = texts.join('\n') var f = new File(CONFIG.outFile) f.encoding = 'UTF-8' f.lineFeed = 'Unix' f.open('w') f.write(output) f.close() } catch (e) { alert('Error: ' + e) }
始めはこのスクリプトのデバッグを、ログメッセージをファイル出力して行なっていたのですが、 ファイルに何も書き込まれないという事象(原因は後述)に陥ったため、ExtendScript Debuggerの導入に踏み切りました。 ファイル出力を行う処理のデバッグ用のログをファイル出力で行なったため、結果として混乱が増大しました。 デバッグ専用の情報出力チャネルの存在は大切ですね。
ExtendScript Debuggerの使い方
使い方と言っても基本的には公式のドキュメントに従えば問題なく使えます。
ExtendScript Debugger - Visual Studio Marketplace
VS Codeのデバッグ機能を使ったことがないと分かりづらいのは、デバッグ対象のプログラム
(今回の場合はスクリプトを動作させるプログラムを指すのでAdobe Illustrator)
を指定してやらないと
Can’t start a session without an active target and engine. Select an active target and engine before trying again.
と表示されて失敗するところです。意図するところは、どこでデバッグ対象のスクリプトを動かすか指定する必要があるということです。
これを解決するにはデバッグを実行する前に、下のステータスバーで対象プログラムを指定します。
Select the target application
と表示されているところを選択すると選択モードになるので Adobe Illustrator
を選択します。
デバッグの実行に成功すると $.write()
で指定したメッセージがコンソールに流れます。
その他
毎回デバッグ対象のプログラムを指定したくない
${command:AskForScriptName}
を固定文字列にすれば毎回ダイアログで入力せずにすみます。
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "extendscript-debug", "request": "launch", "name": "Ask for script name", // "program": "${workspaceFolder}/${command:AskForScriptName}", "program": "${workspaceFolder}/copy-textbox.jsx", "stopOnEntry": false } ] }
それにしてもこの program
っていう表現、デバッグ対象のスクリプトなのか、ランタイムを指すのか、何を指しているか曖昧で分かりづらいですね。
ファイル出力ではまったところ
はまったところは2点。
join('\n')
で結合した文字列の改行文字がfileObj.write()
時に\r
になるf.lineFeed = 'Unix'
で期待通りになった
- 日本語が出力されない
f.encoding = 'UTF-8'
で改善された。
ちなみに File
クラスのリファレンスは
Illustrator_Scripting_Guide_cc.pdf
ではなく
JavaScriptToolsGuide_CS5.pdf
にあります。
共にAdobeサイト内の検索に引っかからないのもあり非常に探しづらい。
AdobeはもっとExtendScriptのリファレンスを整備してほしい。なんでPDFでしか提供されていないんだよ。 というか公式リファレンスくらいちゃんとアクセスできるところに置いてほしい。AdobeはExtendScriptを捨てたいんだろうか。