LEARN VIMSCRIPT THE HARD WAY 11-15
Autocommands
- Autocommands are a way to tell Vim to run certain commands whenever certain event happen
:autocmd BufNewFile * :write- With this command, vim will automatically create thefile
Autocommand Structure
:autocmd BufNewFile * :write
^ ^ ^
| | |
| | The command to run.
| |
| A "pattern" to filter the event.
|
The "event" to watch for.- Event
Vim offers many events like
- Starting to edit a file that doens't exist
- Reading a file
- Switching a buffer's
filetypesetting - Not pressing a key for a certain amount of time
- Entering insert mode
- Exiting insert mode
- Pattern
:autocmd BufNewFile *.txt :write- Vim writes only
bar.txtautomatically, but doesn't writebar
Another Example
:autocmd BufWritePre *.html :normal gg=G- Then create a new file called
foo.htmland enter following text exactly including whitespace
<html>
<body>
<p>Hello!</p>
</body>
</html>- When save this file with
:w, Vim seems to have reindented the file before saving it! BufWritePremeans the event will be checked just before you write any file
Multiple Events
example
:autocmd BufWritePre,BufRead *.html :normal gg=G- A common idiom in Vim scripting is
BufReadandBufNewFile.
:autocmd BufNeewFile,BufRead *.html setlocal nowrapFileType Events
- One of the most useful events:
FileTypeevent. - This event is fierd whenever Vim set a buffer`s
FileType
:autocmd FileType javascript nnoremap <buffer> <localleader>c I//<esc>
:autocmd FileType python nnoremap <buffer> <localleader>c I#<esc>Exercises
- Skim
:help autocmd-events
Buffer-Local Abbreviations
- Open
fooandbarfiles, switch tofooand run following commands
:iabbrev <buffer> --- —Then write following texts
Hello --- world.- Vim will replace
---only infoofile.
Autocommands and Abbreviations
:autocmd FileType python :iabbrev <buffer> iff if:<left>Autocommand Group
:autocmd BufWrite * :echom "Writing Buffer!"Now write the buffer (
:w) and run:message, you can see theWriting Buffer!messageAnd run the exact same autocommand again:
:autocmd BufWrite * :echom "Writing Buffer!"After
:messageagain, you can seeWriting Buffer!twice increased.Vim has no way to know if you want it to replace or create.
The problem
- Sourcing your
~/.vimrcfile rereads the entire file: every time source your~/.vimrcyou'll be duplicating autocommand - Will make vim run slower
Grouping Autocommands
- Vim has a solution to the problem: group related autocommands
:augroup testgroup
: autocmd BufWrite * :echom "Foo"
: autocmd BufWrite * :echom "Bar"
:augroup ENDThe indentation is insignificant
- after
:wand see:message, you can see"Foo"and"Bar".
:augroup testgroup
: autocmd BufWrite * :echom "Baz"
:augroup ENDClearing Groups
- If you want to clear a group, you can use
autocmd!inside the group
:augroup testgroup
: autocmd!
: autocmd BufWrite * :echom "Cats"
:augroup ENDUsing Autocommands in your Vimrc
- Can use this to add autocmd to
~/.vimrcthat don't add a duplicate every time we source it.
augroup filetype_html
autocmd!
autocmd FileType html nnoremap <buffer> <localleader>f Vatzf
augroup ENDExcersize
- Try to figure out what the mapping in the last example does. (
Vatzf)V: visual mode for the lineat: a<tag></tag>blockzf: fold
Operator-Pending Mappings
- An operator is a command that waits for you to enter a movement command like
d,c,ybelow.
Keys Operator Movement
---- -------- -------------
dw Delete to next word
ci( Change inside parens
yt, Yank until commaMovement mapping
You can create new movements.
- Example
Let's make a example movement for inner parentheses (())
:onoremap p i(And with the line below, and put the cursor in cat and type dp.
return person.get_pets(type="cat", fluffy_only=True)The whole text inside the parentheses are deleted.
You can use p with other operators as well like cp or yp.
- Other example
:onoremap b /return<cr>And write text below
def count(i):
i += 1
print i
return fooMove the cursor to i in the second line, and type db. Vim automatically remove all the body until the return.
Changing the start
For the last example with dp, you have to move the cursor to inside the parentheses. Let's make for the operator that can used in whole line.
:onoremap in( :<c-u>normal! f(vi(<cr>Also, write or copy the text that we used before.
return person.get_pets(type="cat", fluffy_only=True)Move the cursor whereever you want in the line - like p in person. When type cin(, you can see whole text inside parentheses was deleted.
You can think of this mapping as meaning "inside next parentheses", and it will perform the operator on the text inside the next set of parentheses on the current line.
Let's make inside last parentheses too.
:onoremap il( :<c-u>normal! F)vi(<cr>Now, you can use the motion il( for find the last parentheses backwards.
Exercises
- Create operator-pending mappings for "around next parentheses" and "around last parentheses".
:onoremap an( :<c-u>normal! f(va)<cr>
:onoremap al( :<c-u>normal! F)va(<cr>- Create similar mappings for in/around next/last for curly brackets.
# in next curly brackets
:onoremap in{ :<c-u>normal! f{vi}<cr>
# around next curly brackets
:onoremap an{ :<c-u>normal! f{va}<cr>
# in last curly brackets
:onoremap il{ :<c-u>normal! F}vi{<cr>
# around last curly brackets
:onoremap al{ :<c-u>normal! F}va{<cr>- Read :help omap-info and see if you can puzzle out what the
in the examples is for.
The CTRL-U (
) is used to remove the range that Vim may insert
# example for find the next function name in the current line
:onoremap <silent> F :<c-u>normal! 0f(hviw<c-r>