KeySnailついて

自分はEmacsユーザーでもありませんが、KeyConfigの代わりにKeySnailを使い始めました。
そもそもKeyConfigとは役割違うし、KeyConfigもFirefox4対応したので併用しています。
keysnailはuserChrome.jsのキー特化みたいな存在で、便利なAPIがある環境みたいなとらえ方でもいいかもしれないです。(emacsのキーバインドは一切使わないで、まっさらな状態で始めました)

KeySnailのプラグイン開発について

JSReferenceというMDN(MDC)やECMA-262 3rd EditionをKeySnailのプロンプトから検索できるプラグインを書いたので、これに沿って説明していきます。

こんな感じの動作するやつです。(フルスクリーンで見た方がいい)
端的に言えばChemr-jsみたいな感じでインデックスをキャッシュしてリファレンスを検索するものです。

KeySnailのプラグイン開発の情報元

KeySnailのプラグイン開発についての情報はドキュメントが不足(分散)している印象を受けるため、wikiに情報を反映させたり(github wiki使いにくいのでもっと他のがあるといいのだけど)、ブログなど開発手順を記したりすると他の人のためにもなると思います。

メタデータ

まずKeySnailにはドキュメントも表示できる優秀なプラグインマネージャーとGUIでも追加したコマンドなどの管理ができる(.keysnail.jsを直接いじるのも可能)ため、プラグインを作った時にはメタデータが結構重要です。

プラグインマネージャー
GUIで管理できるキーマネージャー
プラグインはJavaScript(拡張子は .ks.js)で書きますが、プラグイン内部にE4Xを利用してメタ情報を含めることができます。(是非入れて)
メタ情報の書式はWriting Plugins (Japanese)に詳細に書いてあるので、これと他のPluginをまねるのが早いです。E4Xで書くのでプラグインの詳細な情報を入れるdetail内には簡単なWiki記法を使ってプラグインの詳細を書くことができます。

<detail lang="ja"><![CDATA[
複数行のヒアドキュメント
のような書き方ができる。
簡単なWikiみたいな記法も使える

見出し:
    - == heading1 == で第一見出し(h1)
    - === heading2 === で第二見出し(h2)
    - ==== heading3 ==== で第三見出し(h3)
整形式テキスト:
    >|| と ||< で囲むと整形式テキスト(pre)になります。
    コードなどを書きたい場合に使用できるでしょう。
など
 ]]></detail>

自分の書いたJSReferenceでは以下のようなメタ情報を書きました。

var PLUGIN_INFO =
        <KeySnailPlugin>
            <name>JsReferrence</name>
            <description>JavaScriptリファレンスを引く</description>
            <updateURL>https://github.com/azu/KeySnail-Plugins/raw/master/JSReference/js-referrence.ks.js</updateURL>
            <iconURL>https://github.com/azu/KeySnail-Plugins/raw/master/JSReference/MyIcon.png</iconURL>
            <version>0.0.1</version>
            <author mail="[email protected]" homepage="https://efcl.info/">azu</author>
            <license>The MIT License</license>
            <provides>
                <ext>JsReferrence-open-prompt</ext>
                <ext>JsReferrence-reIndex</ext>
            </provides>
            <detail><![CDATA[]]></detail>
            <detail lang="ja"><![CDATA[
            === 使い方 ===
            ....略.....
            ]]></detail>
        </KeySnailPlugin>;

それぞれの属性についてはWriting Plugins (Japanese)を見ればいいので飛ばしますが、E4Xを利用しているのでプラグイン内部からこれらのメタデータを利用する事もできます。
たとえば、プラグイン内部からname(JsReferrence)を取得したいと思ったら、

var name = PLUGIN_INFO.name.toString();// JsReferrence

という風に参照することができます。詳しいE4Xのプロパティやメソッドについてはrephrase § E4Xが詳しいです。
E4X自体については以下にリンクをいろいろまとめてあります。

以上でメタデータについては終わりですが、アップデートURLやアイコンURLなども指定できてとてもいい感じにできてると思います。

デバッグ方法

自分のデバッグ方法を書きますがもっと効率のいい方法があったらお知らせくださいな。
まずKeySnailにはいくつかのデバッグ関係に使えそうなのAPIがあります。

util.message("format", [args...]); // コンソールにログを出力
display.showPopup(title, msg, [options]);// Growlみたいな通知(Firefoxの通知のやつ)
display.prettyPrint(msg, [options]);// DOM内にポップアップで出力
display.notify(aMsg, aButtons, aIcon);// ページ上部に出てくるインストールButtonみたいな感じ

display.prettyPrintは以下みたいなのが出ます。

display.prettyPrint
他のutil関係のAPIはutil.js – GitHubに載っています。(ただこれがkeysnail API全部ではなくてドキュメント化されてないものも含めて他にもたくさんあります)

これらの用意されてる出力形式はオブジェクトを渡すと[object Object]と表示されてしまうので、Firebugでオブジェクトの中身を見られる関数を.keysnail.js(or _keysnail.js)に書き足してデバッグに使っていました。

// PRESERVE エリア内に
// firebugでオブジェクトをインスペクト
function fbug(x) {
    var args = Array.slice(arguments);
    var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
                        .getService(Components.interfaces.nsIWindowMediator);
    var {Firebug} = windowManager.getMostRecentWindow("navigator:browser");
    if (Firebug.Console.isEnabled() && Firebug.toggleBar(true, 'console')) {
        Firebug.Console.logFormatted(args);
    }
    return args.length > 1 ? args : args[0];
}

上を書き足したら、プラグイン内でfbugというメソッドが使えるようになります。
fbugに適当な値を渡すとFirebugでそれを開いて表示してくれます。(要はconsole.logみたいなもの)
この関数はxqjsから拝借しています。xqjsはとても便利なJavaScript実行コンソールなので是非使うといいです。

注意としてマルチバイトの文字列を渡すと文字化けするので、Writing Plugins (Japanese)にも書いてありましたが、そのときはL() と M()を使いましょう。

プラグインのリロードについて

プラグインのインストールは.ks.jsファイルへのリンク上で右クリックかプラグインマネージャーから行う事ができます。
プラグイン開発しているときはkeysnailのプラグインディレクトリ(プロファイル/keysnail/plugin)に.ks.jsファイルを置いて開発すると思います。変更を反映させるとき、毎回プラグインマネージャーから”プラグインのリロード”をするのは面倒なので、以下のようなものを.keysnail.jsに書き込んで使ってます。

// PRESERVE エリアの外に
key.setViewKey(['ESC', 'ESC'], function (ev) {
    userscript.loadPlugins();
}, 'プラグインのリロード');

これでESCを2回押したらプラグインのリロードするようになるため、プラグインを書き換えて実行→確認がすぐにできるようになります。(ページのリロードすらいらない)

プラグインのAPI

プラグイン内でthisを見ると、プラグインから使える関数などが見えてくるかも知れません。

fbug(this) -thisをFirebugで見る
KeySnail 1.8.5からはundersocre.jsを使えるようになっています。

また、プラグイン内でグローバル空間(this)を拡張しても問題ないそうです。
今回、KeySnailプラグイン書くために使ったAPIはJSONでデータの読み書きをするpersist.preserve(aObj, aName) , persist.restore(aName) と 渡した配列から絞り込み検索UIを簡単に使えるprompt.selectorです。
特にprompt.selectorは便利なので、これのためにKeysnailを使うのもありです。(はてなブックマーク検索ができるHatebnailとかがすごく便利)

それぞれのAPIの使い方は以下を参考にしました。

注意点としてpersist.preserveに渡すオブジェクトは特にシリアライズしないでそのままオブジェクトを渡せばいいようです。また、prompt.selectorのflagsでHIDDEN IGNORE, ICON以外に数値で指定されている場合がありますが、内部でそれぞれ対応する数値が割り当てされているので、直接数値で指定しても大丈夫なようです。

他にもいろいろ使えるAPIがありますが、Github wikiの方に適当にまとめておいたのでそこら辺を参照するといいです。

プラグイン開発の参考リンク

Writing Plugins (Japanese) – GitHub

以上でKeySnailのプラグイン開発については終わりです。
是非、引っかかった点や参考にしたものなどは文章化してください。これは別にKeySnailに限ったことではありませんが、文章化されていないコードは非実在コードになりがちなため、文章やドキュメントにすることは大切だと思います。

azu/KeySnail-Plugins – GitHubi : https://github.com/azu/KeySnail-Plugins

KeySnaili : https://github.com/mooz/keysnail/wiki