This page is not available in every language. Missing translations are disabled in the language selector.

Quick reference

Vimscript Cheatsheet

A comprehensive reference guide for Vimscript: variables, functions, custom commands, control flow, data structures, key mappings, and syntax highlighting.

· Published

Vimscript is the built-in scripting language for customizing and extending the Vim text editor.

Getting Started

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

You can put this in a script (script.vim) and source it (:source script.vim), or run individual commands in normal mode directly via :let and :echo.

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

Variables

Definition

let var = "hello"

Variable Scope 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)
let a:arg = 'baz'              " a: function argument

The s: prefix can also be used for script-local function names. See :help local-variables.

Other Scopes

let w:foo = 'bar'    " w: window local
let b:state = 'on'   " b: buffer local
let t:state = 'off'  " t: tab page local
echo v:version       " v: vim internal variable
let @/ = ''          " @  register (this clears last search pattern)
echo $PATH           " $  environment variable

Vim Options

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

Prefix option names with & to read or modify them in expressions.

Arithmetic & String Operators

a + b             " Numbers only!
'hello ' . name   " String concatenation
let var -= 2
let var += 5
let var .= 'string'   " Append string

Strings

String Syntax

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

let literal = 'literal, no \ escaping'
let literal = 'that''s enough'  " Double '' produces single '

echo "result = " . res   " Concatenation

String Functions

strlen(str)                  " Byte length
len(str)                     " Same as strlen
strchars(str)                " Character count

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

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

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

Functions

Function Definition

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

  return 1
endfunction

Overwriting Functions

function! MyFunc()
  echo "Function defined or replaced"
endfunction

Using function! (with !) replaces any previously defined function with the same name without throwing an error.

Namespacing & Autoload

function! myplugin#hello()
  " Automatically loaded from autoload/myplugin.vim
endfunction

Invoking Functions

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

Capturing Return Values

let result = s:Initialize()

Abort on Error

function! MyFunction() abort
  " Aborts immediately on runtime errors
endfunction

Variadic Arguments

function! Infect(...)
  echo a:0    "=> Number of extra arguments (e.g. 2)
  echo a:1    "=> First extra argument: 'jake'
  echo a:2    "=> Second extra argument: 'bella'

  for item in a:000  " a:000 is a list of all variadic arguments
    echon ' ' . item
  endfor
endfunction

call Infect('jake', 'bella')

Loops & Flow Control

Loops

for s in list
  echo s
  continue  " Skip to next iteration
  break     " Break out of loop
endfor
while x < 5
  let x += 1
endwhile

Custom Commands

Defining Commands

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

User-defined commands must start with an uppercase letter. The ! flag allows replacing an existing command.

Invoking Functions in Commands

command! Save call <SID>Foo()

function! s:Foo()
  " Implementation
endfunction

Command Arguments

command! -nargs=? Save call script#foo(<args>)
Argument Spec Description
-nargs=0 0 arguments (default)
-nargs=1 Exactly 1 argument (may include spaces)
-nargs=? 0 or 1 argument
-nargs=* 0 or more whitespace-separated arguments
-nargs=+ 1 or more whitespace-separated arguments

Conditionals

If / Elseif / Else

let char = getchar()
if char == "\<LeftMouse>"
  " Left click
elseif char == "\<RightMouse>"
  " Right click
else
  " Other input
endif

Truthiness

if 1       "=> True
if 0       "=> False
if "1"     "=> True (parsed as 1)
if "456"   "=> True (parsed as 456)
if "xfz"   "=> False (strings not starting with digits evaluate to 0)

Vimscript has no standalone boolean type: 0 is false and nonzero integers are true.

Comparison Operators

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

Case Sensitivity in Strings

if name ==# 'John'     " Explicitly case-sensitive
if name ==? 'John'     " Explicitly case-insensitive
if name == 'John'      " Dependent on &ignorecase setting

Identity Comparison

if a is b
if a isnot b

Tests if a and b reference the identical data instance.

Regular Expression Matches

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

\v activates "very magic" regex syntax, allowing characters like <>, +, and {} without extra escaping.

Single Line Statements

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

Use | to chain multiple statements on one line.

Data Structures

Lists

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

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

" Safe index lookup with fallback
let second = get(mylist, 1)
let fallback = get(mylist, 10, "NONE")

List Operations

len(mylist)
empty(mylist)

let sortedlist = sort(copy(mylist))

" Sublists
let shortlist = mylist[2:-1]
let shortlist = mylist[2:]     " From index 2 to end
let single = mylist[2:2]       " Single item list

" Concatenation & append
let longlist = mylist + [5, 6]
let mylist += [7, 8]
call add(mylist, 9)

Functional List Methods

call map(files, "bufname(v:val)")  " Map using v:val
call filter(files, 'v:val != ""')  " Filter using boolean expression

Dictionaries

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

echo colors["apple"]
echo get(colors, "apple")   " Suppresses missing key error

Dictionary Operations

call remove(colors, "apple")

if has_key(dict, 'foo')
if empty(dict)
let k = keys(dict)
let v = values(dict)
let n = len(dict)

echo max(dict)
echo min(dict)

" Extending dictionary
call extend(s:fruits, { "cherry": "red" })
for key in keys(mydict)
  echo key . ': ' . mydict[key]
endfor

Scope prefixes (s:, g:, l:, b:) are themselves accessible as dictionary objects:

let script_keys = keys(s:)

Numbers & Arithmetic

let int = 1000
let hex = 0xff
let oct = 0755
let fl = 100.1
let sci = 5.4e4
3 / 2     "=> 1 (integer division)
3 / 2.0   "=> 1.5 (float division)
sqrt(100)
floor(3.5)
ceil(3.3)
abs(-3.4)

Vim Specifics

Executing Commands

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

Normal Mode Keystrokes

normal G
normal! G   " Ignores custom mappings

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

Filename Expansion

echo expand("%")      " Current file path: path/file.txt
echo expand("%:t")    " Basename tail: file.txt
echo expand("%:p:h")  " Directory full path: /home/user/path
echo expand("%:r")    " Root name: path/file
echo expand("%:e")    " Extension: txt

Output Control & Messages

silent g/pattern/p    " Suppress command output

echo 'Simple text'
echomsg 'Persistent text recorded in :messages'
echoerr 'Error message'

echohl WarningMsg | echomsg "=> Warning!" | echohl None

Configuration Options

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

Introspection & Feature Detection

has("clipboard")      " Check compiled features
executable("python3") " Check binary in PATH
globpath(&rtp, "syntax/c.vim")

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

Key Mappings

Modes

[nvixso](nore)map
  • n: Normal mode
  • v: Visual and Select mode
  • x: Visual mode only
  • i: Insert mode
  • c: Command-line mode
  • o: Operator-pending mode
  • nore: Non-recursive (prevents infinite mapping loops)

Common Flags

Flag Meaning
<buffer> Local to current buffer only
<silent> Do not echo command in status line
<nowait> Trigger immediately without waiting for longer mappings

Syntax Highlighting & Conceal

Highlight Groups

hi Comment term=bold gui=bold ctermfg=4 guifg=#80a0ff
hi def link markdownH1 htmlH1

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

Include Guards

if exists('g:loaded_myplugin')
  finish
endif
let g:loaded_myplugin = 1

Related topics