2012-06-13 35 views
9

是否可以在VIM中重複使用ex命令的範圍?重複使用VIM中ex命令的前一個範圍

:4,10w foo/bar.txt 

但我真正想要做的是移動線:

舉個例子,我可以使用下面的命令寫從我目前的文件(複印件)線4至10到一個新文件一個新文件。我可以這樣做:

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

但是有兩次輸入4,10都有點煩人。

所以我有兩個問題:

  1. 一般,有沒有引用ex命令以前使用的範圍呢?
  2. 特別是,如果沒有辦法做(1),是否有更簡單的方法將一行文件中的多行剪切並粘貼到新文件中。

回答

1

通常,我所做的是從一個文件中刪除行,切換到另一個文件並粘貼。

此外,我一般使用標記。我輸入mb來標記開始行,而不是輸入實際的數字,然後轉到結束行並點擊d'b刪除回到標記爲b的行。但是你可以用mb標誌着一個開始行,me標記的端線,然後運行一個ex命令:

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

當然你也可以通過z爲您的標記使用來自a的信;我通常使用be,但你可以使用你喜歡的。

我怎麼會動線:

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中有效;只是你不需要它。

4

我不知道答案(1),但回答(2),有很多不同的方法來做到這一點,不需要手動重新選擇線條。在可視化模式,這將工作:

4GV10G 
:w foo/bar.txt 
gvd 

因爲GV重新選擇以前的選擇,這幾乎是你想要的東西,不使用Ex範圍。

但是你可以只是把問題在它的頭,並嘗試:

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

切割,然後粘貼到一個新的文件,然後將其關閉。

0

您可以先執行刪除操作,然後打開一個新標籤並粘貼內容 - 如:4,10d,然後:tabe foo/bar.txt,然後是p ......聽起來好嗎?

3

除了使用Vim的歷史(光標向上q:)等,只是範圍保持刪除以前的命令,沒有辦法再使用過去的範圍內,沒有神奇的變化。

如果我更常採用這種招行組合,我會爲它編寫自定義命令:

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

你只需要一次指定範圍,節省打字。

你也可以爲其他組合寫這樣的東西。主要的挑戰是指定所有的命令屬性(bang,range,completion),然後記住自定義命令名稱。

2

這是一個實現此目的的命令行映射。我已經將它綁定到了CTRL-G CTRL-U,因爲它執行了與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> 
1

你也可以做這樣的事情寫匿名寄存器的內容FILE2.TXT

:4,10d | :call writefile(split(@@, "\n", 1), 'file2.txt') 
5

我通常用貓做這樣的:

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

這工作,因爲你是通過貓管道線路,並用所得輸出,這是沒有什麼替代它們。當然,您可以通過執行>>代替>來追加到現有文件的末尾。

+0

這是一個有趣的方式來處理它!那種優雅。 – steveha