2010年2月22日月曜日

GroovyからInDesignを叩く(Mac限定)

昔、ターミナル、AutomatorからAdobeアプリ用JavaScriptを呼び出すというエントリを書いたことがあるんですが、Macならコマンドを叩ける言語であれば、基本的にどんな言語からでもAppleScriptを介してExtendScriptを呼べるはずです。

なので、GroovyからInDesignを呼んでみます。
String[] init = ["osascript", "-e",
'''
tell application "Adobe InDesign CS3"
do script "

#targetengine \\"groovy\\"
$.evalFile(\\"~/Desktop/json2.js\\");

" language javascript
end tell
'''
]
init.execute()

String[] args = ["osascript", "-e",
'''
tell application "Adobe InDesign CS3"
do script "
#targetengine \\"groovy\\"
(function(){

var obj={};
var sels = app.activeDocument.selection;
for(var i=0;i<sels.length;i++){
if(sels[i].constructor.name === \\"TextFrame\\"){
var id = sels[i].id;
var cont = sels[i].contents;
obj[id] = cont;
alert(cont)
}
}
return JSON.stringify(obj);
})()

" language javascript
end tell
'''
]

def ary = []
def proc = args.execute().text.readLines().collect{ary.push(it)}
def cont = ary.join('')
println cont

実行結果。


返り値。


値のやりとりをどうするか考えたんですが、結局json2.jsを使う事にしました。
targetengineを指定することで、セッション間でも読み込んだライブラリを使い回すことができます。
一度Javaのコンパイラを通るので、スクリプト内のバックスラッシュは2重にしないといけません。

これでちょっとGroovyが流行るの希望。

2010年2月10日水曜日

ExtendScript ToolKitのヘルプから、10桁数値→人間語のハッシュマップを生成する

昨日のエントリを読んで、milligrammeさんがEnumerationの値を列挙したハッシュマップを作ってくれました。ありがとうございます!
なんと、ExtendScript Toolkitのヘルプ用のXMLファイルから、Enum値を抜き出す離れ業。
InDesign_10桁数値→人間語のハッシュマップ - diary NET. 1mg
元ネタのExtendScript Tool Kit のInDesign用のヘルプのxmlファイルは
/Users/xxxxxx/Library/Preferences/ExtendScript Toolkit/2.0/omv$indesign-5.0-ja_jp.xml(Mac CS3の場合)

自分はこれをスクリプトで抜き出してみます。(後出しジャンケンの強みで、オブジェクト名も入れてみます。)InDesignCS3、Macのみ対応。Windowsの場合のファイルパスは調べてません。また、CS4でもパスを書き換えて試したのですが動きませんでした。


最後尾のテストの、コメントアウトを外して実行して下さい。

できた!
使用する場合は、このスクリプトを basedOnEnum.jsx というファイル名で保存して、スクリプトの先頭に #include "basedOnEnum.jsx" を入れてもらえればOKです。
正直、一人ではおそらくできませんでした。
今更ながらインターネットってすごいや。

InDesignの10桁数値から意味のあるプロパティ名を得たい

InDesignのプロパティを取ろうとすると、10桁の整数で返るものがある。
たとえば、定規の単位を取ろうとして
var vUnit=app.activeDocument.viewPreferences.verticalMeasurementUnits;
alert(vUnit);
とやると

と出る。ExtendScript ToolkitのInDesignCS3オブジェクトモデルを開き、この10桁を見ながらこれが何なのか探す。書き出して、開いて、探して…
そんな風に探すのめんどくさい!意味のある言葉で返せないのか?

まず、viewPreferencesの取る値「MeasurementUnits」を見てみると
$.writeln(MeasurementUnits.toSource());

({POINTS:2054188905, PICAS:2054187363, INCHES:2053729891, INCHES_DECIMAL:2053729892, MILLIMETERS:2053991795, CENTIMETERS:2053336435, CICEROS:2053335395, Q:2054255973, HA:1516790048, AMERICAN_POINTS:1514238068, CUSTOM:1131639917, AGATES:2051106676})
undefined
と出る。要するにこれは単なるハッシュマップで、意味のある文字を書くと数値として代入されてるだけ。
だったらこれを逆マップにしてやれば…。
試しに書いてみる。
var map=(function(o,m){for(var i in o){m[o[i]]=i}return m})(RulerOrigin,{});
var map=(function(o,m){for(var i in o){m[o[i]]=i}return m})(MeasurementUnits,map);

var v=app.activeDocument.viewPreferences;
var rOrigin=v.rulerOrigin;
var vUnit=v.verticalMeasurementUnits;
var hUnit=v.horizontalMeasurementUnits;
var kUnit=v.typographicMeasurementUnits;
var tUnit=v.textSizeMeasurementUnits;
var lUnit=v.lineMeasurementUnits;

//ふつうに表示
var text="定規の単位\n開始位置:\t\t\t"+rOrigin
+"\n水平方向:\t\t\t"+vUnit
+"\n垂直方向:\t\t\t"+hUnit
+"\n組版:\t\t\t\t"+kUnit
+"\nテキストサイズ:\t\t"+tUnit
+"\n線幅:\t\t\t\t"+lUnit;
alert(text);

//意味のある
var text2="定規の単位\n開始位置:\t\t\t"+map[rOrigin]
+"\n水平方向:\t\t\t"+map[vUnit]
+"\n垂直方向:\t\t\t"+map[hUnit]
+"\n組版:\t\t\t\t"+map[kUnit]
+"\nテキストサイズ:\t\t"+map[tUnit]
+"\n線幅:\t\t\t\t"+map[lUnit];
alert(text2);

これを走らせると、ひとつ目のアラートで10桁数字を表示。

ふたつ目のアラート。

これで、Enumerationな値を全部とって同じ逆マップに入れて代入できれば、どんな数値が来ても意味のある文字列として返せるじゃないか!と思ったけど、そこまで。スクリプトでそれを全部とってリストする方法は見つからなかった。
オブジェクトモデルから全部名前ひろって、ひとつひとつ手書きで書くしかないかな…もし方法知っている人がいたら教えて下さい。

20100211追記:
milligrammeさんがEnumerationの値を列挙したハッシュマップを作ってくれました。
InDesign_10桁数値→人間語のハッシュマップ - diary NET. 1mg
それを受けて、自動でマップを生成するエントリを書きました。
ExtendScript ToolKitのヘルプから、10桁数値→人間語のハッシュマップを生成する

2010年2月4日木曜日

ExtendScriptでテキストに追記する。

ちょっと調べたメモ。
普通に
var file=new File("test.txt");
file.encoding="UTF8";
file.lineFeed="Unix";
if(file.open('w')){
file.writeln('これを\n追記\nするんだよ!');
file.close();
}
とやると、ファイルの内容が上書きされてしまう。
ポイントは2つ。
  1. File.open('e')で開く
  2. File.seek(0,2)でいちばん後ろにファイルポインタを移動させる
var file=new File("test.txt");
file.encoding="UTF8";
file.lineFeed="Unix";
if(file.open('e')){
file.seek(0,2);
file.writeln('これを\n追記\nするんだよ!');
file.close();
}