Combine and Conquer in Vim

Combine and Conquer

Much of Vim’s power stems from the way that operators and motions can be combined. In this tip, we’ll look at how this works and consider the implications.

Operator + Motion = Action

The d{motion} command can operate on a single character (dl), a complete word (daw), or an entire paragraph (dap). Its reach is defined by the motion. The same goes for c{motion}, y{motion}, and a handful of others. Collectively, these commands are called operators. You can find the complete list by looking up :h operator , while Table 2, Vim's Operator Commands, on page 25, summarizes some of the more common ones.

Trigger Effect
c Change
d Delete
y Yank into register
g~ Swap case
gu Make lowercase
gU Make uppercase
> Shift right
< Shift left
= Autoindent
! Filter {motion} lines through an external program
Table 2—Vim’s Operator Commands

The g~, gu, and gU commands are invoked by two keystrokes. In each case, we can consider the g to be a prefix that modifies the behavior of the subsequent keystroke. See Meet Operator-Pending Mode, on page 27, for further discussion.

The combination of operators with motions forms a kind of grammar. The first rule is simple: an action is composed from an operator followed by a motion. Learning new motions and operators is like learning the vocabulary of Vim. If we follow the simple grammar rules, we can express more ideas as our vocabulary grows.

Suppose that we already know how to delete a word using daw, and then we learn about the gU command (see :h gU ). It’s an operator too, so we can invoke gUaw to convert the current word to SHOUTY case. If we then expand our vocabulary to include the ap motion, which acts upon a paragraph, then we find two new operations at our disposal: dap to delete, or gUap to make the whole paragraph shout.

Vim’s grammar has just one more rule: when an operator command is invoked in duplicate, it acts upon the current line. So dd deletes the current line, while >> indents it. The gU command is a special case. We can make it act upon the current line by running either gUgU or the shorthand gUU.

Extending Vim’s Combinatorial Powers

The number of actions that we can perform using Vim’s default set of operators and motions is vast. But we can expand these even further by rolling our own custom motions and operators. Let’s consider the implications.

Custom Operators Work with Existing Motions

The standard set of operators that ships with Vim is relatively small, but it is possible to define new ones. Tim Pope’s commentary.vim plugin provides a good example.2 This adds a command for commenting and uncommenting lines of code in all languages supported by Vim.

The commentary command is triggered by gc{motion}, which toggles commenting for the specified lines. It’s an operator command, so we can combine it with all of the usual motions. gcap will toggle commenting for the current paragraph. gcG comments from the current line to the end of the file. gcc comments the current line.

If you’re curious about how to create your own custom operators, start by reading :h :map-operator .

Custom Motions Work with Existing Operators

Vim’s standard set of motions is fairly comprehensive, but we can augment it further by defining new motions and text objects.

Kana Natsuno’s textobj-entire plugin is a good example.3 It adds two new text objects to Vim: ie and ae, which act upon the entire file.

If we wanted to autoindent the entire file using the = command, we could run gg=G (that is, gg to jump to the top of the file and then =G to autoindent everything from the cursor position to the end of the file). But if we had the textobj-entire plugin installed, we could simply run =ae. It wouldn’t matter where our cursor was when we ran this command; it would always act upon the entire file.

Note that if we had both the commentary and textobj-entire plugins installed, we could use them together. Running gcae would toggle commenting throughout the current file.

If you’re curious about how to create your own custom motions, start by reading :h omap-info .

結合與征服

Vim的強大功能在很大程度上源自於操作符和動作指令可以被組合使用的方式。在這個技巧中,我們將探討它是如何工作的,並考慮其含義。

操作符 + 動作 = 行動

d{motion}命令可以操作一個單獨的字符(dl)、一個完整的單詞(daw)或一個整個段落(dap)。其作用範圍由動作指令定義。c{motion}y{motion}以及其他一些命令同樣如此。這些命令統稱爲操作符。你可以通過查找:h operator找到完整列表,而第25頁的表2,Vim的操作命令,總結了一些更常見的操作符。

g~gugU命令通過兩次按鍵調用。在每種情況下,我們可以認爲g是一個修改後續按鍵行爲的前綴。更多討論見第27頁的遇見操作符-等待模式。

操作符與動作的組合形成了一種語法。第一條規則很簡單:一個行動由一個操作符後跟一個動作組成。學習新的動作和操作符就像學習Vim的詞彙一樣。如果我們遵循簡單的語法規則,隨着詞彙量的增長,我們可以表達更多的想法。

假設我們已經知道如何使用daw刪除一個單詞,然後我們學習了gU命令(見:h gU)。它也是一個操作符,所以我們可以調用gUaw將當前單詞轉換爲大寫。如果我們然後擴展我們的詞彙表包括ap動作,它作用於一個段落,那麼我們發現有兩個新的操作可用:dap刪除,或gUap使整個段落大寫。

Vim的語法只有另一條規則:當一個操作命令被重複調用時,它作用於當前行。所以dd刪除當前行,而>>縮進它。gU命令是一個特例。我們可以通過運行gUgU或簡寫gUU使其作用於當前行。

擴展Vim的組合能力

我們可以使用Vim默認的操作符和動作集合執行的動作數量是巨大的。但通過創建我們自己的自定義動作和操作符,我們可以進一步擴展這些功能。讓我們考慮一下其含義。

自定義操作符與現有動作兼容

隨Vim一起提供的標準操作符集相對較小,但定義新的操作符是可能的。Tim Pope的commentary.vim插件提供了一個很好的例子。這個插件爲Vim支持的所有語言中的代碼行添加了註釋和取消註釋的命令。

評論命令通過gc{motion}觸發,它爲指定的行切換註釋。這是一個操作命令,所以我們可以將它與所有常用的動作結合。gcap將切換當前段落的註釋。gcG從當前行評論到文件的末尾。gcc評論當前行。

如果你好奇如何創建你自己的自定義操作符,請開始閱讀:h :map-operator

自定義動作與現有操作符兼容

Vim的標準動作集相當全面,但我們可以通過定義新的動作和文本對象進一步增強它。

Kana Natsuno的textobj-entire插件是一個很好的例子。它爲Vim添加了兩個新的文本對象:ieae,它們作用於整個文件。

如果我們想使用=命令自動縮進整個文件,我們可以運行gg=G(即,gg跳到文件頂部然後=G從光標位置到文件末尾自動縮進一切)。但如果我們安裝了textobj-entire插件,我們可以簡單地運行=ae。當我們運行這個命令時,光標的位置無關緊要;它總是作用於整個文件。

注意,如果我們同時安裝了commentary和textobj-entire插件,我們可以將它們一起使用。運行gcae將切換整個當前文件的註釋。

如果你好奇如何創建你自己的自定義動作,請開始閱讀:h omap-info

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章