2009年8月29日土曜日

emacs-w3mでjavadocのアンカーにうまく飛ばない

症状

emacs-w3m-1.4.4で、 javadocをブラウズしていると、一部のnameアンカーにうまく飛ばない時がある。
例えば、
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/String.html
にある、
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/String.html#String(byte[], int)
をアクセスすると、No such anchor: String(byte[],%20int) でエラーになる。
javadoc がURLに空白を使っているのが良くないのだとは思うが不便なので調べてみた。

問題のエラーは、w3m.el というファイルに定義されている、関数 w3m-search-name-anchorの内部で起きている。
上記の javadoc URLの場合、この w3m-search-name-anchor のname引数には、 URLエンコードされた%20付きの文字列 `String(byte[],%20int)` が渡される。 しかし、あらかじめページ内のアンカーをキャッシュしている、 w3m-name-anchor プロパティには、エンコード前の空白含みの `String(byte[],     int)` しかないので、アンカーが見つからないとなるのが原因ではないか。

解決

w3m-search-name-anchorを次のように変更したら、 いちおう動作するようになった。
(defun w3m-search-name-anchor (name &optional quiet)
  "My w3m-search-name-anchor (for Java doc anchor)"
  (interactive "sName: ")
  (let ((pos (point-min))
        ;; add for javadoc anchor
        (name-sp (w3m-url-decode-string name)) ;; better??
        ;; (name-sp (replace-regexp-in-string "%20" " " name))
        )
    (if (string= name name-sp) (setq name-sp nil))
    (catch 'found
      (while (setq pos (next-single-property-change pos 'w3m-name-anchor))
        (when (or (member name (get-text-property pos 'w3m-name-anchor))
                  ;; add for javadoc anchor
                  (and name-sp
                       (member name-sp (get-text-property pos 'w3m-name-anchor))))
          (goto-char pos)
          (when (eolp) (forward-line))
          (w3m-horizontal-on-screen)
          (throw 'found t)))
      (setq pos (point-min))
      (while (setq pos (next-single-property-change pos 'w3m-name-anchor2))
        (when (or (member name (get-text-property pos 'w3m-name-anchor2))
                  ;; Add for javadoc anchor
                  (and name-sp
                       (member name-sp (get-text-property pos 'w3m-name-anchor2))))
          (goto-char pos)
          (when (eolp) (forward-line))
          (w3m-horizontal-on-screen)
          (throw 'found t)))
      (unless quiet
        (message "No such anchor: %s !!" name))
      nil)))

とりあえずの野良インストール方法は、
  1. 上のソースを、my-w3m.elというファイルにセーブ
  2. my-w3m.elをload-pathが切ってあるディレクトリーに置く。
  3. .emacs.el に以下を追加
  4. (add-hook 'w3m-load-hook
       '(lambda () (load "my-w3m") 
          (message "*** Loaded my-w3m ****")))
        
もちろん、この方法は emacs-w3mのバージョン1.4.4 限定だ。
CVS版は試した事がないので、もしかしたら既に解決済みかもしれない。

0 件のコメント:

コメントを投稿