效率至上-一文帶你真正走進vim

vim一直是程序員之間比較有爭議的一個話題。有人認爲她是編輯器之神,有人則認爲她古老過期,遠遠不如IDE,或是以當紅小生vscode爲表明的圖形化文本編輯器。不管愛恨,咱們的開發工做,大到遠程登陸服務器coding,修改config文件,小到git commit message,或多或少總要接觸她。git

爲何要寫這篇blog呢,是由於我發現各大平臺充斥的vim教程類blog其實很不友好,大多數是命令的堆砌,不多有對思想的解讀。由此形成的結果,不少工程師對vim老是敬畏三分,或者就算部分人可使用vim,也只是以本身的固有思惟,結合vim的命令操做,並無真正掌握vim的精髓。因此我嘗試用本身的方式,試圖幫助你們系統地創建起vim的知識系統。程序員

文章主要結構以下:shell

  • 首先介紹vim編輯器最簡單、基本的操做,讓你快速入門,在遇到vim時,能夠不至於驚慌,從容完成任務。若是想到某些操做,好比經常使用的複製、粘貼之類,能夠到第二部分查找對應高階操做,按部就班使用vim
  • 接下來,將會介紹vim一系列高級操做,將咱們的效率最大化。注:這部分信息量較大,建議您在閱讀部份內容後,快速瀏覽不熟悉的命令,作到心中有數;隨後可前進到第三部分;回過頭來,再按部就班,邊學邊練。
  • 最後,試圖講述vim思想的精髓,既讓咱們真正對vim的操做融會貫通,又讓咱們能夠在使用其餘IDE/編輯器時應用這些思想,甚至在咱們本身設計、實現功能、組件時,都能進行應用。這纔算真正掌握了神器vim

模式

vim有三個模式,分別爲普通(正常)模式、插入模式以及命令模式。vim

  • 普通模式:通常用於瀏覽文件,也包括一些複製、粘貼、除等操做。
  • 插入模式:主要用來輸入、修改、刪除字符,此時的操做,除了不能用鼠標外,與咱們平常在編輯器中操做無異。普通模式下,經過i等命令進入插入模式。
  • 命令模式:用以執行一些輸入並執行一些vim或插件提供的指令。在普通模式下經過輸入:後,能夠發現,屏幕的右下角會出現:,此時便進入了命令模式。本文中使用開頭的命令,即可視爲輸入:進入命令模式後,輸入後面的字符,執行命令。

不少人對於vim的第一點疑惑,便來源於此。咱們習慣了圖形化編輯器下,始終處於插入狀態。然而在vim中,大多數狀況下,咱們會處於正常模式。只有當須要輸入字符時,進入插入模式;當須要使用命令時,進入到命令模式。在插入和命令模式下,輸入Esc即可返回正常模式。一張圖歸納以下:服務器

image

注:後文講解,如無特殊說明,均爲普通模式下操做。編輯器

基本操做

若是不追求效率,只想完成修改文件的任務,並保存退出,只須要掌握如下三個命令:工具

  1. 移動:h j k l 最簡單的移動,至關於鍵盤上面的方向鍵,分別對應左下上右。
  2. 進入插入模式:i
  3. 保存退出:ZZ(注意區分大小寫)

流程以下:佈局

  1. 普通模式下,經過h j k l 移動到想要修改的位置
  2. 輸入i進入插入模式,此時經過輸入(字母、數字、符號),刪除(Backspace)等,完成基本修改操做
  3. Esc回到普通模式,ZZ,保存修改並退出。

進階:命令形式

普通模式下,vim的命令主要分爲如下三種:spa

  1. 動做,用以移動光標,或者定義操做的範圍;好比:插件

    1. h:定義操做範圍爲一格,單獨使用時,向左移動光標一格。
    2. w:定義操做範圍爲一個單詞,移動光標到下一個單詞首部。
  2. 操做,這種命令須要在後面接表示操做範圍的指令;

    1. d,刪除,後接表示一個單詞操做範圍的w,即dw時,表示刪除到當前詞尾。
    2. c,修改,後接表示一個單詞操做範圍的w,即cw時,表示修改當前單詞。(編輯器行爲表現爲,刪除到當前詞尾,同時進入插入模式)。
  3. 命令,直接執行的命令,其中一部分,在執行命令後,直接進入編輯模式;好比:

    1. D,刪除至行末。
    2. I,到行首進入插入模式。 咱們的使用方式主要也是三種:命令、動做、操做+動做。 此外,在動做類的命令前,加上number爲可選項,可實現重複n次的效果:
  4. [number] + h/j/k/l左/下/上/右移動number個字符。好比,'2j',向下移動光標2個字符。

  5. 依舊使用dw來舉例,d是刪除,w是單詞,dw表明刪除一個單詞,d2w表明刪除兩個單詞。後面的命令,大多均可應用此種形式組合使用,你們多注意,養成這種操做 + [次數] + 範圍的思惟模式,觸類旁通,即可發揮最大功效。

移動進階

單詞級別的移動

這裏有僅大小寫不一樣的兩組命令,兩組命令的功能,是相同的:跳轉光標到對應位置。可是對應的單位不一樣,分別爲wordstring。具體區別是:

  • string僅以空格分開;

  • word字母數字之外的字符分開。

    以這個字符串爲例:hello world-hehe111 abcde

  • word有5個,分別爲hello world, -, hehe111abcde

  • string有3個,分別爲hello world-hehe111abcde

兩組命令以下:(跳轉光標至)

  • w 下一個單詞開頭
  • e 當前或下一個單詞結尾
  • b 當前或上一個單詞開頭
  • ge 上一個單詞的結尾
  • W 下一個字符串的開頭
  • E 當前或下一個字符串結尾
  • B 當前或上一個字符串的開頭
  • GE 上一個字符串的結尾

舉個例子,當光標位於hehe111的第一個字符h時,先後的單詞/字符串信息以下:

前一個 當前 後一個
單詞 - hehe111 abcde
字符串 hello world-hehe111 abcde

那麼以上各個敲擊以上各個命令的結果,便一目瞭然(加粗字表示命令運行後光標位置):

image

句子,段落級別的移動

  • 0 移動到當前行行首

  • ^ 移動到當前行的第一個非空字符

  • $ 移動到當前行尾

  • ( 跳轉到當前或前一個句子的開頭

  • ) 跳轉到當前或下一個句子的結尾

  • { 跳轉到當前或前一個段落的開頭

  • } 跳轉到當前或下一個段落的結尾

  • 這裏段落很容易理解,是以空行分隔開的。句子麻煩些,是按照句號來算的。

  • 記得在這些命令前添加 d試一下效果吧,掌握操做+範圍這種命令形式吧。

頁面級別的移動

按行移動光標
  • gg 移動到文本第一行行首
  • G 移動到文本末行行首
  • [n] + %:按百分比近似定位到某行,該行位於整個文件的n%
  • [n] + gg/G 跳轉到第n行,經常使用。

要想用好上述幾個命令,有兩個簡單的建議:

  1. 結合命令:ctrl-g。該命令的做用是顯示當前行的位置信息(第幾行,相對整個文本行數的百分比)。
  2. 在命令模式下輸入如下命令,或在~/.vimrc中添加以下代碼片斷
set nu " 顯示行號
set cursorline " 高亮光標所在行</pre>
複製代碼
顯示頁面內移動光標
  • H:屏幕頂部行首
  • M:屏幕中央行首
  • L:屏幕底部行首
滾動與翻頁
  • ctrl-d/u:前進/後退半頁
  • ctrl-f/b:前進/後退整頁
  • ctrl+e:上滾一行
  • ctrl+y:下滾一行
  • zt:使光標所在位置移動到屏幕的頂部(全部內容作位移)
  • zz:使光標所在位置移動到屏幕的中央(全部內容作位移)
  • zb:使光標所在位置移動到屏幕的底部(全部內容作位移)

匹配

  • f+單個字符:在本行內向右移動到指定字符
  • F+單個字符:在本行內向左移動到指定字符
  • t+單個字符:在本行內向右移動到指定字符的前一個字符
  • T+單個字符:在本行內向左移動到指定字符的前一個字符
  • %: 在「( )」、「[ ]」、「{ }」類符號的首尾間切換
  • *#: 匹配光標當前所在的單詞,移動光標到下一個(或上一個)匹配單詞(*是下一個,#是上一個)。

Mark

  • m+[a~z] :在當前光標作標記,如ma
  • '+[mark]:光標返回指定標記所在的行,如'a,則光標返回到標記a所在行首
  • "`"+[mark]:光標返回指定標記
  • ctrl+o:跳轉回光標前一個位置
  • ctrl+i:跳轉回較新的光標位置
  • 建議結合命令模式下以下兩個命令,可得到更好體驗:
    • :marks:顯示所有mark
    • :delmarks [mark]:刪除指定mark

編輯進階

進入插入模式

在不一樣位置進入插入模式
  • i:在光標前插入字符
  • I:在行首插入字符
  • a:在光標後插入字符
  • A:在行尾插入字符
  • o:在光標下發插入空行
  • O:在光標上方插入空行
使用修改命令進入插入模式
  • c:修改,後面須要接範圍

  • c+w:刪除光標位置單詞,並進入插入模式

  • c+l / s:刪除光標位置字符,並進入插入模式

  • c+c / S:刪除光標所在行,並進入插入模式

  • c+$ / C:刪除光標位置到行尾的字符,並進入插入模式

  • r: 替換當前字符。

  • R:(進入replace模式)持續替換光標所在字符,直到使用ESC退出替換模式。

刪除

  • x: 刪除當前位置或下一個位置的字符。

  • d:刪除,屬於動做指令,後面須要加操做類指令。好比以下命令:

    • de:刪除到當前單詞結尾。
    • dw:刪除到下一個單詞開始。
    • 注意,此處與de的區別在於,dw會刪除兩個單詞之間的空格。
    • daw:刪除一個單詞,包含單詞的邊界(空格)。
    • d0:刪除至行首。
    • d$ / D:刪除至行尾。
  • da[:刪除[ ]整個塊,包含符號自己;

  • di[:刪除[ ]塊,不包含符號自己;

  • da/di + ' " { ( 等,也與接[相似,刪除整個區塊。惟一須要注意的,"和'僅僅在行內。

  • dt[x]:在本行,刪除到[x]。好比,dt"刪除到雙引號,dtf,刪除到字母fd/foo:在全文, 刪除到 「foo」 。

剪切

剪切操做其實就是咱們以前講的刪除。也就是d。刪除的內容,默認會存放到剪切板中。也就至關於進行了剪切。

進階操做符

從這裏你們能夠看出,ia的做用比較特殊,表明與區塊相關的某種操做。區別就在於,i不包含區塊邊界符號。a包含。這兩個操做符很重要,在後面的複製操做中還會用到。此外還有t/。此外,ia還能夠接t,此時t表示一對xml標籤。i:區塊,不包含邊界。a:區塊,包含邊界。t:"to",本行到哪裏。/:接匹配,全文到哪裏。

粘貼

  • p:粘貼到光標後,或下一行。
  • P:粘貼到光標前,或前一行。

爲何會有光標先後或上下一行兩種狀況呢?是由於咱們複製或剪切的內容有多是字符串或者整行:

  • 當複製內容爲字符串時,粘貼到光標前/後。
  • 當複製內容爲整行時,粘貼到上/下一行。

複製

  • y,複製,屬於操做,後面須要接動做來標識複製的範圍。好比:
    • yw:複製到當前單詞結尾。
    • ye:從當前位置複製到本單詞的最後一個字符。
    • y$:複製到當前行尾。
    • yyY:複製當前行。
    • nyy:複製從光標所在行起的n行,注意n在最前面。

0y$: 命令意味着:

  • 0 → 先到行頭
  • y → 從這裏開始拷貝
  • $ → 拷貝到本行最後一個字符

固然也能夠結合咱們剛剛介紹的進階操做符來進行操做:

  • yi":複製兩個引號之間
  • yit:複製兩個xml標籤之間
  • y/[x]:複製到x。

剪切板

vim 有 12 個剪切板,分別是 0、一、二、...、九、a、「、+。:reg:查看各個剪切板裏的內容。yp默認使用 "剪切板中的內容。 "[n]y:複製到剪切板n中。"[n]p:粘貼剪切板n中的內容。

查看是否支持系統剪切板:

vim --version | grep "clipboard"
複製代碼

觀看輸出中,clipboard前面是+仍是-。如果-,則說明不支持系統剪切板。 +號剪切板比較特殊,是系統剪切板,用於與系統其餘應用互動:

  • "+y,將內容複製到系統剪切板,ctrl+v將其粘貼到其餘應用中,好比vs code
  • "+p,將其餘應用中複製的內容,粘貼到vim中。

可視模式

v:進入可視模式。V:進入行選擇模式。Crtl + v:進入塊選擇模式。

進入可視模式後,能夠經過以前的移動操做,來進行選擇。好比:hjkl:先後左右選擇。$:選擇到行尾。i":選擇兩個引號之間。

選擇後,可使用

  • d進行刪除/剪切,
  • y進行復制。
  • 還可使用如下頗有意思的命令:
    • gU:變大寫。
    • gu:變小寫。
    • J:把全部的行鏈接起來(變成一行)。
    • <>:左右縮進。
    • = :自動縮進 。

格式化

=:調整格式化縮進。gg=G:全文代碼格式化。

  • gg,到文章開頭
  • =,調整格式
  • G,到文章結尾。

自動補全

編輯模式下Ctrl + n/p出現提示,此時會出現補全的選項。按住Ctrl不放,用np來遍歷提示選項,到達期待的選項後,無需其餘操做,繼續輸入便可。

撤銷

  • u:撤銷前一個動做
  • U:撤銷當前行的一系列動做
  • CTRL-R:Redo,意思就是我又不想撤銷了。

查找替換

  • /: 查找,此時Terminal左下角會出現/,在後面輸入想要查找的內容,回車便可。
  • ?:反向查找,一樣道理,左下角會出現?
  • /[search]\c:忽略大小寫。好比:/test\c,查找test,忽略大小寫
  • n: 下一個匹配
  • N: 前一個匹配

命令模式下:

  • s/old/new/:用new替換old
  • s/old/new/g:全局替換
  • set hlsearch高亮搜索結果

宏錄製

qa 操做序列 q, @a, @@

  • qa 把你的操做記錄在寄存器 a。
  • 因而 @a 會replay被錄製的宏。
  • @@ 是一個快捷鍵用來replay最新錄製的宏。

命令

  • :w:保存修改
  • :wq:保存修改並退出
  • ZZ:保存修改並退出
  • q!:不保存修改,強制退出
  • e!:不保存修改,強制從新打開當前文件

你們能夠看到,!的做用便在於,強制。除此之外,他還有另外一個很強勢的功能,就是執行shell命令。具體信息,你們能夠詳細閱讀下一節。

  • .:重複執行前一個命令。這個命令很靈活、實用,建議多多嘗試。
  • :help [command]:查看某命令的help此外,在命令行中執行以下命令,即可進入vim的教程。
vimtutor
複製代碼

外部命令

這是vim的一個很神奇的功能,在編輯的時候能夠與外部文本互動,甚至執行一些shell命令。

  • :w [file-name]:將當前內容輸出到指定文件中

  • :r [file-name]:將另一個文件的內容輸出到當前位置

  • :e filename:vim下打開指定文本

  • ctrl+w, s:水平拆分窗口

  • ctrl+w, v:垂直拆分窗口

  • ctrl+w, ARROW(h,j,k,l或方向鍵):在窗口間切換光標。

  • ctrl+w, w:在窗口間切換光標。

  • :qa:關閉全部窗口。

  • :saveas:另存爲。

  • :n/bn/bp:在打開的多個文件間切換。

  • :![command]:vim下執行某shell命令。

  • 好比,:!ls,便會暫時切換到shell下,輸出當前目錄的文件名。此時輸入回車,即可退回當前vim編輯的文件中。

若是你以爲這種輸入命令的方式還不夠過癮,vim還提供了保留當前工做現場,直接進入shell的方式。這種命令一個典型的工做場景是,如咱們編輯了一個文件,可是發現沒法保存(沒有寫權限),此時能夠先進入到shell下,執行相似chmod u+w [filename],的命令,爲當前用戶獲取該文件的寫權限,而後再回到 vim 保存剛剛的修改。 有以下兩種方法:

  1. :shell:sh,當退出當前 shell 時(好比exit),就會回到 vim。
  2. ctr-z 進入 shell,fg 退回 vim。

Config

這部分主要是一些vim的config。能夠直接命令模式輸入,也能夠保存到~/.vimrc中,即可每次打開vim自動應用。(其中一些命令是互相沖突的,請自行選擇有用的命令)。

syntax on # 開啓語法高亮

set nu[mber] # 顯示行號
set nonu[mber] # 隱藏行號

set cursorline # 高亮當前行
set ruler # 顯示光標位置信息
set noruler # 隱藏光標位置信息

set hlsearch # 高亮匹配
set nohlsearch # 取消高亮匹配
nohlsearch # 臨時取消高亮(只取消一次查詢的高亮)
set incsearch # 在輸入字符串過程當中顯示匹配點
set nowrapscan # 找到文尾後中止查找
set wrapscan # 恢復爲到文尾後自動從頭開始
set ic/ignorecase) # 忽略大小寫
set noic/noignorecase # 區分大小寫</pre>
複製代碼

VIM思想

這部分主要是一些我在使用vim過程當中的一些思考和感悟,試圖盡力闡述出來。若是你們能有一些思考和收穫,說明個人思考是有意義的。若是你們有不一樣看法,十分歡迎拍磚交流。

Why Normal

  • 爲何vim下,要放棄人們習慣的插入模式,使用命令模式呢?仔細想想,其實緣由很簡單:在沒有鼠標的年代,人們只能依靠鍵盤來移動光標,修改文本。
  • 爲何如今有了鼠標,咱們還要用正常模式呢?
    1. 工做內容覆蓋。咱們每一個人都認爲,工程師的工做,是寫代碼。然而,其實咱們主要的工做,是讀,或者說,理解代碼。經調查,工程師平常工做中,讀:寫代碼的比例,爲10:1(參考《Clean Code》一書)。因此默認的普通模式,主要知足佔比重更大的」讀「;遇到須要修改的時候,再進入編輯模式。
    2. 大量快捷鍵。相信每一個人,都最起碼知道一組快捷鍵:ctrl-c/v,也就是咱們熟悉的copy & paste. 若是你平時注重效率,養成了快捷鍵的習慣,還可能知道一些諸如ctrl-a/x/s/w等。不知你注意到沒有,如剛剛列舉的不少快捷鍵,都由 特殊的命令符+字母構成。由於在此時,鍵盤上的大多數按鍵,都是能夠輸入到文本中的字符。而在vim的正常模式下面,沒法直接向文件中輸入這些字符,至關於不用按ctrl等特殊的命令符,直接能夠把這些按鍵,用做命令的快捷鍵。

合理的快捷鍵

  • vim中的快捷鍵,佈局很是合理。根據使用頻繁程度,調整距離手邊的距離。好比,最基礎的移動操做,放在手邊的HJKL。雖然移動將手移動到鍵盤上的方向鍵,並未真正的浪費多少時間,可是其對思惟的打斷,其實很是影響效率。
  • 快捷鍵的設置,也是很是合理,結合了單詞的意義、讀音,很是便於記憶。好比:
    • d delete
    • c change
    • w word
    • e end
    • b back
    • I edit
    • f find
    • r replace

精細化,多維度命令

快捷鍵應有盡有,各個維度移動,都切合使用者思惟,幾乎能夠作到」指哪兒打哪兒「。 好比,移動、刪除、複製、等等操做,均可以結合精細化的位置,根據符合人類思惟的不一樣維度,進行操做。 好比,字符,單詞,行,文章,屏幕,匹配(位置、文字、符號),以及相似書籤的Mark等。

原子、組合命令

vim的大部分快捷鍵,都是原子操做,並經過與範圍結合,排列組合,靈活多變,完成各類強大的功能。這也與unix的主要思想契合:每一個命令作好,且只作好同一件事。 與此同時,經過用數字和宏,代替無心義的重複。 此外,對一些經常使用操做,提供了現成的宏,方便操做。好比,dd,是刪除整行,同時也能夠直接用D來完成。IA等,也是相似道理。

外部命令

相似棧的思路,能夠放下當前操做,保存現場,而後進入另外一個操做。當操做完成後,回到當前現場。

思惟模式

vim的快捷鍵,或者說命令,不只很符合咱們的思惟,並且還能在很大程度上擴展咱們的思惟。 拿編輯代碼時最多的操做,移動光標來講。原來咱們的移動,基本就是經過鍵盤的方向鍵,上下左右,或者經過鼠標,移動到想要去的位置。而在vim中,你會發現,光標除了上下左右,還能夠移動到詞首,詞尾,句首,句尾,行首,行尾,頁面首部,頁面中部,頁面尾部,文檔首部,文檔尾部,文檔任意一行,甚至還能夠移動到某個指定字母,某個tag,匹配大、中、小括號。度過最初的不適應後,經過刻意練習和平常使用,肌肉造成記憶,便無需刻意回想是用什麼命令,而是潛意識完成操做。掌握了這些命令後,當你使用原來的編輯器時,也會去尋找這些快捷鍵。這就不只僅是使用vim時候提供效率了,而是經過提升編輯操做的意識、思想,提升了總體的工做效率。

使用vim一段時間後,我在其餘工具中進行編輯時,編再也沒法忍受,一個一個自讀地移動光標。因而也會主動去找單詞、行級別移動的快捷鍵。

  • Mac系統
    • cmd + ←/→ 移動到:當前行首/尾部
    • alt + ←/→ 移動到:當前單詞首/尾部
  • iterm:
    • ctrl + f/b 前進/後退一個字符
    • Esc + f/b 前進/後退一個單詞
    • ctrl + a/e 行首/行尾
    • ctrl + h/d 刪除光標前/後一個字符
    • ctrl + w 刪除光標前一個單詞
    • ctrl + k/u 刪除光標前/後全部內容
    • ctrl + y 粘貼以前刪除的內容

後記

這篇文章到這裏也就結束了,洋洋灑灑寫了這麼多,一次讀下來就接受,很難;僅僅經過閱讀就掌握,更難。想要真正用熟vim,掌握思想,須要後續更多思考、實踐。可是相信我,這些付出,必定是值得的。由於它不只能讓你掌握一個開發利器,更能帶給你頗有價值的思想。

相關文章
相關標籤/搜索