ブレースを簡単に削除する方法


8

友人の1人から、下の方法で中かっこを削除できると言われました。

削除する中括弧のペアの内側にカーソルを置きます。

y i {中括弧でテキストをヤンクし、v a {貼り付け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];
)

ビジュアルモードで選択した領域は良いようですが、括弧が下がるのはなぜですか?


あなたが投稿したコードサンプルを確信していますか?どうしてそうなるのかわかりませんreturn -1;。また、キーの各シーケンスを実行する前にカーソルを置いた場所を正確に教えてください。
statox

@statox申し訳ありません...後者のブロックを修正し、カーソルを置いた場所に関する説明を追加しました。あなたの推薦をありがとう:-)
MrDwZ 2015年

これを複製することはできません。yi{中括弧の間のヤンクとvap視覚的に段落(この場合はテキスト全体)を選択しますが、これによってテキストがどのように変更されるかはわかりません。あなたは確かにあなたがやっていないしていますかyi{+ va{+ p
jjaderberg 2015年

2
クリーンセッション(vimrcなし)でテキストにyi{+ va{+ pを試したところ-u NONE、結果が再現されました。例えばp、キャラクターとして動いているPにもかかわらずi{、なぜ、そして両方がこの結果をもたらすのか、私にはわかりませんa{。これは、a)テクニックが機能する例のテキストを提供し、b)テクニックのどこで「変更」が発生するかを確認できる場合に役立ちます。@Benは彼の答え(私はそのプラグインを使用しています)に適切な回避策を示していますが、これが最初に発生する理由を理解してもかまいません。
jjaderberg、2015年

私は@jjaderbergに似ています。あなたが説明した動作を再現できません。彼のコメントで尋ねられた詳細を与えることは本当に良い考えでしょう。
statox

回答:


6

「サラウンド」プラグインをインストールします。その後、あなたはただ行うことができますd s B

プロジェクトページから:

Surround.vimは、すべて「周囲」に関するものです。括弧、角括弧、引用符、XMLタグなどです。プラグインは、そのような環境をペアで簡単に削除、変更、追加するためのマッピングを提供します。

コマンドのds後に任意のテキストオブジェクト(Bこの場合は、aBまたはiBテキストオブジェクトの「ブロック」の場合)が続くと、テキストオブジェクトを定義する周囲の文字が削除されます。したがって、d s B あなたのケースではあなたが望むものを達成します。

他のコマンドは、c s B bあなたがしたい場合、変更周囲{...}(...)、またはy s {いずれかのカーソル移動やテキストオブジェクトを} B 取り囲む追加するために、{...}カーソルで選択したテキストに。

詳細については、プラグインのページとドキュメントをご覧ください。


これは良い回避策です。このプラグインがどのように機能するか、および特定のマッピングがタスクを実行する理由を説明する1つまたは2つの文を追加することを検討しますか?
jjaderberg

プラグインなしでこれらのブレースを削除するエレガントな方法はありますか?:(
MrDwZ 2015年

多分。しかし、サラウンドは本当に軽量で、「必須」のプラグインの1つです。だから、それをインストールしてもいいかもしれません...
Ben

6

概要

これはバグであり、パッチ(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を実行して (avim -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、周囲のブラケットを削除するには、あなたが見て可能性があり、より強力な(特にビジュアルモードで)置くためReplaceWithRegisterUnconditionalPaste

最良の方法は、@ Gillesの回答で示されている方法です[{x]}x。高速で、ネストされたブロックを適切に処理し、不適切に行を結合したり、インデントで混乱させたりしません。開始ブラケットの前に空白がある場合はx、コマンドにa を追加して簡単に削除できます。[{xx]}x

他のバニラコマンド

繰り返しますが、私が考えることができる最も適切なコマンドは、@ Gillesの回答の1つ、[{x]}xまたは[{xx]}xですが、このバグに照らして特に2つの選択肢があります。

キャラクターごとにヤンク

このバグは、文字ごとの選択よりも視覚的に配置された行ごとのレジスタでのみ発生し、内部のブロックヤンクでは線ごとであることが偶然に過ぎないため、代わりに文字ごとにヤンクすることを選択できます。簡単な方法の1つは、内部ブロックをヤンクする前に視覚的に選択し、視覚的な選択が文字どおりであることを確認することです(つまり、を使用しvないVvi{yva{p。これは、現在の操作方法とよく似ているため、最も簡単な方法です。

ビジュアルプットを使用しない

変更や削除などの他のコマンドは、このバグの影響を受けません。以前と同じようにヤンクできますが、ブロックをブラックホールレジスタに:help quote_削除して()配置するか、ブロックを削除して0レジスタから配置します(:help quote0):yi{"_da{pまたはyi{da{"0p

一般性

最後に、@ Gillesの回答に似た方法があります。ブロックの先頭に移動し、文字を削除し、ブロックの最後に移動し、文字を削除しますが、より一般的な方法があります。これらを使用する唯一の理由は、削除しようとしている「ブロック」が偏心しており[{、波括弧で区切られたブロックのように機能するモーションが関連付けられていない場合です。vim-surroundプラグインはこれらの偏心ブロックをうまく処理できる可能性がありますが、2つの基本的な方法があります

  1. 偏心ブロックを視覚的に選択し、視覚モードを終了します。カーソルは選択範囲の最後の文字にあります。それを削除してから、最後の選択(:help `<)の先頭に移動し、文字を削除します。va{<Esc>x`<x
  2. 偏心ブロックの先頭を後方に検索して文字を削除し、次に、偏心ブロックの末尾を前方に検索して文字を削除します。?{<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 |
+----+------------------------+----------------------------+------------+

5

カーソルを元の位置に戻すよう求めているわけではないので[{x]}x、仕事をします。長さは6文字で、2回押すだけですShiftが、原則は簡単なので覚えやすいです。

元の位置に戻したい場合は、 [{x``]}x``

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.