Start hacking

let name = "John"
echo "Hello, " . name

You can either put this in a script (script.vim) and run it (:source script.vim), or you can type the commands individually in normal mode as :let and :echo.

Learn by example

function! SuperTab()
  let l:part = strpart(getline('.'),col('.')-2,1)
  if (l:part =~ '^\W\?$')
      return "\<Tab>"
  else
      return "\<C-n>"
  endif
endfunction

imap <Tab> <C-R>=SuperTab()<CR>

Here’s another example with functions, variables and mapping.

Variables

Defining

let var = "hello"

Variable prefixes

let g:ack_options = '-s -H'    " g: global
let s:ack_program = 'ack'      " s: local (to script)
let l:foo = 'bar'              " l: local (to function)

The s: prefix is also available in function names. See :help local-variables

Other prefixes

let w:foo = 'bar'    " w: window
let b:state = 'on'   " b: buffer
let t:state = 'off'  " t: tab
echo v:var           " v: vim special
let @/ = ''          " @  register (this clears last search pattern)
echo $PATH           " $  env

Vim options

echo 'tabstop is ' . &tabstop
if &insertmode
echo &g:option
echo &l:option

Prefix Vim options with &

Operators

a + b             " numbers only!
'hello ' . name   " concat
let var -= 2
let var += 5
let var .= 'string'   " concat

Strings

Strings

let str = "String"
let str = "String with \n newline"

let literal = 'literal, no \ escaping'
let literal = 'that''s enough'  " double '' => '

echo "result = " . re   " concatenation

Also see :help literal-string and :help expr-quote. See: Strings

String functions

strlen(str)    " length
len(str)       " same
strchars(str)  " character length

split("one two three")       "=> ['one', 'two', 'three']
split("one.two.three", '.')  "=> ['one', 'two', 'three']

join(['a', 'b'], ',')  "=> 'a,b'

tolower('Hello')
toupper('Hello')

Also see :help functions See: String functions

Functions

Functions

" prefix with s: for local script-only functions
function! s:Initialize(cmd, args)
  " a: prefix for arguments
  echo "Command: " . a:cmd

  return 1
endfunction

See: Functions

Overwriting

function f1()
  echo "f1"
endfunction


function! f1()
  echo "f1 overridden"
endfunction

If you define two functions with the same name, Vim will throw an error complaining that the function f1 already exists. To overwrite the previous function with the same name, add a ! after the function keyword.

Namespacing

function! myplugin#hello()

Calling functions

call s:Initialize()
call s:Initialize("hello")

Consuming return values

echo "Result: " . s:Initialize()

Abortable

function! myfunction() abort
endfunction

Aborts when an error occurs.

Var arguments

function! infect(...)
  echo a:0    "=> 2
  echo a:1    "=> jake
  echo a:2    "=> bella

  for s in a:000  " a list
    echon ' ' . s
  endfor
endfunction

infect('jake', 'bella')

See :help function-argument. See: Var arguments

Loops

for s in list
  echo s
  continue  " jump to start of loop
  break     " breaks out of a loop
endfor
while x < 5
endwhile

Custom commands

Custom commands

command! Save :set fo=want tw=80 nowrap

Custom commands start with uppercase letters. The ! redefines a command if it already exists.

Commands calling functions

command! Save call <SID>foo()
function! s:foo()
  ...
endfunction

Commands with arguments

command! -nargs=? Save call script#foo(<args>)
What What
-nargs=0 0 arguments, default
-nargs=1 1 argument, includes spaces
-nargs=? 0 or 1 argument
-nargs=* 0+ arguments, space separated
-nargs=+ 1+ arguments, space reparated

Flow

Conditionals

let char = getchar()
if char == "\<LeftMouse>"
  " ...
elseif char == "\<RightMouse>"
  " ...
else
  " ...
endif

Truthiness

if 1 | echo "true"  | endif
if 0 | echo "false" | endif
if 1       "=> 1 (true)
if 0       "=> 0 (false)
if "1"     "=> 1 (true)
if "456"   "=> 1 (true)
if "xfz"   "=> 0 (false)

No booleans. 0 is false, 1 is true. See: Truthiness

Operators

if 3 > 2
if a && b
if (a && b) || (c && d)
if !c

See :help expression-syntax. See: Operators

Strings

if name ==# 'John'     " case-sensitive
if name ==? 'John'     " case-insensitive
if name == 'John'      " depends on :set ignorecase

" also: is#, is?, >=#, >=?, and so on

Identity operators

a is b
a isnot b

Checks if it’s the same instance object.

Regexp matches

"hello" =~ 'xx*'
"hello" !~ 'xx*'
"hello" =~ '\v<\d+>'

\v enables “extended” regex mode which allows word boundary (<>), +, and more.

Single line

if empty(a:path) | return [] | endif
a ? b : c

Use | to join lines together.

Boolean logic

if g:use_dispatch && s:has_dispatch
  ···
endif

Lists

Lists

let mylist = [1, two, 3, "four"]

let first = mylist[0]
let last  = mylist[-1]

" Suppresses errors
let second = get(mylist, 1)
let second = get(mylist, 1, "NONE")

Functions

len(mylist)
empty(mylist)

sort(list)
let sortedlist = sort(copy(list))

split('hello there world', ' ')

Concatenation

let longlist = mylist + [5, 6]
let mylist += [7, 8]

Sublists

let shortlist = mylist[2:-1]
let shortlist = mylist[2:]     " same

let shortlist = mylist[2:2]    " one item

Push

let alist = [1, 2, 3]
let alist = add(alist, 4)

Map

call map(files, "bufname(v:val)")  " use v:val for value
call filter(files, 'v:val != ""')

Dictionaries

Dictionaries

let colors = {
  \ "apple": "red",
  \ "banana": "yellow"
}

echo colors["a"]
echo get(colors, "apple")   " suppress error

See :help dict

Using dictionaries

remove(colors, "apple")
" :help E715
if has_key(dict, 'foo')
if empty(dict)
keys(dict)
len(dict)
max(dict)
min(dict)
count(dict, 'x')
string(dict)
map(dict, '<>> " . v:val')

Iteration

for key in keys(mydict)
  echo key . ': ' . mydict[key]
endfor

Prefixes

keys(s:)

Prefixes (s:, g:, l:, etc) are actually dictionaries.

Extending

" Extending with more
let extend(s:fruits, { ... })

Casting

str2float("2.3")
str2nr("3")
float2nr("3.14")

Numbers

Numbers

let int = 1000
let int = 0xff
let int = 0755   " octal

See :help Number. See: Numbers

Floats

let fl = 100.1
let fl = 5.4e4

See :help Float

Arithmetic

3 / 2     "=> 1, integer division
3 / 2.0   "=> 1.5
3 * 2.0   "=> 6.0

Math functions

sqrt(100)
floor(3.5)
ceil(3.3)
abs(-3.4)

sin() cos() tan()
sinh() cosh() tanh()
asin() acos() atan()

Vim-isms

Execute a command

execute "vsplit"
execute "e " . fnameescape(filename)

Runs an ex command you typically run with :. Also see :help execute. See: Execute a command

Running keystrokes

normal G
normal! G   " skips key mappings

execute "normal! gg/foo\<cr>dd"

Use :normal to execute keystrokes as if you’re typing them in normal mode. Combine with :execute for special keystrokes. See: Running keystrokes

Getting filenames

echo expand("%")      " path/file.txt
echo expand("%:t")    " file.txt
echo expand("%:p:h")  " /home/you/path/file.txt
echo expand("%:r")    " path/file
echo expand("%:e")    " txt

See :help expand

Silencing

silent g/Aap/p

Suppresses output. See :help silent

Echo

echoerr 'oh it failed'
echomsg 'hello there'
echo 'hello'

echohl WarningMsg | echomsg "=> " . a:msg | echohl None

Settings

set number
set nonumber
set number!     " toggle
set numberwidth=5
set guioptions+=e

Prompts

let result = confirm("Sure?")
execute "confirm q"

Built-ins

has("feature")  " :h feature-list
executable("python")
globpath(&rtp, "syntax/c.vim")

exists("$ENV")
exists(":command")
exists("variable")
exists("+option")
exists("g:...")

Mapping

Mapping commands

nmap
vmap
imap
xmap
nnoremap
vnoremap
inoremap
xnoremap
...

Explanation

[nvixso](nore)map
 │       └ don't recurse
 │
 └ normal, visual, insert,
   eX mode, select, operator-pending

Arguments

<buffer> only in current buffer
<silent> no echo
<nowait>  

Syntax

Highlights

hi Comment
  term=bold,underline
  gui=bold
  ctermfg=4
  guifg=#80a0ff

Filetype detection

augroup filetypedetect
  au! BufNewFile,BufRead *.json setf javascript
augroup END

au Filetype markdown setlocal spell

Conceal

set conceallevel=2
syn match newLine "<br>" conceal cchar=}
hi newLine guifg=green

Region conceal

syn region inBold concealends matchgroup=bTag start="<b>" end="</b>"
hi inBold gui=bold
hi bTag guifg=blue

Syntax

syn match :name ":regex" :flags

syn region Comment  start="/\*"  end="\*/"
syn region String   start=+"+    end=+"+	 skip=+\\"+

syn cluster :name contains=:n1,:n2,:n3...

flags:
  keepend
  oneline
  nextgroup=
  contains=
  contained

hi def link markdownH1 htmlH1

Include guards

if exists('g:loaded_myplugin')
  finish
endif

" ...

let g:loaded_myplugin = 1
0 Comments for this cheatsheet. Write yours!