2008年11月24日月曜日

CotEditorで不可視ファイルを表示する


AYNiMac : 自作ソフト : CotEditor
Mac用テキストエディタ。
UTF-8もSJISも表示できて、正規表現もしっかり実装していて、しかもフリー。
今いちばん充実してるんじゃないだろうか。

で、ちょっとしたTipsのメモ。
.bash_profileとかの不過視ファイルを編集したいとき(それぐらいターミナルでやれって言われそうだけど)、CotEditorではファイルメニューの「開く」では普通には表示されない。
でも、Shiftキーを押しながらファイルメニューを開くと、「非表示ファイルを開く」が現れる。そこから選択すればよい。

2008年11月23日日曜日

Groovyでテキスト処理を試す

組版・DTP関連でプログラムを使ったテキスト処理をするなら、普通はsed、perl、rubyなんかを使うと思う。でもここはあえてgroovyでやってみる。

まずテキストを用意。青空文庫から「我輩は猫である」のテキスト版を引っ張ってきて、それの一部を使うことにする。
 吾輩《わがはい》は猫である。名前はまだ無い。
 どこで生れたかとんと見当《けんとう》がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番|獰悪《どうあく》な種族であったそうだ。この書生というのは時々我々を捕《つかま》えて煮《に》て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌《てのひら》に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始《みはじめ》であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶《やかん》だ。その後《ご》猫にもだいぶ逢《あ》ったがこんな片輪《かたわ》には一度も出会《でく》わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙《けむり》を吹く。どうも咽《む》せぽくて実に弱った。これが人間の飲む煙草《たばこ》というものである事はようやくこの頃知った。

この文章を"waganeko.txt"としてSJISで保存。とりあえずデスクトップに置く。
それに対して、
  • ルビにxhtml風のタグをつける。
  • 行ごとに<p></p>タグをつける。
  • 語尾が"んぬ。"で終わるようにする。
  • SJISのテキストをUTF8にする。
  • .htmlをつけて保存。
ここまでやってみる。
以下Groovyコード。
def inputCharCode = "SJIS" //入力側文字コード
def outputCharCode = "UTF8" //出力側文字コード

//変換マップ※なぜか行頭にスペースがないとエラーになる?
def replaceTable=[
/^/:"<p>",
/$/:"</p>",
/\n/:"</p><p>",
/|{0,1}([一-龠]+?)《([ぁ-ん]+?)》/:
{ m0, m1, m2 -> "<ruby><rb>$m1</rb><rt>$m2</rt></ruby>" },
"。":"んぬ。"
]

//--------------------処理ここから--------------------
if(args.length < 1){
println("ファイルを指定して下さい。")

}else{
//argsが1個以上なら数を数えてループ
for(i in 0..< args.length){

//ファイルの中身を読む
def file = new File(args[i])
String str = file.getText(inputCharCode)

//変換マップの中を順に置換する
replaceTable.each{key,value -> str=str.replaceAll(key,value)}

//同じ名前の.htmlを作って書き込み
String newPath = args[i].replace(".txt",".html")
def dir = new File(newPath)
dir.write(str,outputCharCode)
println("-------------${newPath}を書き出しました。")
}
}

これをテキストエディタに貼付け、"aozora.groovy"って名前をつけて保存。とりあえずデスクトップに置く。
ターミナルを立ち上げ、
$ cd Desktop/
$ groovy aozora.groovy waganeko.txt
---------------waganeko.htmlを書き出しました。

とすれば、waganeko.htmlが書き出される。

確認のために、XHTMLルビサポートというFirefox用アドオンがあるので、それをインストールしてFirefoxで開いてみよう。

Pタグ以下しかないんで、完璧なhtmlになってはいないけれど、そのへんはテストってことで。

変換を変えたいのなら、変換マップの中身を書き換えればいいだけ。
簡単だ!

2008年11月22日土曜日

正規表現、先読みと後読み

正規表現でテキスト処理をする際、いちばん分かりにくくて、いちばん役に立ったのが先読み後読み。どうもここが正規表現のキモのような気がする。
そういうわけでメモ。

Groovyの場合、肯定的先読みは(?=pattern)、肯定的後読みは(?<=pattern)と書く。
patternの部分は判別させたい文字列。

先読み、後読みは何に使うのかというと、「文字列の前と後にどんな文字が来るか判別したくて、なおかつその部分にはマッチさせたくない」という場合に使う。
たとえば、「hoge(?=pattern)」は patternが後ろにあるhogeにマッチするが、(?=pattern)部分にはマッチしない。
「(?<=pattern)hoge」は patternが前にあるhogeにマッチするが、(?<=pattern)部分にはマッチしない。

マッチしたい文字の前に後読み、後ろに先読みを使うのがミソ。
順番でいうと(後読み)(欲しい部分)(先読み)と使う。
ここまでOK?

実例。下のような文章があったとする。
長嶋 茂雄の誕生日は1936年2月20日。
1974(昭和11)年2月20日から
2008(平成20)年11月20日の間の日数は26,572日、
72年と274日になります。ところで、ただいまの時間は7:19です。

「ところで」の部分が苦しい…のは置いといて、
このテキストの「1桁と2桁の数字だけ<tcy></tcy>というタグで囲みたい」
どうしよう?

まず、1桁と2桁の数字だから、
\d{1,2}

だけど、これだと3桁以上の数字にもマッチしてしまうので、前後に数字がない場合だけマッチさせたい。
(?<=[^\d])(\d{1,2})(?=[^\d])

また、コンマ区切りと小数点、時間を表しているコロンがあった場合もマッチさせたくない。
(?<=[^\d\.,:])(\d{1,2})(?=[^\d\.,:])

この文章にはないけれど、行頭もしくは行末に数字が来るかもしれない。
(?<=^|[^\d\.,:])(\d{1,2})(?=[^\d\.,:]|$)


これで、数字2桁までの「数字部分にだけ」マッチする。
以下Groovyスクリプト。
def text="""長嶋 茂雄の誕生日は1936年2月20日。
1974(昭和11)年2月20日から
2008(平成20)年11月20日の間の日数は26,572日、
72年と274日になります。ところで、ただいまの時間は7:19です。"""

//半角1,2桁の数字にタテ中ヨコ用タグ付け
text=text.replaceAll(/(?<=^|[^\d\.,:])(\d{1,2})(?=[^\d\.,:]|$)/) {
m0, m1 -> "<tcy>${m1}</tcy>"
}
println(text)



ところで、JavaScriptも正規表現を使えるけれど、後読みをサポートしていない
仕方がないので、後読み部分を普通にマッチさせる。後読み部分も1字なので不具合は出ないと思う。
以下ExtendScript。
var text="長嶋 茂雄の誕生日は1936年2月20日。\n"
+"1974(昭和11)年2月20日から\n"
+"2008(平成20)年11月20日の間の日数は26,572日、\n"
+"72年と274日になります。ところで、ただいまの時間は7:19です。"
//半角1,2桁の数字にタテ中ヨコ用タグ付け
text=text.replace(/(^|[^\d\.,:])(\d{1,2})(?=[^\d\.,:]|$)/g,"$1"+"<tcy>"+"$2"+"</tcy>");
$.writeln(text);

2008年11月19日水曜日

Illustartor→InDesign間でBridgeTalk

IllustratorのvisibleBoundsとgeometricBoundsが、yが上に向かって増える仕様なのでInDesignと合わない。むかついたので、腹いせにBoundsをInDesign風に置き換えるfunctionを書いた。
#target "Illustrator"

forIndBounds=function(bounds){
var h=app.activeDocument.height;
var ary=[h-bounds[1],bounds[0],h-bounds[3],bounds[2]];
return ary;
};

//AIの場合は単位を設定しても常にポイントでくる
var selObj = app.activeDocument.selection;
for(var i=0;i<selObj.length;i++){
var aivb=selObj[i].visibleBounds;
var aigb=selObj[i].geometricBounds;
};

ただ、これだけではInDesignに流用は全くできない。
せっかくならアプリ間連携してInDesignで直接テキストフレーム生成できるといいよね?
そういうわけで余計な苦労をはじめるのだ。

とりあえず拾ったgeometricBoundsを全部Arrayにつっこむ。
そしてInDesignに渡す方法を考える。
illustrator13.executeScriptの正体 - なにする?DTP WEB
↑ここの記事で、AdobeCS間で通信するメソッドがあるのを知った。
indesign5.executeScript("alert(\"こんにちはInDesign\")");

だけども、scriptがレアなままでは渡せない、一度Stringになっている必要がある。
変数はどうやって渡すの?
同じブログの記事で、executeScriptの正体はBridgeTalkだと知る。
BridgeTalkって何? - なにする?DTP WEB
BridgeTalk!!

それを使って、functionと変数をなんとか渡そうとしてるうちに、それもfunctionになった。
とりあえず、InD側の単位は全部ポイントに合わせ、線幅や色も決めうち。
あっはっは!

2008年11月16日日曜日

AdobeCS3のJavaScriptでガベージコレクション

$.gc () 

これだけ。
WIKIPEDIA: ガベージコレクション
ガベージコレクションというのは、いらなくなったメモリを解放する処理で、ようするにメモリ関連のエラーに効果があるらしいんだけど、実際の所どれほど効果があるものなのかよくわからない。

今自分の会社でお客さんに渡しているスクリプトが
「使用するとだんだんInDesignが重くなる」
と言われていたので、これを処理の末尾にそっと挿入。
おまじない。

不具合が解消されたかはまだ不明。こんど聞いてみないとな…。