W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在開頭前幾章我們曾講過怎么在Vim里設(shè)置選項。 對于布爾選項,我們可以使用set someoption!
來"切換"選項。 如果我們能給這個命令創(chuàng)建一個映射,那就再好不過了。
執(zhí)行下面的命令:
:nnoremap <leader>N :setlocal number!<cr>
在normal模式中按下<leader>N
看看。Vim將會在開啟和關(guān)閉行號顯示之間切換。 像這樣的"切換"映射是十分方便的,因此我們就不需要兩個獨立的鍵來開/關(guān)。
不幸的是,這只對布爾選項起作用。如果我們想要切換一個非布爾選項,還需要做更多的工作。
從創(chuàng)建一個可以切換選項的函數(shù),以及調(diào)用該函數(shù)的映射開始吧。 把下面的代碼加入到你的~/.vimrc
(或一個~/.vim/plugin/
中的獨立文件,如果你想要的話):
nnoremap <leader>f :call FoldColumnToggle()<cr>
function! FoldColumnToggle()
echom &foldcolumn
endfunction
保存并source文件,然后按下<leader>f
試試看。Vim顯示當(dāng)前foldcolumn
選項的值。 如果你不熟悉這個選項,閱讀:help foldcolumn
再繼續(xù)。
讓我們添加真正的切換功能。修改代碼成這樣:
nnoremap <leader>f :call FoldColumnToggle()<cr>
function! FoldColumnToggle()
if &foldcolumn
setlocal foldcolumn=0
else
setlocal foldcolumn=4
endif
endfunction
保存并source文件,然后試試看。每次你按下它Vim將顯示或隱藏折疊狀態(tài)條(fold column)。
if
語句判斷&foldcolumn
是否為真(記住Vim把0看作假而其他數(shù)字為真)。 如果是,把它設(shè)成0(隱藏它)。否則就設(shè)置它為4。就是這么簡單。
你可以使用一個簡單的函數(shù)像這樣來切換任何以0
代表關(guān),以其他數(shù)字代表開的選項。
我們的夢想不應(yīng)止于切換選項。還有一個我們想切換的東西是quickfix窗口。 依然以之前的骨架代碼作為起點。加入下面的代碼到你的文件:
nnoremap <leader>q :call QuickfixToggle()<cr>
function! QuickfixToggle()
return
endfunction
這個映射暫時什么都不干。讓我們把它轉(zhuǎn)變成其他稍微有點用的東西(不過還沒有徹底完成)。 把代碼改成這樣:
nnoremap <leader>q :call QuickfixToggle()<cr>
function! QuickfixToggle()
copen
endfunction
保存并source文件。如果現(xiàn)在你試一下這個映射,你就會看到一個空蕩蕩的quickfix窗口。
為了達(dá)到實現(xiàn)切換功能的目的,我們將選擇一個既快捷又骯臟的手段:全局變量。 把代碼改成這樣:
nnoremap <leader>q :call QuickfixToggle()<cr>
function! QuickfixToggle()
if g:quickfix_is_open
cclose
let g:quickfix_is_open = 0
else
copen
let g:quickfix_is_open = 1
endif
endfunction
我們干的事情十分簡單 —— 每次調(diào)用函數(shù)時,我們用一個全局變量來儲存quickfix窗口的開關(guān)狀態(tài)。
保存并source文件,接著執(zhí)行映射試試看。Vim將抱怨變量尚未定義!那么我們先把變量初始化吧。
nnoremap <leader>q :call QuickfixToggle()<cr>
let g:quickfix_is_open = 0
function! QuickfixToggle()
if g:quickfix_is_open
cclose
let g:quickfix_is_open = 0
else
copen
let g:quickfix_is_open = 1
endif
endfunction
保存并source文件,接著試一下映射。成功了!
我們的切換函數(shù)可以工作,但還留有一些問題。
第一個問題是,假設(shè)用戶用:copen
或:cclose
手動開關(guān)窗口,我們的全局變量將不會刷新。 實際上這不會是個大問題,因為大多數(shù)情況下用戶會用這個映射開關(guān)窗口,萬一沒有打開,他們也會再按一次。
這又是關(guān)于寫Vimscript代碼的重要經(jīng)驗:如果你試圖處理每一個邊際條件,你將陷在里面,而且不會有任何進(jìn)展。
在大多數(shù)情況下,先推出可工作(而且即使不能工作也不會造成破壞)的代碼然后回過頭改善, 要比耗費許多小時苛求完美好得多。除外你正在開發(fā)一個很可能有很多人用到的插件。 在這種情況下它才值得耗費時日來達(dá)到無懈可擊的程度,讓用戶滿意并減少bug報告。
我們的函數(shù)的另外一個問題是,當(dāng)用戶已經(jīng)打開了quickfix窗口,并執(zhí)行這個映射時, Vim關(guān)閉了窗口,接著把他們彈到上一個分割中,而不是送他們回之前的地方。 如果你僅僅想快速查看一下quickfix窗口然后繼續(xù)工作,發(fā)生這種事是讓人惱怒的。
為了解決這個問題,我們將引入一種寫Vim插件時非常有用的慣用法。把你的代碼改成這樣:
nnoremap <leader>q :call QuickfixToggle()<cr>
let g:quickfix_is_open = 0
function! QuickfixToggle()
if g:quickfix_is_open
cclose
let g:quickfix_is_open = 0
execute g:quickfix_return_to_window . "wincmd w"
else
let g:quickfix_return_to_window = winnr()
copen
let g:quickfix_is_open = 1
endif
endfunction
我們在映射中加入了新的兩行。其中一行(在else
分支)設(shè)置了另一個全局變量,來保存執(zhí)行:copen
時的當(dāng)前窗口序號。
另一行(在if
分支)執(zhí)行以那個序號作前綴的wincmd w
,來告訴Vim跳轉(zhuǎn)到對應(yīng)窗口。
我們的解決方法又一次不是無懈可擊的,用戶可能在兩次執(zhí)行映射之間打開或關(guān)閉新的分割。 即使這樣,它還是適合于大多數(shù)場合,所以目前這已經(jīng)夠好的了。
在大多數(shù)程序中,這種手工保存全局狀態(tài)的伎倆會遭到譴責(zé),但對于一個非常短小的Vimscript函數(shù)而言, 它既快捷又骯臟,卻能不辱使命,完成重任。
閱讀:help foldcolumn
.
閱讀:help winnr()
閱讀:help ctrl-w_w
.
閱讀:help wincmd
.
在需要的地方加上s:
和<SID>
來把函數(shù)限定在獨自的命名空間中。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: