第0章 いきなり実用マクロ

 あなたはまず「VZのマクロは可読性が低い」という先入観を捨てなくてはなりません。

 簡単な実用マクロを示しますので、マクロの概念をつかんでください。

 基本的にマクロ番号は80、キーアサインは^\[CTRL]+[\])に統一しています。

カーソル位置に定型句を書き込む

80 ^\   "IDと氏名"
        "NBD00533 上村 郁夫"

 このマクロを実行すると、カーソル位置に「NBD00533 上村 郁夫」と書き込みます。二重引用符でくくった文字列はそのまま送り出されるのです。日本語FEPに登録できないような長い定型句を登録するとよいでしょう。「"IDと氏名"」はマクロのタイトルなので、書き込みません。

カーソル位置に定型文を書き込む

80 ^\   "名刺"
        ?.
        #n
        "ロンドン市ベーカー街221番地B" #m
        "シャーロック・ホームズ" #m

 このマクロを実行すると、カーソル位置に2行の文字列を書き込みます。

 #nは1行挿入。#mは改行(リターン)です。[CTRL]+[N][CTRL]+[M]というキーアサインから類推がきくでしょう。#n#53#m#04という具合に、コマンド番号で書くこともできます。巻末のコマンド一覧を参照してください。

 さて、「?.」とは何でしょうか。マクロの先頭で記述した場合にかぎり「(s)?.」と同じ意味になり、編集モード以外(1行ウィンドウ、コマンドライン、ファイラー)では何もしません。いまは意味はわからなくて結構ですが、編集モードで使うマクロの先頭では「?.」という呪文を唱える、とだけおぼえてください。

ファイルの特定行をオープンする

80 ^\   "vz.def"

        ?.
        #O &?(pi) "vz.def -176" #m

 このマクロを実行すると、vz.defをオープンして176行目にジャンプします。

 #Oはファイルのオープンです。[ESC]+[O]というキーアサインから類推がきくでしょう。【入力ファイル】の窓に「vz.def -176」という文字列を書き込んでリターンを押す、という動作をそのままマクロにしています。

 さて、&?(pi)とは何でしょうか。「pi」はvz.defの存在するディレクトリ名を示します。もし、vz.defが「c:\def」というディレクトリにあったとすると、&?(pi)で「c:\def\」と書き込みます。

 したがって、【入力ファイル】の1行ウィンドウに書き込まれる文字列は「c:\def\vz.def -176」になります。最初から「#O "c:\def\vz.def -176" #m」と書いてもかまいませんが、もしvz.defを置くディレクトリを変更した場合には、マクロを書き換えなくてはなりません。&?(pi)なら書き換えずに済みます。

句読点「。、」を「.,」に置換する

80 ^\   "句読点置換"
        ?.
        #56                             ; 文字列の置換
        "。" #m                         ;【検索文字列】に「。」を入力リターン
        "." #m                         ;【置換文字列】に「.」を入力リターン
        "ay"                            ;「A テキスト全体」を全部一度に置換
        #56                             ; 文字列の置換
        "、" #m                         ;【検索文字列】に「、」を入力リターン
        "," #m                         ;【置換文字列】に「,」を入力リターン
        "ay"                            ;「A テキスト全体」を全部一度に置換

 「ay」は画面に書き込まれるわけではなく、メニューに英字で答えています。「AY」と大文字を使っても同じです。

        ┌ 【置換範囲】 ┐
        │A テキスト全体│
        │F カーソル以降│ に「a」と答える。
        │B カーソル以前│
        └───────┘
 《全部一度に置換しますか? (Y/N)》に「y」と答える。

 キーボードマクロで上のようなマクロを作ったことのある人は多いのではないでしょうか。^K_「キーボードマクロ文挿入」で書き出してみると、次のようになったはずです。

90 ^\ "" #56"。"#m"."#m"ay"#56"、"#m","#m"ay

 二重引用符「"」が頻発して読みにくいですが、整理すると前のリストのようになります。最初に二重引用符がふたつ連続しているのは、マクロのタイトルが省略されているためです。「"句読点置換"」のように適当なタイトルを書きこんでかまいません。

 最後の「ay」の後ろに二重引用符がないのは、ちょうどマクロの最後なので、文字列の終端を明示しなくても大丈夫ということのようですが、後ろ側にマクロを付け足す場合など考えると、VZにきちんと処理してほしいところです。

ファイル全体の行数を調べる

80 ^\   "行数"
        ?.
        #_                              ; ファイルの最後へ
        n=ln,                           ; 論理行番号を変数 n に代入
        #U                              ; 直前のカーソル位置へ
        &m("行数 %d",n)                 ; メッセージ

 プログラミングらしくなってきました。

 「#_」でファイルの最後へジャンプします。ちなみに、

#^ファイルの先頭
#<論理行末
#>論理行末

 です。いやはや単純明快。「VZのマクロは可読性が低い」なんて、誰が言ったのでしょう。

 n=ln,は演算式で、変数nに論理行番号lnを代入しています。

 #Uで直前のカーソル位置に戻ります。Uターンする、とおぼえるとよいでしょう。

 &m("行数 %d",n)で、nがあらわす数値を「%d」に置き換えて表示します。nが100だとしたら、画面の最下行に「行数 100」とメッセージが出ます。

次の段落の先頭へカーソルを移動する

80 \[CR]  "次の段落の先頭へ"
        ?.
        #>                              ; 論理行末へ
        #d                              ; カーソルをひとつ進めて次行へ
        (r==-1)? #m                     ; ゆきどまりなら改行

#> #d」は簡単ですね。

#e[↑]
#x[↓]
#s[←]
#d[→]

 これも [CTRL]+[E][X][S][D]のキーアサインから類推がきくでしょう。

 最後の「(r==-1)? #m」は何でしょうか? rは「返り値」と呼ばれる変数で、#dが正常に実行されたら0、異常があれば-1になります。カーソルがEOF(ファイルの最後)にあって、#dでカーソルがこれ以上進まないとき、-1になるので、#mで改行をいれてやります。「(r==-1)? #m」は「返り値が-1なら改行をいれる」と読み換えてください。これが「条件分岐」の考え方です。

条件分岐

(式)? 真なら実行する命令

フリーカーソル

 VZの標準設定では^E[↑])、^X[↓])によって改行より右側でカーソルを動かすことができますが、^S[←])、^D[→])では、カーソルは改行マークの真上にあったものとして処理されるので、見た目とはちがった動作をします(^Dだと次行に移動)。また、ファイルの最後で^X[↓])を押すと、行き止まりなので何も起こりません。

 次のマクロを使えばカーソルを自由に動かすことができます。ただし、カーソルが改行より右側にあるときに文字を入力すると、改行マークの位置から書き込まれる点は変わりません。

80 ^S   "←"
        ?.
        (ct>1)? #s ? &x(lx-1)

80 ^D   "→"
        ?.
        (ct>1)? #d ? &x(lx+1)

80 ^X   "↓"

        ?.
        #x (r==-1)? { #> #m }

 ctはカーソル位置の文字タイプを示すシステム変数です。

ctの値文字タイプ
0EOF(ファイルの最後)
1改行マーク
2半角/全角スペース、タブ、制御コード
3記号(句読点、括弧、半角カタカナなど)
4ひらがな
5全角文字(漢字、全角英数字、全角カタカナなど)
6半角英数字(ドル記号'$'とアンダーバー'_'を含む)

 「&x(数値)」は「数値」で指定された桁位置にカーソルを強制的に(?)移動するシステム関数です。数学の「X方向」「Y方向」から類推がきくでしょう。lxは現在カーソルがある桁位置を示すシステム変数です。「&x(lx+1)」でカーソルは一つ右へ移動します。^Dのマクロは「カーソル位置が改行でなかったら通常どおりカーソルをひとつ進める(#d)、改行だったらカーソルの桁位置を右へ強制移動する「&x(lx+1)」と読み換えてください。

(式)? 真なら実行する命令 ? 偽なら実行する命令

 ^Xのマクロでは、#x[↓])を実行して行き止まりだったら返り値が-1になりますので、「#> #m」で改行を入れます。「{」と「}」で囲むことによって、複数の命令を一つの命令(ブロック)として扱うことができます。

(式)? { 真なら実行する命令1 命令2 }

区切り線をひく

80 ^\   "区切り線"
        ?.
        #<                              ; 論理行頭へ
        #n                              ; 1行挿入
        (79){"*"}                       ; 「"*"」を79回実行する
        #d                              ; [→]

 カーソル位置に「*」で区切り線をひきます。

 (79){"*"}はなんだか条件分岐に似ていますが、「?」がないことに注意してください。

(回数){ 繰り返したい命令 }

 これを「ループ」と呼びます。「*」を79個書き連ねるより、ずっと短く記述できます。命令が一つしかなくても「{」と「}」で囲みます。

 VZの標準設定では画面幅は80桁になっているので、79回「*」を書き込めば、画面幅いっぱいに区切り線を引くことができます。実行してみると、全部書き込むまで多少時間がかかるのが気になります。一瞬にして書き込むには、1文字ずつ画面を書き換える過程を見せないようにします。

80 ^\   "区切り線"
        ?.
        &s                              ; 画面出力を停止(silent)
        #<                              ; 論理行頭へ
        #n                              ; 1行挿入
        (79){"*"}                       ; 「"*"」を79回実行する
        #d                              ; [→]
        &d                              ; 全画面を再表示(display)

 どうでしょう。少しはマクロコードになじめたでしょうか?