Advanced Motions
Once the fundamental key bindings are understood, you can start developing fast vim motions. This starts with understanding Text Objects.
Text Objects
With the standard operator-motion the command acts on the specific cursor position. For example, dw
deletes the word starting from your cursor position, not the entire word your cursor sits on. This means that if you position in the middle of a word and press dw
you will only delete half of it. Having to position cursors precisely for proper actions puts a bottleneck on movement and operation speed. Text objects broadens the scope from cursor position to the object of interest - instead of w
you have aw
for "a word" allowing the command daw
to delete the word regardless of how the cursor is positioned on it. This is called operator-text object.
To change a whole sentence regardless of cursor position, you use cis
. The change operator acts on the text object is
which stands for "inner sentence". This is not be confused with changing the entire line - if you have multiple sentences on one line, it only acts on the sentence you are on. If you have another sentence after the one you delete and you do not want a whitespace there you may consider using as
. The text object as
stands for "a sentence" which compared to is
includes the white space after the sentence.
The key difference between a
and i
is more nuanced than just whitespace:
i
(inner): The text object itself, excluding delimiters/boundariesa
(around/a): The text object plus its surrounding delimiters/boundaries
This is fundamentally about delimiters and boundaries, not just whitespace. For example:
i"
= content inside quotes (excluding the quotes)a"
= content plus the quote marksi)
= content inside parenthesesa)
= content plus the parentheses
For words specifically:
iw
= just the word charactersaw
= the word plus trailing whitespace (or leading if no trailing)
Remember: "a"round includes the boundaries, "i"nside excludes them.
There are a long list of text objects. The ones to get familiar with for now are:
Words & Sentences:
w
/aw
/iw
- wordW
/aW
/iW
- WORD (capital W)s
/as
/is
- sentencep
/ap
/ip
- paragraph
Quotes & Brackets:
"
/a"
/i"
- double quotes'
/a'
/i'
- single quotes`
/a`
/i`
- backticks(
or)
/a(
/i(
- parentheses[
or]
/a[
/i[
- square brackets{
or}
/a{
/i{
- curly braces<
or>
/a<
/i<
- angle brackets
Word vs WORD (w vs W)
The distinction between lowercase "w" and uppercase "W" is crucial for practical editing.aw
(a word): Selects words defined byiskeyword
setting - typically letters, digits, and underscores. Stops at punctuation and whitespace.aW
(a WORD): Selects any sequence of non-whitespace characters separated by whitespace, including punctuation.
Why capital W is essential:
filename.txt config-file.json user@domain.com /path/to/file
-
daw
on "filename.txt" only deletes "filename" (stops at the dot) -
daW
on "filename.txt" deletes the entire "filename.txt" ✨ -
daw
on "config-file.json" only deletes "config" (stops at the hyphen) -
daW
on "config-file.json" deletes "config-file.json" ✨
Use capital W text objects when working with filenames, URLs, email addresses, or any text containing punctuation that you want to treat as a single unit.
Many beginners get frustrated trying to delete filenames or URLs with daw
- remember to use daW
for complete non-whitespace sequences!
Visual Mode
With text objects, now you can select whole sentences or lines inside parenthesis without needing to do a lot of cursor moving and combos! For example, to select all the arguments in the function parenthesis, just type vi(
:
def baz(arg1, arg2, arg3, arg4):
pass
Then you can just either delete it with d
or use c
change operator to delete it and start modifying in insert mode! If you are not within a parenthesis or bracket, vi{
or vi(
will just jump you to the next one in the line, which is actually a neat feature. You can also use yi{
to yank something inside a bracket, then vaw
to select a word, and then p
to paste over that word. As you can see, you can combine text objects with visual mode selection to do a lot of actions.
The capital V
is actually also powerful for dealing with selection linewise as opposed to character-wise with v
. For instance, if you wanted to select the entire file contents, ggvG
will only select up to the start of the last line, because it operates by character. The solution is ggVG
which selects all lines in the file! Or if you want to grab all 4 lines below V4j
is much better than v4j$
.
Other Motion Patterns
Beyond text objects, there are other powerful motion patterns that complement advanced editing workflows.
Till and Find Motions
These motions allow you to jump to specific characters on the current line:
Find motions (f/F):
f{char}
- jump forward to next occurrence of character (inclusive)F{char}
- jump backward to previous occurrence of character (inclusive)
Till motions (t/T):
t{char}
- jump forward till (before) next occurrence of characterT{char}
- jump backward till (after) previous occurrence of character
Common patterns:
dt,
- delete till next comma (useful for function parameters)ct.
- change till next period (sentence editing)dF(
- delete back through previous opening parenthesisdf;
- delete through next semicolon (including the semicolon)
Combining with text objects:
function example(arg1, arg2, arg3) {
return processData(arg1);
}
F(vi(
- jump to previous(
, then select inner parentheses contentf"ci"
- jump to next"
, then change inside quotest,caw
- jump till comma, then change a word
Use t
motions when you want to preserve the target character (like commas in parameter lists), and f
motions when you want to include/delete the character.
After using f
, F
, t
, or T
, you can repeat the motion with ;
(forward) or ,
(backward).
Practical Workflow Examples
These patterns become powerful when chained together:
-
Refactoring function calls:
F(ci(
- jump to opening parenthesis, change inside
-
Editing lists/arrays:
f[vi[
- jump to bracket, select inner contentt,daw
- jump till comma, delete word (removing parameter)
-
Text editing:
T"vt"
- select from after previous quote till before next quotedt:
- delete till colon (useful for key-value editing)
Resources
For more information on advanced vim motions, I highly recommend consulting videos like this one, where they walk you through what the advanced vim motions actually look and feel like.
I also found a fun game you can play that makes you practice your vim motions, it's cool!