Files
neovim/runtime/doc/lua.txt
Justin M. Keyes a99c469e54 NVIM v0.11.0
For notable changes, see runtime/doc/news.txt (or `:help news` in Nvim).

Following is a list of fixes/features commits.

BREAKING
--------------------------------------------------------------------------------
- 0f4f7d32ce remove `nvim` and `provider` module for checkhealth
- 7dbbaaec3f rename 'jumpoptions' flag "unload" to "clean" (#30418)
- 35c5e23107 store artifact shasums in a single shasum.txt file
- 188ec19894 turn off translations by default
- 328ea02eb7 use utf8proc full casefolding
- 737f58e232 api: rename Dictionary => Dict
- a389dc2f95 clipboard: use OSC 52 as fallback clipboard provider (#31730)
- ad70c9892d column: rework 'statuscolumn' %r/l items
- eb60cd74fb deps: bump tree-sitter to HEAD, wasmtime to v29.0.1 (#32200)
- a119aae4d3 diagnostic: filter diagnostics by severity before passing to handlers (#30070)
- 51ccd12b3d diagnostic: make virtual text handler opt-in (#32079)
- a9e725b26e diagnostics: sort underline severity_sort (#30898)
- e8b5dd1e89 lsp: `symbol_to_item` requires `offset_encoding`
- 8260e4860b lsp: multiple client support for vim.lsp.buf.hover()
- debabaf884 lsp: pass buffer number to root_dir function
- 9b357e30fd lsp: remove client-server handlers from vim.lsp.handlers
- 3e3775961f lsp: rename lsp.completion.trigger() to get() (#32911)
- 0083e03d6f lsp: support multiple clients in goto methods (#30877)
- dff684fdb3 lsp: support multiple clients in lsp.buf.references
- 970a27927e lua: do not use typed table for empty dict
- de48fbbd5f messages: vim.ui_attach message callbacks are unsafe
- a27419f3fc options: disallow setting hidden options #28400
- b922b7d6d7 options: use OptVal for option defaults #26691
- 4d9a1b9852 provider/python: add python 3.13, drop 3.7 and 3.8 (EOL) #33022
- 318676ad13 release: remove backwards compatible releases
- ad191be65e signs: place higher-priority signs from the left #27781
- 0dd933265f terminal: cursor shape and blink (#31562)
- 35e5307af2 terminal: include cursor position in TermRequest event data (#31609)
- 3cf602486c terminal: make 'belloff' and 'visualbell' apply to terminal bell (#30859)
- 041d98fe8d treesitter: add default fallback to `ft_to_lang` lookups
- 6913c5e1d9 treesitter: default to correct behavior for quantified captures (#30193)
- bd4ca22d03 treesitter: don't parse tree in get_parser() or start()
- a0b52e7cb3 treesitter: enforce buffer is loaded when creating parser
- 99e0facf3a treesitter: use return values in `language.add()`
- bda63d5b97 typval: remove distinction of binary and nonbinary strings
- 48e2a73610 ui: emit prompt "messages" as cmdline events #31525
- ca5fca2912 windows: drop cat and tee executables from windows
- be89d520d7 windows: only support UCRT, even for mingw

FEATURES
--------------------------------------------------------------------------------
- efa45832ea add "jump" options to vim.diagnostic.config() (#29067)
- 0631492f9c add vim.fs.relpath
- f864b68c5b allow gx to function for markdown links
- f3632e14e3 get/set namespace properties #28728
- a664246171 remove deprecated features
- ead5683ff9 api: add err field to nvim_echo() opts
- aec4938a21 api: broadcast events to ALL channels #28487
- 34d808b73c api: combined highlights in nvim_eval_statusline()
- 19b25f3fea api: deprecate nvim_buf_add_highlight()
- 5c92b40b4b api: deprecate nvim_out/err_write(ln)
- d84a95da7e api: nvim_get_autocmds filter by id#31549
- 25d8c3a5ad api: nvim_open_win() relative to tabline and laststatus #32006
- e00d67ef31 checkhealth: group parsers by name and path in output
- 563051a53e clipboard: support g:clipboard="osc52" #33021
- 60ea046741 clipboard: try cygutils, clip on Windows #30215
- 2c629ad13f column: apply appropriate numhl highlight to virt_lines (#32400)
- 65c7033cbe comment: allow commentstring to be determined from node metadata
- 268a3de0a7 complete: CompleteDone reason "cancel", "discard" #32600
- a616272f56 complete: specify reason for CompleteDone
- f1748b78e3 default: bind `vim.lsp.buf.signature_help` in select mode (#31223)
- ac207c3ac2 defaults: "Show Diagnostics" in mouse popupmenu #32122
- 2c6b635872 defaults: add LSP default mappings (again) (#28650)
- bb7604edda defaults: add default unimpaired style mappings (#28525)
- 4662ad5643 defaults: completeopt=popup #32909
- e8e3b443f8 defaults: disable 'foldcolumn' in terminal buffers (#31480)
- cc6992f1ca defaults: dot-repeat [<Space> #31186
- 6db830e40e defaults: enable diffopt "linematch" #32346
- b31132f1c1 defaults: jump between :terminal shell prompts with ]]/[[ #32736
- 0b7cc014fc defaults: map gO to LSP document_symbol #30781
- 26e765f905 defaults: map gri to vim.lsp.buf.implementation() (#30764)
- 76aa3e52be defaults: popupmenu "Open in browser", "Go to definition" #30261
- 09d76afe84 defaults: pretty :help headings #30544
- 079e5f4f9b defaults: unimpaired empty line below/above cursor #30984
- 1c6d920052 defaults: use vim.diagnostic.jump() for default mappings (#29066)
- c9c17fda80 deprecations: vim._defer_deprecated_module()
- 38a52caec0 diagnostic: add `current_line` option for `virtual_text` handler
- 8ba73f0e4c diagnostic: add vim.diagnostic.jump() (#26745)
- 445ecca398 diagnostic: format() can filter diagnostics by returning nil #32302
- 99e7323aa3 diagnostic: inherit parent 'path' option in open_float (#31273)
- 21961967ff diagnostic: update quickfix list by title #31486
- 7579af3c51 diagnostic: vim.diagnostic.setqflist improvements #30868
- 1759b7844a diagnostic: virtual_lines #31959
- fd65422b99 diff: do not try external when out of memory
- 0c296ab224 docs: "yxx" runs Lua/Vimscript code examples #31904
- 6628741ada docs: improve `@see` meta docstrings #30693
- 23290e7676 editor: handle new multibyte sequences in normal mode replacement
- cb6c0fda71 editorconfig: add support for spelling_language (#28638)
- 4817547ec4 ex_cmds: :sleep! hides the cursor while sleeping (#31493)
- 4f9260d06a ext_messages: add hl_id to ext_messages chunks
- 4cced601c8 extmark: stack multiple highlight groups in `hl_group`
- 931ee5591f extmarks: virtual text can be right-aligned, truncated #31921
- 62d9fab9af float: add winborder option (#31074)
- 9b8907d905 float: allow enabling mouse for non-focusable window (#30844)
- 511b991e66 fs.lua: add vim.fs.rm()
- 054a287dbe ftplugin: change 'commentstring' to `// %s` for C/C++ (#29085)
- f398e3a61a ftplugin: set Lua 'omnifunc' to vim.lua_omnifunc #32491
- b61051ccb4 func: allow manual cache invalidation for _memoize
- 548f19ccc3 health: close checkhealth buffers with q #31870
- f2fa4ca97e health: highlight headings #30525
- b12b91c274 health: show :checkhealth in floating window #31086
- 6592873f77 help: use treesitter for table of contents
- 3e09fbdf82 highlight: add StatusLineTerm and StatusLineTermNC groups
- 295920845e highlight: make `PmenuMatch` and `PmenuMatchSel` bold
- 5b1136a99c inccommand: preview 'nomodifiable' buffers #32034
- 61025c9e7a install: mention standard paths, XDG vars in Windows installer #29101
- 8ef41f5902 jobs: jobstart(…,{term=true}), deprecate termopen() #31343
- e7020306a1 jumplist: allow opting out of removing unloaded buffers (#29347)
- 8d55cc218c keysets: teach Union and LuaRefOf
- 5931f780e0 log: use "ui" as default name for TUI client #30345
- e4c6e732fd lsp: add select kind in showMessageRequest #32387
- f20335a54c lsp: add support for completionItem.command resolving
- 3f1d09bc94 lsp: add vim.lsp.config and vim.lsp.enable
- 6072153796 lsp: announce codeLens resolveSupport (#29956)
- 1f5bcc7c4e lsp: completion opts support custom item conversion (#30060)
- ff097f2091 lsp: completion side effects
- 7a7747f1e4 lsp: deprecate execute_command with client:exec_cmd
- 454ae672aa lsp: deprecate non-method client functions
- 54249d051c lsp: deprecate vim.lsp.buf.completion
- e56437cd48 lsp: deprecate vim.lsp.start_client #31341
- 55e4301036 lsp: drop fswatch, use inotifywait (#29374)
- dad55f5e76 lsp: export diagnostic conversion functions (#30064)
- 44229bb85b lsp: highlight hover target/range #31110
- 27f3750817 lsp: improve LSP doc hover rendering #30695
- 6722149776 lsp: include `end_col` and `end_lnum` in `vim.lsp.buf.symbols_to_items`
- 20f22f75ee lsp: include end_col, end_lnum in vim.lsp.buf.locations_to_items #29164
- 4e90bc3023 lsp: lsp.completion support set deprecated (#29882)
- 6e68fed374 lsp: multi-client support for signature_help
- 629483e24e lsp: require `offset_encoding` param #31249
- e00cd1ab40 lsp: return resolved config for vim.lsp.config[name]
- 130b5fd85f lsp: return table from lsp/ files on runtimepath (#31663)
- ce678043e3 lsp: show server name in code actions #30830
- 07d5dc8938 lsp: show server version in `:checkhealth` #31611
- a1e313ded6 lsp: support `textDocument/foldingRange` (#31311)
- 3b0fe2659e lsp: support completion context #32793
- 41b07b128c lsp: support for resolving code action command (#32704)
- 35247b00a4 lsp: support function for client root_dir (#31630)
- 45e76acaa0 lsp: support hostname in rpc.connect #30238
- b2bad0ac91 lsp: support postfix snippets in completion
- d3e4ffafff lsp: support utf-8 and utf-32 position encodings
- 5d26934c7c lsp: update LSP healthcheck format (#28980)
- ae2fd91b41 lsp: update LSP types
- 0df2c6b5d0 lsp: use fuzzy match on filterText instead of prefix match
- e4c1f6667b lsp: use the meta model to generate server capability map
- 5581a95534 lsp: vim.lsp.buf.format() supports textDocument/rangesFormatting #27323
- 92e4e3fb76 lsp.util: fix type errors
- ff1d7d4299 lsp.util: get_bufs_with_prefix -> get_writeable_bufs
- cbc82011ce lsp.util: improve offset_encoding type annotations
- a18fa2f11c lsp.util: minor codestyle
- 1944c0d610 lsp.util: refactor get_border_size()
- f0973d4227 lsp.util: refactor symbols_to_items()
- 0e8568d72c lsp.util: remove lsp spec extract
- 0621718e3b lsp.util: remove metatable in locations_to_items
- 3f87e222f7 lsp.util: remove some aliases
- e954a16063 lsp.util: remove some variables
- 5bec7288a5 lsp.util: remove uneeded do-end
- 8ad000ef7c lsp.util: remove unneeded table
- d44d36b8ff lsp.util: simplify some bounds checking
- 0066dd0f65 lsp.util: use faster version of vim.validate
- 1edfe5c09e lsp.util: use vim.api alias
- 97119a2369 lsp.util: use vim.w/b
- cd53db2157 lua: add `context.env` (environment variables) to `vim._with()`
- 9afa1fd355 lua: add `vim._with`
- 5180707310 lua: add `vim.fs.abspath`
- b34e137e43 lua: allow vim.on_key() callback to consume the key (#30939)
- d5ae5c84e9 lua: completion for vim.fn, vim.v, vim.o #30472
- 0a5a0efda6 lua: don't complete private (_) fields after dot (.) #32690
- 07cc559cdf lua: update `vim._with` to allow more granular option contexts
- af0ef2ac9d lua: vim.hl.range() "timeout" #32012
- be1fbe38b3 lua: vim.text.indent()
- fdeb01cd77 main: expand file ~\ or ~/ prefix on Windows (#28515)
- ea5b748f24 man.vim: "q" always closes window #30819
- f58e7d5fac marks: add conceal_lines to nvim_buf_set_extmark()
- 51cf84daf9 marks: virtual lines support horizontal scrolling (#32497)
- cfdf68a7ac mbyte: support extended grapheme clusters including more emoji
- 124c655f56 messages: "g<" mapping for ext_messages
- cb7b4e2962 messages: "verbose" message kind #31991
- 5bae80899d messages: add :!cmd shell message kinds
- e16bec41b6 messages: confirm kind for z=, :tselect, inputlist() #32521
- 21151144c6 meta: add type for quickfix entries
- 82a215cb2d options: add 'eventignorewin' (#32152)
- d831392b15 paste: unify cancel and error behavior (#30476)
- 08c328b8b0 runtime: Lua ftplugin 'includeexpr' #32719
- f5714994bc runtime: Lua ftplugin sets 'omnifunc', 'foldexpr' #32697
- e6cfcaed18 snippet: add default keymaps during snippet session
- 123f8d229e snippet: set snippet keymaps permanent instead of dynamic (#31887)
- 96128a5076 startup: validate --listen address
- 230b0c7f02 stdlib: overload vim.str_byteindex, vim.str_utfindex #30735
- 517ecb85f5 stdlib: vim.json.encode(...,{escape_slash:boolean}) #30561
- 8df6736ca1 term: enable reflow by default (#21124)
- 4199671047 term: support OSC 8 hyperlinks in :terminal (#30050)
- 93480f7fba term: trigger TermRequest for APC (#32407)
- 3ad977f01d terminal: add support for copying with OSC 52 in embedded terminal (#29117)
- 6f0bde11cc terminal: add support for kitty keyboard protocol
- 06a1f82f1c terminal: forward X1 and X2 mouse events
- e3bfcf2fd4 terminal: support grapheme clusters, including emoji
- f1c45fc7a4 terminal: support theme update notifications (DEC mode 2031) (#31999)
- 56d11b494b terminal: disable 'number', 'relativenumber', and 'signcolumn' in terminal buffers (#31443)
- 34cd94812d test: support and document lua test case debugging
- b8c75a31e6 treesitter: #trim! can trim all whitespace
- ec8922978e treesitter: add more metadata to `language.inspect()` (#32657)
- bd3b6ec836 treesitter: add node_for_range function
- 688b961d13 treesitter: add support for wasm parsers
- 8543aa406c treesitter: allow LanguageTree:is_valid() to accept a range
- 44ccd9ca24 treesitter: allow `iter_captures` to accept `opts`
- 8b5a0a00c8 treesitter: allow disabling captures and patterns on TSQuery (#32790)
- 1af55bfcf2 treesitter: allow get_node to return anonymous nodes
- a94a2927d0 treesitter: allow passing lang to InspectTree
- 45e606b1fd treesitter: async parsing
- 3dfb9e6f60 treesitter: include capture id in return value of `get_captures_at_pos()` #30559
- 267c7525f7 treesitter: introduce child_with_descendant()
- 09f9f0a946 treesitter: show which nodes are missing in InspectTree
- b9b408a56c treesitter: start moving get_parser to return nil #30313
- da0ae95349 treesitter: support modelines in `query.set()` (#30257)
- 2e5b560482 treesitter: table of contents for checkhealth, markdown (#32282)
- 8ba047e33f treesitter: vertical conceal support for highlighter
- ff85e54939 tui: builtin UI (TUI) sets client info #30397
- 4fb3b57a19 tui: handle kitty key events in libtermkey (#31727)
- f93ecd2760 tui: parse CSI subparams in termkey (#29805)
- 44dbfcfba4 tui: recognize X1 and X2 mouse events
- e41368f3bc tui: support in-band resize events (#29791)
- d460928263 tui: update 'background' on theme change events (#31350)
- 45e319ade6 tutor: give hints to satisfy the line checker #30952
- 4b0e2605ea ui: UI :detach command
- 394f69a25d ui: additional arguments for cmdline_show/hide events
- a0e3fe5741 ui: cascading style inheritance for Pmenu* highlights #29980
- f85bc41c80 ui: don't show unfocusable windows in :tabs, 'tabline' #27984
- 9762c5e340 ui: gx: use url extmark attribute and tree-sitter directive (#30192)
- 43d552c566 ui: more intuitive :substitute confirm prompt #31787
- 433b342baa ui: sign/statuscolumn can combine highlight attrs #31575
- a10636fbe7 ui: specify whether msg_show event is added to history
- e049c6e4c0 ui: statusline text inherits highlights #29976
- 611ef35491 vim.fs: find(), dir() can "follow" symlinks #31551
- 3f15e57b26 vim.ui: configurable "gx" / vim.ui.open() tool
- f4b620c4e6 vim.ui.open: support lemonade #30845
- 3572319b4c vim.validate: improve fast form and deprecate spec form
- cb84cd5d9f win32: embed executable icon

FIXES
--------------------------------------------------------------------------------
- 200e7ad157 apply the change on more files
- 6720bd440f assert failure in VimL expression parser
- d123202ae6 change deprecation presentation
- ded15ca8c2 completion.enable(false,...) deletes invalid augroup #32121
- 7737f89206 deps build for ARM64 MSVC
- 50749f8df8 extend the life of vim.tbl_flatten to 0.13
- 25abcd243e fix broken wasmtime build
- b6ab294838 fix incorrect search code
- 46b69aaf14 include nvim/ascii_defs.h
- 01b4da65c2 merge all provider healthchecks into a single health.lua
- 5c245ec3e9 remove vim.lsp._with_extend
- 98ba65b8be replace NVIM with Nvim in default titlestring (#30348)
- 6aa42e8f92 resolve all remaining LuaLS diagnostics
- e71713ba2b show swapfile warning as a warning (#28971)
- 0418107074 update osc52 termfeatures flag on UIEnter/UILeave (#32756)
- 0829e7575d warn when :InspectTree on buffer with no parser #32783
- 47f2769b46 Man: completion on Mac
- 89f9f168a5 api: alloc and draw cursor window in nvim__redraw
- 743c5808b6 api: allow `scope = 'local'` with `buf` when using `nvim_get_option_value`
- 487c48ec86 api: clamp range lines in `nvim__redraw()` (#31710)
- 141114c170 api: crash on invalid buffer to nvim_buf_del_user_command (#31908)
- 716adbcc45 api: deprecate nvim_subscribe, nvim_unsubscribe #30456
- 1e47aa677a api: deprecated API nvim_get_option does not validate option name #31919
- 095c0876c2 api: don't override Vimscript SID (#32610)
- bff07f6dd0 api: don't try to get/set option for invalid option name (#31302)
- 0e59f6f4c7 api: don't use 'winborder' when reconfiguring float (#32984)
- cce1eb0806 api: error properly with invalid field in nvim_open_win (#30078)
- 63bbb7c109 api: fix 'winborder' preventing splits with nvim_open_win (#32981)
- f55213ce0e api: fix crash/leak with float title/footer on error (#30543)
- 022449b522 api: generic error messages, not using TRY_WRAP #31596
- 8de1dc6923 api: make `nvim_set_hl()` respect all `cterm` attributes (#31390)
- ad60b3fb48 api: memory leaks in vim.api.nvim_*get_option #32390
- 167a2383b9 api: not using TRY_WRAP, generic error messages #31595
- bf48dfadec api: nvim__complete_set requires completeopt=popup #31177
- d1d7d54680 api: nvim_buf_get_text() crashes with large negative column #28740
- 6ea45031d5 api: nvim_echo free text memory with invalid highlight (#31243)
- e2ad251c8d api: nvim_get_option_value does not clean up on FileType error #31219
- 5b9518b436 api: nvim_set_decoration_provider callback return type #31912
- 01a97d2ad7 api: nvim_win_set_buf(0, 0) fails if 'winfixbuf' is set #31576
- 40347f6e27 api: only flush nvim__redraw when necessary #31250
- 36f44b3121 api: remove invalid assertions
- 235cb5bc5f api: update "range" windows in nvim__redraw #31042
- 9c718bc2bc api: validation, documentation of hl_group #31195
- 289c9d21cb autocmds: once=true Lua event-handler may call itself #29544
- ffaab09e99 build: <termios.h> is system-dependent #31705
- 486076a0e1 build: remove USE_FNAME_CASE, redundant with CASE_INSENSITIVE_FILENAME
- 217e26cb64 build: surpress spurious warnings from gcc in -E preprocessor mode
- 34a2bfdcc5 build: vimdoc tags are not validated #32801
- 8070988247 channel: handle writing to file instead of pipe (#30519)
- c49162be59 channel: log after (not before) channel-close
- 965dc81f81 checkhealth: disable 'listchars' #31245
- 4c9f3689a1 checkhealth: failed if 'lua' in plugin name
- f5dd30948e checkhealth: handle nested lua/ directory #32918
- c48cf18752 checkhealth: module not found when `&rtp` has nested paths #32988
- 2495e7e22a clipboard: tmux clipboard depends on $TMUX #31268
- 847c28f6f6 cmdline: always show cmdline when it is a prompt #31866
- af4231d407 cmdline: cmdline completion of _defer_require() modules #33007
- a70ad5cdb6 cmdline: ext_cmdline block events for conditionals
- bbf36ef8ef cmdline: prevent cmdline_show events after exiting cmdline #32033
- 092042b43d cmdline: simplify and correct grapheme cluster adjustment
- 86ae59c612 colorscheme: distinguish CursorLine/Folded/StatusLineNC highlights #32256
- 9b9f54e2c1 colorscheme: underline StatusLineNC with 'notermguicolors' #28810
- 8bc28978b6 column: apply custom highlight to last 'statuscolumn' segment (#32182)
- 3cb1e825e6 column: check if signcolumn changed in all windows #31439
- 1dcda86559 column: clamp line number for legacy signs
- f2083bd55c column: crash with 'signcolumn' set to "number" (#29003)
- f9a49fab0c column: modifying a sign should update placed signs (#29750)
- d5f6f61879 column: set signcolumn width after splitting window (#30556)
- 063b69bab4 column: unnecessary redraws with resized 'statuscolumn' (#32944)
- 0a2218f965 comment: fall back to using trimmed comment markers (#28938)
- e788d1a3a9 completion: avoid deleting text when completion leader changes #31448
- bfa365a872 completion: don't include <Lua function> in -complete= (#30209)
- 55dc482e75 completion: fix inconsistent Enter behavior (#30196)
- 83a7d97d64 coverity: CID 509571 Uninitialized variables #30395
- e1c2179dd9 coverity: INTEGER_OVERFLOW #31657
- f9eb68f340 coverity: error handling CHECKED_RETURN #31618
- 069451bb21 coverity: size_t overflow #30497
- ff7832ad3f coverity/497355: shada_read_when_writing out of bounds read #30665
- c49030b75a coverity/497375: f_strpart cast overflow (#30773)
- 0fe4362e21 coverity/509227/509228: tui driver_ti underflow #30341
- 60e1862ccb coverity/510275: linematch out of bounds access (#30687)
- a2008118a0 coverity/510436: shada_read_when_writing index out of bounds (#30686)
- 71507281fb coverity/530826: validate_opt_idx unchecked negative idx (#32081)
- 5af9c065ad decor: don't draw invalidated virtual lines (#29858)
- a8fbe1d409 decor: don't use separate DecorSignHighlight for url (#30096)
- 34ded4d97b decor: exclude invalid marks from meta total
- 87610d82db decor: set invalid flag for end of invalidated paired marks
- 33ff546b50 decoration: fix crash when on_lines decor provider modifies marktree
- 0e299ebf75 decorator: noisy errors from decoration provider #31418
- f2173b1aa2 defaults: cannot remove "How-to disable mouse" menu item #30375
- 61aabe0730 defaults: default @/Q broken when 'ignorecase' is set (#29343)
- 8323398bc6 defaults: don't replace keycodes in Visual search mappings (#31460)
- f6f2334ac2 defaults: error messages UX for unimpaired mappings #30884
- 59a171fd99 defaults: improve visual search mappings #32378
- 01739d4673 defaults: missing ]Q/[Q unimpaired mappings #30943
- c644228e1d defaults: omit empty line from unimpaired mapping messages (#31347)
- ff93cccbc1 defaults: omit extraneous info from unimpaired mapping errors (#30983)
- 4075e613b2 defaults: properly pass count to quickfix commands (#30632)
- 289380bc40 defaults: use "range" instead of "count" for some mappings (#30642)
- 573fcb8b66 deps: revert accidental test commits (#30864)
- de794f2d24 diagnostic: broken variable reference #31557
- c78728a384 diagnostic: clear autocmd only for valid buf (#32861)
- f1fcf653cb diagnostic: clear virtual_lines autocmd only for valid buf #32979
- 921dc22fc0 diagnostic: correct `severity` type on `setqflist`, `setloclist` (#30506)
- 0e8e4a07f5 diagnostic: don't include diagnostic code when using custom formatter #32464
- d918ebe3b8 diagnostic: fix backwards compatibility for goto_next and goto_prev (#29593)
- f69937fdbd diagnostic: fix float scope filtering (#29134)
- 5bc948c050 diagnostic: improve current_line refresh logic #32275
- 4b3be56a03 diagnostic: make docs agree with code (#29561)
- fd902b1cb2 diagnostic: only store quickfix id when creating a new one #31466
- 3b1d0e7f70 diagnostic: remove deprecated `severity_limit` option
- 5eda7aafe9 diagnostic: setqflist() is stuck after vim.lsp.buf.document_symbol #31553
- 9a43ec13e6 diagnostic: show backtrace for deprecation warnings
- 4cbeb6fa3c diagnostic: silence :chistory #31701
- 6c975515c5 diagnostic: vim.diagnostic.setqflist() opens loclist on first call #31585
- 17c25a66fc diagnostic: virtual lines should scroll horizontally
- fb842dfc22 diagnostic: virtual_lines diagnostic columns (#32703)
- e5e81262af diagnostics: don't apply extmarks to invalid lines #29321
- c65646c247 diff: use mmfile_t in linematch
- 81ea44fa6a display: adjust winline info for concealed lines below last line (#32708)
- f25dd7a8d5 display: correctly store winline info for concealed lines (#32656)
- a901fb875f docs: add missing properties to hl_info #30032
- cc26cf0400 docs: do not treat indexes as `short_link`
- 056009f741 docs: markdown instead of vimdoc in meta docstrings #30680
- 8801b77ed0 docs: missing `@returns` desc in _meta/api.lua #30673
- 09bcb31068 docs: replace `yxx` mappings with `g==` #31947
- efe92f9dff docs: update context type in `vim.lsp.LocationOpts.OnList`
- b8135a76b7 docs: wrong return value annotation for `nvim_buf_get_extmarks`
- 376de1483e drawline: correct highlight priority with Visual selection (#30706)
- 9a0239fdc8 drawline: don't draw beyond end of window (#29035)
- b1c439cef6 drawline: don't draw beyond end of window with 'rnu' (#29406)
- 34344b939c editor: avoid scrolling :substitute confirm message #32149
- 9e7b0bcf51 editorconfig: fix indent style for `local.mk` (#31342)
- b0a1d35f69 eval: don't shorten $HOME in v:stacktrace (#32634)
- 2a3561819e eval: handle wrong v:lua in expr option properly (#29953)
- 4317d36669 event-loop: process input before events in getchar() (#32322)
- f05a6666cf events: always allow some events to be nested (#32706)
- e9f4ceeb74 events: don't expand `args.file` for Lua callback (#31473)
- 1f49a59b8b events: fix incorrect capitalization of Cmdwin* events (#32813)
- 8c2d45be77 exit: close memfiles after processing events (#30872)
- c7ec010ade extmark: builtin completion can still affect nearby extmarks #31387
- 93278e7720 extmark: clearer error message for invalid ephemeral mark usage
- 43a2019f09 extmarks: issues with revalidating marks #28961
- 84ad95fdc9 fileio: copy to correct buffer position when reading
- 93347a67bf filetype: fix :filetype detect error with -u NONE (#29991)
- aa9f21ee95 filetype: fix typos in filetype detection
- 032e024f8a filetype: handle .in files with no filename (#30487)
- 1077843b9b filetype: make filetype detection work with :doautocmd (#31470)
- 21cbd90007 filetype: normalize full path before matching #32227
- 5a8a34dafa filetype: source ftdetect/* after creating scripts.vim autocmds (#29445)
- cff5fa49fc float: "Not enough room" error for 1-line float #25192
- 07c5f41da3 float: can set title/footer without setting border #32594
- be01b361d8 float: cannot set title/footer independently #31993
- ff1791c9e5 float: close preview float window when no selected #29745
- d2cca606a1 float: ensure floating window width can fit title
- 8ddcf9d939 float: handle error in win_float_create() (#29742)
- 8b2b1fba2a float: missing default highlight for title
- df915f3afc float: properly find last window of tabpage (#30571)
- 17383870dd float: re-sort layers when grid zindex changed #30259
- 206f8f24a2 fs: make vim.fs.root work for relative paths and unnamed buffers (#28964)
- 2c160f39d3 ftplugin/man.vim: hide signcolumn (auto)
- 214ce8d33c gen_help_html: first tag in h2 is broken #30720
- ceea6898a8 gen_help_html: handle delimiter, heading #29415
- 6c3f7e7e27 gen_vimdoc: correctly generate function fields
- 913e81c35f getchar: do not simplify keycodes in terminal mode
- b109b1abce glob: avoid `subcapture nesting too deep` error (#29520)
- 4bd86120d4 glob: handle overlapping `{}` condition elements #29236
- b47b0b3f75 grid: double grid_line_start() with ext_messages #31292
- fe87656f29 grid: grid_line_start NULL access with 'redrawdebug'
- a9c89bcbf6 gx: allow `@` in url
- 570a8da01b health: "q" should not close last window #31876
- 2e3f1069f4 health: better layout of vim.treesitter health check
- 10f9173519 health: broken ruby detect #28804
- 84e85aeb10 health: check more "old" files #30421
- 5b778a64ec health: fix fetching url with python in provider health (#29594)
- b4b4cf46a7 health: fix pyenv root and python exepath detect issue
- 237d2aef4d health: return correct name from 'path2name()'
- 5e90406487 health: set nomodifiable in checkhealth buffers
- 9177371014 help: remove runnable code virtual text
- ff75f345ab highlight: 'winhl' shouldn't take priority over API (#31288)
- 458473acb8 highlight: add `StatusLineTerm`/`StatusLineTermNC` to `:color vim` (#29313)
- 6bcefad5a6 highlight: fix the seg fault caused by the invalid linked hl ids
- 8e81212e15 highlight: floating windows inherit NormalFloat from global-ns
- 6719276040 highlight: make TablineSel more noticeable with 'notermguicolors' #31905
- b67fcd0488 highlight: make `TablineSel` more noticeable #31896
- 862679c70f highlight: update `PmenuSel` for colored completion items #30183
- 59e130b6ca inccommand: ensure cursor is where it belongs
- 16f63b964f input: handle vim.on_key() properly with ALT and K_SPECIAL (#29677)
- b52ffd0a59 inspect: always show priority
- 9c278af7cc inspect: show priority for treesitter highlights
- 22fd52325b inspector: update semantic token namespace (#32157)
- efe1732c6f jobs: do not block UI when jobwait() doesn't block (#31803)
- 574ea6a191 keycodes: recognize <Find>, <Select> #28431
- 67bb0cfa79 loader: follow the style of the error message for built-in loaders
- 44740e561f log: RPC log format #32337
- 851137f679 log: log unset $TMPDIR at "debug" level #32137
- c908c2560d log: unify error messages for vim.ui_attach/decor providers #33005
- a6f219b06b log: unintuitive message for undefined $TMPDIR
- 2e6d295f79 lsp: account for changedtick version gap on modified reset (#29170)
- fac96b72a5 lsp: add foldingrange method support check #31463
- 8263ed4670 lsp: add textDocument/documentLink to capability map (#28838)
- a41b6fd173 lsp: autocmds to close lsp preview windows not cleared
- b42dc232c5 lsp: autotrigger should only trigger on client's triggerCharacters (#32266)
- 7031949be0 lsp: avoid reusing diagnostics from different servers in actions (#30002)
- fc9b70826e lsp: avoid vim.keymap.del error when stopping a client (#29478)
- 39d79efa1e lsp: better multi-client support for callHierarchy
- bdfba8598b lsp: cancel pending requests before refreshing
- f9bf64d746 lsp: check buffer is loaded and valid #30330
- c2bf09ddff lsp: check for configuration workspace folders when reusing clients
- 81b372fecd lsp: check for nil response from server (#29196)
- a9cdf76e3a lsp: check for valid buf before processing semantic tokens response
- 230bc34ca5 lsp: check if buffer is valid before LspDetach autocmd (#29162)
- af200c10cf lsp: check if buffer was detached in on_init callback (#28914)
- 02097e43c8 lsp: check if sig_help window is focusable when configuring cycle keymap
- 025c874415 lsp: clear lsp client diagnostics (#29050)
- c374f26430 lsp: clear word when expand multi-lines word (#32393)
- adf7c98d60 lsp: compare URI instead of workspace folder name (#30962)
- b4599acbf8 lsp: correct hover result handling (#30995)
- f8d5811c71 lsp: correctly check for "codeAction/resolve" support
- 7d8db54441 lsp: delete b:lsp_floating_preview buf var after win close
- 2a1f604c77 lsp: delete bufvar inside WinClosed event
- 879d17ea8d lsp: detach all clients on_reload to force buf_state reload (#28875)
- 292365fa1b lsp: do not detach from buffer if there are uninitialized clients (#29029)
- 37bf4c572a lsp: do not reset buf version when detaching client (#29242)
- d56ba71af1 lsp: document_symbol uses loclist by default #32070
- 720b309c78 lsp: don't send foreign diagnostics to servers in buf.code_action (#29501)
- 1f2f460b4a lsp: don't show codelens for buffers that don't support it (#29690)
- 5f527f24f0 lsp: don't use completion filterText if prefix is empty
- 305012ea07 lsp: enable `additionalPropertiesSupport`
- 9d9ee3476e lsp: ensure watcher cancel
- aec7f1979a lsp: fallback to `label` for completion items if all others are missing (#29522)
- 33d10db5b7 lsp: filter completion candidates based on completeopt (#30945)
- b3109084c2 lsp: fix cursor position after snippet expansion (#30659)
- 4b001f297a lsp: fix infinite loop
- 983953858e lsp: fix isIncomplete condition in completion trigger (#30130)
- 2ce4a4d91e lsp: fix reverse sorting of same position text edits (#29212)
- 8654a97006 lsp: handle empty call hierarchy items #30349
- f279d1ae33 lsp: handle encoding bounds in str_utfindex_enc
- 882a450a29 lsp: handle locations exceeding line length #30253
- 008782208d lsp: handle mixed encoding in tagfunc params
- e0a5c3bb58 lsp: handle multiline signature help labels #30460
- 8512f669f0 lsp: handle nil bytes in strings
- f03b1622ad lsp: handle nil root_dir in health check (#29007)
- ed07167261 lsp: handle non-existent configs in lsp.config/enable
- 003b8a251d lsp: handle out-of-bounds character positions #30288
- 5187be81c2 lsp: handle using array as open_floating_preview title (#33016)
- d9a2acdab3 lsp: hide layout in codelenses in virtual text (#28794) (#28807)
- f54266dbed lsp: hover border type can be string (#31013)
- 9a681ad09e lsp: hover keymap (#31208)
- a14fca432b lsp: improve LSP floating preview window cleanup #31353
- e29f245a10 lsp: inlay hints are rendered in the correct order (#29707)
- 0086ee90dd lsp: list all workspace folders in healthcheck #30966
- 0e394f136f lsp: log when receiving markup messages (#30065)
- 203e7a43d1 lsp: mention function name in warning #31301
- a4f575abd8 lsp: minimum height for floating popup #31990
- 4fd2694f20 lsp: missing method parameter when canceling requests
- be8d87014c lsp: on detach, cancel pending foldingRange requests #31509
- 7d5866d471 lsp: open_floating_preview() ignores max_height (#32716)
- 86770108e2 lsp: open_floating_preview() zindex relative to current window #31886
- 724d1110b1 lsp: pre-filter matches on label if filterText is missing (#29491)
- a450fda4ed lsp: prefer `on_list` over `loclist` in default handler
- 6bb40f3dbf lsp: prevent desync due to empty buffer (#29904)
- eb629cce91 lsp: redundant spaces in lsp log (#29970)
- 43581011e4 lsp: remove superfluous on_detach callback from semantic tokens module (#29174)
- d76f7fef13 lsp: reset active request when reporting an error
- 6bc7979044 lsp: reset the applied hints on `refresh` request #32446
- 47aaddfa0d lsp: resize hover window for concealed lines
- 081beb3659 lsp: restore get_language_id behaviour
- 29c72cdf4a lsp: retrigger diagnostics request on server cancellation (#31345)
- d9ccd828b0 lsp: return call hierarchy item, not the index (#30145)
- 9c20342297 lsp: reuse client if configs match and no root dir
- 6e45cd7f00 lsp: revert buf_versions deprecation/replacement (#29217)
- bdff50dee5 lsp: revert text edit application order change (#29877)
- e8a6c1b021 lsp: schedule call to vim.lsp.start for async root_dir (#31998)
- a108852b00 lsp: semantic token functions allow "0" bufnr #28849
- c3cb702ac7 lsp: set 'smoothscroll' in docs hover #30748
- 8a236c242a lsp: set floating window filetype after setup #32112
- 3c51058d76 lsp: set tagstack on jump via goto methods
- 24d7debdfb lsp: signature_help highlights wrong parameter #32382
- 80e37aa533 lsp: str_byteindex_enc bounds checking #30747
- 629a5b71b5 lsp: support multiple clients in typehierarchy
- e48179f31e lsp: suppress completion request if completion is active (#30028)
- 50f006b617 lsp: tagfunc fails in unusual buffer #30700
- 5ac8db10f0 lsp: trigger LspDetach on buffer delete (#28795)
- 19be3d2683 lsp: trim trailing whitespace from completion words (#29122)
- aa47af7e69 lsp: tune completion word extraction for decorated labels (#29331)
- 38838fb00a lsp: type-errors, other nits in vim.lsp.log #31235
- 8d7eb03040 lsp: unify get_completion_word for textEdits/insertText
- fe5ae88b20 lsp: update request name to capability map #30098
- 5aa9906676 lsp: use client.id instead of pairs index (#29143)
- c8d7d65679 lsp: use correct method for prepareTypehierarchy
- b9e6fa7ec8 lsp: use filterText as word if textEdit/label doesn't match
- 5d08b65ac2 lsp: use unresolved code action when `codeAction/resolve` fails
- 0a7e4e9e5f lsp: vim.lsp.enable(...,false) does not disable  #32002
- 888a803755 lsp: vim.lsp.start fails if existing client has no workspace_folders #31608
- 42ed0ffad9 lsp: when prefix is non word add all result into matches (#30044)
- 55bdb077b7 lsp: wrapped ctx in opts before passed to vim.lsp.completion.trigger #32837
- 2dcbfe78fc lsp.buf: use correct offset_encoding for all requests
- 3275ae830d lsp.protocal: improve typing of constants
- acbc6a7f91 lsp.util: inconsistent handling of offset_encoding
- 564173e556 lsp.util: wrong arguments to 'validate' function
- 614c9322d5 lua: SIGSEGV in luv callback with error(nil) #32595
- b283736388 lua: `@private` => `@nodoc` #32587
- b6e350a6b4 lua: allows tables with integer keys to be merged in tbl_deep_extend
- c8b64b7a43 lua: always use vim.inspect() for :lua= (#32715)
- 0e42c81c7f lua: avoid recursive vim.on_key() callback (#30753)
- fe1e2eff06 lua: avoid vim._with() double-free with cmdmod (#31505)
- 487f44a6c1 lua: change some vim.fn.expand() to vim.fs.normalize() (#29583)
- 43bd9c9c1c lua: don't clamp -1 or v:maxcol in vim.highlight.range() (#29203)
- bdc6e38781 lua: don't include text after cursor in completion pattern (#29587)
- e2aca58bcc lua: don't override script ID from :source (#32626)
- d40481322a lua: ensure inspect_pos() only shows visible highlight extmarks
- 948f2beed4 lua: find length of completion prefix earlier (#29384)
- ebb963a4a0 lua: format errors from luv callbacks using __tostring
- 65a703e060 lua: ignore stdout and stderr for xdg-open
- 6b00c9acfd lua: no omni/cmdline completion for vim.env (#33044)
- c6d2cbf8f5 lua: pop retval for fast context LuaRef
- a5b1b83a26 lua: prevent SIGSEGV when lua error is NULL in libuv_worker
- 3d707e6f14 lua: remove vim.loader.disable() #31344
- 3a88113246 lua: revert vim.tbl_extend behavior change and document it
- 3688a33354 lua: show stacktrace for error in vim.on_key() callback (#31021)
- 40a149e7f9 lua: types for vim.api.keyset.win_config #32700
- 7f33c1967b lua: use rawget() to get __call in vim.is_callable() (#29536)
- 960fdc775a lua: vim.deprecate does not support major>0
- d832518ec6 lua: vim.hl.on_yank highlights wrong region with yi' (#32850)
- cd3855fb2b lua: vim.tbl_get({}, nil, 1) should return nil #32218
- 89d6d6f25c lua: wrong script context for option set by func from nvim_exec2 (#32659)
- 9eb0426002 luacats: allow all types inside tuples
- ee5aaba215 man: avoid setting v:errmsg (#30052)
- 7588ff2d89 man: check if buffer is valid before restoring 'tagfunc' (#30180)
- da6f68ee69 man: filter OSC 8 hyperlink markup #29171
- 7940ec6913 man.lua: `:Man <tab>` does not complete #31569
- e08e3d15f6 man.lua: skip `Attrs.None` highlights #32262
- d6653e1cc9 marks: ensure decor is removed with proper range (#32973)
- 906ad04ddd marks: handle composing in inline virt_text with 'nowrap' (#32477)
- 8452032554 marks: handle double-with inline virt_text with 'nowrap' (#32476)
- 86046c5a31 marks: ineffective conceal_line callback optimization (#32662)
- 72f630f92d marks: issues with invalid marks and marks beyond eob (#32862)
- 8da59060c6 marks: mark winline as invalid if change is in a concealed line (#32766)
- 012db2b0f5 marks: revalidate marks whose position did not change
- 5cc93ef472 marks: revise metadata for start mark of revalidated pair #32017
- c4f76299f0 marks: skip right_gravity marks when deleting text
- cdedfc3743 marks: truncate double-width inline virt_text consistently (#32560)
- 7371abf755 marks: wrong winline info for concealed line with below virt line (#32747)
- a9287dd882 mbyte: check for utf8proc_map() failure (#30531)
- 50a576ba57 mbyte: mark any 0xFE0F sequence as a TUI ambiguous width char
- 15bc930fca memline: don't check line count for closed memline #32403
- aa976f0d93 messages: add a trailing space to inputlist() etc. prompts (#32328)
- 37c77ab46b messages: attaching/detaching ext_messages causes asserts #31952
- d98827b634 messages: avoid empty msg_showmode with 'noshowmode'
- 31d6885deb messages: better formatting for :highlight with ext_messages #31627
- 21718c67dd messages: better formatting for ext_messages #31839
- 92556be33d messages: compute msg_col after last newline in ext_messages
- ad853d1df0 messages: improve deadly signal messages #32364
- 51853b82bc messages: incorrect error message splitting and kind #32990
- 08f7c22377 messages: list_cmd kind for :registers, :au[g] #32531
- 7ce27381fb messages: lsp window/showMessage is not an error
- 1b6442034f messages: more ext_messages kinds #31279
- 9c6a3703bb messages: no message kind for :undo messages #31590
- ca760e645b messages: no message kind for :write messages #31519
- 909b18d05a messages: no message kind for completion menu messages #31646
- f111c32ff9 messages: no message kind for search pattern #31272
- 282f73f067 messages: no trailing newline for inputlist, tselect, z= with ext_messages
- 9fa3a0964e messages: pass previous highlight id to ext chunks
- e025f5a5b3 messages: proper multiline Lua print() messages #31205
- d1e00a5f6d messages: typo and unwanted truncation in msg_outtrans_long #31669
- d55b17e2b4 messages: verbose kind for nvim_echo()
- c8e47f6480 meta: do not use hyphens in param names
- 2cd72258f6 mouse: 'statuscolumn' fold and popopmenu handling
- 81d4e96bc8 mouse: don't treat click on hsep as click on statusline (#29565)
- 102971a396 mouse: early return when clicking in padded 'statuscolumn' (#29394)
- 86c5c8724b mouse: indicate X1 and X2 button clicks on statusline (#30655)
- f86864f22f move: 'scrolloff' cursor correction no longer handles folds properly (#32642)
- 5947f249f8 move: half-page scrolling with resized grid at eob (#28821)
- ac7e0ff32f move: redraw for 'concealcursor' after changing w_wcol (#31276)
- af0a2157ad move: wrong cursor row on concealed line (#32629)
- 83479b95ab mpack: remove invalid bool definition
- d32780de4d mswin: UI may hang on exit
- fa99afe35e multibyte: handle backspace of wide clusters in replace mode
- de83cc5842 netrw: re-add missing comment marker in syntax file
- d9585bdcfb nvim__set_complete: pum preview info truncated during completion #32555
- 34e2185022 options: better handling of empty values
- 190d0241e2 options: fix 'winborder' accepting multiple string values (#32978)
- 8c532a9ea8 options: fix 'winhl' still accepting invalid value (#30896)
- 1b9dafa67b options: fix :setglobal not working for 'spelloptions' (#30894)
- 395f420fc6 options: fix some 'belloff' flags not working properly (#30856)
- 50e63c8171 options: missing error check for global 'scl' and 'winhl' (#30919)
- e697c1b43d paste: improve repeating of pasted text (#30438)
- 052875b9dc paste: only record a paste when it's from RPC (#30491)
- 9516997eb0 paste: wrong '[ mark after pasting a big string (streamed chunks) #33025
- 42aa69b076 path: avoid chdir() when resolving path (#28799)
- 42db8b1759 path: crash with nvim_get_runtime_file during wildcard expansion (#32992)
- 0dfcf3fe12 plines: don't count invalidated virt text in char size (#29863)
- afc3c43f12 popup: new preview_bufnr created when menu item is selected #32819
- ac1c5ccb2c popup: reuse pum preview float win, set 'winfixbuf' #32636
- d288f7003d popup: wrong extmark data sync when lines changed in popup preview #30246
- d24fb72c33 pum: don't select item when clicking to the left/right (#30967)
- 73ae7d44a2 quickfix: make shortmess+=O work with cmdheight=0 (#29609)
- 3bcd5624be regexp: fix typo in E888 error message (#30161)
- cb924764a4 runtime: "E121 Undefined variable s:termguicolors" #32209
- 29a47b39cc runtime: E15: Invalid expression in lua file when `gf`
- b6c1ce8a95 runtime: add commentstring for glsl ftplugin
- 9ddfcb64bf runtime: add remaining missing commentstrings (#30252)
- e641155b02 runtime: avoid E31 in ftplugin (#32578)
- 82b02ae2f2 runtime: clean up one-off scripts
- 9788b81d7e runtime: fully port emoji_list to Lua
- 74fcc9452c runtime: gO always says "Help TOC" #32971
- 69aa33d890 runtime: let matchit and matchparen skips fallback on treesitter captures
- 8369590eb2 runtime: remove obsolete ftplugin/calender.lua
- 41b70a0dea runtime: set 'keywordprg' only once in vim ftplugin
- 7b16c1fa84 runtime: source c ftplugin properly for cpp on Windows (#29053)
- 12c9791e0f runtime: stop treesitter highlight in b:undo_ftplugin (#29533)
- 862338255d runtime: sync bundled treesitter queries
- 9e80738f30 runtime: sync bundled treesitter queries
- 5057753431 runtime: treat b:undo_ftplugin consistently in Lua ftplugins (#30473)
- 8f5e908110 runtime: update b:undo_ftplugin in Lua runtime files (#29529)
- a5bd6665b0 scripts: update bundled dependencies in bump_deps
- 573a71469d scrollbind: properly take filler/virtual lines into account
- a8b6fa07c4 search: avoid quadratic time complexity when computing fuzzy score (#32153)
- 648d6426c8 server: CID 509282: DEADCODE #30316
- f4921e2b7d shada: ":wshada/:rshada [filename]" with shadafile=NONE #32538
- cd48b72b60 shada: restore search pattern length properly (#28929)
- 608543f8a9 snippet: cancel snippet session when leaving the buffer (#29031)
- 7994fdba6a snippet: don't override unnamed register on tabstop select (#28998)
- 5fe4ce6678 snippet: modify base indentation when there's actually whitespace (#29670)
- 424f4cc038 snippet: wrong indentation when snippet contains "^" #32970
- d46ebd2a74 startup: avoid crash with completion from -l script (#32160)
- 08153ddd1c startup: ignore broken $XDG_RUNTIME_DIR #30285
- 17e00d0cc6 startup: report --startuptime error to stderr (#31131)
- 8a2aec9974 startup: server fails if $NVIM_APPNAME is relative dir #30310
- 19fc65acbc statuscolumn: misleading v:lnum for virtual lines #32912
- 87e806186c statusline: overwriting stl_items with nvim_eval_statusline() {-item #32265
- 1c30d86c33 tabline: restore behavior of click after last tabpage (#30602)
- a49f95d887 terminal: avoid mismatched `busy_start` without `busy_stop` (#32458)
- f3ce67549c terminal: avoid more `busy_start` lacking `busy_stop` (#32509)
- 3d49c55d3c terminal: avoid rescheduling events onto the same queue (#32755)
- 69a19295f8 terminal: delay when finishing terminal process #32846
- f8c8a245aa terminal: don't crash on unprintable chars
- 6d997f8068 terminal: handle C0 characters in OSC terminator (#30090)
- fa46441264 terminal: improve cursor refresh handling (#32596)
- 1d11808bfd terminal: interrupt/got_int hangs terminal (#30056)
- 3db3947b0e terminal: restore cursor from 'guicursor' on TermLeave (#31620)
- c51bf5a6b2 terminal: set cursor cell percentage (#31703)
- 5def8714ad terminal: set local values of window options (#29326)
- e9c077d197 termkey: fix null pointer dereference (#31792)
- c8e3618e0e test: "tempdir not a directory" in CI logs
- f7e32fb6e6 test: better management of tmpfiles
- db2c3d1143 tests: filter out lines with __typeof__ keyword (#32524)
- e61228a214 tests: needing two calls to setup a screen is cringe
- 639734bed4 tests: remove the __extension__ keyword  in filter_complex_blocks (#32483)
- 59baa5e8a1 tohtml: apply sp color if present #30110
- 67c39f5eca tohtml: disable modeline #32822
- e37404f7fe tohtml: enclose font-family names in quotation marks
- 25db0a1385 tohtml: extmark text may be out of bounds
- 8cd9feb501 tohtml: ignore lsp inlay hints
- eb37241d38 tohtml: properly handle multiple hl groups #29012
- 2ed6423c7e tohtml: replace ipairs with pairs
- 88c7997503 tohtml: show how many warnings are hidden
- 118ae7e5ed tohtml: support ranges again
- c63e49cce2 treesitter: #trim! range for nodes ending at col 0 #31488
- b63cd8cbae treesitter: EditQuery shows swapfile ATTENTION #30536
- 55b165ac15 treesitter: `TSNode:field()` returns all children with the given field
- 86b737649b treesitter: add 'QuitPre' event to autocommands in inspect_tree
- bc1018a8d3 treesitter: avoid computing fold levels for empty buffer
- a119dab40f treesitter: avoid computing foldlevels for reloaded buffer #32233
- 6696ea7f10 treesitter: clean up parsing queue
- 99acc9de55 treesitter: close InspectTree/EditQuery window on BufUnload (#31036)
- f50f86b9ff treesitter: compute folds on_changedtree only if not nil
- 7a20f93a92 treesitter: correct condition in `__has_ancestor`
- 9b25c68db2 treesitter: correctly parse queries with combined injections
- 3abfaafad2 treesitter: detect trees with outdated regions in `is_valid()`
- 9217e0d671 treesitter: display fields for anonymous nodes in :InspectTree
- da4e8dc5b0 treesitter: do not modify highlight state for _on_spell_nav
- 0e3e1e6b6d treesitter: don't open fold when o/O adds a line below #28709
- aa2b44fbb0 treesitter: don't return error message on success #31955
- b0bbe25c48 treesitter: don't spam query errors in the highlighter
- b88874d33c treesitter: empty queries can disable injections (#31748)
- d413038b4f treesitter: ensure syntaxset augroup exists (#29542)
- f8e1ebd6f6 treesitter: escape things like `"` in omnifunc results
- c4eb0b64bd treesitter: find buffer in multiple windows #28922
- 94d42a3e72 treesitter: highlight anonymous nodes in inspect_tree
- 5331f87f61 treesitter: indent size for inspect_tree #28727
- 6ef80eb42c treesitter: keep treeview open if source window is still open #31198
- 052e048db6 treesitter: lint top-level anonymous nodes
- 4b90952851 treesitter: mark supertype nodes as named
- 096ae3bfd7 treesitter: nil access when running string parser async
- c3337e357a treesitter: nil check query for has_conceal_line
- 6711fa27ca treesitter: recalculate folds on VimEnter #32240
- 05dcda8f9b treesitter: recognize aliased parsers in omnifunc, query linter
- d3193afc25 treesitter: remove duplicate symbol names in language.inspect()
- cdc9baeaf8 treesitter: remove redundant on_bytes callback #31041
- 1827ab7a1f treesitter: separately track the number of valid regions
- 36990f324d treesitter: show proper node name error messages
- 4349bdbd0b treesitter: specify success status in edit_query return value
- e7ebc5c13d treesitter: stop async parsing if buffer is invalid
- 0f067cd34d treesitter: suppress get_parser warnings via opts.error
- ae917dbd06 treesitter: sync queries from upstream
- c4e9ff30a6 treesitter: sync queries with upstream
- d8eec81560 treesitter: update lua, markdown queries
- 6e44a6a289 treesitter: update queries
- 5a54681025 treesitter: uv_dlclose after uv_dlerror
- e4bc8b5967 treesitter.foldexpr: only refresh valid buffers
- 48acbc4d64 treesitter.foldexpr: refresh in the buffers affected by OptionSet
- 8474f52978 treesitter.foldexpr: robustness against ctrl-c
- f81131cca2 tui: also reset cursor color if it was invisible (#31348)
- 4846bf05dc tui: avoid flushing buffer halfway an OSC 2 sequence (#30793)
- 720ec5cec2 tui: cursor color in suckless terminal #32310
- b5cb69f8a4 tui: handle key events for arrow and function keys (#31804)
- d7651b27d5 tui: move $COLORTERM check to _defaults.lua (#29197)
- a811d4babd tui: only reset cursor color if it was changed (#31337)
- 0c0352783f tui: remove DCS escaping in tmux (#32723)
- 47c741e30c tui: remove duplicate disabling of synchronized output (#28884)
- f32557ca67 tui: reset active attr ID when OSC 8 sequence is terminated (#29960)
- bc63ffcf39 tui: reset clear_region attributes during startup #28713
- b02c839414 tui: set id parameter in OSC 8 sequences (#29840)
- 0231265c8c tui: skip TUI in ui_rgb_attached (#29096)
- 8b8096500d tutor: incorrect lines marked as correct #29833
- 31745b17e6 types: add narrower vim.validate types
- 44410d063a types: add some vim.fn type annotations
- b813075b8a types: do not mark unstable API as private
- e947f226be types: use vararg return type annotation
- a1906c23dd ui: Windows :detach is opt-in
- 594c7f3d77 ui: avoid ambiguity about last chunk when flushing halfway (#29718)
- 216ec73972 ui: avoid redundant ext_cmdline events (#32237)
- 6cdcac4492 ui: clamp 'cmdheight' for other tabpages on screen resize (#31419)
- 318c0415d5 ui: correctly pass metadata to get_node_text #30222
- 7eba016c86 ui: ensure screen update before waiting for input #30576
- 5b6477be45 ui: flush ext_cmdline events before doing cmdpreview #27950
- 6e4df18b45 ui: no fast context for prompt message kinds #31224
- 6b8c56c7f6 ui: schedule UI detach (#32827)
- b66106a46c ui: superfluous showmode / excessive grid_cursor_goto #29089
- d1fd674df3 ui: update title in more cases (#31508)
- 442d338cb5 uri: uri_encode encodes brackets incorrectly for RFC2732 #31284
- d049752e45 version: fix vim.version().prerelease
- 8bdfc2ab2b version: return nil with empty string
- 6401b433f7 vim.fs: default to follow=false #32859
- 47e6b2233f vim.fs: dirname() returns "." on mingw/msys2 #30480
- 0bef3b911c vim.fs: joinpath() does not normalize slashes on Windows #31782
- 6dc0eb9f41 vim.fs.abspath: correctly handle UNC paths
- a8ace2c58a vim.fs.normalize: normalize case for windows drive letter
- 4c0d18c197 vim.iter: enable optimizations for arrays (lists with holes) (#28781)
- 734dba04d1 vim.system: close pipe handles after process handle
- 4e130c1ee4 vim.system: invalid MAX_TIMEOUT for 32-bit systems #31638
- ad3472e291 vim.system: resolve executable paths on windows
- 33464189bc vim.text: handle very long strings (#30075)
- 4cff418564 vim.text: remove assert from vim.text.hexdecode
- d338ec9cb2 vim.ui.open: prefer xdg-open on WSL #30302
- 8bf79bd13c vim.wo: never allow non-zero bufnr
- 453f2c52d2 vim_snprintf: special-case handling of binary format
- 32e128f209 watch: exclude .git when using inotifywait (#29914)
- 9e23b4e185 watch: ignore nonexistent paths (ENOENT)
- a18652ed61 win-msi: add bin to PATH per-machine after installation (#29099)
- 88f07d6ca4 win-msi: set installer scope to machine #29895
- 4f9311b759 window: making float with title/footer non-float leaks memory (#30551)
- 7b71fdbc1e window: respect hide flag of float windows when switching (#30507)
- 59da82abd9 wininfo: when freeing windows, free the lowest priority wininfo

PERFORMANCE
--------------------------------------------------------------------------------
- 48251134ee add fast path to vim.validate (#28977)
- 3abd7ed4a4 consider only active decorations when drawing lines
- 8d2ee542a8 decor: join predicates and matches cache
- 48e3ac60c6 diagnostics: cache line diagnostics when `current_line` is set #32288
- b8ddd3b6bb events: remove unnecessary loop in event_nr2name() (#32777)
- 15f2da55a8 events: use hashy for event name lookup (#32802)
- abf4b65a51 filetype: cache (more) pattern data during "add" time
- f61efe3fe7 filetype: implement parent pattern pre-matching (#29660)
- ff575b3886 filetype: optimize internal data structures
- dc04ef2a20 filetype: skip contents check in `match()` if there is no contents (#29596)
- 12d4caa9d3 keycodes: use hashy for string lookup
- f8fc6cb157 loader: reduce calls to Loader.cache_file
- 138a93a057 lsp: avoid repeated table lookup in completion.enable
- 7342e6b00d lsp: do not apply semantic tokens to folded lines
- c85d15e0d5 lsp: don't construct potentially expensive strings
- cc1f2d2ca6 lsp: don't copy completion items in filter pass
- 3e855d533f lsp: use faster version of str_byteindex
- 000129201c mouse: only generate <MouseMove> for a new cell positon (#31103)
- 3fdc430241 treesitter: cache queries strongly
- b192d58284 treesitter: calculate folds asynchronously
- c6abc97006 treesitter: do not use tree cursors with a small lifetime
- cbad2c6628 treesitter: don't block when finding injection ranges
- d9ee0d2984 treesitter: don't fetch parser for each fold line
- 562056c875 treesitter: only search for injections within the parse range
- c57a85e0ed treesitter: remove unnecessary foldexpr loop
- 64847fbdc9 treesitter: use `child_containing_descendant()` in `is_ancestor()`
- 4b02916334 treesitter: use child_containing_descendant() in has-ancestor? (#28512)
- 3f3e4837d5 validate: use lighter version
- 99b5ffd688 vim.text: use lookup table implementation for hex encoding (#30080)

BUILD
--------------------------------------------------------------------------------
- 104800ce2e "popcount" name conflict on NetBSD #28983
- 198a952c13 add luals check
- ef8067a19d add quotes around `CMAKE_GENERATOR` variable
- 32e16cb0b6 add utf8proc as dependency
- b213f5169c allow comment after #include for required header (#29722)
- 382eb878bc bump lua dev dependencies
- 1d815acd78 bump minimum cmake version to 3.16
- 5284a2a793 bump unibilium to v2.1.2
- ac5a6d9ff5 fix RelWithDebInfo optimization flags #31802
- 7c65224257 fix lint error on macos
- 046e0956ee fix or silence new clang-tidy warnings
- 5719f2b91a fix uncrustify install in nix devShell (#33020)
- 4a0ee22e77 make makefile work on msys
- 4ee65484b1 make makefile work on windows
- 1b90f4a9c4 mark CMake variables advanced #31412
- 0f24b0826a move all generator scripts to `src/gen/`
- e5ff302033 remove -O2 from gen_cflags
- d74c74aae3 remove `lintcommit` from `lint` target
- 573bcb2aaf remove enforcement of cmake build type
- 0e9c92a900 remove nix flakes (#28863)
- f09f5c45fa reuse code for deps.txt for both deps and main build
- e1dc824b7e set luals checklevel to Hint #32392
- cac86e9b4c silence "po" noise #30469
- 07b14c8e2e specify POST_BUILD when using add_custom_command
- e83ce331da use treesitter's CMakeLists.txt
- e268fcbdaa work around bug in make when PATH includes cmake as dir
- b288fa8d62 bump_deps: abort if archive doesn't exist
- 7ead328a48 cjson: sync with upstream (#32114)
- 0e2f92ed79 clint: make NOLINT work with header checks (#31281)
- 327110ff8c cmake: remove unnecessary policy code
- 535c2f8658 contrib: add zsh completion (#32617)
- 51d85f7ea5 deps: drop unused bundled bash, python parsers and queries
- 9216bc927c deps: fix formatc target on MSVC
- b3641b8008 deps: remove libtermkey dependency
- 1247684ae1 deps: remove msgpack-c dependency
- fa79a8ad6d deps: vendor libvterm at v0.3.3
- c614969570 docs: update CSS #28896
- 0a087f2073 generator: add dependencies on hashy (#32796)
- e178331488 lpeg: search for lpeg.so on MacOS
- 7e099cf3eb macos: disable deduplication in link step
- f4d9a2983a release.sh: fix hang when generating docs (#33026)
- b923fcbaf0 vim-patch.sh: don't ignore changes to version*.txt (#29425)
- 7aaa4a51b7 vim-patch.sh: include commit subject #28767
- 3146433190 vim-patch.sh: use 7 hex digits for runtime patch file name (#29940)
2025-03-26 14:48:09 +01:00

4686 lines
172 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

*lua.txt* Nvim
NVIM REFERENCE MANUAL
Lua engine *lua* *Lua*
Type |gO| to see the table of contents.
==============================================================================
INTRODUCTION *lua-intro*
The Lua 5.1 script engine is builtin and always available. Try this command to
get an idea of what lurks beneath: >vim
:lua vim.print(package.loaded)
Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the
"editor stdlib" (|vimscript-functions| + |Ex-commands|) and the |API|, all of
which can be used from Lua code (|lua-vimscript| |vim.api|). These three
namespaces form the Nvim programming interface.
Lua plugins and user config are automatically discovered and loaded, just like
Vimscript. See |lua-guide| for practical guidance.
You can also run Lua scripts from your shell using the |-l| argument: >
nvim -l foo.lua [args...]
<
*lua-compat*
Lua 5.1 is the permanent interface for Nvim Lua. Plugins should target Lua 5.1
as specified in |luaref|; later versions (which are essentially different,
incompatible, dialects) are not supported. This includes extensions such as
`goto` that some Lua 5.1 interpreters like LuaJIT may support.
*lua-luajit*
While Nvim officially only requires Lua 5.1 support, it should be built with
LuaJIT or a compatible fork on supported platforms for performance reasons.
LuaJIT also comes with useful extensions such as `ffi`, |lua-profile|, and
enhanced standard library functions; these cannot be assumed to be available,
and Lua code in |init.lua| or plugins should check the `jit` global variable
before using them: >lua
if jit then
-- code for luajit
else
-- code for plain lua 5.1
end
<
One exception is the LuaJIT `bit` extension, which is always available: when
built with PUC Lua, Nvim includes a fallback implementation which provides
`require("bit")`. See |lua-bit|.
*lua-profile*
If Nvim is built with LuaJIT, Lua code can be profiled via >lua
-- Start a profiling session:
require('jit.p').start('ri1', '/tmp/profile')
-- Perform arbitrary tasks (use plugins, scripts, etc.) ...
-- Stop the session. Profile is written to /tmp/profile.
require('jit.p').stop()
See https://luajit.org/ext_profiler.html or the `p.lua` source for details: >
:lua vim.cmd.edit(package.searchpath('jit.p', package.path))
==============================================================================
LUA CONCEPTS AND IDIOMS *lua-concepts*
Lua is very simple, and _consistent_: while there are some quirks, once you
internalize those quirks, everything works the same everywhere. Scopes
(closures) in particular are very consistent, unlike JavaScript or most other
languages.
Lua has three fundamental mechanisms—one for "each major aspect of
programming": tables, closures, and coroutines.
https://www.lua.org/doc/cacm2018.pdf
- Tables are the "object" or container datastructure: they represent both
lists and maps, you can extend them to represent your own datatypes and
change their behavior using |metatable|s (like Python's "datamodel").
- EVERY scope in Lua is a closure: a function is a closure, a module is
a closure, a `do` block (|lua-do|) is a closure--and they all work the same.
A Lua module is literally just a big closure discovered on the "path"
(where your modules are found: |package.cpath|).
- Stackful coroutines enable cooperative multithreading, generators, and
versatile control for both Lua and its host (Nvim).
*lua-error-handling*
Lua functions may throw |lua-errors| for exceptional (unexpected) failures,
which you can handle with |pcall()|.
*lua-result-or-message*
When failure is normal and expected, it's idiomatic to return `nil` which
signals to the caller that failure is not "exceptional" and must be handled.
This "result-or-message" pattern is expressed as the multi-value return type
`any|nil,nil|string`, or in LuaLS notation: >
---@return any|nil # result on success, nil on failure.
---@return nil|string # nil on success, error message on failure.
<
Examples of the "result-or-message" pattern:
- |vim.ui.open()|
- |io.open()|
- |luv-error-handling|
When a caller can't proceed on failure, it's idiomatic to `assert()` the
"result-or-message" result: >lua
local value = assert(fn())
Guidance: use the "result-or-message" pattern for...
- Functions where failure is expected, especially when communicating with the
external world. E.g. HTTP requests or LSP requests often fail because of
server problems, even if the caller did everything right.
- Functions that return a value, e.g. Foo:new().
- When there is a list of known error codes which can be returned as a third
value (like |luv-error-handling|).
<
*iterator*
An iterator is just a function that can be called repeatedly to get the "next"
value of a collection (or any other |iterable|). This interface is expected by
|for-in| loops, produced by |pairs()|, supported by |vim.iter|, etc.
https://www.lua.org/pil/7.1.html
*iterable*
An "iterable" is anything that |vim.iter()| can consume: tables, dicts, lists,
iterator functions, tables implementing the |__call()| metamethod, and
|vim.iter()| objects.
*list-iterator*
Iterators on |lua-list| tables have a "middle" and "end", whereas iterators in
general may be logically infinite. Therefore some |vim.iter| operations (e.g.
|Iter:rev()|) make sense only on list-like tables (which are finite by
definition).
*lua-function-call*
Lua functions can be called in multiple ways. Consider the function: >lua
local foo = function(a, b)
print("A: ", a)
print("B: ", b)
end
The first way to call this function is: >lua
foo(1, 2)
-- ==== Result ====
-- A: 1
-- B: 2
This way of calling a function is familiar from most scripting languages. In
Lua, any missing arguments are passed as `nil`, and extra parameters are
silently discarded. Example: >lua
foo(1)
-- ==== Result ====
-- A: 1
-- B: nil
<
*kwargs*
When calling a function, you can omit the parentheses if the function takes
exactly one string literal (`"foo"`) or table literal (`{1,2,3}`). The latter
is often used to mimic "named parameters" ("kwargs" or "keyword args") as in
languages like Python and C#. Example: >lua
local func_with_opts = function(opts)
local will_do_foo = opts.foo
local filename = opts.filename
-- ...
end
func_with_opts { foo = true, filename = "hello.world" }
<
There's nothing special going on here except that parentheses are implicitly
added. But visually, this small bit of sugar gets reasonably close to a
"keyword args" interface.
*lua-regex*
Lua intentionally does not support regular expressions, instead it has limited
|lua-patterns| which avoid the performance pitfalls of extended regex. Lua
scripts can also use Vim regex via |vim.regex()|.
Examples: >lua
print(string.match("foo123bar123", "%d+"))
-- 123
print(string.match("foo123bar123", "[^%d]+"))
-- foo
print(string.match("foo123bar123", "[abc]+"))
-- ba
print(string.match("foo.bar", "%.bar"))
-- .bar
==============================================================================
IMPORTING LUA MODULES *lua-module-load*
Modules are searched for under the directories specified in 'runtimepath', in
the order they appear. Any "." in the module name is treated as a directory
separator when searching. For a module `foo.bar`, each directory is searched
for `lua/foo/bar.lua`, then `lua/foo/bar/init.lua`. If no files are found,
the directories are searched again for a shared library with a name matching
`lua/foo/bar.?`, where `?` is a list of suffixes (such as `so` or `dll`) derived from
the initial value of |package.cpath|. If still no files are found, Nvim falls
back to Lua's default search mechanism. The first script found is run and
`require()` returns the value returned by the script if any, else `true`.
The return value is cached after the first call to `require()` for each module,
with subsequent calls returning the cached value without searching for, or
executing any script. For further details see |require()|.
For example, if 'runtimepath' is `foo,bar` and |package.cpath| was
`./?.so;./?.dll` at startup, `require('mod')` searches these paths in order
and loads the first module found ("first wins"): >
foo/lua/mod.lua
foo/lua/mod/init.lua
bar/lua/mod.lua
bar/lua/mod/init.lua
foo/lua/mod.so
foo/lua/mod.dll
bar/lua/mod.so
bar/lua/mod.dll
<
*lua-package-path*
Nvim automatically adjusts |package.path| and |package.cpath| according to the
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 |package.cpath| (defined at compile-time or derived from
`$LUA_CPATH` / `$LUA_INIT`) 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 its 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 a 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 a `/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: >vim
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.
==============================================================================
COMMANDS *lua-commands*
These commands execute a Lua chunk from either the command line (:lua, :luado)
or a file (:luafile) on the given line [range]. As always in Lua, each chunk
has its own scope (closure), so only global variables are shared between
command calls. The |lua-stdlib| modules, user modules, and anything else on
|package.path| are available.
The Lua print() function redirects its output to the Nvim message area, with
arguments separated by " " (space) instead of "\t" (tab).
*:lua=* *:lua*
:lua {chunk}
Executes Lua chunk {chunk}. If {chunk} starts with "=" the rest of the
chunk is evaluated as an expression and printed. `:lua =expr` and `:=expr`
are equivalent to `:lua print(vim.inspect(expr))`.
Examples: >vim
:lua vim.api.nvim_command('echo "Hello, Nvim!"')
< To see the Lua version: >vim
:lua print(_VERSION)
< To see the LuaJIT version: >vim
:lua =jit.version
<
:{range}lua
Executes buffer lines in {range} as Lua code. Unlike |:source|, this
always treats the lines as Lua code.
Example: select the following code and type ":lua<Enter>" to execute it: >lua
print(string.format(
'unix time: %s', os.time()))
<
*:lua-heredoc*
:lua << [trim] [{endmarker}]
{script}
{endmarker}
Executes Lua script {script} from within Vimscript. You can omit
[endmarker] after the "<<" and use a dot "." after {script} (similar to
|:append|, |:insert|). Refer to |:let-heredoc| for more information.
Example: >vim
function! CurrentLineInfo()
lua << EOF
local linenr = vim.api.nvim_win_get_cursor(0)[1]
local curline = vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1]
print(string.format('Line [%d] has %d bytes', linenr, #curline))
EOF
endfunction
<
Note that the `local` variables will disappear when the block finishes.
But not globals.
*:luado*
:[range]luado {body}
Executes Lua chunk "function(line, linenr) {body} end" for each buffer
line in [range], where `line` is the current line text (without <EOL>),
and `linenr` is the current line number. If the function returns a string
that becomes the text of the corresponding buffer line. Default [range] is
the whole file: "1,$".
Examples: >vim
: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*
:luafile {file}
Execute Lua script in {file}.
The whole argument is used as the filename (like |:edit|), spaces do not
need to be escaped. Alternatively you can |:source| Lua files.
Examples: >vim
:luafile script.lua
:luafile %
<
==============================================================================
luaeval() *lua-eval*
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: >lua
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 Vimscript types. If a Lua string contains a NUL byte, it will be
converted to a |Blob|. Conversion of other Lua types is an error.
The magic global "_A" contains the second argument to luaeval().
Example: >vim
:echo luaeval('_A[1] + _A[2]', [40, 2])
" 42
:echo luaeval('string.match(_A, "[a-z]+")', 'XYXfoo123')
" foo
<
*lua-table-ambiguous*
Lua tables are used as both dictionaries and lists, so it is impossible to
decide whether empty table is a list or a dict. Also Lua does not have integer
numbers. To disambiguate these cases, we define:
*lua-list*
0. Empty table is a list. Use |vim.empty_dict()| to represent empty dict.
1. Table with N consecutive (no `nil` values, aka "holes") integer keys 1…N is
a list. See also |list-iterator|.
*lua-dict*
2. Table with string keys, none of which contains NUL byte, is a dict.
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.array}` is converted to an empty list. As well
as `{[vim.type_idx]=vim.types.array, [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: >vim
: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` is converted ("marshalled") from Vimscript
to Lua, so changes to Lua containers do not affect values in Vimscript. Return
value is also always converted. When converting, |msgpack-special-dict|s are
treated specially.
==============================================================================
Vimscript v:lua interface *v:lua-call*
From Vimscript the special `v:lua` prefix can be used to call Lua functions
which are global or accessible from global tables. The expression >vim
call v:lua.func(arg1, arg2)
is equivalent to the Lua chunk >lua
return func(...)
where the args are converted to Lua values. The expression >vim
call v:lua.somemod.func(args)
is equivalent to the Lua chunk >lua
return somemod.func(...)
Lua module functions can be accessed like: >vim
call v:lua.require'mypack'.func(arg1, arg2)
call v:lua.require'mypack.submod'.func(arg1, arg2)
Note: Only single quote form without parens is allowed. Using
`require"mypack"` or `require('mypack')` as a prefix does NOT work.
You can use `v:lua` in "func" options like 'tagfunc', 'omnifunc', etc.
For example consider the following Lua omnifunc handler: >lua
function mymod.omnifunc(findstart, base)
if findstart == 1 then
return 0
else
return {'stuff', 'steam', 'strange things'}
end
end
-- Note: The module ("mymod") must be a Lua global, or use require() as
-- shown above to access it from a package.
vim.bo[buf].omnifunc = 'v:lua.mymod.omnifunc'
You can also use `v:lua` to call Lua functions as Vimscript |method|s: >vim
:eval arg1->v:lua.somemod.func(arg2)
<
Note: `v:lua` without a call is not allowed in a Vimscript expression:
|Funcref|s cannot represent Lua functions. The following are errors: >vim
let g:Myvar = v:lua.myfunc " Error
call SomeFunc(v:lua.mycallback) " Error
let g:foo = v:lua " Error
let g:foo = v:['lua'] " Error
<
==============================================================================
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: >vim
:lua vim.print(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: >vim
:help vim.deepcopy()
Note that underscore-prefixed functions (e.g. "_os_proc_children") are
internal/private and must not be used by plugins.
------------------------------------------------------------------------------
VIM.UV *lua-loop* *vim.uv*
`vim.uv` exposes the "luv" Lua bindings for the libUV library that Nvim uses
for networking, filesystem, and process management, see |luvref.txt|.
In particular, it allows interacting with the main Nvim |luv-event-loop|.
*E5560* *lua-loop-callbacks*
It is an error to directly invoke `vim.api` functions (except |api-fast|) in
`vim.uv` callbacks. For example, this is an error: >lua
local timer = vim.uv.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: >lua
local timer = vim.uv.new_timer()
timer:start(1000, 0, vim.schedule_wrap(function()
vim.api.nvim_command('echomsg "test"')
end))
<
(For one-shot timers, see |vim.defer_fn()|, which automatically adds the
wrapping.)
Example: repeating timer
1. Save this code to a file.
2. Execute it with ":luafile %". >lua
-- Create a timer handle (implementation detail: uv_timer_t).
local timer = vim.uv.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 *watch-file*
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|). >lua
local w = vim.uv.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>'))")
<
*inotify-limitations*
When on Linux you may need to increase the maximum number of `inotify` watches
and queued events as the default limit can be too low. To increase the limit,
run: >bash
sysctl fs.inotify.max_user_watches=494462
<
This will increase the limit to 494462 watches and queued events. These lines
can be added to `/etc/sysctl.conf` to make the changes persistent.
Note that each watch is a structure in the Kernel, thus available memory is
also a bottleneck for using inotify. In fact, a watch can take up to 1KB of
space. This means a million watches could result in 1GB of extra RAM usage.
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"): >lua
local function create_server(host, port, on_connect)
local server = vim.uv.new_tcp()
server:bind(host, port)
server:listen(128, function(err)
assert(not err, err) -- Check for errors.
local sock = vim.uv.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)
<
Multithreading *lua-loop-threading*
Plugins can perform work in separate (os-level) threads using the threading
APIs in luv, for instance `vim.uv.new_thread`. Each thread has its own
separate Lua interpreter state, with no access to Lua globals on the main
thread. Neither can the editor state (buffers, windows, etc) be directly
accessed from threads.
A subset of the `vim.*` stdlib is available in threads, including:
- `vim.uv` with a separate event loop per thread.
- `vim.mpack` and `vim.json` (useful for serializing messages between threads)
- `require` in threads can use Lua packages from the global |package.path|
- `print()` and `vim.inspect`
- `vim.diff`
- Most utility functions in `vim.*` that work with pure Lua values, like
`vim.split`, `vim.tbl_*`, `vim.list_*`, etc.
- `vim.is_thread()` returns true from a non-main thread.
==============================================================================
VIM.HL *vim.hl*
vim.hl.on_yank({opts}) *vim.hl.on_yank()*
Highlight the yanked text during a |TextYankPost| event.
Add the following to your `init.vim`: >vim
autocmd TextYankPost * silent! lua vim.hl.on_yank {higroup='Visual', timeout=300}
<
Parameters: ~
• {opts} (`table?`) Optional parameters
• higroup highlight group for yanked region (default
"IncSearch")
• timeout time in ms before highlight is cleared (default 150)
• on_macro highlight when executing macro (default false)
• on_visual highlight when yanking visual selection (default
true)
• event event structure (default vim.v.event)
• priority integer priority (default
|vim.hl.priorities|`.user`)
vim.hl.priorities *vim.hl.priorities*
Table with default priorities used for highlighting:
• `syntax`: `50`, used for standard syntax highlighting
• `treesitter`: `100`, used for treesitter-based highlighting
• `semantic_tokens`: `125`, used for LSP semantic token highlighting
• `diagnostics`: `150`, used for code analysis such as diagnostics
• `user`: `200`, used for user-triggered highlights such as LSP document
symbols or `on_yank` autocommands
*vim.hl.range()*
vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
Apply highlight group to range of text.
Parameters: ~
• {bufnr} (`integer`) Buffer number to apply highlighting to
• {ns} (`integer`) Namespace to add highlight to
• {higroup} (`string`) Highlight group to use for highlighting
• {start} (`integer[]|string`) Start of region as a (line, column)
tuple or string accepted by |getpos()|
• {finish} (`integer[]|string`) End of region as a (line, column)
tuple or string accepted by |getpos()|
• {opts} (`table?`) A table with the following fields:
• {regtype}? (`string`, default: `'v'` i.e. charwise) Type
of range. See |getregtype()|
• {inclusive}? (`boolean`, default: `false`) Indicates
whether the range is end-inclusive
• {priority}? (`integer`, default:
`vim.hl.priorities.user`) Highlight priority
• {timeout}? (`integer`, default: -1 no timeout) Time in ms
before highlight is cleared
==============================================================================
VIM.DIFF *vim.diff*
vim.diff({a}, {b}, {opts}) *vim.diff()*
Run diff on strings {a} and {b}. Any indices returned by this function,
either directly or via callback arguments, are 1-based.
Examples: >lua
vim.diff('a\n', 'b\nc\n')
-- =>
-- @@ -1 +1,2 @@
-- -a
-- +b
-- +c
vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
-- =>
-- {
-- {1, 1, 1, 2}
-- }
<
Parameters: ~
• {a} (`string`) First string to compare
• {b} (`string`) Second string to compare
• {opts} (`table?`) Optional parameters:
• {on_hunk}?
(`fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer?`)
Invoked for each hunk in the diff. Return a negative number
to cancel the callback for any remaining hunks. Arguments:
• `start_a` (`integer`): Start line of hunk in {a}.
• `count_a` (`integer`): Hunk size in {a}.
• `start_b` (`integer`): Start line of hunk in {b}.
• `count_b` (`integer`): Hunk size in {b}.
• {result_type}? (`'unified'|'indices'`, default: `'unified'`)
Form of the returned diff:
• `unified`: String in unified format.
• `indices`: Array of hunk locations. Note: This option is
ignored if `on_hunk` is used.
• {linematch}? (`boolean|integer`) Run linematch on the
resulting hunks from xdiff. When integer, only hunks upto
this size in lines are run through linematch. Requires
`result_type = indices`, ignored otherwise.
• {algorithm}? (`'myers'|'minimal'|'patience'|'histogram'`,
default: `'myers'`) Diff algorithm to use. Values:
• `myers`: the default algorithm
• `minimal`: spend extra time to generate the smallest
possible diff
• `patience`: patience diff algorithm
• `histogram`: histogram diff algorithm
• {ctxlen}? (`integer`) Context length
• {interhunkctxlen}? (`integer`) Inter hunk context length
• {ignore_whitespace}? (`boolean`) Ignore whitespace
• {ignore_whitespace_change}? (`boolean`) Ignore whitespace
change
• {ignore_whitespace_change_at_eol}? (`boolean`) Ignore
whitespace change at end-of-line.
• {ignore_cr_at_eol}? (`boolean`) Ignore carriage return at
end-of-line
• {ignore_blank_lines}? (`boolean`) Ignore blank lines
• {indent_heuristic}? (`boolean`) Use the indent heuristic for
the internal diff library.
Return: ~
(`string|integer[][]?`) See {opts.result_type}. `nil` if
{opts.on_hunk} is given.
==============================================================================
VIM.MPACK *vim.mpack*
This module provides encoding and decoding of Lua objects to and from
msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
vim.mpack.decode({str}) *vim.mpack.decode()*
Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
Parameters: ~
• {str} (`string`)
Return: ~
(`any`)
vim.mpack.encode({obj}) *vim.mpack.encode()*
Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
Parameters: ~
• {obj} (`any`)
Return: ~
(`string`)
==============================================================================
VIM.JSON *vim.json*
This module provides encoding and decoding of Lua objects to and from
JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
vim.json.decode({str}, {opts}) *vim.json.decode()*
Decodes (or "unpacks") the JSON-encoded {str} to a Lua object.
• Decodes JSON "null" as |vim.NIL| (controllable by {opts}, see below).
• Decodes empty object as |vim.empty_dict()|.
• Decodes empty array as `{}` (empty Lua table).
Example: >lua
vim.print(vim.json.decode('{"bar":[],"foo":{},"zub":null}'))
-- { bar = {}, foo = vim.empty_dict(), zub = vim.NIL }
<
Parameters: ~
• {str} (`string`) Stringified JSON data.
• {opts} (`table<string,any>?`) Options table with keys:
• luanil: (table) Table with keys:
• object: (boolean) When true, converts `null` in JSON
objects to Lua `nil` instead of |vim.NIL|.
• array: (boolean) When true, converts `null` in JSON arrays
to Lua `nil` instead of |vim.NIL|.
Return: ~
(`any`)
vim.json.encode({obj}, {opts}) *vim.json.encode()*
Encodes (or "packs") Lua object {obj} as JSON in a Lua string.
Parameters: ~
• {obj} (`any`)
• {opts} (`table<string,any>?`) Options table with keys:
• escape_slash: (boolean) (default false) Escape slash
characters "/" in string values.
Return: ~
(`string`)
==============================================================================
VIM.BASE64 *vim.base64*
vim.base64.decode({str}) *vim.base64.decode()*
Decode a Base64 encoded string.
Parameters: ~
• {str} (`string`) Base64 encoded string
Return: ~
(`string`) Decoded string
vim.base64.encode({str}) *vim.base64.encode()*
Encode {str} using Base64.
Parameters: ~
• {str} (`string`) String to encode
Return: ~
(`string`) Encoded string
==============================================================================
VIM.SPELL *vim.spell*
vim.spell.check({str}) *vim.spell.check()*
Check {str} for spelling errors. Similar to the Vimscript function
|spellbadword()|.
Note: The behaviour of this function is dependent on: 'spelllang',
'spellfile', 'spellcapcheck' and 'spelloptions' which can all be local to
the buffer. Consider calling this with |nvim_buf_call()|.
Example: >lua
vim.spell.check("the quik brown fox")
-- =>
-- {
-- {'quik', 'bad', 5}
-- }
<
Parameters: ~
• {str} (`string`)
Return: ~
(`[string, 'bad'|'rare'|'local'|'caps', integer][]`) List of tuples
with three items:
• The badly spelled word.
• The type of the spelling error: "bad" spelling mistake "rare" rare
word "local" word only valid in another region "caps" word should
start with Capital
• The position in {str} where the word begins.
==============================================================================
VIM *vim.builtin*
vim.api.{func}({...}) *vim.api*
Invokes Nvim |API| function {func} with arguments {...}.
Example: call the "nvim_get_current_line()" API function: >lua
print(tostring(vim.api.nvim_get_current_line()))
vim.NIL *vim.NIL*
Special value representing NIL in |RPC| and |v:null| in Vimscript
conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
table representing a Dictionary or Array, because it is treated as
missing: `{"foo", nil}` is the same as `{"foo"}`.
vim.type_idx *vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the values from
|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 *vim.val_idx*
Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >lua
{
[vim.type_idx] = vim.types.float,
[vim.val_idx] = 1.0,
}
< See also |vim.type_idx| and |lua-special-tbl|.
vim.types *vim.types*
Table with possible values for |vim.type_idx|. Contains two sets of
key-value pairs: first maps possible values for |vim.type_idx| to
human-readable strings, second maps human-readable type names to values
for |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.
*log_levels* *vim.log.levels*
Log levels are one of the values defined in `vim.log.levels`:
vim.log.levels.DEBUG
vim.log.levels.ERROR
vim.log.levels.INFO
vim.log.levels.TRACE
vim.log.levels.WARN
vim.log.levels.OFF
vim.empty_dict() *vim.empty_dict()*
Creates a special empty table (marked with a metatable), which Nvim
converts to an empty dictionary when translating Lua values to Vimscript
or API types. Nvim by default converts an empty table `{}` without this
metatable to an list/array.
Note: If numeric keys are present in the table, Nvim ignores the metatable
marker and converts the dict to a list/array anyway.
Return: ~
(`table`)
vim.iconv({str}, {from}, {to}) *vim.iconv()*
The result is a String, which is the text {str} converted from encoding
{from} to encoding {to}. When the conversion fails `nil` is returned. When
some characters could not be converted they are replaced with "?". The
encoding names are whatever the iconv() library function can accept, see
":Man 3 iconv".
Parameters: ~
• {str} (`string`) Text to convert
• {from} (`string`) Encoding of {str}
• {to} (`string`) Target encoding
Return: ~
(`string?`) Converted string if conversion succeeds, `nil` otherwise.
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.rpcnotify({channel}, {method}, {...}) *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|.
Parameters: ~
• {channel} (`integer`)
• {method} (`string`)
• {...} (`any?`)
vim.rpcrequest({channel}, {method}, {...}) *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
Parameters: ~
• {channel} (`integer`)
• {method} (`string`)
• {...} (`any?`)
vim.schedule({fn}) *vim.schedule()*
Schedules {fn} to be invoked soon by the main event-loop. Useful to avoid
|textlock| or other temporary restrictions.
Parameters: ~
• {fn} (`fun()`)
vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
Gets the distance (in bytes) from the last byte of the codepoint
(character) that {index} points to.
Examples: >lua
-- The character 'æ' is stored as the bytes '\xc3\xa6' (using UTF-8)
-- Returns 0 because the index is pointing at the last byte of a character
vim.str_utf_end('æ', 2)
-- Returns 1 because the index is pointing at the penultimate byte of a character
vim.str_utf_end('æ', 1)
<
Parameters: ~
• {str} (`string`)
• {index} (`integer`)
Return: ~
(`integer`)
vim.str_utf_pos({str}) *vim.str_utf_pos()*
Gets a list of the starting byte positions of each UTF-8 codepoint in the
given string.
Embedded NUL bytes are treated as terminating the string.
Parameters: ~
• {str} (`string`)
Return: ~
(`integer[]`)
vim.str_utf_start({str}, {index}) *vim.str_utf_start()*
Gets the distance (in bytes) from the starting byte of the codepoint
(character) that {index} points to.
The result can be added to {index} to get the starting byte of a
character.
Examples: >lua
-- The character 'æ' is stored as the bytes '\xc3\xa6' (using UTF-8)
-- Returns 0 because the index is pointing at the first byte of a character
vim.str_utf_start('æ', 1)
-- Returns -1 because the index is pointing at the second byte of a character
vim.str_utf_start('æ', 2)
<
Parameters: ~
• {str} (`string`)
• {index} (`integer`)
Return: ~
(`integer`)
vim.stricmp({a}, {b}) *vim.stricmp()*
Compares strings case-insensitively.
Parameters: ~
• {a} (`string`)
• {b} (`string`)
Return: ~
(`0|1|-1`) if strings are equal, {a} is greater than {b} or {a} is
lesser than {b}, respectively.
vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
WARNING: This feature is experimental/unstable.
Subscribe to |ui-events|, similar to |nvim_ui_attach()| but receive events
in a Lua callback. Used to implement screen elements like popupmenu or
message handling in Lua.
{options} is a dict with one or more `ext_…` |ui-option|s set to true to
enable events for the respective UI element.
{callback} receives event name plus additional parameters. See
|ui-popupmenu| and the sections below for event format for respective
events.
Callbacks for `msg_show` events are executed in |api-fast| context;
showing the message should be scheduled.
Excessive errors inside the callback will result in forced detachment.
WARNING: This api is considered experimental. Usability will vary for
different screen elements. In particular `ext_messages` behavior is
subject to further changes and usability improvements. This is expected to
be used to handle messages when setting 'cmdheight' to zero (which is
likewise experimental).
Example (stub for a |ui-popupmenu| implementation): >lua
ns = vim.api.nvim_create_namespace('my_fancy_pum')
vim.ui_attach(ns, {ext_popupmenu=true}, function(event, ...)
if event == 'popupmenu_show' then
local items, selected, row, col, grid = ...
print('display pum ', #items)
elseif event == 'popupmenu_select' then
local selected = ...
print('selected', selected)
elseif event == 'popupmenu_hide' then
print('FIN')
end
end)
<
Parameters: ~
• {ns} (`integer`)
• {options} (`table<string, any>`)
• {callback} (`fun()`)
vim.ui_detach({ns}) *vim.ui_detach()*
Detach a callback previously attached with |vim.ui_attach()| for the given
namespace {ns}.
Parameters: ~
• {ns} (`integer`)
vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
Wait for {time} in milliseconds until {callback} returns `true`.
Executes {callback} immediately and at approximately {interval}
milliseconds (default 200). Nvim still processes other events during this
time.
Cannot be called while in an |api-fast| event.
Examples: >lua
---
-- Wait for 100 ms, allowing other events to process
vim.wait(100, function() end)
---
-- Wait for 100 ms or until global variable set.
vim.wait(100, function() return vim.g.waiting_for_var end)
---
-- Wait for 1 second or until global variable set, checking every ~500 ms
vim.wait(1000, function() return vim.g.waiting_for_var end, 500)
---
-- Schedule a function to set a value in 100ms
vim.defer_fn(function() vim.g.timer_result = true end, 100)
-- Would wait ten seconds if results blocked. Actually only waits 100 ms
if vim.wait(10000, function() return vim.g.timer_result end) then
print('Only waiting a little bit of time!')
end
<
Parameters: ~
• {time} (`integer`) Number of milliseconds to wait
• {callback} (`fun(): boolean?`) Optional callback. Waits until
{callback} returns true
• {interval} (`integer?`) (Approximate) number of milliseconds to wait
between polls
• {fast_only} (`boolean?`) If true, only |api-fast| events will be
processed.
Return (multiple): ~
(`boolean`)
(`-1|-2?`)
• If {callback} returns `true` during the {time}: `true, nil`
• If {callback} never returns `true` during the {time}: `false, -1`
• If {callback} is interrupted during the {time}: `false, -2`
• If {callback} errors, the error is raised.
==============================================================================
LUA-VIMSCRIPT BRIDGE *lua-vimscript*
Nvim Lua provides an interface or "bridge" to Vimscript variables and
functions, and editor commands and options.
Objects passed over this bridge are COPIED (marshalled): there are no
"references". |lua-guide-variables| For example, using `vim.fn.remove()` on a
Lua list copies the list object to Vimscript and does NOT modify the Lua list: >lua
local list = { 1, 2, 3 }
vim.fn.remove(list, 0)
vim.print(list) --> "{ 1, 2, 3 }"
<
vim.call({func}, {...}) *vim.call()*
Invokes |vim-function| or |user-function| {func} with arguments {...}.
See also |vim.fn|.
Equivalent to: >lua
vim.fn[func]({...})
<
vim.cmd({command})
See |vim.cmd()|.
vim.fn.{func}({...}) *vim.fn*
Invokes |vim-function| or |user-function| {func} with arguments {...}.
To call autoload functions, use the syntax: >lua
vim.fn['some#function']({...})
<
Unlike vim.api.|nvim_call_function()| this converts directly between Vim
objects and Lua objects. If the Vim function returns a float, it will be
represented directly as a Lua number. Empty lists and dictionaries both
are represented by an empty table.
Note: |v:null| values as part of the return value is represented as
|vim.NIL| special value
Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
enumerates functions that were called at least once.
Note: The majority of functions cannot run in |api-fast| callbacks with some
undocumented exceptions which are allowed.
*lua-vim-variables*
The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
described below. In this way you can easily read and modify global Vimscript
variables from Lua.
Example: >lua
vim.g.foo = 5 -- Set the g:foo Vimscript variable.
print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
vim.b[2].foo = 6 -- Set b:foo for buffer 2
<
Note that setting dictionary fields directly will not write them back into
Nvim. This is because the index into the namespace simply returns a copy.
Instead the whole dictionary must be written as one. This can be achieved by
creating a short-lived temporary.
Example: >lua
vim.g.my_dict.field1 = 'value' -- Does not work
local my_dict = vim.g.my_dict --
my_dict.field1 = 'value' -- Instead do
vim.g.my_dict = my_dict --
vim.g *vim.g*
Global (|g:|) editor variables.
Key with no value returns `nil`.
vim.b *vim.b*
Buffer-scoped (|b:|) variables for the current buffer.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific buffer.
vim.w *vim.w*
Window-scoped (|w:|) variables for the current window.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific window.
vim.t *vim.t*
Tabpage-scoped (|t:|) variables for the current tabpage.
Invalid or unset key returns `nil`. Can be indexed with
an integer to access variables for a specific tabpage.
vim.v *vim.v*
|v:| variables.
Invalid or unset key returns `nil`.
*lua-options*
*lua-vim-options*
*lua-vim-set*
*lua-vim-setlocal*
Vim options can be accessed through |vim.o|, which behaves like Vimscript
|:set|.
Examples: ~
To set a boolean toggle:
Vimscript: `set number`
Lua: `vim.o.number = true`
To set a string value:
Vimscript: `set wildignore=*.o,*.a,__pycache__`
Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
window-scoped options. Note that this must NOT be confused with
|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
global value of a |global-local| option, see |:setglobal|.
*vim.opt_local*
*vim.opt_global*
*vim.opt*
A special interface |vim.opt| exists for conveniently interacting with list-
and map-style options from Lua: It allows accessing them as Lua tables and
offers object-oriented method for adding and removing entries.
Examples: ~
The following methods of setting a list-style option are equivalent:
In Vimscript: >vim
set wildignore=*.o,*.a,__pycache__
<
In Lua using `vim.o`: >lua
vim.o.wildignore = '*.o,*.a,__pycache__'
<
In Lua using `vim.opt`: >lua
vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
<
To replicate the behavior of |:set+=|, use: >lua
vim.opt.wildignore:append { "*.pyc", "node_modules" }
<
To replicate the behavior of |:set^=|, use: >lua
vim.opt.wildignore:prepend { "new_first_value" }
<
To replicate the behavior of |:set-=|, use: >lua
vim.opt.wildignore:remove { "node_modules" }
<
The following methods of setting a map-style option are equivalent:
In Vimscript: >vim
set listchars=space:_,tab:>~
<
In Lua using `vim.o`: >lua
vim.o.listchars = 'space:_,tab:>~'
<
In Lua using `vim.opt`: >lua
vim.opt.listchars = { space = '_', tab = '>~' }
<
Note that |vim.opt| returns an `Option` object, not the value of the option,
which is accessed through |vim.opt:get()|:
Examples: ~
The following methods of getting a list-style option are equivalent:
In Vimscript: >vim
echo wildignore
<
In Lua using `vim.o`: >lua
print(vim.o.wildignore)
<
In Lua using `vim.opt`: >lua
vim.print(vim.opt.wildignore:get())
<
In any of the above examples, to replicate the behavior |:setlocal|, use
`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
`vim.opt_global`.
Option:append({value}) *vim.opt:append()*
Append a value to string-style options. See |:set+=|
These are equivalent: >lua
vim.opt.formatoptions:append('j')
vim.opt.formatoptions = vim.opt.formatoptions + 'j'
<
Parameters: ~
• {value} (`string`) Value to append
Option:get() *vim.opt:get()*
Returns a Lua-representation of the option. Boolean, number and string
values will be returned in exactly the same fashion.
For values that are comma-separated lists, an array will be returned with
the values as entries in the array: >lua
vim.cmd [[set wildignore=*.pyc,*.o]]
vim.print(vim.opt.wildignore:get())
-- { "*.pyc", "*.o", }
for _, ignore_pattern in ipairs(vim.opt.wildignore:get()) do
print("Will ignore:", ignore_pattern)
end
-- Will ignore: *.pyc
-- Will ignore: *.o
<
For values that are comma-separated maps, a table will be returned with
the names as keys and the values as entries: >lua
vim.cmd [[set listchars=space:_,tab:>~]]
vim.print(vim.opt.listchars:get())
-- { space = "_", tab = ">~", }
for char, representation in pairs(vim.opt.listchars:get()) do
print(char, "=>", representation)
end
<
For values that are lists of flags, a set will be returned with the flags
as keys and `true` as entries. >lua
vim.cmd [[set formatoptions=njtcroql]]
vim.print(vim.opt.formatoptions:get())
-- { n = true, j = true, c = true, ... }
local format_opts = vim.opt.formatoptions:get()
if format_opts.j then
print("J is enabled!")
end
<
Return: ~
(`string|integer|boolean?`) value of option
Option:prepend({value}) *vim.opt:prepend()*
Prepend a value to string-style options. See |:set^=|
These are equivalent: >lua
vim.opt.wildignore:prepend('*.o')
vim.opt.wildignore = vim.opt.wildignore ^ '*.o'
<
Parameters: ~
• {value} (`string`) Value to prepend
Option:remove({value}) *vim.opt:remove()*
Remove a value from string-style options. See |:set-=|
These are equivalent: >lua
vim.opt.wildignore:remove('*.pyc')
vim.opt.wildignore = vim.opt.wildignore - '*.pyc'
<
Parameters: ~
• {value} (`string`) Value to remove
vim.bo[{bufnr}] *vim.bo*
Get or set buffer-scoped |options| for the buffer with number {bufnr}.
Like `:setlocal`. If {bufnr} is omitted then the current buffer is used.
Invalid {bufnr} or key is an error.
Example: >lua
local bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].buflisted = true -- same as vim.bo.buflisted = true
print(vim.bo.comments)
print(vim.bo.baz) -- error: invalid key
<
vim.env *vim.env*
Environment variables defined in the editor session. See |expand-env| and
|:let-environment| for the Vimscript behavior. Invalid or unset key
returns `nil`.
Example: >lua
vim.env.FOO = 'bar'
print(vim.env.TERM)
<
vim.go *vim.go*
Get or set global |options|. Like `:setglobal`. Invalid key is an error.
Note: this is different from |vim.o| because this accesses the global
option value and thus is mostly useful for use with |global-local|
options.
Example: >lua
vim.go.cmdheight = 4
print(vim.go.columns)
print(vim.go.bar) -- error: invalid key
<
vim.o *vim.o*
Get or set |options|. Works like `:set`, so buffer/window-scoped options
target the current buffer/window. Invalid key is an error.
Example: >lua
vim.o.cmdheight = 4
print(vim.o.columns)
print(vim.o.foo) -- error: invalid key
<
vim.wo[{winid}][{bufnr}] *vim.wo*
Get or set window-scoped |options| for the window with handle {winid} and
buffer with number {bufnr}. Like `:setlocal` if setting a |global-local|
option or if {bufnr} is provided, like `:set` otherwise. If {winid} is
omitted then the current window is used. Invalid {winid}, {bufnr} or key
is an error.
Note: only {bufnr} with value `0` (the current buffer in the window) is
supported.
Example: >lua
local winid = vim.api.nvim_get_current_win()
vim.wo[winid].number = true -- same as vim.wo.number = true
print(vim.wo.foldmarker)
print(vim.wo.quux) -- error: invalid key
vim.wo[winid][0].spell = false -- like ':setlocal nospell'
<
==============================================================================
Lua module: vim *lua-vim*
vim.cmd({command}) *vim.cmd()*
Executes Vimscript (|Ex-commands|).
Note that `vim.cmd` can be indexed with a command name to return a
callable function to the command.
Example: >lua
vim.cmd('echo 42')
vim.cmd([[
augroup My_group
autocmd!
autocmd FileType c setlocal cindent
augroup END
]])
-- Ex command :echo "foo"
-- Note string literals need to be double quoted.
vim.cmd('echo "foo"')
vim.cmd { cmd = 'echo', args = { '"foo"' } }
vim.cmd.echo({ args = { '"foo"' } })
vim.cmd.echo('"foo"')
-- Ex command :write! myfile.txt
vim.cmd('write! myfile.txt')
vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
vim.cmd.write { args = { "myfile.txt" }, bang = true }
vim.cmd.write { "myfile.txt", bang = true }
-- Ex command :colorscheme blue
vim.cmd('colorscheme blue')
vim.cmd.colorscheme('blue')
<
Parameters: ~
• {command} (`string|table`) Command(s) to execute. If a string,
executes multiple lines of Vimscript at once. In this case,
it is an alias to |nvim_exec2()|, where `opts.output` is
set to false. Thus it works identical to |:source|. If a
table, executes a single command. In this case, it is an
alias to |nvim_cmd()| where `opts` is empty.
See also: ~
• |ex-cmd-index|
vim.defer_fn({fn}, {timeout}) *vim.defer_fn()*
Defers calling {fn} until {timeout} ms passes.
Use to do a one-shot timer that calls {fn} Note: The {fn} is
|vim.schedule_wrap()|ped automatically, so API functions are safe to call.
Parameters: ~
• {fn} (`function`) Callback to call once `timeout` expires
• {timeout} (`integer`) Number of milliseconds to wait before calling
`fn`
Return: ~
(`table`) timer luv timer object
*vim.deprecate()*
vim.deprecate({name}, {alternative}, {version}, {plugin}, {backtrace})
Shows a deprecation message to the user.
Parameters: ~
• {name} (`string`) Deprecated feature (function, API, etc.).
• {alternative} (`string?`) Suggested alternative feature.
• {version} (`string`) Version when the deprecated function will be
removed.
• {plugin} (`string?`) Name of the plugin that owns the deprecated
feature. Defaults to "Nvim".
• {backtrace} (`boolean?`) Prints backtrace. Defaults to true.
Return: ~
(`string?`) Deprecated message, or nil if no message was shown.
vim.inspect() *vim.inspect()*
Gets a human-readable representation of the given object.
Return: ~
(`string`)
See also: ~
• |vim.print()|
• https://github.com/kikito/inspect.lua
• https://github.com/mpeterv/vinspect
vim.keycode({str}) *vim.keycode()*
Translates keycodes.
Example: >lua
local k = vim.keycode
vim.g.mapleader = k'<bs>'
<
Parameters: ~
• {str} (`string`) String to be converted.
Return: ~
(`string`)
See also: ~
• |nvim_replace_termcodes()|
vim.lua_omnifunc({find_start}) *vim.lua_omnifunc()*
Omnifunc for completing Lua values from the runtime Lua interpreter,
similar to the builtin completion for the `:lua` command.
Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer.
Parameters: ~
• {find_start} (`1|0`)
vim.notify({msg}, {level}, {opts}) *vim.notify()*
Displays a notification to the user.
This function can be overridden by plugins to display notifications using
a custom provider (such as the system notification provider). By default,
writes to |:messages|.
Parameters: ~
• {msg} (`string`) Content of the notification to show to the user.
• {level} (`integer?`) One of the values from |vim.log.levels|.
• {opts} (`table?`) Optional parameters. Unused by default.
vim.notify_once({msg}, {level}, {opts}) *vim.notify_once()*
Displays a notification only one time.
Like |vim.notify()|, but subsequent calls with the same message will not
display a notification.
Parameters: ~
• {msg} (`string`) Content of the notification to show to the user.
• {level} (`integer?`) One of the values from |vim.log.levels|.
• {opts} (`table?`) Optional parameters. Unused by default.
Return: ~
(`boolean`) true if message was displayed, else false
vim.on_key({fn}, {ns_id}, {opts}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
yes every, input key.
The Nvim command-line option |-w| is related but does not support
callbacks and cannot be toggled dynamically.
Note: ~
• {fn} will be removed on error.
• {fn} won't be invoked recursively, i.e. if {fn} itself consumes input,
it won't be invoked for those keys.
• {fn} will not be cleared by |nvim_buf_clear_namespace()|
Parameters: ~
• {fn} (`fun(key: string, typed: string): string??`) Function
invoked for every input key, after mappings have been applied
but before further processing. Arguments {key} and {typed}
are raw keycodes, where {key} is the key after mappings are
applied, and {typed} is the key(s) before mappings are
applied. {typed} may be empty if {key} is produced by
non-typed key(s) or by the same typed key(s) that produced a
previous {key}. If {fn} returns an empty string, {key} is
discarded/ignored. When {fn} is `nil`, the callback
associated with namespace {ns_id} is removed.
• {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns
a new |nvim_create_namespace()| id.
• {opts} (`table?`) Optional parameters
Return: ~
(`integer`) Namespace id associated with {fn}. Or count of all
callbacks if on_key() is called without arguments.
See also: ~
• |keytrans()|
vim.paste({lines}, {phase}) *vim.paste()*
Paste handler, invoked by |nvim_paste()|.
Note: This is provided only as a "hook", don't call it directly; call
|nvim_paste()| instead, which arranges redo (dot-repeat) and invokes
`vim.paste`.
Example: To remove ANSI color codes when pasting: >lua
vim.paste = (function(overridden)
return function(lines, phase)
for i,line in ipairs(lines) do
-- Scrub ANSI color codes from paste input.
lines[i] = line:gsub('\27%[[0-9;mK]+', '')
end
return overridden(lines, phase)
end
end)(vim.paste)
<
Parameters: ~
• {lines} (`string[]`) |readfile()|-style list of lines to paste.
|channel-lines|
• {phase} (`-1|1|2|3`) -1: "non-streaming" paste: the call contains all
lines. If paste is "streamed", `phase` indicates the stream
state:
• 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once)
Return: ~
(`boolean`) result false if client should cancel the paste.
See also: ~
• |paste|
vim.print({...}) *vim.print()*
"Pretty prints" the given arguments and returns them unmodified.
Example: >lua
local hl_normal = vim.print(vim.api.nvim_get_hl(0, { name = 'Normal' }))
<
Parameters: ~
• {...} (`any`)
Return: ~
(`any`) given arguments.
See also: ~
• |vim.inspect()|
• |:=|
vim.schedule_wrap({fn}) *vim.schedule_wrap()*
Returns a function which calls {fn} via |vim.schedule()|.
The returned function passes all arguments to {fn}.
Example: >lua
function notify_readable(_err, readable)
vim.notify("readable? " .. tostring(readable))
end
vim.uv.fs_access(vim.fn.stdpath("config"), "R", vim.schedule_wrap(notify_readable))
<
Parameters: ~
• {fn} (`function`)
Return: ~
(`function`)
See also: ~
• |lua-loop-callbacks|
• |vim.schedule()|
• |vim.in_fast_event()|
*vim.str_byteindex()*
vim.str_byteindex({s}, {encoding}, {index}, {strict_indexing})
Convert UTF-32, UTF-16 or UTF-8 {index} to byte index. If
{strict_indexing} is false then then an out of range index will return
byte length instead of throwing an error.
Invalid UTF-8 and NUL is treated like in |vim.str_utfindex()|. An {index}
in the middle of a UTF-16 sequence is rounded upwards to the end of that
sequence.
Parameters: ~
• {s} (`string`)
• {encoding} (`"utf-8"|"utf-16"|"utf-32"`)
• {index} (`integer`)
• {strict_indexing} (`boolean?`) default: true
Return: ~
(`integer`)
*vim.str_utfindex()*
vim.str_utfindex({s}, {encoding}, {index}, {strict_indexing})
Convert byte index to UTF-32, UTF-16 or UTF-8 indices. If {index} is not
supplied, the length of the string is used. All indices are zero-based.
If {strict_indexing} is false then an out of range index will return
string length instead of throwing an error. Invalid UTF-8 bytes, and
embedded surrogates are counted as one code point each. An {index} in the
middle of a UTF-8 sequence is rounded upwards to the end of that sequence.
Parameters: ~
• {s} (`string`)
• {encoding} (`"utf-8"|"utf-16"|"utf-32"`)
• {index} (`integer?`)
• {strict_indexing} (`boolean?`) default: true
Return: ~
(`integer`)
vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
Runs a system command or throws an error if {cmd} cannot be run.
Examples: >lua
local on_exit = function(obj)
print(obj.code)
print(obj.signal)
print(obj.stdout)
print(obj.stderr)
end
-- Runs asynchronously:
vim.system({'echo', 'hello'}, { text = true }, on_exit)
-- Runs synchronously:
local obj = vim.system({'echo', 'hello'}, { text = true }):wait()
-- { code = 0, signal = 0, stdout = 'hello\n', stderr = '' }
<
See |uv.spawn()| for more details. Note: unlike |uv.spawn()|, vim.system
throws an error if {cmd} cannot be run.
Parameters: ~
• {cmd} (`string[]`) Command to execute
• {opts} (`vim.SystemOpts?`) Options:
• cwd: (string) Set the current working directory for the
sub-process.
• env: table<string,string> Set environment variables for
the new process. Inherits the current environment with
`NVIM` set to |v:servername|.
• clear_env: (boolean) `env` defines the job environment
exactly, instead of merging current environment.
• stdin: (string|string[]|boolean) If `true`, then a pipe
to stdin is opened and can be written to via the
`write()` method to SystemObj. If string or string[] then
will be written to stdin and closed. Defaults to `false`.
• stdout: (boolean|function) Handle output from stdout.
When passed as a function must have the signature
`fun(err: string, data: string)`. Defaults to `true`
• stderr: (boolean|function) Handle output from stderr.
When passed as a function must have the signature
`fun(err: string, data: string)`. Defaults to `true`.
• text: (boolean) Handle stdout and stderr as text.
Replaces `\r\n` with `\n`.
• timeout: (integer) Run the command with a time limit.
Upon timeout the process is sent the TERM signal (15) and
the exit code is set to 124.
• detach: (boolean) If true, spawn the child process in a
detached state - this will make it a process group
leader, and will effectively enable the child to keep
running after the parent exits. Note that the child
process will still keep the parent's event loop alive
unless the parent process calls |uv.unref()| on the
child's process handle.
• {on_exit} (`fun(out: vim.SystemCompleted)?`) Called when subprocess
exits. When provided, the command runs asynchronously.
Receives SystemCompleted object, see return of
SystemObj:wait().
Return: ~
(`vim.SystemObj`) Object with the fields:
• cmd (string[]) Command name and args
• pid (integer) Process ID
• wait (fun(timeout: integer|nil): SystemCompleted) Wait for the
process to complete. Upon timeout the process is sent the KILL
signal (9) and the exit code is set to 124. Cannot be called in
|api-fast|.
• SystemCompleted is an object with the fields:
• code: (integer)
• signal: (integer)
• stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed
• kill (fun(signal: integer|string))
• write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to
close the stream.
• is_closing (fun(): boolean)
==============================================================================
Lua module: vim.inspector *vim.inspector*
vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
Get all the items at a given buffer position.
Can also be pretty-printed with `:Inspect!`. *:Inspect!*
Attributes: ~
Since: 0.9.0
Parameters: ~
• {bufnr} (`integer?`) defaults to the current buffer
• {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
the current cursor
• {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
the current cursor
• {filter} (`table?`) Table with key-value pairs to filter the items
• {syntax} (`boolean`, default: `true`) Include syntax based
highlight groups.
• {treesitter} (`boolean`, default: `true`) Include
treesitter based highlight groups.
• {extmarks} (`boolean|"all"`, default: true) Include
extmarks. When `all`, then extmarks without a `hl_group`
will also be included.
• {semantic_tokens} (`boolean`, default: true) Include
semantic token highlights.
Return: ~
(`table`) a table with the following key-value pairs. Items are in
"traversal order":
• treesitter: a list of treesitter captures
• syntax: a list of syntax groups
• semantic_tokens: a list of semantic tokens
• extmarks: a list of extmarks
• buffer: the buffer used to get the items
• row: the row used to get the items
• col: the col used to get the items
vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
Show all the items at a given buffer position.
Can also be shown with `:Inspect`. *:Inspect*
Example: To bind this function to the vim-scriptease inspired `zS` in
Normal mode: >lua
vim.keymap.set('n', 'zS', vim.show_pos)
<
Attributes: ~
Since: 0.9.0
Parameters: ~
• {bufnr} (`integer?`) defaults to the current buffer
• {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
the current cursor
• {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
the current cursor
• {filter} (`table?`) A table with the following fields:
• {syntax} (`boolean`, default: `true`) Include syntax based
highlight groups.
• {treesitter} (`boolean`, default: `true`) Include
treesitter based highlight groups.
• {extmarks} (`boolean|"all"`, default: true) Include
extmarks. When `all`, then extmarks without a `hl_group`
will also be included.
• {semantic_tokens} (`boolean`, default: true) Include
semantic token highlights.
*vim.Ringbuf*
Fields: ~
• {clear} (`fun()`) See |Ringbuf:clear()|.
• {push} (`fun(item: T)`) See |Ringbuf:push()|.
• {pop} (`fun(): T?`) See |Ringbuf:pop()|.
• {peek} (`fun(): T?`) See |Ringbuf:peek()|.
Ringbuf:clear() *Ringbuf:clear()*
Clear all items
Ringbuf:peek() *Ringbuf:peek()*
Returns the first unread item without removing it
Return: ~
(`any?`)
Ringbuf:pop() *Ringbuf:pop()*
Removes and returns the first unread item
Return: ~
(`any?`)
Ringbuf:push({item}) *Ringbuf:push()*
Adds an item, overriding the oldest item if the buffer is full.
Parameters: ~
• {item} (`any`)
vim.deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality
Tables are compared recursively unless they both provide the `eq`
metamethod. All other types are compared using the equality `==` operator.
Parameters: ~
• {a} (`any`) First value
• {b} (`any`) Second value
Return: ~
(`boolean`) `true` if values are equals, else `false`
vim.deepcopy({orig}, {noref}) *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.
Functions are naively copied, so functions in the copied table point to
the same functions as those in the input table. Userdata and threads are
not copied and will throw an error.
Note: `noref=true` is much more performant on tables with unique table
fields, while `noref=false` is more performant on tables that reuse table
fields.
Parameters: ~
• {orig} (`table`) Table to copy
• {noref} (`boolean?`) When `false` (default) a contained table is only
copied once and all references point to this single copy.
When `true` every occurrence of a table results in a new
copy. This also means that a cyclic reference can cause
`deepcopy()` to fail.
Return: ~
(`table`) Table of copied keys and (nested) values.
vim.defaulttable({createfn}) *vim.defaulttable()*
Creates a table whose missing keys are provided by {createfn} (like
Python's "defaultdict").
If {createfn} is `nil` it defaults to defaulttable() itself, so accessing
nested keys creates nested tables: >lua
local a = vim.defaulttable()
a.b.c = 1
<
Parameters: ~
• {createfn} (`fun(key:any):any?`) Provides the value for a missing
`key`.
Return: ~
(`table`) Empty table with `__index` metamethod.
vim.endswith({s}, {suffix}) *vim.endswith()*
Tests if `s` ends with `suffix`.
Parameters: ~
• {s} (`string`) String
• {suffix} (`string`) Suffix to match
Return: ~
(`boolean`) `true` if `suffix` is a suffix of `s`
vim.gsplit({s}, {sep}, {opts}) *vim.gsplit()*
Gets an |iterator| that splits a string at each instance of a separator,
in "lazy" fashion (as opposed to |vim.split()| which is "eager").
Example: >lua
for s in vim.gsplit(':aa::b:', ':', {plain=true}) do
print(s)
end
<
If you want to also inspect the separator itself (instead of discarding
it), use |string.gmatch()|. Example: >lua
for word, num in ('foo111bar222'):gmatch('([^0-9]*)(%d*)') do
print(('word: %s num: %s'):format(word, num))
end
<
Parameters: ~
• {s} (`string`) String to split
• {sep} (`string`) Separator or pattern
• {opts} (`table?`) Keyword arguments |kwargs|:
• {plain}? (`boolean`) Use `sep` literally (as in
string.find).
• {trimempty}? (`boolean`) Discard empty segments at start and
end of the sequence.
Return: ~
(`fun():string?`) Iterator over the split components
See also: ~
• |string.gmatch()|
• |vim.split()|
• |lua-patterns|
• https://www.lua.org/pil/20.2.html
• http://lua-users.org/wiki/StringLibraryTutorial
vim.is_callable({f}) *vim.is_callable()*
Returns true if object `f` can be called as a function.
Parameters: ~
• {f} (`any`) Any object
Return: ~
(`boolean`) `true` if `f` is callable, else `false`
vim.isarray({t}) *vim.isarray()*
Tests if `t` is an "array": a table indexed only by integers (potentially
non-contiguous).
If the indexes start from 1 and are contiguous then the array is also a
list. |vim.islist()|
Empty table `{}` is an array, unless it was created by |vim.empty_dict()|
or returned as a dict-like |API| or Vimscript result, for example from
|rpcrequest()| or |vim.fn|.
Parameters: ~
• {t} (`table?`)
Return: ~
(`boolean`) `true` if array-like table, else `false`.
See also: ~
• https://github.com/openresty/luajit2#tableisarray
vim.islist({t}) *vim.islist()*
Tests if `t` is a "list": a table indexed only by contiguous integers
starting from 1 (what |lua-length| calls a "regular array").
Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or
returned as a dict-like |API| or Vimscript result, for example from
|rpcrequest()| or |vim.fn|.
Parameters: ~
• {t} (`table?`)
Return: ~
(`boolean`) `true` if list-like table, else `false`.
See also: ~
• |vim.isarray()|
vim.list_contains({t}, {value}) *vim.list_contains()*
Checks if a list-like table (integer keys without gaps) contains `value`.
Parameters: ~
• {t} (`table`) Table to check (must be list-like, not validated)
• {value} (`any`) Value to compare
Return: ~
(`boolean`) `true` if `t` contains `value`
See also: ~
• |vim.tbl_contains()| for checking values in general tables
vim.list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
Extends a list-like table with the values of another list-like table.
NOTE: This mutates dst!
Parameters: ~
• {dst} (`table`) List which will be modified and appended to
• {src} (`table`) List from which values will be inserted
• {start} (`integer?`) Start index on src. Defaults to 1
• {finish} (`integer?`) Final index on src. Defaults to `#src`
Return: ~
(`table`) dst
See also: ~
• |vim.tbl_extend()|
vim.list_slice({list}, {start}, {finish}) *vim.list_slice()*
Creates a copy of a table containing only elements from start to end
(inclusive)
Parameters: ~
• {list} (`any[]`) Table
• {start} (`integer?`) Start range of slice
• {finish} (`integer?`) End range of slice
Return: ~
(`any[]`) Copy of table sliced from start to finish (inclusive)
vim.pesc({s}) *vim.pesc()*
Escapes magic chars in |lua-patterns|.
Parameters: ~
• {s} (`string`) String to escape
Return: ~
(`string`) %-escaped pattern string
See also: ~
• https://github.com/rxi/lume
vim.ringbuf({size}) *vim.ringbuf()*
Create a ring buffer limited to a maximal number of items. Once the buffer
is full, adding a new entry overrides the oldest entry. >lua
local ringbuf = vim.ringbuf(4)
ringbuf:push("a")
ringbuf:push("b")
ringbuf:push("c")
ringbuf:push("d")
ringbuf:push("e") -- overrides "a"
print(ringbuf:pop()) -- returns "b"
print(ringbuf:pop()) -- returns "c"
-- Can be used as iterator. Pops remaining items:
for val in ringbuf do
print(val)
end
<
Returns a Ringbuf instance with the following methods:
• |Ringbuf:push()|
• |Ringbuf:pop()|
• |Ringbuf:peek()|
• |Ringbuf:clear()|
Parameters: ~
• {size} (`integer`)
Return: ~
(`vim.Ringbuf`) ringbuf See |vim.Ringbuf|.
vim.spairs({t}) *vim.spairs()*
Enumerates key-value pairs of a table, ordered by key.
Parameters: ~
• {t} (`table`) Dict-like table
Return (multiple): ~
(`fun(table: table<K, V>, index?: K):K, V`) |for-in| iterator over
sorted keys and their values
(`table`)
See also: ~
• Based on
https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.split({s}, {sep}, {opts}) *vim.split()*
Splits a string at each instance of a separator and returns the result as
a table (unlike |vim.gsplit()|).
Examples: >lua
split(":aa::b:", ":") --> {'','aa','','b',''}
split("axaby", "ab?") --> {'','x','y'}
split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'}
split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
<
Parameters: ~
• {s} (`string`) String to split
• {sep} (`string`) Separator or pattern
• {opts} (`table?`) Keyword arguments |kwargs|:
• {plain}? (`boolean`) Use `sep` literally (as in
string.find).
• {trimempty}? (`boolean`) Discard empty segments at start and
end of the sequence.
Return: ~
(`string[]`) List of split components
See also: ~
• |vim.gsplit()|
• |string.gmatch()|
vim.startswith({s}, {prefix}) *vim.startswith()*
Tests if `s` starts with `prefix`.
Parameters: ~
• {s} (`string`) String
• {prefix} (`string`) Prefix to match
Return: ~
(`boolean`) `true` if `prefix` is a prefix of `s`
vim.tbl_contains({t}, {value}, {opts}) *vim.tbl_contains()*
Checks if a table contains a given value, specified either directly or via
a predicate that is checked for each value.
Example: >lua
vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v)
return vim.deep_equal(v, { 'b', 'c' })
end, { predicate = true })
-- true
<
Parameters: ~
• {t} (`table`) Table to check
• {value} (`any`) Value to compare or predicate function reference
• {opts} (`table?`) Keyword arguments |kwargs|:
• {predicate}? (`boolean`) `value` is a function reference to
be checked (default false)
Return: ~
(`boolean`) `true` if `t` contains `value`
See also: ~
• |vim.list_contains()| for checking values in list-like tables
vim.tbl_count({t}) *vim.tbl_count()*
Counts the number of non-nil values in table `t`. >lua
vim.tbl_count({ a=1, b=2 }) --> 2
vim.tbl_count({ 1, 2 }) --> 2
<
Parameters: ~
• {t} (`table`) Table
Return: ~
(`integer`) Number of non-nil values in table
See also: ~
• https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
Merges recursively two or more tables.
Only values that are empty tables or tables that are not |lua-list|s
(indexed by consecutive integers starting from 1) are merged recursively.
This is useful for merging nested tables like default and user
configurations where lists should be treated as literals (i.e., are
overwritten instead of merged).
Parameters: ~
• {behavior} (`'error'|'keep'|'force'`) 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
• {...} (`table`) Two or more tables
Return: ~
(`table`) Merged table
See also: ~
• |vim.tbl_extend()|
vim.tbl_extend({behavior}, {...}) *vim.tbl_extend()*
Merges two or more tables.
Parameters: ~
• {behavior} (`'error'|'keep'|'force'`) 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
• {...} (`table`) Two or more tables
Return: ~
(`table`) Merged table
See also: ~
• |extend()|
vim.tbl_filter({func}, {t}) *vim.tbl_filter()*
Filter a table using a predicate function
Parameters: ~
• {func} (`function`) Function
• {t} (`table`) Table
Return: ~
(`any[]`) Table of filtered values
vim.tbl_get({o}, {...}) *vim.tbl_get()*
Index into a table (first argument) via string keys passed as subsequent
arguments. Return `nil` if the key does not exist.
Examples: >lua
vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
<
Parameters: ~
• {o} (`table`) Table to index
• {...} (`any`) Optional keys (0 or more, variadic) via which to index
the table
Return: ~
(`any`) Nested value indexed by key (if it exists), else nil
vim.tbl_isempty({t}) *vim.tbl_isempty()*
Checks if a table is empty.
Parameters: ~
• {t} (`table`) Table to check
Return: ~
(`boolean`) `true` if `t` is empty
See also: ~
• https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_keys({t}) *vim.tbl_keys()*
Return a list of all keys used in a table. However, the order of the
return table of keys is not guaranteed.
Parameters: ~
• {t} (`table`) Table
Return: ~
(`any[]`) List of keys
See also: ~
• From
https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table.
Parameters: ~
• {func} (`fun(value: T): any`) Function
• {t} (`table<any, T>`) Table
Return: ~
(`table`) Table of transformed values
vim.tbl_values({t}) *vim.tbl_values()*
Return a list of all values used in a table. However, the order of the
return table of values is not guaranteed.
Parameters: ~
• {t} (`table`) Table
Return: ~
(`any[]`) List of values
vim.trim({s}) *vim.trim()*
Trim whitespace (Lua pattern "%s") from both sides of a string.
Parameters: ~
• {s} (`string`) String to trim
Return: ~
(`string`) String with whitespace removed from its beginning and end
See also: ~
• |lua-patterns|
• https://www.lua.org/pil/20.2.html
*vim.validate()*
vim.validate({name}, {value}, {validator}, {optional}, {message})
Validate function arguments.
This function has two valid forms:
1. `vim.validate(name, value, validator[, optional][, message])`
Validates that argument {name} with value {value} satisfies
{validator}. If {optional} is given and is `true`, then {value} may be
`nil`. If {message} is given, then it is used as the expected type in
the error message.
Example: >lua
function vim.startswith(s, prefix)
vim.validate('s', s, 'string')
vim.validate('prefix', prefix, 'string')
-- ...
end
<
2. `vim.validate(spec)` (deprecated) where `spec` is of type
`table<string,[value:any, validator: vim.validate.Validator, optional_or_msg? : boolean|string]>)`
Validates a argument specification. Specs are evaluated in alphanumeric
order, until the first failure.
Example: >lua
function user.new(name, age, hobbies)
vim.validate{
name={name, 'string'},
age={age, 'number'},
hobbies={hobbies, 'table'},
}
-- ...
end
<
Examples with explicit argument values (can be run directly): >lua
vim.validate('arg1', {'foo'}, 'table')
--> NOP (success)
vim.validate('arg2', 'foo', 'string')
--> NOP (success)
vim.validate('arg1', 1, 'table')
--> error('arg1: expected table, got number')
vim.validate('arg1', 3, function(a) return (a % 2) == 0 end, 'even number')
--> error('arg1: expected even number, got 3')
<
If multiple types are valid they can be given as a list. >lua
vim.validate('arg1', {'foo'}, {'table', 'string'})
vim.validate('arg2', 'foo', {'table', 'string'})
-- NOP (success)
vim.validate('arg1', 1, {'string', 'table'})
-- error('arg1: expected string|table, got number')
<
Note: ~
• `validator` set to a value returned by |lua-type()| provides the best
performance.
Parameters: ~
• {name} (`string`) Argument name
• {value} (`any`) Argument value
• {validator} (`vim.validate.Validator`)
• (`string|string[]`): Any value that can be returned
from |lua-type()| in addition to `'callable'`:
`'boolean'`, `'callable'`, `'function'`, `'nil'`,
`'number'`, `'string'`, `'table'`, `'thread'`,
`'userdata'`.
• (`fun(val:any): boolean, string?`) A function that
returns a boolean and an optional string message.
• {optional} (`boolean?`) Argument is optional (may be omitted)
• {message} (`string?`) message when validation fails
==============================================================================
Lua module: vim.loader *vim.loader*
vim.loader.enable({enable}) *vim.loader.enable()*
WARNING: This feature is experimental/unstable.
Enables or disables the experimental Lua module loader:
Enable (`enable=true`):
• overrides |loadfile()|
• adds the Lua loader using the byte-compilation cache
• adds the libs loader
• removes the default Nvim loader
Disable (`enable=false`):
• removes the loaders
• adds the default Nvim loader
Parameters: ~
• {enable} (`boolean?`) true/nil to enable, false to disable
vim.loader.find({modname}, {opts}) *vim.loader.find()*
WARNING: This feature is experimental/unstable.
Finds Lua modules for the given module name.
Parameters: ~
• {modname} (`string`) Module name, or `"*"` to find the top-level
modules instead
• {opts} (`table?`) Options for finding a module:
• {rtp}? (`boolean`, default: `true`) Search for modname in
the runtime path.
• {paths}? (`string[]`, default: `{}`) Extra paths to
search for modname
• {patterns}? (`string[]`, default:
`{"/init.lua", ".lua"}`) List of patterns to use when
searching for modules. A pattern is a string added to the
basename of the Lua module being searched.
• {all}? (`boolean`, default: `false`) Search for all
matches.
Return: ~
(`table[]`) A list of objects with the following fields:
• {modpath} (`string`) Path of the module
• {modname} (`string`) Name of the module
• {stat}? (`uv.fs_stat.result`) The fs_stat of the module path. Won't
be returned for `modname="*"`
vim.loader.reset({path}) *vim.loader.reset()*
WARNING: This feature is experimental/unstable.
Resets the cache for the path, or all the paths if path is nil.
Parameters: ~
• {path} (`string?`) path to reset
==============================================================================
Lua module: vim.uri *vim.uri*
vim.uri_decode({str}) *vim.uri_decode()*
URI-decodes a string containing percent escapes.
Parameters: ~
• {str} (`string`) string to decode
Return: ~
(`string`) decoded string
vim.uri_encode({str}, {rfc}) *vim.uri_encode()*
URI-encodes a string using percent escapes.
Parameters: ~
• {str} (`string`) string to encode
• {rfc} (`"rfc2396"|"rfc2732"|"rfc3986"?`)
Return: ~
(`string`) encoded string
vim.uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()*
Gets a URI from a bufnr.
Parameters: ~
• {bufnr} (`integer`)
Return: ~
(`string`) URI
vim.uri_from_fname({path}) *vim.uri_from_fname()*
Gets a URI from a file path.
Parameters: ~
• {path} (`string`) Path to file
Return: ~
(`string`) URI
vim.uri_to_bufnr({uri}) *vim.uri_to_bufnr()*
Gets the buffer for a uri. Creates a new unloaded buffer if no buffer for
the uri already exists.
Parameters: ~
• {uri} (`string`)
Return: ~
(`integer`) bufnr
vim.uri_to_fname({uri}) *vim.uri_to_fname()*
Gets a filename from a URI.
Parameters: ~
• {uri} (`string`)
Return: ~
(`string`) filename or unchanged URI for non-file URIs
==============================================================================
Lua module: vim.ui *vim.ui*
vim.ui.input({opts}, {on_confirm}) *vim.ui.input()*
Prompts the user for input, allowing arbitrary (potentially asynchronous)
work until `on_confirm`.
Example: >lua
vim.ui.input({ prompt = 'Enter value for shiftwidth: ' }, function(input)
vim.o.shiftwidth = tonumber(input)
end)
<
Parameters: ~
• {opts} (`table?`) Additional options. See |input()|
• prompt (string|nil) Text of the prompt
• default (string|nil) Default reply to the input
• completion (string|nil) Specifies type of completion
supported for input. Supported types are the same that
can be supplied to a user-defined command using the
"-complete=" argument. See |:command-completion|
• highlight (function) Function that will be used for
highlighting user inputs.
• {on_confirm} (`function`) ((input|nil) -> ()) Called once the user
confirms or abort the input. `input` is what the user
typed (it might be an empty string if nothing was
entered), or `nil` if the user aborted the dialog.
vim.ui.open({path}, {opt}) *vim.ui.open()*
Opens `path` with the system default handler (macOS `open`, Windows
`explorer.exe`, Linux `xdg-open`, …), or returns (but does not show) an
error message on failure.
Can also be invoked with `:Open`. *:Open*
Expands "~/" and environment variables in filesystem paths.
Examples: >lua
-- Asynchronous.
vim.ui.open("https://neovim.io/")
vim.ui.open("~/path/to/file")
-- Use the "osurl" command to handle the path or URL.
vim.ui.open("gh#neovim/neovim!29490", { cmd = { 'osurl' } })
-- Synchronous (wait until the process exits).
local cmd, err = vim.ui.open("$VIMRUNTIME")
if cmd then
cmd:wait()
end
<
Parameters: ~
• {path} (`string`) Path or URL to open
• {opt} (`{ cmd?: string[] }?`) Options
• cmd string[]|nil Command used to open the path or URL.
Return (multiple): ~
(`vim.SystemObj?`) Command object, or nil if not found.
(`string?`) Error message on failure, or nil on success.
See also: ~
• |vim.system()|
vim.ui.select({items}, {opts}, {on_choice}) *vim.ui.select()*
Prompts the user to pick from a list of items, allowing arbitrary
(potentially asynchronous) work until `on_choice`.
Example: >lua
vim.ui.select({ 'tabs', 'spaces' }, {
prompt = 'Select tabs or spaces:',
format_item = function(item)
return "I'd like to choose " .. item
end,
}, function(choice)
if choice == 'spaces' then
vim.o.expandtab = true
else
vim.o.expandtab = false
end
end)
<
Parameters: ~
• {items} (`any[]`) Arbitrary items
• {opts} (`table`) Additional options
• prompt (string|nil) Text of the prompt. Defaults to
`Select one of:`
• format_item (function item -> text) Function to format
an individual item from `items`. Defaults to
`tostring`.
• kind (string|nil) Arbitrary hint string indicating the
item shape. Plugins reimplementing `vim.ui.select` may
wish to use this to infer the structure or semantics of
`items`, or the context in which select() was called.
• {on_choice} (`fun(item: T?, idx: integer?)`) Called once the user
made a choice. `idx` is the 1-based index of `item`
within `items`. `nil` if the user aborted the dialog.
==============================================================================
Lua module: vim.filetype *vim.filetype*
vim.filetype.add({filetypes}) *vim.filetype.add()*
Add new filetype mappings.
Filetype mappings can be added either by extension or by filename (either
the "tail" or the full file path). The full file path is checked first,
followed by the file name. If a match is not found using the filename,
then the filename is matched against the list of |lua-patterns| (sorted by
priority) until a match is found. Lastly, if pattern matching does not
find a filetype, then the file extension is used.
The filetype can be either a string (in which case it is used as the
filetype directly) or a function. If a function, it takes the full path
and buffer number of the file as arguments (along with captures from the
matched pattern, if any) and should return a string that will be used as
the buffer's filetype. Optionally, the function can return a second
function value which, when called, modifies the state of the buffer. This
can be used to, for example, set filetype-specific buffer variables. This
function will be called by Nvim before setting the buffer's filetype.
Filename patterns can specify an optional priority to resolve cases when a
file path matches multiple patterns. Higher priorities are matched first.
When omitted, the priority defaults to 0. A pattern can contain
environment variables of the form "${SOME_VAR}" that will be automatically
expanded. If the environment variable is not set, the pattern won't be
matched.
See $VIMRUNTIME/lua/vim/filetype.lua for more examples.
Example: >lua
vim.filetype.add({
extension = {
foo = 'fooscript',
bar = function(path, bufnr)
if some_condition() then
return 'barscript', function(bufnr)
-- Set a buffer variable
vim.b[bufnr].barscript_version = 2
end
end
return 'bar'
end,
},
filename = {
['.foorc'] = 'toml',
['/etc/foo/config'] = 'toml',
},
pattern = {
['.*/etc/foo/.*'] = 'fooscript',
-- Using an optional priority
['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
-- A pattern containing an environment variable
['${XDG_CONFIG_HOME}/foo/git'] = 'git',
['.*README.(%a+)'] = function(path, bufnr, ext)
if ext == 'md' then
return 'markdown'
elseif ext == 'rst' then
return 'rst'
end
end,
},
})
<
To add a fallback match on contents, use >lua
vim.filetype.add {
pattern = {
['.*'] = {
function(path, bufnr)
local content = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or ''
if vim.regex([[^#!.*\\<mine\\>]]):match_str(content) ~= nil then
return 'mine'
elseif vim.regex([[\\<drawing\\>]]):match_str(content) ~= nil then
return 'drawing'
end
end,
{ priority = -math.huge },
},
},
}
<
Parameters: ~
• {filetypes} (`table`) A table containing new filetype maps (see
example).
• {pattern}? (`vim.filetype.mapping`)
• {extension}? (`vim.filetype.mapping`)
• {filename}? (`vim.filetype.mapping`)
*vim.filetype.get_option()*
vim.filetype.get_option({filetype}, {option})
Get the default option value for a {filetype}.
The returned value is what would be set in a new buffer after 'filetype'
is set, meaning it should respect all FileType autocmds and ftplugin
files.
Example: >lua
vim.filetype.get_option('vim', 'commentstring')
<
Note: this uses |nvim_get_option_value()| but caches the result. This
means |ftplugin| and |FileType| autocommands are only triggered once and
may not reflect later changes.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {filetype} (`string`) Filetype
• {option} (`string`) Option name
Return: ~
(`string|boolean|integer`) Option value
vim.filetype.match({args}) *vim.filetype.match()*
Perform filetype detection.
The filetype can be detected using one of three methods:
1. Using an existing buffer
2. Using only a file name
3. Using only file contents
Of these, option 1 provides the most accurate result as it uses both the
buffer's filename and (optionally) the buffer contents. Options 2 and 3
can be used without an existing buffer, but may not always provide a match
in cases where the filename (or contents) cannot unambiguously determine
the filetype.
Each of the three options is specified using a key to the single argument
of this function. Example: >lua
-- Using a buffer number
vim.filetype.match({ buf = 42 })
-- Override the filename of the given buffer
vim.filetype.match({ buf = 42, filename = 'foo.c' })
-- Using a filename without a buffer
vim.filetype.match({ filename = 'main.lua' })
-- Using file contents
vim.filetype.match({ contents = {'#!/usr/bin/env bash'} })
<
Parameters: ~
• {args} (`table`) Table specifying which matching strategy to use.
Accepted keys are:
• {buf}? (`integer`) Buffer number to use for matching.
Mutually exclusive with {contents}
• {filename}? (`string`) Filename to use for matching. When
{buf} is given, defaults to the filename of the given buffer
number. The file need not actually exist in the filesystem.
When used without {buf} only the name of the file is used
for filetype matching. This may result in failure to detect
the filetype in cases where the filename alone is not enough
to disambiguate the filetype.
• {contents}? (`string[]`) An array of lines representing file
contents to use for matching. Can be used with {filename}.
Mutually exclusive with {buf}.
Return (multiple): ~
(`string?`) If a match was found, the matched filetype.
(`function?`) A function that modifies buffer state when called (for
example, to set some filetype specific buffer variables). The function
accepts a buffer number as its only argument.
==============================================================================
Lua module: vim.keymap *vim.keymap*
vim.keymap.del({modes}, {lhs}, {opts}) *vim.keymap.del()*
Remove an existing mapping. Examples: >lua
vim.keymap.del('n', 'lhs')
vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
<
Parameters: ~
• {modes} (`string|string[]`)
• {lhs} (`string`)
• {opts} (`table?`) A table with the following fields:
• {buffer}? (`integer|boolean`) Remove a mapping from the
given buffer. When `0` or `true`, use the current buffer.
See also: ~
• |vim.keymap.set()|
vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
Defines a |mapping| of |keycodes| to a function or keycodes.
Examples: >lua
-- Map "x" to a Lua function:
vim.keymap.set('n', 'x', function() print("real lua function") end)
-- Map "<leader>x" to multiple modes for the current buffer:
vim.keymap.set({'n', 'v'}, '<leader>x', vim.lsp.buf.references, { buffer = true })
-- Map <Tab> to an expression (|:map-<expr>|):
vim.keymap.set('i', '<Tab>', function()
return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
end, { expr = true })
-- Map "[%%" to a <Plug> mapping:
vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)')
<
Parameters: ~
• {mode} (`string|string[]`) Mode "short-name" (see
|nvim_set_keymap()|), or a list thereof.
• {lhs} (`string`) Left-hand side |{lhs}| of the mapping.
• {rhs} (`string|function`) Right-hand side |{rhs}| of the mapping,
can be a Lua function.
• {opts} (`table?`) Table of |:map-arguments|. Same as
|nvim_set_keymap()| {opts}, except:
• {replace_keycodes} defaults to `true` if "expr" is `true`.
Also accepts:
• {buffer}? (`integer|boolean`) Creates buffer-local mapping,
`0` or `true` for current buffer.
• {remap}? (`boolean`, default: `false`) Make the mapping
recursive. Inverse of {noremap}.
See also: ~
• |nvim_set_keymap()|
• |maparg()|
• |mapcheck()|
• |mapset()|
==============================================================================
Lua module: vim.fs *vim.fs*
*vim.fs.exists()*
Use |uv.fs_stat()| to check a file's type, and whether it exists.
Example: >lua
if vim.uv.fs_stat(file) then
vim.print("file exists")
end
<
vim.fs.abspath({path}) *vim.fs.abspath()*
Convert path to an absolute path. A tilde (~) character at the beginning
of the path is expanded to the user's home directory. Does not check if
the path exists, normalize the path, resolve symlinks or hardlinks
(including `.` and `..`), or expand environment variables. If the path is
already absolute, it is returned unchanged. Also converts `\` path
separators to `/`.
Parameters: ~
• {path} (`string`) Path
Return: ~
(`string`) Absolute path
vim.fs.basename({file}) *vim.fs.basename()*
Return the basename of the given path
Attributes: ~
Since: 0.8.0
Parameters: ~
• {file} (`string?`) Path
Return: ~
(`string?`) Basename of {file}
vim.fs.dir({path}, {opts}) *vim.fs.dir()*
Return an iterator over the items located in {path}
Attributes: ~
Since: 0.8.0
Parameters: ~
• {path} (`string`) An absolute or relative path to the directory to
iterate over. The path is first normalized
|vim.fs.normalize()|.
• {opts} (`table?`) Optional keyword arguments:
• depth: integer|nil How deep the traverse (default 1)
• skip: (fun(dir_name: string): boolean)|nil Predicate to
control traversal. Return false to stop searching the
current directory. Only useful when depth > 1
• follow: boolean|nil Follow symbolic links. (default: false)
Return: ~
(`Iterator`) over items in {path}. Each iteration yields two values:
"name" and "type". "name" is the basename of the item relative to
{path}. "type" is one of the following: "file", "directory", "link",
"fifo", "socket", "char", "block", "unknown".
vim.fs.dirname({file}) *vim.fs.dirname()*
Return the parent directory of the given path
Attributes: ~
Since: 0.8.0
Parameters: ~
• {file} (`string?`) Path
Return: ~
(`string?`) Parent directory of {file}
vim.fs.find({names}, {opts}) *vim.fs.find()*
Find files or directories (or other items as specified by `opts.type`) in
the given path.
Finds items given in {names} starting from {path}. If {upward} is "true"
then the search traverses upward through parent directories; otherwise,
the search traverses downward. Note that downward searches are recursive
and may search through many directories! If {stop} is non-nil, then the
search stops when the directory given in {stop} is reached. The search
terminates when {limit} (default 1) matches are found. You can set {type}
to "file", "directory", "link", "socket", "char", "block", or "fifo" to
narrow the search to find only that type.
Examples: >lua
-- list all test directories under the runtime directory
local test_dirs = vim.fs.find(
{'test', 'tst', 'testdir'},
{limit = math.huge, type = 'directory', path = './runtime/'}
)
-- get all files ending with .cpp or .hpp inside lib/
local cpp_hpp = vim.fs.find(function(name, path)
return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$')
end, {limit = math.huge, type = 'file'})
<
Attributes: ~
Since: 0.8.0
Parameters: ~
• {names} (`string|string[]|fun(name: string, path: string): boolean`)
Names of the items to find. Must be base names, paths and
globs are not supported when {names} is a string or a table.
If {names} is a function, it is called for each traversed
item with args:
• name: base name of the current item
• path: full path of the current item
The function should return `true` if the given item is
considered a match.
• {opts} (`table`) Optional keyword arguments:
• {path}? (`string`) Path to begin searching from. If
omitted, the |current-directory| is used.
• {upward}? (`boolean`, default: `false`) Search upward
through parent directories. Otherwise, search through child
directories (recursively).
• {stop}? (`string`) Stop searching when this directory is
reached. The directory itself is not searched.
• {type}? (`string`) Find only items of the given type. If
omitted, all items that match {names} are included.
• {limit}? (`number`, default: `1`) Stop the search after
finding this many matches. Use `math.huge` to place no
limit on the number of matches.
• {follow}? (`boolean`, default: `false`) Follow symbolic
links.
Return: ~
(`string[]`) Normalized paths |vim.fs.normalize()| of all matching
items
vim.fs.joinpath({...}) *vim.fs.joinpath()*
Concatenates partial paths (one absolute or relative path followed by zero
or more relative paths). Slashes are normalized: redundant slashes are
removed, and (on Windows) backslashes are replaced with forward-slashes.
Examples:
• "foo/", "/bar" => "foo/bar"
• Windows: "a\foo\", "\bar" => "a/foo/bar"
Attributes: ~
Since: 0.10.0
Parameters: ~
• {...} (`string`)
Return: ~
(`string`)
vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
Normalize a path to a standard format. A tilde (~) character at the
beginning of the path is expanded to the user's home directory and
environment variables are also expanded. "." and ".." components are also
resolved, except when the path is relative and trying to resolve it would
result in an absolute path.
• "." as the only part in a relative path:
• "." => "."
• "././" => "."
• ".." when it leads outside the current directory
• "foo/../../bar" => "../bar"
• "../../foo" => "../../foo"
• ".." in the root directory returns the root directory.
• "/../../" => "/"
On Windows, backslash (\) characters are converted to forward slashes (/).
Examples: >lua
[[C:\Users\jdoe]] => "C:/Users/jdoe"
"~/src/neovim" => "/home/jdoe/src/neovim"
"$XDG_CONFIG_HOME/nvim/init.vim" => "/Users/jdoe/.config/nvim/init.vim"
"~/src/nvim/api/../tui/./tui.c" => "/home/jdoe/src/nvim/tui/tui.c"
"./foo/bar" => "foo/bar"
"foo/../../../bar" => "../../bar"
"/home/jdoe/../../../bar" => "/bar"
"C:foo/../../baz" => "C:../baz"
"C:/foo/../../baz" => "C:/baz"
[[\\?\UNC\server\share\foo\..\..\..\bar]] => "//?/UNC/server/share/bar"
<
Attributes: ~
Since: 0.8.0
Parameters: ~
• {path} (`string`) Path to normalize
• {opts} (`table?`) A table with the following fields:
• {expand_env}? (`boolean`, default: `true`) Expand
environment variables.
• {win}? (`boolean`, default: `true` in Windows, `false`
otherwise) Path is a Windows path.
Return: ~
(`string`) Normalized path
vim.fs.parents({start}) *vim.fs.parents()*
Iterate over all the parents of the given path.
Example: >lua
local root_dir
for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do
if vim.fn.isdirectory(dir .. "/.git") == 1 then
root_dir = dir
break
end
end
if root_dir then
print("Found git repository at", root_dir)
end
<
Attributes: ~
Since: 0.8.0
Parameters: ~
• {start} (`string`) Initial path.
Return (multiple): ~
(`fun(_, dir: string): string?`) Iterator
(`nil`)
(`string?`)
vim.fs.relpath({base}, {target}, {opts}) *vim.fs.relpath()*
Gets `target` path relative to `base`, or `nil` if `base` is not an
ancestor.
Example: >lua
vim.fs.relpath('/var', '/var/lib') -- 'lib'
vim.fs.relpath('/var', '/usr/bin') -- nil
<
Parameters: ~
• {base} (`string`)
• {target} (`string`)
• {opts} (`table?`) Reserved for future use
Return: ~
(`string?`)
vim.fs.rm({path}, {opts}) *vim.fs.rm()*
Remove files or directories
Attributes: ~
Since: 0.11.0
Parameters: ~
• {path} (`string`) Path to remove
• {opts} (`table?`) A table with the following fields:
• {recursive}? (`boolean`) Remove directories and their
contents recursively
• {force}? (`boolean`) Ignore nonexistent files and arguments
vim.fs.root({source}, {marker}) *vim.fs.root()*
Find the first parent directory containing a specific "marker", relative
to a file path or buffer.
If the buffer is unnamed (has no backing file) or has a non-empty
'buftype' then the search begins from Nvim's |current-directory|.
Example: >lua
-- Find the root of a Python project, starting from file 'main.py'
vim.fs.root(vim.fs.joinpath(vim.env.PWD, 'main.py'), {'pyproject.toml', 'setup.py' })
-- Find the root of a git repository
vim.fs.root(0, '.git')
-- Find the parent directory containing any file with a .csproj extension
vim.fs.root(0, function(name, path)
return name:match('%.csproj$') ~= nil
end)
<
Attributes: ~
Since: 0.10.0
Parameters: ~
• {source} (`integer|string`) Buffer number (0 for current buffer) or
file path (absolute or relative to the |current-directory|)
to begin the search from.
• {marker} (`string|string[]|fun(name: string, path: string): boolean`)
A marker, or list of markers, to search for. If a function,
the function is called for each evaluated item and should
return true if {name} and {path} are a match.
Return: ~
(`string?`) Directory path containing one of the given markers, or nil
if no directory was found.
==============================================================================
Lua module: vim.glob *vim.glob*
vim.glob.to_lpeg({pattern}) *vim.glob.to_lpeg()*
Parses a raw glob into an |lua-lpeg| pattern.
This uses glob semantics from LSP 3.17.0:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
Glob patterns can have the following syntax:
• `*` to match one or more characters in a path segment
• `?` to match on one character in a path segment
• `**` to match any number of path segments, including none
• `{}` to group conditions (e.g. `*.{ts,js}` matches TypeScript and
JavaScript files)
• `[]` to declare a range of characters to match in a path segment (e.g.,
`example.[0-9]` to match on `example.0`, `example.1`, …)
• `[!...]` to negate a range of characters to match in a path segment
(e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
`example.0`)
Parameters: ~
• {pattern} (`string`) The raw glob pattern
Return: ~
(`vim.lpeg.Pattern`) pattern An |lua-lpeg| representation of the
pattern
==============================================================================
VIM.LPEG *vim.lpeg*
LPeg is a pattern-matching library for Lua, based on Parsing Expression
Grammars (PEGs). https://bford.info/packrat/
*lua-lpeg* *vim.lpeg.Pattern*
The LPeg library for parsing expression grammars is included as `vim.lpeg`
(https://www.inf.puc-rio.br/~roberto/lpeg/).
In addition, its regex-like interface is available as |vim.re|
(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
Pattern:match({subject}, {init}, {...}) *Pattern:match()*
Matches the given `pattern` against the `subject` string. If the match
succeeds, returns the index in the subject of the first character after
the match, or the captured values (if the pattern captured any value). An
optional numeric argument `init` makes the match start at that position in
the subject string. As usual in Lua libraries, a negative value counts
from the end. Unlike typical pattern-matching functions, `match` works
only in anchored mode; that is, it tries to match the pattern with a
prefix of the given subject string (at position `init`), not with an
arbitrary substring of the subject. So, if we want to find a pattern
anywhere in a string, we must either write a loop in Lua or write a
pattern that matches anywhere.
Example: >lua
local pattern = lpeg.R('az') ^ 1 * -1
assert(pattern:match('hello') == 6)
assert(lpeg.match(pattern, 'hello') == 6)
assert(pattern:match('1 hello') == nil)
<
Parameters: ~
• {subject} (`string`)
• {init} (`integer?`)
• {...} (`any`)
Return: ~
(`any`) ...
vim.lpeg.B({pattern}) *vim.lpeg.B()*
Returns a pattern that matches only if the input string at the current
position is preceded by `patt`. Pattern `patt` must match only strings
with some fixed length, and it cannot contain captures. Like the `and`
predicate, this pattern never consumes any input, independently of success
or failure.
Parameters: ~
• {pattern} (`vim.lpeg.Pattern|string|integer|boolean|table`)
Return: ~
(`vim.lpeg.Pattern`)
vim.lpeg.C({patt}) *vim.lpeg.C()*
Creates a simple capture, which captures the substring of the subject that
matches `patt`. The captured value is a string. If `patt` has other
captures, their values are returned after this one.
Example: >lua
local function split (s, sep)
sep = lpeg.P(sep)
local elem = lpeg.C((1 - sep) ^ 0)
local p = elem * (sep * elem) ^ 0
return lpeg.match(p, s)
end
local a, b, c = split('a,b,c', ',')
assert(a == 'a')
assert(b == 'b')
assert(c == 'c')
<
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Carg({n}) *vim.lpeg.Carg()*
Creates an argument capture. This pattern matches the empty string and
produces the value given as the nth extra argument given in the call to
`lpeg.match`.
Parameters: ~
• {n} (`integer`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cb({name}) *vim.lpeg.Cb()*
Creates a back capture. This pattern matches the empty string and produces
the values produced by the most recent group capture named `name` (where
`name` can be any Lua value). Most recent means the last complete
outermost group capture with the given name. A Complete capture means that
the entire pattern corresponding to the capture has matched. An Outermost
capture means that the capture is not inside another complete capture. In
the same way that LPeg does not specify when it evaluates captures, it
does not specify whether it reuses values previously produced by the group
or re-evaluates them.
Parameters: ~
• {name} (`any`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cc({...}) *vim.lpeg.Cc()*
Creates a constant capture. This pattern matches the empty string and
produces all given values as its captured values.
Parameters: ~
• {...} (`any`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cf({patt}, {func}) *vim.lpeg.Cf()*
Creates a fold capture. If `patt` produces a list of captures C1 C2 ...
Cn, this capture will produce the value
`func(...func(func(C1, C2), C3)...,Cn)`, that is, it will fold (or
accumulate, or reduce) the captures from `patt` using function `func`.
This capture assumes that `patt` should produce at least one capture with
at least one value (of any type), which becomes the initial value of an
accumulator. (If you need a specific initial value, you may prefix a
constant capture to `patt`.) For each subsequent capture, LPeg calls
`func` with this accumulator as the first argument and all values produced
by the capture as extra arguments; the first result from this call becomes
the new value for the accumulator. The final value of the accumulator
becomes the captured value.
Example: >lua
local number = lpeg.R('09') ^ 1 / tonumber
local list = number * (',' * number) ^ 0
local function add(acc, newvalue) return acc + newvalue end
local sum = lpeg.Cf(list, add)
assert(sum:match('10,30,43') == 83)
<
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
• {func} (`fun(acc, newvalue)`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cg({patt}, {name}) *vim.lpeg.Cg()*
Creates a group capture. It groups all values returned by `patt` into a
single capture. The group may be anonymous (if no name is given) or named
with the given name (which can be any non-nil Lua value).
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
• {name} (`string?`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cmt({patt}, {fn}) *vim.lpeg.Cmt()*
Creates a match-time capture. Unlike all other captures, this one is
evaluated immediately when a match occurs (even if it is part of a larger
pattern that fails later). It forces the immediate evaluation of all its
nested captures and then calls `function`. The given function gets as
arguments the entire subject, the current position (after the match of
`patt`), plus any capture values produced by `patt`. The first value
returned by `function` defines how the match happens. If the call returns
a number, the match succeeds and the returned number becomes the new
current position. (Assuming a subject sand current position `i`, the
returned number must be in the range `[i, len(s) + 1]`.) If the call
returns `true`, the match succeeds without consuming any input (so, to
return true is equivalent to return `i`). If the call returns `false`,
`nil`, or no value, the match fails. Any extra values returned by the
function become the values produced by the capture.
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
• {fn} (`fun(s: string, i: integer, ...: any)`) (position:
boolean|integer, ...: any)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cp() *vim.lpeg.Cp()*
Creates a position capture. It matches the empty string and captures the
position in the subject where the match occurs. The captured value is a
number.
Example: >lua
local I = lpeg.Cp()
local function anywhere(p) return lpeg.P({I * p * I + 1 * lpeg.V(1)}) end
local match_start, match_end = anywhere('world'):match('hello world!')
assert(match_start == 7)
assert(match_end == 12)
<
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Cs({patt}) *vim.lpeg.Cs()*
Creates a substitution capture. This function creates a substitution
capture, which captures the substring of the subject that matches `patt`,
with substitutions. For any capture inside `patt` with a value, the
substring that matched the capture is replaced by the capture value (which
should be a string). The final captured value is the string resulting from
all replacements.
Example: >lua
local function gsub (s, patt, repl)
patt = lpeg.P(patt)
patt = lpeg.Cs((patt / repl + 1) ^ 0)
return lpeg.match(patt, s)
end
assert(gsub('Hello, xxx!', 'xxx', 'World') == 'Hello, World!')
<
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.Ct({patt}) *vim.lpeg.Ct()*
Creates a table capture. This capture returns a table with all values from
all anonymous captures made by `patt` inside this table in successive
integer keys, starting at 1. Moreover, for each named capture group
created by `patt`, the first value of the group is put into the table with
the group name as its key. The captured value is only the table.
Parameters: ~
• {patt} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~
(`vim.lpeg.Capture`)
vim.lpeg.locale({tab}) *vim.lpeg.locale()*
Returns a table with patterns for matching some character classes
according to the current locale. The table has fields named `alnum`,
`alpha`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`,
`upper`, and `xdigit`, each one containing a correspondent pattern. Each
pattern matches any single character that belongs to its class. If called
with an argument `table`, then it creates those fields inside the given
table and returns that table.
Example: >lua
lpeg.locale(lpeg)
local space = lpeg.space ^ 0
local name = lpeg.C(lpeg.alpha ^ 1) * space
local sep = lpeg.S(',;') * space
local pair = lpeg.Cg(name * '=' * space * name) * sep ^ -1
local list = lpeg.Cf(lpeg.Ct('') * pair ^ 0, rawset)
local t = list:match('a=b, c = hi; next = pi')
assert(t.a == 'b')
assert(t.c == 'hi')
assert(t.next == 'pi')
local locale = lpeg.locale()
assert(type(locale.digit) == 'userdata')
<
Parameters: ~
• {tab} (`table?`)
Return: ~
(`vim.lpeg.Locale`)
vim.lpeg.match({pattern}, {subject}, {init}, {...}) *vim.lpeg.match()*
Matches the given `pattern` against the `subject` string. If the match
succeeds, returns the index in the subject of the first character after
the match, or the captured values (if the pattern captured any value). An
optional numeric argument `init` makes the match start at that position in
the subject string. As usual in Lua libraries, a negative value counts
from the end. Unlike typical pattern-matching functions, `match` works
only in anchored mode; that is, it tries to match the pattern with a
prefix of the given subject string (at position `init`), not with an
arbitrary substring of the subject. So, if we want to find a pattern
anywhere in a string, we must either write a loop in Lua or write a
pattern that matches anywhere.
Example: >lua
local pattern = lpeg.R('az') ^ 1 * -1
assert(pattern:match('hello') == 6)
assert(lpeg.match(pattern, 'hello') == 6)
assert(pattern:match('1 hello') == nil)
<
Parameters: ~
• {pattern} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
• {subject} (`string`)
• {init} (`integer?`)
• {...} (`any`)
Return: ~
(`any`) ...
vim.lpeg.P({value}) *vim.lpeg.P()*
Converts the given value into a proper pattern. The following rules are
applied:
• If the argument is a pattern, it is returned unmodified.
• If the argument is a string, it is translated to a pattern that matches
the string literally.
• If the argument is a non-negative number `n`, the result is a pattern
that matches exactly `n` characters.
• If the argument is a negative number `-n`, the result is a pattern that
succeeds only if the input string has less than `n` characters left:
`lpeg.P(-n)` is equivalent to `-lpeg.P(n)` (see the unary minus
operation).
• If the argument is a boolean, the result is a pattern that always
succeeds or always fails (according to the boolean value), without
consuming any input.
• If the argument is a table, it is interpreted as a grammar (see
Grammars).
• If the argument is a function, returns a pattern equivalent to a
match-time capture over the empty string.
Parameters: ~
• {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~
(`vim.lpeg.Pattern`)
vim.lpeg.R({...}) *vim.lpeg.R()*
Returns a pattern that matches any single character belonging to one of
the given ranges. Each `range` is a string `xy` of length 2, representing
all characters with code between the codes of `x` and `y` (both
inclusive). As an example, the pattern `lpeg.R('09')` matches any digit,
and `lpeg.R('az', 'AZ')` matches any ASCII letter.
Example: >lua
local pattern = lpeg.R('az') ^ 1 * -1
assert(pattern:match('hello') == 6)
<
Parameters: ~
• {...} (`string`)
Return: ~
(`vim.lpeg.Pattern`)
vim.lpeg.S({string}) *vim.lpeg.S()*
Returns a pattern that matches any single character that appears in the
given string (the `S` stands for Set). As an example, the pattern
`lpeg.S('+-*/')` matches any arithmetic operator. Note that, if `s` is a
character (that is, a string of length 1), then `lpeg.P(s)` is equivalent
to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also that both
`lpeg.S('')` and `lpeg.R()` are patterns that always fail.
Parameters: ~
• {string} (`string`)
Return: ~
(`vim.lpeg.Pattern`)
vim.lpeg.setmaxstack({max}) *vim.lpeg.setmaxstack()*
Sets a limit for the size of the backtrack stack used by LPeg to track
calls and choices. The default limit is `400`. Most well-written patterns
need little backtrack levels and therefore you seldom need to change this
limit; before changing it you should try to rewrite your pattern to avoid
the need for extra space. Nevertheless, a few useful patterns may
overflow. Also, with recursive grammars, subjects with deep recursion may
also need larger limits.
Parameters: ~
• {max} (`integer`)
vim.lpeg.type({value}) *vim.lpeg.type()*
Returns the string `"pattern"` if the given value is a pattern, otherwise
`nil`.
Parameters: ~
• {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
Return: ~
(`"pattern"?`)
vim.lpeg.V({v}) *vim.lpeg.V()*
Creates a non-terminal (a variable) for a grammar. This operation creates
a non-terminal (a variable) for a grammar. The created non-terminal refers
to the rule indexed by `v` in the enclosing grammar.
Example: >lua
local b = lpeg.P({'(' * ((1 - lpeg.S '()') + lpeg.V(1)) ^ 0 * ')'})
assert(b:match('((string))') == 11)
assert(b:match('(') == nil)
<
Parameters: ~
• {v} (`boolean|string|number|function|table|thread|userdata|lightuserdata`)
Return: ~
(`vim.lpeg.Pattern`)
vim.lpeg.version() *vim.lpeg.version()*
Returns a string with the running version of LPeg.
Return: ~
(`string`)
==============================================================================
VIM.RE *vim.re*
The `vim.re` module provides a conventional regex-like syntax for pattern
usage within LPeg |vim.lpeg|. (Unrelated to |vim.regex| which provides Vim
|regexp| from Lua.)
See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
documentation including regex syntax and examples.
vim.re.compile({string}, {defs}) *vim.re.compile()*
Compiles the given {string} and returns an equivalent LPeg pattern. The
given string may define either an expression or a grammar. The optional
{defs} table provides extra Lua values to be used by the pattern.
Parameters: ~
• {string} (`string`)
• {defs} (`table?`)
Return: ~
(`vim.lpeg.Pattern`)
vim.re.find({subject}, {pattern}, {init}) *vim.re.find()*
Searches the given {pattern} in the given {subject}. If it finds a match,
returns the index where this occurrence starts and the index where it
ends. Otherwise, returns nil.
An optional numeric argument {init} makes the search starts at that
position in the subject string. As usual in Lua libraries, a negative
value counts from the end.
Parameters: ~
• {subject} (`string`)
• {pattern} (`vim.lpeg.Pattern|string`)
• {init} (`integer?`)
Return (multiple): ~
(`integer?`) the index where the occurrence starts, nil if no match
(`integer?`) the index where the occurrence ends, nil if no match
vim.re.gsub({subject}, {pattern}, {replacement}) *vim.re.gsub()*
Does a global substitution, replacing all occurrences of {pattern} in the
given {subject} by {replacement}.
Parameters: ~
• {subject} (`string`)
• {pattern} (`vim.lpeg.Pattern|string`)
• {replacement} (`string`)
Return: ~
(`string`)
vim.re.match({subject}, {pattern}, {init}) *vim.re.match()*
Matches the given {pattern} against the given {subject}, returning all
captures.
Parameters: ~
• {subject} (`string`)
• {pattern} (`vim.lpeg.Pattern|string`)
• {init} (`integer?`)
Return: ~
(`integer|vim.lpeg.Capture?`)
See also: ~
• vim.lpeg.match()
vim.re.updatelocale() *vim.re.updatelocale()*
Updates the pre-defined character classes to the current locale.
==============================================================================
VIM.REGEX *vim.regex*
Vim regexes can be used directly from Lua. Currently they only allow matching
within a single line.
*regex:match_line()*
regex:match_line({bufnr}, {line_idx}, {start}, {end_})
Matches line at `line_idx` (zero-based) in buffer `bufnr`. Match is
restricted to byte index range `start` and `end_` if given, otherwise see
|regex:match_str()|. Returned byte indices are relative to `start` if
given.
Parameters: ~
• {bufnr} (`integer`)
• {line_idx} (`integer`)
• {start} (`integer?`)
• {end_} (`integer?`)
Return (multiple): ~
(`integer?`) match start (byte index) relative to `start`, or `nil` if
no match
(`integer?`) match end (byte index) relative to `start`, or `nil` if
no match
regex:match_str({str}) *regex:match_str()*
Matches string `str` against this regex. To match the string precisely,
surround the regex with "^" and "$". Returns the byte indices for the
start and end of the match, or `nil` if there is no match. Because any
integer is "truthy", `regex:match_str()` can be directly used as a
condition in an if-statement.
Parameters: ~
• {str} (`string`)
Return (multiple): ~
(`integer?`) match start (byte index), or `nil` if no match
(`integer?`) match end (byte index), or `nil` if no match
vim.regex({re}) *vim.regex()*
Parses the Vim regex `re` and returns a regex object. Regexes are "magic"
and case-sensitive by default, regardless of 'magic' and 'ignorecase'.
They can be controlled with flags, see |/magic| and |/ignorecase|.
Parameters: ~
• {re} (`string`)
Return: ~
(`vim.regex`)
==============================================================================
Lua module: vim.secure *vim.secure*
vim.secure.read({path}) *vim.secure.read()*
Attempt to read the file at {path} prompting the user if the file should
be trusted. The user's choice is persisted in a trust database at
$XDG_STATE_HOME/nvim/trust.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {path} (`string`) Path to a file to read.
Return: ~
(`string?`) The contents of the given file if it exists and is
trusted, or nil otherwise.
See also: ~
• |:trust|
vim.secure.trust({opts}) *vim.secure.trust()*
Manage the trust database.
The trust database is located at |$XDG_STATE_HOME|/nvim/trust.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {opts} (`table`) A table with the following fields:
• {action} (`'allow'|'deny'|'remove'`) - `'allow'` to add a
file to the trust database and trust it,
• `'deny'` to add a file to the trust database and deny it,
• `'remove'` to remove file from the trust database
• {path}? (`string`) Path to a file to update. Mutually
exclusive with {bufnr}. Cannot be used when {action} is
"allow".
• {bufnr}? (`integer`) Buffer number to update. Mutually
exclusive with {path}.
Return (multiple): ~
(`boolean`) success true if operation was successful
(`string`) msg full path if operation was successful, else error
message
==============================================================================
Lua module: vim.version *vim.version*
The `vim.version` module provides functions for comparing versions and ranges
conforming to the https://semver.org spec. Plugins, and plugin managers, can
use this to check available tools and dependencies on the current system.
Example: >lua
local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
if vim.version.gt(v, {3, 2, 0}) then
-- ...
end
<
*vim.version()* returns the version of the current Nvim process.
VERSION RANGE SPEC *version-range*
A version "range spec" defines a semantic version range which can be tested
against a version, using |vim.version.range()|.
Supported range specs are shown in the following table. Note: suffixed
versions (1.2.3-rc1) are not matched. >
1.2.3 is 1.2.3
=1.2.3 is 1.2.3
>1.2.3 greater than 1.2.3
<1.2.3 before 1.2.3
>=1.2.3 at least 1.2.3
~1.2.3 is >=1.2.3 <1.3.0 "reasonably close to 1.2.3"
^1.2.3 is >=1.2.3 <2.0.0 "compatible with 1.2.3"
^0.2.3 is >=0.2.3 <0.3.0 (0.x.x is special)
^0.0.1 is =0.0.1 (0.0.x is special)
^1.2 is >=1.2.0 <2.0.0 (like ^1.2.0)
~1.2 is >=1.2.0 <1.3.0 (like ~1.2.0)
^1 is >=1.0.0 <2.0.0 "compatible with 1"
~1 same "reasonably close to 1"
1.x same
1.* same
1 same
* any version
x same
1.2.3 - 2.3.4 is >=1.2.3 <=2.3.4
Partial right: missing pieces treated as x (2.3 => 2.3.x).
1.2.3 - 2.3 is >=1.2.3 <2.4.0
1.2.3 - 2 is >=1.2.3 <3.0.0
Partial left: missing pieces treated as 0 (1.2 => 1.2.0).
1.2 - 2.3.0 is 1.2.0 - 2.3.0
<
vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parses and compares two version objects (the result of
|vim.version.parse()|, or specified literally as a `{major, minor, patch}`
tuple, e.g. `{1, 0, 3}`).
Example: >lua
if vim.version.cmp({1,0,3}, {0,2,1}) == 0 then
-- ...
end
local v1 = vim.version.parse('1.0.3-pre')
local v2 = vim.version.parse('0.2.1')
if vim.version.cmp(v1, v2) == 0 then
-- ...
end
<
Note: ~
• Per semver, build metadata is ignored when comparing two
otherwise-equivalent versions.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`) Version object.
• {v2} (`vim.Version|number[]|string`) Version to compare with `v1`.
Return: ~
(`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
vim.version.eq({v1}, {v2}) *vim.version.eq()*
Returns `true` if the given versions are equal. See |vim.version.cmp()|
for usage.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
vim.version.ge({v1}, {v2}) *vim.version.ge()*
Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
Attributes: ~
Since: 0.10.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
vim.version.gt({v1}, {v2}) *vim.version.gt()*
Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
vim.version.last({versions}) *vim.version.last()*
TODO: generalize this, move to func.lua
Parameters: ~
• {versions} (`vim.Version[]`)
Return: ~
(`vim.Version?`)
vim.version.le({v1}, {v2}) *vim.version.le()*
Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
Attributes: ~
Since: 0.10.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
vim.version.lt({v1}, {v2}) *vim.version.lt()*
Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
Attributes: ~
Since: 0.9.0
Parameters: ~
• {v1} (`vim.Version|number[]|string`)
• {v2} (`vim.Version|number[]|string`)
Return: ~
(`boolean`)
vim.version.parse({version}, {opts}) *vim.version.parse()*
Parses a semantic version string and returns a version object which can be
used with other `vim.version` functions. For example "1.0.1-rc1+build.2"
returns: >
{ major = 1, minor = 0, patch = 1, prerelease = "rc1", build = "build.2" }
<
Attributes: ~
Since: 0.9.0
Parameters: ~
• {version} (`string`) Version string to parse.
• {opts} (`table?`) Optional keyword arguments:
• strict (boolean): Default false. If `true`, no coercion
is attempted on input not conforming to semver v2.0.0. If
`false`, `parse()` attempts to coerce input such as
"1.0", "0-x", "tmux 3.2a" into valid versions.
Return: ~
(`vim.Version?`) parsed_version Version object or `nil` if input is
invalid.
See also: ~
• https://semver.org/spec/v2.0.0.html
vim.version.range({spec}) *vim.version.range()*
Parses a semver |version-range| "spec" and returns a range object: >
{
from: Version
to: Version
has(v: string|Version)
}
<
`:has()` checks if a version is in the range (inclusive `from`, exclusive
`to`).
Example: >lua
local r = vim.version.range('1.0.0 - 2.0.0')
print(r:has('1.9.9')) -- true
print(r:has('2.0.0')) -- false
print(r:has(vim.version())) -- check against current Nvim version
<
Or use cmp(), le(), lt(), ge(), gt(), and/or eq() to compare a version
against `.to` and `.from` directly: >lua
local r = vim.version.range('1.0.0 - 2.0.0') -- >=1.0, <2.0
print(vim.version.ge({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to))
<
Attributes: ~
Since: 0.9.0
Parameters: ~
• {spec} (`string`) Version range "spec"
Return: ~
(`table?`) A table with the following fields:
• {from} (`vim.Version`)
• {to}? (`vim.Version`)
• {has} (`fun(self: vim.VersionRange, version: string|vim.Version)`)
See also: ~
• https://github.com/npm/node-semver#ranges
==============================================================================
Lua module: vim.iter *vim.iter*
*vim.iter()* is an interface for |iterable|s: it wraps a table or function
argument into an *Iter* object with methods (such as |Iter:filter()| and
|Iter:map()|) that transform the underlying source data. These methods can be
chained to create iterator "pipelines": the output of each pipeline stage is
input to the next stage. The first stage depends on the type passed to
`vim.iter()`:
• Lists or arrays (|lua-list|) yield only the value of each element.
• Holes (nil values) are allowed (but discarded).
• Use pairs() to treat array/list tables as dicts (preserve holes and
non-contiguous integer keys): `vim.iter(pairs(…))`.
• Use |Iter:enumerate()| to also pass the index to the next stage.
• Or initialize with ipairs(): `vim.iter(ipairs(…))`.
• Non-list tables (|lua-dict|) yield both the key and value of each element.
• Function |iterator|s yield all values returned by the underlying function.
• Tables with a |__call()| metamethod are treated as function iterators.
The iterator pipeline terminates when the underlying |iterable| is exhausted
(for function iterators this means it returned nil).
Note: `vim.iter()` scans table input to decide if it is a list or a dict; to
avoid this cost you can wrap the table with an iterator e.g.
`vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator|
operations such as |Iter:rev()|).
Examples: >lua
local it = vim.iter({ 1, 2, 3, 4, 5 })
it:map(function(v)
return v * 3
end)
it:rev()
it:skip(2)
it:totable()
-- { 9, 6, 3 }
-- ipairs() is a function iterator which returns both the index (i) and the value (v)
vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
if i > 2 then return v end
end):totable()
-- { 3, 4, 5 }
local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
it:map(function(s) return tonumber(s) end)
for i, d in it:enumerate() do
print(string.format("Column %d is %d", i, d))
end
-- Column 1 is 1
-- Column 2 is 2
-- Column 3 is 3
-- Column 4 is 4
-- Column 5 is 5
vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
return k == 'z'
end)
-- true
local rb = vim.ringbuf(3)
rb:push("a")
rb:push("b")
vim.iter(rb):totable()
-- { "a", "b" }
<
Iter:all({pred}) *Iter:all()*
Returns true if all items in the iterator match the given predicate.
Parameters: ~
• {pred} (`fun(...):boolean`) Predicate function. Takes all values
returned from the previous stage in the pipeline as arguments
and returns true if the predicate matches.
Iter:any({pred}) *Iter:any()*
Returns true if any of the items in the iterator match the given
predicate.
Parameters: ~
• {pred} (`fun(...):boolean`) Predicate function. Takes all values
returned from the previous stage in the pipeline as arguments
and returns true if the predicate matches.
Iter:each({f}) *Iter:each()*
Calls a function once for each item in the pipeline, draining the
iterator.
For functions with side effects. To modify the values in the iterator, use
|Iter:map()|.
Parameters: ~
• {f} (`fun(...)`) Function to execute for each item in the pipeline.
Takes all of the values returned by the previous stage in the
pipeline as arguments.
Iter:enumerate() *Iter:enumerate()*
Yields the item index (count) and value for each item of an iterator
pipeline.
For list tables, this is more efficient: >lua
vim.iter(ipairs(t))
<
instead of: >lua
vim.iter(t):enumerate()
<
Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next()
-- 1 'a'
it:next()
-- 2 'b'
it:next()
-- 3 'c'
<
Return: ~
(`Iter`)
Iter:filter({f}) *Iter:filter()*
Filters an iterator pipeline.
Example: >lua
local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded)
<
Parameters: ~
• {f} (`fun(...):boolean`) Takes all values returned from the previous
stage in the pipeline and returns false or nil if the current
iterator element should be removed.
Return: ~
(`Iter`)
Iter:find({f}) *Iter:find()*
Find the first value in the iterator that satisfies the given predicate.
Advances the iterator. Returns nil and drains the iterator if no value is
found.
Examples: >lua
local it = vim.iter({ 3, 6, 9, 12 })
it:find(12)
-- 12
local it = vim.iter({ 3, 6, 9, 12 })
it:find(20)
-- nil
local it = vim.iter({ 3, 6, 9, 12 })
it:find(function(v) return v % 4 == 0 end)
-- 12
<
Parameters: ~
• {f} (`any`)
Return: ~
(`any`)
Iter:flatten({depth}) *Iter:flatten()*
Flattens a |list-iterator|, un-nesting nested values up to the given
{depth}. Errors if it attempts to flatten a dict-like value.
Examples: >lua
vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
-- { 1, 2, { 3 } }
vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
-- { 1, { a = 2 }, 3 }
vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
-- error: attempt to flatten a dict-like table
<
Parameters: ~
• {depth} (`number?`) Depth to which |list-iterator| should be
flattened (defaults to 1)
Return: ~
(`Iter`)
Iter:fold({init}, {f}) *Iter:fold()*
Folds ("reduces") an iterator into a single value. *Iter:reduce()*
Examples: >lua
-- Create a new table with only even values
vim.iter({ a = 1, b = 2, c = 3, d = 4 })
:filter(function(k, v) return v % 2 == 0 end)
:fold({}, function(acc, k, v)
acc[k] = v
return acc
end) --> { b = 2, d = 4 }
-- Get the "maximum" item of an iterable.
vim.iter({ -99, -4, 3, 42, 0, 0, 7 })
:fold({}, function(acc, v)
acc.max = math.max(v, acc.max or v)
return acc
end) --> { max = 42 }
<
Parameters: ~
• {init} (`any`) Initial value of the accumulator.
• {f} (`fun(acc:A, ...):A`) Accumulation function.
Return: ~
(`any`)
Iter:join({delim}) *Iter:join()*
Collect the iterator into a delimited string.
Each element in the iterator is joined into a string separated by {delim}.
Consumes the iterator.
Parameters: ~
• {delim} (`string`) Delimiter
Return: ~
(`string`)
Iter:last() *Iter:last()*
Drains the iterator and returns the last item.
Example: >lua
local it = vim.iter(vim.gsplit('abcdefg', ''))
it:last()
-- 'g'
local it = vim.iter({ 3, 6, 9, 12, 15 })
it:last()
-- 15
<
Return: ~
(`any`)
See also: ~
• |Iter:rpeek()|
Iter:map({f}) *Iter:map()*
Maps the items of an iterator pipeline to the values returned by `f`.
If the map function returns nil, the value is filtered from the iterator.
Example: >lua
local it = vim.iter({ 1, 2, 3, 4 }):map(function(v)
if v % 2 == 0 then
return v * 3
end
end)
it:totable()
-- { 6, 12 }
<
Parameters: ~
• {f} (`fun(...):...:any`) Mapping function. Takes all values returned
from the previous stage in the pipeline as arguments and returns
one or more new values, which are used in the next pipeline
stage. Nil return values are filtered from the output.
Return: ~
(`Iter`)
Iter:next() *Iter:next()*
Gets the next value from the iterator.
Example: >lua
local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber)
it:next()
-- 1
it:next()
-- 2
it:next()
-- 3
<
Return: ~
(`any`)
Iter:nth({n}) *Iter:nth()*
Gets the nth value of an iterator (and advances to it).
If `n` is negative, offsets from the end of a |list-iterator|.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 })
it:nth(2)
-- 6
it:nth(2)
-- 12
local it2 = vim.iter({ 3, 6, 9, 12 })
it2:nth(-2)
-- 9
it2:nth(-2)
-- 3
<
Parameters: ~
• {n} (`number`) Index of the value to return. May be negative if the
source is a |list-iterator|.
Return: ~
(`any`)
Iter:peek() *Iter:peek()*
Gets the next value in a |list-iterator| without consuming it.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 })
it:peek()
-- 3
it:peek()
-- 3
it:next()
-- 3
<
Return: ~
(`any`)
Iter:pop() *Iter:pop()*
"Pops" a value from a |list-iterator| (gets the last value and decrements
the tail).
Example: >lua
local it = vim.iter({1, 2, 3, 4})
it:pop()
-- 4
it:pop()
-- 3
<
Return: ~
(`any`)
Iter:rev() *Iter:rev()*
Reverses a |list-iterator| pipeline.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):rev()
it:totable()
-- { 12, 9, 6, 3 }
<
Return: ~
(`Iter`)
Iter:rfind({f}) *Iter:rfind()*
Gets the first value satisfying a predicate, from the end of a
|list-iterator|.
Advances the iterator. Returns nil and drains the iterator if no value is
found.
Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1)
-- 5 1
it:rfind(1)
-- 1 1
<
Parameters: ~
• {f} (`any`)
Return: ~
(`any`)
See also: ~
• |Iter:find()|
Iter:rpeek() *Iter:rpeek()*
Gets the last value of a |list-iterator| without consuming it.
Example: >lua
local it = vim.iter({1, 2, 3, 4})
it:rpeek()
-- 4
it:rpeek()
-- 4
it:pop()
-- 4
<
Return: ~
(`any`)
See also: ~
• |Iter:last()|
Iter:rskip({n}) *Iter:rskip()*
Discards `n` values from the end of a |list-iterator| pipeline.
Example: >lua
local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
it:next()
-- 1
it:pop()
-- 3
<
Parameters: ~
• {n} (`number`) Number of values to skip.
Return: ~
(`Iter`)
Iter:skip({n}) *Iter:skip()*
Skips `n` values of an iterator pipeline.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):skip(2)
it:next()
-- 9
<
Parameters: ~
• {n} (`number`) Number of values to skip.
Return: ~
(`Iter`)
Iter:slice({first}, {last}) *Iter:slice()*
Sets the start and end of a |list-iterator| pipeline.
Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
Parameters: ~
• {first} (`number`)
• {last} (`number`)
Return: ~
(`Iter`)
Iter:take({n}) *Iter:take()*
Transforms an iterator to yield only the first n values.
Example: >lua
local it = vim.iter({ 1, 2, 3, 4 }):take(2)
it:next()
-- 1
it:next()
-- 2
it:next()
-- nil
<
Parameters: ~
• {n} (`integer`)
Return: ~
(`Iter`)
Iter:totable() *Iter:totable()*
Collect the iterator into a table.
The resulting table depends on the initial source in the iterator
pipeline. Array-like tables and function iterators will be collected into
an array-like table. If multiple values are returned from the final stage
in the iterator pipeline, each value will be included in a table.
Examples: >lua
vim.iter(string.gmatch('100 20 50', '%d+')):map(tonumber):totable()
-- { 100, 20, 50 }
vim.iter({ 1, 2, 3 }):map(function(v) return v, 2 * v end):totable()
-- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
-- { { 'a', 1 }, { 'c', 3 } }
<
The generated table is an array-like table with consecutive, numeric
indices. To create a map-like table with arbitrary keys, use
|Iter:fold()|.
Return: ~
(`table`)
==============================================================================
Lua module: vim.snippet *vim.snippet*
*vim.snippet.ActiveFilter*
Fields: ~
• {direction} (`vim.snippet.Direction`) Navigation direction. -1 for
previous, 1 for next.
vim.snippet.active({filter}) *vim.snippet.active()*
Returns `true` if there's an active snippet in the current buffer,
applying the given filter if provided.
Parameters: ~
• {filter} (`vim.snippet.ActiveFilter?`) Filter to constrain the search
with:
• `direction` (vim.snippet.Direction): Navigation direction.
Will return `true` if the snippet can be jumped in the
given direction. See |vim.snippet.ActiveFilter|.
Return: ~
(`boolean`)
vim.snippet.expand({input}) *vim.snippet.expand()*
Expands the given snippet text. Refer to
https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax
for the specification of valid input.
Tabstops are highlighted with |hl-SnippetTabstop|.
Parameters: ~
• {input} (`string`)
vim.snippet.jump({direction}) *vim.snippet.jump()*
Jumps to the next (or previous) placeholder in the current snippet, if
possible.
By default `<Tab>` is setup to jump if a snippet is active. The default
mapping looks like: >lua
vim.keymap.set({ 'i', 's' }, '<Tab>', function()
if vim.snippet.active({ direction = 1 }) then
return '<Cmd>lua vim.snippet.jump(1)<CR>'
else
return '<Tab>'
end
end, { descr = '...', expr = true, silent = true })
<
Parameters: ~
• {direction} (`vim.snippet.Direction`) Navigation direction. -1 for
previous, 1 for next.
vim.snippet.stop() *vim.snippet.stop()*
Exits the current snippet.
==============================================================================
Lua module: vim.text *vim.text*
vim.text.hexdecode({enc}) *vim.text.hexdecode()*
Hex decode a string.
Parameters: ~
• {enc} (`string`) String to decode
Return (multiple): ~
(`string?`) Decoded string
(`string?`) Error message, if any
vim.text.hexencode({str}) *vim.text.hexencode()*
Hex encode a string.
Parameters: ~
• {str} (`string`) String to encode
Return: ~
(`string`) Hex encoded string
vim.text.indent({size}, {text}, {opts}) *vim.text.indent()*
Sets the indent (i.e. the common leading whitespace) of non-empty lines in
`text` to `size` spaces/tabs.
Indent is calculated by number of consecutive indent chars.
• The first indented, non-empty line decides the indent char (space/tab):
• `SPC SPC TAB …` = two-space indent.
• `TAB SPC …` = one-tab indent.
• Set `opts.expandtab` to treat tabs as spaces.
To "dedent" (remove the common indent), pass `size=0`: >lua
vim.print(vim.text.indent(0, ' a\n b\n'))
<
To adjust relative-to an existing indent, call indent() twice: >lua
local indented, old_indent = vim.text.indent(0, ' a\n b\n')
indented = vim.text.indent(old_indent + 2, indented)
vim.print(indented)
<
To ignore the final, blank line when calculating the indent, use gsub()
before calling indent(): >lua
local text = ' a\n b\n '
vim.print(vim.text.indent(0, (text:gsub('\n[\t ]+\n?$', '\n'))))
<
Parameters: ~
• {size} (`integer`) Number of spaces.
• {text} (`string`) Text to indent.
• {opts} (`{ expandtab?: number }?`)
Return (multiple): ~
(`string`) Indented text.
(`integer`) Indent size before modification.
==============================================================================
Lua module: tohtml *vim.tohtml*
:[range]TOhtml {file} *:TOhtml*
Converts the buffer shown in the current window to HTML, opens the generated
HTML in a new split window, and saves its contents to {file}. If {file} is not
given, a temporary file (created by |tempname()|) is used.
tohtml.tohtml({winid}, {opt}) *tohtml.tohtml.tohtml()*
Converts the buffer shown in the window {winid} to HTML and returns the
output as a list of string.
Parameters: ~
• {winid} (`integer?`) Window to convert (defaults to current window)
• {opt} (`table?`) Optional parameters.
• {title}? (`string|false`, default: buffer name) Title tag
to set in the generated HTML code.
• {number_lines}? (`boolean`, default: `false`) Show line
numbers.
• {font}? (`string[]|string`, default: `guifont`) Fonts to
use.
• {width}? (`integer`, default: 'textwidth' if non-zero or
window width otherwise) Width used for items which are
either right aligned or repeat a character infinitely.
• {range}? (`integer[]`, default: entire buffer) Range of
rows to use.
Return: ~
(`string[]`)
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: