2010年5月10日月曜日

Groovyでスクリプト自身の場所を確認する

Javaと全く同じ。(Groovyだし、もっといい方法もあるかも)


実行。
$ groovy urltest.groovy 
file:/Users/kanemu/Desktop/groovytest/urltest.groovy

Groovyのファイル名ハマりどころメモ

ちょっと焦ったのでメモ。

その1:
groovyスクリプトを書くとき、たとえば
println('Hello, World!')
とだけ書いて、ファイル名を「これは最初のスクリプトだから……」とか思って
01_println.groovy
とつけて実行すると、
Caught: java.lang.ClassFormatError: Illegal class name "01_println" in class file 01_println
というエラーが出て動かない。
groovyはいったんJavaのクラスとしてコンパイルされてから実行される。その際ファイル名のクラスが作られるので、ファイル名の頭文字が数字だと動かない。

その2:
groovyスクリプト内にclassを書く時、
class Test {
def name = 'kanemu'
}

def test = new Test()
println test.name
のようなスクリプトを書いたとして、ファイル名を
Test.groovy
にすると、
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/Users/kanemu/Desktop/groovytest/Test.groovy: 1: Invalid duplicate class definition of class Test : The source /Users/kanemu/Desktop/groovytest/Test.groovy contains at least two definitions of the class Test.
One of the classes is a explicit generated class using the class statement, the other is a class generated from the script body based on the file name. Solutions are to change the file name or to change the class name.
@ line 1, column 1.
class Test {
^

1 error
のようなエラーが出て、動かない。
これも上と同じ理由で、いったんJavaクラスとして実行される際、ファイル名をとってTest.classを作っているので、スクリプト内のTestクラスとかぶってエラーが出てる。
中で使うクラス名と、ファイル名は別にしておかないといけない。

うーん、これはちょっとどうかと思うよ。

2010年5月5日水曜日

Jsdoc-ToolkitをExtendScriptで試す

Jsdoc-toolkitという、JavaDocのようなドキュメント生成ツールがある。
それをExtendScriptで使えないか、ずっと試そうと思ってたんだけど、GW休みになってようやく試す事ができたのでメモ。

Jsdoc-toolkitは、JavaDocと似た文法でJavaScriptのソースコードにコメントを書くと、それからHTMLのドキュメントを書き出してくれるフリーウェア。
JsDoc Toolkitを使う!
を参考にさせてもらう。上記ページにほとんどのことは書いてあるので、ドキュメントの記述方法など、詳しい事はそちらを参照して下さい。

手順としては、
1.Javaのインストール
これはMacには標準で入っているのでOK。

2.JsDoc-toolkitのインストール
http://code.google.com/p/jsdoc-toolkit/downloads/list
から最新のjsdoc_toolkit-x.x.x.zipを落として解凍し、任意の場所に置く。
(自分の習慣として、こういうのは/optに置いています。)

3.とりあえずドキュメントを用意
http://www12.atwiki.jp/aias-jsdoctoolkit/pages/13.html
のサンプルコードをテスト用に、そのままコピってくる。jsxなので#targetとか入れてみる。
#target "Illustrator"
/**
* 数値に1を加算して返す。
* @param {Number} num 数値
* @returns {Number} 引数で与えられた数値に1を加算した数値
*/

function incrementNumber(num) {
return num + 1;
}
これを
~/Desktop/jsdoctest/jsdoctest.jsx
に保存する。

4.コマンド実行
$ cd '/opt/jsdoc-toolkit/'
$ java -jar jsrun.jar app/run.js /Users/kanemu/Desktop/jsdoctest -x=jsx
-t=templates/jsdoc/ -d=/Users/kanemu/Desktop/jsdoctest/jsdoc
-xオプションは拡張子の指定。.jsならば入れなくても書き出すが、.jsxを書き出すためには-xオプションで指定しなければいけない。
-tオプションはHTMLテンプレート。これはJsdoc-toolkitに付属しているものを使うが、カスタマイズもできるみたい。
-dオプションは書き出し先の指定。

これでターミナルから実行すると……

できた!こんなふうに、ドキュメントが生成される。
いくつか試したが、ExtendScriptだからってとくにエラーを出すでもなく、きれいに行った。いいんじゃないかな?


さて、いちいちコマンドを打つのは面倒なんで、もっと簡単な方法はないかと、Antを使った方法(jsdoctoolkit-ant-task)なんかをいろいろ試したが、あんまり上手くいかなかったので割愛。

自分はスクリプトを書くのにTextMateを使っているので、それのバンドルがないかと思って探したら、見つけた。
jsdoctoolkit-tmbundle
これを試してみる。ターミナルから、
$ cd ~/Library/Application\ Support/TextMate/Bundles/
$ git clone http://github.com/choan/jsdoctoolkit-tmbundle.git Jsdoctoolkit.tmbundle
これでTextMateを立ち上げると、Bundleが入っている。Jsdoc-Toolkitも一緒に入るので、別にインストールしたものは削除してしまって良い。

ただ、このままだと.jsxの拡張子に対応しないので、Bundle EditorでJsdocToolkitバンドルの"Create Docs"の下の方にある
java -jar "${JSDOC_DIR}/jsrun.jar" "${JSDOC_DIR}/app/run.js" -a
-t="${JSDOC_DIR}/templates/jsdoc" -d="${DOCS_DIR}" -r .
の行を
java -jar "${JSDOC_DIR}/jsrun.jar" "${JSDOC_DIR}/app/run.js" -a
-x="js,jsx" -t="${JSDOC_DIR}/templates/jsdoc" -d="${DOCS_DIR}" -r .
に変更。

あと、Scope Selectorの「source.js」はJavaScriptバンドルの方で記述されているので、
JavaScriptバンドルの"JavaScript"の上の方の行
fileTypes = ( 'js', 'htc' );

fileTypes = ( 'js', 'jsx', 'jsxinc', 'htc' );
に変更。これで Bundles>JsDoc Toolkit>Cleate Docs を実行すれば、JsDocが生成される。

満足!これからはがんばってドキュメント書くぞ!

20100509追記:
もう一つ。jsdoctoolkit-tmbundleを入れているとjsdocの
/**
*
*/
が/*+tabで入力できるのだが、これの中でreturnを押すと行頭に * のついた行が1行増える。英語環境なら良いのだけど、CJK-Input.tmpluginを入れて日本語を使っていると、エンターで変換できなくなっちゃう……。
なので、 jsdoctoolkit-tmbundleの "Newline"の、入力補完をreturnからshift+returnに変更。これでjsdocの中も日本語入力可能に。

2010年5月3日月曜日

Illustrator EPSのみを.aiで別名保存する

EPSは、Illustratorで作成しても、Photoshopで作成してもどちらも拡張子は.eps。当然Windowsでは区別がつかないし、MacでもSnowLeopardからはクリエータが廃止されてしまった。
今後は拡張子が違う形式で運用していく必要がある。
なので、IllustratorEPSのみを.aiで再保存する方法を考えてみる。

まず、普通に書いた変換スクリプト。Illustrator CS3、MacOSX 10.5.8にて検証。
あまりテストしてないので、ファイルや環境によってはエラーを出すかもです。
#target "Illustrator"
(function(){

var fol=Folder.selectDialog('フォルダを選択して下さい');
if(!fol) return;

var mask=function(file){
return /^[^\.].*\.eps/i.test(file.name);
};

var files=fol.getFiles(mask);
for(var i=0,len=files.length;i<len;i++){
var file=files[i];
var doc=app.open(file, DocumentColorSpace.CMYK);
var aiFile=new File(file.absoluteURI.replace(/eps$/i,'ai'));
doc.saveAs(aiFile, undefined);
doc.close(SaveOptions.DONOTSAVECHANGES);
}

alert('処理を終わりました');

})();
これだと、maskフィルタでは.epsを判別しているだけなので、当然Photoshop EPSも全て.aiで再保存してしまう。

まず案1。Macのクリエータを使う方法。
#target "Illustrator"
(function(){

var fol=Folder.selectDialog('フォルダを選択して下さい');
if(!fol) return;

var mask=function(file){
if(/^[^\.].*\.eps/i.test(file.name)){
if(file.creator==='ART5'){
return true;
}
}
return false;
};

var files=fol.getFiles(mask);
for(var i=0,len=files.length;i<len;i++){
var file=files[i];
var doc=app.open(file, DocumentColorSpace.CMYK);
var aiFile=new File(file.absoluteURI.replace(/eps$/i,'ai'));
doc.saveAs(aiFile, undefined);
doc.close(SaveOptions.DONOTSAVECHANGES);
}

alert('処理を終わりました');

})();
maskフィルタ内で、.epsを拾った中でさらにクリエータがIllustrator形式のものだけにtrueを返している。
問題点は、Macでないと使えない事。MacでもSnowLeopard以降では動くかどうかわからない。
また、Macでもネットワークドライブ経由でコピーしたりして、クリエータを落としてしまったファイルの判別はできない。

案2。ファイルのXMPから判別する方法。
#target "Illustrator"
(function(){

var fol=Folder.selectDialog('フォルダを選択して下さい');
if(!fol) return;

var mask=function(file){
return /^[^\.].*\.eps/i.test(file.name);
};

var files=fol.getFiles(mask);
for(var i=0,len=files.length;i<len;i++){
var file=files[i];
var doc=app.open(file, DocumentColorSpace.CMYK);

var xmpStr=doc.XMPString;
var xmp=new XML(xmpStr);
var creator=xmp.xpath('/rdf:RDF/rdf:Description/xmp:CreatorTool');
if(!/Illustrator/i.test(creator)){
doc.close(SaveOptions.DONOTSAVECHANGES);
continue;
}

var aiFile=new File(file.absoluteURI.replace(/eps$/i,'ai'));
doc.saveAs(aiFile, undefined);
doc.close(SaveOptions.DONOTSAVECHANGES);
}

alert('処理を終わりました');

})();
まず.epsを判別し、一度Illustratorで開いた後、ファイルのXMPを読み出して、CreatorToolに"Illustrator"という文字が含まれていなければ保存せずに閉じる。
この方法ならWindows、Macともに使えるだろうが、ファイルにXMPを付加しない過去バージョンについては判別できない。
たぶん今も大量にあるIllustrator8形式のファイルには対応しないと思う。

案3。epsファイルのヘッダ部分を読み出す方法。
#target "Illustrator"
(function(){

var fol=Folder.selectDialog('フォルダを選択して下さい');
if(!fol) return;

var mask=function(file){
if(/^[^\.].*\.eps/i.test(file.name)){
if(file.open('r')){
var header=file.read(200);
if(/illustrator/i.test(header)){
return true;
}
}
}
return false;
};

var files=fol.getFiles(mask);
for(var i=0,len=files.length;i<len;i++){
var file=files[i];
var doc=app.open(file, DocumentColorSpace.CMYK);
var aiFile=new File(file.absoluteURI.replace(/eps$/i,'ai'));
doc.saveAs(aiFile, undefined);
doc.close(SaveOptions.DONOTSAVECHANGES);
}

alert('処理を終わりました');

})();

maskフィルタ内で.epsを拾った後、まずファイルをテキストとして一定量読み出し、そこに"illustrator"の文字が含まれているかどうかを調べ、あればtrueを返している。
これなら古いファイルにも対応するし、きっと上手くいく……と思うのだが、実際に運用してみると、ネットワークドライブのファイルを直接処理しようとするとひとつも処理できなかったり、他にも失敗する要素があるみたい。

どれが一番良いだろう?