From WhyNotWiki
Jump to: navigation, search


About / Defense of / etc.

[1] [2] Google Speaker Series: introducing Open Source Developer Bram Moolenaar

Seven Habits of Effective Editing 2.0

Why do [I (category)] use it?


  • 1. Because it lets you use single-key commands.
  • Because it is very customizable/automatable/scriptable/configurable.
  • Great regular expression search and search and replace
  • Great syntax highlighting

Unfortunately, it uses an ugly, proprietary scripting language. If a good alternative to vim popped up that used, say, Ruby as its scripting language I would jump ship in an instant.

Reference links

  • vim_tutorial.pdf


:help options

Vim has a number of internal variables and switches which can be set to achieve special effects. :set ...

You can get the current value of an option and store it in a variable:

  let old_indentexpr  = &indentexpr
  let &indentexpr = ''

:help expr-option

option                                          *expr-option* *E112* *E113*
&option                     option value, local value if possible
&g:option           global option value
&l:option           local option value

Predefined Vim variables

Predefined Vim variables:                       *vim-variable* *v:var*

v:fname_new     The name of the new version of the file.  Only valid while
                evaluating 'diffexpr'.

                                        *v:fname_diff* *fname_diff-variable*
v:fname_diff    The name of the diff (patch) file.  Only valid while
                evaluating 'patchexpr'.

                                        *v:folddashes* *folddashes-variable*
v:folddashes    Used for 'foldtext': dashes representing foldlevel of a closed
                Read-only. |fold-foldtext|


                                *v:this_session* *this_session-variable*
v:this_session  Full filename of the last loaded or saved session file.  See
                |:mksession|.  It is allowed to set this variable.  When no
                session file has been saved, this variable is empty.
                "this_session" also works, for backwards compatibility.

                                        *v:throwpoint* *throwpoint-variable*
v:throwpoint    The point where the exception most recently caught and not
                finished was thrown.  Not set when commands are typed.  See
                also |v:exception| and |throw-variables|.
                Example: >
        :  throw "oops"
        :catch /.*/
        :  echo "Exception from" v:throwpoint
<            Output: "Exception from test.vim, line 2"

                                        *v:version* *version-variable*
v:version       Version number of Vim: Major version number times 100 plus
                minor version number.  Version 5.0 is 500.  Version 5.1 (5.01)
                is 501.  Read-only.  "version" also works, for backwards
                Use |has()| to check if a certain patch was included, e.g.: >
                        if has("patch123")
<            Note that patch numbers are specific to the version, thus both
                version 5.0 and 5.1 may have a patch 123, but these are
                completely different.


There are nine types of registers:                      *registers* *E354*
1. The unnamed register ""
2. 10 numbered registers "0 to "9
3. The small delete register "-
4. 26 named registers "a to "z or "A to "Z
5. four read-only registers ":, "., "% and "#
6. the expression register "=
7. The selection and drop registers "*, "+ and "~ 
8. The black hole register "_
9. Last search pattern register "/

4. Named registers "a to "z or "A to "Z                     *quote_alpha* *quotea*
Vim fills these registers only when you say so.  Specify them as lowercase
letters to replace their previous contents or as uppercase letters to append
to their previous contents.

5. Read-only registers ":, "., "% and "#
These are '%', '#', ':' and '.'.  You can use them only with the "p", "P",
and ":put" commands and with CTRL-R.  {not in Vi}
                                                *quote_.* *quote.* *E29*
        ". Contains the last inserted text (the same as what is inserted
                with the insert mode commands CTRL-A and CTRL-@).  Note: this
                doesn't work with CTRL-R on the command-line.  It works a bit
                differently, like inserting the text instead of putting it
                ('textwidth' and other options affect what is inserted).
                                                        *quote_%* *quote%*
        "% Contains the name of the current file.
                                                        *quote_#* *quote#*
        "# Contains the name of the alternate file.
                                                *quote_:* *quote:* *E30*
        ": Contains the most recent executed command-line.  Example: Use
                "@:" to repeat the previous command-line command.
                The command-line is only stored in this register when at least
                one character of it was typed.  Thus it remains unchanged if
                the command was completely from a mapping.
                {not available when compiled without the |+cmdline_hist|


8. Black hole register "_                          *quote_*
When writing to this register, nothing happens.  This can be used to delete
text without affecting the normal registers.  When reading from this register,
nothing is returned.  {not in Vi}

9. Last search pattern register "/                 *quote_/* *quote/*
Contains the most recent search-pattern.  This is used for "n" and 'hlsearch'.
It is writable with ":let", you can change it to have 'hlsearch' highlight
other matches without actually searching.  You can't yank or delete into this
register.  {not in Vi}

You can write to a register with a ":let" command |:let-@|.  Example: >
        :let @/ = "the"

Reading and writing registers

register                                                *expr-register*
@r                      contents of register 'r'

The result is the contents of the named register, as a single string.
Newlines are inserted where required.  To get the contents of the unnamed
register use @" or @@.  The '=' register can not be used here.  See
|registers| for an explanation of the available registers.

:let @{reg-name} = {expr1}                      *:let-register* *:let-@*
                        Write the result of the expression {expr1} in register
                        {reg-name}.  {reg-name} must be a single letter, and
                        must be the name of a writable register (see
                        |registers|).  "@@" can be used for the unnamed
                        register, "@/" for the search pattern.
                        If the result of {expr1} ends in a <CR> or <NL>, the
                        register will be linewise, otherwise it will be set to
                        This can be used to clear the last search pattern: >
                                :let @/ = ""
<                    This is different from searching for an empty string,
                        that would match everywhere.

Scripting in vim

Useful functions/commands

:echo fnamemodify("main.c", ":p:h")

Pre-made scripts/plugins winmanager - A windows style IDE for Vim 6.0 : vim online taglist.vim - Source code browser (supports C/C++, java, perl, python, tcl, sql, php, etc) : vim online Vim Taglist plugin


This is for general usage tips (not script-writing tips). Tip #305 - Best of VIM Tips (VIM's best Features) : vim online [To do: {{{1}}}]

Listing settings

:history          : list of all your commands 

How to capitalize a whole word

Go to beginning of word and type:


Moving around (moving the cursor)

gg               : Beginning
G                : End

<C-O>            : retrace your movements in file (old)
<C-I>            : retrace your movements in file (new)
:help jump-motions

(                       [count] sentences backward.  |exclusive| motion.
)                       [count] sentences forward.  |exclusive| motion.
{                       [count] paragraphs backward.  |exclusive| motion.
}                       [count] paragraphs forward.  |exclusive| motion.

# Markers
`< , `> -- jump to beginning/end of (visual) selection
'.               : jump to last modification line (SUPER)
`.               : jump to exact spot in last modification line


(changing the viewpoint/interacting with the "scroll bars")

you can scroll up/down with C-y and C-e

How to make vim show hidden characters

        '$' indicates EOL
        '^I' indicates tabspace

    To visualize non-printing control characters hidden in a file, do
        ':set list'
        ':set nolist'   #toggles back to normal mode 
        ':set invlist'  #toggles

Text object selection

help object-select / :help text-objects
This is a series of commands that can only be used while in Visual mode or
after an operator.  The commands that start with "a" select "a"n object
including white space, the commands starting with "i" select an "inner" object
without white space, or just the white space.  Thus the "inner" commands
always select less text than the "a" commands.

These commands are {not in Vi}.
These commands are not available when the |+textobjects| feature has been
disabled at compile time.
aw                      "a word", select [count] words (see |word|).
                        Leading or trailing white space is included, but not

iw                      "inner word", select [count] words (see |word|).

aW                      "a WORD", select [count] WORDs (see |WORD|).
                        Leading or trailing white space is included, but not

iW                      "inner WORD", select [count] WORDs (see |WORD|).

as                      "a sentence", select [count] sentences

is                      "inner sentence", select [count] sentences (see
                        When used in Visual mode it is made characterwise.

                                                        *v_ap* *ap*
ap                      "a paragraph", select [count] paragraphs (see
                        Exception: a blank line (only containing white space)
                        is also a paragraph boundary.
                        When used in Visual mode it is made linewise.

                                                        *v_ip* *ip*
ip                      "inner paragraph", select [count] paragraphs (see
                        Exception: a blank line (only containing white space)
                        is also a paragraph boundary.
                        When used in Visual mode it is made linewise.

a]                                              *v_a]* *v_a[* *a]* *a[*
a[                      "a [] block", select [count] '[' ']' blocks.  This
                        goes backwards to the [count] unclosed '[', and finds
                        the matching ']'.  The enclosed text is selected,
                        including the '[' and ']'.
                        When used in Visual mode it is made characterwise.

a)                                                      *v_a)* *a)* *a(*
a(                                                      *v_ab* *v_a(* *ab*
ab                      "a block", select [count] blocks, from "[count] [(" to
                        the matching ')', including the '(' and ')' (see
                        |[(|).  Does not include white space outside of the

Editing XHTML - HTML/XHTML editing macros and menus. (haven't tried)

Wrapping the visual selection in a tag or other delimiter

star_full.gif star_full.gif star_full.gif star_full.gif star_full.gif star_full.gif surround.vim plugin

Prerequisite: Understand text-objects!

help surround
  Old text                  Command     New text ~
  "Hello *world!"           ds"         Hello world!
  [123+4*56]/2              cs])        (123+456)/2
  "Look ma, I'm *HTML!"     cs"<q>      <q>Look ma, I'm HTML!</q>
  if *x>3 {                 ysW(        if ( x>3 ) {
  my $str = *whee!;         vlllls'     my $str = 'whee!';

Delete surroundings is *ds*.  The next character given determines the target
to delete.  The exact nature of the target are explained in
|surround-targets| but essentially it is the last character of a
|text-object|.  This mapping deletes the difference between the "inner"
object and "an" object.  This is easiest to understand with some examples:

  Old text                  Command     New text ~
  "Hello *world!"           ds"         Hello world!
  (123+4*56)/2              ds)         123+456/2
  <div>Yo!*</div>           dst         Yo!

Change surroundings is *cs*.  It takes two arguments, a target like with
|ds|, and a replacement.  Details about the second argument can be found
below in |surround-replacements|.  Once again, examples are in order.

  Old text                  Command     New text ~
  "Hello *world!"           cs"'        'Hello world!'
  "Hello *world!"           cs"<q>      <q>Hello world!</q>
  (123+4*56)/2              cs)]        [123+456]/2
  (123+4*56)/2              cs)[        [ 123+456 ]/2

  <div>Yo!*</div>           cst<p>      <p>Yo!</p>
(A t is a pair of HTML or XML tags.  See |tag-blocks| for details.  Remember
that you can specify a numerical argument if you want to get to a tag other
than the innermost one.)

*ys* takes an valid Vim motion or text object as the first object, and wraps
it using the second argument as with |cs|.  (Unfortunately there's no good
mnemonic for "ys").

  Old text                  Command     New text ~
  Hello w*orld!             ysiw)       Hello (world)!

As a special case, *yss* operates on the current line, ignoring leading

  Old text                  Command     New text ~
      Hello w*orld!         yssB            {Hello world!}

There is also *yS* and *ySS* which indent the surrounded text and place it
on a line of its own.

In visual mode, a simple "s" with an argument wraps the selection.  This is
referred to as the *vs* mapping, although ordinarily there will be
additional keystrokes between the v and s.  In linewise visual mode, the
surroundings are placed on separate lines.  In blockwise visual mode, each
line is surrounded.

viss"    : Surround current sentence in "..."
vips)    : Surround current paragraph with (...) (delimiters on separate lines)
vipS)    : Surround current paragraph with (...) (delimiters on separate lines) and indent the whole paragraph

An "S" in visual mode (*vS*) behaves similarly but always places the
surroundings on separate lines.  Additionally, the surrounded text is
indented.  In blockwise visual mode, using "S" instead of "s" instead skips
trailing whitespace.

You can even easily create your own custom replacements (without modifying the plugin script itself)!

:echo char2nr("p"))
" Customizations for surround plugin

" Ruby
" Use v or # to get a variable interpolation (inside of a string)}
" ysiw#   Wrap the token under the cursor in #{}
" v...s#  Wrap the selection in #{}
let g:surround_113 = "#{\r}"   " v
let g:surround_35  = "#{\r}"   " #

" Select text in an ERb file with visual mode and then press s- or s=
" Or yss- to do entire line.
let g:surround_45 = "<% \r %>"    " -
let g:surround_61 = "<%= \r %>"   " =

" Use p to get php tags
autocmd FileType php let b:surround_112 = "<?php \r ?>"     " p

Tip 1495 Tip #1495 - Wrap a Visual hilight in an arbitrary HTML tag : vim online

star_full.gif star_full.gif star_empty.gif Tip 346

" Tag Select/Wrapper
" These mappings and TagSelection function will allow you to place " an XML tag around either the current word, or the current selected " text

" Use nmap, not nnoremap, since we do want to use an existing mapping
nmap ,,, viw,,,
vnoremap ,,, <Esc>:call TagSelection()<CR>

function! TagSelection()
  let tag = input("Tag name (include attributes)? ")

  if strlen(tag) == 0

  " Save b register
  let saveB       = @b
  " <C-R> seems to automatically reindent the line for some filetypes
  " this will disable it until we have applied our changes
  let saveIndent  = &indentexpr
  let curl        = line(".")
  let curc        = col(".")
  let &indentexpr = ''

  " If the visual selection is over multiple lines, then place the
  " data between the tags on newlines:
  "    <tag>
  "    data
  "    </tag>
  let newline = ''
  if getline("'>") != getline("'<")
      let newline = "\n"
      let curl  = line("'>")

  " Strip off all but the first word in the tag for the end tag
  let @b = newline . substitute( tag, '^[ \t"]*\(\<\S*\>\).*', '<\/\1>\e', "" )
  let curc = curc + strlen(@b)
  exec "normal `>a\<C-R>b"

  let @b = substitute( tag, '^[ \t"]*\(\<.*\)', '<\1>\e', "" ) . newline
  let curc = curc + strlen(@b)
  exec "normal `<i\<C-R>b"

  " Now format the area
  exec "normal `<V'>j="

  " Restore b register
  let @b          = saveB
  let &indentexpr = saveIndent

  call cursor(curl, curc)

How to type/search for/remove special characters like ^M and ^[

Press Ctrl-V to get the ^ character, and then (while still holding Ctrl) press Ctrl-whatever.

  • Ctrl-V Ctrl-M
  • Ctrl-V Ctrl-[
  • etc.

If you have a buffer with color codes in it like this:


, then you could remove those characters with something like this %s/Ctrl-V Ctrl-[[\d*m//g.

[Search and Replacement (category)]

(Alias: Substitution) [Regular expressions / Applications of (category)]

For more help, check the documentation:

:help pattern-overview

From the vim documentation (change.txt.gz or :help substitute)):

When the {string} starts with "\=" it is evaluated as an expression, see
|sub-replace-expression|.  Otherwise these characters in {string} have a
special meaning:

magic   nomagic   action    ~
  &       \&      replaced with the whole matched pattern            *s/\&*
 \&        &      replaced with &
      \0          replaced with the whole matched pattern          *\0* *s/\0*
      \1          replaced with the matched pattern in the first
                  pair of ()                                         *s/\1*
      \2          replaced with the matched pattern in the first
                  pair of ()                                         *s/\2*
      ..          ..                                                 *s/\3*
      \9          replaced with the matched pattern in the ninth
                  pair of ()                                         *s/\9*
  ~       \~      replaced with the {string} of the previous
                  substitute                                         *s~*
 \~        ~      replaced with ~                                    *s/\~*
      \u          next character made uppercase                      *s/\u*
      \U          following characters made uppercase, until \E      *s/\U*
      \l          next character made lowercase                      *s/\l*
      \L          following characters made lowercase, until \E      *s/\L*
      \e          end of \u, \U, \l and \L (NOTE: not <Esc>!)        *s/\e*
      \E          end of \u, \U, \l and \L                           *s/\E*
      <CR>        split line in two at this point
                  (Type the <CR> as CTRL-V <Enter>)                  *s<CR>*
      \r          idem                                               *s/\r*
      \<CR>       insert a carriage-return (CTRL-M)
                  (Type the <CR> as CTRL-V <Enter>)                  *s/\<CR>*
      \n          insert a <NL> (<NUL> in the file)
                  (does NOT break the line)                          *s/\n*
      \b          insert a <BS>                                      *s/\b*
      \t          insert a <Tab>                                     *s/\t*
      \\          insert a single backslash                          *s/\\*
      \x          where x is any character not mentioned above:
                  Reserved for future expansion

How to match the beginning of the line


How to match not the beginning of the line


Find and replace all : characters, except the ones that occur at the beginning of the line


How to create a non-greedy any-number-of-characters pattern

.\{-} is the non-greedy version of .*. So simply replace .* with .\{-}.

Example: Trying to match words starting with "e" and ending in "t", like "element":

/e.*t is greedy and matches all of this:

an E element, only child of its parent

/e.\{-}t is non-greedy and generates two, shorter matches in this example:

an E element, only child of its parent


Overview of multi items.                                */multi* *E61* *E62*
More explanation and examples below, follow the links.                  *E64*

          multi ~
     'magic' 'nomagic'  matches of the preceding atom ~
|/star| *       \*      0 or more       as many as possible
|/\+|   \+      \+      1 or more       as many as possible (*)
|/\=|   \=      \=      0 or 1          as many as possible (*)
|/\?|   \?      \?      0 or 1          as many as possible (*)

|/\{|   \{n,m}  \{n,m}  n to m          as many as possible (*)
        \{n}    \{n}    n               exactly (*)
        \{n,}   \{n,}   at least n      as many as possible (*)
        \{,m}   \{,m}   0 to m          as many as possible (*)
        \{}     \{}     0 or more       as many as possible (same as *) (*)

|/\{-|  \{-n,m} \{-n,m} n to m          as few as possible (*)
        \{-n}   \{-n}   n               exactly (*)
        \{-n,}  \{-n,}  at least n      as few as possible (*)
        \{-,m}  \{-,m}  0 to m          as few as possible (*)
        \{-}    \{-}    0 or more       as few as possible (*)

How to do a substitution using the last search pattern

It involves a bit of hackery, unfortunately. I'd like to be able to just press : , press Up to browse in my command history back to my previous search, and then edit the (plain old, read-only) search command to turn it into a substitution command.

Unfortunately, the searches are stored in a separate command history from other commands (so press /<Up> is different from :<Up>).

So this is my workaround:

:execute "%s/" . @/ . "/\"/g"

You can use /<Up> to preview and edit the last search pattern before you commit to using it. I use that to strip off the \< and \> from the search pattern that get added for me if I do a [keyword]/[tag] search (using * or #).

Why would I ever need this? How about when it shows some weird Unicode character on the screen that I can't even type. Maybe I can just select it with my mouse to copy and paste it, but that doesn't always work, like when the character is stored properly but not displayed properly. Also, in Windows gvim, how do you paste onto the command line? (I don't know if it's possible.)


  • Is actually: a left pretty-quote (“), which displays fine on the rendered wiki page and in the textarea for editing the page
  • But I'm using a Firefox extension to edit the textarea in vim, which doesn't display it correctly for some reason.
  • Vim displays it as: ?\<â▪▪input\> (3 characters instead of 1; squares in place of 2 of the real characters)
  • When I copy and paste it from vim, it appears as ?\<“input\> (so even if I could paste that back into the command buffer to create a substitute command, it probably wouldn't work properly...)

So that's when I use it...

How to strip out (remove) all HTML tags from your document


How to expand a 1-line <td>whatever</td> into a 3-line <td> tag

:%s#<td>\(.*\)</td>#<td>\r      \1\r    </td>#cg

How to prepend something to the (non-white-space) beginning of the line

Let's say you started with this:


and you're goal is to prefix each column name with a table name, to turn it into this:


You could match all word characters ([0-9A-Za-z_]) that are followed by commas and do a replacement on that match:


Or, if you prefer to use whitespace as your matching basis, you can append your new text at the end of the whitesace at the beginning of the line, like this:


When to prefer one method over the other? Well, one advantage of the first method is that it only matches lines with a comma on them, so you might be able to get away with doing the command on the whole file (%).

The second method, on the other hand, will match every line that has whitespace at the beginning of the line, which could be most of the lines in the file! So with the second one, you might have to restrict the command to only operate on a range, like this (after first selecting the lines containing the column names):


How to change the order of the :to and :from options in a state_machine transition declaration

:%s/:to => '\(.*\)', :from => '\(.*\)'/:from => '\2', :to => '\1'/cg


      transition :to => 'address', :from => 'in_progress'


      transition :from => 'in_progress', :to => 'address'

How to get rid of line numbers if you've copied and pasted from a vim screen containing line numbers

:%s/^[ 0-9]\+[0-9]\+ //g
:%s/^[ 0-9]\+[0-9]\+\n/\r/cg

Will change something like this:

144 do |release|
145     release.user_name = ENV['RUBYFORGE_USER']
146     release.password = ENV['RUBYFORGE_PASSWORD']
147     release.files = release_files.to_a
149     release.release_changes = ''
150     release.release_notes = ''
151   end
152 end

into this: do |release|
    release.user_name = ENV['RUBYFORGE_USER']
    release.password = ENV['RUBYFORGE_PASSWORD']
    release.files = release_files.to_a
    release.release_changes = ''
    release.release_notes = ''

For processing MediaWiki markup

Turn : characters into literal : characters so that they're not interpreted as [indent] characters

:'<,'>s#[^^]:#:#g         # Match any ':' that's *not* at the beginning of the line (because those we legitimately *want* to be [indent] characters; replace with ":"

[Search and Replacement (category)]: Converting copied-and-pasted web pages into wiki text

(These examples/solutions all assume we have copy and pasted from a rendered web page in Firefox and that the target wiki is MediaWiki)

Definition lists

How to turn this:

    any element
    an element of type E

into MediaWiki wiki text:

:any element
:an element of type E

Here's how:

Select region to change.
:'<,'>s/^\(\S\)/;\1/g        " Match all lines that start with a non-whitespace character, and prefix that character with ';' (definition item)
:'<,'>s/^\s\+/:/g       " Match every line that starts with 1 or more whitespace characters. Replace those characters with a ':' character (definition)


Viki/Deplate : A personal wiki for Vim

Neat idea, but... I don't think it's what I want, as it makes you do all your editing through vim (?) and probably stores information in flat files rather than a DB.


If backspace produces ^?

When you try to save, it says "CONVERSION ERROR"

Type :set to see what encoding and fileencoding are set to...

You probably have added some Unicode characters that can't be converted to Latin1?

Anyway, setting :set fileencoding=utf8 and then trying to save again usually works for me.

To do

Vim / To do

Retrieved from ""
Personal tools