Vim:核心思想和基本操做

The Missing Semester —— 學校不教的 CS 基礎

最近在看一個 MIT 發佈的系列課程視頻:The Missing Semeter Of Your Computer Science Education,課程涵蓋了不少咱們在日常開發中遇到過的、可是課程體系中不多涉及到的話題,並介紹了相關的基礎知識和最佳實踐。這一系列視頻中,其中一節是關於 Vim 的,介紹了 Vim 背後的思想和一些基本操做。python

雖然以前在搗鼓雲服務器的時候用過 VIm 編輯過一些文件,可是那時候對命令行環境還比較陌生,有一些基本的操做還不夠熟練,也就不肯意去深刻學習 Vim,致使一直沒有入門。平時也主要用 VS Code 這樣的現代編輯器,因此也沒有太強的動力去學習 Vim。shell

最近在一些項目中,開始愈來愈多地和終端、shell 腳本打交道,愈發感受須要學習一些進階的操做,來提升生產力。這一系列課程視頻剛好爲我打開了新世界的大門。另外,在寫代碼的時候,確實發如今鍵盤和鼠標之間來回切換至關費時間。編程

正好如今藉着這一系列視頻,開始從新學習 Vim 的操做。如今斷斷續續已經用了兩個禮拜、四五個小時了,基本的操做逐漸熟悉,編輯速度直線上升。甚至發現即便是在現代編輯器中,不少操做使用 Vim 也會更快一些。因而連 VS Code、Chrome 瀏覽器什麼的全都配置了 Vim,儘可能避免使用鼠標或者觸控板。vim

在進入正題以前,向你們推薦一下這一系列的課程。若是你想系統地瞭解一下命令行界面、Vim 等各類工具,想要提高本身的生產力,或者簡單地想學一些「高端」操做,均可以去看一下這一系列視頻,相信你不會後悔的。瀏覽器

接下來,我會簡單介紹一下 Vim 及其背後的思想,並經過一些簡單的使用場景,介紹 Vim 入門級別的一些命令。服務器

Vim 的基本思想

Vim 認爲,開發者大部分時間花在閱讀代碼、對代碼進行小幅編輯上,而非花在編寫大量代碼上。因而,Vim 就有了各類模式:在 普通(NORMAL) 模式下閱讀代碼、跳轉位置、快速編輯,在 編輯(INSERT) 模式下編寫代碼,在 可視(VISUAL) 模式下選擇代碼,等等。app

Vim 是可編程的,能夠經過 Vimscript 或者 Python 編寫控制 Vim 的程序。甚至連 Vim 的界面自己也是一種「編程語言」——每個按鍵對應一個命令,而且多個命令能夠組合在一塊兒。編程語言

Vim 幫助你脫離對鼠標的依賴。在鍵盤和鼠標中頻繁切換太慢了。甚至,在鍵盤和方向鍵之間切換也很慢,因此它連方向鍵也不須要。編輯器

基於這些思想,Vim 可以跟上咱們思考的速度,使用熟練之後,會大大提升咱們的效率。ide

Vim 的基本操做

模式切換

  • 當使用 Vim 命令打開一個文件時,會默認進入普通模式。
  • 使用 i (insert) 進入編輯模式,在當前光標以前插入文本。(還有另外的命令能夠進入編輯模式,在以後會詳細列出)
  • 使用 v (visual) 進入可視模式
  • 在非普通模式下,使用 ESC 回到普通模式
    • 在使用 Vim 時,會頻繁使用到 ESC。所以,建議將大寫鎖定鍵綁定爲 ESC,來減小手的移動幅度。

普通模式

正如在基本思想中所說,開發者很大一部分時間是在閱讀代碼。並且閱讀並不是老是線性的,須要在同一文件的不一樣部分來回跳轉切換,或者須要查看多個文件。所以,在閱讀模式下快速移動光標到本身想要查看的位置尤其重要。

Vim 不須要方向鍵,而是由 hjkl 代替,分別對應左、下、上、右四個方向鍵。雖然其實用方向鍵也能夠移動,可是爲了可以儘可能避免手的位移,仍是習慣一下 hjkl 爲好。在 Vim 的配置文件中,也能夠設置禁用方向鍵,這個以後會給出相應的配置。

可是這僅僅只是實現了方向鍵。咱們仍是隻能一點點的上下左右移動。因而,又有了不少別的操做,讓咱們更快地移動

行間移動:

  • w 向後移動一個詞。
  • b 向前移動一個詞
  • e 向後移動到當前詞的末尾字符
  • {number}w/b/e 移動規定詞數,好比 3w 會向後移動三個詞
  • $ / ^ 光標移動至行尾/行首

跨行移動:

  • {number}j/k 向下/向上移動相應行數,好比 5k 向上移動 5 行
    • 這樣移動時,行號很重要。Vim 不只支持顯示當前行數,還能夠在配置文件中設置顯示相對行號,這樣很方便就能看出須要向上或者向下移動幾行。詳細配置會在後面一併給出。
  • {number}G 移動到該行
  • H 移動到窗口頂端,M 移動至窗口中間,L 移動到窗口底部
  • Ctrl-u 向上滾動半個窗口,Ctrl-d 向下滾動半個窗口
  • gg 移至文件頂端,G 文件移至底端

搜索:

  • f{character} F{character},在當前行,向後/向前查找某一字符,光標移動到該字符
    • 使用 ,; 跳至下一處或者上一處
  • t{character}, T{character},在當前行,向後/向前查找某一字符,光標移動到該字符以前
    • 一樣,使用 ,; 跳至下一處或者上一處
  • /{regex} 搜索文件,n / N 跳轉到下一處/上一處

編輯模式

在普通模式下,除了上面提到的用 i 進入編輯模式,還有其餘的命令:

  • I (shift + i) 在當前行的第一個非空字符以前進入編輯模式
  • a (append) 在光標以後進入編輯模式
  • A 在行尾進入編輯模式
  • o 在當前行下新插入一行,光標移動至行首,進入編輯模式
  • O 在當前行上面新插入一行,光標移動至行首,進入編輯模式

這幾個操做對應了幾個不一樣的場景。在實際的開發過程當中很常見。好比行尾少了冒號或者分號,好比須要新開一行,不須要先移動光標到行尾,而能夠直接使用對應的指令在相應位置開始編寫代碼。

還有一些常見的命令,能夠對應其餘的編輯場景:

  • d{motion} 刪除,好比 dw 是刪除當前詞,d$ 刪除光標至行尾的全部字符,d^ 刪除光標至行首的全部字符
  • c{motion} 修改,cw 是修改當前詞,效果是刪除當前詞,並進入編輯模式,等同於 dw + i
  • x 刪除當前字符,至關於 dl
  • s 替換當前字符,至關於 xi

進入可視模式後,能夠選中文本,再進行操做:

  • 可視模式下經過前面介紹過的移動命令能夠選中特定文本
  • 選中後,d 刪除,c 修改
  • y 複製(英文是 yank),d 也會複製,p 粘貼

Vim 中也有對應的撤銷、重作:

  • 在普通模式下,u 撤銷 ctrl + r 重作

計數與修飾

在前面咱們見過了 {number}k 這樣的操做,能夠經過計數來執行特定次數相同的操做。更多的例子有:3w 向後移動 3 個詞,7dw 刪除 7 個詞

經過修飾,能夠修更名詞的意思,實現不一樣的編輯效果。好比,ci( 能夠修改當前括號內的內容,它會刪除當前括號內的內容,並進入編輯模式。da' 則會刪除引號以及引號內部的內容。這裏 i 的意思是 inside,a 則是 around

Vim 命令行

在普通模式下,使用 : 進入命令行,進行文件的讀取、寫入等操做:

  • :w 保存
  • :q 退出。 :wq 保存 + 退出
  • :q! 放棄修改的內容強行退出
  • :e {file name} 打開某一文件
  • :ls 顯示打開的文件(緩衝)
  • :help {topic} 打開幫助界面
    • :help :w 打開 :w 命令的幫助
    • :help w 打開 w 移動操做的幫助

Vim 實例演示

介紹了一些基本操做,能夠經過一個例子來看看如何使用這些命令來編輯一個文件:

The Missing Semester 提供了一個例子,裏面是一段有問題的 Python 程序:

def fizz_buzz(limit):
    for i in range(limit):
        if i % 3 == 0:
            print('fizz')
        if i % 5 == 0:
            print('fizz')
        if i % 3 and i % 5:
            print(i)

def main():
    fizz_buzz(10)
複製代碼

該程序存在一些問題:

  • main 函數不會執行,須要在文件末尾添加一些語句
  • 循環會從 0 開始,而不是從 1 開始,須要修改 range 中的內容
  • 當數字是 3 的倍數 或者是 5 的倍數的時候,打印的是同一個詞, 須要修改其中一個引號內的詞爲別的什麼以區分
  • main 函數中使用的是寫死的參數,而非命令行參數或者是用戶的輸入

下面的幾個動圖,顯示瞭如何經過 Vim 來修改這個程序。按鍵操做顯示在了動圖中

添加 if __name__ == 'main': 語句,涉及到行數跳轉:

add main

修改其中一個 'fizz''buzz'

modify range

修改 range 範圍:

modify word

添加命令行參數:

Vim 基本配置

前面提到了一些須要配置的功能。在上面的動圖中你也看到了相對行號顯示、自動縮進等,這些在最開始打開 Vim 的時候並非默認開啓的,須要在 Vim 的配置文件中進行配置。

在 macOS 和 Linux 系統中,Vim 的配置文件位於 '~/' 目錄下,文件名爲 .vimrc。Vim 在每次啓動時都會默認讀取該文件的配置。

這裏是一個比較簡單的配置文件,建議你閱讀註釋的描述,判斷本身是否須要這一設置,再手動配置你的 '~/.vimrc` 文件,僅僅加入你須要的配置項。這樣可以避免你在不清楚設置的具體內容是什麼的狀況下,盲目拷貝別人的配置,致使引入一些你不習慣的操做。

配置文件來自於 The Missing Semester,翻譯了註釋

" 雙引號爲註釋標記.

" 若是在 Vim 中打開這個文件,則會看到語法高亮

" Vim 是基於 Vi 開發的。設置 `nocompatible` 會取消默認的 Vi 兼容模式,並啓用一些有用的 Vim 功能
" 這項配置在 ~/.vimrc 中其實不必,由於若是用戶有 `~/.vimrc` 文件,Vim 會自動使用非兼容模式。
" 寫在這以防配置文件是經過其餘方式引入的(好比文件另存爲了 foo,並經過 `vim -u foo` 命令啓動了 Vim
set nocompatible

" 打開語法高亮
syntax on

" 禁用默認的開啓提示文字
set shortmess+=I

" 顯示行號
set number

" 啓用相對行號。當前行所顯示的數字是實際行號,上面和下面的行都會顯示相對的行號,便於跳轉
set relativenumber

" 在窗口底部顯示狀態欄
set laststatus=2

" 若是搜索的關鍵詞所有爲小寫,則搜索忽略大小寫。若是關鍵詞中含有大寫字母,則搜索變爲大小寫敏感
set ignorecase
set smartcase

" 即時顯示搜索結果,而非等待按回車以後再顯示
set incsearch

" 啓用鼠標。雖然你應該儘可能避免使用鼠標,可是某些狀況下仍是鼠標比較方便 
set mouse+=a

" 當使用方向鍵跳轉行數時發出提示
" Do this in normal mode...
nnoremap <Left>  :echoe "Use h"<CR>
nnoremap <Right> :echoe "Use l"<CR>
nnoremap <Up>    :echoe "Use k"<CR>
nnoremap <Down>  :echoe "Use j"<CR>
" ...and in insert mode
inoremap <Left>  <ESC>:echoe "Use h"<CR>
inoremap <Right> <ESC>:echoe "Use l"<CR>
inoremap <Up>    <ESC>:echoe "Use k"<CR>
inoremap <Down>  <ESC>:echoe "Use j"<CR>

" 將縮進符顯示爲 4 個空格 
set tabstop=4
" 當使用 '>' 縮進時, 使用 4 個空格
set shiftwidth=4
" 按 Tab 鍵時,插入 4 個空格
set expandtab
" 設置自動縮進,根據文件類型縮進 
set autoindent
filetype plugin indent on
複製代碼

小結

本篇文章介紹了 Vim 的基本思想,入門 Vim 須要瞭解的基本操做,以及基本的配置項。這篇文章也是在 VS Code 中 啓用了 Vim 插件以後編寫的。

我本身也是剛用了沒幾個小時,雖然大部分操做已經比較熟悉,可是仍是有些地方會卡住一小會。不過,用得越多,就能發現卡殼兒的地方愈來愈少,寫代碼的速度愈來愈快了。

Vim 是一個很是強大的編輯器,還有不少的功能、插件和配置沒有探索到。後續當我用得再多一些,總結出一些高級用法以後,再來分享。

網上也有很多資源能夠學習 Vim,好比 Vim Tutor 在命令行學習 Vim 操做。還有人建了一個網頁,你們互相比拼誰能用最少的命令修改完一段文本。另外,當你以爲在編輯什麼文件時,有些操做過於繁瑣,那頗有可能確實存在一個更好的方式,這時不妨上網查一下,看看前人有沒有相應的解決方法。

入門 Vim 確實是一個按部就班的過程,一開始很不習慣。可是當你逼着本身用一段時間之後,就會越用越順手。固然,仍是在業餘時間偷偷練習吧,熟悉 Vim 操做以前,在搬磚修福報的時候仍是保持效率更重要。。

參考連接:

missing.csail.mit.edu/2020/editor…

文章同步發佈於博客:點擊查看

相關文章
相關標籤/搜索