這是 Neovim 從零開始系列的第三篇。整個系列共 12 篇文章,將帶你從完全不懂 Vim,到能用 Neovim 打造一個完整的現代化開發環境。

移動是一切的基礎

上一篇我們學了 Vim 的「語言」系統。而這門語言中的「名詞」,很大一部分就是移動指令(motions)。你移動越快、越精準,整體的編輯效率就越高。

這篇會把所有重要的移動指令一次講清楚。不用急著全背下來——先看過有個印象,然後每天挑 2-3 個新的來練習。

基本移動:hjkl

     k
h ←     → l
     j
方向 記憶法
h 最左邊的鍵
j j 的尾巴往下勾
k k 的筆畫往上
l 最右邊的鍵

為什麼不用方向鍵?

方向鍵離 home row 太遠了。hjkl 就在你右手的 home row 位置,手完全不需要移動。

小技巧:剛開始可以在鍵盤上貼小貼紙提醒,一兩天就習慣了。

搭配數字

指令 功能
5j 往下 5 行
10k 往上 10 行
3l 往右 3 格

單字級移動:w / b / e

這三個可能是你除了 hjkl 之外最常用的移動:

This is a simple-example of text.
^    ^  ^ ^      ^       ^  ^
w    w  w w      w       w  w     (按 w 的停靠點)
指令 功能 記憶法
w 到下一個單字的開頭 word
b 到上一個單字的開頭 back
e 到目前單字的結尾 end
ge 到上一個單字的結尾 go + end

大寫版本:W / B / E

大寫版本只以空白字元為分界:

hello-world foo_bar  baz
^           ^        ^        W 的停靠點(以空白分界)
^    ^^     ^  ^^    ^        w 的停靠點(以標點分界)

在處理帶有 -_. 的程式碼時特別有用:

  • user-profile-componentw 要按 5 次,W 只要 1 次
  • req.body.usernamew 要按 5 次,W 只要 1 次

行內移動

指令 功能 說明
0 行首(第 0 列) 絕對行首
^ 行首第一個非空白字元 跳過縮排
$ 行尾 最後一個字元
g_ 行尾最後一個非空白字元 略過尾部空白

0 vs ^ 的差別

    function hello() {
^   ^
0   ^(^ 跳過前面的空白)

大多數時候你想要的是 ^(跳過縮排到程式碼開始處),而不是 0(真正的第 0 列)。

行間移動

指令 功能
gg 到檔案第一行
G 到檔案最後一行
{數字}G:{數字} 到指定行號
{數字}% 到檔案百分比位置(如 50% 到中間)

搭配行號

如果你開啟了行號顯示(建議開啟相對行號),就能快速跳轉:

看到目標在第 42 行 → 按 42G 或 :42
看到目標在往下 15 行 → 按 15j

段落 / 區塊移動

指令 功能
{ 往上一個空行(段落開頭)
} 往下一個空行(段落結尾)
% 跳到配對的括號 ()[]{}

% 對程式設計者特別好用——游標在 { 上按 % 就跳到對應的 },再按一次就跳回來。在讀複雜的巢狀程式碼時非常實用。

行內搜尋:f / t / F / T

這四個指令讓你在同一行內精準跳到任何字元:

指令 功能 記憶法
f{char} 跳到下一個 {char} find
F{char} 跳到上一個 {char} Find backwards
t{char} 跳到下一個 {char} 的前一格 till
T{char} 跳到上一個 {char} 的後一格 Till backwards

重複搜尋

指令 功能
; 重複上一次 f/t 搜尋(同方向)
, 反向重複上一次搜尋

實戰範例

const result = calculateTotal(price, quantity, discount)
^
// 想跳到 discount:
f d   discount  d
// 想刪除從游標到 quantity 前:
d t q  刪除到 q 的前一格

f vs t 的使用時機

  • f:你想跳到那個字元上(用於移動)
  • t:你想操作「到那個字元之前」的內容(常搭配 dc
hello, world, foo
^
dt,  →  , world, foo       (刪除到逗號前,保留逗號)
df,  →   world, foo        (刪除到逗號,含逗號)

全文搜尋:/ 和 ?

指令 功能
/{pattern} 向下搜尋
?{pattern} 向上搜尋
n 跳到下一個匹配
N 跳到上一個匹配
* 搜尋游標下的單字(向下)
# 搜尋游標下的單字(向上)

搜尋的實用技巧

/function    " 搜尋 function 這個詞
/TODO        " 找所有 TODO
/\v\d{3}     " 用 regex 搜尋三位數字(\v 開啟 very magic 模式)

* 特別好用——游標放在某個變數名上,按 * 就能立刻找到它在其他地方的出現位置。

搜尋 + 操作

搜尋也是一種 motion,所以可以和 operator 組合:

指令 功能
d/hello 刪除到 “hello” 出現的位置
c/TODO 修改到 “TODO” 出現的位置
y/func 複製到 “func” 出現的位置

Marks:書籤系統

Marks 讓你在檔案中設定書籤,之後可以快速跳回。

指令 功能
m{a-z} 在目前位置設定 mark(小寫 = 檔案內)
m{A-Z} 設定全域 mark(大寫 = 跨檔案)
`{mark} 跳到 mark 的精確位置(行 + 列)
'{mark} 跳到 mark 所在行的開頭

特殊 Marks

Mark 功能
` ` 上一次跳轉的位置
`. 上一次修改的位置
`^ 上一次 Insert mode 退出的位置
'' 上一次跳轉的行

使用場景

1. 在函數開頭按 ma(設定 mark a)
2. 滾動到其他地方看程式碼
3. 按 `a 跳回函數開頭

螢幕移動(不移動游標)

指令 功能
Ctrl-d 往下半頁
Ctrl-u 往上半頁
Ctrl-f 往下一頁
Ctrl-b 往上一頁
zz 把目前行置中
zt 把目前行移到頂部
zb 把目前行移到底部

Ctrl-dCtrl-u 是瀏覽程式碼最常用的滾動方式。配合 zz 把當前行置中,閱讀體驗非常好。

跳轉歷史

指令 功能
Ctrl-o 跳回上一個位置(jump list 往回)
Ctrl-i 跳到下一個位置(jump list 往前)
g; 跳到上一個修改位置(change list 往回)
g, 跳到下一個修改位置(change list 往前)

Ctrl-o 可能是最容易被低估的指令。當你用 * 搜尋跳到其他位置、用 gg 跳到檔案開頭之後,按 Ctrl-o 就能一步步跳回原來的位置。就像瀏覽器的「上一頁」。

常見移動模式整理

以下按「你想到哪裡」來整理:

想到行內某個位置

目標 指令
行首 0^
行尾 $
行內某個字元 f{char}t{char}
下一個單字 wW

想到某一行

目標 指令
指定行號 {n}G:{n}
檔案開頭 gg
檔案結尾 G
往上/下 N 行 {n}k / {n}j

想到某個結構

目標 指令
配對括號 %
下一個段落 }
上一個段落 {

想到某個詞

目標 指令
搜尋特定文字 /{text}
找游標下的詞 *#

練習題

嘗試在一個真實的程式碼檔案中完成以下操作(只使用 Vim 移動指令):

練習 1:基本移動

  1. gg 跳到檔案開頭
  2. G 跳到檔案結尾
  3. Ctrl-o 跳回開頭
  4. 50G 跳到第 50 行

練習 2:行內精準移動

  1. 找到一行有多個逗號的程式碼
  2. f, 跳到第一個逗號
  3. ; 跳到下一個逗號
  4. , 跳回上一個逗號

練習 3:搜尋與跳轉

  1. * 搜尋游標下的變數名
  2. n 跳到下一個出現位置
  3. N 跳回上一個
  4. Ctrl-o 回到原始位置

練習 4:Marks

  1. 在某個重要位置按 ma
  2. 滾動到檔案其他位置
  3. `a 跳回標記位置
  4. `` 跳回跳轉前的位置

挑戰:不碰滑鼠地閱讀一個 200 行的檔案

  • Ctrl-d / Ctrl-u 滾動
  • } / { 跳過段落
  • / 搜尋特定函數
  • zz 把感興趣的行置中

小結

移動指令看似很多,但日常最常用的大概是這些:

頻率 指令
每分鐘都在用 w b e j k 0 $
每小時用很多次 f t / * n % gg G
需要時超好用 Ctrl-d Ctrl-u Ctrl-o zz marks

先把第一行的指令練到自然,再慢慢加入其他的。不用急。

下一篇,我們會學習讓編輯效率再加倍的進階技巧:registers、macros 和 dot command。


Neovim 系列文章導航

基礎篇

  1. 為什麼我想離開 VSCode?
  2. Vim 的語言——動詞、名詞、組合技
  3. 移動的藝術(本篇)
  4. 編輯效率加倍

設定篇 5. 安裝 Neovim 與 init.lua 6. Plugin 管理 lazy.nvim 7. 程式碼智能 LSP + 補全 8. 語法高亮與檔案導航

進階篇 9. Git 整合工作流 10. Terminal 與 Claude Code 整合 11. 打造快捷鍵系統 12. 從 VSCode 完全畢業