Difference between revisions of "Vim"

From Noah.org
Jump to navigationJump to search
 
(10 intermediate revisions by the same user not shown)
Line 3: Line 3:
  
 
Learning Vim is like learning short-hand. It seems crazy and cryptic at first, but given time Vim will become second nature. There are not many great books on Vim. It's best to start with the `vimtutor` which is installed wherever Vim in found. Just run `vimtutor`. Once you get comfortable I recommend [http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FHacking-Vim-Cookbook-Latest-Editor%2Fdp%2F1847190936%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1202672267%26sr%3D8-1&tag=wwwnoahorg-20&linkCode=ur2&camp=1789&creative=9325 Hacking Vim] for intermediate users.  
 
Learning Vim is like learning short-hand. It seems crazy and cryptic at first, but given time Vim will become second nature. There are not many great books on Vim. It's best to start with the `vimtutor` which is installed wherever Vim in found. Just run `vimtutor`. Once you get comfortable I recommend [http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FHacking-Vim-Cookbook-Latest-Editor%2Fdp%2F1847190936%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1202672267%26sr%3D8-1&tag=wwwnoahorg-20&linkCode=ur2&camp=1789&creative=9325 Hacking Vim] for intermediate users.  
 +
 +
== Diff current edits with original file ==
 +
 +
Modern Vim can use this command:
 +
<pre>
 +
DiffOrig
 +
</pre>
 +
Older Vim use this:
 +
<pre>
 +
:w !diff % -
 +
</pre>
 +
 +
== Diff current edits with original in git ==
 +
 +
<pre>
 +
function! s:DiffWithGITCheckedOut()
 +
  let filetype=&ft
 +
  diffthis
 +
  vnew | exe "%!git diff " . expand("#:p:h") . "| patch -p 1 -Rs -o /dev/stdout"
 +
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
 +
  diffthis
 +
endfunction
 +
com! DiffGIT call s:DiffWithGITCheckedOut()
 +
</pre>
  
 
== My .vimrc ==
 
== My .vimrc ==
Line 36: Line 60:
 
== The awesome power of :g -- global ex command execution based on pattern matches ==
 
== The awesome power of :g -- global ex command execution based on pattern matches ==
  
=== vim yank all lines matching a pattern ==
+
=== vim yank all lines matching a pattern ===
  
This copies and appends all lines that match the given pattern into the register, 'a'. When you capitalize a register name it appends rather than overwrites the given register.
+
This copies and appends all lines that match the given pattern into the register, 'a'. When you capitalize a register name it appends rather than overwrites the given register. You will want to clear the 'a' register before doing this, "ay0
  
 
<pre>
 
<pre>
Line 44: Line 68:
 
</pre>
 
</pre>
  
[http://www.vim.org/tips/tip.php?tip_id=227 :g]
+
Remember you can always reuse your last search just by using an empty pattern //. For example, you could search for /my_pattern/ and then later use that pattern. For example, if you searched for /PATTERN/ this will perform the same search and yank all lines containing that pattern into the 'a' register:
 +
 
 +
<pre>
 +
:g//y A
 +
</pre>
 +
 
 +
=== append unnamed register ===
 +
 
 +
<pre>
 +
:normal y0
 +
:normal "ay0
 +
:g//y A
 +
:let @" = @a
 +
:let @* = @a
 +
</pre>
 +
 
 +
=== more... ===
 +
 
 +
[http://vim.wikia.com/wiki/Power_of_g The Power of g]
 +
http://vim.wikia.com/wiki/Copy_the_search_results_into_clipboard Copy the search results into clipboard]
 +
 
 +
== Unicode, Latin1, utf-8, utf-16, utf-16le, utf-16be... ==
 +
 
 +
'''NOTE''', The instructions below are still useful, but the problem described below is most easily avoided simply by editing your '''~/.vimrc''' where you should add 'set encoding=utf-8' and check that 'fileencoding' is not set. In this case Vim should automatically detect the encoding and transparently translate back and forth between the document's encoding and Vim's utf-8 internal encoding.
 +
 
 +
If you open a file and it looks like every other character is noise then it means your Unicode settings are screwed up. Usually Vim will detect Unicode and set the encoding correctly. I have most often seen Vim get this wrong when the Unicode encoded file was saved on a platform with a different byte order (little-endian vs. big-endian).
 +
 
 +
In the example below the first two blank characters are probably the BOM (Byte Order Marker).
 +
<pre>
 +
  T^@h^@e^@ ^@a^@b^@o^@v^@e^@ ^@c^@o^@p^@y^@r^@i^@g^@h^@t^@ ^@n^@o^@t^@i^@c^@e^@
 +
</pre>
 +
 
 +
Examples showing the encoding settings. The first one is bad.
 +
<pre>
 +
:echo &encoding
 +
latin1
 +
:echo &encoding
 +
utf-8
 +
</pre>
 +
 
 +
'''NOTE''', Vim made this totally confusing. These two samples below actually handle the problem in two different ways. Originally I thought it was just different style and syntax for the same operation. But I was confused because the end results were similar, but not identical, so I knew these operations couldn't be exactly the same. The '''++enc''' command is a very stupid name because it makes it seem related to '''set enc=utf-16le'''. But, in fact, '''++enc=utf-16le''' does not set the '''encoding''' option, it sets the '''fileencoding''' option! ... I like the Vim paradigm, but internally Vim does a lot of things to piss me off.
 +
 
 +
From the command-line use this command to open the file.
 +
<pre>
 +
vim --cmd "set enc=utf-16le" ppc_gpio_test.py
 +
</pre>
 +
Or, from inside Vim run this command:
 +
<pre>
 +
:e ++enc=utf-16le ppc_gpio_test.py
 +
</pre>
 +
Or, from inside Vim you can set '''fileencoding'''.
 +
<pre>
 +
:set fileencoding=ascii
 +
:w
 +
</pre>
 +
 
 +
When using the command-line form I get this:
 +
<pre>
 +
&lt;feff&gt;The above copyright notice
 +
</pre>
 +
 
 +
When using the command from within Vim I get this:
 +
<pre>
 +
The above copyright notice
 +
</pre>
 +
 
 +
The command-line form seems to give a more correct file. It preserves special graphic characters better. Opening from within Vim looses characters often used to draw boxes. I suspect there is some additional conflict with my '''.vimrc''' file that is causing this.
 +
 
 +
== delete without saving last line in unnamed register ==
 +
 
 +
I use '''dd''' and '''p''' or '''P''' quite a lot to move lines. Sometimes I do a '''dd''' to delete a line and then I realize I want to delete another line, but I don't want to loose the first line that is now saved in the unnamed register. Simply type underscore '''_''' before typing '''dd''':
 +
<pre>
 +
_dd
 +
</pre>
  
 
== Run a macro on matching lines ==
 
== Run a macro on matching lines ==
Line 58: Line 155:
 
<pre>
 
<pre>
 
:g!/<pattern>/normal @q
 
:g!/<pattern>/normal @q
 +
</pre>
 +
 +
== Vim regular expressions ==
 +
 +
CSS color numbers. CSS is stupid because it does not allow you to define constants. This causes a lot of headaches when trying to update all colors. This regex will match the HEX color numbers for both three digit form and six digit form.
 +
 +
<pre>
 +
/#[0-9a-fA-F]\{3,6\}/
 
</pre>
 
</pre>
  

Latest revision as of 15:37, 17 May 2015

Vi is an archaic text editor that has survived since before the early dawn of the computer age. Vi continues to evolve and adapt in the form of Vim; although, it still retains its reptilian skin to remind us of its primitive past.

Learning Vim is like learning short-hand. It seems crazy and cryptic at first, but given time Vim will become second nature. There are not many great books on Vim. It's best to start with the `vimtutor` which is installed wherever Vim in found. Just run `vimtutor`. Once you get comfortable I recommend Hacking Vim for intermediate users.

Diff current edits with original file

Modern Vim can use this command:

DiffOrig

Older Vim use this:

:w !diff % -

Diff current edits with original in git

function! s:DiffWithGITCheckedOut()
  let filetype=&ft
  diffthis
  vnew | exe "%!git diff " . expand("#:p:h") . "| patch -p 1 -Rs -o /dev/stdout"
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
  diffthis
endfunction
com! DiffGIT call s:DiffWithGITCheckedOut()

My .vimrc

This is a link to my super-terrific .vimrc file.

   .vimrc

You can also see the entire .vimrc file at the end of this article: #.vimrc.

To make full use of this you also want the .vim directory and everything below it.

I tried to balance vi compatibility and Vim features. I didn't want to make my vim so custom and unique that I would go crazy when I had to go back to a machine without my custom Vim. I tried to add some really useful features, but keep Vim familiar. Some have customized Vim so much that it is nearly unrecognizable (see Cream).

Temptations

It's very tempting to remap lots of keys, but this temptation can quickly get out of control. For example, I would like a little bit of emacs compatibility (CTRL-A and CTRL-E for beginning and end of line); an inverted T for cursor control would be better than HJKL cursor control; the redo key should be r not Control-R. But after a while you would not be able to use a stock Vim installation. This happened to me when I first learned Emacs. I had my own version of Emacs so tweaked that I forgot how to use the default key bindings. I avoid most temptations to "fix" Vim. It's better to stick with stock.

But I have made a few small concessions to sanity that deviate from the default Vim key mappings. The following .vimrc settings change Vim's default behavior.


Q

I mapped this to replay a recording named 'q'. My typical habit is to type qq to start a recording named 'q'. Then I type Q to replay the recording named 'q'. By default Q puts you in ex mode. When have I ever needed to use ex mode? Never.

<up> and <down>

These are mapped to do gk and gj, which move the cursor up and down based on the display rows. The difference is subtle. It's useful for editing 1000 character long lines with wrap set. The j and k keys still do the normal up and down. Only the arrow keys <up> and <down> are effected.

The awesome power of :g -- global ex command execution based on pattern matches

vim yank all lines matching a pattern

This copies and appends all lines that match the given pattern into the register, 'a'. When you capitalize a register name it appends rather than overwrites the given register. You will want to clear the 'a' register before doing this, "ay0

:g/pattern/y A

Remember you can always reuse your last search just by using an empty pattern //. For example, you could search for /my_pattern/ and then later use that pattern. For example, if you searched for /PATTERN/ this will perform the same search and yank all lines containing that pattern into the 'a' register:

:g//y A

append unnamed register

:normal y0
:normal "ay0
:g//y A
:let @" = @a
:let @* = @a

more...

The Power of g http://vim.wikia.com/wiki/Copy_the_search_results_into_clipboard Copy the search results into clipboard]

Unicode, Latin1, utf-8, utf-16, utf-16le, utf-16be...

NOTE, The instructions below are still useful, but the problem described below is most easily avoided simply by editing your ~/.vimrc where you should add 'set encoding=utf-8' and check that 'fileencoding' is not set. In this case Vim should automatically detect the encoding and transparently translate back and forth between the document's encoding and Vim's utf-8 internal encoding.

If you open a file and it looks like every other character is noise then it means your Unicode settings are screwed up. Usually Vim will detect Unicode and set the encoding correctly. I have most often seen Vim get this wrong when the Unicode encoded file was saved on a platform with a different byte order (little-endian vs. big-endian).

In the example below the first two blank characters are probably the BOM (Byte Order Marker).

  T^@h^@e^@ ^@a^@b^@o^@v^@e^@ ^@c^@o^@p^@y^@r^@i^@g^@h^@t^@ ^@n^@o^@t^@i^@c^@e^@

Examples showing the encoding settings. The first one is bad.

:echo &encoding
latin1
:echo &encoding
utf-8

NOTE, Vim made this totally confusing. These two samples below actually handle the problem in two different ways. Originally I thought it was just different style and syntax for the same operation. But I was confused because the end results were similar, but not identical, so I knew these operations couldn't be exactly the same. The ++enc command is a very stupid name because it makes it seem related to set enc=utf-16le. But, in fact, ++enc=utf-16le does not set the encoding option, it sets the fileencoding option! ... I like the Vim paradigm, but internally Vim does a lot of things to piss me off.

From the command-line use this command to open the file.

vim --cmd "set enc=utf-16le" ppc_gpio_test.py

Or, from inside Vim run this command:

:e ++enc=utf-16le ppc_gpio_test.py

Or, from inside Vim you can set fileencoding.

:set fileencoding=ascii
:w

When using the command-line form I get this:

<feff>The above copyright notice

When using the command from within Vim I get this:

The above copyright notice

The command-line form seems to give a more correct file. It preserves special graphic characters better. Opening from within Vim looses characters often used to draw boxes. I suspect there is some additional conflict with my .vimrc file that is causing this.

delete without saving last line in unnamed register

I use dd and p or P quite a lot to move lines. Sometimes I do a dd to delete a line and then I realize I want to delete another line, but I don't want to loose the first line that is now saved in the unnamed register. Simply type underscore _ before typing dd:

_dd

Run a macro on matching lines

After you record a macro it's easy to play it back on lines that match a pattern (example assumes a macro recorded as 'q'):

:g/<pattern>/normal @q

Or run the macro on lines that don't match:

:g!/<pattern>/normal @q

Vim regular expressions

CSS color numbers. CSS is stupid because it does not allow you to define constants. This causes a lot of headaches when trying to update all colors. This regex will match the HEX color numbers for both three digit form and six digit form.

/#[0-9a-fA-F]\{3,6\}/

Folding

Most folding is complicated and bothersome. These notes describe easy Vim folding.

My favorite trick is to fold on the current /search/ pattern. This way I can see only the lines that contain what I'm searching for. This is handy even for regular text documents, not just code.

set foldexpr=getline(v:lnum)!~@/
set foldmethod=expr foldlevel=0 foldcolumn=1

To make life easy, I map that to a key sequence \z (The <leader> character is the \ key on most systems).

map <silent><leader>z :set foldexpr=getline(v:lnum)!~@/ foldlevel=0 foldcolumn=0 foldmethod=expr<CR>

When I fold code, I just want show class, method, and function names. I just want an index view of my code. I don't want to fold on every nested statement, so I only need one level of folding. I add a map so that I can quickly set the search pattern to find all classes and functions. The following search pattern works for both PHP and Python:

/^\s*class\s\\|^\s*function\s\\|^\s*def\s/

I combine this with the search folding trick so that I can quickly fold code without the bother of syntax files or nested folding regions.

Finally, I add a map so that the SPACE key will toggle the hide/show state of the fold under the cursor.

To use these tips together, in normal mode type "zff" to highlight all classes and functions. Then type "\z" to fold. Now the document looks like an index. Press SPACE to view a class or function.

Put the following in your .vimrc file:

" folding using /search/ pattern
" \z
" This folds every line that does not contain the search pattern.
" see vimtip #282 and vimtip #108
map <silent><leader>z :set foldexpr=getline(v:lnum)!~@/ foldlevel=0 foldcolumn=0 foldmethod=expr<CR>
" this folds all classes and function to create a code index.
" mnemonic: think "function fold"
map zff :/^\s*class\s\\|^\s*function\s\\|^\s*def\s/<CR>:set foldmethod=expr foldlevel=0 foldcolumn=1<CR><CR>
" space toggles the fold state under the cursor.
nnoremap <silent><space> :exe 'silent! normal! za'.(foldlevel('.')?'':'l')<cr>

Intermediate Vim

help

Vim has very complete help, but it can be difficult to search because of the ambiguous matches on many commands. Usually it helps to specify the context (normal mode, insert mode, command-line command, etc.)

        WHAT                  PREPEND    EXAMPLE
    Normal mode command      (nothing)   :help x
    Visual mode command         v_       :help v_u
    Insert mode command         i_       :help i_<Esc>
    Command-line command        :        :help :quit
    Command-line editing        c_       :help c_<Del>
    Vim command argument        -        :help -r
    Option                      '        :help 'textwidth'

Modeline

A modeline is a magic comment embedded in a document that tells Vim how to set preferences. Modelines contain set commands. By default the modeline must appear in the first five or last five lines of a file.

:help modeline

Dumb Vim commands that I actually use

These are commands that I thought seemed pretty lame when I first learned them. I thought that I would forget them quickly, yet for some reason I find that I keep using them.

CTRL-A CTRL-X

This increments a number to the right of the cursor. I thought this was totally pointless when I first saw it; yet, I seem to use it a lot.

 :h i_CTRL-A

CTRL-X does the opposite -- it decrements a number to the right of the cursor.

CTRL-O

This executes one command then returns to Insert mode. For example, if you want to reformat the paragraph you are editing type:

 CTRL-Ogwap

I tend to forget about the insert mode commands.

 :h i_CTRL-O

CTRL-W

This backspaces an entire word in insert mode.

 :h i_CTRL-W

Recording keystrokes

When you record a sequence of keystrokes using q these go into a register. You can paste the register and edit the recording then Yank the lines back into a register and play it back. This is handy if you have a long recording that you want to fix.

Visual mode range

Pressing v, V, or <C-v> in normal mode will switch to visual mode. This lets you select lines visually. If you go out of visual mode and want to return to visual mode with the same range that you had selected previously then type:

 gv

Run macro recording on a visual range

After you record a macro you may want to run the macro for each line in a range. For example, if your macro recording is store in register q then select a visual range and type:

 :'<,'>normal @q

To run the macro on every line in the file:

 :%normal @q

filename-modifiers

In Vim scripting you can refer to a the current working filename using %. For example, to make a backup copy of the current file do this:

silent! execute '!cp % %.bak'

There are also modifiers to filenames that allow you to just refer to the extension (%:e) of the filename before the extension (%:r). For example, the following makes a backup but changes the extension:

silent! execute '!cp % %:r.bak'


See help for more info:

:h filename-modifiers

Vim scripting setting option values -- set versus let

Many people confuse set and let. 'let' can do more than 'set'. 'set; is the older vi-compatile way to set options. 'let' is the Vim-way to set options, variables, environment variables, etc. With 'let' you must put & in front of option names. This shows 'set' and 'let' both setting an option:

set textwidth = 79
let &textwidth = 79

Boolean options are set to 1 for true and 0 for false. With 'set' you can prepend "no" in front of the option name to set it to false. These two lines are equivalent:

set noautoindent
let &autoindent = 0

'set' allows multiple options to be set at once:

set et sr ts=4 sw=4

Set GVim as the default editor in Gnome

You can set GVim as the default editor for all users by editing /etc/gnome/defaults.list and doing a search-and-replace for 'gedit.desktop' with 'gvim.desktop'. This saves you the hassle of having to set GVim as the default editor for each file type individually.

You can also set this for each individual user by editing or creating a file ~/.local/share/applications/defaults.list and adding these lines:

[Default Applications]
text/plain=gvim.desktop

Vim Cheat Sheet

VIM Cheat SheetClick to view this handy VIM cheat sheet. This was taken from ViEmu -- home of vi/vim emulation for Microsoft Visual Sutdio.

.vimrc

<include svncat src="file:///home/svn/src/dotfiles/.vimrc" />