Vz resources : MACRO FAQ
2005-06-12T09:10:30+09:00

VZ Macro FAQ - 移動・ジャンプ

論理行頭に移動するには

論理行頭へ移動するコマンド#<#11)がありますので,これを使ってください。また,論理行頭からカーソルを後退させると前の論理行の終端になります。前の行に移動すると考えたとき,初心者は #e#05)を使ってしまいがちですが,論理行頭から後退させる方が確実です。

なお,論理行頭に移動するコマンドには,保存された半端なページング量をクリアする働きもあります。

こういうことも出来ることは出来ますが,意味ないですよね。

1 ^^ "" ?.
        #] cp=cl, #?    ;clは行頭のオフセット値

論理行末に移動するには

論理行末へ移動するコマンド#>#12)がありますので,これを使ってください。また,論理行末からカーソルを前進させると次の論理行の先端になります。次の行に移動すると考えたとき,初心者は #x#06)を使ってしまいがちですが,論理行末から前進させる方が確実です。

表示行頭に移動するには

表示行頭に移動するコマンドはありませんので,関数の&x()を使ってください。引数には画面の左端を0としたx座標の数値を与えます。

製品版サンプルのVZ.defには,次のような標準組込マクロがあります。要するに,これだけです。コード本体よりもヘッダの方が長かったりします。

#if 98
12 ^Q[ @[<--] "画面の左端"
#else
12 ^Q[ [HOME] "画面の左端"
#endif
        ?. &x(0)

表示行末に移動するには

表示行末に移動するコマンドはありませんので,表示行頭への移動と同様に&x()関数を使ってください。ただし,&x(0)だけでよかった表示行頭に比べると格段に難しくなります。標準組込マクロでも非常に手抜きで中途半端です。c.mos流の手抜きという擁護感覚もありますが,全角/半角問題が解決されていませんので今ひとつです。

動作の美しさを考えなくてもよい場合は,素直にコマンドのカーソル移動を次の行頭で実行すればよいでしょう。

        &x(0)                   ;当該表示行頭へ移動する
        #x                      ;次の表示行頭へ移動する
        (r==-1)?{ #> . }        ;移動に失敗したときは論理行末へ移動して終了
        #s                      ;前の行末へ移動する

機能としてはこれで十分なはずですが,画面の下端の行で実行された場合などはスクロールが発生するので,あまり美しくありません。どうしても完璧にやりたいとお嘆きの貴兄には,T.Tanomura氏の究極表示行末をおすすめします。

1 ^Q] [END]  "" ?. &s ly[, kx-, #x (r) ? #> ? #s ky], &d #]     ;T.Tanomura

ファイルの先頭行に移動するには

コマンド #^#41)を使ってください。それだけ。

おいおい。

ファイルの先頭に移動するには

コマンド #^#41)で先頭行へ移動するだけではファイルの先端に到達するとは限りません。#^ の前後いずれかに #<#11)が必要です。

次のような方法もないわけではありませんが,馬鹿みたい。

1 ^^ "" ?.
        &Im(wa+126,0) #U

なお,ファイル全体に対して文字列の検索を行うために,ファイルの先端に移動しておいて前方検索に移行するというのは通常のやりかただと思いますが,この場合はファイルの先端にマッチする文字列があったとしてもヒットしません。

解決方法は色々あるかと思いますが,cp=0 としておいて #c で検索を行った場合は,環境や機種によってはハングアップする事例があるので注意が必要です。

簡単な,しかし泥臭い方法としては,ファイルの先頭にコマンド#nで空行を入れることです。確実なのはファイルの末尾から先頭に向かって検索することです。

ファイルの最終行に移動するには

コマンド #_#42)を使ってください。それだけ。

おいおい。

ファイルの末尾に移動するには

コマンド #_#42)で最終行へ移動するだけではファイルの終端に到達するとは限りません。#^ の後ろに #>#12)が必要です。

ファイル全体をブロックするという場合,ふつう次のようなコードを書くと思います。

        #^ #b #_

はっきり言って,これはダメです。

カーソルのx位置は不定なので,#_でファイルの最終行に飛んでも,そこがファイルの終端とは限りません。ファイルの最終行は常に[EOF]だけの行とは限らないからです。したがって,行ブロックでは取りこぼしが起こる可能性があります。ファイル全体をブロックするなら文字ブロックしましょう。

また,比較的大きなブロックになる場合,カーソル位置がファイル末にあると速度にたいへん大きな差が出ることを覚えておきましょう。ブロックは尾から頭に向かって,が鉄則です。

以上のことを踏まえると,ファイル全体のブロックは次のようになります。

        #_ #> #b #^ #<

ジャンプ直前の位置に戻るには

ジャンプ直前の位置に戻るコマンド #U#43)がありますので,簡単です。ただし,元に戻れる直前のジャンプコマンドに制限があって,カーソル位置に印をつけてからジャンプするコマンドおよびコマンド関数は,#^#_#U#J#M#F&#U() の7種類だけです。#c#r にマーク機能はありませんので,連続した検索後に直前のヒット位置には戻らず,検索文字列を設定して検索を始めた位置になります。もっとも,逆方向に検索すれば済む話なので不都合はないでしょう。

#Uコマンドでの戻り先は,マーク0番の位置になります。このマーク0番の情報は書き換えることも可能ですので,意図的に特定の値を入れておいてコマンド#Uを実行すれば,値が意味する番地にカーソルを飛ばすことも可能です。

#Uコマンド自身にマーク機能があるので,2つの地点を連続で往復できます。(次のマクロはほとんどジョークに近いです。)

1 ^^ "" ?.
        mp[-, #M #c
        (10){ #U }
        mp],

記憶したカーソル位置にジャンプするには

標準組込マクロに4箇所のマーク付けとマークへのジャンプを行うというものがあります。マーク付けに用意された記憶領域は4つあり,マクロでもそのまま使用できます。コマンド関数&#M()&#U()は対になっていて,与えた引数でマークした位置に同じ引数でジャンプできるようになっています。

標準組込マクロの引用

16 ^K0 "マーク(1-4)"
        ?. i=r, &#M(r) (r)?. &m("マーク #%d",i)

17 ^Q0 "マーク位置へジャンプ"
        ?. &#U(r)

ファイルの中間点に移動するには

総行数から計算する

ファイル末尾の行番号を取得して2で割った数値を,コマンド関数&#J()の引数としてやれば,ファイルのほぼ中間に移動できます。&#J()の引数は論理行番号・表示行番号いずれかを行番号モードに応じて与えます。一行あたりの文字数の偏りには対応できませんし,論理行で与えた場合はファイルの大きさにも左右されると思いますが,この場合,精度は問題にしなくてもよいでしょう。

1 ^^ "" ?.
        &s Dn[-, #_ &#J(ln/2) Dn], &d

少し工夫すれば,80%の位置とか指定したジャンプもできます。

1 ^^ "" ?.
        &g("Jump n/10") n=r, (n<0 || n>10)?. &s #_ n=(ln/10)*n, &#J(n) &d

でも,これらのマクロ,実行してみれば明らかですが,システム情報に表示されている百分率表示とかなりずれますよね。行番号で計算しているわけですから当然なのですが,中間点にジャンプしたつもりが「47%」なんて表示されていると,わけもなく嫌な気分に陥るのはわたしだけではないと思います。

ファイルサイズから計算する

さて,そこで正確(…と言うか,システム情報の値の近く)にジャンプさせる方法を考えましょう。ロングポインタを使えば,一応正確な位置に飛べるはずですね。

1 ^\ "" ?.
        &g("n/10") n=r,
        (n>10 || n<0)?>^
        &s
        #_ #M &Le(pu,wa+126)    ;ファイル末尾のポインタ=ファイルサイズ
        &Im(pu,n) &Id(pu,10)    ;先にn倍してから10で割る(誤差対策)
        &Le(wa+126,pu)          ;値を戻す
        #U                      ;ジャンプ
        #f                      ;微調整(^^;
        &d #] .

微調整は必要なようです。n倍しておいてから割ることで誤差の発生を極力抑えていますが,それでも常に10で割り切れるわけではないので,商は内輪に納まります。ほんの数バイトですが,それによって5を指定すれば4.999くらいになって49%と表示される位置にとどまることになります。10-nの部分を引いてやればよいのでしょうが,まぁ,そこまでしなくてもいいかなと思います。

「いや,オレは5を指定したら50%と表示される位置じゃないと絶対に嫌だ」という人は,

        &Le(pu+4,pu)
        &Im(pu+4,10-n)
        &Id(pu+4,10)
        &Ls(pu,pu+4)

…という感じで,お尻から攻めたらいいかもしれません。VZの百分率表示が案外いい加減だということがわかるでしょう。(笑)

ファイルサイズをリアルタイムで取得する

さて,これらのマクロはいずれも一旦ファイルの末尾に飛んでファイルサイズを取得してから該当箇所に飛ぶので,大きなファイルでは速度に問題があることになりますね。しかも,この手のマクロのニーズは大きなファイルで発生するのが普通だと考えられます。ファイルの末尾に飛ばなくても,ファイルサイズをリアルタイムに取得することができればいいですね。だって,ほら,システム情報にはほぼリアルタイムでファイルサイズや現在位置の百分率が表示されているわけですから,VZが内部に持っているのではないでしょうか。そんなの,あったりまえですよねぇ。d(^o^)

残念でした。その手の情報はいちいち保持されずに,ステータスラインに表示されているだけなんですね。ですからリアルタイムに編集中のテキストファイルサイズを取得するには,システム情報を表示している状態で一旦ステータスラインを書き換え,メッセージ展開バッファにあるシステム情報文字列を取得し,そこからファイルサイズを抽出計算することになります。文字列だけ取り出すのは簡単なんですけどね。

1 ^^ "" ?.
        ds[+, #] &Sc(pa,pu+bu,8) ds],   ;システム情報を8バイト複写
        &Ss(pa) &m("%s",r)              ;先頭からの空白をスキップして表示

これを数値にするとなると,やや複雑になります。(他のマクロでpaをヒストリーとして利用することが多い場合は,別にバッファを用意する必要があります。)

1 ^^ "" ?.
        ds[+, #] &Sc(pa,pu+bu,8) ds],   ;システム情報を8バイト複写
        &Ss(pa) t=r, u=pa+10, i-,       ;バッファ,カウンタのセット
        &Im(u,0)                        ;ロング整数初期化
 :l     &Ia(u,t.i-$30)                  ;文字を数値に変換
        i++, (t.i)?{ &Im(u,10) >l }     ;次の桁があれば桁繰上
        &m("%lu",u..0,u..1)             ;ロング整数表示

これにより取得したファイルサイズから飛び先のポインタを算出し,マーク0に格納して#Uでジャンプを行えば,ファイルの末尾にいちいち飛ぶことなく任意の位置に移動できるでしょう。

なお,編集テキストのサイズをリアルタイムで取得するための機械語部品が,Emmett博士によって作成されていますので,より速度を要求するのであれば利用するとよいでしょう。

nifty:FGALDC/MES/15/04414(1997/01/27)の引用

71 ^^ "test.def"
        ss[-, ds[+, #] &Ss(pu+bu)
        ax=gz, si=r, &>
        ds], #] ss],
        &m("%lu",ax,dx)
 
00:     &i(3+$)."$
        $(56,8E,D8,33,C0,8B,D0,BF,0A,00,50,AC,8A,C8,58,80)$
        $(F9,30,7C,05,80,F9,39,7E,02,EB,15,50,8B,C2,F7,E7)$
        $(8B,D8,58,F7,E7,03,D3,80,E9,30,B5,00,03,C1,EB,DA)$
        $(59,2B,F1,83,FE,01,75,05,B8,FF,FF,8B,D0,C3)"

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