Skip to content

Instantly share code, notes, and snippets.

@yegappan
Last active January 12, 2024 10:51
Show Gist options
  • Save yegappan/16d964a37ead0979b05e655aa036cad0 to your computer and use it in GitHub Desktop.
Save yegappan/16d964a37ead0979b05e655aa036cad0 to your computer and use it in GitHub Desktop.
Vim script for Python Developers

Vim Script for Python Developers

This is a guide to Vim Script development for Python developers. Sample code for the various expressions, statements, functions and programming constructs is shown in both Python and Vim Script. This is not intended to be a tutorial for developing Vim scripts. It is assumed that the reader is familiar with Python programming.

For an introduction to Vim Script development, refer to usr_41.txt, eval.txt and Learn Vimscript the Hard Way

For a guide similar to this one for JavaScript developers, refer to Vim Script for the JavaScripter

This guide only describes the programming constructs that are present in both Python and Vim. The constructs that are unique to Vim (e.g. autocommands, key-mapping, abbreviations, user-commands, plugins, etc.) are not described in this guide.

Some of the features described in this guide are available only in the recent versions of Vim (8.2).

The Github repository for this gist is available at: https://github.com/yegappan/VimScriptForPythonDevelopers.


Table of Contents


Literals

Type Python VimScript
integer -1, 0, 5 -1, 0, 5
binary 0b1011 0b1011
octal 0o477 0477
hexadecimal 0x1AE 0x1AE
float 3.14, -1.5e2 3.14, -1.5e2
string "hello", 'world' "hello", 'world'
boolean True, False v:true, v:false
list [], [5, 9], ['a', 'b'] [], [5, 9], ['a', 'b']
dict {}, {'idx' : 2, 'name' : 'abc'} {}, {'idx' : 2, 'name' : 'abc'}
special None v:none, v:null

Help: expr-number, string, Boolean, list, dict, v:none, v:null


Variables

Creating a Variable

Python:

i = 10
pi = 3.1415
str = "Hello"
a, b, s = 10, 20, "sky"

VimScript:

let i = 10
let pi = 3.1415
let str = "Hello"
let [a, b, s] = [10, 20, "sky"]

Help: variables

Deleting a Variable

Python:

del str

VimScript:

unlet str

Help: :unlet

Here Document

Assigning multi-line values to a variable.

Python:

import textwrap
i = textwrap.dedent("""
    one
    two three
      four
    five
""".lstrip('\n')).splitlines()
# i == ['one', 'two three', '  four', 'five']

VimScript:

let i =<< trim END
    one
    two three
      four
    five
END
" i == ['one', 'two three', '  four', 'five']

Help: :let-heredoc

Types

Type Python VimScript
Number num = 10 let num = 10
Float f = 3.4 let f = 3.4
Booelan done = True let done = v:true
String str = "green" let str = "green"
List l = [1, 2, 3] let l = [1, 2, 3]
Dictionary d = {'a' : 5, 'b' : 6} let d = #{a : 5, b : 6}

Help: variables

Type Conversion

Conversion Python VimScript
Number to Float float(n) floor(n)
Float to Number int(f) float2nr(f)
Number to String str(n) string(n)
String to Number int(str) str2nr(str)
Float to String str(f) string(f)
String to Float float(str) str2float(str)
List to String str(l) string(l)
String to List eval(str) eval(str)
Dict to String str(d) string(d)
String to Dict eval(str) eval(str)

Help: string(), str2nr(), str2float(), float2nr(), floor(), eval()

Type Check

Type Python VimScript
Number isintance(x, int) type(x) is v:t_number
String isinstance(x, str) type(x) is v:t_string
List isintance(x, list) type(x) is v:t_list
Dictionary isintance(x, dict) type(x) is v:t_dict
Float isintance(x, float) type(x) is v:t_float
Boolean isinstance(x, bool) type(x) is v:t_bool

Help: type()

Variable Namespaces

All the variables in VimScript have a scope. The scope is specified by prefixing the variable name with one of the prefix strings shown in the table below. If a variable name is used without a scope prefix, then inside a function the function local scope is used. Otherwise the global variable scope is used.

Scope Prefix Description
g: global
l: function-local
s: script-local
a: function argument
v: internal
b: buffer local
w: window local
t: tab local

Help: global-variable, local-variable, script-variable, function-argument, vim-variable, buffer-variable, window-variable, tabpage-variable


Operators

Arithmetic Operators

What Python VimScript
addition a = 10 + 20 let a = 10 + 20
subtraction a = 30 - 10 let a = 30 - 10
multiplication a = 3 * 5 let a = 3 * 5
division a = 22 / 7 let a = 22 / 7
modulus a = 10 % 3 let a = 10 % 3
exponentiation a = 2 ** 3 let a = float2nr(pow(2, 3))
floor division a = 10 // 3 let a = floor(10 / 3.0)

Help: expr5

Assignment Operators

What Python VimScript
addition a += 1 let a += 1
subtraction a -= 2 let a -= 2
multiplication a *= 4 let a *= 4
division a /= 2 let a /= 2
modulus a %= 2 let a %= 2

Help: :let+=

Comparison Operators

What Python VimScript
equal to a == b a == b
not equal to a != b a != b
greater than a > b a > b
less than a < b a < b
greater than or equal to a >= b a >= b
less than or equal to a <= b a <= b

Help: expr4

Logical Operators

What Python VimScript
logical and x and y x && y
logical or x or y x || y
logical not not x !x

Help: expr2

Bitwise Operators

What Python VimScript
bitwise AND c = a & b let c = and(a, b)
bitwise OR c = a | b let c = or(a, b)
bitwise NOT c = ~a let c = invert(a)
bitwise XOR c = a ^ b let c = xor(a, b)
left shift c = a << b let c = a * float2nr(pow(2, b))
right shift c = a >> b let c = float2nr(floor(a / pow(2, b)))

Help: and(), or(), invert(), xor()

Identity Operators

What Python VimScript
is x is y x is y
is not x is not y x isnot y

Help: expr-is, expr-isnot


String

Vim has functions for dealing with both multibyte and non-multibyte strings. Some functions deal with bytes and some functions deal with characters. Refer to the reference guide for the various functions to get the detailed information.

Raw string

Python:

s1 = r"one\ntwo\n"
s2 = "one\ntwo\n"

VimScript:

let s1 = 'one\ntwo\n'
let s2 = "one\ntwo\n"

Help: literal-string, string

Finding string length

Python:

n = len("Hello World")

VimScript:

" count the number of bytes in a string
let n = len("Hello World")
" count the number of bytes in a string
let n = strlen("Hello World")
" count the number of characters in a string
let n = strcharlen("Hello World")
" count the number of characters in a string
let n = strwidth("Hello World")

Help: len(), strlen(), strcharlen(), strwidth(), strdisplaywidth()

String Concatenation

Python:

str1 = "blue"
str2 = "sky"
s = str1 + str2

VimScript:

let str1 = "blue"
let str2 = "sky"
let s = str1 .. str2

" Deprecated way of concatenating strings
let s = str1 . str2

String Comparison

Python:

# compare strings matching case
str1 = "blue"
str2 = "blue"
str3 = "sky"
if str1 == str2:
  print("str1 and str2 are same")
if str1 is str2:
  print("str1 and str2 are same")
if str1 != str3:
  print("str1 and str3 are not same")
if str1 is not str3:
  print("str1 and str3 are not same")

# compare strings ignoring case
str1 = "Blue"
str2 = "BLUE"
str3 = "sky"
if str1.lower() == str2.lower():
  print("str1 and str2 are same")
if str1.lower() != str3.lower():
  print("str1 and str3 are not same")

VimScript:

" compare strings matching case
let str1 = "blue"
let str2 = "blue"
let str3 = "sky"
if str1 ==# str2
  echo "str1 and str2 are same"
endif
if str1 is# str2
  echo "str1 and str2 are same"
endif
if str1 !=# str3
  echo "str1 and str3 are not same"
endif
if str1 isnot# str3
  echo "str1 and str3 are not same"
endif

" compare strings ignoring case
let str1 = "Blue"
let str2 = "BLUE"
let str3 = "sky"
if str1 ==? str2
  echo "str1 and str2 are same"
endif
if str1 is? str2
  echo "str1 and str2 are same"
endif
if str1 !=? str3
  echo "str1 and str3 are not same"
endif
if str1 isnot? str3
  echo "str1 and str3 are not same"
endif

Help: expr4

Getting a substring

In Python, when using an index range to specify a sequence of characters in a string, the character at the end index is not included. In Vim, the character at the end index is included. The slice() function excludes the character at the end index.

Python:

str = "HelloWorld"
sub = str[2:5]

VimScript:

let str = "HelloWorld"
" use byte index range
echo str[2:4]
" use a negative byte range
echo str[-3:]
echo str[2:-3]
" use byte index and length
echo strpart(str, 2, 3)
" use character index and length
echo strcharpart(str, 2, 3)
" use the start and end character indexes
echo slice(str, 2, 3)
" exclude the last character
echo slice(str, 6, -1)

Help: expr-[:], strpart(), slice()

Counting the occurrences of a substring

Python:

str = "Hello World"
c = str.count("l")

VimScript:

let str = "Hello World"
let c = str->count("l")

Help: count()

Finding the position of a substring

Python:

str = "running"
idx = str.find("nn")    # leftmost
idx = str.rfind("ing")  # rightmost
# idx == -1 if the substring is not present

VimScript:

let str = "running"
let idx = str->stridx("nn")    " leftmost
let idx = str->strridx("ing")  " rightmost
" idx == -1 if the substring is not present

Help: stridx(), strridx()

Checking whether a string starts with or ends with a substring

Python:

str = "running"
if str.startswith("run"):
    print("starts with run")
if str.endswith("ing"):
    print("ends with ing")

VimScript:

let str = "running"
if str =~# '^run'
  echo "starts with run"
endif
if str[:len('run') - 1] is# 'run'
  echo "starts with run"
endif

if str =~# 'ing$'
  echo "ends with ing"
endif

Help: expr-=~#

Joining strings in a List with a separator

Python:

s = ":".join(['ab', 'cd', 'ef'])

VimScript:

let s = join(['ab', 'cd', 'ef'], ':')

Help: join()

Changing the case of letters in a string

Python:

s = "Hello World"
l = s.lower()
l = s.upper()

VimScript:

let s = "Hello World"
let l = s->tolower()
let l = s->toupper()

Help: tolower(), toupper()

Replace a substring

Python:

s = "Hello World"
s2 = s.replace("Hello", "New")

VimScript:

let s = "Hello World"
let s2 = s->substitute("Hello", "New", 'g')

Help: substitute()

Split a string

Python:

s = "a:b:c"
s2 = s.split(":")

VimScript:

let s = "a:b:c"
let s2 = s->split(":")

Help: split(), join(),

Stripping leading and trailing whitespace from a string

Python:

s = "  python  "
# strip leading and trailing whitespace
s2 = s.strip()
print(f"<{s2}>")
# strip leading space characters
s2 = s.lstrip(' ')
print(f"<{s2}>")
# strip trailing space characters
s2 = s.rstrip(' ')
print(f"<{s2}>")

VimScript:

let s = "  vim  "
" strip leading and trailing whitespace
let s2 = s->trim()
echo $"<{s2}>"
" strip leading space characters
let s2 = s->trim(' ', 1)
echo $"<{s2}>"
" strip trailing space characters
let s2 = s->trim(' ', 2)
echo $"<{s2}>"

Help: trim()

Checking whether a string contains specific type of characters

Python:

s = "text"
if s.isalnum():
    print("Contains only alphanumeric characters")
if s.isalpha():
    print("Contains only alphabetic characters")
if s.isdigit():
    print("Contains only digits")
if s.isspace():
    print("Contains only whitespace characters")
if s.isupper():
    print("Contains only uppercase characters")
if s.islower():
    print("Contains only lowercase characters")

VimScript:

let s = "text"
if s =~ '^[:alnum:]\+'
  echo "Contains only alphanumeric characters"
endif
if s =~ '^\a\+$'
  echo "Contains only alphabetic characters"
endif
if s =~ '^\d\+$'
  echo "Contains only digits"
endif
if s =~ '^\s\+$'
  echo "Contains only whitespace characters"
endif
if s =~ '^\u\+$'
  echo "Contains only uppercase characters"
endif
if s =~ '^\l\+$'
  echo "Contains only lowercase characters"
endif

Help: /collection

Data type conversion to string

Python:

s = str(268)
s = str(22.7)
s = str([1, 2, 3])
s = str({'a' : 1, 'b' : 2})

VimScript:

let s = string(268)
let s = string(22.7)
let s = string([1, 2, 3])
let s = string({'a' : 1, 'b' : 2})

Help: string()

Evaluating a string

Python:

x = 10
y = eval("x * 2")
print(y)
n = eval("min([4, 3, 5])")

VimScript:

let x = 10
let y = eval("x * 2")
echo y
let n = eval("min([4, 3, 5])")

Help: eval()

Executing commands in a string

Python:

exec("for i in range(5):\n    print(i)\n")

VimScript:

execute "for i in range(5)\necho i\nendfor"

Help: :execute

Substituting variables in a string (String Interpolation)

Python:

aVar = 10
str = f"Value of 'a' is {aVar}"
print(str)

bList = [1, 2, 3]
str = f"bList is {bList}"
print(str)

VimScript:

let aVar = 10
let str = $"Value of 'a' is {aVar}"
echo str

let bList = [1, 2, 3]
let str = $"bList is {string(bList)}"
echo str

Help: interp-string

Getting the Unicode value of a character and vice versa

Python:

print("Ordinal value of 'a' is " + str(ord("a")))
print("Character with value 65 is " + chr(65))

VimScript:

echo "Ordinal value of 'a' is " .. char2nr('a')
echo "Character with value 65 is " .. nr2char(65)

Help: char2nr(), nr2char()

Getting the character values of a string

Python:

l = [ord(i) for i in 'Hello']
s = ''.join(chr(i) for i in l)
print(s)
print(l)

VimScript:

let l = str2list('Hello')
let s = list2str(l)
echo s
echo l

Help: str2list(), list2str()

Fuzzy matching strings

Python:

from fuzzywuzzy import process
from fuzzywuzzy import fuzz

str_list = ['crow', 'clay', 'cobb']
m = process.extractOne('cay', str_list, scorer=fuzz.partial_ratio)
print(m)

VimScript:

let str_list = ['crow', 'clay', 'cobb']
let m = matchfuzzy(str_list, 'cay')
echo m

Help: matchfuzzy(), matchfuzzypos()

String Methods

Method Python VimScript
capitalize() 'one two'.capitalize() 'one two'->substitute('.', '\u&', '')
center() 'abc'.center(10) Not available
count() "abbc".count('b') "abbc"->count('b')
decode() str.decode() Not available
encode() str.encode() Not available
endswith() 'running'.endswith('ing') 'running' =~# 'ing$'
expandtabs() "a\tb".expandtabs() "a\tb"->substitute("\t", repeat(' ', 8), 'g')
find() "running".find('nn') "running"->stridx('nn')
index() 'hello'.index('e') 'hello'->stridx('e')
isalnum() str.isalnum() str =~ '^[[:alnum:]]\+'
isalpha() str.isalpha() str =~ '^\a\+$'
isdigit() str.isdigit() str =~ '^\d\+$'
islower() str.islower() str =~ '^\l\+$'
isspace() str.isspace() str =~ '^\s\+$'
istitle() str.istitle() str =~ '\(\<\u\l\+\>\)\s\?'
isupper() str.isupper() str =~ '^\u\+$'
join() ':'.join(['a', 'b', 'c']) join(['a', 'b', 'c'], ':')
ljust() 'abc'.ljust(10) Not available
lower() 'Hello'.lower() 'Hello'->tolower()
lstrip() ' vim '.lstrip() ' vim '->trim(' ', 1)
partition() 'ab-cd-ef'.partition('-') 'ab-cd-ef'->matchlist('\(.\{-}\)\(-\)\(.*\)')[1:3]
replace() 'abc'.replace('abc', 'xyz') 'abc'->substitute('abc', 'xyz', 'g')
rfind() 'running'.rfind('ing') 'running'->strridx('ing')
rindex() 'running'.rindex('ing') 'running'->strridx('ing')
rjust() 'abc'.rjust(10) Not available
rpartition() 'ab-cd-ef'.rpartition('-') 'ab-cd-ef'->matchlist('\(.*\)\(-\)\(.*\)')[1:3]
rsplit() 'a-b-c-d'.rsplit('-', 2) Not available
rstrip() ' vim '.rstrip() ' vim '->trim(' ', 2)
split() 'a-b-c'.split('-') 'a-b-c'->split('-')
splitlines() "one\ntwo".splitlines() "one\ntwo"->split("\n")
startswith() 'running'.startswith('run') 'running' =~# '^run'
strip() ' vim '.strip() ' vim '->trim()
swapcase() 'Abc'.swapcase() Not available
title() 'onE twO'.title() 'onE twO'->substitute('\<\(.\)\(\S\+\)\>', '\u\1\L\2', 'g')
translate() 'abcd'.translate(string.maketrans('bd', '12')) 'abcd'->tr('bd', '12')
upper() 'Hello'.upper() 'Hello'->toupper()
zfill() str.zfill(10) Not available

Help: string-functions


List

Creating a List

Python:

l = [1, 2, 3, 4]

VimScript:

let l = [1, 2, 3, 4]

Help: List

Accessing a List element

Python:

l = [1, 2, 3, 4]
v1 = l[2]
v2 = l[-2]

VimScript:

let l = [1, 2, 3, 4]
let v1 = l[2]
let v2 = l[-2]

Help: list-index

Changing the value of a List element

Python:

l = [1, 2, 3, 4]
l[3] = 5

VimScript:

let l = [1, 2, 3, 4]
let l[3] = 5

Help: list-modification

Adding an item to a List

Python:

l = []
l.append(5)
l += [6, 7]

VimScript:

let l = []
call add(l, 5)
let l += [5, 6]

Help: add()

Extending a List using another List

Python:

l = []
l.extend([2, 3])
l += [6, 7]

VimScript:

let l = []
call extend(l, [2, 3])
let l += [6, 7]

Help: extend()

Inserting an item in a List

Python:

l = [1, 3]
l.insert(1, 2)

VimScript:

let l = [1, 3]
" insert before index 1
eval l->insert(2, 1)
" insert at the begining
eval l->insert(5)

Help: insert()

Removing an item from a List

Python:

l = [4, 5, 6]
l.remove(5)
del l[0]

VimScript:

let l = [4, 5, 6]
let idx = index(l, 5)
if idx != -1
  call remove(l, idx)
endif
unlet l[0]

Help: remove(), :unlet

Removing the last element from a List

Python:

l = [1, 2, 3]
v = l.pop()

VimScript:

let l = [1, 2, 3]
let v = l->remove(-1)

Help: remove()

Find the index of an item in a List

Python:

l = [1, 2, 3]
x = l.index(2)

VimScript:

let l = [1, 2, 3]
let x = l->index(2)

Help: index()

Find the index of an item in a List of Dicts by a Dict item value

Python:

colors = [{'color': 'red'}, {'color': 'blue'}, {'color': 'green'}]
idx = next((i for i, v in enumerate(colors) if v['color'] == 'blue'), -1)
print(idx)

VimScript:

let colors = [{'color': 'red'}, {'color': 'blue'}, {'color': 'green'}]
let idx = indexof(colors, {i, v -> v.color == 'blue'})
echo idx

Help: indexof()

List slices

In Python, when using an index range to specify a series of items in a List, the item at the end index is not included. In Vim, the item at the end index is included. The slice() function excludes the item at the end index.

Python:

l = [1, 2, 3, 4]
print(l[1:3])
print(l[2:])

VimScript:

let l = [1, 2, 3, 4]
echo l[1:3]
echo l[2:]
echo l[-2:]

" slice() function excludes the item at the end index.
echo slice(l, 2, 3)
echo slice(l, 2)

Help: sublist, slice()

List Concatenation

Python:

l = [1, 2] + [3 ,4]

VimScript:

let l = [1, 2] + [3 ,4]

Help: list-index

Adding multiple items to a List using repetition

Python:

l = ['vim'] * 4

VimScript:

let l = ['vim']->repeat(4)

Help: repeat()

Count the number of occurrences of an item in a List

Python:

l = [2, 4, 4, 5]
x = l.count(4)

VimScript:

let l = [2, 4, 4, 5]
let x = l->count(2)

Help: count()

Finding the List length

Python:

l = ['a', 'b', 'c']
n = len(l)

VimScript:

let l = ['a', 'b', 'c']
let n = l->len()

Help: len()

List Iteration

Python:

l = [10, 20, 30]
for v in l:
  print(v)

# Print both the list index and the value
for i, v in enumerate(l):
  print(i, v)

# Use a for loop for list iteration
for i in range(len(l)):
  print(i, l[i])

VimScript:

let l = [10, 20, 30]
for v in l
  echo v
endfor

" Print both the list index and the value
for [i, v] in items(l)
  echo i v
endfor

" Use a for loop for list iteration
for i in range(len(l))
  echo i l[i]
endfor

Help: :for

Sort a List

Python:

l = [3, 2, 1]
l.sort()
print(l)

VimScript:

let l = [3, 2, 1]
echo l->sort()

Help: sort()

Getting unique elements in a List

Python:

l = ['a', 'b', 'b', 'c', 'c', 'd']
# order of the elements is not retained
tset = set(l)
print(list(tset))

VimScript:

" needs a sorted list
let l = ['a', 'b', 'b', 'c', 'c', 'd']
echo copy(l)->uniq()

Help: uniq()

Reverse a List

Python:

l = [1, 2, 3]
l.reverse()
print(l)

VimScript:

let l = [1, 2, 3]
echo reverse(l)

Help: reverse()

Copying a List

Python:

l = [3, 2, 1]
l2 = l.copy()

VimScript:

let l = [3, 2, 1]
let l2 = l->copy()

Help: copy()

Deep Copying a List

Python:

import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)

VimScript:

let a = [[1, 2], [3, 4]]
let b = a->deepcopy()

Help: deepcopy()

Empty a List

Python:

l = [3, 2, 1]
l.clear()

VimScript:

let l = [3, 2, 1]
unlet l[:]

Help: :unlet

Comparing two Lists

Python:

l1 = [1, 2]
l2 = l1
l3 = [1, 2]
if l1 is l2:
  print("Lists l1 and l2 refer to the same list")
if l1 is not l3:
  print("Lists l1 and l3 do not refer to the same list")
if l1 == l3:
  print("Lists l1 and l3 contain the same elements")
if l1 != l3:
  print("Lists l1 and l3 are different")

VimScript:

let l1 = [1, 2]
let l2 = l1
let l3 = [1, 2]
if l1 is l2
  echo "Lists l1 and l2 refer to the same list"
endif
if l1 isnot l3
  echo "Lists l1 and l2 do not refer to the same list"
endif
if l1 == l3
  echo "Lists l1 and l3 contain the same elements"
endif
if l1 != l3
  echo "Lists l1 and l3 are different"
endif

Help: list-identity

Filter selected elements from a List

Note that Vim does not support List comprehension.

Python:

odd = list(filter(lambda x: x % 2, range(10)))
odd = [x for x in range(10) if x % 2]

VimScript:

let odd = filter(range(10), {idx, v -> v % 2})

Help: filter()

Map List elements

Note that Vim does not support List comprehension.

Python:

num_str = list(map(lambda x: str(x), range(10)))
num_str = [str(x) for x in range(10)]

VimScript:

let num_str = map(range(10), {idx, v -> string(v)})

Help: map()

Reducing List elements

Python:

# using a lambda function
from functools import reduce
sum = reduce((lambda x, y: x + y), [1, 2, 3, 4])

# using a function
def SumNum(a, b):
    return a + b
sum = reduce(SumNum, [1, 2, 3, 4])

VimScript:

" using a lambda function
let sum = reduce([1, 2, 3, 4], {x, y -> x + y})

" using a function
func SumNum(x, y)
  return a:x + a:y
endfunc
let sum = reduce([1, 2, 3, 4], function('SumNum'))
echo sum

Help: reduce()

Flattening a List

Python:

l = [[5, 9], [1, 3], [10, 20]]
flattenlist = [i for subl in l for i in subl]
print(flattenlist)

VimScript:

let l = [[5, 9], [1, 3], [10, 20]]
let flattenlist = flattennew(l)
echo flattenlist

Help: flatten(), flattennew()

Finding the mix/max value in a List

Python:

l = [3, 10, 8]
v1 = min(l)
v2 = max(l)
print(v1, v2)

VimScript:

let l = [3, 10, 8]
let v1 = l->min()
let v2 = l->max()
echo v1 v2

Help: max(), min()

Converting a List to a string

Python:

s = str([3, 5, 7])

VimScript:

let s = string([3, 5, 7])

Help: string()

List Methods

Method Python VimScript
append() m.append(6) m->add(6)
clear() m.clear() unlet m[:]
copy() m.copy() m->copy()
count() m.count(6) m->count(6)
extend() m.extend([5, 6]) m->extend([5, 6])
index() m.index(6) m-index(6)
insert() m.insert(2, 9) m->insert(9, 2)
pop() m.pop() m->remove(-1)
remove() m.remove(6) m->remove(m->index(6))
reverse() m.reverse() m->reverse()
sort() m.sort() m->sort()

Help: list-functions


Dictionary

Creating a Dict

Python:

d = {'red' : 10, 'blue' : 20}
x = {}

VimScript:

let d = {'red' : 10, 'blue' : 20}
let d = #{red : 10, blue : 20}
let x = {}

Help: Dict

Retrieving the value of a Dict item

Python:

d = {'red' : 10, 'blue' : 20}
x = d['red']

VimScript:

let d = #{red : 10, blue : 20}
let x = d['red']
let x = d.red

Help: dict

Changing the value of a Dict item

Python:

d = {'red' : 10, 'blue' : 20}
d['red'] = 15

VimScript:

let d = #{red : 10, blue : 20}
let d.red = 15

Help: dict-modification

Accessing a Dict item

Python:

d = {'red' : 10, 'blue' : 20}
v = d.get('red')

VimScript:

let d = {'red' : 10, 'blue' : 20}
let v = get(d, 'red')

Help: get()

Adding a new Dict item

Python:

d = {'red' : 10, 'blue' : 20}
d['green'] = 30

VimScript:

let d = {'red' : 10, 'blue' : 20}
let d.green = 30

Help: dict-modification

Extending a Dict using another Dict

Python:

d = {}
d.update({'color' : 'grey'})

VimScript:

let d = {}
eval d->extend({'color' : 'grey'})

Help: extend()

Removing an item from a Dict

Python:

d = {'red' : 10, 'blue' : 20}
d.pop('red')

VimScript:

let d = {'red' : 10, 'blue' : 20}
call remove(d, 'red')

Help: remove(),

Clearing all the items from a Dict

Python:

d = {'red' : 10, 'blue' : 20}
d.clear()

VimScript:

let d = {'red' : 10, 'blue' : 20}
call filter(d, "0")

Help: dict-modification

Getting the size of a Dict

Python:

d = {'red' : 10, 'blue' : 20}
n = len(d)

VimScript:

let d = {'red' : 10, 'blue' : 20}
let n = d->len()

Help: len()

Count the number of occurrences of a value in a Dict

Python:

d = {'red' : 10, 'blue' : 10}
x = sum(n == 10 for n in d.values())
print(x)

VimScript:

let d = {'red' : 10, 'blue' : 10}
let x = d->count(10)
echo x

Help: count()

Checking Dict membership

Python:

d = {'red' : 10, 'blue' : 20}
if 'red' in d:
    print("found red key")

VimScript:

let d = {'red' : 10, 'blue' : 20}
if d->has_key('red')
  echo "found red key"
endif

Help: has_key()

Iterating through all the keys in a Dict

Python:

d = {'red' : 10, 'blue' : 20}
for k in d:
    print(k)
for k in d:
    print(d[k])

VimScript:

let d = {'red' : 10, 'blue' : 20}
for k in keys(d)
  echo k
endfor
for k in d->keys()
  echo d[k]
endfor

Help: keys()

Iterating through all the values in a Dict

Python:

d = {'red' : 10, 'blue' : 20}
for v in d.values():
    print(v)

VimScript:

let d = {'red' : 10, 'blue' : 20}
for v in d->values()
  echo v
endfor

Help: values()

Iterating through all the key, value pairs in a Dict

Python:

d = {'red' : 10, 'blue' : 20}
for k, v in d.items():
    print(k, v)

VimScript:

let d = {'red' : 10, 'blue' : 20}
for [k, v] in d->items()
  echo k v
endfor

Help: items()

Copying a Dict

Python:

d = {'red' : 10, 'blue' : 20}
new_d = d.copy()

VimScript:

let d = {'red' : 10, 'blue' : 20}
let new_d = d->copy()

Help: copy()

Deep Copying a Dict

Python:

import copy
a = {'x' : [1, 2], 'y' : [3, 4]}
b = copy.deepcopy(a)

VimScript:

let a = {'x' : [1, 2], 'y' : [3, 4]}
let b = a->deepcopy()

Help: deepcopy()

Comparing two Dicts

Python:

d1 = {'a' : 10, 'b' : 20}
d2 = {'a' : 10, 'b' : 20}
if d1 == d2:
    print("Dicts d1 and d2 have the same content")
d3 = d1
if d1 is d3:
  print("Dicts d1 and d3 refer to the same dict")
if d2 is not d3:
  print("Dicts d2 and d3 do not refer to the same dict")

VimScript:

let d1 = {'a' : 10, 'b' : 20}
let d2 = {'a' : 10, 'b' : 20}
if d1 == d2
  echo "Dicts d1 and d2 have the same content"
endif
let d3 = d1
if d1 is d3
  echo "Dicts d1 and d3 refer to the same dict"
endif
if d2 isnot d3
  echo "Dicts d2 and d3 do not refer to the same dict"
endif

Help: dict-identity

Filter selected elements from a Dict

Note that Vim does not support Dict comprehension.

Python:

d1 = {'red' : 10, 'green' : 20, 'blue' : 10}
# filter dict items with value 10
d2 = dict(filter(lambda e : e[1] == 10, d1.items()))
print(d1, d2)
# use dict comprehension
d3 = {k: v for [k, v] in d1.items() if v == 10}
print(d1, d3)

VimScript:

let d1 = {'red' : 10, 'green' : 20, 'blue' : 10}
" filter dict items with value 10
let d2 = copy(d1)->filter({k, v -> v == 10})
echo d1 d2

Help: filter()

Map Dict elements

Note that Vim does not support Dict comprehension.

Python:

d1 = {'red' : 10, 'green' : 20, 'blue' : 30}
# increment the values by 5
d2 = dict(map(lambda e : (e[0], e[1] + 5), d1.items()))
print(d1, d2)
# use dict comprehension
d3 = {k: v + 5 for k, v in d1.items()}
print(d1, d3)

VimScript:

let d1 = {'red' : 10, 'green' : 20, 'blue' : 30}
" increment the values by 5
let d2 = copy(d1)->map({k, v -> v + 5})
echo d1 d2

Help: map()

Finding the min/max value in a Dict

Python:

d = {'red' : 10, 'green' : 20}
v1 = min(d.values())
v2 = max(d.values())
print(v1, v2)

VimScript:

let d = {'red' : 10, 'green' : 20}
let v1 = d->min()
let v2 = d->max()
echo v1 v2

Help: max(), min()

Converting a Dict to a string

Python:

d = str({'a' : 1, 'b' : 2})

VimScript:

let d = string({'a' : 1, 'b' : 2})

Help: string()

Dictionary Methods

Method Python VimScript
clear() d.clear() call filter(d, '0')
copy() newDict = d.copy() let newDict = d->copy()
fromkeys() d = dict.fromkeys(x) Not available
get() v = d.get('red') let v = d->get('red')
in or has_key() 'red' in d d->has_key('red')
items() d.items() d->items()
keys() d.keys() d->keys()
pop() d.pop('red') call d->remove('red')
popitem() d.popitem() Not available
setdefault() d.setdefault('red', 10) Not available
update() d.update({'a' : 10, 'b' : 20} d->extend({'a' : 10, 'b' : 20})
values() d.values() d->values()

Help: dict-functions


If statement

Basic If statement

Python:

if a > b:
    print("a is greater than b")

VimScript:

if a > b
  echo "a is greater than b"
endif

Help: :if

If-else statement

Python:

if a > b:
    print("a is greater than b")
else:
    print("a is less than or equal to b")

VimScript:

if a > b
  echo "a is greater than b"
else
  echo "a is less than or equal to b"
endif

Help: :else

If-elseif statement

Python:

if a > b:
    print("a is greater than b")
elif a < b:
    print("a is less than b")
else:
    print("a is equal to b")

VimScript:

if a > b
  echo "a is greater than b"
elseif a < b
  echo "a is less than b"
else
  echo "a is equal to b"
endif

Help: :elseif

Checking multiple conditions

Python:

if a > b and (a > c or a > d):
    print "a is greater than b and greater than c or d"

VimScript:

if a > b && (a > c || a > d)
  echo "a is greater than b and greater than c or d"
endif

Help: expr2

Nested If statements

Python:

if status == True:
    if a >= 1:
        print("Nested if")

VimScript:

if status == v:true
  if a >= 1
    echo "Nested if"
  endif
endif

Help: :if


For Loop

Python:

for i in range(5):
    print(i)

VimScript:

for i in range(5)
  echo i
endfor

Help: :for

Breaking out of a For loop

Python:

for i in ['a', 'b', 'c']:
    if i == 'b':
        break
    print(i)

VimScript:

for i in ['a', 'b', 'c']
  if i == 'b'
    break
  endif
  echo i
endfor

Help: :break

Continuing a For loop

Python:

for i in ['a', 'b', 'c']:
    if i == 'b':
        continue
    print(i)

VimScript:

for i in ['a', 'b', 'c']
  if i == 'b'
    continue
  endif
  echo i
endfor

Help: :continue

Nested For Loops

Python:

for i in range(10):
    for j in range(10):
        print(str(i) + 'x' + str(j) + '=' + str(i * j))

VimScript:

for i in range(4)
  for j in range(4)
    echo i .. 'x' .. j .. '=' .. i * j
  endfor
endfor

Help: :for


While Loop

Python:

i = 1
while i <= 5 :
   print(i)
   i += 1

VimScript:

let i = 1
while i <= 5
  echo i
  let i += 1
endwhile

Help: :while


Comment

Python:

# This is a python comment
i = 0    # First iteration

VimScript:

" This is a Vimscript comment
let i = 0    " First iteration

Help: :comment


Function

The names of global functions in Vim must start with an uppercase letter. The examples in this document use the "function" and "endfunction" keywords for defining a function. But these can be abbreviated as "func" and "endfunc".

When a function encounters an error, it will continue to execute the rest of the function unless the "abort" argument is specified when defining the function. So it is recommended to specify the "abort" keyword at the end of the "function" line. To simplify the example code, this keyword is not used in this guide.

Defining a Function

Python:

def Min(x, y):
    return x if < y else y

print(Min(6, 3)

VimScript:

function Min(x, y) abort
  return a:x < a:y ? a:x : a:y
endfunction

echo Min(6, 3)

Help: user-functions

Calling a Function

Python:

def EchoValue(v):
    print(v)

EchoValue(100)

VimScript:

function EchoValue(v)
  echo a:v
endfunction

call EchoValue(100)

Help: :call

Function return value

Python:

def Sum(a, b):
    return a + b

s = Sum(10, 20)

VimScript:

function Sum(a, b)
  return a:a + a:b
endfunction

let s = Sum(10, 20)

Help: :return

Pass by reference

Python:

def AddValues(l):
    l.extend([1, 2, 3, 4])

VimScript:

function AddValues(l)
  call extend(a:l, [1, 2, 3, 4])
endfunction

Help: function-argument

Variable number of arguments

Python:

def Sum(v1, *args):
    sum = v1
    for i in *args:
        sum += i
    return sum

VimScript:

function Sum(v1, ...)
  let sum = a:v1
  for i in a:000
    let sum +=i
  endfor
  return sum
endfunction
let s1 = Sum(10, 20, 30, 40)
let s1 = Sum(10)

Help: a:000

Default value for arguments

Python:

def Powerof(base, exp = 2):
    return base ** exp

VimScript:

function PowerOf(base, exp = 2)
  return float2nr(pow(a:base, a:exp))
endfunction
let val = PowerOf(4)
let val = PowerOf(4, 3)

Help: optional-function-argument

Accessing global variables

Python:

counter = 1
def Incr():
    global counter
    counter += 1

VimScript:

let counter = 1
function Incr()
  let g:counter += 1
endfunction
cal Incr()

Help: global-variable

Function reference

Python:

def Foo():
    print("Foo")
Bar = Foo
Bar()

VimScript:

function Foo()
  echo "Foo"
endfunction
let Bar = function("Foo")
call Bar()

Help: Funcref


Lambda Function

Python:

F = lambda x , y: x - y
print(F(5,2))

VimScript:

let F = {x, y -> x - y}
echo F(5,2)

Help: lambda


Partial Function

Python:

import functools
def Mylog(subsys, msg):
    print("%s: %s" % (subsys, msg))

ErrLog = functools.partial(Mylog, 'ERR')
ErrLog("Failed to open file")

VimScript:

function Mylog(subsys, msg)
  echo printf("%s: %s", a:subsys, a:msg)
endfunction

let ErrLog = function('Mylog', ['ERR'])
call ErrLog("Failed to open file")

Help: Partial


Closure

Closure with a lambda function

Python:

def foo(arg):
  i = 3
  return lambda x: x + i - arg

bar = foo(4)
print(bar(6))

VimScript:

function Foo(arg)
  let i = 3
  return {x -> x + i - a:arg}
endfunction

let Bar = Foo(4)
echo Bar(6)

Help: closure

Closure with a function reference

Python:

def Foo(base):
    def Bar(val):
        return base + val
    return Bar

F = Foo(10)
print(F(2))
F = Foo(20)
print(F(2))

VimScript:

function Foo(base)
  function Bar(val) closure
    return a:base + a:val
  endfunction
  return funcref('Bar')
endfunction

let F = Foo(10)
echo F(2)
let F = Foo(20)
echo F(2)

Help: func-closure


Class

Defining a class

Python:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    def setX(self, x):
        self.x = x

    def setY(self, y):
        self.y = y

    def Print(self):
        print("Pt = (" + str(self.x) + ", " + str(self.y) + ")")

pt = Point(10, 20)
pt.setX(40)
pt.setY(50)
pt.Print()

VimScript:

function s:new(x, y) dict
  let newpt = copy(self)
  let newpt.x = a:x
  let newpt.y = a:y
  return newpt
endfunction

function s:getX() dict
  return self.x
endfunction

function s:getY() dict
  return self.y
endfunction

function s:setX(x) dict
  let self.x = a:x
endfunction

function s:setY(y) dict
  let self.y = a:y
endfunction

function s:Print() dict
  echo "Pt = (" .. self.x .. ", " .. self.y .. ")"
endfunction

let Point = {}
let Point.new = function("s:new")
let Point.getX = function("s:getX")
let Point.getY = function("s:getY")
let Point.setX = function("s:setX")
let Point.setY = function("s:setY")
let Point.Print = function("s:Print")

let p = Point.new(10, 20)
call p.setX(40)
call p.setY(50)
call p.Print()

Help: Dictionary-function, numbered-function, :func-dict


Exception Handling

Basic exception handling

Python:

try:
    f = open('buf.java', 'r')
    lines = f.readlines()
    f.close()
except IOError:
    print("Failed to open file")

VimScript:

try
  let l = readfile('buf.java')
catch /E484:/
  echo "Failed to read file"
endtry

Help: exception-handling

Catching all exceptions

Python:

try:
    f = open('buf.java', 'r')
    lines = f.readlines()
    f.close()
except Exception as e:
    print("Caught " + str(e))

VimScript:

try
  let l = readfile('buf.java')
catch
  echo "Caught " .. v:exception
endtry

Help: catch-errors

Executing code after a try block (finally)

Python:

try:
    f = open('buf.java', 'r')
    lines = f.readlines()
    f.close()
finally:
    print("executing code in finally block")

VimScript:

try
  let l = readfile('buf.java')
finally
  echo "executing code in finally block"
endtry

Help: try-finally

Raising a custom exception

Python:

try:
    raise Exception('MyException')
except Exception as e:
    if str(e) == 'MyException':
        print("Caught MyException")
finally:
    print("Finally block")

VimScript:

try
  throw 'MyException'
catch /MyException/
  echo "Caught MyException"
finally
  echo "Finally block"
endtry

Help: throw-catch


Line Continuation

Python:

a = 1 + 2 + 3 + \
      4 + 5 + 6

VimScript:

let a = 1 + 2 + 3 +
      \ 4 + 5 + 6

Help: line-continuation


File Operations

Reading all the lines from a file

Vim has a function to read the entire file but doesn't have a function to read a file one line at a time.

Python:

with open('myfile.txt', 'r') as f:
    lines = f.readlines()
# lines == ['line1\n', 'line2\n'] 

VimScript:

let lines = readfile("myfile.txt")
" lines == ['line1', 'line2'] 

Help: readfile()

Writing lines to a file

Python:

lines = ['line1\n', 'line2\n']
with open('myfile.txt', 'w') as fh:
    fh.writelines(lines)
    
lines = ['line1', 'line2']
with open('myfile.txt', 'w') as fh:
    print(*lines, sep='\n', file=fh)

VimScript:

call writefile(['line1', 'line2'], 'myfile.txt')

Help: writefile()

Appending lines to a file

Python:

lines = ["line3\n", "line4\n"]
with open('myfile.txt', 'a') as fh:
    fh.writelines(lines)

VimScript:

call writefile(['line3', 'line4'], 'myfile.txt', 'a')

Help: writefile()

Checking whether a file exists

Python:

import os.path
if os.path.isfile('myfile.txt'):
    print("File exists")

VimScript:

if filereadable('myfile.txt')
  echo "File is readable"
endif

Help: filereadable()

Deleting a file

Python:

import os
os.remove('myfile.txt')

VimScript:

call delete('myfile.txt')

Help: remove()

Renaming a file

Python:

import os
os.rename('myfile.txt', 'somefile.txt)

VimScript:

call rename('myfile.txt', 'somefile.txt')

Help: rename()

Getting the size of a file

Python:

import os
sz = os.path.getsize('move.py')

VimScript:

let sz = getfsize('move.py')

Help: getfsize()


Directory Operations

Creating a directory

Python:

os.mkdir('somedir')

VimScript:

call mkdir('somedir')

Help: mkdir()

Changing to a directory

Python:

os.chdir('someotherdir')

VimScript:

call chdir('someotherdir')

Help: chdir()

Getting the current directory

Python:

dir = os.getcwd()

VimScript:

let dir = getcwd()

Help: getcwd()

Deleting a directory

Python:

os.rmdir('somedir')

VimScript:

call delete('somedir', 'd')

Help: delete()

Reading the directory contents

Python:

import os
dir = os.scandir('.')
for f in dir:
  print(f.name)

# get extended file information
dir = os.scandir('.')
for f in dir:
  print(f.stat())

VimScript:

let dir = readdir('.')
for f in dir
  echo f
endfor

" get extended file information
let dir = readdirex('.')
for f in dir
  echo f
endfor

Help: readdir(), readdirex(), glob()


Random numbers

Generating a random number

Python:

import random
r = random.randint(0, 2147483647)

VimScript:

let r = rand()

Help: rand()

Generating a random number from a seed

Python:

import random
random.seed()
r = random.randint(0, 2147483647)
print(r)

VimScript:

let seed = srand()
let r = rand(seed)

Help: srand()


Mathematical Functions

Function Python VimScript
abs f = math.fabs(-10) let f = abs(-10)
acos f = math.acos(0.8) let f = acos(0.8)
asin f = math.asin(0.8) let f = asin(0.8)
atan f = math.atan(0.8) let f = atan(0.8)
atan2 f = math.atan2(0.4, 0.8) let f = atan2(0.4, 0.8)
ceil f = math.ceil(1.2) let f = ceil(1.2)
cos f = math.cos(4) let f = cos(4)
cosh f = math.cosh(4) let f = cosh(4)
exp f = math.exp(2) let f = exp(2)
floor f = math.floor(1.4) let f = floor(1.4)
log f = math.log(12) let f = log(12)
log10 f = math.log10(100) let f = log10(100)
mod f = math.fmod(4, 3) let f = fmod(4, 3)
pow f = math.pow(2, 3) let f = pow(2, 3)
sin f = math.sin(4) let f = sin(4)
sinh f = math.sinh(4) let f = sinh(4)
sqrt f = math.sqrt(9) let f = sqrt(9)
tan f = math.tan(4) let f = tan(4)
tanh f = math.tanh(4) let f = tanh(4)
trunc f = math.trunc(1.3) let f = trunc(1.3)

Help: ceil(), abs(), floor(), fmod(), trunc(), exp(), log(), log10(), pow(), sqrt(), cos(), sin(), tan(), cosh(), sinh(), tanh(), acos(), asin(), atan(), atan2()


Date/Time functions

Get current date and time

Python:

from datetime import datetime
d = datetime.now()
print(d.strftime("%c"))

VimScript:

echo strftime("%c")

Help: strftime()

Parse a date/time string

Python:

from datetime import datetime
print(datetime.strptime("1997 Apr 27 11:49:23", "%Y %b %d %X"))

VimScript:

echo strptime("%Y %b %d %X", "1997 Apr 27 11:49:23")

Help: strptime()

Getting the time in seconds since epoch

Python:

import time
print int(time.time())

VimScript:

echo localtime()

Help: localtime()

Measuring elapsed time

Python:

import time
start_time = time.perf_counter()
sum = 1
for i in range(1000):
    sum += i
end_time = time.perf_counter()
print("Elapsed time " + str(end_time - start_time))

VimScript:

let start = reltime()
let sum = 0
for i in range(1000)
  let sum += i
endfor
let elapsed_time = reltime(start)
echo "Elasped time" reltimefloat(elapsed_time)

Help: reltime(), reltimestr(), reltimefloat()


External commands

Getting the output of an external command as a string

Python:

import subprocess
procObj = subprocess.Popen('grep class *.java',
    stdout=subprocess.PIPE,
    shell=True)
lines, err = procObj.communicate()
print(lines)
print("Error = " + str(procObj.returncode))

VimScript:

let lines = system('grep class *.java')
echo lines
echo "Error = " .. v:shell_error

Help: system(), v:shell_error

Splitting the output of an external command into lines

Python:

import subprocess
procObj = subprocess.Popen('grep class *.java',
    stdout=subprocess.PIPE,
    shell=True)
lines, err = procObj.communicate()
print("Number of matches = " + str(len(lines.splitlines())))

VimScript:

let lines = systemlist('grep class *.java')
echo "Number of matches = " .. len(lines)

Help: systemlist()

Sending input to an external command and getting the output

Python:

import subprocess
procObj = subprocess.Popen('wc',
    stdout=subprocess.PIPE,
    stdin=subprocess.PIPE,
    shell=True)
lines, err = procObj.communicate("one\ntwo\n")
print(lines)
print("Error = " + str(procObj.returncode))

VimScript:

let lines = system('wc', "one\ntwo\n")
echo lines
echo "Error = " .. v:shell_error

Help: system()


User Input/Output

Getting input from the user

Python:

choice = input("coffee or tea? ")
print("You selected " + choice)

VimScript:

let ans = input("coffee or tea? ", "tea")
echo "You selected " .. ans

Help: input(), inputlist(), inputdialog()

Getting password from the user

Python:

import getpass
passwd = getpass.getpass("Password: ")
print("You entered " + passwd)

VimScript:

let passwd = inputsecret("Password: ")
echo "You entered " .. passwd

Help: inputsecret()

Print an expression

Python:

print("Hello World\n")
s = "vim"
print("Editor = %s" % (s))

VimScript:

echo "Hello World"
let s = "vim"
echo "Editor = " .. s

Help: :echo, :echon, echoraw(), :echohl, :echoerr, :echomsg

Formatted Output

Python:

name = "John"
id = 1001
print(f"Name: {name}, ID: {id}")
print("Name: {}, ID: {}".format(name, id))
print("Name: %s, ID: %d" % (name, id))

VimScript:

let name = "John"
let id = 1001
echo printf("Name: %s, ID: %d", name, id)

Help: printf()


Environment Variables

Getting the value of an environment variable

Python:

import os
h = os.environ.get('HOME', '')
if h == '':
    print("HOME is not set")
else:
    print("HOME = " + h)

VimScript:

let h = getenv('HOME')
if h == v:null
  echo 'HOME is not set'
else
  echo 'HOME = ' .. h
endif

if !exists('$HOME')
  echo 'HOME is not set'
else
  echo 'HOME = ' .. $HOME
endif

Help: getenv(), expr-env, exists()

Setting an environment variable

Python:

import os
os.environ['FOO'] = "BAR"

VimScript:

call setenv('FOO', 'BAR')

let $FOO = 'BAR'

Help: setenv(), :let-environment

Removing an environment variable

Python:

import os
del os.environ['FOO']

VimScript:

call setenv('FOO', v:null)

unlet $FOO

Help: setenv(), :unlet-environment

Getting all the environment variables

Python:

import os
print(os.environ)

VimScript:

echo environ()

Help: environ()


Command-line Arguments

Displaying the command-line arguments

Python:

import sys
print("Number of arguments = " + str(len(sys.argv)))
print("Arguments = " + str(sys.argv))
for arg in sys.argv:
    print(arg)

VimScript:

echo "Number of arguments = " .. len(v:argv)
echo "Arguments = " .. string(v:argv)
for arg in v:argv
  echo arg
endfor

Help: v:argv


Regular Expressions

Finding whether a pattern matches a string

Python:

import re
s = 'Test failed with error E123:'
if re.search(r'E\d+:', s):
    print('Error code found')

s = 'Test successful'
if re.search(r'E\d+:', s) is None:
    print("Test passed")

VimScript:

let s = 'Test failed with error E123:'
if s =~# 'E\d\+:'
  echo "Error code found"
endif

let s = 'Test successful'
if s !~# 'E\d\+:'
  echo "Test passed"
endif

Help: expr-=~, expr-!~

Finding the beginning or ending index of a pattern in a string

Python:

import re
m = re.search(r'\d+', "Abc 123 Def")
if m is not None:
    idx = m.start()
    end_idx = m.end()

VimScript:

let idx = match("Abc 123 Def", '\d\+')
let end_idx = matchend("Abc 123 Def", '\d\+')

let l = matchstrpos("Abc 123 Def", '\d\+')
echo "start:" l[1] "end:" l[2]

Help: match(), matchend(), matchstrpos()

Getting matching substring using a pattern

Python:

import re
m = re.search(r'\d+', "Abc 123 Def")
if m is not None:
    s = m.group(0)
    print s

VimScript:

let s = matchstr("Abc 123 Def", '\d\+')

Help: matchstr()

Getting multiple matches using a pattern

Python:

import re
m = re.match(r'(\w+) (\w+) (\w+)', "foo bar baz")
if m is not None:
    print("Full match: " + m.group(0))
    print("1: " + m.group(1) + " 2: " + m.group(2) + " 3: " + m.group(3))

VimScript:

let list = matchlist("foo bar baz", '\(\w\+\) \(\w\+\) \(\w\+\)')
echo "Full match:" list[0]
echo "1:" list[1] "2:" list[2] "3:" list[3]

Help: matchlist()

Substituting text using a pattern

Python:

import re
s = re.sub(r'bar', r'baz', "foo bar")
print(s)

VimScript:

let s = substitute("foo bar", 'bar', 'baz', '')
echo s

Help: substitute()

Using a function to get the replacement string

Python:

import re
def Dashrepl(m):
  if m.group(0) == '-':
    return ' '
  else:
    return '-'
s = re.sub('-{1,2}', Dashrepl, 'pro----gram-files')
print(s)

VimScript:

function Dashrepl(m)
  if a:m[0] == '-'
    return ' '
  else
    return '-'
  endif
endfunction
let s = substitute("pro----gram-files", '-\{1,2}', function('Dashrepl'), 'g')
echo s

Help: substitute()

Regular expression comparison

Note that the below table contains only the regular expressions that are present in both Python and Vim.

What Python Vim
single character . .
start of string ^ ^
end of string $ $
0 or more matches * *
1 or more matches + \+
0 or 1 match ? \?
non-greedy match *? \{-}
fixed matches {n} \{n}
m to n matches {m,n} \{m,n}
m to n non-greedy matches {m,n}? \{-m,n}
character class [...] [...]
negated character class [^...] [^...]
range [a-z] [a-z]
either-or branch | \|
capturing group (...) \(...\)
non-capturing match (?:...) \%(...\)
positive look-ahead (?=...) \(...\)\@=
negative look-ahead (?!...) \(...\)\@!
positive look-behind (?<=...) \(...\)\@<=
negative look-behind (?<!...) \(...\)\@<!
start of word \b \<
end of word \b \>
digit \d \d
non-digit \D \D
whitespace \s \s
non-whitespace \S \S
word character \w \w
non-word character \W \W
ignore case (?i) \c

Help: pattern


Binary Data

Storing binary data in a variable

Python:

data = bytearray(b'\x12\xF6\xAB\xFF\x49\xC0\x88\x3A\xE2\xC1\x42\xAA')
print(data)
print(data[0:4])

VimScript:

let data = 0z12F6ABFF.49C0883A.E2C142AA
echo data
echo data[0:3]

Help: blob

Manipulating binary data stored in a variable

Python:

data = bytearray(b'')
data.append(0xC2)
data += b'\xB3\xF7\xA5'
del data[2]
print(data)

VimScript:

let data = 0z
let data[0] = 0xC2
let data += 0zB3F7A5
call remove(data, 2)
echo data

Help: blob-index, blob-modification

Converting a List of numbers to binary data and vice versa

Python:

l = [11, 12, 14]
data = bytearray(l)
print(data)

data = bytearray(b'\xDE\xAD\xBE\xEF')
l = list(data)
print(l)

VimScript:

let l = [11, 12, 14]
let data = list2blob(l)
echo data

let data = 0zDEADBEEF
let  l = blob2list(data)
echo l

Help: list2blob(), blob2list()

Reading and writing binary data from a file

Python:

with open("datafile.bin", "rb") as bin_fh:
    data = bytearray(bin_fh.read())

with open("data2.bin", "wb") as bin_fh:
    bin_fh.write(data)

VimScript:

let data = readblob('datafile.bin')
call writefile(data, 'data2.bin')

Help: readblob(), writefile()


Timers

One-shot Timer

Python:

import threading
def TimerCallback(ctx):
    print("Timer callback, context = " + ctx)

timer = threading.Timer(5, TimerCallback, args=["green"])
timer.start()

VimScript:

func TimerCallback(ctx, timer_id)
  echo "Timer callback, context = " .. a:ctx .. ", id = " .. a:timer_id
endfunc

" Run a function after 5 seconds
let timer_id = timer_start(5 * 1000, function('TimerCallback', ["green"]))

Help: timer_start()

Periodic Timer

Python:

import threading
def TimerCallback():
    print("Timer callback")
    threading.Timer(5, TimerCallback).start()

# run a function every 5 seconds (approximately)
timer = threading.Timer(5, TimerCallback)
timer.start()

VimScript:

func TimerCallback(timer_id)
  echo "Timer callback"
endfunc

" run a function every 5 seconds periodically
let timer_id = timer_start(5 * 1000, function('TimerCallback'), {'repeat' : -1})

Help: timer

Stopping a timer

Python:

import threading
def TimerCallback():
    print("Timer callback")

timer = threading.Timer(1, TimerCallback)
timer.start()
timer.cancel()

VimScript:

func TimerCallback(timer_id)
  echo "Timer callback"
endfunc

" start a timer and then stop it
let timer_id = timer_start(1000, 'TimerCallback')
call timer_stop(timer_id)

" to stop all the timers
call timer_stopall()

Help: timer_start()

Sleeping for a specified number of seconds

Python:

import time
time.sleep(5)
time.sleep(0.2)

VimScript:

" sleep for 5 seconds
sleep 5
" sleep for 200 milliseconds
sleep 200m

Help: :sleep


JSON encoder and decoder

Python:

import json
v = ['foo', {'a' : 3}, True]
# encode data to JSON
str = json.dumps(v)
# decode data from JSON
x = json.loads(str)

VimScript:

let v = ['foo', {'a' : 3}, v:true]
" encode data to JSON
let str = v->json_encode()
echo str
" decode data from JSON
let x = str->json_decode()
echo x

Help: json_encode(), json_decode(), js_encode(), js_decode()


Network Sockets

Python:

import requests
# Get a web page from http://httpbin.org
def Display_Page():
  r = requests.get('http://httpbin.org/')
  if r.status_code == requests.codes.ok:
    # display the received header and contents
    print(r.headers)
    print(r.text)
  else:
    print("Error: Failed to open URL")
Display_Page()

VimScript:

let g:rcvd_data = []

" channel data callback function. Called for every received line.
func Chan_data_cb(ch, msg)
  call add(g:rcvd_data, a:msg)
endfunc

" channel close callback function.
func Chan_close_cb(ch)
  echo g:rcvd_data
endfunc

func Display_Page()
  let addr = "httpbin.org:80"
  let ch_opt = {}
  " data received is processed one line at a time
  let ch_opt.mode = 'nl'
  let ch_opt.waittime = -1
  let ch_opt.drop = "never"
  let ch_opt.callback = function('Chan_data_cb')
  let ch_opt.close_cb = function('Chan_close_cb')
  " open the channel
  let ch = ch_open(addr, ch_opt)
  if ch_status(ch) != "open"
    echomsg "Failed to open channel, status = " .. ch_status(ch)
    return
  endif
  " send a http request
  call ch_sendraw(ch, "GET / HTTP/1.0\nHost: httpbin.org\n\n")
endfunc

call Display_Page()

Help: job-channel-overview, ch_open(), ch_status(), ch_sendraw(), ch_close()


Background Processes

Starting a background process and communicating with it

The 'bc' calculator utility is used in the below example for illustrative purposes only.

Python:

import subprocess
procObj = subprocess.Popen('bc',
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    shell=True)
lines, err = procObj.communicate("12 * 6\n")
print("Result = " + lines)
print("Exitcode = " + str(procObj.returncode))

VimScript:

let job = job_start('bc')
if job_status(job) != "run"
  echo "Failed to start bc"
else
  let output = ch_evalraw(job, "6 * 12\n")
  echo "Result =" output
  call job_stop(job, "kill")
  let info = job_info(job)
  echo "Exitcode = " info.exitval
endif

Help: job, job_start(), job_status(), job_stop(), job_info()


Unit Tests

Python:

import unittest

class TestDemoMethods(unittest.TestCase):
    def test_abc(self):
        self.assertEqual('FOO'.lower(), 'foo')
        self.assertNotEqual(1, 2)
        self.assertTrue('foo' == 'foo')
        self.assertFalse('FOO' == 'foo')
        self.assertIsNot('foo', 1)
        self.assertRegex('ab123xy', '\d+')
        self.assertNotRegex('abcd', '\d+')
        with self.assertRaises(TypeError):
            'a:b'.split(2)

unittest.main()

VimScript:

let v:errors = []
call assert_equal(tolower('FOO'), 'foo')
call assert_notequal(1, 2)
call assert_true('foo' == 'foo')
call assert_false('FOO' == 'foo')
call assert_fails('let l = split("a:b", [])', 'E730:')
call assert_match('\d\+', 'ab123xy')
call assert_notmatch('\d\+', 'abcd')
if len(v:errors) == 0
    echo "Test passed"
else
    echo "Test failed: ", v:errors
endif

Help: testing, v:errors

@idbrii
Copy link

idbrii commented May 25, 2020

In "Formatted Output", you may want to include the more modern python way of formatting strings (str.format) to show that there's no better vimscript equivalent than printf:

"Name: {name}, ID: {id}".format(name=name, id=id)

Great work!

@lervag
Copy link

lervag commented May 25, 2020

In "Formatted Output", you may want to include the more modern python way of formatting strings (str.format) to show that there's no better vimscript equivalent than printf:

"Name: {name}, ID: {id}".format(name=name, id=id)

Great work!

Or better, the even more modern f string notation:

f"Name: {name}, ID: {id}"

@mgedmin
Copy link

mgedmin commented Jun 1, 2020

This ought to be a proper repository so that people could send pull requests ;)

@dpelle
Copy link

dpelle commented Jun 1, 2020

Nice comparison.

In the regular expression comparison, I see:

ignore case | (?i) | \c

To be pedantic, it's not equivalent:

  • case is ignored in Python after (?i)
  • whereas case is ignored everywhere in Vim before or after \c

@yegappan
Copy link
Author

yegappan commented Jun 1, 2020

This ought to be a proper repository so that people could send pull requests ;)

I have created the https://github.com/yegappan/VimScriptForPythonDevelopers repository for this gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment