Hatena::ブログ(Diary)

mooz deceives you

(about 'mooz) ; => "See http://mooz.github.com/index-ja.html"

 | 

November 01 (Sun), 2009

サイト毎にキーバインドを定義することが可能となるプラグインをリリースしました

サイトローカル・キーマップ

ウェブサイト毎にキーバインドを定義 / 再定義 / 無効にすることが可能となるプラグイン「サイトローカル・キーマップ」をリリースしました。

インストールは以下のプラグイン名を右クリックし、「このプラグインをインストール」を選択することで行えます。

サイトローカル・キーマップ ウェブサイト毎にキーバインドを定義

f:id:mooz:20091101153723p:image

どんなことができるのか

j / k にスクロールのアップ / ダウンを登録しているような方は Gmail など、独自のショートカットキーを提供するサイトでキーバインドがバッティングしてしまうため、次のような対応を取るしかありませんでした。

  • エスケープキーを利用し j / k の代わりに C-q j / C-q k などと打ち込む
  • ブラックリストに Gmail を登録し、そのサイトでは KeySnail をサスペンドする
  • KeySnail 側でショートカットキーが被らないように注意する

しかしこういった方法は、どれも一長一短、一長十短で、本質的な解決には至っていません。

そこで今回リリースされた「サイトローカル・キーマップ」の出番です。このプラグインをインストールすることにより、次のようなことが可能となります。

  • Gmail では KeySnail の j / k を無効に
  • そのサイトに特化したキーバインドを定義
    • Amazon で C-1 を押したら〜
    • Youtube で C-1 を押したら〜

先ほどの問題も、ばっちり解決されます。

設定方法

初期化ファイルの PRESERVE エリアへ次のようなコードを張り付けることで、サイトローカルなキーバインドを定義することができます。

// Site local keymap {{ ===================================================== //

var local = {};
plugins.options["site_local_keymap.local_keymap"] = local;

function fake(k, i) function () { key.feed(k, i); };
function pass(k, i) [k, fake(k, i)];
function ignore(k, i) [k, null];

local["^https?://mail.google.com/mail/"] = [
    pass(['g', 'i'], 3),
    pass(['g', 's'], 3),
    pass(['g', 't'], 3),
    pass(['g', 'd'], 3),
    pass(['g', 'a'], 3),
    pass(['g', 'b'], 3),
    pass(['g', 'c'], 3),
    pass(['g', 'k'], 3),
    // thread list
    pass(['*', 'a'], 3),
    pass(['*', 'n'], 3),
    pass(['*', 'r'], 3),
    pass(['*', 'u'], 3),
    pass(['*', 's'], 3),
    pass(['*', 't'], 3),
    // navigation
    ['u', null],
    ['k', null],
    ['j', null],
    ['o', null],
    ['p', null],
    ['n', null],
    // application
    ['c', null],
    ['/', null],
    ['q', null],
    ['?', null],
    // manipulation
    ['x', null],
    ['s', null],
    ['y', null],
    ['e', null],
    ['m', null],
    ['!', null],
    ['#', null],
    ['r', null],
    ['R', null],
    ['a', null],
    ['A', null],
    ['f', null],
    ['F', null],
    ['N', null],
    pass(['<tab>', 'RET'], 3),
    ['ESC', null],
    [']', null],
    ['[', null],
    ['z', null],
    ['.', null],
    ['I', null],
    ['U', null],
    ['C-s', null],
    ['T', null]
];

local["^http://www.google.(co.jp|com)/reader/view/"] = [
    // jump
    pass(["g", "h"]),
    pass(["g", "a"]),
    pass(["g", "s"]),
    pass(["g", "S"]),
    pass(["g", "u"]),
    pass(["g", "t"]),
    pass(["g", "T"]),
    pass(["g", "d"]),
    pass(["g", "f"]),
    pass(["g", "F"]),
    pass(["g", "c"]),
    pass(["g", "C"]),
    pass(["g", "e"]),
    pass(["g", "p"]),
    // navigation
    ["j", null],
    ["k", null],
    ["n", null],
    ["p", null],
    ["N", null],
    ["P", null],
    ["X", null],
    ["o", null],
    // item
    ["s", null],
    ["L", null],
    ["t", null],
    ["e", null],
    ["S", null],
    ["d", null],
    ["v", null],
    ["o", null],
    ["c", null],
    ["C", null],
    ["m", null],
    ["A", null],
    ["T", null],
    // application
    ["r", null],
    ["u", null],
    ["1", null],
    ["2", null],
    ["/", null],
    ["a", null],
    ["=", null],
    ["-", null]
];

null が指定されたキーは KeySnail が無視するようになるというところがポイントで、この例では Gmail と Google Reader のショートカットキー (すさまじい量ですね) とバッティングしてしまうものに null を指定しています。

また "g の後に h" といったキーシーケンスに関しては pass 関数を使ってキーボードイベントを作り、投げてやっています。

詳しい説明はプラグインマネージャでのヘルプに記載されているので、そちらを参照して下さい。

注意

このプラグインは KeySnail 1.0.8 以降でのみ正しく動作するので、以下のサイトより最新版の KeySnail を DL した後でお試し下さい。

keysnail japanese ? mooz/keysnail Wiki ? GitHub

追記 (2010 02/14)

Gmail 側の仕様変更に伴い fake, pass が一部うまく動かなくなっていた。 pass(['g', 'i'], 4) としていたところを pass(['g', 'i'], 3) のように変更してやることで、対処できる。

上に示したコード例のほうは変更済み。

inouetakuyainouetakuya 2011/01/24 17:28 これまで Firemacs + LoL を使っていたのですが、最近 keysnail に乗り換えました。本当に助かっています。

ところで下記の件、質問です。お手すきのときに対処法をご教示いただけないでしょうか?(急ぎの件ではありません。)

■概要 Gmail との相性について
プラグイン「サイトローカル・キーマップ」を使用中ですが、Gmail ショートカット ['g', 'i'] で受信トレイを表示すると、Gmail ショートカット(例えば j, k)と、KeySnail の(Global以外の)キーバインドが効かなくなります。

下記のいずれかを行うと、Gmail ショートカットも KeySnail のキーバインドも有効になります。

・F5 で更新する
・コンテンツエリアをクリック

■補足
なお、.keysnail.js の PRESERVE エリアには上記「設定方法」のとおり記述しています。また、上記では、例として Gmail ショートカット ['g', 'i'] を挙げましたが、すべてのメールを表示する ['g', 'a'] や、スター付きを表示する ['g', 's'] も同様に、Gmail ショートカット(例えば j, k)と、KeySnail の(Global以外の)キーバインドが効かなくなります。

moozmooz 2011/01/24 18:35 >inouetakuya

そう言っていただけると,大変励みになります.

Gmail の件ですが,私もこの問題には悩まされておりまして,コメントを機に次のような設定を行ってみました.極めて対症療法的ではありますが.

function passThenFocus(k, i, selector, type) {
return [k, function () {
key.feed(k, i, type);
let elem = content.document.querySelector(selector);
if (elem)
elem.focus();
}];
}

local["^https?://mail.google.com/mail/"] = [
passThenFocus(['g', 'i'], 3, "#canvas_frame"),
passThenFocus(['g', 's'], 3, "#canvas_frame"),
passThenFocus(['g', 't'], 3, "#canvas_frame"),
passThenFocus(['g', 'd'], 3, "#canvas_frame"),
passThenFocus(['g', 'a'], 3, "#canvas_frame"),
passThenFocus(['g', 'b'], 3, "#canvas_frame"),
passThenFocus(['g', 'c'], 3, "#canvas_frame"),
passThenFocus(['g', 'k'], 3, "#canvas_frame"),
// 以下省略

Gmail のスレッドを表示部分が iframe となっているようなので,逐一その iframe にフォーカスをあてています.

inouetakuyainouetakuya 2011/01/24 22:38 id:mooz さん早速回答いただいてありがとうございます。試してみたらうまく行きました!

akiaki 2013/08/14 17:12 ちょっと疑問があったので書き込ませてください。
>local["^https?://mail.google.com/mail/"] = [
の部分の「.」はエスケープ不要な仕様になっていると考えてよろしいのでしょうか?

moozmooz 2013/08/14 22:47 >akiさん

ご指摘の通りです。URLパターンは基本的に正規表現ですが、

- . は \. へとエスケープされる
- * は .* へと変換される

という二つの変換処理が内部でおこなわれます。簡便にパターンを記述したいという考えから、このような仕様としました。

正直なところ負の遺産なので、どうにかしたいところなのですが……

 |