シンタックスハイライトなHTMLに変換するオブジェクト指向AppleScript その1

はてなダイアリーにはシンタックスハイライトしてくれる記法がある。でも、AppleScriptには対応していない...。決して、色付きにしてコードの価値が上がる訳ではない。でも、予約語なのか、自分の名付けなのか、色で判断できると読み易いのも確か。(他人の書いたコードなんか特に)だから、日記の中ではいつも色付きのコードでいてもらいたいのである。

このまま待っていてもおそらく、AppleScriptには対応してくれないだろうと思い、それなら、自分でやってみようと始めてみた。最初は、予約語を分類したデータベースにして、それに基づいて色付けする、というシンプルな仕組みでOKだと思った。しかし、すべての予約語を網羅する方法が分からない...。AppleScript対応のアプリケーションは無数にあるだろうし、そうすると、予約語も無数に存在することになる。自分の環境だけでも網羅すれば良いのだけど、それだけでも大変な作業になりそう。この方法では無理だと思った。

次に考えたのは...。スクリプトエディタのAppleScriptコードをテキストエディタにコピーすると、リッチテキスト形式なら色やフォントも含めてコピーされる。このリッチテキストの持つ色やフォントの情報をHTMLに変換できれば良いのではないかと。

  • 問題は、リッチテキストの情報をどうやって取得するか、ということだが...
  • 調べてみると、意外にもシンプルな方法で取得できることがわかった。

開発環境

  • この日記のコードをスクリプトエディタにコピー&ペーストした場合、以下の置き換え操作(command-F)をしておかないと動作しない可能性があります。
    • ??は、インライン改行(option-L)にすべて置き換える
    • 半角の¥は、半角の\にすべて置き換える

hello world!のリッチテキスト情報


tell application "Script Editor"
tell document 1
set everyText to attribute run of every paragraph
set everyFont to font of attribute run of every paragraph
set everySize to size of attribute run of every paragraph
set everyColor to color of attribute run of every paragraph
end tell
end tell

  • 上記のようなコードを用意して、以下のAppleScriptコードのリッチテキスト情報を取得してみた。


display dialog "hello world!"

  • every paragraphによって形態素解析されたコードは、AppleScriptのリストとして表現され、順番に並んでいる。
  • もし、2行目以降があるとすれば{{1行目}, {2行目}, {3行目}...}のように続くはず。
    • everyTextの結果:


{{"display dialog", " ", "\"", "hello world!", "\""}}

    • everyFontの結果:


{{"CourierNewPSMT", "Helvetica", "CourierNewPSMT", "CourierNewPSMT", "CourierNewPSMT"}}

    • everySizeの結果:


{{12.0, 12.0, 12.0, 12.0, 12.0}}

    • everyColorの結果:


{{{0, 0, 65535}, {0, 0, 0}, {65535, 52428, 26214}, {0, 0, 0}, {65535, 52428, 26214}}}

  • 例えば、最初の"Display Dialog"は、以下の情報が付加されているということ。
    • Font:"CourierNewPSMT"
    • Size:12.0
    • Color:{0, 0, 65535}(おそらくRGB値で青が最大輝度ということ)

とりあえず動くコードを作る

  • この情報さえ取得できれば、後はひたすらスタイル情報に変換して、タグで囲いまくるだけなのだ。
  • 最初はとりあえず動くものを目指して、必要最小限のコードを手順に従って書いてみた。(まずは色情報のみ変換する)


--??は、インライン改行(option-L)にすべて置き換える
--半角の¥は、半角の/にすべて置き換える

tell application "Script Editor"
tell document 1
set everyText to attribute run of every paragraph
set everyFont to font of attribute run of every paragraph
set everySize to size of attribute run of every paragraph
set everyColor to color of attribute run of every paragraph
end tell
end tell

set html to ""
repeat with i from 1 to everyText's number
set line_text to everyText's item i
set line_color to everyColor's item i
repeat with j from 1 to line_text's number
set aText to line_text's item j
set aColor to line_color's item j
--特殊文字の置き換え
set k to 0
repeat with str in {"\t", "&", "<", ">"}
set k to k + 1
set AppleScript's text item delimiters to str
set temp_list to aText's text items
set AppleScript's text item delimiters to {" ", "&amp;", "&lt;", "&gt;"}'s item k
set aText to temp_list as text
set AppleScript's text item delimiters to ""
end repeat
--rgbコード生成
set R to (aColor's item 1) div 256
set G to (aColor's item 2) div 256
set B to (aColor's item 3) div 256
set rgb to "rgb(" & R & "," & G & "," & B & ")"
--タグ生成
"<span style=\"color:" & rgb & ";\">" & aText & "</span>"
set html to html & result
end repeat
end repeat

set html to "<pre>\n" & html & "\n</pre>" & return
set the clipboard to html

次の日に続く...