9

VIM で ex コマンドの範囲を再利用することは可能ですか?

例として、次のコマンドを使用して、現在のファイルの 4 行目から 10 行目を新しいファイルに書き込む (コピーする) ことができます。

:4,10w foo/bar.txt

しかし、私が本当にやりたいのは、行を新しいファイルに移動することです。私はこれを次のように行うことができます:

:4,10w foo/bar.txt
:4,10d

しかし、両方とも 4,10 と入力しなければならないのは少し面倒です。

だから私は2つの質問があります:

  1. 一般的に、以前に使用された範囲をexコマンドで参照する方法はありますか?
  2. 具体的には、(1) を実行する方法がない場合、1 つのファイルから複数の行を切り取り、新しいファイルに貼り付ける簡単な方法はありますか。
4

8 に答える 8

5

私は通常これを行うために猫を使用します:

:4,10!cat > foo/bar.txt

これは、猫を介してラインを配管し、結果の出力に置き換えるために機能しますが、これは何もありません。もちろん、>の代わりに>>を実行すると、既存のファイルの末尾に追加できます。

于 2012-06-13T17:54:22.887 に答える
4

(1) に対する答えはわかりませんが、(2) には、手動で行を再選択する必要のないさまざまな方法があります。ビジュアルモードでは、これは機能します:

4GV10G
:w foo/bar.txt
gvd

gv は前の選択範囲を再選択するためです。これは、元の範囲を使用せずに、ほとんどあなたが望むものです。

しかし、問題をひっくり返して、次のことを試すことができます。

:4,10d
:sp foo/bar.txt
pZZ

切り取り、新しいファイルに貼り付けてから閉じます。

于 2012-06-13T09:35:13.240 に答える
3

Vim 履歴 ( :Cursor Up, q:) を使用し、以前のコマンドを削除して範囲だけを保持する以外に、最後の範囲を再利用する方法はなく、魔法の変数もありません。

このムーブ ラインの組み合わせをもっと頻繁に使用する場合は、カスタム コマンドを作成します。

command! -bang -range -nargs=1 -complete=file MoveWrite <line1>,<line2>write<bang> <args> | <line1>,<line2>delete _

範囲を指定する必要があるのは 1 回だけで、入力を節約できます。

他の組み合わせについても、このように書くことができます。主な課題は、すべてのコマンド属性 (bang、range、complete) を指定することと、後でカスタム コマンド名を覚えることです。

于 2012-06-13T09:39:59.533 に答える
2

通常、私が行うことは、1 つのファイルから行を削除し、別のファイルに切り替えて貼り付けることです。

また、私は一般的にマークを使用します。実際の数字を入力する代わりに、 を押してmb開始行をマークし、次に終了行に移動して、 とd'bマークされた行まで削除しbます。ただし、 を使用mbして開始行meをマークし、終了行をマークしてから ex コマンドを実行できます。

:'b,'e w somefile.txt<Enter>

もちろん、 からaまでの任意の文字をzマークに使用できます。通常はbandeを使用しますが、お好みで使用してください。

行を移動する方法:

m'b
<navigate to end line>
d'b
:n somefile.txt<Enter>
p
Ctrl+^

Ctrl+^ は、現在開いているファイルから前に開いていたファイルに切り替えます。(必要に応じて、ペインを開いてペインを切り替えることもできます。ペインは通常の vi では機能しませんが、vim では機能します。)

上記は、autowriteオプションをオンに設定していることを前提としています。ではautowrite:nコマンドと Ctrl+^ はどちらも現在のファイルを書き込んでからファイルを切り替えるだけで、保存せずにファイルが変更されたと文句を言うのではありません。:n上記を実行して、または Ctrl+^を使用する前にファイルを明示的に書き込むこともできます。

ちなみに、私は Ctrl+^ を使いすぎて にマッピングしましKた。入力するのは簡単ですが、Ctrl + ^を入力できないダム端末を時々使用しなければならなかったとき、私はずっと前にその習慣を身につけました.

ちなみに、行を削除すると「名前のないバッファ」に入ります。vim では、ファイルを切り替えると名前のないバッファが保持されます。元の vi では、名前のないバッファはクリアされます。したがって、上記は古い vi では機能しません。名前付きバッファに削除してから、名前付きバッファから貼り付けることで機能させることができます。vi のどのバージョンでも動作します。

m'b
<navigate to end line>
"ad'b
:n somefile.txt<Enter>
"ap
Ctrl+^

上記は、 という名前のバッファに削除し、別のファイルにa貼り付けaます。もちろん、これはvimで機能します。それはあなたがそれを必要としないというだけです。

于 2012-06-13T09:32:59.113 に答える
2

これを実現するコマンドライン マッピングを次に示します。CTRL-U と同様のアクションを実行するため、CTRL-G CTRL-U にバインドしました。(ただし、もちろん変更できます!)

" c_CTRL-G_CTRL-U   Remove all characters between the cursor position and
"           the closest previous |:range| given to a command. When
"           directly after a range, remove it.
"           Useful to repeat a recalled command line with the same
"           range, but a different command.
let s:singleRangeExpr = '\%(\d\+\|[.$%]\|''\S\|\\[/?&]\|/[^/]*/\|?[^?]*?\)\%([+-]\d*\)\?'
let s:rangeExpr = s:singleRangeExpr.'\%([,;]'.s:singleRangeExpr.'\)\?'
let s:upToRangeExpr = '^\%(.*\\\@<!|\)\?\s*' . s:rangeExpr . '\ze\s*\h'
" Note: I didn't take over the handling of command prefixes (:verbose, :silent,
" etc.) to avoid making this overly complex.
function! s:RemoveAllButRange()
    let l:cmdlineBeforeCursor = strpart(getcmdline(), 0, getcmdpos() - 1)
    let l:cmdlineAfterCursor = strpart(getcmdline(), getcmdpos() - 1)

    let l:upToRange = matchstr(l:cmdlineBeforeCursor, s:upToRangeExpr)
    if empty(l:upToRange)
        return getcmdline()
    else
        call setcmdpos(strlen(l:upToRange) + 1)
        return l:upToRange . l:cmdlineAfterCursor
    endif
endfunction
cnoremap <C-g><C-u> <C-\>e(<SID>RemoveAllButRange())<CR>

プラグインとして

私のCmdlineSpecialEdits プラグインには、(他の多くのプラグインの中でも) このマッピングもあります。

于 2012-06-13T10:57:22.737 に答える
1

次のようにして、匿名レジスタの内容を file2.txt に書き込むこともできます。

 :4,10d | :call writefile(split(@@, "\n", 1), 'file2.txt')
于 2012-06-13T11:17:31.173 に答える
0

最初に削除を行ってから、新しいタブを開いて内容を貼り付けることができ:4,10dます。:tabe foo/bar.txtp

于 2012-06-13T09:36:46.023 に答える