This file documents emacs-w3m, an Emacs interface to w3m.

このファイルは Emacs で動く w3m のインタフェースである emacs-w3m に関
する説明書です。

Copyright (C) 2000, 2001, 2002, 2003 TSUCHIYA Masatoshi

This edition is for emacs-w3m version 1.3.6.

この版は emacs-w3m バージョン 1.3.6 に対応します。

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU General Public License, Version 2 or any
later version published by the Free Software Foundation.

この文書を、フリーソフトウェア財団発行の GNU 一般公用使用許諾書第 2 版
またはそれ以降の版が定める条件の下で複製、配布、あるいは変更することを
許可します。

This document is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

この文書は有用とは思いますが, 頒布にあたっては, 市場性及び特定目的適合
性についての暗黙の保証を含めて, いかなる保証も行ないません. 詳細につい
ては GNU 一般公有使用許諾書をお読みください.

You should have received a copy of the GNU General Public License
along with this document; if not, you can either send email to this
document's maintainer or write to: The Free Software Foundation, Inc.;
59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.

あなたは, この文書と一緒に GNU 一般公有使用許諾の写しを受け取っている
はずです. そうでない場合は, 文書の管理者にメールを送るか、または、フリー
ソフトウェア財団 (675 Mass Ave, Cambridge, MA 02139, USA) に手紙を書い
てください。

新聞モジュールの作り方
======================

`Shimbun' は emacs-w3m の付属ライブラリで、Gnus や Wanderlust、Mew な
どの MUA を利用し、ウェブコンテンツをメールと同じユーザインターフェー
スで読むことを可能にするものです。ここでは `shimbun' モジュールを作成
する典型的な方法を説明します。

概略
----

`http://www.foobar.net' のコンテンツを閲覧する新たな `shimbun' モジュー
ル `foobar' を作成するとして、まず最初に貴方がしなればならないことは、
`sb-foobar.el' の冒頭に

     (require 'shimbun)
     (luna-define-class shimbun-foobar (shimbun) ())

のような宣言を入れておくことです。徐々に分かると思いますので、今はおま
じないと思っておいて下さい。注意すべきことは、`shimbun' モジュールを入
れるファイル名の `sb-foobar.el' の `foobar' の名前と、
`luna-define-class' の第一引数の `shimbun-foobar' の `foobar' の名前は
合わせておく必要があることです。

`Shimbun' モジュール `shimbun-foobar' がこなすべき仕事は大きく四つあり
ます (あなたが Gnus のユーザならば、「フォルダ」を「グループ」に読み換
えて下さい):

  1. MUA が `foobar' フォルダを開いたら、記事の標題などをリストアップ
     するために `http://www.foobar.net' からウェブページのソースを取得
     すること。

  2. 取得したウェブページのソースに対し、記事の見出しに必要ないくつか
     の情報とともに取得して、`headers' というリストに代入して返すこと。

  3. MUA が `foobar' フォルダの記事の閲覧を要求したら、実際の記事内容
     を記載したウェブページのソースを (例えば
     `http://www.foobar.net/030530.html' から) 取得すること。

  4. `http://www.foobar.net/030530.html' から取得したウェブページのソー
     スを、必要に応じ閲覧しやすいように整形すること。

最初の作業は `shimbun.el' の `shimbun-headers' が、二番目の作業は
`shimbun-get-headers' が担当します。そして三番目の作業は
`shimbun-article' が、最後の作業は `shimbun-make-contents' が担当しま
す。

`shimbun.el' の中をご覧下さい。`defun' による関数定義の他に、見慣れな
い `luna-define-generic', `luna-define-method' などの宣言がありますよ
ね。どうも使用方法は `defun' のそれと似ているようです。そして、前者は
何だか doc-string だけを書いてあるようで、同名のシンボルについて後者に
よって再度宣言しているように見えます。更に、あるシンボルについて、
`luna-define-generic' の宣言だけがあって、`luna-define-method' の宣言
がないものもあります。

実は、`shimbun.el' 及び各 `shimbun' モジュールは、Emacs Lisp にてオブ
ジェクト志向プログラミングを可能とする `luna.el' (1) (see
Overview-Footnotes) を利用して書かれています。

`shimbun.el' の中では、`shimbun-headers' がある URL のウェブページのソー
スを取得し、`shimbun-get-headers' がそのウェブページのソースから標題な
どを抜き出し... という前述の手順がハードコーディングされています。しか
し、決め打ちするだけでは、千差万別のウェブページのソースを、その構造に
合わせて変化させることができません。

そこで `luna' により、メソッドがコールされる手順だけ決めておいて、
`shimbun' により変化させるべきメソッドの実体定義を各 `shimbun' モジュー
ルに任せているのです。各 `shimbun' モジュールで共通で使えそうなメソッ
ドは `shimbun.el' の中にメソッドの実体も定義してありますが、それすら各
`shimbun' モジュールにおいて再定義をすることが可能です。

もうお分かりのように、`luna-define-generic' は、言わば殼だけの宣言、
`luna-define-method' は `shimbun' モジュール毎に作成できる実体の宣言。
そして `sb-foobar.el' の冒頭に入れた `luna-define-class' での宣言は、
`luna' 上での新たなクラスの宣言だったわけです。

(1) FLIM に含まれています。

ウェブページのソース及びヘッダ情報を取得する
--------------------------------------------

まず記事見出しを取得する対象となるウェブページを決めることから始めます。
フレーム表示されている場合は、フレームの中で必要なページだけを単独で指
し示す URL を特定するべきです。特定できたら、新たに作成する `shimbun'
モジュールの中で `luna-define-method' を使い、`shimbun-index-url' の定
義を作成しましょう。単純に URL を返すようにすれば良いですよ。後で説明
しますので、変数 `shimbun-foobar-groups' も用意しておきましょう (1)
(see Getting web page and header information-Footnotes)。

     (defvar shimbun-foobar-url "http://www.foobar.net")

     (luna-define-method shimbun-index-url ((shimbun shimbun-foobar))
       shimbun-foobar-url)

     (defvar shimbun-foobar-groups '("news"))

`shimbun-headers' メソッドは `shimbun.el' の中に既に定義されていますか
ら、`sb-foobar.el' で `shimbun-index-url' メソッドの定義を作成すればウェ
ブページのソースの取得ができるようになります。`shimbun-headers' はウェ
ブページのソースを取得した後、`shimbun-get-headers' メソッドを呼び、ヘッ
ダ情報の収集に入ります。`shimbun.el' の中には `shimbun-get-headers' の
メソッド宣言がありせんから、`sb-foobar.el' の中で独自にメソッドを作成
しなければなりません。

`sb-foobar.el' に `shimbun-get-headers' のメソッドを作成するために、取
得したページのソースを分析しましょう。どのような正規表現で記事のヘッダ
情報を収集するかを検討します。記事の見出しとして特に必要な情報は、標題、
日付、作成者、その記事の URL、そして `message-id' です。これらの情報は、
それぞれの MUA において、Subject, Date, From, Xref, Message-ID として
表示されます。例えば、下記の

     <a href="030530.html">5月30日の話題(投稿者-みきお &lt;foo@bar.net&gt;)</a>

のような行を集めて記事にしたいのでしたら、

     "<a href=\"\\(\\([0-9][0-9][0-9][0-9]\\)\\.html\\)\">\\([^<(]+\\)(投稿者-\\([^<]+\\))<\/a>"

のような正規表現になるでしょう。そして記事の Xref の値は
`(match-string 1)' で取得できます、Date は
`(match-string 2)' の値を加工すれば良いでしょう。Subject は
`(match-string 3)' で取得できますね。From は
`(match-string 4)' を加工すれば良いでしょう。これらの値
は MUA で見易いように更に加工しても構いません。`sb-muchy.el' では結
構凝った Subject を作っていますので一度見て下さい。

上記のように記事の URL が相対パス表示されている場合は、
`w3m-expand-url' を使用し、絶対パス表示に変更してからヘッダに収めましょ
う。記事の URL がヘッダの URL と同じ、つまり記事毎に個別に URL を持た
ない構造のウェブページもあります。この場合は少しやっかいで、ヘッダ情報
取得の段階で、記事の内容も取得しておき、Emacs のメモリに収めておく必要
があります。具体的には `sb-palmfan.el', `sb-dennou.el', `sb-tcup.el'
の `shimbun-headers' メソッドの定義を参照して下さい。

ウェブページによっては Date が特定できないものがあります。そういう場合
は無理に特定せずとも `""' を入れておけば OK です。記事の内容を見て初め
て Date が特定できるなら、`shimbun-make-contents' メソッドの中で改めて
ヘッダに Date の情報を入れても OK です。それから、From を決め打ちして
も良い場合もあります。

`message-id' の作成には注意を要します。一部の記事が読めなかったりしま
すので (2) (see Getting web page and header information-Footnotes)、
必ず単一性 (uniqueness) を保証しなければなりません。日付やドメイン、そ
のページの URL の一部を使って文字列を生成することで単一性を確保しましょ
う。その他、`message-id' の一部に必ず `@' を含めるようにし、逆に `:'
は含まないようにしましょう。このルールを守らないとインライン画像がきち
んと出力されませんよ。詳しくは RFC2387, RFC822 を参照して下さい。

苦労して取得したこれらの情報は `shimbun-make-header' という関数を利用
してヘッダに収めます。

結局 `sb-foobar.el' の中での `shimbun-get-headers' の定義の骨組みはこ
んな風になりますね。

     (luna-define-method shimbun-get-headers ((shimbun shimbun-foobar)
                                              &optional range)
       (let ((regexp "....")
             subject from date id url headers)
         ...
         (catch 'stop
           (while (re-search-forward regexp nil t nil)
             ...
             (when (shimbun-search-id shimbun id)
               (throw 'stop nil))
             (push (shimbun-make-header
                    0 (shimbun-mime-encode-string subject)
                    (shimbun-mime-encode-string from)
                   date id "" 0 0 url)
                   headers)))
         headers))

なお、このメソッドの中では `shimbun' という一時変数で、`shimbun' モジュー
ル `shimbun-foobar' のインスタンスにアクセスできます。

ところで、先程保留にした変数 `shimbun-foobar-groups' について説明しま
しょう。

仮に `http://www.foobar.net' の中に読みたい記事グループが二つあっ
て、それぞれの記事のヘッダ情報を得るウェブページが別々の場所にあったとし
ましょう。`http://www.foobar.net/whatsnew/index.hmtl' にサイト
の更新情報が、`http://www.foobar.net/ml/index.html' に ML の記
事アーカイブの一覧があるときなどです。こういう場合は、`shimbun' モ
ジュール `foobar' のグループとして、`foobar.whatsnew',
`foobar.ml' としてアクセスできると便利ですよね。そういう場合は下記
のようにしてみましょう。

     (defvar shimbun-foobar-url "http://www.foobar.net")

     (defvar shimbun-foobar-group-path-alist
       '(("whatsnew" . "/whatsnew/index.html")
         ("ml" . "/ml/index.html")))

     (defvar shimbun-foobar-groups
       (mapcar 'car shimbun-foobar-group-path-alist))

     (luna-define-method shimbun-index-url ((shimbun shimbun-foobar))
       (concat shimbun-foobar-url
               (cdr (assoc (shimbun-current-group-internal shimbun)
                           shimbun-foobar-groups))))

現在ユーザがアクセスしているグループには
`shimbun-current-group-internal' を使えば分かります。
`shimbun-get-headers' などでもグループが違えば作業内容が違ってくる可能
性もありますね。

なお、`shimbun' モジュール一つにつき、最低でも一つのグループが必要です。
グループの名前の決め方に特に決まりはありませんが、グループ名に悩んだら、
`news' とか `main' などと付けておきましょう。

(1) `Shimbun' モジュール一つにつき、最低でも一つのグループが必要
です。

(2) shimbun の一部の記事が読めないだけならまだしも、下手に
`message-id' を作成すると、貴方が受領する大事なメールのそれとかち
合ってしまい、そのメールが読めなくなる可能性すらあります。

記事の表示
----------

`shimbun.el' に定義された `shimbun-article' メソッドは、ヘッダ情報から
Xref を取り出し、その URL のウェブページのソースを取得した後に、そのソー
スを入れたワーキングバッファの中で `shimbun-make-contents' を呼びます。
具体的な記事の加工は `shimbun-make-contents' の仕事です。

記事となるウェブページのソースが、どばっとワーキングバッファにぶちまけ
られていると想像して下さい。`shimbun.el' の標準の
`shimbun-make-contents' は、そのバッファの先頭にまずヘッダ情報を挿入し、
その直後に `<html>' や `<body>' などを、また、バッファの末尾に
`</body>', `</html>' を挿入してくれます。そうやって HTML メールとして
表示させるのです。

記事を何も加工する必要がなければ `sb-foobar.el' の中では
`shimbun-make-contents' について新たに定義する必要はありません。

単純に記事の前半と後半に捨てたい部分があるだけならば、
`shimbun-foobar-content-start', `shimbun-foobar-content-end' に捨てた
い部分を検索可能な正規表現を指定しておきましょう。

     (defvar shimbun-foobar-content-start "^<body>$")
     (defvar shimbun-foobar-content-end "^<\/body>$")

標準の `shimbun-make-contents' がこれらの正規表現を利用して、
`point-min' から `shimbun-foobar-content-start' まで、
`shimbun-foobar-content-end' から `point-max' までを切り捨ててくれます
よ。但し、これら二つのマッチはいずれかが成功しないと切り捨ては行われま
せんので注意が必要です。

広告などの不要な情報があって、それを細かく検索して捨てたい場合は、
`sb-foobar.el' の中で `luna-define-method' の `method-qualifier' に対
して `:before' を指定して `shimbun-make-contents' を宣言し、
`shimbun.el' の `shimbun-make-contents' が呼ばれる前に (1) (see
Displaying an article-Footnotes) 掃除をしましょう。親メソッドに渡す
際に正常に動くよう、`save-excursion' で囲ってポイントを保存することを
忘れずに。

     (luna-define-method shimbun-make-contents :before ((shimbun shimbun-foobar)
                                                        header)
       (save-excursion
         ;; cleaning up
         (while (re-search-forward "..." nil t nil)
           (delete-region (match-beginning 0) (match-end 0)))
         ...
         ))

より具体的な方法は、`sb-ibm-dev.el' が参考になるかもしれません。

先程、see Getting web page and header information の節で、記事毎に
個別に URL を持たない構造のウェブページの場合、ヘッダ情報取得の段階で、
記事の内容も取得しておき、Emacs のメモリに収めておく必要があると申し上
げました。この場合、`shimbun-article' では上記のような Xref 情報からの
web page の取得は必要になりませんので、ただ Emacs のメモリから取り出し
て、バッファに整形して挿入すれば足ります。具体的には `sb-palmfan.el',
`sb-dennou.el', `sb-tcup.el' の `shimbun-article' メソッドの定義を参照
して下さい。

(1) ご想像の通り、`:before' を指定すると、まず `:before' 付
きのメソッドがコールされて、その後で `:before' が付いていない親ク
ラスのメソッドがコールされます。なお、`method-qualifier' を付けな
いで `sb-foobar.el' の中でメソッドを作った場合は親クラスのメソッ
ドを上書きします。

Shimbun モジュールの継承
------------------------

メーリングリストマネージャ (アーカイバ) として有名なものがいくつかあり
ます。

   * Mailman The GNU Mailing List Manager. 以前は `pipermail' と呼ばれ
     ていました。詳細は
     `http://www.gnu.org/software/mailman/index.html' をご覧下さい。

   * MHonArc 詳細は `http://www.oac.uci.edu/indiv/ehood/mhonarc.html'
     をご覧下さい。

   * fml fml mailing list server/manager.  詳細は
     `http://www.fml.org/software/fml/' をご覧下さい。

   * mailarc 詳細は `http://cvs.namazu.org/mailarc/' をご覧下さい。

貴方が Getting web page and header information のステップで取
得したウェブページのソースを分析しているときに、そのソースの中にこれら
メーリングリストマネージャの名前を見つけたら (1) (see Inheriting shimbun module-Footnotes)
、それはすごくラッキーなことです。
`sb-mailman.el', `sb-mhonarc.el', `sb-fml.el', `sb-mailarc.el' に既に
`shimbun-get-headers' などの必要なメソッドが定義されています。これらを
利用してなお足りない部分だけの差分プログラミングをすれば、貴方の
`sb-foobar.el' は早速動きます。

例えば `sb-mailman.el' を利用するなら `sb-foobar.el' の冒頭は、

     (require 'shimbun)
     (require 'sb-mailman)
     (luna-define-class shimbun-foobar (shimbun-mailman) ())

こんな風になります。これで `shimbun' モジュール `shimbun-foobar' は
`shimbun-mailman' クラスを継承し (2) (see Inheriting shimbun module-Footnotes)
、`shimbun-foobar' の中では、`sb-mailman.el' の中で
定義されているメソッドが標準で使用されることとなります (更にメソッドの
一部を上書きすることも可能です)。

`sb-mailman.el' を実際に利用したサンプルとして、`sb-pilot-mailsync.el'
などをご覧下さい。如何に楽ができるかがお分かりになるでしょう。

気を付けることが一つあるとすれば、これらのメーリングリストマネージャの
中には地域化 (localize) されて、例えば日付表示を日本語で行うように改造
されているものがあることです。`sb-mailman.el', `sb-mhonarc.el',
`sb-fml.el', `sb-mailarc.el' はいずれも標準の、英語版のものに対応して
います。これら地域化されたメーリングリストマネージャを利用しているウェ
ブサイトを `shimbun' で読みたいときは、いくつかのメソッドを上書きしな
ければならないかもしれません。

(1) ウェブページのソースの中にこれらメーリングリストマネージャの名前が
表示されていることが多いです。

(2) つまり `shimbun-mailman' クラスが親クラスになります。

Emacs-w3m を使う洒落た小物たち
******************************

他の Emacs の応用機能とともに emacs-w3m を便利に使うためのヒント集です。

   * browse-url

     `browse-url' の機能とともに emacs-w3m を使うことができます。例え
     ば、以下の行を `~/.emacs' ファイルに入れて下さい:

          (setq browse-url-browser-function 'w3m-browse-url)
          (autoload 'w3m-browse-url "w3m" "Ask emacs-w3m to show a URL." t)
          (global-set-key "\C-xm" 'browse-url-at-point)

     こうすることによって、Emacs のどのバッファでも、URL のような文字
     列の上で `C-x m' キーをタイプすると、emacs-w3m が起動されます。加
     えて、`C-c C-v' キーをタイプすることによって、まさに編集中の HTML
     ファイルを emacs-w3m で下見 (preview) することができます (HTML ファ
     イルの編集に、Emacs と `html-mode' メジャーモードを使う必要があり
     ます)。

     Emacs-w3m のバッファにいるときに、`C-x m' キーをタイプすることに
     よって、emacs-w3m の代わりに他のウェブブラウザを使いたい場合は
     (そんなことをしたい人がいるのかな?)、以下のアドバイスを
     `~/.emacs' ファイルに加えて下さい:

          (defadvice browse-url-at-point
            (around change-browse-url-browser-function activate)
            "Use Netscape only when it is invoked in an emacs-w3m buffer."
            (let ((browse-url-browser-function
                   (if (eq major-mode 'w3m-mode)
                       'browse-url-netscape
                     'w3m-browse-url)))
              ad-do-it))

   * dired

     `dired' のバッファで `C-x m' キーをタイプすることによって、
     emacs-w3m を使って HTML ファイルを閲覧することができます。
     `~/.emacs' ファイルで、以下の設定を使って下さい:

          (eval-after-load "dired"
            '(define-key dired-mode-map "\C-xm" 'dired-w3m-find-file))

          (defun dired-w3m-find-file ()
            (interactive)
            (require 'w3m)
            (let ((file (dired-get-filename)))
              (if (y-or-n-p (format "Use emacs-w3m to browse %s? "
                                    (file-name-nondirectory file)))
                  (w3m-find-file file))))

   * hnf-mode

     ハイパー日記システムと emacs-w3m を使って、最新の日記を見ることが
     できます。以下の行を `~/.emacs' ファイルに入れて、`hnf-mode' のバッ
     ファで `C-c C-b' キーをタイプして下さい:

          (autoload 'w3m-browse-url "w3m" nil t)
          (defun w3m-hnf-browse-url-w3m (url &optional new-window)
            (interactive (browse-url-interactive-arg "URL: "))
            (save-selected-window
              (pop-to-buffer (get-buffer-create "*w3m*"))
              (w3m-browse-url url new-window)))
          (setq hnf-browse-url-browser-function #'w3m-hnf-browse-url-w3m)

   * Gnus

     あなたが Gnus のユーザで、この項がこの Info で初めて読むベージで
     あるのならば、あなたは入り口を間違えましたね。最初に
     Hooking into MUAs を見て下さい。

     デフォルトでは、Gnus は例えば `gnus-treat-strip-banner' のような
     treatment 変数を `text/html' パートに適用しません。自動的に行なわ
     せるには二つの方法があります:

          ;; すべての treatment を text/html パートに適用する。
          (eval-after-load "gnus-art"
            '(add-to-list 'gnus-article-treat-types "text/html"))

          ;; 特定の treatment を text/html パートに適用する。
          (setq gnus-treat-strip-banner '(or t (typep "text/html")))

     詳しいことは *Note Customizing Articles: (gnus)Customizing
     Articles を見て下さい。

     加えて、以下の実験的なコードは `multipart/related' な絵を見るため
     のものです。表示される場所に難があります。

          (eval-after-load "gnus-art"
            '(or (assoc "multipart/related" gnus-mime-multipart-functions)
                 (setq gnus-mime-multipart-functions
                       (cons
                        (cons
                         "multipart/related"
                         (byte-compile
                          (lambda (handle)
                            (gnus-mime-display-mixed (cdr handle)))))
                        gnus-mime-multipart-functions))))

   * yahtml-mode

     Emacs-w3m を使って、`yahtml-mode' でまさに編集中の HTML ファイル
     を下見 (preview) することができます。例です:

          (autoload 'w3m-goto-url "w3m")
          (defadvice yahtml-browse-html
            (around w3m-yahtml-browse-html activate compile)
            (w3m-goto-url (ad-get-arg 0) t))

メーリングリスト、バグリポート
******************************

Emacs-w3m に関するすべてのことがらを話し合うためのメーリングリストが用
意されています。講読していない人も投稿できます。バグを見つけたり、こん
な機能が欲しいなと思ったり、あるいはコードを書きましたという人はどうぞ
投稿して下さい。単なるユーザだけれどもプログラムに興味があるという人も、
ぜひ参加して下さい。アドレスは以下の通りです:

     Emacs-w3m メーリングリスト <emacs-w3m@namazu.org>

もし `mail-user-agent' を正しく動作するように設定してあれば、
`report-emacs-w3m-bug' コマンド (または `C-c C-b' キー) を使ってバグリ
ポートを送ることもできます。

このリストに投稿するときは、日本語か英語を使って下さい。多くのメンバー
は日本人です。投稿された記事は公開されていて、ウェブ
(`http://emacs-w3m.namazu.org/ml/') や NetNews (サーバ
`news.gmane.org' 上の `gmane.emacs.w3m' というグループ) でも読むことが
できます。

このリストのメッセージをメールで受け取りたい人は、本文に

     subscribe ANATANO Namae

のように書いて (メールアドレスではなくてあなたの名前を書きます)、
`emacs-w3m-ctl@namazu.org' 宛にメールを送るとメーリングリストに登録さ
れます。また、メールを受け取るのをやめるには、本文に

     # bye

と書いたメールを `emacs-w3m-ctl@namazu.org' 宛に送って下さい。

Emacs-w3m の関数の詳しい説明
****************************

このマニュアルを書いた人たち
****************************

   * 白井 秀行
   * 土屋 雅稔
   * 中島 幹夫
   * 中山 洋一
   * Romain FRANCOISE
   * 山岡 克美
   * 大和 正武

索引
****