SciTEのJavaScriptのインデントと戦う

SciTEを使ってJavaScriptを書いているとたまにオートインデントが動かないことがある。
例えばこんなケース。

m.Core = Backbone.Model.extend({
    initialize: function () {/*ここでReturnキーを押したとき*/}
});

そんなんスクリプト書いて直せばいい。ええ、もちろんそう思いましたよ。まずはインデント位置を求めて、それをもとにインデントし直す…。

-- 古典的なインデント幅の求め方
math.floor(editor.LineIndentation[editor:LineFromPosition(editor.CurrentPos - 1)] / editor.TabWidth)

しかし、この方法は全く上手くいかない。というのもこのスクリプト自体、オートインデントが動作していることを前提としているからだ。
実はこれ、先日のポスト、「キャレットのあるブロックの開始位置を取得する」手法を使うことで適当っぽいインデント幅を取得することができる。

prevFoldLine = scite.SendEditor(SCI_GETFOLDPARENT, editor:LineFromPosition(editor.CurrentPos))

if prevFoldLine < 0 then
    -- 一番外側の場合だけ固定で0
    newIndent = 0

else
    -- それ以外の場合、手前のブロックを元にインデント位置を算出
    newIndent = math.floor(editor.LineIndentation[prevFoldLine] / editor.TabWidth) + 1
end

新しいブロック→新しいインデントのハズですからね。あとはこれを元に適当にインデントを直してやればいい。
ただ、Douglas Clockford式に、一関数 一 var でコーディングしている時、二つ目以降の変数のインデントがズレる。これはまた別の問題。

(function () {
    var func1 = function () {
            //...
        },
        func2 = function () {/*ここでReturnキーを押したとき*/};
}());

SciTEのLuaでキャレットのあるブロックの開始位置を取得する

SciTEをLua拡張しているとたまに、今のブロック(スコープ)の開始位置を知りたいことがある。例えばJavaScriptで new Backbone.Model.extend({ ってやってたら Model のプロパティをオートコンプリートで表示させたい、とかそんな感じ。
これって、キャレットの位置から一行ずつさかのぼって、カッコの数を数えて…うげぇ、ってのを想像してたが、実は Scintilla のドキュメントを眺めてたところ案外簡単にできることが分かった。

scite.SendEditor(SCI_GETFOLDPARENT, editor:LineFromPosition(editor.CurrentPos))

これだけ。
SCI_GETFOLDPARENT は引数の位置と同一レベルかつ、直近の折り畳み位置を取得するというもの。折り畳み位置は各ファイルタイプのブロック単位で設定されるので、引数にキャレットの現在位置を与えれば、直近のブロック開始位置を求められる、というワケだ。
夢が広がりますね。

続:SciTEでEmacsキーバインド

さて、時間もできたことだし、そろそろブログでも再開すっかね、と、その前に、前に広げてた風呂敷をちょいと畳んでおかねば。
前回のポストで(既に一年の時日が経っているわけだが)書いた、SciTEでEmacsキーバインドをやる話、何もアレは「とりあえずやってみたけど、でもどうせ使わねぇし」と放置されているワケではない。バグ修正はもちろん、kill-ringまで動くよう、アップデートされていた。ただちょっと、はてなブログの文字数制限という壁に行く手を阻まれ、二の足を踏んでいた、と、そういう事情が…あー、まあ、面倒だった、と、そういうことよ。
なわけで、最新のluaを以下に格納したので興味があればどうぞ、と。
https://docs.google.com/file/d/0B-eAonTsTeJOTzlsUUhQVU81X0k/edit?usp=sharing

IEで動的にCSSを読ませる時の注意点

事の発端は、AJAXで画面をロードしまくったところ、突如IECSSを無視し始めたことだった。
調査を進めていくと、この問題は一定数以上画面をロードすると発生することがわかった。そして、〜IE9にはCSSを31個(ルールとしては4095個)しか読み込めないという制約があることが判明する。
http://stackoverflow.com/questions/9906794/internet-explorers-css-rules-limits

ここでIEに文句を言ってもしょうがない。ぱっと思いつく手は、一つのStyleタグにスタイルをJSで流し込む方法である。

<body>

<!--ページ本体-->

<!--IEでCSSをヘッダ以外で読み込ませる場合、CSSは適用対象のHTMLより後に無くてはならない-->
<style id="forge" type="text/css"></style>
</body>
cssForge = function (style) {
  document.getElementById("forge").innerHTML += style;
}

この手は一見上手くいくのだが、IE8でエラーを吐く。未知のエラーとかそんな感じのヤツ。どうも style タグの innerHTML は〜IE8で読み取り専用らしい。
ここでIEに文句を言ってもしょうがない。ぱっと思いつく手は、innerHTML が読み取り専用でない要素を親にし、親からinnerHTMLを書き換える方法である。

<body>

<!--ページ本体-->

<div id="forge">
  <style type="text/css"></style>
</div>
</body>
cssForge = function (style) {
  var forge = document.getElementById("forge"),
    melt = forge.innerHTML.split(/<\/?style[^>]*>/gi);//IE8はstyleタグを大文字で挿入する為、i オプションが必須

  forge.innerHTML = '<style type="text/css">' + melt[1] + style + '</style>'
}

この手は一見上手くいくのだが、IE8でどうにも上手くいかない。F12でデバッガを立ち上げ、実際に挿入されたinnerHTMLを確認してみる。すると挿入したはずの