[Japanese] [English]


Title: 私家版w3m

超強力なテキストブラウザw3m。しかし、いくつか不便な点があるので勝手に改造してしまいました。

1 概要

こうして書き出してみるといろいろいじっているものです。

2 新着情報

更新次第ここに追加します。

3 ダウンロード

4 新設コマンド

キーバインド例一覧が欲しければ、w3mで

| egrep '^ +keymap'

としてみてください。

4.1 機能拡張コマンド

他のコマンドと組み合わせてそのコマンドの機能を拡張するものです。

COLON prefix

デフォルト文字列prefixがすでに入力されている状態でCOMMANDのコマンドラインを入力できるようにします。 prefixはクオートされている必要があります。

キーバインド例

keymap xc COLON "GOTO file:/cgi-bin/"
PUSHD command

commandを実行する前に現在開いているファイルバッファのディレクトリにカレントディレクトリを変更します。 たとえば/usr/share/doc/foo/READMEを開いているとき、/usr/share/doc/fooをカレントディレクトリにします。 Emacsでファイルを編集しているときにC-x C-fを打ったときを思い出してみてください。 このコマンドは単独で使用するものではなく、ファイルを開くコマンド等と併用します。

キーバインド例

keymap  !  PUSHD SHELL
keymap  #  PUSHD PIPE_SHELL
keymap  @  PUSHD READ_SHELL
keymap  V  PUSHD TAB_LOAD
keymap  |  PUSHD PIPE_BUF

4.2 Local CGI支援コマンド

主にLocal CGIでの使用を意図しています。

INPUT arg-descriptor

URLやファイルを開くときのようにw3mが1行入力を求めてきます。 arg-descriptorは入力の方法を宣言します。 入力結果は左から順に環境変数W3M_INPUT0, W3M_INPUT1...に格納されます。 通常はCOMMANDとGOTOと組み合わせて使います。

arg-descriptorの内容は、コード文字とそれに続くプロンプトから成っています。 プロンプトは、文字列の終わりかセミコロンで終わります。 コード文字は's'と'f'のふたつ用意しています。 's'が通常の文字列、'f'がファイル名の入力を指定します。 EmacsLispのinteractive指定に似ていますね。

使用例

[1] COMMAND 'INPUT "sGoogle: "; GOTO file:/cgi-bin/mygoogle.cgi'
[2] COMMAND 'INPUT "sPattern: "; READ_SHELL "grep $W3M_INPUT0 $W3M_SOURCEFILE"'
[3] COMMAND 'INPUT "sPattern: ;fFilename: "; READ_SHELL "grep $W3M_INPUT0 $W3M_INPUT1"'

INPUTは非常に応用範囲が広いです。[1]がgoogle検索文字列を入力してmygoogle.cgiに渡します。[2]がカレントバッファをgrepします。[3]が任意のファイルのgrepです。

素のw3mの場合だといちいち入力フォームのHTMLを開いてフォームに入力しなければいけないので面倒でした。 おまけにファイル名を入力したくても補完がききません。 こういうとき、INPUTを使うと使い勝手が大幅に向上します。

MSG string

最下行に1行メッセージを表示します。 Local CGIで結果を出力する場合、新しいバッファに出力されますが、いちいちバッファを使うまでもないほど短いメッセージならこのコマンドを使いましょう。 当然、新しいバッファへの出力と1行メッセージは併用できます。

SEARCH_BACK2 regexp
SEARCH_FORE2 regexp
SEARCH2 regexp

SEARCH_NEXTで使う検索文字列を更新しない検索です。 主にLocal CGIでカーソル移動のために使うためのサーチです。 素のw3mの場合、手動で検索操作をしている最中にカーソル移動のための検索をしてしまうと検索文字列が変わってしまい、非常に迷惑です。

REDRAW_OFF
REDRAW_ON

画面再描画を抑制/再開するコマンドです。 カーソル移動のためのサーチで画面が再描画されるのが嫌な人は使ってみましょう。 1度REDRAW_OFFしたら、Local CGI終了直前にREDRAW_ONする必要があります。 さもないとLocal CGI終了後もずっと画面が再描画されません。

4.3 その他のコマンド

ANIMATE [ms]

msミリ秒ごとに画像を再描画する。アニメーションgifを動かしたいときに使います。 msを指定しなかった場合、アニメーションを中止します。

キーバインド例

keymap xa ANIMATE 50
keymap xA ANIMATE
VSET_OPTION arg

SET_OPTIONを実行後、設定した値を表示します。 特にtoggleと指定した場合、onになったのかoffになったのかが一目でわかります。

キーバインド例

keymap  xi  VSET_OPTION auto_image=toggle
keymap  M-o  VSET_OPTION
TAB_LOAD filename

LOADのタブ版です。TAB_GOTOはあるのになぜTAB_LOADがないのだろうということで作成しました。 *1 例によってPUSHDと併用しましょう。

キーバインド例

keymap  V  PUSHD TAB_LOAD
SHELL2 shellcommand

[Hit any key]が出ずにすぐw3mに復帰する点以外SHELLと同じです。 出力のないプログラムの実行に便利です。

5 拡張したコマンド

MARK_WORD

単語をリンク化するコマンドです。 素のw3mは:、"、'、`、<、>、(、)、[、]、{、}、&、|、;、*、?、$を含まないように単語を選択しますが、私家版では:、"、'、`、<、>、(、)、[、]、{、}、\を含まないようにします。 特にJavaScriptを含むHTMLソースを見ていて、JavaScriptの引数のURLへ飛びたいときに有用です。 &や?が含まれたURLが正しく選択できなかったので不便でした。

FRAME

レンダリング終了後、再描画されなかったので修正。もうC-lを押したりする必要はありません。

各種検索コマンド

検索時、前に戻れるようにマークをしていますが、検索終了後にマークがクリアされてしまいました。 それだと不便なのでマークがクリアされないように修正しました。

LOAD
各種シェルコマンド実行コマンド

カレントディレクトリを表示するようにしました。

各種保存コマンド

保存先ディレクトリを明示するようにしました。これで迷子になる心配はありません。

INFO

Information about current pageにはSourcefileやFilenameの情報を追加しました。 Current Position informationにCurrent Word、Current Line、Current Columnを表示します。 Last Input informationにINPUTコマンドによる入力結果を表示します。 Local CGIのデバッグに有用です。

COMMAND

コマンド名に小文字も使えるようになりました。いちいち大文字を入力するのは面倒なので。

PEEK
PEEK_LINK
PEEK_IMG

環境変数STYが設定されているとき、GNU ScreenのペーストバッファにURLを設定します。 また、~/.w3m/bufinfoにもURLを書き出します。

6 お手軽機能拡張方法

w3mで新しいコマンドを作成するのは非常に簡単です。

  1. main.c(メニュー関連はmenu.c)にDEFUNを使って関数定義を書く。
  2. proto.hにプロトタイプを追加する。

の2ステップでokです。

6.1 DEFUN

w3mのコマンドはすべてDEFUNというマクロで行われています。 DEFUNの定義は

#define DEFUN(funcname, macroname, docstring) void funcname(void)

と一見意味がないようですが、ソースから全コマンドを取り出す処理に役立っています。 *2 その処理はMakefileに書かれています。 そのため、コマンドを新規作成するためには、DEFUNを使って関数定義します。

ソースを眺めればわかるようにコマンド定義はパターン化されています。

DEFUN(foo, FOO, "test function")
{
  char *data;
  /* コマンドの引数をchar*で得る */
  data = searchKeyData();                     
  /* 引数が空ならば */
  if (data == NULL || *data == '\0') {
      /* 入力を求める */    
      data = inputStrHist(プロンプト, デフォルト文字列, ヒストリ);
      /* 入力が空ならば画面を再描画して終了 */
      if (data == NULL) {
          displayBuffer(Currentbuf, B_NORMAL);
          return;
      }
  }
  /* 以後本処理 */
}

あとはgrepなどの検索ツールを活用して見よう見真似で頑張ってください。なんとかなります。

6.2 Boehm-GCでスクリプト言語並の手軽さ

しかも嬉しいことにw3mはBoehm-GCが使われているので文字列を「使い棄て」できます。 文字列を使ってもfreeする必要がないのです。 StrというのがGCつきの文字列型です。

typedef struct _Str {
    char *ptr;
    int length;
    int area_size;
} *Str;

文字列作成関数を使ったら文字列が確保され、メモリ管理はBoehm-GCが受け持ってくれます。 圧巻はSprintf関数です。

Str Sprintf(char *fmt, ...);

このように定義されているので、

Str s;
s = Sprintf("%s", string);

と、スクリプト言語を思わせる使い心地です。 普通のchar *が欲しければ、s->ptrとするだけです! どういう関数が使えるかはStr.h, Str.cを見てください。 w3mのソース全体も大切な使用例です。

6.2.1 参考URL

w3mの原作者aitoさん御自身で書かれた文書です。

6.3 proto.cにプロトタイプを追加

同梱のaddproto.rbを使うと簡単です。(要ruby) 使い方は

ruby addproto.rb funcname [funcname...]

です。 macronameではなくてfuncname(DEFUNの第一引数)であることに注意してください。

とはいえ、proto.hにあるコマンド定義をdefun.hに分けておけば自動生成できそうな気がするんですけどね。 プリプロセッサで条件付きコンパイルがなされているけど、cppで処理した後なら完全に自動生成できそうです。


Back to Top

Valid XHTML 1.0!
rubikitch(rubikitch __nos_pam__ At __nos_pam__ ruby-lang DoT org)

Mail Form
Name Mail
URL


*1NEW_TABとLOADでできるじゃないかという声が聞こえてきそうですが、それだとC-gでとりやめたときに新しいタブができたままで気持ち悪いです。
*2まだdocstringは使われていないようです。将来documentも自動生成させる予定なのでしょう。