2019-11-10 16:05:23 +03:00
|
|
|
---
|
|
|
|
language: Vimscript
|
2019-12-22 15:31:46 +03:00
|
|
|
filename: learnvimscript.vim
|
2019-11-10 16:05:23 +03:00
|
|
|
contributors:
|
|
|
|
- ["HiPhish", "http://hiphish.github.io/"]
|
|
|
|
---
|
|
|
|
|
|
|
|
```vim
|
2019-12-22 15:31:46 +03:00
|
|
|
" ##############
|
|
|
|
" Introduction
|
|
|
|
" ##############
|
|
|
|
"
|
|
|
|
" Vim script (also called VimL) is the subset of Vim's ex-commands which
|
2022-04-20 13:12:47 +03:00
|
|
|
" supplies a number of features one would expect from a scripting language,
|
2019-12-22 15:31:46 +03:00
|
|
|
" such as values, variables, functions or loops. Always keep in the back of
|
|
|
|
" your mind that a Vim script file is just a sequence of ex-commands. It is
|
|
|
|
" very common for a script to mix programming-language features and raw
|
|
|
|
" ex-commands.
|
|
|
|
"
|
2020-02-02 19:56:16 +03:00
|
|
|
" You can run Vim script directly by entering the commands in command-line mode
|
|
|
|
" (press `:` to enter command-line mode), or you can write them to a file
|
|
|
|
" (without the leading `:`) and source it in a running Vim instance (`:source
|
2019-12-22 15:31:46 +03:00
|
|
|
" path/to/file`). Some files are sourced automatically as part of your
|
|
|
|
" configuration (see |startup|). This guide assumes that you are familiar
|
|
|
|
" with ex-commands and will only cover the scripting. Help topics to the
|
|
|
|
" relevant manual sections are included.
|
|
|
|
"
|
|
|
|
" See |usr_41.txt| for the official introduction to Vim script. A comment is
|
|
|
|
" anything following an unmatched `"` until the end of the line, and `|`
|
|
|
|
" separates instructions (what `;` does in most other languages). References to
|
|
|
|
" the manual as surrounded with `|`, such as |help.txt|.
|
|
|
|
|
2019-11-10 16:05:23 +03:00
|
|
|
" This is a comment
|
|
|
|
|
|
|
|
" The vertical line '|' (pipe) separates commands
|
|
|
|
echo 'Hello' | echo 'world!'
|
|
|
|
|
|
|
|
" Putting a comment after a command usually works
|
|
|
|
pwd " Displays the current working directory
|
|
|
|
|
2022-12-10 18:05:34 +03:00
|
|
|
" Except for some commands it does not; use the command delimiter before the
|
2019-11-10 16:05:23 +03:00
|
|
|
" comment (echo assumes that the quotation mark begins a string)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 'Hello world!' | " Displays a message
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2022-06-17 22:56:04 +03:00
|
|
|
" Line breaks can be escaped by placing a backslash as the first non-whitespace
|
2019-11-10 16:05:23 +03:00
|
|
|
" character on the *following* line. Only works in script files, not on the
|
|
|
|
" command line
|
|
|
|
echo " Hello
|
|
|
|
\ world "
|
|
|
|
|
2024-04-20 10:57:37 +03:00
|
|
|
echo [1,
|
2019-11-10 16:05:23 +03:00
|
|
|
\ 2]
|
|
|
|
|
|
|
|
echo {
|
|
|
|
\ 'a': 1,
|
|
|
|
\ 'b': 2
|
|
|
|
\}
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" #######
|
|
|
|
" Types
|
|
|
|
" #######
|
|
|
|
"
|
|
|
|
" For an overview of types see |E712|. For an overview of operators see
|
|
|
|
" |expression-syntax|
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Numbers (|expr-number|)
|
|
|
|
" #######
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 123 | " Decimal
|
|
|
|
echo 0b1111011 | " Binary
|
|
|
|
echo 0173 | " Octal
|
|
|
|
echo 0x7B | " Hexadecimal
|
|
|
|
echo 123.0 | " Floating-point
|
|
|
|
echo 1.23e2 | " Floating-point (scientific notation)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Note that an *integer* number with a leading `0` is in octal notation. The
|
|
|
|
" usual arithmetic operations are supported.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 1 + 2 | " Addition
|
|
|
|
echo 1 - 2 | " Subtraction
|
|
|
|
echo - 1 | " Negation (unary minus)
|
|
|
|
echo + 1 | " Unary plus (does nothing really, but still legal)
|
|
|
|
echo 1 * 2 | " Multiplication
|
|
|
|
echo 1 / 2 | " Division
|
|
|
|
echo 1 % 2 | " Modulo (remainder)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Booleans (|Boolean|)
|
|
|
|
" ########
|
|
|
|
"
|
|
|
|
" The number 0 is false, every other number is true. Strings are implicitly
|
|
|
|
" converted to numbers (see below). There are two pre-defined semantic
|
|
|
|
" constants.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo v:true | " Evaluates to 1 or the string 'v:true'
|
|
|
|
echo v:false | " Evaluates to 0 or the string 'v:false'
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Boolean values can result from comparison of two objects.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo x == y | " Equality by value
|
2022-12-10 18:05:34 +03:00
|
|
|
echo x != y | " Inequality
|
2019-12-22 15:41:46 +03:00
|
|
|
echo x > y | " Greater than
|
|
|
|
echo x >= y | " Greater than or equal
|
|
|
|
echo x < y | " Smaller than
|
|
|
|
echo x <= y | " Smaller than or equal
|
|
|
|
echo x is y | " Instance identity (lists and dictionaries)
|
|
|
|
echo x isnot y | " Instance non-identity (lists and dictionaries)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Strings are compared based on their alphanumerical ordering
|
|
|
|
" echo 'a' < 'b'. Case sensitivity depends on the setting of 'ignorecase'
|
2019-12-22 15:31:46 +03:00
|
|
|
"
|
2019-11-10 16:05:23 +03:00
|
|
|
" Explicit case-sensitivity is specified by appending '#' (match case) or '?'
|
2022-12-10 18:05:34 +03:00
|
|
|
" (ignore case) to the operator. Prefer explicitly case sensitivity when writing
|
2019-11-10 16:05:23 +03:00
|
|
|
" portable scripts.
|
|
|
|
|
|
|
|
echo 'a' < 'B' | " True or false depending on 'ignorecase'
|
|
|
|
echo 'a' <? 'B' | " True
|
|
|
|
echo 'a' <# 'B' | " False
|
|
|
|
|
|
|
|
" Regular expression matching
|
2019-12-22 15:41:46 +03:00
|
|
|
echo "hi" =~ "hello" | " Regular expression match, uses 'ignorecase'
|
|
|
|
echo "hi" =~# "hello" | " Regular expression match, case sensitive
|
|
|
|
echo "hi" =~? "hello" | " Regular expression match, case insensitive
|
|
|
|
echo "hi" !~ "hello" | " Regular expression unmatch, use 'ignorecase'
|
|
|
|
echo "hi" !~# "hello" | " Regular expression unmatch, case sensitive
|
|
|
|
echo "hi" !~? "hello" | " Regular expression unmatch, case insensitive
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Boolean operations are possible.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo v:true && v:false | " Logical AND
|
|
|
|
echo v:true || v:false | " Logical OR
|
|
|
|
echo ! v:true | " Logical NOT
|
|
|
|
echo v:true ? 'yes' : 'no' | " Ternary operator
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Strings (|String|)
|
|
|
|
" #######
|
|
|
|
"
|
|
|
|
" An ordered zero-indexed sequence of bytes. The encoding of text into bytes
|
|
|
|
" depends on the option |'encoding'|.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Literal constructors
|
2019-12-22 15:41:46 +03:00
|
|
|
echo "Hello world\n" | " The last two characters stand for newline
|
|
|
|
echo 'Hello world\n' | " The last two characters are literal
|
|
|
|
echo 'Let''s go!' | " Two single quotes become one quote character
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Single-quote strings take all characters are literal, except two single
|
2024-04-20 10:57:37 +03:00
|
|
|
" quotes, which are taken to be a single quote in the string itself. See
|
2019-12-22 15:31:46 +03:00
|
|
|
" |expr-quote| for all possible escape sequences.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" String concatenation
|
|
|
|
" The .. operator is preferred, but only supported in since Vim 8.1.1114
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 'Hello ' . 'world' | " String concatenation
|
|
|
|
echo 'Hello ' .. 'world' | " String concatenation (new variant)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" String indexing
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 'Hello'[0] | " First byte
|
|
|
|
echo 'Hello'[1] | " Second byte
|
|
|
|
echo 'Hellö'[4] | " Returns a byte, not the character 'ö'
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Substrings (second index is inclusive)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 'Hello'[:] | " Copy of entire string
|
|
|
|
echo 'Hello'[1:3] | " Substring, second to fourth byte
|
|
|
|
echo 'Hello'[1:-2] | " Substring until second to last byte
|
|
|
|
echo 'Hello'[1:] | " Substring with starting index
|
|
|
|
echo 'Hello'[:2] | " Substring with ending index
|
|
|
|
echo 'Hello'[-2:] | " Substring relative to end of string
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" A negative index is relative to the end of the string. See
|
|
|
|
" |string-functions| for all string-related functions.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Lists (|List|)
|
|
|
|
" #####
|
|
|
|
"
|
|
|
|
" An ordered zero-indexed heterogeneous sequence of arbitrary Vim script
|
|
|
|
" objects.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Literal constructor
|
2019-12-22 15:41:46 +03:00
|
|
|
echo [] | " Empty list
|
|
|
|
echo [1, 2, 'Hello'] | " List with elements
|
|
|
|
echo [1, 2, 'Hello', ] | " Trailing comma permitted
|
|
|
|
echo [[1, 2], 'Hello'] | " Lists can be nested arbitrarily
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" List concatenation
|
2019-12-22 15:41:46 +03:00
|
|
|
echo [1, 2] + [3, 4] | " Creates a new list
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" List indexing, negative is relative to end of list (|list-index|)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo [1, 2, 3, 4][2] | " Third element
|
|
|
|
echo [1, 2, 3, 4][-1] | " Last element
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" List slicing (|sublist|)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo [1, 2, 3, 4][:] | " Shallow copy of entire list
|
|
|
|
echo [1, 2, 3, 4][:2] | " Sublist until third item (inclusive)
|
|
|
|
echo [1, 2, 3, 4][2:] | " Sublist from third item (inclusive)
|
|
|
|
echo [1, 2, 3, 4][:-2] | " Sublist until second-to-last item (inclusive)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" All slicing operations create new lists. To modify a list in-place use list
|
|
|
|
" functions (|list-functions|) or assign directly to an item (see below about
|
|
|
|
" variables).
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Dictionaries (|Dictionary|)
|
|
|
|
" ############
|
|
|
|
"
|
|
|
|
" An unordered sequence of key-value pairs, keys are always strings (numbers
|
|
|
|
" are implicitly converted to strings).
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Dictionary literal
|
2019-12-22 15:41:46 +03:00
|
|
|
echo {} | " Empty dictionary
|
|
|
|
echo {'a': 1, 'b': 2} | " Dictionary literal
|
|
|
|
echo {'a': 1, 'b': 2, } | " Trailing comma permitted
|
|
|
|
echo {'x': {'a': 1, 'b': 2}} | " Nested dictionary
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Indexing a dictionary
|
2019-12-22 15:41:46 +03:00
|
|
|
echo {'a': 1, 'b': 2}['a'] | " Literal index
|
|
|
|
echo {'a': 1, 'b': 2}.a | " Syntactic sugar for simple keys
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" See |dict-functions| for dictionary manipulation functions.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Funcref (|Funcref|)
|
|
|
|
" #######
|
|
|
|
"
|
|
|
|
" Reference to a function, uses the function name as a string for construction.
|
|
|
|
" When stored in a variable the name of the variable has the same restrictions
|
|
|
|
" as a function name (see below).
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo function('type') | " Reference to function type()
|
2019-12-22 15:31:46 +03:00
|
|
|
" Note that `funcref('type')` will throw an error because the argument must be
|
|
|
|
" a user-defined function; see further below for defining your own functions.
|
2019-12-22 15:41:46 +03:00
|
|
|
echo funcref('type') | " Reference by identity, not name
|
2019-12-22 15:31:46 +03:00
|
|
|
" A lambda (|lambda|) is an anonymous function; it can only contain one
|
|
|
|
" expression in its body, which is also its implicit return value.
|
2019-12-22 15:41:46 +03:00
|
|
|
echo {x -> x * x} | " Anonymous function
|
|
|
|
echo function('substitute', ['hello']) | " Partial function
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Regular expression (|regular-expression|)
|
|
|
|
" ##################
|
|
|
|
"
|
|
|
|
" A regular expression pattern is generally a string, but in some cases you can
|
|
|
|
" also use a regular expression between a pair of delimiters (usually `/`, but
|
|
|
|
" you can choose anything).
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Substitute 'hello' for 'Hello'
|
|
|
|
substitute/hello/Hello/
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" ###########################
|
|
|
|
" Implicit type conversions
|
|
|
|
" ###########################
|
|
|
|
"
|
|
|
|
" Strings are converted to numbers, and numbers to strings when necessary. A
|
|
|
|
" number becomes its decimal notation as a string. A string becomes its
|
|
|
|
" numerical value if it can be parsed to a number, otherwise it becomes zero.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
echo "1" + 1 | " Number
|
|
|
|
echo "1" .. 1 | " String
|
|
|
|
echo "0xA" + 1 | " Number
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Strings are treated like numbers when used as booleans
|
2019-12-22 15:41:46 +03:00
|
|
|
echo "true" ? 1 : 0 | " This string is parsed to 0, which is false
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" ###########
|
|
|
|
" Variables
|
|
|
|
" ###########
|
2024-04-20 10:57:37 +03:00
|
|
|
"
|
2019-12-22 15:31:46 +03:00
|
|
|
" Variables are bound within a scope; if no scope is provided a default is
|
|
|
|
" chosen by Vim. Use `:let` and `:const` to bind a value and `:unlet` to unbind
|
|
|
|
" it.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
let b:my_var = 1 | " Local to current buffer
|
|
|
|
let w:my_var = 1 | " Local to current window
|
|
|
|
let t:my_var = 1 | " Local to current tab page
|
|
|
|
let g:my_var = 1 | " Global variable
|
|
|
|
let l:my_var = 1 | " Local to current function (see functions below)
|
|
|
|
let s:my_var = 1 | " Local to current script file
|
|
|
|
let a:my_arg = 1 | " Function argument (see functions below)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" The Vim scope is read-only
|
2019-12-22 15:41:46 +03:00
|
|
|
echo v:true | " Special built-in Vim variables (|v:var|)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Access special Vim memory like variables
|
2019-12-22 15:41:46 +03:00
|
|
|
let @a = 'Hello' | " Register
|
|
|
|
let $PATH='' | " Environment variable
|
|
|
|
let &textwidth = 79 | " Option
|
|
|
|
let &l:textwidth = 79 | " Local option
|
|
|
|
let &g:textwidth = 79 | " Global option
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Access scopes as dictionaries (can be modified like all dictionaries)
|
2019-12-22 15:31:46 +03:00
|
|
|
" See the |dict-functions|, especially |get()|, for access and manipulation
|
2019-12-22 15:41:46 +03:00
|
|
|
echo b: | " All buffer variables
|
|
|
|
echo w: | " All window variables
|
|
|
|
echo t: | " All tab page variables
|
|
|
|
echo g: | " All global variables
|
|
|
|
echo l: | " All local variables
|
|
|
|
echo s: | " All script variables
|
|
|
|
echo a: | " All function arguments
|
|
|
|
echo v: | " All Vim variables
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Constant variables
|
2019-12-22 15:41:46 +03:00
|
|
|
const x = 10 | " See |:const|, |:lockvar|
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Function reference variables have the same restrictions as function names
|
2019-12-22 15:41:46 +03:00
|
|
|
let IsString = {x -> type(x) == type('')} | " Global: capital letter
|
|
|
|
let s:isNumber = {x -> type(x) == type(0)} | " Local: any name allowed
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" When omitted the scope `g:` is implied, except in functions, there `l:` is
|
|
|
|
" implied.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Multiple value binding (list unpacking)
|
|
|
|
" #######################################
|
|
|
|
"
|
2019-11-10 16:05:23 +03:00
|
|
|
" Assign values of list to multiple variables (number of items must match)
|
|
|
|
let [x, y] = [1, 2]
|
|
|
|
|
2022-12-10 18:05:34 +03:00
|
|
|
" Assign the remainder to a rest variable (note the semicolon)
|
2019-11-10 16:05:23 +03:00
|
|
|
let [mother, father; children] = ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" ##############
|
|
|
|
" Flow control
|
|
|
|
" ##############
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Conditional (|:if|, |:elseif|, |:else|, |:endif|)
|
|
|
|
" ###########
|
2024-04-20 10:57:37 +03:00
|
|
|
"
|
2019-12-22 15:31:46 +03:00
|
|
|
" Conditions are set between `if` and `endif`. They can be nested.
|
|
|
|
|
|
|
|
let condition = v:true
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
if condition
|
|
|
|
echo 'First condition'
|
|
|
|
elseif another_condition
|
|
|
|
echo 'Second condition'
|
|
|
|
else
|
|
|
|
echo 'Fail'
|
|
|
|
endif
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Loops (|:for|, |:endfor|, |:while|, |:endwhile|, |:break|, |:continue|)
|
|
|
|
" #####
|
|
|
|
"
|
|
|
|
" Two types of loops: `:for` and `:while`. Use `:continue` to skip to the next
|
|
|
|
" iteration, `:break` to break out of the loop.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" For-loop (|:for|, |:endfor|)
|
|
|
|
" ========
|
|
|
|
"
|
|
|
|
" For-loops iterate over lists and nothing else. If you want to iterate over
|
|
|
|
" another sequence you need to use a function which will create a list.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Iterate over a list
|
|
|
|
for person in ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
|
|
|
|
echo 'Hello ' .. person
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Iterate over a nested list by unpacking it
|
|
|
|
for [x, y] in [[1, 0], [0, 1], [-1, 0], [0, -1]]
|
|
|
|
echo 'Position: x =' .. x .. ', y = ' .. y
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Iterate over a range of numbers
|
|
|
|
for i in range(10, 0, -1) " Count down from 10
|
|
|
|
echo 'T minus' .. i
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Iterate over the keys of a dictionary
|
|
|
|
for symbol in keys({'π': 3.14, 'e': 2.71})
|
|
|
|
echo 'The constant ' .. symbol .. ' is a transcendent number'
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Iterate over the values of a dictionary
|
|
|
|
for value in values({'π': 3.14, 'e': 2.71})
|
|
|
|
echo 'The value ' .. value .. ' approximates a transcendent number'
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Iterate over the keys and values of a dictionary
|
|
|
|
for [symbol, value] in items({'π': 3.14, 'e': 2.71})
|
|
|
|
echo 'The number ' .. symbol .. ' is approximately ' .. value
|
|
|
|
endfor
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" While-loops (|:while|, |:endwhile|)
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
let there_yet = v:true
|
2019-11-10 16:05:23 +03:00
|
|
|
while !there_yet
|
|
|
|
echo 'Are we there yet?'
|
|
|
|
endwhile
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Exception handling (|exception-handling|)
|
|
|
|
" ##################
|
|
|
|
"
|
|
|
|
" Throw new exceptions as strings, catch them by pattern-matching a regular
|
|
|
|
" expression against the string
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Throw new exception
|
|
|
|
throw "Wrong arguments"
|
|
|
|
|
|
|
|
" Guard against an exception (the second catch matches any exception)
|
|
|
|
try
|
|
|
|
source path/to/file
|
|
|
|
catch /Cannot open/
|
|
|
|
echo 'Looks like that file does not exist'
|
|
|
|
catch /.*/
|
2020-02-02 19:56:16 +03:00
|
|
|
echo 'Something went wrong, but I do not know what'
|
2019-11-10 16:05:23 +03:00
|
|
|
finally
|
2020-02-02 19:56:16 +03:00
|
|
|
echo 'I am done trying'
|
2019-11-10 16:05:23 +03:00
|
|
|
endtry
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" ##########
|
|
|
|
" Functions
|
|
|
|
" ##########
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Defining functions (|:function|, |:endfunction|)
|
|
|
|
" ##################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Unscoped function names have to start with a capital letter
|
|
|
|
function! AddNumbersLoudly(x, y)
|
|
|
|
" Use a: scope to access arguments
|
2019-12-22 15:41:46 +03:00
|
|
|
echo 'Adding' .. a:x .. 'and' .. a:y | " A side effect
|
|
|
|
return a:x + a:y | " A return value
|
2019-11-10 16:05:23 +03:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
" Scoped function names may start with a lower-case letter
|
|
|
|
function! s:addNumbersLoudly(x, y)
|
|
|
|
echo 'Adding' .. a:x .. 'and' .. a:y
|
|
|
|
return a:x + a:y
|
|
|
|
endfunction
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Without the exclamation mark it would be an error to re-define a function,
|
|
|
|
" with the exclamation mark the new definition can replace the old one. Since
|
|
|
|
" Vim script files can be reloaded several times over the course of a session
|
|
|
|
" it is best to use the exclamation mark unless you really know what you are
|
|
|
|
" doing.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Function definitions can have special qualifiers following the argument list.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Range functions define two implicit arguments, which will be set to the range
|
|
|
|
" of the ex-command
|
|
|
|
function! FirstAndLastLine() range
|
|
|
|
echo [a:firstline, a:lastline]
|
|
|
|
endfunction
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Prints the first and last line that match a pattern (|cmdline-ranges|)
|
2019-11-10 16:05:23 +03:00
|
|
|
/^#!/,/!#$/call FirstAndLastLine()
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Aborting functions, abort once error occurs (|:func-abort|)
|
2019-11-10 16:05:23 +03:00
|
|
|
function! SourceMyFile() abort
|
2019-12-22 15:41:46 +03:00
|
|
|
source my-file.vim | " Try sourcing non-existing file
|
2019-11-10 16:05:23 +03:00
|
|
|
echo 'This will never be printed'
|
|
|
|
endfunction
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Closures, functions carrying values from outer scope (|:func-closure|)
|
2019-11-10 16:05:23 +03:00
|
|
|
function! MakeAdder(x)
|
|
|
|
function! Adder(n) closure
|
|
|
|
return a:n + a:x
|
|
|
|
endfunction
|
|
|
|
return funcref('Adder')
|
|
|
|
endfunction
|
|
|
|
let AddFive = MakeAdder(5)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo AddFive(3) | " Prints 8
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Dictionary functions, poor man's OOP methods (|Dictionary-function|)
|
2019-11-10 16:05:23 +03:00
|
|
|
function! Mylen() dict
|
2019-12-22 15:41:46 +03:00
|
|
|
return len(self.data) | " Implicit variable self
|
2019-11-10 16:05:23 +03:00
|
|
|
endfunction
|
|
|
|
let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
|
|
|
|
echo mydict.len()
|
|
|
|
|
|
|
|
" Alternatively, more concise
|
|
|
|
let mydict = {'data': [0, 1, 2, 3]}
|
|
|
|
function! mydict.len()
|
|
|
|
return len(self.data)
|
|
|
|
endfunction
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Calling functions (|:call|)
|
|
|
|
" #################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Call a function for its return value, and possibly for its side effects
|
|
|
|
let animals = keys({'cow': 'moo', 'dog': 'woof', 'cat': 'meow'})
|
|
|
|
|
2020-02-02 19:56:16 +03:00
|
|
|
" Call a function for its side effects only, ignore potential return value
|
2019-11-10 16:05:23 +03:00
|
|
|
call sign_undefine()
|
|
|
|
|
|
|
|
" The call() function calls a function reference and passes parameters as a
|
|
|
|
" list, and returns the function's result.
|
2019-12-22 15:41:46 +03:00
|
|
|
echo call(function('get'), [{'a': 1, 'b': 2}, 'c', 3]) | " Prints 3
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Recall that Vim script is embedded within the ex-commands, that is why we
|
|
|
|
" cannot just call a function directly, we have to use the `:call` ex-command.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Function namespaces (|write-library-script|, |autoload|)
|
|
|
|
" ###################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Must be defined in autoload/foo/bar.vim
|
|
|
|
" Namspaced function names do not have to start with a capital letter
|
|
|
|
function! foo#bar#log(value)
|
|
|
|
echomsg value
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call foo#bar#log('Hello')
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" #############################
|
|
|
|
" Frequently used ex-commands
|
|
|
|
" #############################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Sourcing runtime files (|'runtimepath'|)
|
|
|
|
" ######################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Source first match among runtime paths
|
|
|
|
runtime plugin/my-plugin.vim
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Defining new ex-commands (|40.2|, |:command|)
|
|
|
|
" ########################
|
|
|
|
|
2019-11-10 16:05:23 +03:00
|
|
|
" First argument here is the name of the command, rest is the command body
|
|
|
|
command! SwapAdjacentLines normal! ddp
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" The exclamation mark works the same as with `:function`. User-defined
|
|
|
|
" commands must start with a capital letter. The `:command` command can take a
|
|
|
|
" number of attributes (some of which have their own parameters with `=`), such
|
|
|
|
" as `-nargs`, all of them start with a dash to set them apart from the command
|
|
|
|
" name.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2020-02-02 19:56:16 +03:00
|
|
|
command! -nargs=1 Error echoerr <args>
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Defining auto-commands (|40.3|, |autocmd|, |autocommand-events|)
|
|
|
|
" ######################
|
|
|
|
|
2019-11-10 16:05:23 +03:00
|
|
|
" The arguments are "events", "patterns", rest is "commands"
|
|
|
|
autocmd BufWritePost $MYVIMRC source $MYVIMRC
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Events and patterns are separated by commas with no space between. See
|
|
|
|
" |autocmd-events| for standard events, |User| for custom events. Everything
|
|
|
|
" else are the ex-commands which will be executed.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Auto groups
|
|
|
|
" ===========
|
|
|
|
"
|
|
|
|
" When a file is sourced multiple times the auto-commands are defined anew,
|
|
|
|
" without deleting the old ones, causing auto-commands to pile up over time.
|
|
|
|
" Use auto-groups and the following ritual to guard against this.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
augroup auto-source | " The name of the group is arbitrary
|
|
|
|
autocmd! | " Deletes all auto-commands in the current group
|
2019-11-10 16:05:23 +03:00
|
|
|
autocmd BufWritePost $MYVIMRC source $MYVIMRC
|
2019-12-22 15:41:46 +03:00
|
|
|
augroup END | " Switch back to default auto-group
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" It is also possible to assign a group directly. This is useful if the
|
|
|
|
" definition of the group is in one script and the definition of the
|
|
|
|
" auto-command is in another script.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" In one file
|
|
|
|
augroup auto-source
|
|
|
|
autocmd!
|
|
|
|
augroup END
|
|
|
|
|
|
|
|
" In another file
|
|
|
|
autocmd auto-source BufWritePost $MYVIMRC source $MYVIMRC
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Executing (run-time macros of sorts)
|
|
|
|
" ####################################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Sometimes we need to construct an ex-command where part of the command is not
|
|
|
|
" known until runtime.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
let line = 3 | " Line number determined at runtime
|
|
|
|
execute line .. 'delete' | " Delete a line
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Executing normal-mode commands
|
|
|
|
" ##############################
|
|
|
|
"
|
|
|
|
" Use `:normal` to play back a sequence of normal mode commands from the
|
|
|
|
" command-line. Add an exclamation mark to ignore user mappings.
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:41:46 +03:00
|
|
|
normal! ggddGp | " Transplant first line to end of buffer
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Window commands can be used with :normal, or with :wincmd if :normal would
|
|
|
|
" not work
|
2019-12-22 15:41:46 +03:00
|
|
|
wincmd L | " Move current window all the way to the right
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" ###########################
|
|
|
|
" Frequently used functions
|
|
|
|
" ###########################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Feature check
|
2019-12-22 15:41:46 +03:00
|
|
|
echo has('nvim') | " Running Neovim
|
|
|
|
echo has('python3') | " Support for Python 3 plugins
|
|
|
|
echo has('unix') | " Running on a Unix system
|
|
|
|
echo has('win32') | " Running on a Windows system
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
|
|
|
|
" Test if something exists
|
2019-12-22 15:41:46 +03:00
|
|
|
echo exists('&mouse') | " Option (exists only)
|
|
|
|
echo exists('+mouse') | " Option (exists and works)
|
|
|
|
echo exists('$HOSTNAME') | " Environment variable
|
|
|
|
echo exists('*strftime') | " Built-in function
|
|
|
|
echo exists('**s:MyFunc') | " User-defined function
|
|
|
|
echo exists('bufcount') | " Variable (scope optional)
|
|
|
|
echo exists('my_dict["foo"]') | " Variable (dictionary entry)
|
|
|
|
echo exists('my_dict["foo"]') | " Variable (dictionary entry)
|
|
|
|
echo exists(':Make') | " Command
|
|
|
|
echo exists("#CursorHold") | " Auto-command defined for event
|
|
|
|
echo exists("#BufReadPre#*.gz") | " Event and pattern
|
|
|
|
echo exists("#filetypeindent") | " Auto-command group
|
2022-12-10 18:05:34 +03:00
|
|
|
echo exists("##ColorScheme") | " Auto-command supported for event
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Various dynamic values (see |expand()|)
|
2019-12-22 15:41:46 +03:00
|
|
|
echo expand('%') | " Current file name
|
|
|
|
echo expand('<cword>') | " Current word under cursor
|
|
|
|
echo expand('%:p') | " Modifier are possible
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Type tests
|
2020-02-02 19:56:16 +03:00
|
|
|
" There are unique constants defined for the following types. Older versions
|
|
|
|
" of Vim lack the type variables, see the reference " documentation for a
|
|
|
|
" workaround
|
|
|
|
echo type(my_var) == v:t_number | " Number
|
|
|
|
echo type(my_var) == v:t_string | " String
|
|
|
|
echo type(my_var) == v:t_func | " Funcref
|
|
|
|
echo type(my_var) == v:t_list | " List
|
|
|
|
echo type(my_var) == v:t_dict | " Dictionary
|
|
|
|
echo type(my_var) == v:t_float | " Float
|
|
|
|
echo type(my_var) == v:t_bool | " Explicit Boolean
|
|
|
|
" For the null object should compare it against itself
|
|
|
|
echo my_var is v:null
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Format strings
|
|
|
|
echo printf('%d in hexadecimal is %X', 123, 123)
|
|
|
|
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" #####################
|
|
|
|
" Tricks of the trade
|
|
|
|
" #####################
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Source guard
|
|
|
|
" ############
|
2019-11-10 16:05:23 +03:00
|
|
|
|
2020-02-02 19:56:16 +03:00
|
|
|
" Prevent a file from being sourced multiple times; users can set the variable
|
2019-11-10 16:05:23 +03:00
|
|
|
" in their configuration to prevent the plugin from loading at all.
|
|
|
|
if exists('g:loaded_my_plugin')
|
|
|
|
finish
|
|
|
|
endif
|
|
|
|
let g:loaded_my_plugin = v:true
|
|
|
|
|
2019-12-22 15:31:46 +03:00
|
|
|
" Default values
|
|
|
|
" ##############
|
2019-11-10 16:05:23 +03:00
|
|
|
|
|
|
|
" Get a default value: if the user defines a variable use it, otherwise use a
|
|
|
|
" hard-coded default. Uses the fact that a scope is also a dictionary.
|
2019-12-22 15:41:46 +03:00
|
|
|
let s:greeting = get(g:, 'my_plugin_greeting', 'Hello')
|
2019-11-10 16:05:23 +03:00
|
|
|
```
|