[vim ] 你應該擴充的 text object
看板Editor (編輯器(vim/emacs))作者as23041248 (KAIKAIKAI)時間4年前 (2020/09/22 21:52)推噓3(3推 0噓 2→)留言5則, 2人參與討論串1/1
小弟我寫了一篇文章,和各位聊聊 vim text object
網誌版: https://reurl.cc/Z7WmRQ
# 前言
vim 高效率編輯的背後,operator, motion, text object 的配合功不可沒。
operator 是編輯的動作, text object 就是文字區塊,motion 是跳轉到文件點,
透過三者的按鍵配合,就能達到所想及所得的編輯方式。
如果你有看過別人使用 vim ,通常會有這種想法:怎麼隨便按幾個鍵就刪這裡刪那裡
複製這複製那,速度快到看不懂在幹嘛,而且還不會錯,因為只要想好要做什麼,
按鍵按下去就對了,這也是為什麼會高效率。說了一堆,反正就是 ""耍潮必備""。
本篇將會提到:
- operator, text object, motion 的配合用法
- 內建 text object 的不足之處
- 擴充 text object 的 plugin
- 淺談 nvim-treesitter
# Operator & text object
Vim 定義了多個 operator 最常用的就是:
- d: delete (刪除)
- c: change (更改)
- y: yank (複製)
operator 沒有配合 text object 或是 motion 是沒有意義的,想像一下
使用了 d 刪除,但是沒告訴它要刪除什麼,就像有了鐵鎚不知道要打什麼。
所以需要給 operator 一個目標,讓它要對誰做什麼。這個誰就有兩種,motion
和 text object。
motion:其實就是跳轉指令,像是常用的 G,gg, w, f{char} ... 等都可以配合
operator。基本使用方法為 {operator}{motion},語意就是做這個 operator
到 motion 所到的地方
以 d operator 做舉例的話 (其他 operator 以此類推):
- dG: 刪除 從游標到檔案的尾部
- dgg: 刪除 從游標到檔案的頭部
- dw: 刪除 從游標到下一個字
- dfz: 刪除 從游標底下到達此行 z 這個字母 (如果此行無 z 則不動作)
text object: 通常是已經定義的一個範圍,像是 word, quote, () block
... 等。內建的 text object 都會有 i 或 a 為前輟,i 表示 inside (不包含的概念)
、 a 表示 around (包含的概念)。
常用的 text object:
- iw :游標下的字不包含後面的空白 (英文斷字使用空白)
- aw :游標下的字包含後面的空白 (英文斷字使用空白)
- i" :游標下在雙引號裡的所有字不包含雙引號
- a" :游標下在雙引號裡的所有字包含雙引號
- i(, i) :游標下在小括號裡的所有字不包含小括號
- a(, a) :游標下在小括號裡的所有字包含小括號
基本使用方式為 {operator}{text object},語意就是對此 text object
做這個 operator
使用 d operator 做舉例:
- diw :刪除 游標下的字不包含後面的空白 (英文斷字使用空白)
- daw :刪除 游標下的字包含後面的空白 (英文斷字使用空白)
- di :刪除 游標下在雙引號裡的所有字不包含雙引號
- da :刪除 游標下在雙引號裡的所有字不包含雙引號
- di(, di) :刪除 游標下在小括號裡的所有字不包含雙引號
- da(, da) :刪除 游標下在小括號裡的所有字包含雙引號
建議自己把 :help motion.txt 翻一翻,找出自己常用的 text object 看一看
,寫成一個 cheat sheet
雖然 vim 定義了大量的 text object,但可能大部分都不是你想要的,那就透過
plugin 來滿足需求吧。
# 簡單好用的 vim-textobj-user
kana 所發展的 kana/vim-textobj-user[1] 是一個 lib,讓使用者藉由這個 lib 輕鬆的
製作屬於自己的 text object,所以就有一些 plugin 基於此 lib 做出更多的
text object,這些 plugin 的名字通常都叫 vim-textobj-xxx 。
使用 plugin 的方法為:
- 安裝 kana/vim-textobj-user[1]
- 在 wiki[2] 裡查看自己所需的
text object plugin,並且安裝
舉例來說:我最常用的兩個 text object 是 comment 和 funtion parameter,
所以我選定 glts/vim-textobj-comment[3] 和 sgur/vim-textobj-parameter[4]
Plug 'kana/vim-textobj-user'
Plug 'glts/vim-textobj-comment'
Plug 'sgur/vim-textobj-parameter'
vim-textobj-comment 提供了:
- ic:comment 內容
- ac:comment 內容 + comment 符號
vim-textobj-parameter 提供了:
- i,:參數
- a,:參數符號 + 分隔符號 (也就是逗號)
# 更細膩的 text object - targets.vim
wellle/targets.vim[5] 把 text object 的種類拆成四類型:
- Pair text objects - ( ) { } [ ] < >
- Quote text objects - ' " `
- Separator text objects - , . ; : + - = ~ _ * # / | \ & $
- Argument text objects
- Tag text objects
Pair 和 Quote text objects 是 vim 原本就有的概念,Separator text objects
如其名,兩個 separator 之間的字就是 Separator text objects 了。
舉個使用情境:url GET 參數都用 & 所隔開,如果想刪除 & 之間的字那就用得上了
內建的 text object 使用了 i 和 a 做前輟,而 targets.vim 更為細膩,
提供了額外的 I 和 A 擴充原本的 i 和 a,再加上一層概念 n 和 l,
n 代表下一個,l 則代表上一個。
註:內建的 text object 都是以游標位置為準,沒上一個和下一個的概念
以 ) 做個舉例:
- i):包含括號裡的所有字
- I):包含括號裡的所有字,但括號裡兩邊的空白不包含
- a):包含括號和括號裡的所有字
- A):包含括號和括號裡的所有字還有兩邊括號外的空白
加上 n 和 l 的話就是下一個跟上一個
. 表示游標所在位置
https://i.imgur.com/a2prq5U.png
target.vim 提供的 text object 實在太多太複雜,所以很貼心的做了 cheat sheet[6]
# syntax 相關 text object
以上所提到的 text object 都是和程式語言較無相關的 text object。
程式語言相關的 text object,比如說 function, class, structure...等,
這些相關的 text object plugin 相對來說比較少見。
vim 並沒有提供一個介面直接拿取 syntax tree 的某一個 node,所以現在的所有
text object 的 plugin 都是靠 regex 或是其他字串比對的方式。假如想要一個
function 的 text object,就必須在每種語言都用 regex 或字串比對做一遍,
相當的麻煩,kana/vim-textobj-function[7] 就是一個例子,目前只提供三種語言,
並且每種語言實做一次。
一個 text object 為主的 plugin 想要集成所有的 syntax 相關 text object 變得
不太可能,所以這些 syntax 相關 text object plugin 通常都已一種語言為主,
或是附屬在某些語言 plugin 底下:
- vim-go 提供了 comment (ac, ic) 和 function (af, if) text object
- sgur/vim-textobj-parameter[8] 為 python syntax 相關的 text object
- mjbrownie/django-template-textobjects[9] 為 django-template 相關的
text object
# 救世主 treesitter
一個 text object 為主的 plugin 想要集成所有的 syntax 相關 text object
真的不可能達到嗎?
等到 Treesitter 被 neovim 整合完成後一切將變得簡單許多。
Treesitter 簡單來講就是個 parser,可以使用它建立 syntax tree,官方介紹如下:
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited
neovim 0.5 版的目標就是要將 treesitter 整合,完成之後將可在 neovim 裡使用
treesitter 相關的 api,拿到了 syntax tree, 要抓到 text object 變得容易許多。
別說做 text object plugin 了,連 syntax highlight, code folding 等相關 plugin
都可以不需倚賴 regex ,而目前已經有基於 treesitter 的 plugin 了:
nvim-treesitter/nvim-treesitter[10]
詳見 :help treesitter-parsers
# 結語
wellle/targets.vim 和 kana/vim-textobj-user 在開發上使用截然不同的方式,
前者定義好大量細膩的 text object,後者則是一個 lib,由使用者以此 lib 為基礎
在開發 plugin。
對我來說,內建的 text object 已經足夠強大幾乎滿足需求,只需要在做一點補強,
像是常用的 comment 和 funtion parameter 就沒有被 vim 定義。而 target.vim 大量
細膩的 text object 使用情境都比較特殊,所以我就選擇了 vim-textobj-user 陣營
——只選擇自己所需要的安裝,不會有多餘的功能。
nvim-treesitter/nvim-treesitter 倚賴 syntax tree 解決了使用 regex 開發
text object plugin 的麻煩,而且更精準,可以預見 neovim 0.5 完成後的未來,
syntax 相關的 text object plugin 將會被此 plugin 統一。
# Reference
- https://codeinthehole.com/tips/vim-text-objects/
- https://www.tandrewnichols.me/motions-operators-text-objects-introduction/
- :help 'motion.txt'
[1]: https://github.com/kana/vim-textobj-user
[2]: https://github.com/kana/vim-textobj-user/wiki
[3]: https://github.com/glts/vim-textobj-comment
[4]: https://github.com/sgur/vim-textobj-parameter
[5]: https://github.com/wellle/targets.vim
[6]: https://github.com/wellle/targets.vim/blob/master/cheatsheet.md
[7]: https://github.com/kana/vim-textobj-function
[8]: https://github.com/sgur/vim-textobj-parameter
[9]: https://github.com/mjbrownie/django-template-textobjects
[10]: https://github.com/nvim-treesitter/nvim-treesitter
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.167.73.202 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/Editor/M.1600782775.A.3FF.html
※ 編輯: as23041248 (118.167.73.202 臺灣), 09/22/2020 21:55:49
推
09/23 00:49,
4年前
, 1F
09/23 00:49, 1F
咦又是你,在vim版留言的人不多,感謝觀看文章囉
※ 編輯: as23041248 (118.167.73.202 臺灣), 09/23/2020 06:41:08
※ 編輯: as23041248 (118.167.73.202 臺灣), 09/23/2020 13:11:15
推
09/23 22:58,
4年前
, 2F
09/23 22:58, 2F
→
09/23 22:58,
4年前
, 3F
09/23 22:58, 3F
→
09/23 22:59,
4年前
, 4F
09/23 22:59, 4F
Dotfile 寫到這麼多 commit 真拼 期待你寫篇文章介紹 交流交流
※ 編輯: as23041248 (118.167.73.202 臺灣), 09/24/2020 02:04:53
※ 編輯: as23041248 (118.167.73.202 臺灣), 09/24/2020 02:05:35
推
09/24 09:05,
4年前
, 5F
09/24 09:05, 5F
其實我也沒講的很細,我盡量講精髓,因為還在更新的plug-in是隨時有可能在改變的,
但精髓一樣
※ 編輯: as23041248 (114.136.253.112 臺灣), 09/24/2020 09:13:10
Editor 近期熱門文章
PTT數位生活區 即時熱門文章