diff options
author | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 |
commit | c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57 (patch) | |
tree | b7e59c416d1435725c65f8952b6e55c70544d97e /runtime/doc/if_lua.txt | |
parent | 62108c3b0be46936c83f6d4c98b44ceb5e6f77fd (diff) | |
parent | 27a577586eace687c47e7398845178208cae524a (diff) | |
download | rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.gz rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.bz2 rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.zip |
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'runtime/doc/if_lua.txt')
-rw-r--r-- | runtime/doc/if_lua.txt | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt new file mode 100644 index 0000000000..968d882a22 --- /dev/null +++ b/runtime/doc/if_lua.txt @@ -0,0 +1,361 @@ +*if_lua.txt* Nvim + + + NVIM REFERENCE MANUAL + + +Lua Interface to Nvim *lua* *Lua* + + Type |gO| to see the table of contents. + +============================================================================== +Importing modules *lua-require* + +Nvim automatically adjusts `package.path` and `package.cpath` according to +effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is +changed. `package.path` is adjusted by simply appending `/lua/?.lua` and +`/lua/?/init.lua` to each directory from 'runtimepath' (`/` is actually the +first character of `package.config`). + +Similarly to `package.path`, modified directories from 'runtimepath' are also +added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and +`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of +the existing `package.cpath` are used. Example: + +1. Given that + - 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`; + - initial (defined at compile-time or derived from + `$LUA_CPATH`/`$LUA_INIT`) `package.cpath` contains + `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`. +2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in + order: parts of the path starting from the first path component containing + question mark and preceding path separator. +3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same + as the suffix of the first path from `package.path` (i.e. `./?.so`). Which + leaves `/?.so` and `/a?d/j/g.elf`, in this order. +4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The + second one contains semicolon which is a paths separator so it is out, + leaving only `/foo/bar` and `/abc`, in order. +5. The cartesian product of paths from 4. and suffixes from 3. is taken, + giving four variants. In each variant `/lua` path segment is inserted + between path and suffix, leaving + + - `/foo/bar/lua/?.so` + - `/foo/bar/lua/a?d/j/g.elf` + - `/abc/lua/?.so` + - `/abc/lua/a?d/j/g.elf` + +6. New paths are prepended to the original `package.cpath`. + +The result will look like this: + + `/foo/bar,/xxx;yyy/baz,/abc` ('runtimepath') + × `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so` (`package.cpath`) + + = `/foo/bar/lua/?.so;/foo/bar/lua/a?d/j/g.elf;/abc/lua/?.so;/abc/lua/a?d/j/g.elf;./?.so;/def/ghi/a?d/j/g.elf;/def/?.so` + +Note: to keep up with 'runtimepath' updates paths added at previous update are +remembered and removed at the next update, while all paths derived from the +new 'runtimepath' are prepended as described above. This allows removing +paths when path is removed from 'runtimepath', adding paths when they are +added and reordering `package.path`/`package.cpath` content if 'runtimepath' +was reordered. + +Note 2: even though adjustments happens automatically Nvim does not track +current values of `package.path` or `package.cpath`. If you happened to +delete some paths from there you need to reset 'runtimepath' to make them +readded. Just running `let &runtimepath = &runtimepath` should work. + +Note 3: skipping paths from 'runtimepath' which contain semicolons applies +both to `package.path` and `package.cpath`. Given that there is a number of +badly written plugins using shell which will not work with paths containing +semicolons it is better to not have them in 'runtimepath' at all. + +------------------------------------------------------------------------------ +Example of a plugin that uses lua modules *lua-require-example* + +The following example plugin adds a command `:MakeCharBlob` which transforms +current buffer into a long `unsigned char` array. Lua contains transformation +function in a module `lua/charblob.lua` which is imported in +`autoload/charblob.vim` (`require("charblob")`). Example plugin is supposed +to be put into any directory from 'runtimepath', e.g. `~/.config/nvim` (in +this case `lua/charblob.lua` means `~/.config/nvim/lua/charblob.lua`). + +autoload/charblob.vim: > + + function charblob#encode_buffer() + call setline(1, luaeval( + \ 'require("charblob").encode(unpack(_A))', + \ [getline(1, '$'), &textwidth, ' '])) + endfunction + +plugin/charblob.vim: > + + if exists('g:charblob_loaded') + finish + endif + let g:charblob_loaded = 1 + + command MakeCharBlob :call charblob#encode_buffer() + +lua/charblob.lua: > + + local function charblob_bytes_iter(lines) + local init_s = { + next_line_idx = 1, + next_byte_idx = 1, + lines = lines, + } + local function next(s, _) + if lines[s.next_line_idx] == nil then + return nil + end + if s.next_byte_idx > #(lines[s.next_line_idx]) then + s.next_line_idx = s.next_line_idx + 1 + s.next_byte_idx = 1 + return ('\n'):byte() + end + local ret = lines[s.next_line_idx]:byte(s.next_byte_idx) + if ret == ('\n'):byte() then + ret = 0 -- See :h NL-used-for-NUL. + end + s.next_byte_idx = s.next_byte_idx + 1 + return ret + end + return next, init_s, nil + end + + local function charblob_encode(lines, textwidth, indent) + local ret = { + 'const unsigned char blob[] = {', + indent, + } + for byte in charblob_bytes_iter(lines) do + -- .- space + number (width 3) + comma + if #(ret[#ret]) + 5 > textwidth then + ret[#ret + 1] = indent + else + ret[#ret] = ret[#ret] .. ' ' + end + ret[#ret] = ret[#ret] .. (('%3u,'):format(byte)) + end + ret[#ret + 1] = '};' + return ret + end + + return { + bytes_iter = charblob_bytes_iter, + encode = charblob_encode, + } + +============================================================================== +Commands *lua-commands* + + *:lua* +:[range]lua {chunk} + Execute Lua chunk {chunk}. + +Examples: +> + :lua vim.api.nvim_command('echo "Hello, Nvim!"') +< +To see the Lua version: > + :lua print(_VERSION) + +To see the LuaJIT version: > + :lua print(jit.version) +< + +:[range]lua << {endmarker} +{script} +{endmarker} + Execute Lua script {script}. + +{endmarker} must NOT be preceded by any white space. If {endmarker} is +omitted from after the "<<", a dot '.' must be used after {script}, like +for the |:append| and |:insert| commands. +This form of the |:lua| command is mainly useful for including Lua code +in Vim scripts. + +Example: +> + function! CurrentLineInfo() + lua << EOF + local linenr = vim.api.nvim_win_get_cursor(0)[1] + local curline = vim.api.nvim_buf_get_lines( + 0, linenr, linenr + 1, false)[1] + print(string.format("Current line [%d] has %d bytes", + linenr, #curline)) + EOF + endfunction + +Note that the `local` variables will disappear when block finishes. This is +not the case for globals. + + *:luado* +:[range]luado {body} Execute Lua function "function (line, linenr) {body} + end" for each line in the [range], with the function + argument being set to the text of each line in turn, + without a trailing <EOL>, and the current line number. + If the value returned by the function is a string it + becomes the text of the line in the current turn. The + default for [range] is the whole file: "1,$". + +Examples: +> + :luado return string.format("%s\t%d", line:reverse(), #line) + + :lua require"lpeg" + :lua -- balanced parenthesis grammar: + :lua bp = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" } + :luado if bp:match(line) then return "-->\t" .. line end +< + + *:luafile* +:[range]luafile {file} + Execute Lua script in {file}. + The whole argument is used as a single file name. + +Examples: +> + :luafile script.lua + :luafile % +< + +All these commands execute a Lua chunk from either the command line (:lua and +:luado) or a file (:luafile) with the given line [range]. Similarly to the Lua +interpreter, each chunk has its own scope and so only global variables are +shared between command calls. All Lua default libraries are available. In +addition, Lua "print" function has its output redirected to the Nvim message +area, with arguments separated by a white space instead of a tab. + +Lua uses the "vim" module (see |lua-vim|) to issue commands to Nvim +and manage buffers (|lua-buffer|) and windows (|lua-window|). However, +procedures that alter buffer content, open new buffers, and change cursor +position are restricted when the command is executed in the |sandbox|. + + +============================================================================== +The vim module *lua-vim* + +Lua interfaces Nvim through the "vim" module. Currently it has the `api` +submodule and some Nvim-specific utilities. + +------------------------------------------------------------------------------ +vim.api.* functions + +`vim.api` exposes the Nvim |API| as a table of Lua functions. All functions +are available. + +For example, to use the "nvim_get_current_line()" API function, call +"vim.api.nvim_get_current_line()": > + + print(tostring(vim.api.nvim_get_current_line())) + +------------------------------------------------------------------------------ +vim.* utility functions + +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.type_idx *lua-vim.type_idx* + Type index for use in |lua-special-tables|. Specifying one of the + values from |lua-vim.types| allows typing the empty table (it is + unclear whether empty lua table represents empty list or empty array) + and forcing integral numbers to be |Float|. See |lua-special-tbl| for + more details. + +vim.val_idx *lua-vim.val_idx* + Value index for tables representing |Float|s. A table representing + floating-point value 1.0 looks like this: > + { + [vim.type_idx] = vim.types.float, + [vim.val_idx] = 1.0, + } +< See also |lua-vim.type_idx| and |lua-special-tbl|. + +vim.types *lua-vim.types* + Table with possible values for |lua-vim.type_idx|. Contains two sets + of key-value pairs: first maps possible values for |lua-vim.type_idx| + to human-readable strings, second maps human-readable type names to + values for |lua-vim.type_idx|. Currently contains pairs for `float`, + `array` and `dictionary` types. + + Note: one must expect that values corresponding to `vim.types.float`, + `vim.types.array` and `vim.types.dictionary` fall under only two + following assumptions: + 1. Value may serve both as a key and as a value in a table. Given the + properties of lua tables this basically means “value is not `nil`”. + 2. For each value in `vim.types` table `vim.types[vim.types[value]]` + is the same as `value`. + No other restrictions are put on types, and it is not guaranteed that + values corresponding to `vim.types.float`, `vim.types.array` and + `vim.types.dictionary` will not change or that `vim.types` table will + only contain values for these three types. + +============================================================================== +The luaeval function *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 + +Note that "_A" receives the argument to "luaeval". Lua nils, numbers, strings, +tables and booleans are converted to their respective VimL types. An error is +thrown if conversion of any of the remaining Lua types is attempted. + +Note 2: lua tables are used as both dictionaries and lists, thus making it +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. + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: |