VIM 程式碼片段外掛 Ultisnips 使用教程

keelii發表於2018-09-03

安裝

Ultisnips 外掛安裝分兩部分,一個是 ultisnips 外掛本身,另外一個是程式碼片段倉庫。一般來說把預設的程式碼片段倉庫下載下來按需修改後上傳到自己的 github 即可。如果你和我一樣也使用 vim-plug 來管理外掛的話,新增下面的程式碼到你的 vimrc 中儲存重新整理即可

上面的示例中所有的程式碼片段都存放在外掛安裝目錄下面的 vim-snippets/UltiSnips 中,檔案命名格式為 ft.snippets, ft 就是 vim 中的 filetype,其中有個 all.snippets 是唯一一個所有檔案都適用的程式碼片段

配置

快捷鍵設定,我一般使用 tab 來觸發程式碼片段補全,且不使用 YCM (官方文件表示使用YCM的話就不能使用tab補全)

依賴

ultisnips 外掛需要你的 vim 支援 python,可以在 vim 命令模式下使用下面的檢測你的 vim 版本是否支援 python

定義一個程式碼片段

定義格式

最小化的一個程式碼片段

這時當你在 vim 中輸入 if 敲 tab 就會展開一條 if 語句,第一個觸發點是 if 條件表示式,最後一個是 if 語句體

${1:true} 表示這是第一個觸發點,佔位符為 true,如果佔位符沒有預設值可直接使用 $1, $2, $3

可視選擇區的內容為佔位符

${VISUAL} 表示在 vim 中使用可視模式下選擇的文字,這個在重構程式碼的時候非常有用後面會有高階用法),上個圖感受一下:

if-with-visual-mode

程式碼片段的引數

  • b 表示觸發字元應該在一行的開始
  • i 表示觸發字元可以在單詞內(連續展示會使用這個選項)
  • w 表示觸發字元的前後必須是一個字母分界點
  • r 表示觸發字元可以是一個正規表示式
  • t 表示展開的程式碼片段中如果有製表符,原樣輸出,即使你的 vimrc 裡面設定了 expandtab
  • m 表示刪除程式碼片段右邊的所有空白字元
  • e 表示自定義上下文
  • A 表示自動觸發,不需要按 tab,類似於 VIM 中的 abbr

內容直譯器

Ultisnips 定義的程式碼片段中支援三種不同的語言注入:shell, vimscript, python,在程式碼片段中用反引號表示

shell 程式碼

就是在你的命令列 shell 能執行的程式碼片段,比如輸出當前時間

在程式碼片段中用反引號「`」引用即可

輸入 today 按 tab 展開後(格式和上面shell中的不一樣,估計是因為 vim 語言設定的問題):

vimscript 程式碼

使用 indent 來輸出當前縮排值,使用字首 !v 表示是 vimscript

vimscript-indent-size

python 程式碼

在程式碼片段中解釋執行 python 程式碼是 ultisnips 最強大的功能,以字首 !p 開始。系統會向 python 中注入一些變數,可以使用 python 程式碼直接對其進行操作

  • fn – 表示當前檔名
  • path – 當前檔名的路徑
  • t – 佔位符的字典,可以使用 t[1], t[2], t.v 來取佔位符內容
  • snipUltiSnips.TextObjects.SnippetUtil 物件的一個例項
  • match – 正則程式碼片段時返回的匹配元素(非常強大)

其中最常用的 snip 物件提供了下面一些變數:

  • snip.rv 表示 return value,python 程式碼執行後處理過的字串賦給 rv 即可
  • snip.fn 表示當前檔名
  • snip.ft 表示當前檔案型別
  • snip.v 表示 VISUAL 模式變數,其中 snip.v.mode 表示模式型別,snip.v.text 表示 VISUAL 模式中選擇的字元

python-snippet-var

佔位符選擇

UltiSnips 支援使用快捷鍵切換佔位符,我使用 <tab> 和 <shift-tab> 來切換 下一個 和 上一個佔位符,佔位符切換的作用域為當前程式碼片段內部(即使佔位符已被修改過),當游標移動出去以後就不起作用了

mul-placeholder-editing

自定義上下文

自定義上下文可以通過正則匹配來決定程式碼片斷是否可用,比如判斷在指定的 if 語句裡面才起作用的程式碼片斷,定義格式如下:

snippet 觸發字元 “描述” “表示式” 引數

比如我們定義一個 只有 在上一行以 if (DEVELOPMENT) { 開頭才可以展開的程式碼片段

常見用法

行內連續展開

這個常見於需要連續展開程式碼片段的情況,比如,有兩個片段,一個列印變數,一個處理 JSON 序列化。這時需要使用引數選項 in-word

continue-expand-snippets

使用正則程式碼片段

通常寫程式碼的時候需要使用 log, print 等來列印上下文中的變數。使用普通片段按 cl 展示 console.log() 然後把變數字元複製進括號,這樣操作會比較複雜。使用正則來動態匹配前面的字元可以很好的解決這個問題

動圖演示

expand-regexp-snippets

注意:正則程式碼片段只適用於單行文字處理,如果是多行轉換還是得用到下面的 python + VISUAL 程式碼片段來處理

使用 python 直譯器 + VISUAL 模式實現程式碼註釋功能

通常我們需要使用一大堆外掛來實現各種程式碼的註釋功能。不過 Ultisnips 提供了 VISUAL 模式可以提取 vim 可視模式中選擇的內容到程式碼片段裡面,於是我們就可以結合起來製作一個具有註釋功能的程式碼片段

流程大概是這樣的:

  1. 進入 vim 可視模式,選擇要註釋的內容
  2. 按 tab,清除選擇內容
  3. 輸入程式碼片段觸發字元,按 tab 完成

由於實現的 python 程式碼相對複雜一些,主要分成兩個方法。單行註釋和多行註釋,注意 Ultisnips 中可以直接寫 python 但是大段的方法建議放在外掛目錄下面的 pythonx 目錄下面,使用的時候在對應的程式碼片段中的全域性 python 程式碼 global !p 引入即可

單行註釋(pythonx/javascript_snippets.py):

多行註釋:

程式碼片段定義:

動圖演示

python-snippets-to-comment

不同的語言可以在對應的片段檔案中定義並傳入註釋符號引數即可,有了這個功能就可以愉快的刪除其它的 vim 註釋外掛了 ?

相關文章