常見文本編輯器都會提供剪切闆來支援複制粘貼,Vim也不例外。 不同的是Vim提供了10類共48個寄存器,提供無與倫比的寄存功能。 最常用的
y
操作将會拷貝到預設的匿名寄存器中,我們也可以指定具體拷貝到哪個寄存器中。
一般來講,可以用
"{register}y
來拷貝到
{register}
中, 用
"{register}p
來粘貼
{register}
中的内容。例如:
"ayy
可以拷貝目前行到寄存器
a
中,而
"ap
則可以粘貼寄存器
a
中的内容。
注:Vim的拷貝與大家預期的方式可能略有不同。拷貝指令不是大家料想的c。因為c表示“修改”,已經被占用了。Vim用拉取(yank)來表示拷貝,簡寫為y。
- y: 拷貝選中内容
- yy: 拷貝目前行
除了
a-z
26個命名寄存器,Vim還提供了很多特殊寄存器。合理地使用可以極大地提高效率。例如:
-
可以粘貼剪切闆的内容,"+p
-
可以粘貼上一個Vim指令(比如你剛剛費力拼寫的正規表達式),":p
-
可以粘貼上一次搜尋關鍵詞(你猜的沒錯,正是normal模式下的"/p
搜尋指令)。/foo
在Vim中可通過
:reg
來檢視每個寄存器目前的值。
寄存器分類
Vim提供了10類寄存器,可在Vim中通過
:help registers
檢視幫助。
- 匿名寄存器
""
- 編号寄存器
到"0
"9
- 小删除寄存器
"-
- 26個命名寄存器
到"a
"z
- 3個隻讀寄存器
,":
,".
"%
- Buffer交替檔案寄存器
"#
- 表達式寄存器
"=
- 選區和拖放寄存器
,"*
,"+
"~
- 黑洞寄存器
"_
- 搜尋模式寄存器
"/
1. 匿名寄存器
使用
d
,
c
,
s
,
x
等會删除字元的指令時,被删除字元會進入匿名寄存器
""
。 你可以認為
""
寄存器是一個指針,指向剛才被存到的寄存器。
在如何用Vim搭建IDE?一文中提到,Mac下可通過下列設定來讓Vim共享系統剪切闆, 就是這個原理:所有删除和拷貝操作預設都會到匿名寄存器。
set clipboard=unnamed
使用
y
指令未指定寄存器會存到
"0
寄存器中,同時
""
會與該寄存器保有同樣的值。 這意味着你使用
p
和
"p
總會得到同樣的結果。
2. 編号寄存器
編号寄存器從
"0
到
"9
共10個,其中
"0
儲存着拷貝來的字元串,
"1
到
"9
儲存着删除掉的字元串。 删除操作符包括
s
,
c
,
d
,
x
。 删除掉的字元串會被存到
"1
中,上次删除的則會被存到
"2
中。以此類推,Vim會儲存你最近的9次删除。
- 隻有整行整行的删除,和通過段落級别的移動指令(包括
) 的删除才會被放到%,(,),/,`,?,n,N,{,}
中。"1
- 當使用者指定拷貝操作的寄存器時(如
),"ap
不會被寫入;但删除操作一定會被寫入到"0
中。"1
寄存器很有用,比如我們copy了一段文本然後用它替換另一段文本。 這時預設寄存器
"0
中的值就變成了被替換文本,如果還需要用copy的文本繼續替換的話就需要
""
了。
"0p
3. 小删除寄存器
不足一行的小删除則會被放到小删除寄存器中(
"-
),起作用的删除操作符也包括
s
,
c
,
d
,
x
。 例如:
dw # 删除一個詞
d9l # 删除9個字元
cb # 向前更改一個詞
與
"0
寄存器類似,當使用者指定寄存器并進行删除時,
"-
不會被寫入。
4. 命名寄存器
命名寄存器有
"a
到
"z
共26個,這些寄存器隻有當我們指定時才會被使用。 其實我們在錄制宏時,所有鍵盤操作會以字元串的形式存到寄存器中。 例如錄制一個宏存到
"a
寄存器中,内容為更改目前行
cc
,改為
foo
字元串:
qaccfoo
然後執行
:reg
來檢視寄存器,可以發現
a
寄存器的值是
ccfoo
。
小技巧:當使用小寫字母進行操作時會覆寫目前寄存器内容,當使用大寫字母進行操作時,會追加目前寄存器内容。
5. 隻讀寄存器
隻讀寄存器共3個,它們的值是由Vim提供的,不允許改變:
-
:上次insert模式中插入的字元串。還記得嗎?".
指令可以重複上次操作,而.
存儲了上次插入。".
-
:目前檔案名,不是全路徑,也不是純檔案名,而是從目前Vim的工作目錄到該檔案的路徑。例如此時Harttle的Vim中,"%
的結果為"%p
。_drafts/vim-registers.md
-
:上次指令模式下鍵入的指令。正如":
可以執行@a
寄存器中的宏一樣,"a
可以執行上次指令。@:
6. 交替檔案寄存器
交替檔案寄存器
"#
存儲着目前Vim視窗(Window)的交替檔案。交替檔案(alternate file)是指 Buffer中的上一個檔案,可通過
Ctrl+^
來切換交替檔案與目前檔案。
Window和Buffer有什麼差別?參見Vim 多檔案編輯:視窗一文。
7. 表達式寄存器
表達式寄存器
"=
主要用于計算Vim腳本的傳回值,并插入到文本中。 當我們鍵入
"=
後光标會移動到指令行,此時我們可以輸入任何Vim腳本的表達式。 例如
3+2
,按下回車并且
p
則會得到
5
。
這在我們調試Vim腳本時非常有用,比如調用一個函數看它是否有正确的傳回值。
8. 選擇和拖放寄存器
選擇和拖放寄存器包括
"*
,
"+
, 和
"~
,這三個寄存器的行為是和GUI相關的。
"*
和
"+
在Mac和Windows中,都是指系統剪貼闆(clipboard),例如
"*yy
即可複制目前行到剪貼闆。 以供其他程式中粘貼。其他程式中複制的内容也會被存儲到這兩個寄存器中。 在X11系統中(絕大多數帶有桌面環境的Linux發行版),二者是有差別的:
-
指X11中的PRIMARY選區,即滑鼠選中區域。在桌面系統中可按滑鼠中鍵粘貼。(滑鼠中鍵即滑鼠中間的滑輪)"*
-
指X11中的CLIPBOARD選區,即系統剪切闆。在桌面系統中可按Ctrl+V粘貼。"+
上文所述的Mac下會使得系統剪切闆寄存器
set clipboard=unnamed
和Vim預設的匿名寄存器
"*
始終保有同樣的值,即Vim和系統共用剪切闆。
""
有文本拖拽到Vim時,被拖拽的文本被存儲在
"~
中。Vim預設的行為是将
"~
中内容插入到光标所在位置。 當然你可以給
<DROP>
做鍵盤映射。
9. 黑洞寄存器
黑洞寄存器
"_
,所有删除或拷貝到黑洞寄存器的文本将會消失。 這是為了在删除文本的同時不影響任何寄存器的值,
"_
通常用于Vim腳本中。
10. 搜尋寄存器
搜尋寄存器
"/
用于存儲上一次搜尋的關鍵詞。Vim中如何進行搜尋呢? 在normal模式下按下
/
即進入search模式,輸入關鍵字并按下回車即可。
該寄存器是可寫的,例如
:let @/ = "harttle"
将會把
"harttle"
寫入該寄存器。 下次搜尋時不輸入搜尋詞直接回車便會搜尋
"harttle"
。
指令行模式拷貝
值得一提的時,任何寄存器中的值都是可以拷貝到指令模式下的。
比如對于寄存器
"a
中的值,在normal模式下可以通過
"ap
來粘貼;在command-line模式下通過
<Ctrl-R>a
來粘貼。這一操作存在風險,因為寄存器中的值可能是從網頁中拷貝來的。
如果寄存器中的字元串存在
<Esc>
字元或
<CR>
字元,則會時Vim回到normal模式, 并繼續執行寄存器中的指令。為了防範剪切闆劫持,可以添加下列的Vim配置:
inoremap <C-r>+ <C-g>u<C-\><C-o>"+gP
該指令的解釋請移步:http://vim.wikia.com/wiki/Pasting_registers
擴充閱讀
- 剪切闆與X11選區:http://stackoverflow.com/questions/11489428/how-to-make-vim-paste-from-and-copy-to-systems-clipboard
- Vikia-Pasting Registers: http://vim.wikia.com/wiki/Pasting_registers
- Vim Help:
,:help registers
,:help quotestar
:help quoteplus
本文采用 知識共享署名 4.0 國際許可協定(CC-BY 4.0)進行許可。轉載請注明來源: https://harttle.land/2016/07/25/vim-registers.html 歡迎對文中引用進行考證,歡迎指出任何不準确和模糊之處。可以在下面評論區評論,也可以郵件至 [email protected]。