讓 Vim 採用基於視覺行的游標移動

Vim 是一款文字編輯器,就是和微軟的記事本有著同樣用途的那種東西。

1.jpg

▲ Vim 的其中一種介面--Gvim

這玩意兒外觀看起來破破的,但在同類軟體之中,其功能之強彈性之大卻是罕有敵手,我現在差不多寫任何純文字的東西都靠這個。

不過話說回來,Vim 彈性太大也導致了一些問題:因為各式各樣不同的人都在用它,如果沒有好好對它施以教育(設定),讓它適應自己的使用習慣,它可一點也不好用。但即使下定決心要對它進行設定,光基本設定參數就好長一大堆,初學者初設定時一定會昏倒個兩三回。

其他的事就不抱怨了,今天就來聊聊其中一項設定:「基於視覺行的游標移動。」

視覺行與實體行是啥?

在進入正文前,先簡單介紹一下視覺行與實體行的差異。

2.jpg

▲ 範例文字:以上這段文字中有 4 個實體行和 10 個視覺行。源自維基百科。

實體行

按 Enter 鍵時產生的行被稱為實體行。總地來說,實體行的行尾一定是 Enter 或文件尾巴。

在網頁上,一個實體行也往往會被當成一個段落

實體行的英文正式稱呼為 “physical line”,有時也被稱呼為 “logical line”。

視覺行

因為視窗橫向空間不足,而自動折行產生的新行就叫作視覺行。行數會受到視窗寬度影響而會自動變化。

一般而言,網頁中一個段落(等於實體行)可能會佔據著很多個視覺行。

視覺行似乎沒有正式的稱呼方式,這三個字是我自己發明的。


在用 Word 或其他文書或文字編輯軟體時,我們移動游標時都是依據視覺行來移動的:按「上」向上移動一個視覺行,按「下」游標下跑一個視覺行……理所當然!但 Vim 的游標偏偏是基於實體行來移動:按上下鍵時,游標是一次跳一個實體行。

寫程式時因為單獨的實體行都不長,如此操作倒也沒太大差別。不過當寫網誌或小說時,每個實體行都會因為過長而被折成好多個顯示行,基於實體行的移動此時就變得很不直覺,而且礙手礙腳,選字超麻煩,讓咱想在手與鍵盤之間選一個來砸。

其實這時該砸的是 Vim 才對。

Vim 的調整方法

我寫了些設定來把 Vim 教得更聰明一點。總之,請將以下設定貼入 Vim 的設定檔 vimrc 中。

"===視覺光標操作 ===
"一言以蔽之,按上下鍵將變更光標所處的可視行,而非實體行。
noremap <silent> <Leader>w :call ToggleDisplayMove()<CR>
let ToggleDisplayMove_Mode = 0
function PhysicalLineMove()
silent! nunmap <buffer> <Up>
silent! nunmap <buffer> <Down>
silent! nunmap <buffer> <Home>
silent! nunmap <buffer> <End>
silent! iunmap <buffer> <Up>
silent! iunmap <buffer> <Down>
silent! iunmap <buffer> <Home>
silent! iunmap <buffer> <End>
let g:ToggleDisplayMove_Mode = 0
endfunction
function DisplayedLineMove()
noremap <buffer> <silent> <Up> gk
noremap <buffer> <silent> <Down> gj
noremap <buffer> <silent> <Home> g<Home>
noremap <buffer> <silent> <End> g<End>
inoremap <buffer> <silent> <Up> <C-o>gk
inoremap <buffer> <silent> <Down> <C-o>gj
inoremap <buffer> <silent> <Home> <C-o>g<Home>
inoremap <buffer> <silent> <End> <C-o>g<End>
let g:ToggleDisplayMove_Mode = 1
endfunction
function ToggleDisplayMove()
if g:ToggleDisplayMove_Mode
call PhysicalLineMove()
echo "Move cursor now base on PHYSICAL LINE"
else
call DisplayedLineMove()
echo "Move cursor now base on DISPLAYED LINE"
endif
endfunction
call DisplayedLineMove()

如此一來,Vim 預設就會採用「基於視覺行」的移動了。而當您想在兩種移動模式間切換時,只要輸入 <Leader>w 就可以無痛進行切換。

補充