$モーション後のカーソル移動

Aug 22 2020

私はVIMアドベンチャーと呼ばれる素晴らしいゲームをプレイしています(以下の画像から)。質問はゲームからですが、VIMでも再現できるので、ここが私が尋ねる場所です。

normal modeある行nと列に立っていると仮定しますm。キーを押すjと、位置は行n+1と同じ列になりますm。行のn+1列数がm、たとえばo、より少ない場合は、列に配置されますo。もう一度を押しjます。n+2列の行に移動しますm(前と同じチェック)。参照してください、あなたが始めた列mは、記憶されています。これは最初の画像で見ることができ、赤い線はj動きを表しています。

ただし、中にいてnormal modeキーを押す$と、現在の行の最後に移動します。ここで、前の段落で説明したのと同じ一連の動きについて考えてみましょう。各運動は、jその行の最後の文字にあなたを移動します。mこの場合、は記憶されません。これは2番目の画像で見ることができます。最初$に押すと、最初の行の最後にクーサーが配置されます。次に、複数のj動きを押すことによりm、最初の段落で記憶されていたを無視して、各行の終わりにクーサーを着陸させます。

これはVIMのドキュメントにはありません。この記憶メカニズムがどのように機能するかを説明できますか、それともこれを説明しているドキュメントの一部を教えてください。


回答

2 filbranden Aug 22 2020 at 16:58

実際、$コマンド自体のドキュメントには、この動作への直接的な言及はありません。

g$モーションのドキュメントでは、実際にはこの動作について言及していますが、以下g$との違いを説明しています$

$行の最後の文字が画面に表示されていない場合、またはカウントが使用されている場合とは異なります。さらに、垂直方向の動きは、行の終わりに行くのではなく、列を維持します。

ドキュメントを介する以外に、Vimが実際にこの列追跡を実装する方法を確認できます。これは、getcurpos()その情報を「curswant」属性としてエクスポートするなどの機能があるためです。

curswant垂直方向にカーソルを移動する際数が好ましいカラムです。

(によって返されるDictにも「curswant」属性がありますwinsaveview()。)

たとえば、長い行を水平方向に列24に移動し、次に垂直方向に17列しかない行に移動した場合、次のように表示されます。

:echo getcurpos()
[0、39、17、0、24 ]

したがって、列17にいることがわかりますが、「curswant」は列24であり、行に十分な列がある場合、Vimは最大24列に移動します。

を押し$getcurpos()出力をもう一度確認すると、次のように表示されます。

:echo getcurpos()
[ 0、39、17、0、2147483647 ]

したがって、Vimが$「curswant」を非常に大きな数に設定することで動作を実装していることがわかります。これは、Vimが1行に格納できる列の最大数です。

(その数は実際には2 31-1であり、これはintC言語の符号付き型に格納できる最大の正の整数です。)