日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从零开始配置 vim(3)—— 键盘映射进阶

發(fā)布時間:2024/8/1 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始配置 vim(3)—— 键盘映射进阶 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

嚴(yán)格意義上來說,快捷鍵的綁定應(yīng)該是鍵盤映射,將某些鍵映射為另一些鍵。

在上篇我們介紹了基本的鍵盤映射操作,知道了如何 :map、:imap、:vmap、:nmap這些命令來映射鍵盤快捷鍵。它們很方便,也很簡單,但是有一個致命的缺點(diǎn)。他們是遞歸的,我們先來討論什么是遞歸

映射的遞歸問題

讓我們先來執(zhí)行下面的命令

:nmap jj J :nmap J j

這里我們原本是想 jj來實(shí)現(xiàn) J的功能,更加快速的實(shí)現(xiàn)合并行的功能,但是我們按下之后發(fā)現(xiàn),它只是將光標(biāo)移動到下一行了。這并不是我們想要的。到底發(fā)生什么了呢?

因?yàn)檫@些命令是遞歸的。如何理解遞歸呢?我們以函數(shù)的思想來考慮,每定義一個快捷鍵,就相當(dāng)于定義了一個函數(shù)。并且在新定義的函數(shù)中調(diào)用老函數(shù)。依照這個思路我們來分析一下上述兩個命令產(chǎn)生的結(jié)果:

  • 首先定義了一個名為 jj的函數(shù),它的函數(shù)代碼為 J()
  • 然后我們定義了一個名為 J的函數(shù),它的代碼定義為 j()
  • 我們執(zhí)行 jj函數(shù)的時候,它在函數(shù)內(nèi)部調(diào)用 J(),J函數(shù)內(nèi)部調(diào)用 j()。因此它表現(xiàn)出來的最終效果就是 jj等效與 j。
  • 這些映射產(chǎn)生的偽代碼如下:

    void J() {j(); }void jj() {J(); }

    我們在調(diào)用 jj 這個函數(shù)的時候就相當(dāng)于在調(diào)用 j

    有點(diǎn)繞是不是呢。為了講述這個問題,我們再來看這么一個例子

    :nmap dd o<esc>kddj

    我們來分析一下它的本意:

    • 首先使用 o在光標(biāo)所在行之下插入一行
    • 退回到普通模式,并且讓光標(biāo)向上移動一行
    • 刪除光標(biāo)所在行
    • 移動到下一行,也就是剛剛的插入行

    看起來這個命令的作用是清除本行,但是vim并沒有這么做,只有按下 <C-c>才能停下來,而且vim中多出了許多空白行。

    依照上述分析思路,我們可以對這個命令的執(zhí)行結(jié)果寫出如下的偽代碼

    void dd() {o();esc();k();dd();j(); }

    從上述的代碼看出這個映射會陷入無限循環(huán),或者叫死遞歸。我們只能使用 <Ctrl +c>來終止。

    在正式進(jìn)入下一步之前讓我們先刪除這個映射。我們可以使用 :nunmpa 來刪除一條快捷鍵映射,輸入 :nunmap dd 來終止上述出錯的映射。之前介紹的那些映射命令都有 un 系列的命令,例如 map 對應(yīng) unmap,imap 對應(yīng) iunmap 。

    我們從上面的幾個例子應(yīng)該看出來了, 之前介紹的函數(shù)好用是好用,但是會形成遞歸。在上述代碼中還算是比較好找,如果我們配置文件大了,不同插件有自己的映射,而我們也會定義一堆自己的映射,這個時候出問題就難查了。

    為了解決這個問題,vim提供了一系列的 nore 開頭的函數(shù)。它相比于之前介紹的函數(shù)來說,是非遞歸的。之前每個命令對應(yīng)的非遞歸版本如下:

    • nmap 對應(yīng) nnoremap
    • imap 對應(yīng) inorempap
    • vmap 對應(yīng) vnoremap
    • cmap 對應(yīng) cnoremap

    相信各位應(yīng)該看出來了,我們在原來命令的基礎(chǔ)之上添加了 nore 作為非遞歸版本。我們來做一個試驗(yàn)

    :nmap x dd :nnoremap \ x

    我們輸入 \ 發(fā)現(xiàn)它只刪除了一個單詞,即使用 :nnoremap 只保留了 \ 作為 x 操作符的作用,而斬?cái)嗔酥?x 被映射為 dd 的操作。

    那么我們何時該使用遞歸版本,何時使用非遞歸版本呢?答案是在任何時候,永遠(yuǎn)使用非遞歸版本,現(xiàn)在就請各位小伙伴忘掉非遞歸版本把。現(xiàn)在多敲幾個單詞將來會省去大量排錯時間。

    lua 配置

    到此位置我們學(xué)會了怎么使用 :map 系列的命令定義快捷鍵,同時也知道什么是快捷鍵之間的遞歸和非遞歸。可以說掌握了關(guān)于 vimscript 定義快捷鍵的基本方法。那么如何跟 lua 對應(yīng)呢?

    neovim 定義了一系列的函數(shù)幫助我們定義、獲取和刪除快捷鍵

    • vim.api.nvim_set_keymap: 設(shè)置快捷鍵
    • vim.api.nvim_get_keymap: 獲取快捷鍵
    • vim.api.nvim_del_keymap: 刪除快捷鍵

    我們可以通過幫助文檔查到 vim.api.nvim_set_keymap 的定義如下:

    nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts})

    mode 是一個字符串,對應(yīng)著一個模式,即我們之前說的可視模式、插入模式或者普通模式,下面是各個模式對應(yīng)的字符串名稱 。

    字符串模式對應(yīng)的vim 命令
    “”所有模式:map
    “n”普通模式:nmap
    “v”可視模式:vmap
    “i”插入模式:imap
    “s”選擇模式:smap
    “c”命令模式:cmap

    lhs 對應(yīng)著一個鍵位,即我們想映射的鍵位,如果傳入空字符串,相當(dāng)于通過 :map傳入 <NOP>。表示將要禁用這個鍵
    rhs 對應(yīng)著將要執(zhí)行的命令,是 :map 的第二個參數(shù)
    opts 代表映射的其他屬性,主要是一個表,你可以暫時理解為一個字典。比如可以使用 noremap 表示禁止遞歸,使用 silent 表示執(zhí)行命令時不回顯內(nèi)容

    例如我們在配置文件中定義

    vim.api.nvim_set_keymap("n", "<space>", "/nvim<CR>", {noremap = true, silent = false})

    通過這段代碼,我們將 空格鍵映射為在文件中查找 nvim 字符。因?yàn)?silent 設(shè)置的是 false 因此我們在按下空格鍵之后在vim 的左下角會看到 /nvim 的字樣

    我們可以通過設(shè)置 silent = true來取消這個回顯。

    vim.api.nvim_set_keymap("n", "<space>", "/nvim<CR>", {norema=true, silent = true});

    映射leader 鍵

    常見的映射主要出現(xiàn)在普通模式下,普通模式下的很多按鍵都有其特殊用途,而且還大多挺常用的,想來想去不怎么使用,而且位置好按的也就 <space>、H、L、D 這些了,將他們進(jìn)行映射,映射到常用功能,減輕我們的按鍵負(fù)擔(dān)是再好不過了。但是我們常用功能又那么多,特別是裝了插件之后的。這些鍵完全不夠使用的。

    這個時候我們要延續(xù) emacs 或者其他軟件的思路了,一個鍵不夠就兩個鍵,比如使用下面的映射

    :noremap -d dd :noremap -c ddO

    這意味著我們可以使用一個鍵作為前綴,后面接其他字符,將他們作為一個整體來映射一個功能。多按一個鍵而已,比你輸入整個命令要輕松多了。

    這就引入一個新的思路了,我們可以統(tǒng)一定義一個鍵作為前綴鍵,后面添加一些字符來整體進(jìn)行映射。當(dāng)然我們可以手工這么做,每次需要多個按鍵的時候的就手動寫上 - 或者其他的。但是后期我發(fā)現(xiàn) - 并不容易按到,我覺得 <space> 或者 ,更容易按到,要進(jìn)行修改,那么修改的量就太大了。

    vim 中有一個被稱之為 leader 鍵的東西來解決這個問題,我們可以提前定義一個 leader ,在映射的時候使用 <leader> 來代表對應(yīng)的前綴鍵。例如,先設(shè)置 leader 為 <space> 后面再定義 <leader>d 作為 dd,后面可以很方便的修改 <space>d 這個映射為 ,d,只需要修改 leader 鍵的定義。

    可以使用 :let mapleader = <space> 來定義 leader 鍵為空格。這里你可以定義成你喜歡的鍵,我平時喜歡用空格,因?yàn)樗容^大,平時也在大拇指的位置,方便按。

    然后我們可以使用 :noremap <leader>d dd 來定義映射

    如何在 lua 中定義 leader 鍵呢?
    從上面的 vimscript 代碼中可以看到 mapleader 是用 let 關(guān)鍵字來設(shè)置的,一般 let 是用來設(shè)置變量的。lua 中自定義變量可以直接定義,但是 mapleader 明顯是vim 自帶的變量。跟設(shè)置選項(xiàng)類似,neovim 提供了兩種訪問 vim 內(nèi)部變量的方式,一種是使用函數(shù),一種是使用 元訪問器。

    跟變量有關(guān)的函數(shù)主要有:

    • vim.api.nvim_set_var():設(shè)置全局變量的值
    • vim.api.nvim_get_var():獲取全局變量
    • vim.api.nvim_del_var():刪除全局變量

    當(dāng)然使用元訪問器會更加簡便,對應(yīng)的元訪問器為 vim.g。所以這里我們可以使用 vim.g.mapleader = " " 來設(shè)置

    到此我們已經(jīng)學(xué)會了關(guān)于映射的所有初級的內(nèi)容,現(xiàn)在已經(jīng)可以完成大部分的配置工作了。至于在定義快捷鍵的時候是使用 leader鍵還是使用多個普通鍵,看具體場景和各位小伙伴的使用習(xí)慣了。這里我就不給建議了,一切以方便好按為主。

    總結(jié)

    以上是生活随笔為你收集整理的从零开始配置 vim(3)—— 键盘映射进阶的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。