aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/doc/if_lua.txt285
-rw-r--r--runtime/lua/vim/shared.lua128
2 files changed, 286 insertions, 127 deletions
diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt
index b97341e319..7f90074ff0 100644
--- a/runtime/doc/if_lua.txt
+++ b/runtime/doc/if_lua.txt
@@ -30,7 +30,7 @@ finds and loads Lua modules. The conventions are similar to VimL plugins,
with some extra features. See |lua-require-example| for a walkthrough.
==============================================================================
-Importing modules *lua-require*
+Importing Lua modules *lua-require*
Nvim automatically adjusts `package.path` and `package.cpath` according to
effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
@@ -258,7 +258,77 @@ position are restricted when the command is executed in the |sandbox|.
==============================================================================
-vim.* *lua-vim* *lua-stdlib*
+luaeval() *lua-luaeval* *lua-eval*
+ *luaeval()*
+
+The (dual) equivalent of "vim.eval" for passing Lua values to Nvim is
+"luaeval". "luaeval" takes an expression string and an optional argument used
+for _A inside expression and returns the result of the expression. It is
+semantically equivalent in Lua to:
+>
+ local chunkheader = "local _A = select(1, ...) return "
+ function luaeval (expstr, arg)
+ local chunk = assert(loadstring(chunkheader .. expstr, "luaeval"))
+ return chunk(arg) -- return typval
+ end
+
+Lua nils, numbers, strings, tables and booleans are converted to their
+respective VimL types. An error is thrown if conversion of any other Lua types
+is attempted.
+
+The magic global "_A" contains the second argument to luaeval().
+
+Example: >
+ :echo luaeval('_A[1] + _A[2]', [40, 2])
+ 42
+ :echo luaeval('string.match(_A, "[a-z]+")', 'XYXfoo123')
+ foo
+
+Lua tables are used as both dictionaries and lists, so it is impossible to
+determine whether empty table is meant to be empty list or empty dictionary.
+Additionally lua does not have integer numbers. To distinguish between these
+cases there is the following agreement:
+
+0. Empty table is empty list.
+1. Table with N incrementally growing integral numbers, starting from 1 and
+ ending with N is considered to be a list.
+2. Table with string keys, none of which contains NUL byte, is considered to
+ be a dictionary.
+3. Table with string keys, at least one of which contains NUL byte, is also
+ considered to be a dictionary, but this time it is converted to
+ a |msgpack-special-map|.
+ *lua-special-tbl*
+4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
+ value:
+ - `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to
+ a floating-point 1.0. Note that by default integral lua numbers are
+ converted to |Number|s, non-integral are converted to |Float|s. This
+ variant allows integral |Float|s.
+ - `{[vim.type_idx]=vim.types.dictionary}` is converted to an empty
+ dictionary, `{[vim.type_idx]=vim.types.dictionary, [42]=1, a=2}` is
+ converted to a dictionary `{'a': 42}`: non-string keys are ignored.
+ Without `vim.type_idx` key tables with keys not fitting in 1., 2. or 3.
+ are errors.
+ - `{[vim.type_idx]=vim.types.list}` is converted to an empty list. As well
+ as `{[vim.type_idx]=vim.types.list, [42]=1}`: integral keys that do not
+ form a 1-step sequence from 1 to N are ignored, as well as all
+ non-integral keys.
+
+Examples: >
+
+ :echo luaeval('math.pi')
+ :function Rand(x,y) " random uniform between x and y
+ : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y})
+ : endfunction
+ :echo Rand(1,10)
+
+Note that currently second argument to `luaeval` undergoes VimL to lua
+conversion, so changing containers in lua do not affect values in VimL. Return
+value is also always converted. When converting, |msgpack-special-dict|s are
+treated specially.
+
+==============================================================================
+Lua standard modules *lua-stdlib*
The Nvim Lua "standard library" (stdlib) is the `vim` module, which exposes
various functions and sub-modules. It is always loaded, thus require("vim")
@@ -292,7 +362,7 @@ Note that underscore-prefixed functions (e.g. "_os_proc_children") are
internal/private and must not be used by plugins.
------------------------------------------------------------------------------
-vim.api.* functions
+VIM.API *lua-api*
`vim.api` exposes the full Nvim |API| as a table of Lua functions.
@@ -302,55 +372,18 @@ For example, to use the "nvim_get_current_line()" API function, call
print(tostring(vim.api.nvim_get_current_line()))
------------------------------------------------------------------------------
-vim.* builtin functions
-
-vim.deepcopy({object}) *vim.deepcopy*
- Performs a deep copy of the given object, and returns that copy.
- For a non-table object, that just means a usual copy of the object,
- while for a table all subtables are copied recursively.
-
-vim.gsplit({s}, {sep}, {plain}) *vim.gsplit*
- Split a given string by a separator. Returns an iterator of the
- split components. The separator can be a lua pattern, see
- https://www.lua.org/pil/20.2.html
- Setting {plain} to `true` turns off pattern matching, as it is passed
- to `string:find`, see
- http://lua-users.org/wiki/StringLibraryTutorial
-
- Parameters:~
- {s} String: String to split
- {sep} String: Separator pattern. If empty, split by chars.
- {plain} Boolean: If false, match {sep} verbatim
-
- Return:~
- Iterator of strings, which are the components of {s} after
- splitting
-
-vim.split({s}, {sep}, {plain}) *vim.split*
- Split a given string by a separator. Returns a table containing the
- split components. The separator can be a lua pattern, see
- https://www.lua.org/pil/20.2.html
- Setting {plain} to `true` turns off pattern matching, as it is passed
- to `string:find`, see
- http://lua-users.org/wiki/StringLibraryTutorial
-
- Parameters:~
- {s} String: String to split
- {sep} String: Separator pattern. If empty, split by chars.
- {plain} Boolean: If false, match {sep} verbatim
-
- Return:~
- Table of strings, which are the components of {s} after
- splitting
+VIM *lua-util*
+
+vim.inspect({object}, {options}) *vim.inspect*
+ Return a human-readable representation of the passed object. See
+ https://github.com/kikito/inspect.lua
+ for details and possible options.
vim.stricmp(a, b) *lua-vim.stricmp*
Function used for case-insensitive string comparison. Takes two
string arguments and returns 0, 1 or -1 if strings are equal, a is
greater then b or a is lesser then b respectively.
-vim.trim({string}) *vim.trim*
- Returns the string with all leading and trailing whitespace removed.
-
vim.type_idx *lua-vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the
values from |lua-vim.types| allows typing the empty table (it is
@@ -386,86 +419,106 @@ vim.types *lua-vim.types*
`vim.types.dictionary` will not change or that `vim.types` table will
only contain values for these three types.
-------------------------------------------------------------------------------
-vim.* runtime functions
+==============================================================================
+Lua module: vim *lua-vim*
-Those functions are only available after the runtime files have been loaded.
-In particular, they are not available when using `nvim -u NONE`.
+trim({s}) *vim.trim()*
+ Trim whitespace (Lua pattern "%%s") from both sides of a
+ string.
-vim.inspect({object}, {options}) *vim.inspect*
- Return a human-readable representation of the passed object. See
- https://github.com/kikito/inspect.lua
- for details and possible options.
+ Parameters: ~
+ {s} String to trim
-==============================================================================
-luaeval() *lua-luaeval* *lua-eval*
- *luaeval()*
+ Return: ~
+ String with whitespace removed from its beginning and end
-The (dual) equivalent of "vim.eval" for passing Lua values to Nvim is
-"luaeval". "luaeval" takes an expression string and an optional argument used
-for _A inside expression and returns the result of the expression. It is
-semantically equivalent in Lua to:
->
- local chunkheader = "local _A = select(1, ...) return "
- function luaeval (expstr, arg)
- local chunk = assert(loadstring(chunkheader .. expstr, "luaeval"))
- return chunk(arg) -- return typval
- end
+ See also: ~
+ https://www.lua.org/pil/20.2.html
-Lua nils, numbers, strings, tables and booleans are converted to their
-respective VimL types. An error is thrown if conversion of any other Lua types
-is attempted.
-The magic global "_A" contains the second argument to luaeval().
-Example: >
- :echo luaeval('_A[1] + _A[2]', [40, 2])
- 42
- :echo luaeval('string.match(_A, "[a-z]+")', 'XYXfoo123')
- foo
-Lua tables are used as both dictionaries and lists, so it is impossible to
-determine whether empty table is meant to be empty list or empty dictionary.
-Additionally lua does not have integer numbers. To distinguish between these
-cases there is the following agreement:
+deepcopy({orig}) *vim.deepcopy()*
+ Returns a deep copy of the given object. Non-table objects are
+ copied as in a typical Lua assignment, whereas table objects
+ are copied recursively.
-0. Empty table is empty list.
-1. Table with N incrementally growing integral numbers, starting from 1 and
- ending with N is considered to be a list.
-2. Table with string keys, none of which contains NUL byte, is considered to
- be a dictionary.
-3. Table with string keys, at least one of which contains NUL byte, is also
- considered to be a dictionary, but this time it is converted to
- a |msgpack-special-map|.
- *lua-special-tbl*
-4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
- value:
- - `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to
- a floating-point 1.0. Note that by default integral lua numbers are
- converted to |Number|s, non-integral are converted to |Float|s. This
- variant allows integral |Float|s.
- - `{[vim.type_idx]=vim.types.dictionary}` is converted to an empty
- dictionary, `{[vim.type_idx]=vim.types.dictionary, [42]=1, a=2}` is
- converted to a dictionary `{'a': 42}`: non-string keys are ignored.
- Without `vim.type_idx` key tables with keys not fitting in 1., 2. or 3.
- are errors.
- - `{[vim.type_idx]=vim.types.list}` is converted to an empty list. As well
- as `{[vim.type_idx]=vim.types.list, [42]=1}`: integral keys that do not
- form a 1-step sequence from 1 to N are ignored, as well as all
- non-integral keys.
+ Parameters: ~
+ {orig} Table to copy
-Examples: >
+ Return: ~
+ New table of copied keys and (nested) values.
- :echo luaeval('math.pi')
- :function Rand(x,y) " random uniform between x and y
- : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y})
- : endfunction
- :echo Rand(1,10)
+gsplit({s}, {sep}, {plain}) *vim.gsplit()*
+ Splits a string at each instance of a separator.
-Note that currently second argument to `luaeval` undergoes VimL to lua
-conversion, so changing containers in lua do not affect values in VimL. Return
-value is also always converted. When converting, |msgpack-special-dict|s are
-treated specially.
+ Parameters: ~
+ {s} String to split
+ {sep} Separator string or pattern
+ {plain} If `true` use `sep` literally (passed to
+ String.find)
-==============================================================================
- vim:tw=78:ts=8:et:ft=help:norl:
+ Return: ~
+ Iterator over the split components
+
+ See also: ~
+ |vim.split()|
+ https://www.lua.org/pil/20.2.html
+ http://lua-users.org/wiki/StringLibraryTutorial
+
+split({s}, {sep}, {plain}) *vim.split()*
+ Splits a string at each instance of a separator.
+
+ Examples: >
+ split(":aa::b:", ":") --> {'','aa','','bb',''}
+ split("axaby", "ab?") --> {'','x','y'}
+ split(x*yz*o, "*", true) --> {'x','yz','o'}
+<
+
+ Parameters: ~
+ {s} String to split
+ {sep} Separator string or pattern
+ {plain} If `true` use `sep` literally (passed to
+ String.find)
+
+ Return: ~
+ List-like table of the split components.
+
+ See also: ~
+ |vim.gsplit()|
+
+tbl_contains({t}, {value}) *vim.tbl_contains()*
+ Checks if a list-like (vector) table contains `value` .
+
+ Parameters: ~
+ {t} Table to check
+ {value} Value to compare
+
+ Return: ~
+ true if `t` contains `value`
+
+tbl_extend({behavior}, {...}) *vim.tbl_extend()*
+ Merges two or more map-like tables.
+
+ Parameters: ~
+ {behavior} Decides what to do if a key is found in more
+ than one map:
+ - "error": raise an error
+ - "keep": use value from the leftmost map
+ - "force": use value from the rightmost map
+ {...} Two or more map-like tables.
+
+ See also: ~
+ |extend()|
+
+tbl_flatten({t}) *vim.tbl_flatten()*
+ Creates a copy of a list-like table such that any nested
+ tables are "unrolled" and appended to the result.
+
+ Parameters: ~
+ {t} List-like table
+
+ Return: ~
+ Flattened copy of the given list-like table.
+
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 9dca51ce9a..07f9f52e5c 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -1,9 +1,107 @@
---- Shared functions
--- - Used by Nvim and tests
--- - Can run in vanilla Lua (do not require a running instance of Nvim)
+-- Functions shared by Nvim and its test-suite.
+--
+-- The singular purpose of this module is to share code with the Nvim
+-- test-suite. If, in the future, Nvim itself is used to run the test-suite
+-- instead of "vanilla Lua", these functions could move to src/nvim/lua/vim.lua
+
+
+--- Returns a deep copy of the given object. Non-table objects are copied as
+--- in a typical Lua assignment, whereas table objects are copied recursively.
+---
+--@param orig Table to copy
+--@returns New table of copied keys and (nested) values.
+local function deepcopy(orig)
+ error()
+end
+local function _id(v)
+ return v
+end
+local deepcopy_funcs = {
+ table = function(orig)
+ local copy = {}
+ for k, v in pairs(orig) do
+ copy[deepcopy(k)] = deepcopy(v)
+ end
+ return copy
+ end,
+ number = _id,
+ string = _id,
+ ['nil'] = _id,
+ boolean = _id,
+}
+deepcopy = function(orig)
+ return deepcopy_funcs[type(orig)](orig)
+end
+
+--- Splits a string at each instance of a separator.
+---
+--@see |vim.split()|
+--@see https://www.lua.org/pil/20.2.html
+--@see http://lua-users.org/wiki/StringLibraryTutorial
+---
+--@param s String to split
+--@param sep Separator string or pattern
+--@param plain If `true` use `sep` literally (passed to String.find)
+--@returns Iterator over the split components
+local function gsplit(s, sep, plain)
+ assert(type(s) == "string")
+ assert(type(sep) == "string")
+ assert(type(plain) == "boolean" or type(plain) == "nil")
+ local start = 1
+ local done = false
+
+ local function _pass(i, j, ...)
+ if i then
+ assert(j+1 > start, "Infinite loop detected")
+ local seg = s:sub(start, i - 1)
+ start = j + 1
+ return seg, ...
+ else
+ done = true
+ return s:sub(start)
+ end
+ end
--- Checks if a list-like (vector) table contains `value`.
+ return function()
+ if done then
+ return
+ end
+ if sep == '' then
+ if start == #s then
+ done = true
+ end
+ return _pass(start+1, start)
+ end
+ return _pass(s:find(sep, start, plain))
+ end
+end
+
+--- Splits a string at each instance of a separator.
+---
+--- Examples:
+--- <pre>
+--- split(":aa::b:", ":") --> {'','aa','','bb',''}
+--- split("axaby", "ab?") --> {'','x','y'}
+--- split(x*yz*o, "*", true) --> {'x','yz','o'}
+--- </pre>
+--
+--@see |vim.gsplit()|
+---
+--@param s String to split
+--@param sep Separator string or pattern
+--@param plain If `true` use `sep` literally (passed to String.find)
+--@returns List-like table of the split components.
+local function split(s,sep,plain)
+ local t={} for c in gsplit(s, sep, plain) do table.insert(t,c) end
+ return t
+end
+
+--- Checks if a list-like (vector) table contains `value`.
+---
+--@param t Table to check
+--@param value Value to compare
+--@returns true if `t` contains `value`
local function tbl_contains(t, value)
if type(t) ~= 'table' then
error('t must be a table')
@@ -17,13 +115,14 @@ local function tbl_contains(t, value)
end
--- Merges two or more map-like tables.
---
+---
--@see |extend()|
---
--- behavior: Decides what to do if a key is found in more than one map:
--- "error": raise an error
--- "keep": use value from the leftmost map
--- "force": use value from the rightmost map
+---
+--@param behavior Decides what to do if a key is found in more than one map:
+--- - "error": raise an error
+--- - "keep": use value from the leftmost map
+--- - "force": use value from the rightmost map
+--@param ... Two or more map-like tables.
local function tbl_extend(behavior, ...)
if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
error('invalid "behavior": '..tostring(behavior))
@@ -46,7 +145,11 @@ local function tbl_extend(behavior, ...)
return ret
end
--- Flattens a list-like table: unrolls and appends nested tables to table `t`.
+--- Creates a copy of a list-like table such that any nested tables are
+--- "unrolled" and appended to the result.
+---
+--@param t List-like table
+--@returns Flattened copy of the given list-like table.
local function tbl_flatten(t)
-- From https://github.com/premake/premake-core/blob/master/src/base/table.lua
local result = {}
@@ -66,6 +169,9 @@ local function tbl_flatten(t)
end
local module = {
+ deepcopy = deepcopy,
+ gsplit = gsplit,
+ split = split,
tbl_contains = tbl_contains,
tbl_extend = tbl_extend,
tbl_flatten = tbl_flatten,