Learning the vi Editor/Vim/VimL Script language
Vim script (aka Vimscript, or VimL) is a full feature scripting language, meaning it can solve almost any text processing problem.
Statements
[edit | edit source]Assignment
[edit | edit source]To set a variable use:
let variable = expression
To set a built-in setting you have two options:
set setting = expression " (use the regular command for changing a setting) let &setting = "expression" " (treat the setting as a special kind of variable)
Data types
[edit | edit source]There are five datatypes:
Number
[edit | edit source]A 32 bit signed integer.
String
[edit | edit source]A NULL terminated string of 8-bit unsigned characters (bytes). Strings can be created by either ‘'’ or ‘"’ quotes. When using strings quoted with the double quote ‘"’ the text is interpreted i.e. "\n" becomes a new line while strings quoted with a single quote ‘'’ are not interpreted, i.e. '\n' means just that, a backslash and an n. The following two strings are identical:
let String_1 = "C:\\WinNT" let String_2 = 'C:\WinNT'
Any other datatype can be converted into a string using the string () function.
Funcref
[edit | edit source]A reference to a function. A Funcref can be created from a string by the use of the function function.
let Function_1 = function ("MyFunc")
List
[edit | edit source]An ordered sequence of items.
let List_1 = [
\ "a",
\ "b",
\ "c"]
A list can be created from a string by the use of the split function.
let List_2 = split ("a b c")
Dictionary
[edit | edit source]An associative, unordered array: Each entry has a key and a value.
let Dictionary_1 = {
\ 1: 'one',
\ 2: 'two',
\ 3: 'three'}
Objects
[edit | edit source]VIM also supports object oriented programming by combining Funcref and Dictionary to an Object:
let mydict = { \'data': [0, 1, 2, 3]} function mydict.len () dict return len (self.data) endfunction mydict.len
for more information see Object oriented programming
Control Structures
[edit | edit source]The existence of control structures is the main difference between vi's ex commands and vim's scripting language. They make the difference between a simple command set (vi) and a full features script language (vim).
condition
[edit | edit source]if condition operations elseif condition operations else operations endif
loop
[edit | edit source]while
[edit | edit source]while condition operations endwhile
for
[edit | edit source]For loops are available from vim 7 onwards. They iterate over List or Directory structures.
for var in list operations endfor
exceptions
[edit | edit source]try operations catch /pattern/ error handling operations finally clean-up operations endtry
Subprograms
[edit | edit source]Simple Subprograms
[edit | edit source]Like most Shell-Languages all subprograms are stored in separate files which you load either with the source or runtime command. The difference lies in the use of a search path. runtime uses a search path and allows wildcards to find the sub-program while source needs the full path. The following commands do the same - provided that "~/vimfiles" is part of your runtime search path:
runtime setup.vim source ~/vimfiles/setup.vim
For both commands need to add the .vim
extension. Since runtime supports both a search path and wildcards more than one match is possible. If you want runtime to load all the matches - and not just the first hit - use runtime!.
Functions
[edit | edit source]function f ( parameter ) operations endfunction
New with vim 7 is the autoload option for functions. If you name a function Filename#Functionname or Directory#Filename#Functionname then the function will be automatically loaded on first call. The file containing the function must be placed in one of the "autoload" runtime directories and be named "Filename.vim" or "Directory/Filename.vim". This option is especially useful for functions which you don't always need on in Object oriented programming.
Commands
[edit | edit source]command Command Command
Command are often used as shortcut for functions and subprograms:
command C -nargs=* call F ( <f-args> ) command C source ~/vimfiles/s.vim
Object oriented programming
[edit | edit source]Vim 7 now allows object oriented programming. However, in order to make it real you need to combine several features, namely Dictionaries, Funcrefs and the new function autoload.
The following example class is taken from the gnat compiler plugin for vim. The actual functions implementations have been removed as they are not needed to understand the concept. If you like to have a look at the full version you can download the plugin from vim.org site.
Step by Step walk-through
[edit | edit source]We add our new class to a autoload script. That way the class is available when and only when needed:
if exists ("g:loaded_gnat_autoload") || version < 700 finish else let g:loaded_gnat_autoload=1
Each function we define need to be defined with the "dict" attribute. Apart from that they are just normal scripting functions.
function gnat#Make () dict ... return endfunction gnat#Make function gnat#Pretty () dict ... return endfunction gnat#Pretty function gnat#Find () dict ... return endfunction gnat#Find function gnat#Tags () dict ... return endfunction gnat#Tags function gnat#Set_Project_File (...) dict ... return endfunction gnat#Set_Project_File function gnat#Get_Command (Command) dict ... return ... endfunction gnat#Get_Command
The most important step is the composition of the object. In most OO languages this happens automatically - But with vim we have to do this ourselves. For best flexibility the use of a so called constructor function is suggested. The constructor is not marked with "dict":
function gnat#New ()
The constructor creates a dictionary which assigns all the object functions to one element of the dictionary:
let Retval = { \ 'Make' : function ('gnat#Make'), \ 'Pretty' : function ('gnat#Pretty'), \ 'Find' : function ('gnat#Find'), \ 'Tags' : function ('gnat#Tags'), \ 'Set_Project_File' : function ('gnat#Set_Project_File'), \ 'Get_Command' : function ('gnat#Get_Command'), \ 'Project_File' : '',
We optionally can now add data entries to our object:
\ 'Make_Command' : '"gnat make -P " . self.Project_File . " -F -gnatef "', \ 'Pretty_Command' : '"gnat pretty -P " . self.Project_File . " "', \ 'Find_Program' : '"gnat find -P " . self.Project_File . " -F "', \ 'Tags_Command' : '"gnat xref -P " . self.Project_File . " -v *.AD*"', \ 'Error_Format' : '%f:%l:%c: %trror: %m,' . \ '%f:%l:%c: %tarning: %m,' . \ '%f:%l:%c: (%ttyle) %m'}
If needed additional modifications to the object are also possible. At this stage you can already use the OO-way:
if argc() == 1 && fnamemodify(argv (0), ':e') == 'gpr' call Retval.Set_Project_File(argv(0)) elseif strlen(v:servername) > 0 call Retval.Set_Project_File(v:servername . '.gpr') endif
The last operation of the constructor is the return of the newly created object.
return Retval endfunction gnat#New
It is also possible to defined additional non dict functions. These functions are the equivalent to the "static" or "class" methods of other OO languages.
function gnat#Insert_Tags_Header() ... return endfunction gnat#Insert_Tags_Header finish endif