-
Notifications
You must be signed in to change notification settings - Fork 1
vim script
- Help
- Numbers
- Variables
- Constants
- Variable containing code
- File system
- Buffers
- Output
- Functions
- Tabs & windows
- Mappings
- Autocommands
As a VimL programmer, the most used help file is :
:help eval.txt
Once there, you can use a plain search.
E.g., searching for buf.*()
will give you buffer related functions.
You can also use the completion in command mode :
:help buf*(<tab>
will give you a list of candidates, like bufnr()
or bufadd()
.
The :helpgrep
command search in all help files and fill the quickfix
list.
Each kind of VimL object has its own syntax :
- normal mode key :
ctrl-a
- insert mode key :
i_ctrl-a
- visual mode key :
v_o
- command mode key :
c_ctrl-d
,c_<tab>
- command :
:buffers
- function :
getbufinfo()
- option :
'option'
- expression :
expr-&&
- regex pattern :
/*
- vim flag :
-p
Finally, the reference :
:help help
:help help-context
Float to integer with float2nr()
:
let float = 2.01
echo float2nr(float)
Integer to float with round()
:
let int = 2
echo round(int)
String to integer with str2nr()
:
let string = ' 0002 '
echo str2nr(string)
Most of the time, variables used inside a function are local, even
without the l:
prefix :
let var = 1
let box = 2
fun! Locals ()
let var = 3
let l:box = 4
echo 'var from inside : ' var
echo 'l:box from inside : ' l:box
echo 'box from inside : ' box
endfun
call Locals ()
echo 'var : ' var
echo 'box : ' box
The l:
can sometimes be useful however, for instance to avoid
confusion with a (neo)vim v:
variable, like v:count
.
Its almost for readability, for the editor seem to see the difference :
fun! VimVars ()
let l:count = 3
echo 'l:count : ' l:count
echo 'count : ' count
echo 'v:count : ' v:count
endfun
let box = 3
echo box
" box -> constant
lockvar box
" throws error E741
let box = 4
echo box
" box -> variable
unlockvar box
" ok
let box = 5
echo box
With :execute
:
let code = 'let var = range(5)'
execute code
echo var
With eval()
:
let expression = "strftime('%H:%M')"
echo eval(expression)
Can be used to revert string()
:
let list = range(10)
let str = string(list)
" returns 1 = string
echo type(str)
let new_list = eval(str)
" returns 3 = list
echo type(new_list)
With :normal
:
let delta = 2
execute 'normal! ' . delta . "\<c-o>"
Variable containing the name of another variable :
let var = 'hello'
let ptr = 'var'
echo {ptr}
Test for a regular file :
if filereadable(my_file)
call do_something (my_file)
endif
Test for a directory :
if isdirectory(my_dir)
call do_something (my_dir)
endif
Expand the tilde with expand()
:
echo expand('~/Documents')
Modify the name with fnamemodify()
:
" full path
echo fnamemodify('~/Documents/file', ':p')
echo fnamemodify('Documents/folder/file', ':p')
" directory part (head)
echo fnamemodify('~/Documents/file', ':h')
echo fnamemodify('Documents/folder/file', ':h')
" file part (tail)
echo fnamemodify('~/Documents/file', ':t')
echo fnamemodify('Documents/folder/file', ':t')
" without extension
echo fnamemodify('~/Documents/file.ext', ':r')
echo fnamemodify('Documents/folder/file.ext', ':r')
echo fnamemodify('~/Documents/file.tar.gz', ':r')
echo fnamemodify('~/Documents/file.tar.gz', ':r:r')
" extension
echo fnamemodify('~/Documents/file.ext', ':e')
echo fnamemodify('~/Documents/file.tar.gz', ':e')
echo fnamemodify('~/Documents/file.tar.gz', ':e:e')
List of files & dirs in current folder :
echo glob('*', v:false, v:true)
Recursive, all tree of files & dirs in current folder :
echo glob('**', v:false, v:true)
Note the double asterisk.
Tree of vim files :
echo glob('**/*.vim', v:false, v:true)
Name from number :
echo bufname(1)
Number from name :
let name = bufname(1)
echo bufnr(name)
All buffers :
let buffers = getbufinfo()
for buf in buffers
echo buf.number ':' buf.name
endfor
Listed buffers :
let buffers = getbufinfo({'buflisted' : 1})
for buf in buffers
echo buf.number ':' buf.name
endfor
List of lines in current buffer :
" -- line number, output is a string
" current line
echo getline('.')
" last line
echo getline('$')
" -- range of line, output is a list
echo getline(1, 10)
echo getline('.', '$')
With setline(line, text)
, you can change a line.
With :put =var
, you can add var
content below the cursor.
With :put =list
, you add an element of list
per line.
" alternate buffer
let bufnum = '#'
" -- line number, output is a string
echo getbufline(bufnum, 5)
echo getbufline(bufnum, '$')
" -- range of line, output is a list
echo getbufline(bufnum, 1, 10)
echo getbufline(bufnum, 1, '$')
echo getbufline(bufnum, 1, '$')[4]
See also setbufline()
, appendbufline()
.
With execute()
:
let var = execute('tabs')
echo var
let list = split(var, "\n")
echo list
With :redir
:
redir => var
tabs
redir END
let list = split(var, "\n")
echo list
With system*()
:
let var = system('ls -l')
echo var
let list = systemlist('ls -l')
echo list
With writefile()
:
let list = ['first line', 'second line', 'third line']
let file = expand('~/Documents/list-file')
" replace content
call writefile(list, file)
" add content
call writefile(list, file, 'a')
With :redir
:
let list = ['first line', 'second line', 'third line']
let content = join(list, "\n")
let file = expand('~/Documents/content-file')
execute 'redir! >' file
silent! echo content
redir END
execute 'redir! >>' file
silent! echo content
redir END
Note the distinction between the function execute()
and the command :execute
Variable containing a function name :
let fun = 'strftime'
echo {fun}('%H:%M')
Function call(function, argument-list)
:
let list = range(5)
let element = 'new'
" add(list, element)
echo call('add', [list, element])
echo list
Variables linked to optional arguments :
- a:0 : number of optional args
- a:1 : first optional arg
- a:2 : second optional arg
- ...
- a:000 : list of optional args
Pass the optional arguments of a function to another one :
fun! Fun (...)
let var = call('add', a:000)
return var
endfun
let list = range(5)
echo Fun (list, 7)
let list = range(3)
let Fun = function('add')
echo Fun(list, 4)
echo list
With predefined argument(s) :
let list = range(3)
" add(list, element)
let Fun = function('add', [list])
echo Fun(4)
echo Fun(5)
echo list
let list = [2, 3, 5, 4, 1]
echo filter(list, {index, value -> value >= 4})
let list = [2, 3, 5, 1, -1]
echo map(list, {index, value -> index + value})
let number = -3.14
echo number->abs()
echo number->abs()->cos()
echo number->abs()->cos()->acos()
Lambda method :
let number = 3
echo number->{ x -> 2 * x }()
echo number->{ x, y -> x + y }(4)
fun! Fonctional(fn, value)
fun! Function(arg) closure
return a:fn(a:arg, a:value)
endfun
return funcref('Function')
endfun
let list = range(10)
" add(list, element)
echo Fonctional(function('add'), 3)(list)
let F = Fonctional(function('add'), 5)
echo F(list)
Dict function :
fun! Fundict (arg) dict
echo self.name a:arg
endfun
" associate it with a dict
let dict = {'name' : 'John'}
let dict.fn = function('Fundict')
" call it
call dict.fn('Doe')
" function ref
let F = function('Fundict', dict)
call F('Smith')
" with empty arg
let G = function('Fundict', [], dict)
call G('Foo')
" with predefined arg
let H = function('Fundict', ['Bar'], dict)
call H()
Anonymous function :
let dict = {'name' : 'John'}
fun! dict.iam (arg) dict
echo self.name a:arg
endfun
call dict.iam('Will')
Each window has a :
- local tab number
- global unique ID (until you restart vim, of course)
let current_tab = tabpagenr()
let last_tab = tabpagenr('$')
With tabpagebuflist()
:
let last = tabpagenr('$')
for tab in range(1, last)
echo tab ':' tabpagebuflist(tab)
endfor
Get id :
let win_nr = winnr()
echo win_nr
Current local number in a given tab :
let tab_nr = 2
let win_nr = tabpagewinnr(tab_nr)
let last_win_nr = tabpagewinnr(tab_nr, '$')
let num_win_on_tab = last_win_nr
Go to it :
let win_nr = 2
execute win_nr 'wincmd w'
Get id :
let win_local_nr = 2
let tab_nr = 3
let win_id = win_getid(win_local_nr, tab_nr)
echo win_id
let current_win_id = win_getid()
echo current_win_id
Go to id :
let win_id = 1012
call win_gotoid(win_id)
Find in which window(s) is displayed a buffer :
let win_list = win_findbuf(buf_nr)
Of course, you can use :
" command
nnoremap <c-right> :tabnext<cr>
" with <c-u> to avoid things like :'<,'>
nnoremap <c-right> :<c-u>tabnext<cr>
" call function
nnoremap <c-right> :call goto_next_tab()<cr>
" from insert mode
inoremap <c-right> <esc>:tabnext<cr>i
but it’s often better to use <cmd>
:
" command, no need to add <c-u>
nnoremap <c-right> <cmd>tabnext<cr>
" call function
nnoremap <c-right> <cmd>call goto_next_tab()<cr>
" from insert mode, no need to surround with <esc>...i
inoremap <c-right> <cmd>tabnext<cr>
Advantages :
- execute the command without leaving the mode
- no need to add
<c-u>
after the colon - also works from insert mode without addition
- faster
- silent
Define a plug :
noremap <plug>(myplugin-function) <cmd>call plugin#file#function()<cr>
and let the user use it for his own map :
map <user-key> <plug>(myplugin-function)
This last map must be recursive to work.
You can trigger a custom event, somewhere in your plugin :
doautocmd User MyPluginEvent
and let the user add whatever command he wants to it :
autocmd User MyPluginEvent echo 'hello there !'
To avoid auto-execution, use noautocmd
.
This one change window without triggering autocommand :
noautocmd call win_gotoid(window_id)
If needed, you can trigger them later by using doautocmd
:
doautocmd WinEnter
doautocmd BufEnter
...
Some buffers are special, and not related to a file, like the quickfix
window. In that case, writing it does not mean a simple copy to the
file system, but can involve a completely distinct operation. The
BufWriteCmd
event is there to modify the meaning of the :write
command. These autocommands are often buffer local. Example :
autocmd BufWriteCmd <buffer> call FancyStuff ()
Writing the buffer where this autocommand is defined will call
FancyStuff()
instead of saving to disc.
First define a global var to hold the ring :
let g:yankring = []
then define a function to add yanks :
fun! Add2yankring ()
let content = getreg('"')
call insert(yanks, content)
endfun
With this autocommand, your function will be triggered at each yank :
autocmd TextYankPost * call Add2yankring()