카테고리 없음

LEARN VIMSCRIPT THE HARD WAY 11-15

seul chan 2020. 3. 11. 22:07

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.
  1. Event

Vim offers many events like

  • Starting to edit a file that doens't exist
  • Reading a file
  • Switching a buffer's filetype setting
  • Not pressing a key for a certain amount of time
  • Entering insert mode
  • Exiting insert mode
  1. Pattern
:autocmd BufNewFile *.txt :write
  • Vim writes only bar.txt automatically, but doesn't write bar

Another Example

:autocmd BufWritePre *.html :normal gg=G
  • Then create a new file called foo.html and 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!
  • BufWritePre means 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 BufRead and BufNewFile.
:autocmd BufNeewFile,BufRead *.html setlocal nowrap

FileType Events

  • One of the most useful events: FileType event.
  • 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 foo and bar files, switch to foo and run following commands
:iabbrev <buffer> --- &mdash;

Then write following texts

Hello --- world.
  • Vim will replace --- only in foo file.

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 the Writing Buffer! message

  • And run the exact same autocommand again:

    :autocmd BufWrite * :echom "Writing Buffer!"
  • After :message again, you can see Writing Buffer! twice increased.

  • Vim has no way to know if you want it to replace or create.

The problem

  • Sourcing your ~/.vimrc file rereads the entire file: every time source your ~/.vimrc you'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 END

The indentation is insignificant

  • after :w and see :message, you can see "Foo" and "Bar".
:augroup testgroup
:   autocmd BufWrite * :echom "Baz"
:augroup END

Clearing Groups

  • If you want to clear a group, you can use autocmd! inside the group
:augroup testgroup
:   autocmd!
:   autocmd BufWrite * :echom "Cats"
:augroup END

Using Autocommands in your Vimrc

  • Can use this to add autocmd to ~/.vimrc that don't add a duplicate every time we source it.
augroup filetype_html
    autocmd!
    autocmd FileType html nnoremap <buffer> <localleader>f Vatzf
augroup END

Excersize

  • Try to figure out what the mapping in the last example does. (Vatzf)
    • V: visual mode for the line
    • at: a <tag></tag> block
    • zf: fold

Operator-Pending Mappings

  • An operator is a command that waits for you to enter a movement command like d, c, y below.
Keys   Operator   Movement
----   --------   -------------
dw     Delete     to next word
ci(    Change     inside parens
yt,    Yank       until comma

Movement 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 foo

Move 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>