Vz resources : MACRO FAQ
2005-10-24T21:06:20+09:00

VZ Macro FAQ - 特定モード

キー入力監視型−いわゆるモード型−マクロを作るには

基本型は,&p(ポーズ:キー入力待ち)で実行を一旦停止してキー入力を待ち,入力されたキーに応じて分岐するというものになります。次のマクロは文字キーでスクロールを行う例です。

1 ^\ "" ?.
        et[-, mp[-,
 :L     &m("EXRCWZ/[ESC]")
        ep[+, &p ep],
        (r==#[)?>Z              ;終了
        (r|32)>!{
                ('x'){ r=#x, >N }
                ('e'){ r=#e, >N }
                ('c'){ r=#c, >N }
                ('r'){ r=#r, >N }
                ('z'){ r=#z, >N }
                ('w'){ r=#w, >N }
        }
        (r==#r||r==#c||r==#w||r==#z||r==#e||r==#x)?{    ;Page,Line
        :N      &o(r) >L
        }
        >L
 :Z     mp], et],
        &m("") #]

さらに詳しい情報を得たい場合は,見米快之氏の「モード型マクロ作法書」(nifty:FGALPK/MES/16/00945 [1994/02/03])という文献を参照するとよいでしょう。

すでにリンクの切れている文献ですので,次に引用しておきます。(引用の範囲を逸脱しているかもしれませんが,再編集を行うと不正確なものとなる可能性があるため,敢えて原文に制御コード変換以外の手を加えておりません。)

モード型マクロの作法

     極端な話、キー監視 &p ではユーザーは何を行うか予想できません。ユーザー
    が何を行っても重大な結果に陥らない作法です。

#      ・マクロの実行禁止 mx+

     例えば文字入力しか受け付けたくないようなキー監視では &p の直前で mx+
    としましょう。 &p キー監視状態からのマクロ実行が抑止され、これさえ書い
    ておけば以下の事柄などまったく不要となります。

     以下、敢えて mx+ にはしたくない &p 監視での作法です。

#      ・&p のネストレベル

     できるだけ最上位のネストレベルでキー監視を行いましょう。キー監視状態
    からユーザーが実行してしまった他のマクロ(以下「他のマクロ」)がマクロ
    ネストの制限いっぱいを使用していた場合、両者とも道連れにマクロが止まっ
    てしまいます。

#      ・マクロスタックへのプッシュ

     これもできるだけ行わないようにしましょう。やはり他のマクロの使用でき
    るスタックを制限してしまいます。必要なら、[ESC] を監視するための ep だ
    けのプッシュに留めておき、&p 直後に必要な変数待避を行いましょう。

#      ・非編集モードへの対応

     忘れがちな対策です。他のマクロによっていつの間にか非編集モードへ移動
    している可能性に備えなければなりません。

     以上をまとめると次のような構造になります。

:A      ep[+, &p ep],           ; キー監視
        (s)?{ &o(r) >A }        ; 非編集モード対策
        jx[,je[,js[,            ; 変数のプッシュ
        mx=sq+, eu=ew-,
        (本体処理ルーチン)
        js],je],jx],            ; 変数のポップ
        >A

#      ・ep+ 対策

     あなたの作成するモード型マクロが [ESC]  を監視するつもりがないときで
    も、(r==#[)?{……} というルーチンは必ず入れておきましょう。
     なぜなら、ep+ 状態のキー監視マクロから、あなたのマクロを実行するユー
    ザーもいるからです。

#      ・多重起動対策

     一般的には実行フラグを用いるところですが、 1.6ではフラグを用いなく
    ても多重起動のチェックができます。これにより、[STOP][ESC] でマクロをブ
    レークしても次にマクロキーを押せば直ちに実行できる安全なマクロを作り上
    げることができます。

1 ^KM "ワープロモード"
        ?.
        (mg..2-mg+16)?{                         ;バックグラウンドにマクロ存在?
                r=mg..2-2, &Sx(r..0+8,"WD")     ;そのマクロは自分自身か?
                (r)?? &q                        ;自分自身ならマクロ終了
                .                               ;他のマクロなら起動しない
        }

1 ^KM "ワープロモード"
        ?.
        (mg..2-mg+16)?{                         ;バックグラウンドにマクロ存在?
                r=mg..2-2, &Sx(r..0+8,"WD")     ;そのマクロは自分自身か?
                (r)??{ &q .}                    ;自分自身ならマクロ終了
        }                                       ;他のマクロならかまわず起動する

1 ^KM "ワープロモード"
        ?.
        (mg..2-mg+16)?{                         ;バックグラウンドにマクロ存在?
                r=mg..2-2, &Sx(r..0+8,"WD")     ;そのマクロは自分自身か?
                (r)?? .                         ;自分自身なら起動しない
        }                                       ;他のマクロならかまわず起動する

1 ^KM "ワープロモード"
        ?.
        (mg..2-mg+16)?{                         ;バックグラウンドにマクロ存在?
                r=mg..2-2, &Sx(r..0+8,"WD")     ;そのマクロは自分自身か?
                (r)??{ &q !01                   ;自分自身ならメニューで分岐
                        (r)>?{ >A >B >C }
                        .                       ;メニューを [ESC] で終了
                }
        }                                       ;他のマクロならかまわず起動する

#      ・保存変数

     他のマクロによって破壊されては困る変数は、マクロ内部にバッファを設けて
    ポインタ変数として確保しましょう。

2:      v3+$,. "$[64]"

     このようなマクロをコールすれば、 ポインタ v に64バイトのワークが確保さ
    れます。 v..0 v..1 v..2 などワード値なら 32 個のローカル変数が確保できる
    わけです。

     そしてこのローカルマクロは、 マクロ実行直前はもちろんのこと、&p 直後に
    も必ずコールします。 他のマクロによって v が破壊されているかもしれないか
    らです。

     以上をまとめると次のようになります。


1 ^KM "ワープロモード"
        ?.
        (mg..2-mg+16)?{                         ;バックグラウンドにマクロ存在?
                r=mg..2-2, &Sx(r..0+8,"WD")     ;そのマクロは自分自身か?
                (r)??{ &q .}                    ;自分自身ならマクロ終了
        }
        &01                                     ; ポインタアクセス
        v..0="d:\dat\",                         ; データディレクトリ
        v..1+,                                  ; 保存変数初期化
:A      &p (s)?{ &o(r) >A }
        (r==#[)?{ &b(1) >A }                    ; ep+ 対策
        k=r,                                    ; k=キー入力
        &01                                     ; ポインタアクセス
        &02                                     ; キー分岐
        >A

1:      v3+$,. "$[64]"

2:      ;--- キー分岐 ---
        (k==#m)? ……
        ……
        ……

#      ・ユーザー変数の初期値

     フラグ変数としてユーザー変数を用いるなら v.0 v.1  などとバイト値でも十
    分です。
     その際、 初期化命令をマクロ冒頭で v.0-, v.1+, などと行わなくても最初か
    らワークに書いておくこともできます。

1:      v3+$,. "$(1,1,0,0,2,0)"
                  | | | | | +- v.5=0,
                  | | | | +- v.4=2,
                  | | | +- v.3=0,
                  | | +- v.2=0,
                  | +- v.1=1,
                  +- v.0=1,

#      ・複数のユーザー変数の同時指定

     例えばフラグ変数として f.0 〜 f.5 の6つを初期値付きで、そして、文字列
    等を格納するためのワード変数を v..0 〜 v..7 の8つ(16バイト)、この2種
    を同時に確保するには次のようにします。

1:      v6+f3+$,. "$(1,1,0,0,1,0)$[16]"

     v6+f3+$, は f=3+$, v=6+f, の合成式です。

一定の間隔で自動的にページングを行うには

最も簡単な方法は,!Timerイベントを使用することです。

1 ^\ "!Timer" ?.
        mp[-, #c mp],   ;表示ページング
        (r)?#^          ;ローテート

もうひとつの方法は,モード型と言えないループカウント型です。これは単純なループの内側でカウンタを設置し,カウントされた数に応じた分岐を行うものです。外側のループは (a%1000)??{ … } というような方法で代用することもできるでしょう。

1 ^\ "" ?.
        mp[-,
 :o     ; ---- outside loop ----
        a-,
        #c (r)?#^
        &m("Scroll mode")
 :i     ; ---- inside loop ----
        a++,
        (ks&1)?>z
        (a>999)?>o
        >i
 :z     ; ---- exit ----
        mp],
        &m("Done.")
        &d #] .

VZ Macro FAQ - mode
The VZ resources, valid XHTML 1.0 Strict. ©2005 by mezala.