読者です 読者をやめる 読者になる 読者になる

KeySnail導入でつまづいた事

今までVimperatorを愛用してましたが、KeySnailがアツそうなので、ようやく移行しました。
案の定、つまづいて転んだので、どこを擦り剥いたか、まとめておこうと思います。

とりあえず、環境などは以下です。

  • WindowsXP SP3 32bit
  • KeySnail 2.0.1

Firefoxのバージョン

KeySnailへの移行に際し、対応しているFirefoxのバージョンがよくわからなかったので、 とりあえずそのままインストールして下記プラグインを入れました。(※1)

  • bmany
  • Builtin command as Ext
  • Caret hint
  • HoK
  • Multi Requester from KeySnail
  • query-replace
  • サイトローカル・キーマップ
  • Tanything

予想通り、動作しないものが色々あったので、ヘルプ - ソフトウェア更新 としたら、 Firefox12になりましたが、まだTanythingが動作しませんでした。
ので、最新の22にしてみたところ、悪名通りというかコンテキストメニューが動作しなくなったりしたので、 適当に18にダウングレードしたら動作するようになったので、18を使うことにしました。

KeySnailとFirefoxのバージョンについて言及しているWebページが見つからなかったんですが、 どのバージョンを使ったら良いかご存知の方がいらっしゃいましたら教えて欲しいです。

キャレットモードで移動ができない

;cでキャレットモードに入った後、キャレットを移動させようとしても、 画面がスクロールするだけでキャレットが動かない・・・。
私の環境だけ?いや、そんなことないよなぁ。と思うんですが、ググっても出てこない。。

.keysnail.jsを見てみると、該当箇所の設定は以下のようになっていました。
順序変えて1行にまとめてキーも変えてますが、初回起動時に"バリバリEmacs"みたいな感じの設定で生成したやつです。

key.setCaretKey("l", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectCharNext") : goDoCommand("cmd_scrollRight"); }, 'キャレットを一文字右へ移動', false);
key.setCaretKey("h", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectCharPrevious") : goDoCommand("cmd_scrollLeft"); }, 'キャレットを一文字左へ移動', false);
key.setCaretKey("L", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectWordNext") : goDoCommand("cmd_wordNext"); }, 'キャレットを一単語右へ移動', false);
key.setCaretKey("H", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectWordPrevious") : goDoCommand("cmd_wordPrevious"); }, 'キャレットを一単語左へ移動', false);
key.setCaretKey("j", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectLineNext") : goDoCommand("cmd_scrollLineDown"); }, 'キャレットを一行下へ', false);
key.setCaretKey("k", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectLinePrevious") : goDoCommand("cmd_scrollLineUp"); }, 'キャレットを一行上へ', false);
key.setCaretKey("SPC", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectPageNext") : goDoCommand("cmd_movePageDown"); }, 'キャレットを一画面分下へ', false);
key.setCaretKey("b", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectPagePrevious") : goDoCommand("cmd_movePageUp"); }, 'キャレットを一画面分上へ', false);
key.setCaretKey("^", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectBeginLine") : goDoCommand("cmd_beginLine"); }, 'キャレットを行頭へ移動', false);
key.setCaretKey("$", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectEndLine") : goDoCommand("cmd_endLine"); }, 'キャレットを行末へ移動', false);
key.setCaretKey("g", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectTop") : goDoCommand("cmd_scrollTop"); }, 'キャレットをページ先頭へ移動', false);
key.setCaretKey("G", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectEndLine") : goDoCommand("cmd_endLine"); }, 'キャレットをページ末尾へ移動', false);

横長で見づらいですが、右の方にgoDoCommand("...scroll...")とあります。
スクロールさせてそうです。確かにキャレットは動かなそう。
で、初回起動時に生成された設定に、モード毎に移動の設定があったのを思い出し、 EditModeの設定を見てみると、以下のようになってました。

key.setEditKey('C-l', function (ev) { command.nextChar(ev); }, '一文字右へ移動', false);
key.setEditKey('C-h', function (ev) { command.previousChar(ev); }, '一文字左へ移動', false);
key.setEditKey('C-L', function (ev) { command.forwardWord(ev); }, '一単語右へ移動', false);
key.setEditKey('C-H', function (ev) { command.backwardWord(ev); }, '一単語左へ移動', false);
key.setEditKey('C-j', function (ev) { command.nextLine(ev); }, '一行下へ', false);
key.setEditKey('C-k', function (ev) { command.previousLine(ev); }, '一行上へ', false);
key.setEditKey('C-J', function (ev) { command.pageDown(ev); }, '一画面分下へ', false);
key.setEditKey('C-K', function (ev) { command.pageUp(ev); }, '一画面分上へ', false);
key.setEditKey('C-a', function (ev) { command.beginLine(ev); }, '行頭へ移動', false);
key.setEditKey('C-e', function (ev) { command.endLine(ev); }, '行末へ', false);
key.setEditKey('C-{', function (ev) { command.moveTop(ev); }, 'テキストエリア先頭へ', false);
key.setEditKey('C-}', function (ev) { command.moveBottom(ev); }, 'テキストエリア末尾へ', false);

試しに、上記の設定を真似てCaretModeの設定を以下のように変えてみたところ、 期待通りの動作をするようになりました。(※2)(※3)

key.setCaretKey("l", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectCharNext") : command.nextChar(ev); }, 'キャレットを一文字右へ移動', false);
key.setCaretKey("h", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectCharPrevious") : command.previousChar(ev); }, 'キャレットを一文字左へ移動', false);
key.setCaretKey("L", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectWordNext") : command.forwardWord(ev); }, 'キャレットを一単語右へ移動', false);
key.setCaretKey("H", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectWordPrevious") : command.backwardWord(ev); }, 'キャレットを一単語左へ移動', false);
key.setCaretKey("j", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectLineNext") : command.nextLine(ev); }, 'キャレットを一行下へ', false);
key.setCaretKey("k", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectLinePrevious") : command.previousLine(ev); }, 'キャレットを一行上へ', false);
key.setCaretKey("SPC", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectPageNext") : command.pageDown(ev); }, 'キャレットを一画面分下へ', false);
key.setCaretKey("b", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectPagePrevious") : command.pageUp(ev); }, 'キャレットを一画面分上へ', false);
key.setCaretKey("^", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectBeginLine") : command.beginLine(ev); }, 'キャレットを行頭へ移動', false);
key.setCaretKey("$", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectEndLine") : command.endLine(ev); }, 'キャレットを行末へ移動', false);
key.setCaretKey("g", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectTop") : command.moveTop(ev); }, 'キャレットをページ先頭へ移動', false);
key.setCaretKey("G", function (ev) { ev.target.ksMarked ? goDoCommand("cmd_selectBottom") : command.moveBottom(ev); }, 'キャレットをページ末尾へ移動', false);

キャレットモードから抜けられない

キャレットの移動ができるようになり、よしよしとC-gしたんですが、キャレットが依然として表示されたままです・・・。
私の環境だけ?いや、そんなことないよなぁ。と思うんですが、またしても出てこない。。

で、初回起動時に生成された設定に、KeyBoardQuitのフックがあったのを思い出し、 その中の処理で匂うところを無知なりに変えたりググったりした結果、 以下の設定で期待通りの動作になりました。(※2)(※4)

hook.addToHook('KeyBoardQuit', function (aEvent) {
    if (key.currentKeySequence.length) {
        return;
    }
    command.closeFindBar();
    var marked = command.marked(aEvent);
    if (util.isCaretEnabled()) {
        if (marked) {
            command.resetMark(aEvent);
        } else {
            if ("blur" in aEvent.target) {
                aEvent.target.blur();
            }
            util.setBoolPref("accessibility.browsewithcaret", false);
            gBrowser.focus();
            _content.focus();
        }
    } else {
        goDoCommand("cmd_selectNone");
    }
    if (KeySnail.windowType === "navigator:browser" && !marked) {
        key.generateKey(aEvent.originalTarget, KeyEvent.DOM_VK_ESCAPE, true);
    }
});

初回に生成された設定に、以下の一行を追加しています。

util.setBoolPref("accessibility.browsewithcaret", false);

その他

※1 Firefox3.xを使ってました。まずいですかね?スルーして下さい。
※2 FirefoxのアドオンにもJavaScriptにも無知なので、これで良いのか自信ありません。
※3 ページの先頭/末尾への移動は上手くいかないです。
※4 参考リンクをつけたかったですが、あまりに試行錯誤したので思い出せません。

あとがき

とはいえ、KeySnail素晴らしいす。
今まで、Vimperatorとyamyをゴリゴリ設定してEmacsっぽくしてたのが、 KeySnailだけでもっと快適になりそうで楽しみです。