--- title: Vim scripting category: Vim prism_languages: [vim] updated: 2020-07-05 weight: -10 tags: [Featurable] --- ### Start hacking ```vim let name = "John" echo "Hello, " . name ``` You can either put this in a script (`script.vim`) and run it (`:source script.vim`), or you can type the commands individually in normal mode as `:let` and `:echo`. ### Learn by example ```vim function! SuperTab() let l:part = strpart(getline('.'),col('.')-2,1) if (l:part =~ '^\W\?$') return "\" else return "\" endif endfunction imap =SuperTab() ``` [Here](http://www.vimbits.com/bits/46)'s another example with [functions](#functions), [variables](#variables) and [mapping](#mapping). Variables --------- ### Defining {: .-prime} ```vim let var = "hello" ``` ### Variable prefixes ```vim let g:ack_options = '-s -H' " g: global let s:ack_program = 'ack' " s: local (to script) let l:foo = 'bar' " l: local (to function) ``` The `s:` prefix is also available in function names. See `:help local-variables` ### Other prefixes ```vim let w:foo = 'bar' " w: window let b:state = 'on' " b: buffer let t:state = 'off' " t: tab echo v:var " v: vim special ``` ```vim let @/ = '' " @ register (this clears last search pattern) echo $PATH " $ env ``` ### Vim options ```vim echo 'tabstop is ' . &tabstop if &insertmode echo &g:option echo &l:option ``` Prefix Vim options with `&` ### Operators ```vim a + b " numbers only! 'hello ' . name " concat ``` ```vim let var -= 2 let var += 5 let var .= 'string' " concat ``` ## Strings ### Strings ```vim let str = "String" let str = "String with \n newline" let literal = 'literal, no \ escaping' let literal = 'that''s enough' " double '' => ' echo "result = " . re " concatenation ``` Also see `:help literal-string` and `:help expr-quote`. See: [Strings](http://learnvimscriptthehardway.stevelosh.com/chapters/26.html) ### String functions ```vim strlen(str) " length len(str) " same strchars(str) " character length split("one two three") "=> ['one', 'two', 'three'] split("one.two.three", '.') "=> ['one', 'two', 'three'] join(['a', 'b'], ',') "=> 'a,b' tolower('Hello') toupper('Hello') ``` Also see `:help functions` See: [String functions](http://learnvimscriptthehardway.stevelosh.com/chapters/27.html) Functions --------- ### Functions {: .-prime} ```vim " prefix with s: for local script-only functions function! s:Initialize(cmd, args) " a: prefix for arguments echo "Command: " . a:cmd return 1 endfunction ``` See: [Functions](http://learnvimscriptthehardway.stevelosh.com/chapters/23.html) ### Overwriting ```vim function f1() echo "f1" endfunction function! f1() echo "f1 overridden" endfunction ``` If you define two functions with the same name, Vim will throw an error complaining that the function `f1` already exists. To overwrite the previous function with the same name, add a `!` after the function keyword. ### Namespacing ```vim function! myplugin#hello() ``` ### Calling functions ```vim call s:Initialize() call s:Initialize("hello") ``` ### Consuming return values ```vim echo "Result: " . s:Initialize() ``` ### Abortable ```vim function! myfunction() abort endfunction ``` Aborts when an error occurs. ### Var arguments ```vim function! infect(...) echo a:0 "=> 2 echo a:1 "=> jake echo a:2 "=> bella for s in a:000 " a list echon ' ' . s endfor endfunction infect('jake', 'bella') ``` See `:help function-argument`. See: [Var arguments](http://learnvimscriptthehardway.stevelosh.com/chapters/24.html) Loops ----- ```vim for s in list echo s continue " jump to start of loop break " breaks out of a loop endfor ``` ```vim while x < 5 endwhile ``` Custom commands --------------- ### Custom commands {: .-prime} ```vim command! Save :set fo=want tw=80 nowrap ``` Custom commands start with uppercase letters. The `!` redefines a command if it already exists. ### Commands calling functions ```vim command! Save call foo() ``` {: .-setup} ```vim function! s:foo() ... endfunction ``` ### Commands with arguments ```vim command! -nargs=? Save call script#foo() ``` {: .-setup} | What | What | | ---- | ---- | | `-nargs=0` | 0 arguments, default | | `-nargs=1` | 1 argument, includes spaces | | `-nargs=?` | 0 or 1 argument | | `-nargs=*` | 0+ arguments, space separated | | `-nargs=+` | 1+ arguments, space reparated | Flow ---- ### Conditionals ```vim let char = getchar() if char == "\" " ... elseif char == "\" " ... else " ... endif ``` ### Truthiness ```vim if 1 | echo "true" | endif if 0 | echo "false" | endif ``` ```vim if 1 "=> 1 (true) if 0 "=> 0 (false) if "1" "=> 1 (true) if "456" "=> 1 (true) if "xfz" "=> 0 (false) ``` No booleans. `0` is false, `1` is true. See: [Truthiness](http://learnvimscriptthehardway.stevelosh.com/chapters/21.html) ### Operators ```vim if 3 > 2 if a && b if (a && b) || (c && d) if !c ``` See `:help expression-syntax`. See: [Operators](http://learnvimscriptthehardway.stevelosh.com/chapters/22.html) ### Strings ```vim if name ==# 'John' " case-sensitive if name ==? 'John' " case-insensitive if name == 'John' " depends on :set ignorecase " also: is#, is?, >=#, >=?, and so on ``` ### Identity operators ```vim a is b a isnot b ``` Checks if it's the same instance object. ### Regexp matches ```vim "hello" =~ 'xx*' "hello" !~ 'xx*' "hello" =~ '\v<\d+>' ``` `\v` enables "extended" regex mode which allows word boundary (`<>`), `+`, and more. ### Single line ```vim if empty(a:path) | return [] | endif a ? b : c ``` Use `|` to join lines together. ### Boolean logic ```vim if g:use_dispatch && s:has_dispatch ··· endif ``` Lists ----- ### Lists ```vim let mylist = [1, two, 3, "four"] let first = mylist[0] let last = mylist[-1] " Suppresses errors let second = get(mylist, 1) let second = get(mylist, 1, "NONE") ``` ### Functions ```vim len(mylist) empty(mylist) sort(list) let sortedlist = sort(copy(list)) split('hello there world', ' ') ``` ### Concatenation ```vim let longlist = mylist + [5, 6] let mylist += [7, 8] ``` ### Sublists ```vim let shortlist = mylist[2:-1] let shortlist = mylist[2:] " same let shortlist = mylist[2:2] " one item ``` ### Push ```vim let alist = [1, 2, 3] let alist = add(alist, 4) ``` ### Map ```vim call map(files, "bufname(v:val)") " use v:val for value call filter(files, 'v:val != ""') ``` Dictionaries ------------ ### Dictionaries ```vim let colors = { \ "apple": "red", \ "banana": "yellow" } echo colors["a"] echo get(colors, "apple") " suppress error ``` See `:help dict` ### Using dictionaries ```vim remove(colors, "apple") ``` ```vim " :help E715 if has_key(dict, 'foo') if empty(dict) keys(dict) len(dict) ``` ```vim max(dict) min(dict) ``` ```vim count(dict, 'x') string(dict) ``` ```vim map(dict, '<>> " . v:val') ``` ### Iteration ```vim for key in keys(mydict) echo key . ': ' . mydict[key] endfor ``` ### Prefixes ```vim keys(s:) ``` Prefixes (`s:`, `g:`, `l:`, etc) are actually dictionaries. ### Extending ```vim " Extending with more let extend(s:fruits, { ... }) ``` Casting ------- ```vim str2float("2.3") str2nr("3") float2nr("3.14") ``` Numbers ------- ### Numbers {: .-prime} ```vim let int = 1000 let int = 0xff let int = 0755 " octal ``` See `:help Number`. See: [Numbers](http://learnvimscriptthehardway.stevelosh.com/chapters/25.html) ### Floats ```vim let fl = 100.1 let fl = 5.4e4 ``` See `:help Float` ### Arithmetic ```vim 3 / 2 "=> 1, integer division 3 / 2.0 "=> 1.5 3 * 2.0 "=> 6.0 ``` ### Math functions ```vim sqrt(100) floor(3.5) ceil(3.3) abs(-3.4) sin() cos() tan() sinh() cosh() tanh() asin() acos() atan() ``` Vim-isms -------- ### Execute a command ```vim execute "vsplit" execute "e " . fnameescape(filename) ``` Runs an ex command you typically run with `:`. Also see `:help execute`. See: [Execute a command](http://learnvimscriptthehardway.stevelosh.com/chapters/28.html) ### Running keystrokes ```vim normal G normal! G " skips key mappings execute "normal! gg/foo\dd" ``` Use `:normal` to execute keystrokes as if you're typing them in normal mode. Combine with `:execute` for special keystrokes. See: [Running keystrokes](http://learnvimscriptthehardway.stevelosh.com/chapters/29.html) ### Getting filenames ```vim echo expand("%") " path/file.txt echo expand("%:t") " file.txt echo expand("%:p:h") " /home/you/path/file.txt echo expand("%:r") " path/file echo expand("%:e") " txt ``` See `:help expand` ### Silencing ```vim silent g/Aap/p ``` Suppresses output. See `:help silent` ### Echo ```vim echoerr 'oh it failed' echomsg 'hello there' echo 'hello' echohl WarningMsg | echomsg "=> " . a:msg | echohl None ``` ### Settings ```vim set number set nonumber set number! " toggle set numberwidth=5 set guioptions+=e ``` ### Prompts ```vim let result = confirm("Sure?") execute "confirm q" ``` ### Built-ins ```vim has("feature") " :h feature-list executable("python") globpath(&rtp, "syntax/c.vim") exists("$ENV") exists(":command") exists("variable") exists("+option") exists("g:...") ``` Mapping ------- {: .-three-column} ### Mapping commands ```vim nmap vmap imap xmap nnoremap vnoremap inoremap xnoremap ... ``` ### Explanation ```vim [nvixso](nore)map ``` ``` │ └ don't recurse │ └ normal, visual, insert, eX mode, select, operator-pending ``` {: .-setup} ### Arguments | `` | only in current buffer | | `` | no echo | | `` | | Syntax ------ ### Highlights ```vim hi Comment term=bold,underline gui=bold ctermfg=4 guifg=#80a0ff ``` ### Filetype detection ```vim augroup filetypedetect au! BufNewFile,BufRead *.json setf javascript augroup END au Filetype markdown setlocal spell ``` ### Conceal ```vim set conceallevel=2 syn match newLine "
" conceal cchar=} hi newLine guifg=green ``` ### Region conceal ```vim syn region inBold concealends matchgroup=bTag start="" end="" hi inBold gui=bold hi bTag guifg=blue ``` ### Syntax ```vim syn match :name ":regex" :flags syn region Comment start="/\*" end="\*/" syn region String start=+"+ end=+"+ skip=+\\"+ syn cluster :name contains=:n1,:n2,:n3... flags: keepend oneline nextgroup= contains= contained hi def link markdownH1 htmlH1 ``` ### Include guards ```vim if exists('g:loaded_myplugin') finish endif " ... let g:loaded_myplugin = 1 ```