Vz Resources
Commands
2018-09-09T23:17:30+09:00

コマンド拡張で学ぶVZマクロ入門 #20(#u)

番号記号初期キー機能
#20#u^U ^[INS]削除文字列の復活出力

s==0(編集モード)

削除バッファに積み込まれた文字列を,削除単位でカーソル位置に復活出力する。

戻り値r:常に0

削除系コマンドを使用すると,削除バッファに一時的に積み込まれる。コマンドと削除単位等は以下の通り。

削除系コマンド一覧
コマンド番号/短縮記号初期キー機能削除単位削除方向フラグ
#14/#h^H/[BS]バックスペース(後退1文字削除)1文字0
#15/#g^G/[DEL]カーソル位置の1文字削除1文字1
#16^QH \[BS]語の先頭まで削除同一文字タイプ(ct)の連続文字列0
#17/#t^T \[DEL]語の終わりまで削除同一文字タイプ(ct)の連続文字列1
#18/#H^QT ^[BS]行頭まで削除カーソル位置の直前から論理行頭0
#19/#l^QY ^[DEL]行末まで削除カーソル位置から論理行末1

次の図は,新たな行で「いろは」と書き始めて#18/#H(行頭まで削除)を実行した後,「あいう」と書いて行頭へ移動し#19/#l(行末まで削除)を実行した時の,削除バッファ終端付近の様子を示したものである。(数値は十六進数)

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬──────────
│い│ろ│は│06│00│あ│い│う│06│80│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴──────────

文字列の次に格納されている2バイトの値がサイズ情報((mg..-3)..-1)である。ただし2バイトまるまるがサイズを示すものではなく,最上位の1ビットが削除方向のフラグに使われているためサイズ情報に使われるのは下位15ビットになる。15ビットで扱える値は2の15乗,つまり32767(7FFFh / 0111 1111 1111 1111)であるので,サイズ情報としては十分であろう。(むしろ過多なくらいである。)

#20/#uの実行にあたり,VZは削除バッファ終端(mg..-3)の2バイト下位にあるサイズ情報を参照して,7FFFhとの論理積で削除バイト数を取得し,遡った位置から文字列を出力する。同時に文字列先頭位置を新たな削除バッファ終端として更新する。また,サイズ情報と8000hとの論理積が真なら出力前のカーソル位置に戻す。

s==1(文字列入力モード)

編集モードと同じ

s==2(コマンドラインモード)

編集モードと同じ

s==3(ファイラーモード)

無効

s==4(メニュー)

戻り値rの内容

s==4(1文字入力モード)

無効

マクロによる拡張

削除バッファは普通に使えば単なるゴミ箱であるが,#20/#u(削除文字列復活)を活用することにより,スタックバッファのように扱うこともできることは#19の解説に述べた。プッシュ・ポップだけでも十分に便利ではあるが,さらにペーストができたらどれほど便利であろう。実は削除バッファもテキストスタックと同様にスタックであって,セグメントや大きさこそ違え,構造は似たようなものである。出力後は終端の位置を論理的に更新しているのも一緒で,文字列が移動して無くなるわけでもない。むしろスタックセグメント内に存在しているので,文字列操作も簡単なくらいである。(巨大なサイズを持つテキストスタックは,オフセットアドレスで直接アクセス可能なスタックセグメントとは別の領域にある。)

1 ^U "削除文字の繰り返し復活"
        (ks&1)?{ ((mg..-3)[, }  ;シフト起動時のみ実行
        ;ブロック↑にしないとうまくいかない場合がある
        #u                      ;共通処理(削除文字の復活)
        ?.                      ;シフト起動でなければここで終了
        mg..-3=0],              ;シフト起動時のみ実行

#19/#l(行末まで削除)の解説ページでは強制的に出力後のカーソル位置を更新する例を示したが,復活時に選択するという方法もあるだろう。次の例は,シフト起動すると出力後のカーソル位置を逆転するというものである。

1 ^U ""
        (ks&1)?{
                (((mg..-3).-1)^=$80,
        }
        #u

また,コマンドの拡張ではないが,まとめて削除した文字列を1文字ずつばらばらに復活したいという場合の例である。ローテクだが,1バイト・2バイト(半角・全角)混在の可能性があるので,メモリ上で操作するよりもエディタに任せるのが簡単だ。

= delodelo = by H_ear
* mad for vz!
1 ^\ "" &s
        a=((((mg..-3).-1)&$80)!=$80,    ;削除方向を記憶
        #J                              ;作業用に入力窓を出す
        #u                              ;削除文字列を吐き出す
        (-1){                           ;無限ループに入る
                &o(#g-a)                ;1文字ずつ削除
                (lx==0&&cd==$A)?{}      ;条件を満たせばループを抜ける
        }
        #[ &d .                         ;入力窓をキャンセルして終了
*

次のマクロは逆に1文字ずつ連続削除したものを,まとめて復活してしまおうというものである。Windowsのアプリケーションで目にする,似た操作のUNDOをまとめるというオプションの#20版ということになるだろう。

= delundo.def = by H_ear
* mad for vz!
1 ^U "連続復活"
        p=((mg..-3)..-1)&$8000,         ;削除バッファサイズ情報/削除方向
 :l     o=((mg..-3)..-1)&$7fff,         ;削除文字サイズ
        ((o==1||o==2) && ((mg..-3)..-1)&$8000==p)??. #u >l
*

削除方向が同じで削除バイト数が1バイトか2バイトなら,連続した1文字削除と見なすのはいささか乱暴な気もするが,大間違いではないように思う。


コマンド拡張で学ぶVZマクロ入門 #20
The VZ resources, valid XHTML 1.0 Strict. ©2007 by mezala.