概要
これはバグであり、パッチ(743)があります。このバグは両方の例に影響しますが、下に移動した文字が (空白)であるため、1つのケースでは表示されません。解決策はパッチをインストールすることですが、バグの影響を受けない多くの回避策や代替方法もあります。
NB:{、}そしてBすべてが同じテキストオブジェクトを参照:ブロックを(:help aB
、:help iB
)。これまたは他の回答が質問で使用されたものとは異なる記号を使用している場合、それが理由である可能性があります。
不具合
完全にはわかりませんが、興味のある方のために説明しておきます。
表示される動作は、vim_devで中平幸宏が言及したバグによるもので、彼のパッチは7.4.743としてリリースされています。ビジュアルモードでの「p」により、予期しない行分割が発生します。
視覚モードput(:help v_p
)は、視覚的に選択されたテキストをレジスターからのテキストで置き換えることを想定しています。このバグは、a)レジスターが行ごとのタイプ(:help linewise-register
)であるが、視覚的な選択が文字ごとのタイプであり、 b)視覚的な選択が行の最後の列で終了する場合に発生します。あなたの場合、内側のブロックをヤンクしてからブロックを視覚的に選択して貼り付けると、ヤンクされたレジスターは線状になり、視覚的な選択は文字状になります。内部ブロックとブロックの両方を名前付きレジスターにヤンクして検査することができます:
オン
for(int i = 0; i < s.length(); i++){
int index = s[i] - c;
if(root->next[index] == NULL)
root->next[index] = new TrieNode;
root = root->next[index];
}
私たちはします
"ayi{
"bya{
:registers ab
示す
--- Registers ---
"a int index = s[i] - c;^J if(root->next[index] == NULL)^J root->next[index] = new TrieNode;^J root = root->next[index];^J
"b {^J int index = s[i] - c;^J if(root->next[index] == NULL)^J root->next[index] = new TrieNode;^J root = root->next[index];^J}
そして
:echo getregtype('a') " displays 'V' for linewise
:echo getregtype('b') " displays 'v' for characterwise
文字ごとのビジュアル選択を行ごとのレジスタに置き換えるには、ビジュアル選択の最初と最後を保持する行を2つに分割して、テキストを間に挿入できるようにする必要があります。これは通常うまくいきます:
vimを実行して
(a)vim -u NONE -U NONE
と入力する
iaaa
bbb
ccc
ddd<Esc>ggYjlvp
結果は
aaa
b
aaa
b
ccc
および(b)
iaaa
bbb
ccc
ddd<Esc>ggYjvjp
に
aaa
aaa
cc
ddd
しかし、文字ごとの視覚的選択が行の最後の列で終了する場合(および改行/n
/を含まない場合)は、^J
何か問題が発生します。これは、カーソル位置に関係します。カーソル位置は、突然-1ずれ、特別にインクリメントする必要があります。これは、パッチが行うことです。(a)をcommandと比較<Esc>ggYjllvp
します。つまり、カーソルを行の最後の「b」に置くために、列をもう1つ右に移動する以外は同じコマンドです。結果は以前と同じです!
次のテキストを取ります:
if (TIRED){
goto bed;
} else {
goto work;
}
カーソルを2行目に置くと、yi{va{p
作業はうまくいき、
if (TIRED)
goto bed;
else {
goto work;
}
ヤンクレジスターは依然として行ごとであり、視覚的な選択は文字ごとに行われますが、視覚的な選択は最後の列で終了することはなく、すべて正常です。
質問の例文
最初の行の右括弧と左中括弧の間の空白が唯一の違いである2つのテキスト例の場合、コマンドの動作は異なるように見えるかもしれませんが、実際にはそうではありません。最初のケースでは、成功したように見えますが、角かっこを削除すると、最初の行に末尾の空白が存在するはずです。末尾の空白は、代わりに最後の行にあります。とyi{va{p
for(int i = 0; i < s.length(); i++) {
int index = s[i] - c;
if(root->next[index] == NULL)
root->next[index] = new TrieNode;
root = root->next[index];
}
なる
for(int i = 0; i < s.length(); i++)
int index = s[i] - c;
if(root->next[index] == NULL)
root->next[index] = new TrieNode;
root = root->next[index];
␣
と同じように
for(int i = 0; i < s.length(); i++){
int index = s[i] - c;
if(root->next[index] == NULL)
root->next[index] = new TrieNode;
root = root->next[index];
}
なる
for(int i = 0; i < s.length(); i++
int index = s[i] - c;
if(root->next[index] == NULL)
root->next[index] = new TrieNode;
root = root->next[index];
)
ソリューション
解決策はパッチをインストールすることですが、バグの影響を受けない周囲のブラケットを削除する他の多くの方法があります。最善の回避策は@Gillesの回答ですが、最も簡単なのは、ヤンクする前に視覚的に選択して、レジスターを文字ごとに維持することです。
Tim Popeのサラウンドプラグインは優れていますが、(少なくとも私にとっては)角かっこを削除するだけではありません。2番目の行を最初の行に結合し、インデントを削除して、カーソルを最初の行の先頭に移動します。これにより、重要なクリーンアップが行われます。Ingo KarkatとLuc Hermitteには、レジスタと貼り付けを処理するプラグインがあり(他にもたくさんあると思います)、これでこれを実行できるはずです。私は彼らと非常に慣れていないんだけど、私は信じていLH-ブラケットあなたが行う可能性があり<M-b>x
、周囲のブラケットを削除するには、あなたが見て可能性があり、より強力な(特にビジュアルモードで)置くためReplaceWithRegisterとUnconditionalPaste。
最良の方法は、@ Gillesの回答で示されている方法です[{x]}x
。高速で、ネストされたブロックを適切に処理し、不適切に行を結合したり、インデントで混乱させたりしません。開始ブラケットの前に空白がある場合はx
、コマンドにa を追加して簡単に削除できます。[{xx]}x
他のバニラコマンド
繰り返しますが、私が考えることができる最も適切なコマンドは、@ Gillesの回答の1つ、[{x]}x
または[{xx]}x
ですが、このバグに照らして特に2つの選択肢があります。
キャラクターごとにヤンク
このバグは、文字ごとの選択よりも視覚的に配置された行ごとのレジスタでのみ発生し、内部のブロックヤンクでは線ごとであることが偶然に過ぎないため、代わりに文字ごとにヤンクすることを選択できます。簡単な方法の1つは、内部ブロックをヤンクする前に視覚的に選択し、視覚的な選択が文字どおりであることを確認することです(つまり、を使用しv
ないV
)vi{yva{p
。これは、現在の操作方法とよく似ているため、最も簡単な方法です。
ビジュアルプットを使用しない
変更や削除などの他のコマンドは、このバグの影響を受けません。以前と同じようにヤンクできますが、ブロックをブラックホールレジスタに:help quote_
削除して()配置するか、ブロックを削除して0レジスタから配置します(:help quote0
):yi{"_da{p
またはyi{da{"0p
一般性
最後に、@ Gillesの回答に似た方法があります。ブロックの先頭に移動し、文字を削除し、ブロックの最後に移動し、文字を削除しますが、より一般的な方法があります。これらを使用する唯一の理由は、削除しようとしている「ブロック」が偏心しており[{
、波括弧で区切られたブロックのように機能するモーションが関連付けられていない場合です。vim-surroundプラグインはこれらの偏心ブロックをうまく処理できる可能性がありますが、2つの基本的な方法があります
- 偏心ブロックを視覚的に選択し、視覚モードを終了します。カーソルは選択範囲の最後の文字にあります。それを削除してから、最後の選択(
:help `<
)の先頭に移動し、文字を削除します。va{<Esc>x`<x
- 偏心ブロックの先頭を後方に検索して文字を削除し、次に、偏心ブロックの末尾を前方に検索して文字を削除します。
?{<CR>x/}<CR>x
これは、ネストされたブロックではうまく機能しない可能性があります。
文字カウント
+----+------------------------+----------------------------+------------+
| | method | command | characters |
+----+------------------------+----------------------------+------------+
| 1. | vim-surround | ds{ | 3 |
| 2. | @Gilles answer | [{x]}x | 6 |
| 3. | Characterwise yank | vi{yva{p | 8 |
| 4. | Delete, not visual put | yi{"_da{p or yi{da{"0p | 9 |
| 5. | Visual mark | va{<Esc>x`<x | 8 |
| 6. | Search | ?{<CR>x/}<CR>x | 8 |
+----+------------------------+----------------------------+------------+
return -1;
。また、キーの各シーケンスを実行する前にカーソルを置いた場所を正確に教えてください。