w3mでhit-a-hintもどき

三連休中にあった飲みの予定が見事潰れたため、三日間ひきこもってました。うーん不健康。

話は変わりますが、皆さんブラウザは何を利用しているでしょうか?
私はデスクトップがWindow7(RC)、ほぼメインとなっているノートPCがLinux(Gentoo)なのですが、利用しているブラウザは

Windows7
Google Chrome, Sleipnir, Firefox3.5
Linux
w3m, firefox3.5(Keysnail)

となっています。書いてある順は利用頻度順です。

Windowsの方ではほとんどマウスのみの操作です。キーボードはほとんど触りません。
Linuxではw3mとKeysnailを導入したfirefoxを利用しています。Keysnailには、「HoK」、「Local Site keymap」など、現在公開されているプラグインの一部を導入しています。

Firefoxでは、以前Vimperatorを利用していたのですが、やはりEmacs利用者の端くれとしては、Emacsライクなキーバインドで利用したいということと、HoKでVimperatorのHit-a-Hintと同等以上の機能を実現したということなので乗り換えました。

で、Linux側のFirefox(in Keysnail)で一番便利だと個人的に思っているのが、このHoKです。一々リンクまでTAB移動・・・とか検索・・・とかしなくていいので、ブラウジングの速度が飛躍的に上がります。
ところで私の生活環境は、90% がmlterm & Emacsの上、メインがw3mです。w3mは色んな点でfirefoxを凌駕していると思いますが、このHoKに関してだけは負けていると思っていました。
(他のw3mマスターの方々はどうやっているのか気になります)

話はちょっと逸れますが、w3mのデフォルトキーバインディングに、 ESC-m (MOVE_LIST_MENU)というのがあります。なんとターミナル上でメニューを開き、aとか1aとかで、そのリンクの位置にジャンプできるという機能です。
このMOVE_LIST_MENU、確かにいいのですが、「必ず一番上のリンクからリストに表示される」「検索にmigemoが利用できない」「キーバインドが微妙に違ったりする(か?)」など、(私にとって)微妙な点があったため、常用には至りませんでした。

さて、ここからが本題です。

で、なんとかw3mでVimperatorのHit-a-Hint、HoK on Keysnailを実現できないのかと考えて、w3m上で↓のようなオペレーションができるようにしてみました。なんとスクリーンショット付きです。

初期状態。
hit-a-hint1.png 直

現在見ているページのリンクにマークを付ける
hit-a-hint2.png 直

マークを入力する(下にajと入力しています)
hit-a-hint3.png 直

指定したマークのリンクにGO !
hit-a-hint4.png 直

どうでしょうか?なんとなくそれっぽいかと思います。


ただし、この機能を実現するためには、本家のw3mではなく、id:rubikitch さんが公開してくださっている、私家版w3m(http://http://www.rubyist.net/~rubikitch/computer/hacks/w3m/)の機能が必要です。というかこれじゃないと不可能です。

このhit-a-hintもどきですが、以下のような設定ファイルで動作します。

# -*- coding: utf-8 -*-

#####################################################################################
# hit-a-hintで指定されたマークのリンクを利用し、処理を行うための拡張を設定する。    #
# 拡張は以下のように記述する。                                                      #
#                                                                                   #
# # 指定されたマークを開く。                                                        #
# extension("normal", {"content" => "",                                             #
#                      "operations" => ["GOTO %s"]})                                #
#                                                                                   #
# extensionの第一引数は、?method=で指定される文字列に対応する。                     #
# 第二引数は、W3m-controlとして設定される文字列を配列で指定する。配列の             #
# 一要素が、W3m-controlヘッダ一つに対応し、先頭から順に実行されるように出力される。 #
#####################################################################################

# methodの指定時、先頭一致で検索するようにする。
# normal, newtab があるとき、no => normal 、ne => newtabで検索が行われる。
match_method_first true

# enable_immediatery_inputが有効であり、methodが指定されない場合に利用されるmethod
default_method "normal"

# マークを付けたと同時にマークの入力を行うか
enable_immediatery_input true

# cgiのURL。enable_immediatery_inputがfalseの場合には無視される。
cgi_url "file:///cgi-bin/hit-a-hint.cgi"

# リンク先に同じタブで飛ぶ
extension("normal", {"content" => "",
            "operations" => ["BACK",
                             "GOTO %s"]}
          )

# リンク先に新しいタブを作成して飛ぶ
extension("newtab", {"content" => "",
            "operations" => ["BACK",
                             "TAB_GOTO %s"]}
          )

HoKとかVimperatorでは、色々な開き方を選択できるので、extensionという形で追加できるようにしてみました。
ここではnormal、newtabというのを追加しています。

さらに、ちょびっとですがオプションも付けています。説明はコメント部分に記載しています。

ただ一つ問題なのが、これをkeymapに登録する際の記述がちょっとあれだということです。↓のような感じになっています。

keymap xm GOTO file:///cgi-bin/hit-a-hint.cgi?setmark
  →現在表示しているページのリンクにマークを付ける。enable_immediatery_inputが有効の場合、マークを付けた直後にマーク入力が促される。
keymap xM GOTO file:///cgi-bin/hit-a-hint.cgi?setmark&input
  →現在表示しているページのリンクにマークを付ける。default_methodは利用されないので、methodの入力も促される。
keymap xE COMMAND "INPUT 'sMark: '; GOTO file:/cgi-bin/hit-a-hint.cgi?method=normal"
  →extension("normal",〜)を利用して、マークを設定する
keymap xR COMMAND "INPUT 'sMethod: ;sMark: '; GOTO file:/cgi-bin/hit-a-hint.cgi"
  →methodとmarkを両方設定する。

なんというか、一々setmarkとかを指定しなきゃいけないのがイケてないと個人的には思っているんですが、まぁ個人でしか利用しないからいいか、とも思っています。

ただ現在なんとも出来ない問題として、私のRubyに対する知識が不足しているため、UTF-8としてそもそも認識できない文字(バイナリですね)が含まれるHTMLについては、ファイル読み込みの際にエラーが発生してしまいます・・・。内部でNokogiriを利用しているため、UTF-8に変換できないような文字が含まれるページの場合、手も足も出ません。
そういうHTML自体は少ないのですが、どうもWordPressを利用しているページに多く見られるようです。認識出来ない文字はそのままで、無理矢理エンコードを行うような設定にするしかないような。

ちなみに、w3mでhatenaのページを読むと、*.gzというファイルになります。なんでこんなんになるかよくわかりませんが、w3mのオプションで「ダウンロード時に自動的に圧縮されたデータを解凍する」をyesにしておくと、ちゃんのマークが付くようになります。

まだ未完成で微妙な点が多々ありますが、興味を持たれた方はとりあえず以下から取得することができます。

Github

hit-a-hint.rbとなっているのがそれです。

取得後、w3mcgi-binにhit-a-hint.cgiとでもリネームして置いてください。この辺は任意です。
で、.w3mの直下に、hah_config.rbというファイルを作成して、↑の設定ファイルの部分をコピペしてください。
最後に、keymapを↑を参考にして設定して下さい。

なおこのスクリプトは、Ruby1.9.1でしか動作を確認していない上、Ruby1.9以降でしか動作しません。このへんはご了承下さい。わかる方はshebang行を書き換えてもらえればいいです。
それと内部でNokogiriを利用していますので、gemからNokogiriのインストールも必要です。

久々に多少まとまった量のRubyを記述したせいか疲れました・・・。C++ならあまり疲れないんですが。

もし試してみたという方は感想とか「こんな書き方してんの?ダサッ」を是非。Rubyはまだまだ難しいです。
後「動かねぇ」という方も是非。動作確認とかエラーチェックとかまだまだ甘いんで・・・(ぉ

皆様の素敵なw3mライフの僅かの助けにでもなれば幸いです。