Vim9 scriptはVim scriptとの互換をなくし変数の型縛りを導入したり、コンパイルをすることなどにより、高速化を実現した新しい処理系です。
def
コマンドで定義された関数内、またはVim script内でvim9script
コマンドを使うことで利用できます(vim9script
コマンドの後ではfunction
コマンドは利用できません)。
この記事は、 https://gist.github.com/yegappan/16d964a37ead0979b05e655aa036cad0 の内容を元にVim(v8.2.2576)上のVim9 scriptで動作するように改変したものです。
Vim9 scriptで動作を確認できなかったもの、まだ実装されていなものはpass
と表記し、省略しています。
Vim9 scriptはまだ開発中で、これから先破壊的な変更がされる可能性があります。
ですので、この記事はHEADのVim9 scriptに合わせた情報を記載するものとします。
内容に間違い・不自由な日本語などがありましたら、コメント欄にご連絡くださると幸いです。
この記事を書くにあたって、Vim-jpの方々に助けていただきました。ありがとうございます!
- Classについて
- Helpのリンクを追加する
- Literals
- Variables
- Operators
- String
- List
- Dictionary
- If Statement
- For Loop
- While Loop
- Comment
- Function
- Lambda Function
- Partial Function
- Closure
- Class
- Exception Handling
- Line Continuation
- File Operations
- Directory Operations
- Random Numbers
- Mathematical Functions
- Date/Time Functions
- External Commands
- User Input/Output
- Environment Variables
- Command Line Arguments
- Regular Expressions
- Binary Data
- Timers
- JSON encoder and decoder
- Network Sockets
- Background Processes
- Unit Tests
Type | Python | Vim script |
---|---|---|
decimal (integer) | -1, 0, 5 |
-1, 0, 5 |
binary (integer) | 0b1011 |
0b1011 |
octal (integer) | 0o477 |
0o477 |
hexadecimal (integer) | 0x1AE |
0x1AE |
float | 3.14, -1.5e2 |
3.14, -1.5e2 |
string | "hello", 'world' |
"hello", 'world' |
boolean | True, False |
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, null (v:null) |
Vim9 script (Vim script)ではinteger
にあたる型はnumber
です。
また、Vim9 scriptではtrue
/v:true
など両方利用できますが、true
を使う方が新しいので、そちらを使うと良いでしょう。(かなり新しいVimでないと動かなくなりますが...)
Python:
i = 10
pi = 3.1415
str = "Hello"
a, b, s = 10, 20, "sky"
Vim script:
var i = 10
var pi = 3.1415
var str = "Hello"
var [a, b, s] = [10, 20, "sky"]
Python:
del str
Vim script:
unlet str
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']
Vim script:
# Not defined
Type | Python | Vim script |
---|---|---|
Number | num = 10 |
var num = 10 |
Float | f = 3.4 |
var f = 3.4 |
Booelan | done = True |
var done = v:true |
String | str = "green" |
var str = "green" |
List | l = [1, 2, 3] |
var l = [1, 2, 3] |
Dictionary | d = {'a' : 5, 'b' : 6} |
var d = {a: 5, b: 6} |
Type | example |
---|---|
bool | true, false |
number | 123, -123, 0 |
float | 3.14, -1.5e2 |
string | "Hello, World" |
blob | 0zFF00ED015DAF |
list<{type}> | [123, 234, 345] |
dict<{type}> | {key1: 123, key2: 2344} |
void | |
any | 123, "Test", [123, 234] |
Vim9 scriptでは型ありの変数宣言が可能です。
宣言は以下の形で行います。
var foo1: number = 123
var foo2: list<string> = ["HUGE", "HUGO"]
また、any
型にはどの型の値も入りますが値はany
を持ちません。
Conversion | Python | Vim script |
---|---|---|
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) |
Type | Python | Vim script |
---|---|---|
Number | isintance(x, int) |
type(x) == v:t_number |
String | isinstance(x, str) |
type(x) == v:t_string |
List | isintance(x, list) |
type(x) == v:t_list |
Dictionary | isintance(x, dict) |
type(x) == v:t_dict |
Float | isintance(x, float) |
type(x) == v:t_float |
Boolean | isinstance(x, bool) |
type(x) == v:t_bool |
Vim scriptでは明示しないかぎりスコープはグローバルですが、Vim9 scriptではスクリプトローカルになります。
Scope Prefix | Description |
---|---|
g: | global |
l: | function-local |
s: | script-local |
a: | 廃止 |
v: | internal |
b: | buffer local |
w: | window local |
t: | tab local |
What | Python | Vim script |
---|---|---|
addition | a = 10 + 20 |
a = 10 + 20 |
subtraction | a = 30 - 10 |
a = 30 - 10 |
multiplication | a = 3 * 5 |
a = 3 * 5 |
division | a = 22 / 7 |
a = 22 / 7 |
modulus | a = 10 % 3 |
a = 10 % 3 |
exponentiation | a = 2 ** 3 |
a = float2nr(pow(2, 3)) |
floor division | a = 10 // 3 |
a = floor(10 / 3.0) |
What | Python | Vim script |
---|---|---|
addition | a += 1 |
a += 1 |
subtraction | a -= 2 |
a -= 2 |
multiplication | a *= 4 |
a *= 4 |
division | a /= 2 |
a /= 2 |
modulus | a %= 2 |
a %= 2 |
What | Python | Vim script |
---|---|---|
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 |
What | Python | Vim script |
---|---|---|
logical and | x and y |
x && y |
logical or | x or y |
x || y |
logical not | not x |
!x |
!! を値の前に付けると、真偽値として扱うことができます。 |
What | Python | Vim script |
---|---|---|
bitwise AND | c = a & b |
c = and(a, b) |
bitwise OR | c = a | b |
c = or(a, b) |
bitwise NOT | c = ~a |
c = invert(a) |
bitwise XOR | c = a ^ b |
c = xor(a, b) |
left shift | c = a << b |
c = a * float2nr(pow(2, b)) |
right shift | c = a >> b |
c = float2nr(floor(a / pow(2, b))) |
What | Python | Vim script |
---|---|---|
is | x is y |
x is y |
is not | x is not y |
x is y |
Vim9 scriptではis
ステートメントをlist,dict,blob,(string)で利用できます。
ただし、stringは参照先が等しいかではなく文字列同士が等しいかを比較するので注意してください。
Python:
s1 = r"one\ntwo\n"
s2 = "one\ntwo\n"
Vim script:
var s1 = 'one\ntwo\n'
var s2 = "one\ntwo\n"
Python:
n = len("Hello World")
Vim script:
# count the number of bytes in a string
var n = len("Hello World")
# count the number of bytes in a string
var n = strlen("Hello World")
# count the number of characters in a string
var n = strwidth("Hello World")
Python:
str1 = "blue"
str2 = "sky"
s = str1 + str2
Vim script:
var str1 = "blue"
var str2 = "sky"
var s = str1 .. str2
pass
Python:
str = "HelloWorld"
sub = str[2:5]
Vim script:
var str = "HelloWorld"
# use character index and length
var sub = str[2 : 4]
var sub = str[-3]
var sub = str[2 : -3]
# use byte index and length
var sub = strpart(str, 2, 3)
# use character index and length
var sub = strcharpart(str, 2, 3)
Vim scriptではスライスを使った文字へのアクセスはbyte単位で行なわれますが、Vim9 scriptでは文字単位で行なわれます。
Python:
str = "Hello World"
c = str.count("l")
Vim script:
var str = "Hello World"
var c = str->count("l")
Python:
str = "running"
idx = str.find("nn") # leftmost
idx = str.rfind("ing") # rightmost
# idx == -1 if the substring is not present
Vim script:
var str = "running"
var idx = str->stridx("nn") # leftmost
idx = str->strridx("ing") # rightmost
# idx == -1 if the substring is not present
Python:
str = "running"
if str.startswith("run"):
print("starts with run")
if str.endswith("ing"):
print("ends with ing")
Vim script: pass
Python:
s = ":".join(['ab', 'cd', 'ef'])
Vim script:
var s = ['ab', 'cd', 'ef']->join(':')
Python:
s = "Hello World"
l = s.lower()
l = s.upper()
Vim script:
var s = "Hello World"
var l = s->tolower()
l = s->toupper()
Python:
s = "Hello World"
s2 = s.replace("Hello", "New")
Vim script:
var s = "Hello World"
var s2 = s->substitute("Hello", "New", 'g')
Python:
s = "a:b:c"
s2 = s.split(":")
Vim script:
var s = "a:b:c"
var s2 = s->split(":")
文字単位の分割は"\zs"を使うことで可能です。
Python:
s = " vim "
s2 = s.strip()
Vim script:
var s = " vim "
# strip leading and trailing whitespace
var s2 = s->trim()
# strip leading space characters
s2 = s->trim(' ', 1)
# strip trailing space characters
s2 = s->trim(' ', 2)
pass
Python:
s = str(268)
s = str(22.7)
s = str([1, 2, 3])
s = str({'a' : 1, 'b' : 2})
Vim script:
var s = string(268)
s = string(22.7)
s = string([1, 2, 3])
s = string({'a': 1, 'b': 2})
Python:
x = 10
y = eval("x * 2")
print(y)
n = eval("min([4, 3, 5])")
Vim script:
var x = 10
var y = eval("x * 2")
echo y
var n = eval("min([4, 3, 5])")
echo n
Python:
exec("for i in range(5):\n print(i)\n")
Vim script:
execute "for i in range(5)\necho i\nendfor"
Python:
print("Ordinal value of 'a' is " + str(ord("a")))
print("Character with value 65 is " + chr(65))
Vim script:
echo "Ordinal value of 'a' is " .. char2nr('a')
echo "Character with value 65 is " .. nr2char(65)
Python:
l = [ord(i) for i in 'Hello']
s = ''.join(chr(i) for i in l)
print(s)
print(l)
Vim script:
var l = str2list('Hello')
var s = list2str(l)
echo s
echo l
Method | Python | Vim script |
---|---|---|
capitalize() | 'one two'.capitalize() |
'one two'->substitute('.', '\u&', '') |
center() | 'abc'.center(10) |
Not availalbe |
count() | "abbc".count('b') |
"abbc"->count('b') |
decode() | str.decode() |
Not availalbe |
encode() | str.encode() |
Not availalbe |
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']) |
['a', 'b', 'c']->join(':') |
ljust() | 'abc'.ljust(10) |
Not availalbe |
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 availalbe |
rpartition() | 'ab-cd-ef'.rpartition('-') |
'ab-cd-ef'->matchlist('\(.*\)\(-\)\(.*\)')[1:3] |
rsplit() | 'a-b-c-d'.rsplit('-', 2) |
Not availalbe |
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 availalbe |
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 availalbe |
Python:
l = [1, 2, 3, 4]
Vim script:
var l = [1, 2, 3, 4]
list
も型をつけて宣言することが可能です。
下記の例(mattnさんよりお借りしました)のようにlist<{type}>
の形で宣言できます。
{type}
で指定した型以外の値を代入するとエラーになりますが、{type}
としてany
を指定すると、list
の中に異なる型を代入できます。
var foo1: list<string> = ["foo", "bar"]
var foo2: list<number> = [1, 3, 3]
var foo3: list<bool> = [true, false]
var foo4: list<any> = ["foo", "bar", 3]
var foo5: list<string> = ["foo", "bar", 3] # エラー
list
内のアイテムに対してmap()
を適用する際、元のlist
の型と異なる型に置き換えるときはmapnew()
を利用します。
mapnew()
では引数に与えられたlist
は更新されず新しいlist
が返されますが、list
内の要素は更新できるためそうしたくない場合deepcopy()
を使用してください。
var foo = [123, 456, 789]
echo map(foo, (i, v) => string(v)) # エラー
echo mapnew(foo, (i, v) => string(v)) # -> ['123', '456', '789']
Python:
l = [1, 2, 3, 4]
v1 = l[2]
v2 = l[-2]
Vim script:
var l = [1, 2, 3, 4]
var v1 = l[2]
var v2 = l[-2]
Python:
l = [1, 2, 3, 4]
l[3] = 5
Vim script:
var l = [1, 2, 3, 4]
l[3] = 5
Python:
l = []
l.append(5)
l += [6, 7]
Vim script:
var l = []
l->add(5)
l += [5, 6]
Python:
l = [1, 3]
l.insert(1, 2)
Vim script:
var l = [1, 3]
# insert before index 1
l->insert(2, 1)
# insert at the begining
l->insert(5)
Python:
l = [4, 5, 6]
l.remove(5)
del l[0]
Vim script:
var l = [4, 5, 6]
var idx = index(l, 5)
if idx != -1
remove(l, idx)
endif
unlet l[0]
Python:
l = [1, 2, 3]
v = l.pop()
Vim script:
var l = [1, 2, 3]
var v = l->remove(-1)
Python:
l = [1, 2, 3]
x = l.index(2)
Vim script:
var l = [1, 2, 3]
var x = l->index(2)
Python:
l = [1, 2, 3, 4]
m = l[1:3]
m = l[2:]
Vim script:
var l = [1, 2, 3, 4]
var m = l[1 : 3]
m = l[2 :]
m = l[-2 :]
Python:
l = [1, 2] + [3 ,4]
Vim script:
var l = [1, 2] + [3, 4]
Python:
l = ['vim'] * 4
Vim script:
var l = ['vim']->repeat(4)
Python:
l = [2, 4, 4, 5]
x = l.count(4)
Vim script:
var l = [2, 4, 4, 5]
var x = l->count(2)
Python:
l = ['a', 'b', 'c']
n = len(l)
Vim script:
var l = ['a', 'b', 'c']
var n = l->len()
Python:
l = [3, 2, 1]
l.sort()
print(l)
Vim script:
var l = [3, 2, 1]
echo l->sort()
Python:
l = ['a', 'b', 'b', 'c', 'c', 'd']
# order of the elements is not retained
tset = set(l)
print(list(tset))
Vim script:
# needs a sorted list
var l = ['a', 'b', 'b', 'c', 'c', 'd']
echo copy(l)->uniq()
Python:
l = [1, 2, 3]
l.reverse()
print(l)
Vim script:
var l = [1, 2, 3]
echo l->reverse()
Python:
l = [3, 2, 1]
l2 = l.copy()
Vim script:
var l = [3, 2, 1]
var l2 = l->copy()
Python:
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
Vim script:
var a = [[1, 2], [3, 4]]
var b = a->deepcopy()
Python:
l = [3, 2, 1]
l.clear()
Vim script:
var l = [3, 2, 1]
unlet l[:]
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")
Vim script:
var l1 = [1, 2]
var l2 = l1
var 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
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]
Vim script:
var odd = filter(range(10), (idx, v) => (v % 2))
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)]
Vim script:
var num_str = mapnew(range(10), (idx, v) => (string(v)))
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])
Vim script:
# using a lambda function
var sum = reduce([1, 2, 3, 4], (x, y) => (x + y))
# using a function
def SumNum(x: number, y: number): number
return x + y
enddef
sum = reduce([1, 2, 3, 4], function('SumNum'))
echo sum
Python:
l = [3, 10, 8]
v1 = min(l)
v2 = max(l)
print(v1, v2)
Vim script:
var l = [3, 10, 8]
var v1 = l->min()
var v2 = l->max()
echo v1 v2
Python:
s = str([3, 5, 7])
Vim script:
var s = string([3, 5, 7])
Method | Python | Vim script |
---|---|---|
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() |
Python:
d = {'red' : 10, 'blue' : 20}
x = {}
Vim script:
var d = {red: 10, blue: 20}
var x = {}
dict
もlist
と同様に型をつけて宣言することができます。
dict
内のアイテムに対してmap()
を適用する際、元のdict
の型と異なる型に置き換えるときはmapnew()
を利用します。
mapnew()
では引数に与えられたdict
は更新されず新しいdict
が返されますが、dict
内の要素は更新できるためそうしたくない場合deepcopy()
を使用してください。
var foo = {key1: 123, key2: 234}
echo map(foo, (k, v) => string(v)) # エラー
echo mapnew(foo, (k, v) => string(v)) # -> {'key1': '123', 'key2': '234'}
Python:
d = {'red' : 10, 'blue' : 20}
x = d['red']
Vim script:
var d = {red: 10, blue: 20}
var x = d['red']
x = d.red
Python:
d = {'red' : 10, 'blue' : 20}
d['red'] = 15
Vim script:
var d = {red: 10, blue: 20}
d.red = 15
d['red'] = 15
Python:
d = {'red' : 10, 'blue' : 20}
v = d.get('red')
Vim script:
var d = {red: 10, blue: 20}
var v = d->get('red')
Python:
d = {'red' : 10, 'blue' : 20}
d['green'] = 30
Vim script:
var d = {red: 10, blue: 20}
d.green = 30
d['green'] = 30
Python:
d = {}
d.update({'color' : 'grey'})
Vim script:
var d = {}
eval d->extend({color: 'grey'})
Python:
d = {'red' : 10, 'blue' : 20}
d.pop('red')
Vim script:
var d = {red: 10, blue: 20}
d->remove('red')
Python:
d = {'red' : 10, 'blue' : 20}
d.clear()
Vim script:
var d = {red: 10, blue: 20}
d->filter("0")
Python:
d = {'red' : 10, 'blue' : 20}
n = len(d)
Vim script:
var d = {red: 10, blue: 20}
var n = d->len()
Python:
d = {'red' : 10, 'blue' : 10}
x = sum(n == 10 for n in d.values())
print(x)
Vim script:
var d = {red: 10, blue: 10}
var x = d->count(10)
echo x
Python:
d = {'red' : 10, 'blue' : 20}
if 'red' in d:
print("found red key")
Vim script:
var d = {red: 10, blue: 20}
if d->has_key('red')
echo "found red key"
endif
Python:
d = {'red' : 10, 'blue' : 20}
for k in d:
print(k)
for k in d:
print(d[k])
Vim script:
var d = {red: 10, blue: 20}
for k in keys(d)
echo k
endfor
for k in d->keys()
echo d[k]
endfor
Python:
d = {'red' : 10, 'blue' : 20}
for v in d.values():
print(v)
Vim script:
var d = {red: 10, blue: 20}
for v in d->values()
echo v
endfor
Python:
d = {'red' : 10, 'blue' : 20}
for k, v in d.items():
print(k, v)
Vim script:
var d = {red: 10, blue: 20}
for [k, v] in d->items()
echo k v
endfor
Python:
d = {'red' : 10, 'blue' : 20}
new_d = d.copy()
Vim script:
var d = {red: 10, blue: 20}
var new_d = d->copy()
Python:
import copy
a = {'x' : [1, 2], 'y' : [3, 4]}
b = copy.deepcopy(a)
Vim script:
var a = {x: [1, 2], y: [3, 4]}
var b = a->deepcopy()
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")
Vim script:
var d1 = {a: 10, b: 20}
var d2 = {a: 10, b: 20}
if d1 == d2
echo "Dicts d1 and d2 have the same content"
endif
var 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
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)
Vim script:
var d1 = {red: 10, green: 20, blue: 10}
# filter dict items with value 10
var d2 = copy(d1)->filter((k, v) => (v == 10))
echo d1 d2
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)
Vim script:
var d1 = {red: 10, green: 20, blue: 30}
# increment the values by 5
var d2 = copy(d1)->map((k, v) => (v + 5))
echo d1 d2
Python:
d = {'red' : 10, 'green' : 20}
v1 = min(d.values())
v2 = max(d.values())
print(v1, v2)
Vim script:
var d = {red: 10, green: 20}
var v1 = d->min()
var v2 = d->max()
echo v1 v2
Python:
d = str({'a' : 1, 'b' : 2})
Vim script:
var d = string({a: 1, b: 2})
Method | Python | Vim script |
---|---|---|
clear() | d.clear() |
call filter(d, '0') |
copy() | newDict = d.copy() |
var newDict = d->copy() |
fromkeys() | d = dict.fromkeys(x) |
Not availalbe |
get() | v = d.get('red') |
var 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') |
d->remove('red') |
popitem() | d.popitem() |
Not availalbe |
setdefault() | d.setdefault('red', 10) |
Not availalbe |
update() | d.update({'a' : 10, 'b' : 20} |
d->extend({a: 10, b: 20}) |
values() | d.values() |
d->values() |
Python:
if a > b:
print("a is greater than b")
Vim script:
if a > b
echo "a is greater than b"
endif
Python:
if a > b:
print("a is greater than b")
else:
print("a is less than or equal to b")
Vim script:
if a > b
echo "a is greater than b"
else
echo "a is less than or equal to b"
endif
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")
Vim script:
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
Python:
if a > b and (a > c or a > d):
print "a is greater than b and greater than c or d"
Vim script:
if a > b && (a > c || a > d)
echo "a is greater than b and greater than c or d"
endif
Python:
if status == True:
if a >= 1:
print("Nested if")
Vim script:
if status == true
if a >= 1
echo "Nested if"
endif
endif
Python:
for i in range(5) :
print(i)
Vim script:
for i in range(5)
echo i
endfor
Python:
for i in ['a', 'b', 'c']:
if i == 'b':
break
print(i)
Vim script:
for i in ['a', 'b', 'c']
if i == 'b'
break
endif
echo i
endfor
Python:
for i in ['a', 'b', 'c']:
if i == 'b':
continue
print(i)
Vim script:
for i in ['a', 'b', 'c']
if i == 'b'
continue
endif
echo i
endfor
Python:
for i in range(10):
for j in range(10):
print(str(i) + 'x' + str(j) + '=' + str(i * j))
Vim script:
for i in range(4)
for j in range(4)
echo i .. 'x' .. j .. '=' .. i * j
endfor
endfor
Python:
i = 1
while i <= 5 :
print(i)
i += 1
Vim script:
var i = 1
while i <= 5
echo i
i += 1
endwhile
Python:
# This is a python comment
i = 0 # First iteration
Vim script:
# This is a Vim script comment
var i = 0 # First iteration
Vim9 scriptの関数は大文字で初める必要があります。また、デフォルトのスコープはスクリプトローカルなためグローバル関数を定義するにはg:
を先頭につけます。
また、エラーが発生するとその時点で実行は止まるため、abort
は必要ありません。また、定義済みの関数を上書きするにはdef!
を使います。
引数の型、返り値の型を指定する必要があります。
Python:
def Min(x, y):
return x if < y else y
print(Min(6, 3)
Vim script:
def! Min(x: number, y: number): number
return x < y ? x : y
enddef
echo Min(6, 3)
Python:
def EchoValue(v):
print(v)
EchoValue(100)
Vim script:
def EchoValue(v: number)
echo v
enddef
EchoValue(100)
Python:
def Sum(a, b):
return a + b
s = Sum(10, 20)
Vim script:
def Sum(a: number, b: number): number
return a + b
enddef
var s = Sum(10, 20)
Python:
def AddValues(l):
l.extend([1, 2, 3, 4])
Vim script:
def AddValues(l: list<number>)
extend(l, [1, 2, 3, 4])
enddef
Python:
def Sum(v1, *args):
sum = v1
for i in *args:
sum += i
return sum
Vim script:
def Sum(...args: list<number>): number
var sum = 0
for i in args
sum += i
endfor
return sum
enddef
var s1 = Sum(10, 20, 30, 40)
s1 = Sum(10)
Python:
def Powerof(base, exp = 2):
return base ** exp
Vim script:
def PowerOf(base: number, exp: number = 2): number
return float2nr(pow(base, exp))
enddef
var val = PowerOf(4)
val = PowerOf(4, 3)
Python:
counter = 1
def Incr():
global counter
counter += 1
Vim script: pass
Python:
def Foo():
print("Foo")
Bar = Foo
Bar()
Vim script:
def! Foo()
echo "Foo"
enddef
var Bar = function("Foo")
Bar()
Python:
F = lambda x , y: x - y
print(F(5,2))
Vim script:
var F = (x, y) => (x - y)
echo F(5, 2)
Python:
import functools
def Mylog(subsys, msg):
print("%s: %s" % (subsys, msg))
ErrLog = functools.partial(Mylog, 'ERR')
ErrLog("Failed to open file")
Vim script:
def Mylog(subsys: string, msg: string)
echo printf("%s: %s", subsys, msg)
enddef
var ErrLog = function('Mylog', ['ERR'])
ErrLog("Failed to open file")
Python:
def foo(arg):
i = 3
return lambda x: x + i - arg
bar = foo(4)
print(bar(6))
Vim script: pass
Python:
def Foo(base):
def Bar(val):
return base + val
return Bar
F = Foo(10)
print(F(2))
F = Foo(20)
print(F(2))
Vim script: pass
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()
Vim script: not implemented yet
Python:
try:
f = open('buf.java', 'r')
lines = f.readlines()
f.close()
except IOError:
print("Failed to open file")
Vim script:
try
var l = readfile('buf.java')
catch /E484:/
echo "Failed to read file"
endtry
Python:
try:
f = open('buf.java', 'r')
lines = f.readlines()
f.close()
except Exception as e:
print("Caught " + str(e))
Vim script:
try
var l = readfile('buf.java')
catch
echo "Caught " .. v:exception
endtry
Python:
try:
f = open('buf.java', 'r')
lines = f.readlines()
f.close()
finally:
print("executing code in finally block")
Vim script: pass
Python:
try:
raise Exception('MyException')
except Exception as e:
if str(e) == 'MyException':
print("Caught MyException")
finally:
print("Finally block")
Vim script:
try
throw 'MyException'
catch /MyException/
echo "Caught MyException"
endtry
Python:
a = 1 + 2 + 3 + \
4 + 5 + 6
Vim script:
# 演算子
var a = 1 + 2 + 3 +
4 + 5 + 6
# 関数呼び出し
var result = Func(
arg1,
arg2
)
# コマンド
autocmd BufNewFile *.match if condition
| echo 'match'
| endif
Python:
with open('myfile.txt', 'r') as f:
lines = f.readlines()
# lines == ['line1\n', 'line2\n']
Vim script:
var lines = readfile("myfile.txt")
# lines == ['line1', 'line2']
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)
Vim script:
writefile(['line1', 'line2'], 'myfile.txt')
Python:
lines = ["line3\n", "line4\n"]
with open('myfile.txt', 'a') as fh:
fh.writelines(lines)
Vim script:
writefile(['line3', 'line4'], 'myfile.txt', 'a')
Python:
import os.path
if os.path.isfile('myfile.txt'):
print("File exists")
Vim script:
if filereadable('myfile.txt')
echo "File is readable"
endif
Python:
import os
os.remove('myfile.txt')
Vim script:
delete('myfile.txt')
Python:
import os
os.rename('myfile.txt', 'somefile.txt)
Vim script:
rename('myfile.txt', 'somefile.txt')
Python:
import os
sz = os.path.getsize('move.py')
Vim script:
var sz = getfsize('move.py')
Python:
os.mkdir('somedir')
Vim script:
mkdir('somedir')
Python:
os.chdir('someotherdir')
Vim script:
chdir('someotherdir')
Python:
dir = os.getcwd()
Vim script:
var dir = getcwd()
Python:
os.rmdir('somedir')
Vim script:
delete('somedir', 'd')
Python:
import random
r = random.randint(0, 2147483647)
Vim script:
var r = rand()
Python:
import random
random.seed()
r = random.randint(0, 2147483647)
print(r)
Vim script:
var seed = srand()
var r = rand(seed)
いくつかの関数はVimが+float
でコンパイルされている必要があります。
Function | Python | Vim script |
---|---|---|
abs | f = math.fabs(-10) |
var f = abs(-10) |
acos | f = math.acos(0.8) |
var f = acos(0.8) |
asin | f = math.asin(0.8) |
var f = asin(0.8) |
atan | f = math.atan(0.8) |
var f = atan(0.8) |
atan2 | f = math.atan2(0.4, 0.8) |
var f = atan2(0.4, 0.8) |
ceil | f = math.ceil(1.2) |
var f = ceil(1.2) |
cos | f = math.cos(4) |
var f = cos(4) |
cosh | f = math.cosh(4) |
var f = cosh(4) |
exp | f = math.exp(2) |
var f = exp(2) |
floor | f = math.floor(1.4) |
var f = floor(1.4) |
log | f = math.log(12) |
var f = log(12) |
log10 | f = math.log10(100) |
var f = log10(100) |
mod | f = math.fmod(4, 3) |
var f = fmod(4, 3) |
pow | f = math.pow(2, 3) |
var f = pow(2, 3) |
sin | f = math.sin(4) |
var f = sin(4) |
sinh | f = math.sinh(4) |
var f = sinh(4) |
sqrt | f = math.sqrt(9) |
var f = sqrt(9) |
tan | f = math.tan(4) |
var f = tan(4) |
tanh | f = math.tanh(4) |
var f = tanh(4) |
trunc | f = math.trunc(1.3) |
var f = trunc(1.3) |
Python:
from datetime import datetime
d = datetime.now()
print(d.strftime("%c"))
Vim script:
echo strftime("%c")
Python:
from datetime import datetime
print(datetime.strptime("1997 Apr 27 11:49:23", "%Y %b %d %X"))
Vim script:
echo strptime("%Y %b %d %X", "1997 Apr 27 11:49:23")
Python:
import time
print int(time.time())
Vim script:
echo localtime()
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))
Vim script:
var start = reltime()
var sum = 0
for i in range(1000)
sum += i
endfor
var elapsed_time = reltime(start)
echo "Elasped time" reltimefloat(elapsed_time)
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))
Vim script:
var lines = system('grep class *.java')
echo lines
echo "Error = " .. v:shell_error
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())))
Vim script:
var lines = systemlist('grep class *.java')
echo "Number of matches = " .. len(lines)
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))
Vim script:
var lines = system('wc', "one\ntwo\n")
echo lines
echo "Error = " .. v:shell_error
Python:
choice = input("coffee or tea? ")
print("You selected " + choice)
Vim script:
var ans = input("coffee or tea? ", "tea")
echo "You selected " .. ans
Python:
import getpass
passwd = getpass.getpass("Password: ")
print("You entered " + passwd)
Vim script:
var passwd = inputsecret("Password: ")
echo "You entered " .. passwd
Python:
print("Hello World\n")
s = "vim"
print("Editor = %s" % (s))
Vim script:
echo "Hello World"
var s = "vim"
echo "Editor = " .. s
Python:
name = "John"
id = 1001
print(f"Name: {name}, ID: {id}")
print("Name: {}, ID: {}".format(name, id))
print("Name: %s, ID: %d" % (name, id))
Vim script:
var name = "John"
var id = 1001
echo printf("Name: %s, ID: %d", name, id)
Python:
import os
h = os.environ.get('HOME', '')
if h == '':
print("HOME is not set")
else:
print("HOME = " + h)
Vim script:
if !exists('$HOME')
echo 'HOME is not set'
else
echo 'HOME = ' .. $HOME
endif
Python:
import os
os.environ['FOO'] = "BAR"
Vim script:
setenv('FOO', 'BAR')
var $FOO
などで変数にsetできますが、既に定義されている場合エラーになるのでsetenv()
を利用すとよいでしょう。
Python:
import os
del os.environ['FOO']
Vim script:
setenv('FOO', v:null)
Python:
import os
print(os.environ)
Vim script:
echo environ()
Python:
import sys
print("Number of arguments = " + str(len(sys.argv)))
print("Arguments = " + str(sys.argv))
for arg in sys.argv:
print(arg)
Vim script:
echo "Number of arguments = " .. len(v:argv)
echo "Arguments = " .. string(v:argv)
for arg in v:argv
echo arg
endfor
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")
Vim script:
var s = 'Test failed with error E123:'
if s =~# 'E\d\+:'
echo "Error code found"
endif
s = 'Test successful'
if s !~# 'E\d\+:'
echo "Test passed"
endif
Python:
import re
m = re.search(r'\d+', "Abc 123 Def")
if m is not None:
idx = m.start()
end_idx = m.end()
Vim script:
var idx = match("Abc 123 Def", '\d\+')
var end_idx = matchend("Abc 123 Def", '\d\+')
var l = matchstrpos("Abc 123 Def", '\d\+')
echo "start:" l[1] "end:" l[2]
Python:
import re
m = re.search(r'\d+', "Abc 123 Def")
if m is not None:
s = m.group(0)
print s
Vim script:
var s = matchstr("Abc 123 Def", '\d\+')
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))
Vim script:
var list = matchlist("foo bar baz", '\(\w\+\) \(\w\+\) \(\w\+\)')
echo "Full match:" list[0]
echo "1:" list[1] "2:" list[2] "3:" list[3]
Python:
import re
s = re.sub(r'bar', r'baz', "foo bar")
print(s)
Vim script:
var s = substitute("foo bar", 'bar', 'baz', '')
echo s
Python:
import re
def Dashrepl(m):
if m.group(0) == '-':
return ' '
else:
return '-'
s = re.sub('-{1,2}', Dashrepl, 'pro----gram-files')
print(s)
Vim script:
def Dashrepl(m: list<string>): string
if m[0] == '-'
return ' '
else
return '-'
endif
enddef
var s = substitute("pro----gram-files", '-\{1,2}', function('Dashrepl'), 'g')
echo s
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 |
Python:
data = bytearray(b'\x12\xF6\xAB\xFF\x49\xC0\x88\x3A\xE2\xC1\x42\xAA')
print(data)
print(data[0:4])
Vim script:
var data = 0z12F6ABFF.49C0883A.E2C142AA
echo data
echo data[0 : 3]
Python:
data = bytearray(b'')
data.append(0xC2)
data += b'\xB3\xF7\xA5'
del data[2]
print(data)
Vim script:
var data = 0z
data[0] = 0xC2
data += 0zB3F7A5
remove(data, 2)
echo data
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)
Vim script:
var data = readfile('datafile.bin', 'B')
writefile(data, 'data2.bin')
Python:
import threading
def TimerCallback(ctx):
print("Timer callback, context = " + ctx)
timer = threading.Timer(5, TimerCallback, args=["green"])
timer.start()
Vim script:
def TimerCallback(ctx: string, timer_id: number)
echo "Timer callback, context = " .. ctx .. ", id = " .. timer_id
enddef
# Run a function after 5 seconds
var timer_id = timer_start(5 * 1000, function('TimerCallback', ["green"]))
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()
Vim script:
def TimerCallback(timer_id: number)
echo "Timer callback"
enddef
# run a function every 5 seconds periodically
var timer_id = timer_start(5 * 1000, function('TimerCallback'), {'repeat': -1})
Python:
import threading
def TimerCallback():
print("Timer callback")
timer = threading.Timer(1, TimerCallback)
timer.start()
timer.cancel()
Vim script:
def TimerCallback(timer_id: number)
echo "Timer callback"
enddef
# start a timer and then stop it
var timer_id = timer_start(1000, 'TimerCallback')
timer_stop(timer_id)
# to stop all the timers
timer_stopall()
Python:
import time
time.sleep(5)
time.sleep(0.2)
Vim script:
# sleep for 5 seconds
sleep 5
# sleep for 200 milliseconds
sleep 200m
Python:
import json
v = ['foo', {'a' : 3}, True]
# encode data to JSON
str = json.dumps(v)
# decode data from JSON
x = json.loads(str)
Vim script:
var v = ['foo', {'a': 3}, v:true]
# encode data to JSON
var str = v->json_encode()
echo str
# decode data from JSON
var x = str->json_decode()
echo x
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()
Vim script: pass
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))
Vim script:
var job = job_start('bc')
if job_status(job) != "run"
echo "Failed to start bc"
else
var output = ch_evalraw(job, "6 * 12\n")
echo "Result =" output
call job_stop(job, "kill")
var info = job_info(job)
echo "Exitcode = " info.exitval
endif
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()
Vim script: 通常のVim scriptで行うことをお勧めします。