diff options
| author | Ashkan Kiani <ashkan.k.kiani@gmail.com> | 2019-11-21 10:04:32 -0800 |
|---|---|---|
| committer | Ashkan Kiani <ashkan.k.kiani@gmail.com> | 2019-11-21 10:04:32 -0800 |
| commit | 6a5140137865025dee68e75a4e8feb2d20a430cf (patch) | |
| tree | bd9815ea488c4ee77bdfd6631ba7159f039ebe3e /runtime | |
| parent | b7170f2d722cee24a62eb74ac836d6192e5475dc (diff) | |
| parent | cc5487e32f6fc6d0034634a1f9e736968afb4450 (diff) | |
| download | rneovim-6a5140137865025dee68e75a4e8feb2d20a430cf.tar.gz rneovim-6a5140137865025dee68e75a4e8feb2d20a430cf.tar.bz2 rneovim-6a5140137865025dee68e75a4e8feb2d20a430cf.zip | |
Merge remote-tracking branch 'origin/master' into lsp-followup
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/autoload/man.vim | 75 | ||||
| -rw-r--r-- | runtime/doc/api.txt | 24 | ||||
| -rw-r--r-- | runtime/doc/eval.txt | 2 | ||||
| -rw-r--r-- | runtime/doc/help.txt | 2 | ||||
| -rw-r--r-- | runtime/doc/if_lua.txt | 939 | ||||
| -rw-r--r-- | runtime/doc/lua.txt | 994 | ||||
| -rw-r--r-- | runtime/doc/msgpack_rpc.txt | 7 | ||||
| -rw-r--r-- | runtime/doc/options.txt | 59 | ||||
| -rw-r--r-- | runtime/doc/vim_diff.txt | 22 | ||||
| -rw-r--r-- | runtime/ftplugin/man.vim | 4 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp.lua | 13 |
11 files changed, 1109 insertions, 1032 deletions
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index a9256638e1..36f42c0003 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -64,33 +64,20 @@ function! man#open_page(count, count1, mods, ...) abort return endtry - call s:push_tag() - let bufname = 'man://'.name.(empty(sect)?'':'('.sect.')') - + let [l:buf, l:save_tfu] = [bufnr(), &tagfunc] try - set eventignore+=BufReadCmd + set tagfunc=man#goto_tag + let l:target = l:name . '(' . l:sect . ')' if a:mods !~# 'tab' && s:find_man() - execute 'silent keepalt edit' fnameescape(bufname) + execute 'silent keepalt tag' l:target else - execute 'silent keepalt' a:mods 'split' fnameescape(bufname) + execute 'silent keepalt' a:mods 'stag' l:target endif finally - set eventignore-=BufReadCmd - endtry - - try - let page = s:get_page(path) - catch - if a:mods =~# 'tab' || !s:find_man() - " a new window was opened - close - endif - call s:error(v:exception) - return + call setbufvar(l:buf, '&tagfunc', l:save_tfu) endtry let b:man_sect = sect - call s:put_page(page) endfunction function! man#read_page(ref) abort @@ -163,6 +150,7 @@ endfunction function! s:put_page(page) abort setlocal modifiable setlocal noreadonly + setlocal noswapfile silent keepjumps %delete _ silent put =a:page while getline(1) =~# '^\s*$' @@ -254,24 +242,6 @@ function! s:verify_exists(sect, name) abort return s:extract_sect_and_name_path(path) + [path] endfunction -let s:tag_stack = [] - -function! s:push_tag() abort - let s:tag_stack += [{ - \ 'buf': bufnr('%'), - \ 'lnum': line('.'), - \ 'col': col('.'), - \ }] -endfunction - -function! man#pop_tag() abort - if !empty(s:tag_stack) - let tag = remove(s:tag_stack, -1) - execute 'silent' tag['buf'].'buffer' - call cursor(tag['lnum'], tag['col']) - endif -endfunction - " extracts the name and sect out of 'path/name.sect' function! s:extract_sect_and_name_path(path) abort let tail = fnamemodify(a:path, ':t') @@ -356,14 +326,18 @@ function! man#complete(arg_lead, cmd_line, cursor_pos) abort return s:complete(sect, sect, name) endfunction -function! s:complete(sect, psect, name) abort +function! s:get_paths(sect, name) abort try let mandirs = join(split(s:system(['man', s:find_arg]), ':\|\n'), ',') catch call s:error(v:exception) return endtry - let pages = globpath(mandirs,'man?/'.a:name.'*.'.a:sect.'*', 0, 1) + return globpath(mandirs,'man?/'.a:name.'*.'.a:sect.'*', 0, 1) +endfunction + +function! s:complete(sect, psect, name) abort + let pages = s:get_paths(a:sect, a:name) " We remove duplicates in case the same manpage in different languages was found. return uniq(sort(map(pages, 's:format_candidate(v:val, a:psect)'), 'i')) endfunction @@ -402,4 +376,27 @@ function! man#init_pager() abort endif endfunction +function! man#goto_tag(pattern, flags, info) abort + let [l:sect, l:name] = man#extract_sect_and_name_ref(a:pattern) + + let l:paths = s:get_paths(l:sect, l:name) + let l:structured = [] + + for l:path in l:paths + let l:n = s:extract_sect_and_name_path(l:path)[1] + let l:structured += [{ 'name': l:n, 'path': l:path }] + endfor + + " sort by relevance - exact matches first, then the previous order + call sort(l:structured, { a, b -> a.name ==? l:name ? -1 : b.name ==? l:name ? 1 : 0 }) + + return map(l:structured, { + \ _, entry -> { + \ 'name': entry.name, + \ 'filename': 'man://' . entry.path, + \ 'cmd': '1' + \ } + \ }) +endfunction + call s:init() diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 4ed0a6aba0..57a72e6173 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -462,7 +462,7 @@ We can get a mark by its id: > We can get all marks in a buffer for our namespace (or by a range): > - echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, -1) + echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, {}) => [[1, 0, 2]] Deleting all text surrounding an extmark does not remove the extmark. To @@ -1516,6 +1516,13 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()* Activates buffer-update events on a channel, or as Lua callbacks. + Example (Lua): capture buffer updates in a global `events` variable (use "print(vim.inspect(events))" to see its + contents): > + events = {} + vim.api.nvim_buf_attach(0, false, { + on_lines=function(...) table.insert(events, {...}) end}) +< + Parameters: ~ {buffer} Buffer handle, or 0 for current buffer {send_buffer} True if the initial notification should @@ -1804,21 +1811,22 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) range ends can be specified as (row, col) tuples, as well as extmark ids in the same namespace. In addition, 0 and -1 works as shorthands for (0,0) and (-1,-1) respectively, so that all - marks in the buffer can be quieried as: + marks in the buffer can be queried as: - all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, -1) + all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) If end is a lower position than start, then the range will be - traversed backwards. This is mostly used with limited amount, - to be able to get the first marks prior to a given position. + traversed backwards. This is mostly useful with limited + amount, to be able to get the first marks prior to a given + position. Parameters: ~ {buffer} The buffer handle {ns_id} An id returned previously from nvim_create_namespace - {lower} One of: extmark id, (row, col) or 0, -1 for + {start} One of: extmark id, (row, col) or 0, -1 for buffer ends - {upper} One of: extmark id, (row, col) or 0, -1 for + {end} One of: extmark id, (row, col) or 0, -1 for buffer ends {opts} additional options. Supports the keys: • amount: Maximum number of marks to return @@ -1845,7 +1853,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {id}, {line}, {col}, {opts}) {ns_id} a identifier returned previously with nvim_create_namespace {id} The extmark's id or 0 to create a new mark. - {row} The row to set the extmark to. + {line} The row to set the extmark to. {col} The column to set the extmark to. {opts} Optional parameters. Currently not used. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 79bf81dc0e..84a893a205 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1738,7 +1738,7 @@ v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr' and |sandbox|. *v:lua* *lua-variable* -v:lua Prefix for calling lua functions from expressions. +v:lua Prefix for calling Lua functions from expressions. See |v:lua-call| for more information. *v:mouse_win* *mouse_win-variable* diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 284cd26583..6090fa96bb 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -129,6 +129,7 @@ Advanced editing ~ |autocmd.txt| automatically executing commands on an event |eval.txt| expression evaluation, conditional commands |fold.txt| hide (fold) ranges of lines +|lua.txt| Lua API Special issues ~ |print.txt| printing @@ -157,7 +158,6 @@ GUI ~ Interfaces ~ |if_cscop.txt| using Cscope with Vim -|if_lua.txt| Lua interface |if_pyth.txt| Python interface |if_ruby.txt| Ruby interface |sign.txt| debugging signs diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt index 911197acd4..34bcf0f039 100644 --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -1,941 +1,8 @@ -*if_lua.txt* Nvim - NVIM REFERENCE MANUAL + NVIM REFERENCE MANUAL - -Lua engine *lua* *Lua* - - Type |gO| to see the table of contents. - -============================================================================== -Introduction *lua-intro* - -The Lua 5.1 language is builtin and always available. Try this command to get -an idea of what lurks beneath: > - - :lua print(vim.inspect(package.loaded)) - -Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the -"editor stdlib" (|functions| and Ex commands) and the |API|, all of which can -be used from Lua code. - -Module conflicts are resolved by "last wins". For example if both of these -are on 'runtimepath': - runtime/lua/foo.lua - ~/.config/nvim/lua/foo.lua -then `require('foo')` loads "~/.config/nvim/lua/foo.lua", and -"runtime/lua/foo.lua" is not used. See |lua-require| to understand how Nvim -finds and loads Lua modules. The conventions are similar to VimL plugins, -with some extra features. See |lua-require-example| for a walkthrough. - -============================================================================== -Importing Lua 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 track '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. - -- Although adjustments happen automatically, Nvim does not track current - values of `package.path` or `package.cpath`. If you happen to delete some - paths from there you can set 'runtimepath' to trigger an update: > - let &runtimepath = &runtimepath - -- Skipping paths from 'runtimepath' which contain semicolons applies both to - `package.path` and `package.cpath`. Given that there are some badly written - plugins using shell which will not work with paths containing semicolons it - is better to not have them in 'runtimepath' at all. - ------------------------------------------------------------------------------- -LUA PLUGIN EXAMPLE *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}. Useful for including Lua - code in Vim scripts. - -The {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. - -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. However, -procedures that alter buffer content, open new buffers, and change cursor -position are restricted when the command is executed in the |sandbox|. - - -============================================================================== -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: second argument to `luaeval` undergoes VimL to Lua conversion -("marshalled"), so changes to Lua containers do not affect values in VimL. -Return value is also always converted. When converting, -|msgpack-special-dict|s are treated specially. - -============================================================================== -v:lua function calls *v:lua-call* - -The special prefix `v:lua` can be used in vimL expressions to call lua -functions which are global or nested inside global tables. The expression -`v:lua.func(arg1, arg2)` is equivalent to executing the lua code -`return func(...)` where the args have been converted to lua values. In addition -`v:lua.somemod.func(args)` will work like `return somemod.func(...)` . - -`v:lua` can also be used in function options like 'omnifunc'. As an -example, consider the following lua implementation of an omnifunc: > - - function mymod.omnifunc(findstart, base) - if findstart == 1 then - return 0 - else - return {'stuff', 'steam', 'strange things'} - end - end - vim.api.nvim_buf_set_option(0, 'omnifunc', 'v:lua.mymod.omnifunc') - -A limitation is that the plugin module ("mymod" in this case) must -be made available as a global. - -Note: `v:lua` without a call is not allowed in a vimL expression. Funcrefs -to lua functions cannot be created. The following are errors: > - - let g:Myvar = v:lua.myfunc - call SomeFunc(v:lua.mycallback) - let g:foo = v:lua - let g:foo = v:['lua'] - -============================================================================== -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") -is unnecessary. - -You can peek at the module properties: > - - :lua print(vim.inspect(vim)) - -Result is something like this: > - - { - _os_proc_children = <function 1>, - _os_proc_info = <function 2>, - ... - api = { - nvim__id = <function 5>, - nvim__id_array = <function 6>, - ... - }, - deepcopy = <function 106>, - gsplit = <function 107>, - ... - } - -To find documentation on e.g. the "deepcopy" function: > - - :help vim.deepcopy() - -Note that underscore-prefixed functions (e.g. "_os_proc_children") are -internal/private and must not be used by plugins. - ------------------------------------------------------------------------------- -VIM.LOOP *lua-loop* *vim.loop* - -`vim.loop` exposes all features of the Nvim event-loop. This is a low-level -API that provides functionality for networking, filesystem, and process -management. Try this command to see available functions: > - - :lua print(vim.inspect(vim.loop)) - -Reference: http://docs.libuv.org -Examples: https://github.com/luvit/luv/tree/master/examples - - *E5560* *lua-loop-callbacks* -It is an error to directly invoke `vim.api` functions (except |api-fast|) in -`vim.loop` callbacks. For example, this is an error: > - - local timer = vim.loop.new_timer() - timer:start(1000, 0, function() - vim.api.nvim_command('echomsg "test"') - end) - -To avoid the error use |vim.schedule_wrap()| to defer the callback: > - - local timer = vim.loop.new_timer() - timer:start(1000, 0, vim.schedule_wrap(function() - vim.api.nvim_command('echomsg "test"') - end)) - -Example: repeating timer - 1. Save this code to a file. - 2. Execute it with ":luafile %". > - - -- Create a timer handle (implementation detail: uv_timer_t). - local timer = vim.loop.new_timer() - local i = 0 - -- Waits 1000ms, then repeats every 750ms until timer:close(). - timer:start(1000, 750, function() - print('timer invoked! i='..tostring(i)) - if i > 4 then - timer:close() -- Always close handles to avoid leaks. - end - i = i + 1 - end) - print('sleeping'); - - -Example: File-change detection *file-change-detect* - 1. Save this code to a file. - 2. Execute it with ":luafile %". - 3. Use ":Watch %" to watch any file. - 4. Try editing the file from another text editor. - 5. Observe that the file reloads in Nvim (because on_change() calls - |:checktime|). > - - local w = vim.loop.new_fs_event() - local function on_change(err, fname, status) - -- Do work... - vim.api.nvim_command('checktime') - -- Debounce: stop/start. - w:stop() - watch_file(fname) - end - function watch_file(fname) - local fullpath = vim.api.nvim_call_function( - 'fnamemodify', {fname, ':p'}) - w:start(fullpath, {}, vim.schedule_wrap(function(...) - on_change(...) end)) - end - vim.api.nvim_command( - "command! -nargs=1 Watch call luaeval('watch_file(_A)', expand('<args>'))") - - -Example: TCP echo-server *tcp-server* - 1. Save this code to a file. - 2. Execute it with ":luafile %". - 3. Note the port number. - 4. Connect from any TCP client (e.g. "nc 0.0.0.0 36795"): > - - local function create_server(host, port, on_connect) - local server = vim.loop.new_tcp() - server:bind(host, port) - server:listen(128, function(err) - assert(not err, err) -- Check for errors. - local sock = vim.loop.new_tcp() - server:accept(sock) -- Accept client connection. - on_connect(sock) -- Start reading messages. - end) - return server - end - local server = create_server('0.0.0.0', 0, function(sock) - sock:read_start(function(err, chunk) - assert(not err, err) -- Check for errors. - if chunk then - sock:write(chunk) -- Echo received messages to the channel. - else -- EOF (stream closed). - sock:close() -- Always close handles to avoid leaks. - end - end) - end) - print('TCP echo-server listening on port: '..server:getsockname().port) - ------------------------------------------------------------------------------- -VIM.TREESITTER *lua-treesitter* - -Nvim integrates the tree-sitter library for incremental parsing of buffers. - -Currently Nvim does not provide the tree-sitter parsers, instead these must -be built separately, for instance using the tree-sitter utility. -The parser is loaded into nvim using > - - vim.treesitter.add_language("/path/to/c_parser.so", "c") - -<Create a parser for a buffer and a given language (if another plugin uses the -same buffer/language combination, it will be safely reused). Use > - - parser = vim.treesitter.get_parser(bufnr, lang) - -<`bufnr=0` can be used for current buffer. `lang` will default to 'filetype' (this -doesn't work yet for some filetypes like "cpp") Currently, the parser will be -retained for the lifetime of a buffer but this is subject to change. A plugin -should keep a reference to the parser object as long as it wants incremental -updates. - -Whenever you need to access the current syntax tree, parse the buffer: > - - tstree = parser:parse() - -<This will return an immutable tree that represents the current state of the -buffer. When the plugin wants to access the state after a (possible) edit -it should call `parse()` again. If the buffer wasn't edited, the same tree will -be returned again without extra work. If the buffer was parsed before, -incremental parsing will be done of the changed parts. - -NB: to use the parser directly inside a |nvim_buf_attach| Lua callback, you must -call `get_parser()` before you register your callback. But preferably parsing -shouldn't be done directly in the change callback anyway as they will be very -frequent. Rather a plugin that does any kind of analysis on a tree should use -a timer to throttle too frequent updates. - -Tree methods *lua-treesitter-tree* - -tstree:root() *tstree:root()* - Return the root node of this tree. - - -Node methods *lua-treesitter-node* - -tsnode:parent() *tsnode:parent()* - Get the node's immediate parent. - -tsnode:child_count() *tsnode:child_count()* - Get the node's number of children. - -tsnode:child(N) *tsnode:child()* - Get the node's child at the given index, where zero represents the - first child. - -tsnode:named_child_count() *tsnode:named_child_count()* - Get the node's number of named children. - -tsnode:named_child(N) *tsnode:named_child()* - Get the node's named child at the given index, where zero represents - the first named child. - -tsnode:start() *tsnode:start()* - Get the node's start position. Return three values: the row, column - and total byte count (all zero-based). - -tsnode:end_() *tsnode:end_()* - Get the node's end position. Return three values: the row, column - and total byte count (all zero-based). - -tsnode:range() *tsnode:range()* - Get the range of the node. Return four values: the row, column - of the start position, then the row, column of the end position. - -tsnode:type() *tsnode:type()* - Get the node's type as a string. - -tsnode:symbol() *tsnode:symbol()* - Get the node's type as a numerical id. - -tsnode:named() *tsnode:named()* - Check if the node is named. Named nodes correspond to named rules in - the grammar, whereas anonymous nodes correspond to string literals - in the grammar. - -tsnode:missing() *tsnode:missing()* - Check if the node is missing. Missing nodes are inserted by the - parser in order to recover from certain kinds of syntax errors. - -tsnode:has_error() *tsnode:has_error()* - Check if the node is a syntax error or contains any syntax errors. - -tsnode:sexpr() *tsnode:sexpr()* - Get an S-expression representing the node as a string. - -tsnode:descendant_for_range(start_row, start_col, end_row, end_col) - *tsnode:descendant_for_range()* - Get the smallest node within this node that spans the given range of - (row, column) positions - -tsnode:named_descendant_for_range(start_row, start_col, end_row, end_col) - *tsnode:named_descendant_for_range()* - Get the smallest named node within this node that spans the given - range of (row, column) positions - ------------------------------------------------------------------------------- -VIM *lua-builtin* - -vim.api.{func}({...}) *vim.api* - Invokes Nvim |API| function {func} with arguments {...}. - Example: call the "nvim_get_current_line()" API function: > - print(tostring(vim.api.nvim_get_current_line())) - -vim.call({func}, {...}) *vim.call()* - Invokes |vim-function| or |user-function| {func} with arguments {...}. - See also |vim.fn|. Equivalent to: > - vim.fn[func]({...}) - -vim.in_fast_event() *vim.in_fast_event()* - Returns true if the code is executing as part of a "fast" event - handler, where most of the API is disabled. These are low-level events - (e.g. |lua-loop-callbacks|) which can be invoked whenever Nvim polls - for input. When this is `false` most API functions are callable (but - may be subject to other restrictions such as |textlock|). - -vim.NIL *vim.NIL* - Special value used to represent NIL in msgpack-rpc and |v:null| in - vimL interaction, and similar cases. Lua `nil` cannot be used as - part of a lua table representing a Dictionary or Array, as it - is equivalent to a missing value: `{"foo", nil}` is the same as - `{"foo"}` - -vim.rpcnotify({channel}, {method}[, {args}...]) *vim.rpcnotify()* - Sends {event} to {channel} via |RPC| and returns immediately. - If {channel} is 0, the event is broadcast to all channels. - - This function also works in a fast callback |lua-loop-callbacks|. - -vim.rpcrequest({channel}, {method}[, {args}...]) *vim.rpcrequest()* - Sends a request to {channel} to invoke {method} via - |RPC| and blocks until a response is received. - - Note: NIL values as part of the return value is represented as - |vim.NIL| special value - -vim.stricmp({a}, {b}) *vim.stricmp()* - Compares strings case-insensitively. Returns 0, 1 or -1 if strings - are equal, {a} is greater than {b} or {a} is lesser than {b}, - respectively. - -vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()* - Convert byte index to UTF-32 and UTF-16 indicies. If {index} is not - supplied, the length of the string is used. All indicies are zero-based. - Returns two values: the UTF |