Vz resources : MACRO FAQ
2005-06-12T02:10:44+09:00

VZ Macro FAQ - ラインエディット

カーソル行限定で指定の文字列を検索するには

二通りの方法が考えられます。

  1. カーソル行全体をブロックし,置換命令を利用する
  2. ラインバッファに対して,拡張文字列関数を使用する

前者は特別にカーソル行限定という用途でなくても,ブロック選択さえできれば複数行であっても可能な方法です。標題の趣旨とはやや外れますが,汎用的な方法ですので簡単に紹介しておきます。

次のコードは,非ブロック状態での置換を手順化したものです。

        #56
        "なんたら" #m
        ; "かんたら"            ;これはヌル置換の例
        #m
        "ay"                    ;置換範囲と置換方法を指定

非ブロックでは置換範囲として「カーソル以前」「カーソル以降」「全文」が選択でき,それぞれ Back/Forward/All を意味する一文字に対応しています。置換方法としては一括置換を「する」「しない(逐一確認置換)」があって,それぞれ Yes/No を意味する一文字に対応しています。先の例では"ay"ですから,全文に対して一括置換を行います。通常のマクロにおいては全文一括となる場合が多いでしょう。逐一確認するようでは,マクロでやる意味が薄れますから。

一方,ブロック範囲を置換対象とする場合は,置換範囲を確認しません。

        (mb)??.
        #56
        "なんたら" #m
        ; "かんたら"            ;これはヌル置換の例
        #m
        'y'                     ;置換範囲は指定しない

さて,ようやく本題(ほんとは本題じゃありません:-p)です。

この項では置換でなく検索が目的ですから,'y'で応答してはいけないことになります。置換方法は'n'で応答してヒットした文字列で一旦とどめ,置換の確認位置の保存と置換のキャンセルを行う必要がありますね。

        (mb)??.
        #56 "なんたら" #m #m 'n'
        cp[, (s>3)?#[ cp],

このように置換命令を検索に利用できます。

さて,ようやく本題(今度こそホントに)です。

二通りの方法の後者である,ラインバッファを文字列として扱う方法です。

ラインバッファというのは,編集画面の描画速度を高める目的でカーソルのある行を一時的に読み込む作業領域です。このバッファは通常の文字列バッファと違って,文字列の終端がヌルではありません。したがって,そのまま拡張文字列関数にかけると,ヒットする文字列が含まれていない場合は,ラインバッファの終端を越えてずんずんとヌルが出現するまで探索を試みてしまいます。ですからこのバッファを安全に文字列として扱うようにするためには,読み込んでいる行の終端にヌルを仕込み,ことが済んだらこっそりと元に戻さなくてはなりません。手順は次の通りです。

  1. ラインバッファを有効にする
  2. 行の終端にヌルを仕込む
  3. 検索処理を行う
  4. ヒットしたら位置を保存する
  5. 行編集をキャンセルして元に戻す
  6. 編集行の該当箇所に移動する

それではコード化してみましょう。

= t
* m
1 ^^ "" ?.
        &g("String",16) (r|1+1)??.
        #28                     ;ラインバッファに入る
        wa..19.2-,              ;ラインバッファの文字列化
        q=wm+230,               ;ラインバッファ先頭
        &SO(q,pw)               ;検索
        (r)?{
                r[,             ;値を保存
                #54             ;行編集をキャンセル
                #< #]           ;行頭
                cp+=r]-q,       ;カーソル位置ポインタをずらして
                &d              ;再表示
        }?{
                #54 &m(19)      ;見つからない
        }
*

ファイルを変更せずに文字列を削除バッファに取得するには

削除バッファは要するにごみ箱ですが,使いようでスタックのように利用できる便利なバッファです。こういうものを利用せずしてエコロジーなマクロ師と言えるでしょうか。(笑)

しかし,単純に利用するだけでは,文字列の移動にしか使えません。複写と貼付ができてこその有効利用と言えるでしょう。ここでは行編集のキャンセル(#54)を利用して,切取を複写にしてしまう手法を紹介します。

次のマクロはm.gann師の拡張#l(行末まで削除)です。通常の実行で削除,シフト実行で複写になっています。

19 ^[DEL] ""    ;Del -> (65)            ;[\] Copy, view too
        ?. (ks&1)?{ &s #] mr[-,
                #l #54 mr], #?. }       ;#] mr[-, #l mr], #54
        (mb*kx[!&&mr-$80) #l ?#g kx],

手順を説明すると次のようになります。

  1. #] ラインバッファから出る
  2. mr[- 修正情報を保存した上で強制的に未修正とする
  3. #l カーソル位置から行末まで削除バッファに入れる
  4. #54 行編集をキャンセルし削除部分を元に戻す
  5. mr] 保存しておいた修正フラグを元に戻す

早い話が,VZを騙しとおすわけですね。(^^; サスガm.gann師

なお,#lで削除した文字列を ^U で復活させると,カーソル位置は復帰文字列の先頭になります。再利用を目的に削除バッファに入れているわけですから,復帰後のカーソル位置は文字列末尾の方がどうも便利なようです。そこで以下のようにわずかに処理を加えると,使い勝手がよくなるように思います。(後半を略しています。)

19 ^[DEL] ""    ;Del -> (41)    ;[\] Copy, view too / csr ptr
        (ks&1)?{ &s #] mr[-,            ;pk14#11003 m.gann
                #l #54 mr], #?          ;#] mr[-, #l mr], #54
                (((mg..-3).-1)^=$80,    ;H_ear cursor ->$
                . }
        #l

mg..-3 は削除バッファの終端です。その1バイト前に削除方向フラグがあります。付加した部分は,その削除方向を逆転することであたかも#H(行頭まで削除)を実行したかのように復活できます。


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