提示

Nvim 的 :help 頁面,是使用 tree-sitter-vimdoc 解析器,從 原始碼 產生而來。


使用 Vim 的提示和想法
這些只是我們認為對許多使用者有幫助的一些提示。您可以在 wiki 上找到更多提示。網址可以在 https://www.vim.org 上找到
別忘了瀏覽使用者手冊,它也包含許多有用的提示 usr_toc.txt

編輯 C 程式 C-editing

Vim 中有相當多的功能可以幫助您編輯 C 程式檔案。以下是一個包含跳轉標籤的概述
usr_29.txt 使用者手冊中關於程式碼移動的章節。usr_30.txt 使用者手冊中關於編輯程式碼的章節。C-indenting 在輸入文字時自動設定行的縮排。= 重新縮排幾行。format-comments 格式化註解。
:checkpath 顯示所有遞迴包含的檔案。[i 在目前和包含的檔案中搜尋游標下的識別符號。[_CTRL-I 跳轉到 "[i" 的匹配項。[I 列出目前和包含的檔案中,游標下識別符號匹配的所有行。[d 在目前和包含的檔案中搜尋游標下的定義。
CTRL-] 跳轉到游標下的標籤 (例如,函式的定義)。CTRL-T 跳回執行 CTRL-] 命令之前的位置。:tselect 從匹配標籤列表中選取一個標籤。
gd 跳到游標下區域變數的宣告。gD 跳到游標下全域變數的宣告。
gf 跳到游標下的檔案名稱。
% 跳到匹配的 (), {}, [], /* */, #if, #else, #endif。[/ 跳到上一個註解的開頭。]/ 跳到下一個註解的結尾。[# 跳回未封閉的 #if, #ifdef 或 #else。]# 跳到未封閉的 #else 或 #endif。[( 跳回未封閉的 '('。]) 跳到未封閉的 ')'。[{ 跳回未封閉的 '{'。]} 跳到未封閉的 '}'
v_ab 選取從 "[(" 到 "])" 的「一個區塊」,包含大括號。v_ib 選取從 "[(" 到 "])" 的「內部區塊」。v_aB 選取從 [{]} 的「一個區塊」,包含中括號。v_iB 選取從 [{]} 的「內部區塊」。

尋找識別符號的使用位置 ident-search

您可能已經知道可以使用 tags 跳到函式或變數定義的位置。但有時您希望跳到函式或變數被使用的所有位置。這可以透過兩種方式實現:1. 使用 :grep 命令。這應該在大多數 Unix 系統上運作,但速度可能很慢(它會讀取所有檔案)並且只會在一個目錄中搜尋。2. 使用 ID 工具。這速度很快,並且可以在多個目錄中運作。它使用資料庫來儲存位置。您需要一些額外的程式才能使其運作。而且您需要保持資料庫為最新狀態。
使用 GNU id-tools
您需要什麼
安裝 GNU id-tools (需要 mkid 來建立 ID,而 lid 則需要使用巨集)。
目前目錄中一個名為「ID」的識別符號資料庫檔案。您可以使用 shell 命令「mkid file1 file2 ..」建立它。
將此放在您的 init.vim
map _u :call ID_search()<Bar>execute "/\\<" .. g:word .. "\\>"<CR>
map _n :n<Bar>execute "/\\<" .. g:word .. "\\>"<CR>
function! ID_search()
  let g:word = expand("<cword>")
  let x = system("lid --key=none " .. g:word)
  let x = substitute(x, "\n", " ", "g")
  execute "next " .. x
endfun
若要使用它,請將游標放在一個單字上,輸入 "_u",Vim 將載入包含該單字的檔案。使用 "n" 在同一個檔案中搜尋該單字的下一個出現位置。使用 "_n" 跳到下一個檔案。
這已在 id-utils-3.2 (這是您最近的 gnu-ftp-mirror 上 id-tools 封存檔案的名稱) 中測試過。
[這個想法來自 Andreas Kutschera]

在插入模式中捲動 scroll-insert

如果您處於插入模式,並且想要查看螢幕外顯示的內容,您可以使用 CTRL-X CTRL-ECTRL-X CTRL-Y 來捲動螢幕。i_CTRL-X_CTRL-E
為了使此操作更容易,您可以使用以下映射
:inoremap <C-E> <C-X><C-E>
:inoremap <C-Y> <C-X><C-Y>
然後您將失去從游標上方/下方複製文字的能力 i_CTRL-E
也請考慮將 'scrolloff' 設定為較大的值,以便您始終可以看到游標周圍的一些上下文。如果 'scrolloff' 大於視窗高度的一半,則游標將始終位於中間,並且在游標向上/向下移動時會捲動文字。

平滑捲動 scroll-smooth

如果您希望捲動更平滑一些,您可以使用以下映射
:map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y>
:map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E>

更正常見的輸入錯誤 type-mistakes

當您不斷以錯誤的方式輸入一些單字時,請建立縮寫來更正它們。例如
:ab teh the
:ab fro for

計算單字、行數等。 count-items

若要計算目前緩衝區中任何模式出現的次數,請使用 substitute 命令並新增 'n' 旗標以避免替代。報告的替代次數就是項目數。範例
:%s/./&/gn                characters
:%s/\i\+/&/gn                words
:%s/^//n                lines
:%s/the/&/gn                "the" anywhere
:%s/\<the\>/&/gn        "the" as a word
您可能想要重設 'hlsearch' 或執行 ":nohlsearch"。如果沒有匹配項時不希望產生錯誤,請新增 'e' 旗標。
另一種替代方法是在視覺模式中使用 v_g_CTRL-G
如果要在多個檔案中尋找匹配項,請使用 :vimgrep
計算位元組數
如果要計算位元組數,您可以使用此方法
以視覺方式選取字元(也可以選取區塊) 使用 "y" 複製字元 使用 strlen() 函式
:echo strlen(@")
換行符號計為一個位元組。

還原游標位置 restore-position

有時您想要編寫一個映射,該映射可以在檔案中的某個位置進行變更並還原游標位置,而不會捲動文字。例如,變更檔案中的日期標記
:map <F2> msHmtgg/Last [cC]hange:\s*/e+1<CR>"_D"=strftime("%Y %b %d")<CR>p'tzt`s
分解儲存位置:ms 將游標位置儲存在 's' 標記中 H 跳到視窗中的第一行 mt 將此位置儲存在 't' 標記中
分解還原位置:'t 跳到先前位於視窗頂部的行 zt 捲動以將此行移動到視窗頂部 s 跳到游標的原始位置
對於更進階的用法,請參閱 winsaveview()winrestview()

重新命名檔案 rename-files

假設我有一個目錄,其中包含以下檔案 (隨機選取的目錄 :-)
buffer.c charset.c digraph.c

...

我想將 *.c 重新命名為 *.bla。我會這樣做
$ vim
:r !ls *.c
:%s/\(.*\).c/mv & \1.bla
:w !sh
:q!

在多個檔案中變更名稱 change-name

使用指令碼檔案在多個檔案中變更名稱的範例
建立一個名為 "subs.vim" 的檔案,其中包含 substitute 命令和 :update 命令
:%s/Jones/Smith/g
:%s/Allen/Peter/g
:update
在您要變更的所有檔案上執行 Vim,並為每個參數來源指令碼
vim *.let
argdo source subs.vim
請參閱 :argdo

加速外部命令 speed-up

在某些情況下,執行外部命令可能會非常慢。這也可能會減慢 Unix 上的萬用字元展開速度。以下是一些提高速度的建議。
如果您的 .cshrc (或其他檔案,具體取決於所使用的 shell) 非常長,您應該將其分成用於互動式使用的區段和用於非互動式使用的區段(通常稱為次要 shell)。當您從 Vim 執行命令(如 ":!ls")時,您不需要互動式內容(例如,設定提示)。將不需要的內容放在這些行之後
if ($?prompt == 0) then
        exit 0
endif
另一種方法是在 'shell' 選項中包含 "-f" 旗標,例如
:set shell=csh\ -f
(需要反斜線才能在選項中包含空格)。這將使 csh 完全跳過使用 .cshrc 檔案。但這可能會導致某些東西停止運作。

有用的映射 useful-mappings

以下是一些人們喜歡使用的映射。
map-backtick
:map ' `
使單引號的運作方式像反引號。將游標放在標記的欄位上,而不是跳到該行的第一個非空白字元。
emacs-keys
用於在命令列上進行 Emacs 式編輯
" start of line
:cnoremap <C-A>                <Home>
" back one character
:cnoremap <C-B>                <Left>
" delete character under cursor
:cnoremap <C-D>                <Del>
" end of line
:cnoremap <C-E>                <End>
" forward one character
:cnoremap <C-F>                <Right>
" recall newer command-line
:cnoremap <C-N>                <Down>
" recall previous (older) command-line
:cnoremap <C-P>                <Up>
" back one word
:cnoremap <Esc><C-B>        <S-Left>
" forward one word
:cnoremap <Esc><C-F>        <S-Right>
format-bullet-list
此映射將格式化任何項目符號清單。它要求每個清單項目上方和下方都有一個空行。使用運算式命令來註解映射的各個部分。
:let m =     ":map _f  :set ai<CR>"   " need 'autoindent' set
:let m ..= "{O<Esc>"                      " add empty line above item
:let m ..= "}{)^W"                      " move to text after bullet
:let m ..= "i     <CR>     <Esc>"     " add space for indent
:let m ..= "gq}"                      " format text after the bullet
:let m ..= "{dd"                      " remove the empty line
:let m ..= "5lDJ"                      " put text after bullet
:execute m                              |" define the mapping
(<> 符號 <>。請注意,這都是照字面輸入。^W 是 "^" "W",而不是

CTRL-W。)

請注意,最後一個註解以 |" 開頭,因為 ":execute" 命令不直接接受註解。
您還需要將 'textwidth' 設定為非零值,例如,
:set tw=70
一個功能大致相同的映射,但會從第一行取得列表的縮排。(注意:此映射是一行很長且有很多空格的單行)
:map _f :set ai<CR>}{a                                                          <Esc>WWmmkD`mi<CR><Esc>kkddpJgq}'mJO<Esc>j
摺疊
這兩個映射會將一連串空白行 (;b) 或空行 (;n) 縮減為單一行
:map ;b   GoZ<Esc>:g/^$/.,/./-j<CR>Gdd
:map ;n   GoZ<Esc>:g/^[ <Tab>]*$/.,/[^ <Tab>]/-j<CR>Gdd

壓縮說明檔案 gzip-helpfile

對於那些磁碟空間非常有限的人來說,您可以壓縮說明檔案,並且仍然可以使用 Vim 來檢視它們。這會讓存取說明檔案的速度稍微變慢,並需要 "gzip" 程式。
(1) 壓縮所有說明檔案: "gzip doc/*.txt"。
(2) 編輯 "doc/tags" 並將 ".txt" 變更為 ".txt.gz"
:%s=\(\t.*\.txt\)\t=\1.gz\t=
(3) 將此行加入您的 vimrc
set helpfile={dirname}/help.txt.gz
其中 {dirname} 是說明檔案所在的目錄。 gzip 外掛程式會負責解壓縮檔案。您必須確定 $VIMRUNTIME 設定為其他 Vim 檔案所在的位置,當它們與壓縮的 "doc" 目錄不在相同位置時。請參閱 $VIMRUNTIME

十六進位編輯 hex-editing using-xxd

請參閱使用者手冊的 23.3 節。
如果某人對於二進位檔案使用特定的副檔名(例如 exe、bin 等),您可能會發現使用以下用於 init.vim 的 autocmds 自動化該過程很有幫助。將該 "*.bin" 變更為您發現自己想要編輯的任何逗號分隔的副檔名清單
" vim -b : edit binary using xxd-format!
augroup Binary
  autocmd!
  autocmd BufReadPre  *.bin set binary
  autocmd BufReadPost *.bin
    \ if &binary
    \ |   execute "silent %!xxd -c 32"
    \ |   set filetype=xxd
    \ |   redraw
    \ | endif
  autocmd BufWritePre *.bin
    \ if &binary
    \ |   let s:view = winsaveview()
    \ |   execute "silent %!xxd -r -c 32"
    \ | endif
  autocmd BufWritePost *.bin
    \ if &binary
    \ |   execute "silent %!xxd -c 32"
    \ |   set nomodified
    \ |   call winrestview(s:view)
    \ |   redraw
    \ | endif
augroup END

在 autocommand 中使用 <> 符號 autocmd-<>

<> 符號在 :autocmd 的參數中無法識別。為了避免使用特殊字元,您可以使用自我銷毀的映射來取得 <> 符號,然後從 autocmd 呼叫該映射。範例
map-self-destroy
" This is for automatically adding the name of the file to the menu list.
" It uses a self-destroying mapping!
" 1. use a line in the buffer to convert the 'dots' in the file name to \.
" 2. store that in register '"'
" 3. add that name to the Buffers menu list
" WARNING: this does have some side effects, like overwriting the
" current register contents and removing any mapping for the "i" command.
"
autocmd BufNewFile,BufReadPre * nmap i :nunmap i<CR>O<C-R>%<Esc>:.g/\./s/\./\\./g<CR>0"9y$u:menu Buffers.<C-R>9 :buffer <C-R>%<C-V><CR><CR>
autocmd BufNewFile,BufReadPre * normal i
另一種方法,可能更好,是使用 ":execute" 命令。在字串中,您可以使用 <> 符號,方法是在其前面加上反斜線。別忘了將現有的反斜線數量加倍,並在 '"' 之前加上反斜線。
autocmd BufNewFile,BufReadPre * exe "normal O\<C-R>%\<Esc>:.g/\\./s/\\./\\\\./g\<CR>0\"9y$u:menu Buffers.\<C-R>9 :buffer \<C-R>%\<C-V>\<CR>\<CR>"
對於真正的緩衝區選單,應該使用使用者函數(請參閱 :function),但是這樣就不會使用 <> 符號,這就失去了在此處將其作為範例的意義。

醒目提示匹配的括號 match-parens

此範例顯示了一些進階技巧的使用
使用 CursorMoved autocommand 事件
使用 searchpairpos() 來尋找匹配的括號
使用 synID() 來偵測游標是否在字串或註解中
使用 :match 來醒目提示某個東西
使用 pattern 來匹配檔案中的特定位置。
這應該放在 Vim 腳本檔案中,因為它會使用腳本區域變數。它會跳過字串或註解中的匹配,除非游標從字串或註解開始。這需要語法醒目提示。
matchparen 外掛程式中使用了稍微更進階的版本。
let s:paren_hl_on = 0
function s:Highlight_Matching_Paren()
  if s:paren_hl_on
    match none
    let s:paren_hl_on = 0
  endif
  let c_lnum = line('.')
  let c_col = col('.')
  let c = getline(c_lnum)[c_col - 1]
  let plist = split(&matchpairs, ':\|,')
  let i = index(plist, c)
  if i < 0
    return
  endif
  if i % 2 == 0
    let s_flags = 'nW'
    let c2 = plist[i + 1]
  else
    let s_flags = 'nbW'
    let c2 = c
    let c = plist[i - 1]
  endif
  if c == '['
    let c = '\['
    let c2 = '\]'
  endif
  let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' ..
        \ '=~?        "string\\|comment"'
  execute 'if' s_skip '| let s_skip = 0 | endif'
  let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip)
  if m_lnum > 0 && m_lnum >= line('w0') && m_lnum <= line('w$')
    exe 'match Search /\(\%' .. c_lnum .. 'l\%' .. c_col ..
          \ 'c\)\|\(\%' .. m_lnum .. 'l\%' .. m_col .. 'c\)/'
    let s:paren_hl_on = 1
  endif
endfunction
autocmd CursorMoved,CursorMovedI * call s:Highlight_Matching_Paren()
autocmd InsertEnter * match none

在目前視窗中開啟說明 help-curwin

預設情況下,說明會顯示在分割視窗中。如果您偏好在目前視窗中開啟,請嘗試此自訂的 :HelpCurwin 命令
command -bar -nargs=? -complete=help HelpCurwin execute s:HelpCurwin(<q-args>)
let s:did_open_help = v:false
function s:HelpCurwin(subject) abort
  let mods = 'silent noautocmd keepalt'
  if !s:did_open_help
    execute mods .. ' help'
    execute mods .. ' helpclose'
    let s:did_open_help = v:true
  endif
  if !empty(getcompletion(a:subject, 'help'))
    execute mods .. ' edit ' .. &helpfile
    set buftype=help
  endif
  return 'help ' .. a:subject
endfunction
主要
命令索引
快速參考