MH のどうでもいいような趣味の講座


「Mh中級者以上向け〜どうでもいい(笑)ような趣味の講座」


◎第3回: Mhフォーマット入門・その1

From: hayashi@atlas10.kuic.kyoto-u.ac.jp (Haruhisa Hayashi)
Subject: Mh-guide#03
Organization: Industrial Chemistry, Kyoto University, Kyoto, Japan.
Date: Mon, 2 Mar 1992 08:03:38 GMT

Mhフォーマットは、慣れてしまえば簡単であるが、ちょっと触りづらい。 Mhは、そのほとんどの出力の方法が、フォーマット・ファイルにより制御される。 あまりにも、カスタマイズ可能なように 書かれていることと、その制御コマンドのややこしさに圧倒され、 なかなか取りつきにくいものになってしまっている。

さらに詳しく説明した本が……ないんです(苦笑)。
一番詳しくかいてあるのが、「UNIX Magazine 1990.9」です。 ここには、mh-format の関数一覧がついているので、まずこれを 読んでください。(ちょっとウソも書いてあるけど)

## 1992年3月時点。まぁ今(1995年5月)でも、あまりいい本はないですが。
## ちなみに mh-6.8 から mh-format のオンラインマニュアルがついた。
## 兎に角、man mh-format してみれば、どーにかなるかと:-)

ここでは、簡単そうなファイルの実例と、私の設定ファイルの内容 を紹介しておく。

/usr/local/lib/mh/scan.timely は、

となっている。これをコマンドラインから用いるのには、

% scan +メールフォルダー名 -form scan.timely

で使用できる。この「scan.timely」フォーマットファイルを使用 すると、

のように、メッセージ番号、時刻、差出人、Subject、内容の一部 が 表示される。

このscan.timelyでは、条件判別で表示を変えるようになっている。

  1. 「時刻」は、まる1日前迄のメールなら「時間」を、1週間前 までのものなら「曜日」を、それ以前のものなら「日&月」を 示すように、設定してある。
  2. 差出人が「自分」の場合 (Alternate-Mailboxes が、ここに効 いてくる) では、「どこに出したのか」を表示するように、設 定してある。
フォーマットファイルは、エスケープシーケンスの集まりである。
では、説明をしていく前に、覚えておくことは、
%
各エスケープシーケンスの開始を表す。 (つまり各コマンドの区切りである)
2つのレジスタ
文字用のレジスタ(str)と数値用(num)がある、
{To}
これは、To ヘッダの内容を表す。(大文字小文字の区別はない) どうやら、この「{ }」の結果は、str にセットされるらしい。 また、「入れ子」になっていない限りは、表示される。
( )
組み込み関数の呼び出しである。 (例えば、「msg」関数を使用するなら、(msg)とする) どうやら、この結果は、num にセットされるらしい。
%<, %|, %>
%< =if、%| =else、%> =endif である。 (mh6.7.2 からは、elsifとして、「%?」が使用可能)
である。

:> %4(msg)%<(cur)+%| %>%<{replied}-%|%<{encrypted}E%| %>%>\

まず、「%4(msg)」で、メッセージ番号(戻り値:整数)を4桁で 表示している。
次に、「%<(cur)+%| %>」とは、

ってことで、そのメールにカーソルがあれば「+」を表示し、 なければ1文字空白を表示する、ということである。 (カーソルの位置は、.mh_sequence ファイルを参照する)

「%<{replied}-%|%<{encrypted}E%| %>%>」 も同様に、ヘッダに「replied」がついていれば、「-」を 表示し、ない場合、さらに「encrypted」であれば、「E」 を表示し、どちらもなければ1文字空白を表示するという ものである。

「\」は行の連続を意味している。

さあここから、「第1の条件設定」である。 そのメールの date の値により、いろいろ判別しているのである。
:> %(void(rclock{date}))\

「(rclock{date})」は、{date}で、ヘッダから date の内容を 取りだし、組み込み関数 rclock で 「現時間との差」を求め、 その値を、num レジスタに void 関数でセットしている。
# (void ...)としないと、画面に表示されてしまう。
あとは、この numレジスタの値との比較を行なっている。

:> %<(gt 15768000)%03(month{date})%02(year{date})%|\

if その値が、15768000 より大きければ、日を3文字、年を2文字 で表示する。(分だから、半年か?)

:> %<(gt 604800)%02(mday{date})%03(month{date})%|\

else if 604800 (1週間)より大きければ…、

:> %<(gt 86400) %(day{date}) %|\

else if 86400 (1日)より大きければ…、

:> %02(hour{date}):%02(min{date})%>%>%>\

else 時を2文字+「:」+分を2文字 表示。
endif endif endif

:> %<{date} %|*%>\

ヘッダに date フィールドがあったら、1文字空白、 なければ、「*」を表示。
これで、「時刻の条件表示」は終了。
次に、「差出人の条件表示」である。

:> %<(mymbox{from})To:%14(friendly{to})%|%17(friendly{from})%> \

(mymbox)は、from行をみて、自分が出したメールかどうかを判別する 関数である。つまり、この書き方は、
「mymbox(from)が真なら、To:%14(friendly{to}) を、 偽であれば、%17(friendly{from})を実行する」 ってわけである。
(friendly)は、そのアドレスを、読みやすいカタチに変換する関数である。 自分が出したものであれば、「To:」+14文字でヘッダのtoフィールドを、 でなければ、17文字でヘッダのfromフィールドを表示するのである。

:> %{subject}%<{body}<<%{body}%>

あとは、%{subject} で、ヘッダの subject フィールドが表示され、 {body} がある、つまり中身があれば、「<<」のあとに表示する、って 訳である。ここで偉いのは、その文字列が長くとも、scan コマンドが 勝手に切ってくれるのである。

以上が scan.timely の説明である。

--
/* はやし☆はるひさ (hayashi@kuic.kyoto-u.ac.jp) 京大・分子・中西研 */
多少改定 10May1995 by はやし はるひさ hayashi あっとまーく laic.u-hyogo.学術.日本
## ちなみに上記の関数の説明は、mh-6.7.2 レベルでの話で、
## mh-6.8 では多少変更されている。
基本的にはほとんど一緒ですが、

mh-6.7.x

mh-6.8.x

最初から説明します

:> %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\
:> %(void(rclock{date}))\
:> %<(gt 15768000)%03(month{date})%(void(year{date}))%02(modulo 100)\

まずここね。
mh-6.7 までのように甘くなく:-)、%02(year{date}) と数値(year関数はinteger)を 文字列的直接操作が出来なくなったので、一旦 void で num レジスタに退避させ、 次の modulo 関数で、100 で割った余り(つまり西暦の下2桁)を str レジスタに 放り込み、%02 で出力している。

## 扱いが厳しくなったのね:-)

:> %?(gt 604800)%02(mday{date})%03(month{date})\
:> %?(gt 86400) %(day{date}) %|\
:> %02(hour{date}):%02(min{date})%>\

このあたりは、%? (=elsif) が使えるようになったから。

:> %<{date} %|*%>\
:> %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \

ここは若干丁寧に判別を増やしたのと、 mymbox{} が そのアドレスが user のものであれば 1、なければ 0 を num レジスタに返すので、「zero」(num レジスタが 0 であれば真)を 用いて判別しているんですね。

:> %{subject}%<{body}<<%{body}%>

あとは同じ:-)


◎第4回: Mhフォーマット入門・その2

From: hayashi@atlas10.kuic.kyoto-u.ac.jp (Haruhisa Hayashi)
Subject: Mh-guide#04
Organization: Industrial Chemistry, Kyoto University, Kyoto, Japan.
Date: Mon, 2 Mar 1992 08:13:11 GMT

次に、私の inc.form、scan.form ファイルを紹介する。
scan.timely をいじっただけなので、ほとんど同じである。

inc.form と scan.form は、それぞれ inc, scan コマンドを用 いるときの為に、私が.mh_profile で設定した format ファイル である。(別に同じファイルでも良いのだが。)
私の場合、inc したときには、差出人によって少し表示を変更し、 また scan したときには、Mailing List からのメールについて は、そのメール番号を表示するように設定している。
(これは、実は書いた当時(1月頃)の話です。現在は slocal を はっているので、inc する必要が全くなくなってしまったの(^^))

## ちなみに「1月」って…………、1992年1月です(遠い彼方を見つめる…^^;;)

1.inc.form

:> %4(msg)%<(cur)+%| %>%<{replied}-%|%<{encrypted}E%| %>%>\
:> %(void(rclock{date}))\
:> %<(gt 15768000)%03(month{date})%02(year{date})%|\
:> %<(gt 604800)%02(mday{date})%03(month{date})%|\
:> %<(gt 86400) %(day{date}) %|\
:> %02(hour{date}):%02(min{date})%>%>%>\
:> %<{date} %|*%>\

ここは全く同じである。

:> %(void{Reply-To})\
:> %<(match 98game)[98] %|\
:> %<(match hayashi)(^^;)%|\
:> %>%> \

これは差出人によって、メッセージ番号、時刻のあとに、 ちょっとした表示がつくように、判別している。

本来なら、from フィールドを参照すればよいのであるが、 ML(メーリングリスト)などからのメールでは、その from が、ML名でなく、そのメールをMLに投稿した人 になっている場合が多い。

# このへんは、どのフィールドを参照するべきか、自分で考えるように。

私の場合、

:> %(void{Reply-To})\

で、Reply-To フィールドを str レジスタにセットし、

:> %<(match 98game)[98] %|\
:> %<(match hayashi)(^^;)%|\

その Reply-To 文字列の中に、「98game」という文字列があれば (match コマンドによる)「[98] 」と表示し、それ以外のメールで 自分が出したメールであれば、「(^^;;)」を表示する。

:> %>%> \

^^^^^ 更にそれ以外のメールでは、5文字分の空白を表示している。

気をつけなければならないのは、その後にある、1文字分の 空白である。

:> %>%> \

これにより、1文字分の空白が表示される。

:> %<(mymbox{from})=>%15(friendly{to})%|%17(friendly{from})%> \
:> %{subject}%<{body}<<%{body}%>

あとここも、ほとんどかわらない。
自分からのメールの場合、「To:」でなく、「=>」にしているだけである。

この format ファイルを用いると、

   1   Thu  (^^;) => hayashi        test< < This is test mail, sorry!!
   2  12:48 [98]  => 98game@ariel10 Souieba....< < そういえば、今度発売の
   3+ 14:29 [98]  Nyan-chan         Re: Souieba....< < おひさしぶりです、
   4  15:39       p-honda@axis.uec. Re: How are you ?< < 土曜日はどうしま
てな具合になる。

## 前回にも書いたように、mh-6.8.X では 数値の文字列操作に対して
## 厳しくなったので、「%02(year{date})」は通りません。
## 「%(void(year{date}))%02(modulo 100)」でないと駄目です。
## また勿論、mh-6.8.X では %? (=elsif) が使えますので、
## もう少し綺麗:-)に書けるはずです。

2. scan.form

これも大筋で変化はない。 ただ、頭の部分がちょっと違うだけである。

:> %4(msg)\
:> %<{X-Ml-Count} %4(compval{X-Ml-Count})%>\

まず4文字分で、メッセージ番号を表示している。

次にヘッダに{X-Ml-Count}というフィールドがあれば、その値を compval 関数で、取りだしてnumレジスタにセットしている。 このとき、「入れ子」になっていないので、4文字で表示される。

私の入っているMLからのメールには、「X-Ml-Count」という フィールドがあり、ここにトータルのメール番号が書かれている。 このフィールドを読み込み、表示することで、メールが整理される。

:> %(lit)\

lit 関数は、その arg を str にセットする関数であるが、 ここでは、str のクリアに用いている。(あまり意味はないが。)

あとは、inc.form と同じ。

:> %<(cur)+%| %>%<{replied}-%|%<{encrypted}E%| %>%>\
:> %(void(rclock{date}))\
:> %<(gt 15768000)%03(month{date})%02(year{date})%|\
:> %<(gt 604800)%02(mday{date})%03(month{date})%|\
:> %<(gt 86400) %(day{date}) %|\
:> %02(hour{date}):%02(min{date})%>%>%>\
:> %<{date} %|*%>\

:> %(void{Reply-To})\
:> %<(match 98game)[98] %|\
:> %<(match hayashi)(^^;)%|\
:> %>%> \
:> %<(mymbox{from})=>%15(friendly{to})%|%17(friendly{from})%> \
:> %{subject}%<{body}<<%{body}%>

んでこれを使うと、

% scan +98game -form scan.form

   1  101  Mon  =>98game@ariel10. Re: about PM<<はやしです。In message 
   2  102  Thu  Pon-Ponko Honda   Re: about PM<<ども、ぽ です。In messa
   3  103 12:48 =>98game@ariel10. Souieba....<<そういえば、今度発売のあ
   4+ 104 14:29 Nyan-chan         Re: Souieba....<<おひさしぶりです、ど
てな具合になる。

# さぁ次回からは、このいい加減な好評連載も、山場(私が一番書きたい)の 「slocalをはろう!」に突入します。

slocalとは、届いたメールを、ヘッダの部分のキーワードに対応して、 自動的にメールフォルダーに分類して放り込んでくれる、というMhの 便利なツールなんです。(誰が使うんだ?>自分) (いつポスト出来ることやら………)

--
/* はやし☆はるひさ (hayashi@kuic.kyoto-u.ac.jp) 京大・分子・中西研 */
多少改定 10May1995 by はやし はるひさ hayashi あっとまーく laic.u-hyogo.学術.日本
ってことで:-)、mh-6.8.X-jp2x では、mime-encode/decode に対応しています。 mh-6.8-JP-README.2 の「[3.6.2] mh-format による方法」を参照して下さい。

つまり:-)、mh-format の関数に、

               argument return
      hencode  expr     string  日本語文字列を RFC-1342 形式に変換
      hdecode  expr     string  RFC-1342 形式を 日本語文字列に変換
という2つの文字列操作関数が拡張されているのです。

## 『RFCー1342形式』については、RFC-1342を読んで下さい:-p
## つまりは、「=?ISO-2022-JP?…………=?=」な文字列のことです。

## ちなみに:-)、この文字列を見て「MIMEメール」とか言う人も居るようですが、
## これは飽く迄、MIME ヘッダでの encode/decode 規格ですので。
## 本来の「MIME」とは、Multipurpose Internet Mail Extensions ですので。

これを scan/inc/repl 等 format 中の RFC-1342形式文字列が出てくるところ、 例えば 「%17(friendly{from})」を「%17(hdecode(friendly{from}))」とか、 噛ませてやるだけで OK です。

## hdecode() を使用したこの format ファイルを使用することで
## decode されて表示されているのですから、勿論元のメールファイル自体は
## なんら変更されていません。

あ、そうそう、この mh-6.8.x-jp2x での hencode/hdecode 関数拡張は、 MH config 時の option MIME とは無関係ですので。

jp2x パッチを当てると、これらの関数が使えるようになります。 ここいらは、そのサイトでの Mh の configuration に依存しますが。

参考) mh-6.8 の日本語化の歴史(笑)。 その後、高田@NTTさんが mh-6.8-JP-patch.2 を発表。 これは上述した RFC-1342 形式の文字列を扱う拡張がなされたもの。 2a、2b、2c とバグフィックスが続く。

知らぬ間(笑)に、日本各地の anonymous-ftp に、 mh-6.8.3-jp2c.tar.gz と、オリジナルとパッチを1つにまとめた のが置かれている:-)

## mh-6.8 -> mh-6.8.? のどこかの version Up で、
## 本当に些細な変更のために、jp-patch が通らないので、
## 誰かが一つにまとめて下さったのでしょう。


目次へ 第1回へ 第3回へ 第5回へ
© Haruhisa Hayashi 1992,1995
改訂(文章の大幅書換+frame化)版 [21Mar1997]は こちら
by はやし はるひさ hayashi あっとまーく laic.u-hyogo.学術.日本