├── .gitattributes ├── scripts ├── docgen.sh ├── sections_tags.awk └── to_vimdoc.sed ├── README.md ├── doc └── nvim-lua-guide.txt └── OLD_README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | scripts/* -linguist-detectable 2 | -------------------------------------------------------------------------------- /scripts/docgen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | SCRIPT_ROOT="$(dirname "$0")" 4 | 5 | "$SCRIPT_ROOT"/to_vimdoc.sed "$SCRIPT_ROOT"/../README.md | fmt -s | "$SCRIPT_ROOT"/sections_tags.awk > "$SCRIPT_ROOT"/../doc/nvim-lua-guide.txt 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **:warning: :warning: :warning: A more up-to-date version of this guide is available in the Neovim documentation, see [`:help lua-guide`](https://neovim.io/doc/user/lua-guide.html#lua-guide) :warning: :warning: :warning:** 2 | 3 | If you still want to read the old guide, see [OLD_README.md](OLD_README.md) 4 | -------------------------------------------------------------------------------- /scripts/sections_tags.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | { 3 | if (lastline ~ /^=+$/) { 4 | tag = tolower($0) 5 | gsub(/[^A-Za-z]/, "-", tag) 6 | print $0 7 | printf("%80s", "*" "luaguide-" tag "*") 8 | print "" 9 | } 10 | else { 11 | print 12 | } 13 | } 14 | 15 | { lastline = $0 } 16 | -------------------------------------------------------------------------------- /scripts/to_vimdoc.sed: -------------------------------------------------------------------------------- 1 | #!/bin/sed -f 2 | 3 | # Title 4 | /^# / { 5 | s/# /*nvim-lua-guide.txt* / 6 | } 7 | 8 | # Sections 9 | /^## / { 10 | s/[a-z]/\u&/g 11 | s/## // 12 | i============================================================================== 13 | } 14 | 15 | # Sub-sections, tips and caveats 16 | /^####\? / { 17 | s/####\? // 18 | s/.*/&~/ 19 | } 20 | 21 | # Help links 22 | s/\[`vim\.api\.\(.*\)`\](.*)/|\1|/ 23 | s/\[`:help \(.*\)`\](.*)/|\1|/ 24 | s/\[`\(.*\)`\](.*)/|\1|/ 25 | 26 | # Markdown links 27 | /\[.*\](http.*)/ { 28 | y/[]()/ : / 29 | } 30 | 31 | # Todos 32 | s/\*\*TODO\*\*: /\t*Todo\t/g 33 | 34 | # Warnings 35 | s/\*\*\(WARNING\)\*\*/\1/ 36 | 37 | # Code blocks 38 | /^```.*$/,/^```$/{ 39 | s/.*/ &/ 40 | s/```.\+/>/ 41 | s/\s*```$/ 115 | 📂 ~/.config/nvim 116 | ├── 📁 after 117 | ├── 📁 ftplugin 118 | ├── 📂 lua 119 | │ ├── 🌑 myluamodule.lua 120 | │ └── 📂 other_modules 121 | │ ├── 🌑 anothermodule.lua 122 | │ └── 🌑 init.lua 123 | ├── 📁 pack 124 | ├── 📁 plugin 125 | ├── 📁 syntax 126 | └── 🇻 init.vim 127 | < 128 | 129 | The following Lua code will load `myluamodule.lua`: 130 | 131 | > 132 | require('myluamodule') 133 | < 134 | 135 | Notice the absence of a `.lua` extension. 136 | 137 | Similarly, loading `other_modules/anothermodule.lua` is done like so: 138 | 139 | > 140 | require('other_modules.anothermodule') 141 | -- or 142 | require('other_modules/anothermodule') 143 | < 144 | 145 | Path separators are denoted by either a dot `.` or a slash `/`. 146 | 147 | A folder containing an `init.lua` file can be required directly, without 148 | having to specify the name of the file. 149 | 150 | > 151 | require('other_modules') -- loads other_modules/init.lua 152 | < 153 | 154 | Requiring a nonexistent module or a module which contains syntax errors 155 | aborts the currently executing script. 156 | `pcall()` may be used to prevent errors. 157 | 158 | > 159 | local ok, _ = pcall(require, 'module_with_error') 160 | if not ok then 161 | -- not loaded 162 | end 163 | < 164 | 165 | See also: 166 | - |lua-require| 167 | 168 | Tips~ 169 | 170 | Several Lua plugins might have identical filenames in their `lua/` 171 | folder. This could lead to namespace clashes. 172 | 173 | If two different plugins have a `lua/main.lua` file, then doing 174 | `require('main')` is ambiguous: which file do we want to source? 175 | 176 | It might be a good idea to namespace your config or your plugin with a 177 | top-level folder, like so: `lua/plugin_name/main.lua` 178 | 179 | Runtime files~ 180 | 181 | Much like Vimscript files, Lua files can be loaded automatically from 182 | special folders in your `runtimepath`. Currently, the following folders 183 | are supported: 184 | 185 | - `colors/` 186 | - `compiler/` 187 | - `ftplugin/` 188 | - `ftdetect/` 189 | - `indent/` 190 | - `plugin/` 191 | - `syntax/` 192 | 193 | Note: in a runtime directory, all `*.vim` files are sourced before 194 | `*.lua` files. 195 | 196 | See also: 197 | - |'runtimepath'| 198 | - |load-plugins| 199 | 200 | Tips~ 201 | 202 | Since runtime files aren't based on the Lua module system, two plugins 203 | can have a `plugin/main.lua` file without it being an issue. 204 | 205 | ============================================================================== 206 | USING LUA FROM VIMSCRIPT 207 | *luaguide-using-lua-from-vimscript* 208 | 209 | :lua~ 210 | 211 | This command executes a chunk of Lua code. 212 | 213 | > 214 | :lua require('myluamodule') 215 | < 216 | 217 | Multi-line scripts are possible using heredoc syntax: 218 | 219 | > 220 | echo "Here's a bigger chunk of Lua code" 221 | 222 | lua << EOF 223 | local mod = require('mymodule') 224 | local tbl = {1, 2, 3} 225 | 226 | for k, v in ipairs(tbl) do 227 | mod.method(v) 228 | end 229 | 230 | print(tbl) 231 | EOF 232 | < 233 | 234 | Note: each `:lua` command has its own scope and variables declared with 235 | the `local` keyword are not accessible outside of the command. This 236 | won't work: 237 | 238 | > 239 | :lua local foo = 1 240 | :lua print(foo) 241 | " prints 'nil' instead of '1' 242 | < 243 | 244 | Note 2: the `print()` function in Lua behaves similarly to the `:echomsg` 245 | command. Its output is saved in the message-history and can be suppressed 246 | by the `:silent` command. 247 | 248 | See also: 249 | 250 | - |:lua| 251 | - |:lua-heredoc| 252 | 253 | :luado~ 254 | 255 | This command executes a chunk of Lua code that acts on a range of lines 256 | in the current buffer. If no range is specified, the whole buffer is 257 | used instead. Whatever string is `return`ed from the chunk is used to 258 | determine what each line should be replaced with. 259 | 260 | The following command would replace every line in the current buffer 261 | with the text `hello world`: 262 | 263 | > 264 | :luado return 'hello world' 265 | < 266 | 267 | Two implicit `line` and `linenr` variables are also provided. `line` 268 | is the text of the line being iterated upon whereas `linenr` is its 269 | number. The following command would make every line whose number is 270 | divisible by 2 uppercase: 271 | 272 | > 273 | :luado if linenr % 2 == 0 then return line:upper() end 274 | < 275 | 276 | See also: 277 | 278 | - |:luado| 279 | 280 | Sourcing Lua files~ 281 | 282 | Neovim provides 3 Ex commands to source Lua files 283 | 284 | - `:luafile` 285 | - `:source` 286 | - `:runtime` 287 | 288 | `:luafile` and `:source` are very similar: 289 | 290 | > 291 | :luafile ~/foo/bar/baz/myluafile.lua 292 | :luafile % 293 | :source ~/foo/bar/baz/myluafile.lua 294 | :source % 295 | < 296 | 297 | `:source` also supports ranges, which can be useful to only execute part 298 | of a script: 299 | 300 | > 301 | :1,10source 302 | < 303 | 304 | `:runtime` is a little different: it uses the `'runtimepath'` option to 305 | determine which files to source. See |:runtime| for more details. 306 | 307 | See also: 308 | 309 | - |:luafile| 310 | - |:source| 311 | - |:runtime| 312 | 313 | Sourcing a lua file vs calling require():~ 314 | 315 | You might be wondering what the difference between calling the `require()` 316 | function and sourcing a Lua file is and whether you should prefer one 317 | way over the other. They have different use cases: 318 | 319 | - `require()`: 320 | - is a built-in Lua function. It allows you to take advantage of 321 | Lua's module system 322 | - searches for modules in `lua/` folders in your `'runtimepath'` 323 | - keeps track of what modules have been loaded and prevents a script 324 | from being parsed and executed a second time. If you change the file 325 | containing the code for a module and try to `require()` it a second 326 | time while Neovim is running, the module will not actually update 327 | - `:luafile`, `:source` and `:runtime`: 328 | - are Ex commands. They do not support modules 329 | - execute the contents of a script regardless of whether it has been 330 | executed before 331 | - `:luafile` and `:source` take a path that is either absolute or 332 | relative to the working directory of the current window 333 | - `:runtime` uses the `'runtimepath'` option to find files 334 | 335 | Files sourced via `:source`, `:runtime` or automatically from runtime 336 | directories will also show up in `:scriptnames` and `--startuptime` 337 | 338 | luaeval()~ 339 | 340 | This built-in Vimscript function evaluates a Lua expression string 341 | and returns its value. Lua data types are automatically converted to 342 | Vimscript types (and vice versa). 343 | 344 | > 345 | " You can store the result in a variable 346 | let variable = luaeval('1 + 1') 347 | echo variable 348 | " 2 349 | let concat = luaeval('"Lua".." is ".."awesome"') 350 | echo concat 351 | " 'Lua is awesome' 352 | 353 | " List-like tables are converted to Vim lists 354 | let list = luaeval('{1, 2, 3, 4}') 355 | echo list[0] 356 | " 1 357 | echo list[1] 358 | " 2 359 | " Note that unlike Lua tables, Vim lists are 0-indexed 360 | 361 | " Dict-like tables are converted to Vim dictionaries 362 | let dict = luaeval('{foo = "bar", baz = "qux"}') 363 | echo dict.foo 364 | " 'bar' 365 | 366 | " Same thing for booleans and nil 367 | echo luaeval('true') 368 | " v:true 369 | echo luaeval('nil') 370 | " v:null 371 | 372 | " You can create Vimscript aliases for Lua functions 373 | let LuaMathPow = luaeval('math.pow') 374 | echo LuaMathPow(2, 2) 375 | " 4 376 | let LuaModuleFunction = luaeval('require("mymodule").myfunction') 377 | call LuaModuleFunction() 378 | 379 | " It is also possible to pass Lua functions as values to Vim functions 380 | lua X = function(k, v) return string.format("%s:%s", k, v) end 381 | echo map([1, 2, 3], luaeval("X")) 382 | < 383 | 384 | `luaeval()` takes an optional second argument that allows you to pass 385 | data to the expression. You can then access that data from Lua using 386 | the magic global `_A`: 387 | 388 | > 389 | echo luaeval('_A[1] + _A[2]', [1, 1]) 390 | " 2 391 | 392 | echo luaeval('string.format("Lua is %s", _A)', 'awesome') 393 | " 'Lua is awesome' 394 | < 395 | 396 | See also: 397 | - |luaeval()| 398 | 399 | v:lua~ 400 | 401 | This global Vim variable allows you to call Lua functions in the global 402 | namespace `_G`: https://www.lua.org/manual/5.1/manual.html#pdf-_G 403 | directly from Vimscript. Again, Vim data types are converted to Lua 404 | types and vice versa. 405 | 406 | > 407 | call v:lua.print('Hello from Lua!') 408 | " 'Hello from Lua!' 409 | 410 | let scream = v:lua.string.rep('A', 10) 411 | echo scream 412 | " 'AAAAAAAAAA' 413 | 414 | " How about a nice statusline? 415 | lua << EOF 416 | function _G.statusline() 417 | local filepath = '%f' 418 | local align_section = '%=' 419 | local percentage_through_file = '%p%%' 420 | return string.format( 421 | '%s%s%s', 422 | filepath, 423 | align_section, 424 | percentage_through_file 425 | ) 426 | end 427 | EOF 428 | 429 | set statusline=%!v:lua.statusline() 430 | 431 | " Also works in expression mappings 432 | lua << EOF 433 | function _G.check_back_space() 434 | local col = vim.api.nvim_win_get_cursor(0)[2] 435 | return (col == 0 or vim.api.nvim_get_current_line():sub(col, 436 | col):match('%s')) and true 437 | end 438 | EOF 439 | 440 | inoremap 441 | \ pumvisible() ? "\" : 442 | \ v:lua.check_back_space() ? "\" : 443 | \ completion#trigger_completion() 444 | 445 | " Call a function from a Lua module by using single quotes and 446 | omitting parentheses: 447 | call v:lua.require'module'.foo() 448 | < 449 | 450 | See also: 451 | - |v:lua| 452 | - |v:lua-call| 453 | 454 | Caveats~ 455 | 456 | This variable can only be used to call functions. The following will 457 | always throw an error: 458 | 459 | > 460 | " Aliasing functions doesn't work 461 | let LuaPrint = v:lua.print 462 | 463 | " Accessing dictionaries doesn't work 464 | echo v:lua.some_global_dict['key'] 465 | 466 | " Using a function as a value doesn't work 467 | echo map([1, 2, 3], v:lua.global_callback) 468 | < 469 | 470 | Tips~ 471 | 472 | You can get Lua syntax highlighting inside .vim files by putting `let 473 | g:vimsyn_embed = 'l'` in your configuration file. See |g:vimsyn_embed| 474 | for more on this option. 475 | 476 | ============================================================================== 477 | THE VIM NAMESPACE 478 | *luaguide-the-vim-namespace* 479 | 480 | Neovim exposes a global `vim` variable which serves as an entry point 481 | to interact with its APIs from Lua. It provides users with an extended 482 | "standard library" of functions as well as various sub-modules. 483 | 484 | Some notable functions and modules include: 485 | 486 | - `vim.inspect`: transform Lua objects into human-readable strings 487 | (useful for inspecting tables) 488 | - `vim.regex`: use Vim regexes from Lua 489 | - `vim.api`: module that exposes API functions (the same API used by 490 | remote plugins) 491 | - `vim.ui`: overridable UI functions that can be leveraged by plugins 492 | - `vim.loop`: module that exposes the functionality of Neovim's event-loop 493 | (using LibUV) 494 | - `vim.lsp`: module that controls the built-in LSP client 495 | - `vim.treesitter`: module that exposes the functionality of the 496 | tree-sitter library 497 | 498 | This list is by no means comprehensive. If you wish to know more about what's 499 | made available by the `vim` variable, |lua-stdlib| and |lua-vim| are the way 500 | to go. Alternatively, you can do `:lua print(vim.inspect(vim))` to get a list 501 | of every module. API functions are documented under |api-global|. 502 | 503 | Tips~ 504 | 505 | Writing `print(vim.inspect(x))` every time you want to inspect the 506 | contents of an object can get pretty tedious. It might be worthwhile 507 | to have a global wrapper function somewhere in your configuration (in 508 | Neovim 0.7.0+, this function is built-in, see |vim.pretty_print()|: 509 | 510 | > 511 | function _G.put(...) 512 | local objects = {} 513 | for i = 1, select('#', ...) do 514 | local v = select(i, ...) 515 | table.insert(objects, vim.inspect(v)) 516 | end 517 | 518 | print(table.concat(objects, '\n')) 519 | return ... 520 | end 521 | < 522 | 523 | You can then inspect the contents of an object very quickly in your code 524 | or from the command-line: 525 | 526 | > 527 | put({1, 2, 3}) 528 | < 529 | 530 | > 531 | :lua put(vim.loop) 532 | < 533 | 534 | Alternatively, you can use the `:lua` command to pretty-print a Lua 535 | expression by prefixing it with `=` (Neovim 0.7+ only): 536 | > 537 | :lua =vim.loop 538 | < 539 | 540 | Additionally, you may find that built-in Lua functions are sometimes 541 | lacking compared to what you would find in other languages (for example 542 | `os.clock()` only returns a value in seconds, not milliseconds). Be 543 | sure to look at the Neovim stdlib (and `vim.fn`, more on that later), 544 | it probably has what you're looking for. 545 | 546 | ============================================================================== 547 | USING VIMSCRIPT FROM LUA 548 | *luaguide-using-vimscript-from-lua* 549 | 550 | vim.api.nvim_eval()~ 551 | 552 | This function evaluates a Vimscript expression string and returns its 553 | value. Vimscript data types are automatically converted to Lua types 554 | (and vice versa). 555 | 556 | It is the Lua equivalent of the `luaeval()` function in Vimscript 557 | 558 | > 559 | -- Data types are converted correctly 560 | print(vim.api.nvim_eval('1 + 1')) -- 2 561 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 562 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) 563 | -- { baz = "qux", foo = "bar" } 564 | print(vim.api.nvim_eval('v:true')) -- true 565 | print(vim.api.nvim_eval('v:null')) -- nil 566 | < 567 | 568 | Caveats~ 569 | 570 | Unlike `luaeval()`, `vim.api.nvim_eval()` does not provide an implicit 571 | `_A` variable to pass data to the expression. 572 | 573 | vim.api.nvim_exec()~ 574 | 575 | This function evaluates a chunk of Vimscript code. It takes in a string 576 | containing the source code to execute and a boolean to determine whether 577 | the output of the code should be returned by the function (you can then 578 | store the output in a variable, for example). 579 | 580 | > 581 | local result = vim.api.nvim_exec( 582 | [[ 583 | let s:mytext = 'hello world' 584 | 585 | function! s:MyFunction(text) 586 | echo a:text 587 | endfunction 588 | 589 | call s:MyFunction(s:mytext) 590 | ]], 591 | true) 592 | 593 | print(result) -- 'hello world' 594 | < 595 | 596 | Caveats~ 597 | 598 | `nvim_exec` does not support script-local variables (`s:`) prior to 599 | Neovim 0.6.0 600 | 601 | vim.api.nvim_command()~ 602 | 603 | This function executes an ex command. It takes in a string containing 604 | the command to execute. 605 | 606 | > 607 | vim.api.nvim_command('new') 608 | vim.api.nvim_command('wincmd H') 609 | vim.api.nvim_command('set nonumber') 610 | vim.api.nvim_command('%s/foo/bar/g') 611 | < 612 | 613 | vim.cmd()~ 614 | 615 | Alias for `vim.api.nvim_exec()`. Only the command argument is needed, 616 | `output` is always set to `false`. 617 | 618 | > 619 | vim.cmd('buffers') 620 | vim.cmd([[ 621 | let g:multiline_list = [ 622 | \ 1, 623 | \ 2, 624 | \ 3, 625 | \ ] 626 | 627 | echo g:multiline_list 628 | ]]) 629 | < 630 | 631 | Tips~ 632 | 633 | Since you have to pass strings to these functions, you often end up 634 | having to escape backslashes: 635 | 636 | > 637 | vim.cmd('%s/\\Vfoo/bar/g') 638 | < 639 | 640 | Double bracketed strings are easier to use as they do not require 641 | escaping characters: 642 | 643 | > 644 | vim.cmd([[%s/\Vfoo/bar/g]]) 645 | < 646 | 647 | vim.api.nvim_replace_termcodes()~ 648 | 649 | This API function allows you to escape terminal codes and Vim keycodes. 650 | 651 | You may have come across mappings like this one: 652 | 653 | > 654 | inoremap pumvisible() ? "\" : "\" 655 | < 656 | 657 | Trying to do the same in Lua can prove to be a challenge. You might be 658 | tempted to do it like this: 659 | 660 | > 661 | function _G.smart_tab() 662 | return vim.fn.pumvisible() == 1 and [[\]] or [[\]] 663 | end 664 | 665 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = 666 | true, noremap = true}) 667 | < 668 | 669 | only to find out that the mapping inserts `\` and `\` 670 | literally... 671 | 672 | Being able to escape keycodes is actually a Vimscript feature. Aside 673 | from the usual escape sequences like `\r`, `\42` or `\x10` that are 674 | common to many programming languages, Vimscript `expr-quotes` (strings 675 | surrounded with double quotes) allow you to escape the human-readable 676 | representation of Vim keycodes. 677 | 678 | Lua doesn't have such a feature built-in. Fortunately, Neovim 679 | has an API function for escaping terminal codes and keycodes: 680 | `nvim_replace_termcodes()` 681 | 682 | > 683 | print(vim.api.nvim_replace_termcodes('', true, true, true)) 684 | < 685 | 686 | This is a little verbose. Making a reusable wrapper can help: 687 | 688 | > 689 | -- The function is called `t` for `termcodes`. 690 | -- You don't have to call it that, but I find the terseness convenient 691 | local function t(str) 692 | -- Adjust boolean arguments as needed 693 | return vim.api.nvim_replace_termcodes(str, true, true, true) 694 | end 695 | 696 | print(t'') 697 | < 698 | 699 | Coming back to our earlier example, this should now work as expected: 700 | 701 | > 702 | local function t(str) 703 | return vim.api.nvim_replace_termcodes(str, true, true, true) 704 | end 705 | 706 | function _G.smart_tab() 707 | return vim.fn.pumvisible() == 1 and t'' or t'' 708 | end 709 | 710 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = 711 | true, noremap = true}) 712 | < 713 | 714 | This is not necessary with `vim.keymap.set()` as it automatically 715 | transforms vim keycodes returned by Lua functions in `expr` mappings 716 | by default: 717 | 718 | > 719 | vim.keymap.set('i', '', function() 720 | return vim.fn.pumvisible() == 1 and '' or '' 721 | end, {expr = true}) 722 | < 723 | 724 | See also: 725 | 726 | - |keycodes| 727 | - |expr-quote| 728 | - |nvim_replace_termcodes()| 729 | 730 | ============================================================================== 731 | MANAGING VIM OPTIONS 732 | *luaguide-managing-vim-options* 733 | 734 | Using api functions~ 735 | 736 | Neovim provides a set of API functions to either set an option or get 737 | its current value: 738 | 739 | - Global options: 740 | - |nvim_set_option()| 741 | - |nvim_get_option()| 742 | - Buffer-local options: 743 | - |nvim_buf_set_option()| 744 | - |nvim_buf_get_option()| 745 | - Window-local options: 746 | - |nvim_win_set_option()| 747 | - |nvim_win_get_option()| 748 | 749 | They take a string containing the name of the option to set/get as well 750 | as the value you want to set it to. 751 | 752 | Boolean options (like `(no)number`) have to be set to either `true` or 753 | `false`: 754 | 755 | > 756 | vim.api.nvim_set_option('smarttab', false) 757 | print(vim.api.nvim_get_option('smarttab')) -- false 758 | < 759 | 760 | Unsurprisingly, string options have to be set to a string: 761 | 762 | > 763 | vim.api.nvim_set_option('selection', 'exclusive') 764 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 765 | < 766 | 767 | Number options accept a number: 768 | 769 | > 770 | vim.api.nvim_set_option('updatetime', 3000) 771 | print(vim.api.nvim_get_option('updatetime')) -- 3000 772 | < 773 | 774 | Buffer-local and window-local options also need a buffer number or 775 | a window number (using `0` will set/get the option for the current 776 | buffer/window): 777 | 778 | > 779 | vim.api.nvim_win_set_option(0, 'number', true) 780 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 781 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 782 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 783 | < 784 | 785 | Using meta-accessors~ 786 | 787 | A few meta-accessors are available if you want to set options in a more 788 | "idiomatic" way. They essentially wrap the above API functions and allow 789 | you to manipulate options as if they were variables: 790 | 791 | - |vim.o|: behaves like `:let &{option-name}` 792 | - |vim.go|: behaves like `:let &g:{option-name}` 793 | - |vim.bo|: behaves like `:let &l:{option-name}` for buffer-local options 794 | - |vim.wo|: behaves like `:let &l:{option-name}` for window-local options 795 | 796 | > 797 | vim.o.smarttab = false -- let &smarttab = v:false 798 | print(vim.o.smarttab) -- false 799 | vim.o.isfname = vim.o.isfname .. ',@-@' -- on Linux: let &isfname = 800 | &isfname .. ',@-@' 801 | print(vim.o.isfname) -- '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@' 802 | 803 | vim.bo.shiftwidth = 4 804 | print(vim.bo.shiftwidth) -- 4 805 | < 806 | 807 | You can specify a number for buffer-local and window-local options. If 808 | no number is given, the current buffer/window is used: 809 | 810 | > 811 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 812 | 'expandtab', true) 813 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 814 | 'number', true) 815 | < 816 | 817 | These wrappers also have more sophisticated `vim.opt*` variants that 818 | provide convenient mechanisms for setting options in Lua. They're similar 819 | to what you might be used to in your `init.vim`: 820 | 821 | - `vim.opt`: behaves like `:set` 822 | - `vim.opt_global`: behaves like `:setglobal` 823 | - `vim.opt_local`: behaves like `:setlocal` 824 | 825 | > 826 | vim.opt.smarttab = false 827 | print(vim.opt.smarttab:get()) -- false 828 | < 829 | 830 | Some options can be set using Lua tables: 831 | 832 | > 833 | vim.opt.completeopt = {'menuone', 'noselect'} 834 | print(vim.inspect(vim.opt.completeopt:get())) -- { "menuone", 835 | "noselect" } 836 | < 837 | 838 | Wrappers for list-like, map-like and set-like options also come with 839 | methods and metamethods that work similarly to their `:set+=`, `:set^=` 840 | and `:set-=` counterparts in Vimscript. 841 | 842 | > 843 | vim.opt.shortmess:append({ I = true }) 844 | -- alternative form: 845 | vim.opt.shortmess = vim.opt.shortmess + { I = true } 846 | 847 | vim.opt.whichwrap:remove({ 'b', 's' }) 848 | -- alternative form: 849 | vim.opt.whichwrap = vim.opt.whichwrap - { 'b', 's' } 850 | < 851 | 852 | Be sure to look at |vim.opt| for more information. 853 | 854 | See also: 855 | - |lua-vim-options| 856 | 857 | ============================================================================== 858 | MANAGING VIM INTERNAL VARIABLES 859 | *luaguide-managing-vim-internal-variables* 860 | 861 | Using api functions~ 862 | 863 | Much like options, internal variables have their own set of API functions: 864 | 865 | - Global variables (`g:`): 866 | - |nvim_set_var()| 867 | - |nvim_get_var()| 868 | - |nvim_del_var()| 869 | - Buffer variables (`b:`): 870 | - |nvim_buf_set_var()| 871 | - |nvim_buf_get_var()| 872 | - |nvim_buf_del_var()| 873 | - Window variables (`w:`): 874 | - |nvim_win_set_var()| 875 | - |nvim_win_get_var()| 876 | - |nvim_win_del_var()| 877 | - Tabpage variables (`t:`): 878 | - |nvim_tabpage_set_var()| 879 | - |nvim_tabpage_get_var()| 880 | - |nvim_tabpage_del_var()| 881 | - Predefined Vim variables (`v:`): 882 | - |nvim_set_vvar()| 883 | - |nvim_get_vvar()| 884 | 885 | With the exception of predefined Vim variables, they can also be deleted 886 | (the `:unlet` command is the equivalent in Vimscript). Local variables 887 | (`l:`), script variables (`s:`) and function arguments (`a:`) cannot 888 | be manipulated as they only make sense in the context of a Vim script, 889 | Lua has its own scoping rules. 890 | 891 | If you are unfamiliar with what these variables do, |internal-variables| 892 | describes them in detail. 893 | 894 | These functions take a string containing the name of the variable to 895 | set/get/delete as well as the value you want to set it to. 896 | 897 | > 898 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 899 | 300 }) 900 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- 901 | { key1 = "value", key2 = 300 } 902 | vim.api.nvim_del_var('some_global_variable') 903 | < 904 | 905 | Variables that are scoped to a buffer, a window or a tabpage also 906 | receive a number (using `0` will set/get/delete the variable for the 907 | current buffer/window/tabpage): 908 | 909 | > 910 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 911 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 912 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 913 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 914 | 'hello world' 915 | vim.api.nvim_win_del_var(0, 'some_window_variable') 916 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 917 | < 918 | 919 | Using meta-accessors~ 920 | 921 | Internal variables can be manipulated more intuitively using these 922 | meta-accessors: 923 | 924 | - |vim.g|: global variables 925 | - |vim.b|: buffer variables 926 | - |vim.w|: window variables 927 | - |vim.t|: tabpage variables 928 | - |vim.v|: predefined Vim variables 929 | - |vim.env|: environment variables 930 | 931 | > 932 | vim.g.some_global_variable = { 933 | key1 = 'value', 934 | key2 = 300 935 | } 936 | 937 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", 938 | key2 = 300 } 939 | 940 | -- target a specific buffer/window/tabpage (Neovim 0.6+) 941 | vim.b[2].myvar = 1 942 | < 943 | 944 | Some variable names may contain characters that cannot be used for 945 | identifiers in Lua. You can still manipulate these variables by using 946 | this syntax: `vim.g['my#variable']`. 947 | 948 | To delete one of these variables, simply assign `nil` to it: 949 | 950 | > 951 | vim.g.some_global_variable = nil 952 | < 953 | 954 | See also: 955 | - |lua-vim-variables| 956 | 957 | Caveats~ 958 | 959 | You cannot add/update/delete keys from a dictionary stored in one of 960 | these variables. For example, this snippet of Vimscript code does not 961 | work as expected: 962 | 963 | > 964 | let g:variable = {} 965 | lua vim.g.variable.key = 'a' 966 | echo g:variable 967 | " {} 968 | < 969 | 970 | You can use a temporary variable as a workaround: 971 | 972 | > 973 | let g:variable = {} 974 | lua << EOF 975 | local tmp = vim.g.variable 976 | tmp.key = 'a' 977 | vim.g.variable = tmp 978 | EOF 979 | echo g:variable 980 | " {'key': 'a'} 981 | < 982 | 983 | This is a known issue: 984 | 985 | - Issue #12544: https://github.com/neovim/neovim/issues/12544 986 | 987 | ============================================================================== 988 | CALLING VIMSCRIPT FUNCTIONS 989 | *luaguide-calling-vimscript-functions* 990 | 991 | vim.fn.{function}()~ 992 | 993 | `vim.fn` can be used to call a Vimscript function. Data types are 994 | converted back and forth from Lua to Vimscript. 995 | 996 | > 997 | print(vim.fn.printf('Hello from %s', 'Lua')) 998 | 999 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 1000 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 1001 | 1002 | local function print_stdout(chan_id, data, name) 1003 | print(data[1]) 1004 | end 1005 | 1006 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 1007 | < 1008 | 1009 | Hashes (`#`) are not valid characters for identifiers in Lua, so autoload 1010 | functions have to be called with this syntax: 1011 | 1012 | > 1013 | vim.fn['my#autoload#function']() 1014 | < 1015 | 1016 | The functionality of `vim.fn` is identical to `vim.call`, but allows a 1017 | more Lua-like syntax. 1018 | 1019 | It is distinct from `vim.api.nvim_call_function` in that converting 1020 | Vim/Lua objects is automatic: `vim.api.nvim_call_function` returns a 1021 | table for floating point numbers and does not accept Lua closures while 1022 | `vim.fn` handles these types transparently. 1023 | 1024 | See also: 1025 | - |vim.fn| 1026 | 1027 | Tips~ 1028 | 1029 | Neovim has an extensive library of powerful built-in functions that are very 1030 | useful for plugins. See |vim-function| for an alphabetical list and 1031 | |function-list| for a list of functions grouped by topic. 1032 | 1033 | Neovim API functions can be used directly through `vim.api.{..}`. See 1034 | |api| for information. 1035 | 1036 | Caveats~ 1037 | 1038 | Some Vim functions that should return a boolean return `1` or `0` 1039 | instead. This isn't a problem in Vimscript as `1` is truthy and `0` 1040 | falsy, enabling constructs like these: 1041 | 1042 | > 1043 | if has('nvim') 1044 | " do something... 1045 | endif 1046 | < 1047 | 1048 | In Lua however, only `false` and `nil` are considered falsy, numbers 1049 | always evaluate to `true` no matter their value. You have to explicitly 1050 | check for `1` or `0`: 1051 | 1052 | > 1053 | if vim.fn.has('nvim') == 1 then 1054 | -- do something... 1055 | end 1056 | < 1057 | 1058 | ============================================================================== 1059 | DEFINING MAPPINGS 1060 | *luaguide-defining-mappings* 1061 | 1062 | API functions~ 1063 | 1064 | Neovim provides a list of API functions to set, get and delete mappings: 1065 | 1066 | - Global mappings: 1067 | - |nvim_set_keymap()| 1068 | - |nvim_get_keymap()| 1069 | - |nvim_del_keymap()| 1070 | - Buffer-local mappings: 1071 | - |nvim_buf_set_keymap()| 1072 | - |nvim_buf_get_keymap()| 1073 | - |nvim_buf_del_keymap()| 1074 | 1075 | Let's start with `vim.api.nvim_set_keymap()` and 1076 | `vim.api.nvim_buf_set_keymap()` 1077 | 1078 | The first argument passed to the function is a string containing the 1079 | name of the mode for which the mapping will take effect: 1080 | 1081 | | String value | Help page | Affected modes | Vimscript equivalent | 1082 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 1083 | | `''` (an empty string) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 1084 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 1085 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 1086 | | `'s'` | `mapmode-s` | Select | `:smap` | 1087 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 1088 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 1089 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 1090 | | `'i'` | `mapmode-i` | Insert | `:imap` | 1091 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 1092 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 1093 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 1094 | 1095 | The second argument is a string containing the left-hand side of the 1096 | mapping (the key or set of keys that trigger the command defined in the 1097 | mapping). An empty string is equivalent to ``, which disables a key. 1098 | 1099 | The third argument is a string containing the right-hand side of the 1100 | mapping (the command to execute). 1101 | 1102 | The final argument is a table containing boolean options for the mapping 1103 | as defined in |:map-arguments|. Since Neovim 0.7.0, you can also pass a 1104 | `callback` option to invoke a Lua function instead of the right-hand 1105 | side when executing the mapping. 1106 | 1107 | Buffer-local mappings also take a buffer number as their first argument 1108 | (`0` sets the mapping for the current buffer). 1109 | 1110 | > 1111 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', 1112 | { noremap = true, silent = true }) 1113 | -- :nnoremap :set hlsearch 1114 | vim.api.nvim_set_keymap('n', 'tegf', [[lua 1115 | require('telescope.builtin').git_files()]], { noremap = true, 1116 | silent = true }) 1117 | -- :nnoremap tegf lua 1118 | require('telescope.builtin').git_files() 1119 | 1120 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : 1121 | "ggcc"', { noremap = true, expr = true }) 1122 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 1123 | 1124 | vim.api.nvim_set_keymap('n', 'ex', '', { 1125 | noremap = true, 1126 | callback = function() 1127 | print('My example') 1128 | end, 1129 | -- Since Lua function don't have a useful string representation, 1130 | you can use the "desc" option to document your mapping 1131 | desc = 'Prints "My example" in the message area', 1132 | }) 1133 | < 1134 | 1135 | `vim.api.nvim_get_keymap()` takes a string containing the shortname of 1136 | the mode for which you want the list of mappings (see table above). The 1137 | return value is a table containing all global mappings for the mode. 1138 | 1139 | > 1140 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 1141 | -- :verbose nmap 1142 | < 1143 | 1144 | `vim.api.nvim_buf_get_keymap()` takes an additional buffer number as 1145 | its first argument (`0` will get mapppings for the current bufffer) 1146 | 1147 | > 1148 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 1149 | -- :verbose imap 1150 | < 1151 | 1152 | `vim.api.nvim_del_keymap()` takes a mode and the left-hand side of 1153 | a mapping. 1154 | 1155 | > 1156 | vim.api.nvim_del_keymap('n', '') 1157 | -- :nunmap 1158 | < 1159 | 1160 | Again, `vim.api.nvim_buf_del_keymap()`, takes a buffer number as its 1161 | first argument, with `0` representing the current buffer. 1162 | 1163 | > 1164 | vim.api.nvim_buf_del_keymap(0, 'i', '') 1165 | -- :iunmap 1166 | < 1167 | 1168 | vim.keymap~ 1169 | 1170 | WARNING: The functions discussed in this section are only available in 1171 | Neovim 0.7.0+ 1172 | 1173 | Neovim provides two functions to set/del mappings: 1174 | - |vim.keymap.set()| 1175 | - |vim.keymap.del()| 1176 | 1177 | These are similar to the above API functions with added syntactic sugar. 1178 | 1179 | `vim.keymap.set()` takes a string as its first argument. It can also be 1180 | a table of strings to define mappings for multiple modes at once: 1181 | 1182 | > 1183 | vim.keymap.set('n', 'ex1', 'lua vim.notify("Example 1184 | 1")') 1185 | vim.keymap.set({'n', 'c'}, 'ex2', 'lua 1186 | vim.notify("Example 2")') 1187 | < 1188 | 1189 | The second argument is the left-hand side of the mapping. 1190 | 1191 | The third argument is the right-hand side of the mapping, which can 1192 | either be a string or a Lua function: 1193 | 1194 | > 1195 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"') 1196 | vim.keymap.set('n', 'ex2', function() print("Example 2") end) 1197 | vim.keymap.set('n', 'pl1', require('plugin').plugin_action) 1198 | -- To avoid the startup cost of requiring the module, you can wrap 1199 | it in a function to require it lazily when invoking the mapping: 1200 | vim.keymap.set('n', 'pl2', function() 1201 | require('plugin').plugin_action() end) 1202 | < 1203 | 1204 | The fourth (optional) argument is a table of options that correspond to 1205 | the options passed to `vim.api.nvim_set_keymap()`, with a few additions 1206 | (see |vim.keymap.set()|. 1207 | 1208 | > 1209 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"', 1210 | {buffer = true}) 1211 | vim.keymap.set('n', 'ex2', function() print('Example 2') 1212 | end, {desc = 'Prints "Example 2" to the message area'}) 1213 | < 1214 | 1215 | Defining keymaps with a Lua function is different from using a string. The 1216 | usual way to show information about a keymap like `:nmap ex1` 1217 | will not output useful information (the string itself), but instead 1218 | only show `Lua function`. It is recommended to add a `desc` key to 1219 | describe the behavior of your keymap. This is especially important for 1220 | documenting plugin mappings so users can understand the usage of the 1221 | keymap more easily. 1222 | 1223 | An interesting feature of this API is that it irons out some historical 1224 | quirks of Vim mappings: 1225 | - Mappings are `noremap` by default, except when the `rhs` is a `` 1226 | mapping. This means you rarely have to think about whether a mapping 1227 | should be recursive or not: 1228 | ```lua 1229 | vim.keymap.set('n', 'test1', 'echo "test"') 1230 | -- :nnoremap test echo "test" 1231 | 1232 | -- If you DO want the mapping to be recursive, set the "remap" 1233 | option to "true" 1234 | vim.keymap.set('n', '>', ']', {remap = true}) 1235 | -- :nmap > ] 1236 | 1237 | -- mappings don't work unless they're recursive, 1238 | vim.keymap.set() handles that for you automatically 1239 | vim.keymap.set('n', 'plug', '(plugin)') 1240 | -- :nmap plug (plugin) 1241 | ``` 1242 | - In `expr` mappings, `nvim_replace_termcodes()` is automatically applied 1243 | to strings returned from Lua functions: 1244 | ```lua 1245 | vim.keymap.set('i', '', function() 1246 | return vim.fn.pumvisible == 1 and '' or '' 1247 | end, {expr = true}) 1248 | ``` 1249 | 1250 | See also: 1251 | - |recursive_mapping| 1252 | 1253 | `vim.keymap.del()` works the same way but deletes mappings instead: 1254 | 1255 | > 1256 | vim.keymap.del('n', 'ex1') 1257 | vim.keymap.del({'n', 'c'}, 'ex2', {buffer = true}) 1258 | < 1259 | 1260 | ============================================================================== 1261 | DEFINING USER COMMANDS 1262 | *luaguide-defining-user-commands* 1263 | 1264 | WARNING: The API functions discussed in this section are only available 1265 | in Neovim 0.7.0+ 1266 | 1267 | Neovim provides API functions for user-defined commands: 1268 | 1269 | - Global user commands: 1270 | - |nvim_create_user_command()| 1271 | - |nvim_del_user_command()| 1272 | - Buffer-local user commands: 1273 | - |nvim_buf_create_user_command()| 1274 | - |nvim_buf_del_user_command()| 1275 | 1276 | Let's start with `vim.api.nvim_create_user_command()` 1277 | 1278 | The first argument passed to this function is the name of the command 1279 | (which must start with an uppercase letter). 1280 | 1281 | The second argument is the code to execute when invoking said command. It 1282 | can either be: 1283 | 1284 | A string (in which case it will be executed as Vimscript). You can use 1285 | escape sequences like ``, ``, etc. like you would with 1286 | `:command` 1287 | > 1288 | vim.api.nvim_create_user_command('Upper', 'echo toupper()', 1289 | { nargs = 1 }) 1290 | -- :command! -nargs=1 Upper echo toupper() 1291 | 1292 | vim.cmd('Upper hello world') -- prints "HELLO WORLD" 1293 | < 1294 | 1295 | Or a Lua function. It receives a dictionary-like table that 1296 | contains the data normally provided by escape sequences (see 1297 | |nvim_create_user_command()| 1298 | > 1299 | vim.api.nvim_create_user_command( 1300 | 'Upper', 1301 | function(opts) 1302 | print(string.upper(opts.args)) 1303 | end, 1304 | { nargs = 1 } 1305 | ) 1306 | < 1307 | 1308 | The third argument lets you pass command attributes as a table (see 1309 | |command-attributes|`. Since you can already define buffer-local user commands 1310 | with |nvim_buf_create_user_command()|, `-buffer` is not a valid attribute. 1311 | 1312 | Two additional attributes are available: 1313 | - `desc` allows you to control what gets displayed when you run `:command 1314 | {cmd}` on a command defined as a Lua callback. Similarly to keymaps, it 1315 | is recommended to add a `desc` key to commands defined as Lua functions. 1316 | - `force` is equivalent to calling `:command!` and replaces a command 1317 | if one with the same name already exists. It is true by default, unlike 1318 | its Vimscript equivalent. 1319 | 1320 | The `-complete` attribute can take a Lua function in addition to the 1321 | attributes listed in |:command-complete|. 1322 | 1323 | > 1324 | vim.api.nvim_create_user_command('Upper', function() end, { 1325 | nargs = 1, 1326 | complete = function(ArgLead, CmdLine, CursorPos) 1327 | -- return completion candidates as a list-like table 1328 | return { 'foo', 'bar', 'baz' } 1329 | end, 1330 | }) 1331 | < 1332 | 1333 | Buffer-local user commands also take a buffer number as their first 1334 | argument. This is an advantage over `-buffer` which can only define a 1335 | command for the current buffer. 1336 | 1337 | > 1338 | vim.api.nvim_buf_create_user_command(4, 'Upper', function() end, {}) 1339 | < 1340 | 1341 | `vim.api.nvim_del_user_command()` takes a command name. 1342 | 1343 | > 1344 | vim.api.nvim_del_user_command('Upper') 1345 | -- :delcommand Upper 1346 | < 1347 | 1348 | Again, `vim.api.nvim_buf_del_user_command()`, takes a buffer number as 1349 | its first argument, with `0` representing the current buffer. 1350 | 1351 | > 1352 | vim.api.nvim_buf_del_user_command(4, 'Upper') 1353 | < 1354 | 1355 | See also: 1356 | - |nvim_create_user_command()| 1357 | - |40.2| 1358 | - |command-attributes| 1359 | 1360 | Caveats~ 1361 | 1362 | The `-complete=custom` attribute automatically filters completion 1363 | candidates and has built-in wildcard (|wildcard| support: 1364 | 1365 | > 1366 | function! s:completion_function(ArgLead, CmdLine, CursorPos) abort 1367 | return join([ 1368 | \ 'strawberry', 1369 | \ 'star', 1370 | \ 'stellar', 1371 | \ ], "\n") 1372 | endfunction 1373 | 1374 | command! -nargs=1 -complete=custom,s:completion_function Test echo 1375 | 1376 | " Typing `:Test st[ae]` returns "star" and "stellar" 1377 | < 1378 | 1379 | Passing a Lua function to `complete` makes it behave like `customlist` 1380 | which leaves filtering up to the user: 1381 | 1382 | > 1383 | vim.api.nvim_create_user_command('Test', function() end, { 1384 | nargs = 1, 1385 | complete = function(ArgLead, CmdLine, CursorPos) 1386 | return { 1387 | 'strawberry', 1388 | 'star', 1389 | 'stellar', 1390 | } 1391 | end, 1392 | }) 1393 | 1394 | -- Typing `:Test z` returns all the completion results because 1395 | the list was not filtered 1396 | < 1397 | 1398 | ============================================================================== 1399 | DEFINING AUTOCOMMANDS 1400 | *luaguide-defining-autocommands* 1401 | 1402 | (this section is a work in progress) 1403 | 1404 | Neovim 0.7.0 has API functions for autocommands. See `:help api-autocmd` 1405 | for details 1406 | 1407 | - Pull request #14661: https://github.com/neovim/neovim/pull/14661 lua: 1408 | autocmds take 2 1409 | 1410 | ============================================================================== 1411 | DEFINING HIGHLIGHTS 1412 | *luaguide-defining-highlights* 1413 | 1414 | (this section is a work in progress) 1415 | 1416 | Neovim 0.7.0 has API functions for highlight groups. See also: 1417 | 1418 | - |nvim_set_hl()| 1419 | - |nvim_get_hl_by_id()| 1420 | - |nvim_get_hl_by_name()| 1421 | 1422 | ============================================================================== 1423 | GENERAL TIPS AND RECOMMENDATIONS 1424 | *luaguide-general-tips-and-recommendations* 1425 | 1426 | Reloading cached modules~ 1427 | 1428 | In Lua, the `require()` function caches modules. This is a good thing 1429 | for performance, but it can make working on plugins a bit cumbersome 1430 | because modules are not updated on subsequent `require()` calls. 1431 | 1432 | If you'd like to refresh the cache for a particular module, you have to 1433 | modify the `package.loaded` global table: 1434 | 1435 | > 1436 | package.loaded['modname'] = nil 1437 | require('modname') -- loads an updated version of module 'modname' 1438 | < 1439 | 1440 | The nvim-lua/plenary.nvim: 1441 | https://github.com/nvim-lua/plenary.nvim plugin has a custom function: 1442 | https://github.com/nvim-lua/plenary.nvim/blob/master/lua/plenary/reload.lua 1443 | that does this for you. 1444 | 1445 | Don't pad Lua strings!~ 1446 | 1447 | When using double bracketed strings, resist the temptation to pad 1448 | them! While it is fine to do in contexts where spaces are ignored, 1449 | it can cause hard to debug issues when whitespace is significant: 1450 | 1451 | > 1452 | vim.api.nvim_set_keymap('n', 'f', [[ call foo() 1453 | ]], {noremap = true}) 1454 | < 1455 | 1456 | In the above example, `f` is mapped to `call 1457 | foo()` instead of `call foo()`. 1458 | 1459 | Notes about Vimscript <-> Lua type conversion~ 1460 | 1461 | Converting a variable creates a copy:~ 1462 | You can't directly interact with the reference to a Vim object from Lua 1463 | or a Lua object from Vimscript. 1464 | For example, the `map()` function in Vimscript modifies a variable 1465 | in place: 1466 | 1467 | > 1468 | let s:list = [1, 2, 3] 1469 | let s:newlist = map(s:list, {_, v -> v * 2}) 1470 | 1471 | echo s:list 1472 | " [2, 4, 6] 1473 | echo s:newlist 1474 | " [2, 4, 6] 1475 | echo s:list is# s:newlist 1476 | " 1 1477 | < 1478 | 1479 | Using this function from Lua creates a copy instead: 1480 | 1481 | > 1482 | local tbl = {1, 2, 3} 1483 | local newtbl = vim.fn.map(tbl, function(_, v) return v * 2 end) 1484 | 1485 | print(vim.inspect(tbl)) -- { 1, 2, 3 } 1486 | print(vim.inspect(newtbl)) -- { 2, 4, 6 } 1487 | print(tbl == newtbl) -- false 1488 | < 1489 | 1490 | Conversion is not always possible~ 1491 | This mostly affects functions and tables: 1492 | 1493 | Lua tables that are a mix between a List and a Dictionary can't be 1494 | converted: 1495 | 1496 | > 1497 | print(vim.fn.count({1, 1, number = 1}, 1)) 1498 | -- E5100: Cannot convert given lua table: table should either have 1499 | a sequence of positive integer keys or contain only string keys 1500 | < 1501 | 1502 | While you can call Vim functions in Lua with `vim.fn`, you can't hold 1503 | references to them. This can cause surprising behaviors: 1504 | 1505 | > 1506 | local FugitiveHead = vim.fn.funcref('FugitiveHead') 1507 | print(FugitiveHead) -- vim.NIL 1508 | 1509 | vim.cmd("let g:test_dict = {'test_lambda': {-> 1}}") 1510 | print(vim.g.test_dict.test_lambda) -- nil 1511 | print(vim.inspect(vim.g.test_dict)) -- {} 1512 | < 1513 | 1514 | Passing Lua functions to Vim functions is OK, storing them in Vim 1515 | variables is not (fixed in Neovim 0.7.0+): 1516 | 1517 | > 1518 | -- This works: 1519 | vim.fn.jobstart({'ls'}, { 1520 | on_stdout = function(chan_id, data, name) 1521 | print(vim.inspect(data)) 1522 | end 1523 | }) 1524 | 1525 | -- This doesn't: 1526 | vim.g.test_dict = {test_lambda = function() return 1 end} -- Error: 1527 | Cannot convert given lua type 1528 | < 1529 | 1530 | Note however that doing the same from Vimscript with `luaeval()` 1531 | **does** work: 1532 | 1533 | > 1534 | let g:test_dict = {'test_lambda': luaeval('function() return 1 end')} 1535 | echo g:test_dict 1536 | " {'test_lambda': function('4714')} 1537 | < 1538 | 1539 | Vim booleans~ 1540 | A common pattern in Vim scripts is to use `1` or `0` instead of proper 1541 | booleans. Indeed, Vim did not have a separate boolean type until version 1542 | 7.4.1154. 1543 | 1544 | Lua booleans are converted to actual booleans in Vimscript, not numbers: 1545 | 1546 | > 1547 | lua vim.g.lua_true = true 1548 | echo g:lua_true 1549 | " v:true 1550 | lua vim.g.lua_false = false 1551 | echo g:lua_false 1552 | " v:false 1553 | < 1554 | 1555 | Setting up linters/language servers~ 1556 | 1557 | If you're using linters and/or language servers to get diagnostics and 1558 | autocompletion for Lua projects, you may have to configure Neovim-specific 1559 | settings for them. Here are a few recommended settings for popular tools: 1560 | 1561 | luacheck~ 1562 | 1563 | You can get luacheck: https://github.com/mpeterv/luacheck/ to recognize 1564 | the `vim` global by putting this configuration in `~/.luacheckrc` or 1565 | `$XDG_CONFIG_HOME/luacheck/.luacheckrc` : 1566 | 1567 | > 1568 | globals = { 1569 | "vim", 1570 | } 1571 | < 1572 | 1573 | The Alloyed/lua-lsp: https://github.com/Alloyed/lua-lsp/ language 1574 | server uses `luacheck` to provide linting and reads the same file. 1575 | 1576 | For more information on how to configure `luacheck`, please refer to 1577 | its documentation: https://luacheck.readthedocs.io/en/stable/config.html 1578 | 1579 | sumneko/lua-language-server~ 1580 | 1581 | The nvim-lspconfig: https://github.com/neovim/nvim-lspconfig/ repository 1582 | contains instructions to configure sumneko/lua-language-server: 1583 | https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#sumneko_lua 1584 | the example uses the built-in LSP client but the configuration should 1585 | be identical for other LSP client implementations . 1586 | 1587 | For more information on how to configure sumneko/lua-language-server: 1588 | https://github.com/sumneko/lua-language-server/ see "Setting": 1589 | https://github.com/sumneko/lua-language-server/wiki/Setting 1590 | 1591 | coc.nvim~ 1592 | 1593 | The rafcamlet/coc-nvim-lua: https://github.com/rafcamlet/coc-nvim-lua/ 1594 | completion source for coc.nvim: https://github.com/neoclide/coc.nvim/ 1595 | provides completion items for the Neovim stdlib. 1596 | 1597 | Debugging Lua code~ 1598 | 1599 | You can debug Lua code running in a separate Neovim 1600 | instance with jbyuki/one-small-step-for-vimkind: 1601 | https://github.com/jbyuki/one-small-step-for-vimkind 1602 | 1603 | The plugin uses the Debug Adapter Protocol: 1604 | https://microsoft.github.io/debug-adapter-protocol/ . Connecting to 1605 | a debug adapter requires a DAP client like mfussenegger/nvim-dap: 1606 | https://github.com/mfussenegger/nvim-dap/ or puremourning/vimspector: 1607 | https://github.com/puremourning/vimspector/ . 1608 | 1609 | Debugging Lua mappings/commands/autocommands~ 1610 | 1611 | The `:verbose` command allows you to see where a 1612 | mapping/command/autocommand was defined: 1613 | 1614 | > 1615 | :verbose map m 1616 | < 1617 | 1618 | > 1619 | n m_ * echo 'example' 1620 | Last set from ~/.config/nvim/init.vim line 26 1621 | < 1622 | 1623 | By default, this feature is disabled in Lua for performance reasons. You 1624 | can enable it by starting Neovim with a verbose level greater than 0: 1625 | 1626 | > 1627 | nvim -V1 1628 | < 1629 | 1630 | See also: 1631 | - |'verbose'| 1632 | - |-V| 1633 | - neovim/neovim#15079: https://github.com/neovim/neovim/pull/15079 1634 | 1635 | Testing Lua code~ 1636 | 1637 | - plenary.nvim: test harness: 1638 | https://github.com/nvim-lua/plenary.nvim/#plenarytest_harness 1639 | - notomo/vusted: https://github.com/notomo/vusted 1640 | 1641 | Using Luarocks packages~ 1642 | 1643 | wbthomason/packer.nvim: https://github.com/wbthomason/packer.nvim 1644 | supports Luarocks packages. Instructions for 1645 | how to set this up are available in the README: 1646 | https://github.com/wbthomason/packer.nvim/#luarocks-support 1647 | 1648 | ============================================================================== 1649 | MISCELLANEOUS 1650 | *luaguide-miscellaneous* 1651 | 1652 | vim.loop~ 1653 | 1654 | `vim.loop` is the module that exposes the LibUV API. Some resources: 1655 | 1656 | - Official documentation for LibUV: https://docs.libuv.org/en/v1.x/ 1657 | - Luv documentation: https://github.com/luvit/luv/blob/master/docs.md 1658 | - teukka.tech - Using LibUV in Neovim: 1659 | https://teukka.tech/posts/2020-01-07-vimloop/ 1660 | 1661 | See also: 1662 | - |vim.loop| 1663 | 1664 | vim.lsp~ 1665 | 1666 | `vim.lsp` is the module that controls the built-in LSP client. The 1667 | neovim/nvim-lspconfig: https://github.com/neovim/nvim-lspconfig/ 1668 | repository contains default configurations for popular language servers. 1669 | 1670 | The behavior of the client can be configured using "lsp-handlers". For 1671 | more information: 1672 | - |lsp-handler| 1673 | - neovim/neovim#12655: https://github.com/neovim/neovim/pull/12655 1674 | - How to migrate from diagnostic-nvim: 1675 | https://github.com/nvim-lua/diagnostic-nvim/issues/73#issue-737897078 1676 | 1677 | You may also want to take a look at plugins built around the LSP client: 1678 | https://github.com/rockerBOO/awesome-neovim#lsp 1679 | 1680 | See also: 1681 | - |lsp| 1682 | 1683 | vim.treesitter~ 1684 | 1685 | `vim.treesitter` is the module that controls the integration of the 1686 | Tree-sitter: https://tree-sitter.github.io/tree-sitter/ library in 1687 | Neovim. If you want to know more about Tree-sitter, you may be interested 1688 | in this presentation 38:37 : https://www.youtube.com/watch?v=Jes3bD6P0To 1689 | . 1690 | 1691 | The nvim-treesitter: https://github.com/nvim-treesitter/ organisation 1692 | hosts various plugins taking advantage of the library. 1693 | 1694 | See also: 1695 | - |lua-treesitter| 1696 | 1697 | Transpilers~ 1698 | 1699 | One advantage of using Lua is that you don't actually have to write Lua 1700 | code! There is a multitude of transpilers available for the language. 1701 | 1702 | - Moonscript: https://moonscript.org/ 1703 | 1704 | Probably one of the most well-known transpilers for 1705 | Lua. Adds a lots of convenient features like classes, list 1706 | comprehensions or function literals. The svermeulen/nvim-moonmaker: 1707 | https://github.com/svermeulen/nvim-moonmaker plugin allows you to write 1708 | Neovim plugins and configuration directly in Moonscript. 1709 | 1710 | - Fennel: https://fennel-lang.org/ 1711 | 1712 | A lisp that compiles to Lua. You can write configuration 1713 | and plugins for Neovim in Fennel with the Olical/aniseed: 1714 | https://github.com/Olical/aniseed or the Hotpot: 1715 | https://github.com/rktjmp/hotpot.nvim plugin. Additionally, the 1716 | Olical/conjure: https://github.com/Olical/conjure plugin provides an 1717 | interactive development environment that supports Fennel among other 1718 | languages . 1719 | 1720 | - Teal: https://github.com/teal-language/tl 1721 | 1722 | The name Teal comes from pronouncing TL typed lua . This is exactly 1723 | what it tries to do - add strong typing to lua while otherwise 1724 | remaining close to standard lua syntax. The nvim-teal-maker: 1725 | https://github.com/svermeulen/nvim-teal-maker plugin can be used to 1726 | write Neovim plugins or configuration files directly in Teal 1727 | 1728 | Other interesting projects: 1729 | - TypeScriptToLua/TypeScriptToLua: 1730 | https://github.com/TypeScriptToLua/TypeScriptToLua 1731 | - Haxe: https://haxe.org/ 1732 | - SwadicalRag/wasm2lua: https://github.com/SwadicalRag/wasm2lua 1733 | - hengestone/lua-languages: https://github.com/hengestone/lua-languages 1734 | 1735 | vim:tw=78:ts=8:noet:ft=help:norl: 1736 | -------------------------------------------------------------------------------- /OLD_README.md: -------------------------------------------------------------------------------- 1 | (Feeling lost? Use the GitHub TOC!) :arrow_upper_right: 2 | 3 | --- 4 | 5 | # Getting started using Lua in Neovim 6 | 7 | ## Translations 8 | 9 | - [Chinese version](https://github.com/glepnir/nvim-lua-guide-zh) 10 | - [Spanish version](https://github.com/RicardoRien/nvim-lua-guide/blob/master/README.esp.md) 11 | - [Portuguese version](https://github.com/npxbr/nvim-lua-guide/blob/master/README.pt-br.md) 12 | - [Japanese version](https://github.com/willelz/nvim-lua-guide-ja/blob/master/README.ja.md) 13 | - [Russian version](https://github.com/kuator/nvim-lua-guide-ru) 14 | - [Ukrainian version](https://github.com/famiclone/nvim-lua-guide-ua) 15 | - [Korean version](https://github.com/krapjost/nvim-lua-guide-kr) 16 | 17 | ## Introduction 18 | 19 | The [integration of Lua](https://www.youtube.com/watch?v=IP3J56sKtn0) as a [first-class language inside Neovim](https://github.com/neovim/neovim/wiki/FAQ#why-embed-lua-instead-of-x) is shaping up to be one of its killer features. 20 | However, the amount of teaching material for learning how to write plugins in Lua is not as large as what you would find for writing them in Vimscript. This is an attempt at providing some basic information to get people started. 21 | 22 | This guide assumes you are using at least version 0.5 of Neovim. 23 | 24 | ### Learning Lua 25 | 26 | If you are not already familiar with the language, there are plenty of resources to get started: 27 | 28 | - The [Learn X in Y minutes page about Lua](https://learnxinyminutes.com/docs/lua/) should give you a quick overview of the basics 29 | - [This guide](https://github.com/medwatt/Notes/blob/main/Lua/Lua_Quick_Guide.ipynb) is also a good resource for getting started quickly 30 | - If videos are more to your liking, Derek Banas has a [1-hour tutorial on the language](https://www.youtube.com/watch?v=iMacxZQMPXs) 31 | - Want something a little more interactive with runnable examples? Try [the LuaScript tutorial](https://www.luascript.dev/learn) 32 | - The [lua-users wiki](http://lua-users.org/wiki/LuaDirectory) is full of useful information on all kinds of Lua-related topics 33 | - The [official reference manual for Lua](https://www.lua.org/manual/5.1/) should give you the most comprehensive tour of the language (exists as a Vimdoc plugin if you want to read it from the comfort of your editor: [milisims/nvim-luaref](https://github.com/milisims/nvim-luaref)) 34 | 35 | It should also be noted that Lua is a very clean and simple language. It is easy to learn, especially if you have experience with similar scripting languages like JavaScript. You may already know more Lua than you realise! 36 | 37 | Note: the version of Lua that Neovim embeds is [LuaJIT](https://staff.fnwi.uva.nl/h.vandermeer/docs/lua/luajit/luajit_intro.html) 2.1.0, which maintains compatibility with Lua 5.1. 38 | 39 | ### Existing tutorials for writing Lua in Neovim 40 | 41 | A few tutorials have already been written to help people write plugins in Lua. Some of them helped quite a bit when writing this guide. Many thanks to their authors. 42 | 43 | - [teukka.tech - From init.vim to init.lua](https://teukka.tech/luanvim.html) 44 | - [dev.to - How to write neovim plugins in Lua](https://dev.to/2nit/how-to-write-neovim-plugins-in-lua-5cca) 45 | - [dev.to - How to make UI for neovim plugins in Lua](https://dev.to/2nit/how-to-make-ui-for-neovim-plugins-in-lua-3b6e) 46 | - [ms-jpq - Neovim Async Tutorial](https://github.com/ms-jpq/neovim-async-tutorial) 47 | - [oroques.dev - Neovim 0.5 features and the switch to init.lua](https://oroques.dev/notes/neovim-init/) 48 | - [Building A Vim Statusline from Scratch - jdhao's blog](https://jdhao.github.io/2019/11/03/vim_custom_statusline/) 49 | - [Configuring Neovim using Lua](https://icyphox.sh/blog/nvim-lua/) 50 | - [Devlog | Everything you need to know to configure neovim using lua](https://vonheikemen.github.io/devlog/tools/configuring-neovim-using-lua/) 51 | 52 | ### Companion plugins 53 | 54 | - [Vimpeccable](https://github.com/svermeulen/vimpeccable) - Plugin to help write your .vimrc in Lua 55 | - [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) - All the lua functions I don't want to write twice 56 | - [popup.nvim](https://github.com/nvim-lua/popup.nvim) - An implementation of the Popup API from vim in Neovim 57 | - [nvim_utils](https://github.com/norcalli/nvim_utils) 58 | - [nvim-luadev](https://github.com/bfredl/nvim-luadev) - REPL/debug console for nvim lua plugins 59 | - [nvim-luapad](https://github.com/rafcamlet/nvim-luapad) - Interactive real time neovim scratchpad for embedded lua engine 60 | - [nlua.nvim](https://github.com/tjdevries/nlua.nvim) - Lua Development for Neovim 61 | - [BetterLua.vim](https://github.com/euclidianAce/BetterLua.vim) - Better Lua syntax highlighting in Vim/NeoVim 62 | 63 | ## Where to put Lua files 64 | 65 | ### init.lua 66 | 67 | Neovim supports loading an `init.lua` file for configuration instead of the usual `init.vim`. 68 | 69 | Note: `init.lua` is of course _completely_ optional. Support for `init.vim` is not going away and is still a valid option for configuration. Do keep in mind that some features are not 100% exposed to Lua yet. 70 | 71 | See also: 72 | - [`:help config`](https://neovim.io/doc/user/starting.html#config) 73 | 74 | ### Modules 75 | 76 | Lua modules are found inside a `lua/` folder in your `'runtimepath'` (for most users, this will mean `~/.config/nvim/lua` on \*nix systems and `~/AppData/Local/nvim/lua` on Windows). You can `require()` files in this folder as Lua modules. 77 | 78 | Let's take the following folder structure as an example: 79 | 80 | ```text 81 | 📂 ~/.config/nvim 82 | ├── 📁 after 83 | ├── 📁 ftplugin 84 | ├── 📂 lua 85 | │ ├── 🌑 myluamodule.lua 86 | │ └── 📂 other_modules 87 | │ ├── 🌑 anothermodule.lua 88 | │ └── 🌑 init.lua 89 | ├── 📁 pack 90 | ├── 📁 plugin 91 | ├── 📁 syntax 92 | └── 🇻 init.vim 93 | ``` 94 | 95 | The following Lua code will load `myluamodule.lua`: 96 | 97 | ```lua 98 | require('myluamodule') 99 | ``` 100 | 101 | Notice the absence of a `.lua` extension. 102 | 103 | Similarly, loading `other_modules/anothermodule.lua` is done like so: 104 | 105 | ```lua 106 | require('other_modules.anothermodule') 107 | -- or 108 | require('other_modules/anothermodule') 109 | ``` 110 | 111 | Path separators are denoted by either a dot `.` or a slash `/`. 112 | 113 | A folder containing an `init.lua` file can be required directly, without having to specify the name of the file. 114 | 115 | ```lua 116 | require('other_modules') -- loads other_modules/init.lua 117 | ``` 118 | 119 | Requiring a nonexistent module or a module which contains syntax errors aborts the currently executing script. 120 | `pcall()` may be used to prevent errors. 121 | 122 | ```lua 123 | local ok, _ = pcall(require, 'module_with_error') 124 | if not ok then 125 | -- not loaded 126 | end 127 | ``` 128 | 129 | See also: 130 | - [`:help lua-require`](https://neovim.io/doc/user/lua.html#lua-require) 131 | 132 | #### Tips 133 | 134 | Several Lua plugins might have identical filenames in their `lua/` folder. This could lead to namespace clashes. 135 | 136 | If two different plugins have a `lua/main.lua` file, then doing `require('main')` is ambiguous: which file do we want to source? 137 | 138 | It might be a good idea to namespace your config or your plugin with a top-level folder, like so: `lua/plugin_name/main.lua` 139 | 140 | ### Runtime files 141 | 142 | Much like Vimscript files, Lua files can be loaded automatically from special folders in your `runtimepath`. Currently, the following folders are supported: 143 | 144 | - `colors/` 145 | - `compiler/` 146 | - `ftplugin/` 147 | - `ftdetect/` 148 | - `indent/` 149 | - `plugin/` 150 | - `syntax/` 151 | 152 | Note: in a runtime directory, all `*.vim` files are sourced before `*.lua` files. 153 | 154 | See also: 155 | - [`:help 'runtimepath'`](https://neovim.io/doc/user/options.html#'runtimepath') 156 | - [`:help load-plugins`](https://neovim.io/doc/user/starting.html#load-plugins) 157 | 158 | #### Tips 159 | 160 | Since runtime files aren't based on the Lua module system, two plugins can have a `plugin/main.lua` file without it being an issue. 161 | 162 | ## Using Lua from Vimscript 163 | 164 | ### :lua 165 | 166 | This command executes a chunk of Lua code. 167 | 168 | ```vim 169 | :lua require('myluamodule') 170 | ``` 171 | 172 | Multi-line scripts are possible using heredoc syntax: 173 | 174 | ```vim 175 | echo "Here's a bigger chunk of Lua code" 176 | 177 | lua << EOF 178 | local mod = require('mymodule') 179 | local tbl = {1, 2, 3} 180 | 181 | for k, v in ipairs(tbl) do 182 | mod.method(v) 183 | end 184 | 185 | print(tbl) 186 | EOF 187 | ``` 188 | 189 | Note: each `:lua` command has its own scope and variables declared with the `local` keyword are not accessible outside of the command. This won't work: 190 | 191 | ```vim 192 | :lua local foo = 1 193 | :lua print(foo) 194 | " prints 'nil' instead of '1' 195 | ``` 196 | 197 | Note 2: the `print()` function in Lua behaves similarly to the `:echomsg` command. Its output is saved in the message-history and can be suppressed by the `:silent` command. 198 | 199 | See also: 200 | 201 | - [`:help :lua`](https://neovim.io/doc/user/lua.html#Lua) 202 | - [`:help :lua-heredoc`](https://neovim.io/doc/user/lua.html#:lua-heredoc) 203 | 204 | ### :luado 205 | 206 | This command executes a chunk of Lua code that acts on a range of lines in the current buffer. If no range is specified, the whole buffer is used instead. Whatever string is `return`ed from the chunk is used to determine what each line should be replaced with. 207 | 208 | The following command would replace every line in the current buffer with the text `hello world`: 209 | 210 | ```vim 211 | :luado return 'hello world' 212 | ``` 213 | 214 | Two implicit `line` and `linenr` variables are also provided. `line` is the text of the line being iterated upon whereas `linenr` is its number. The following command would make every line whose number is divisible by 2 uppercase: 215 | 216 | ```vim 217 | :luado if linenr % 2 == 0 then return line:upper() end 218 | ``` 219 | 220 | See also: 221 | 222 | - [`:help :luado`](https://neovim.io/doc/user/lua.html#:luado) 223 | 224 | ### Sourcing Lua files 225 | 226 | Neovim provides 3 Ex commands to source Lua files 227 | 228 | - `:luafile` 229 | - `:source` 230 | - `:runtime` 231 | 232 | `:luafile` and `:source` are very similar: 233 | 234 | ```vim 235 | :luafile ~/foo/bar/baz/myluafile.lua 236 | :luafile % 237 | :source ~/foo/bar/baz/myluafile.lua 238 | :source % 239 | ``` 240 | 241 | `:source` also supports ranges, which can be useful to only execute part of a script: 242 | 243 | ```vim 244 | :1,10source 245 | ``` 246 | 247 | `:runtime` is a little different: it uses the `'runtimepath'` option to determine which files to source. See [`:help :runtime`](https://neovim.io/doc/user/repeat.html#:runtime) for more details. 248 | 249 | See also: 250 | 251 | - [`:help :luafile`](https://neovim.io/doc/user/lua.html#:luafile) 252 | - [`:help :source`](https://neovim.io/doc/user/repeat.html#:source) 253 | - [`:help :runtime`](https://neovim.io/doc/user/repeat.html#:runtime) 254 | 255 | #### Sourcing a lua file vs calling require(): 256 | 257 | You might be wondering what the difference between calling the `require()` function and sourcing a Lua file is and whether you should prefer one way over the other. They have different use cases: 258 | 259 | - `require()`: 260 | - is a built-in Lua function. It allows you to take advantage of Lua's module system 261 | - searches for modules in `lua/` folders in your `'runtimepath'` 262 | - keeps track of what modules have been loaded and prevents a script from being parsed and executed a second time. If you change the file containing the code for a module and try to `require()` it a second time while Neovim is running, the module will not actually update 263 | - `:luafile`, `:source` and `:runtime`: 264 | - are Ex commands. They do not support modules 265 | - execute the contents of a script regardless of whether it has been executed before 266 | - `:luafile` and `:source` take a path that is either absolute or relative to the working directory of the current window 267 | - `:runtime` uses the `'runtimepath'` option to find files 268 | 269 | Files sourced via `:source`, `:runtime` or automatically from runtime directories will also show up in `:scriptnames` and `--startuptime` 270 | 271 | ### luaeval() 272 | 273 | This built-in Vimscript function evaluates a Lua expression string and returns its value. Lua data types are automatically converted to Vimscript types (and vice versa). 274 | 275 | ```vim 276 | " You can store the result in a variable 277 | let variable = luaeval('1 + 1') 278 | echo variable 279 | " 2 280 | let concat = luaeval('"Lua".." is ".."awesome"') 281 | echo concat 282 | " 'Lua is awesome' 283 | 284 | " List-like tables are converted to Vim lists 285 | let list = luaeval('{1, 2, 3, 4}') 286 | echo list[0] 287 | " 1 288 | echo list[1] 289 | " 2 290 | " Note that unlike Lua tables, Vim lists are 0-indexed 291 | 292 | " Dict-like tables are converted to Vim dictionaries 293 | let dict = luaeval('{foo = "bar", baz = "qux"}') 294 | echo dict.foo 295 | " 'bar' 296 | 297 | " Same thing for booleans and nil 298 | echo luaeval('true') 299 | " v:true 300 | echo luaeval('nil') 301 | " v:null 302 | 303 | " You can create Vimscript aliases for Lua functions 304 | let LuaMathPow = luaeval('math.pow') 305 | echo LuaMathPow(2, 2) 306 | " 4 307 | let LuaModuleFunction = luaeval('require("mymodule").myfunction') 308 | call LuaModuleFunction() 309 | 310 | " It is also possible to pass Lua functions as values to Vim functions 311 | lua X = function(k, v) return string.format("%s:%s", k, v) end 312 | echo map([1, 2, 3], luaeval("X")) 313 | ``` 314 | 315 | `luaeval()` takes an optional second argument that allows you to pass data to the expression. You can then access that data from Lua using the magic global `_A`: 316 | 317 | ```vim 318 | echo luaeval('_A[1] + _A[2]', [1, 1]) 319 | " 2 320 | 321 | echo luaeval('string.format("Lua is %s", _A)', 'awesome') 322 | " 'Lua is awesome' 323 | ``` 324 | 325 | See also: 326 | - [`:help luaeval()`](https://neovim.io/doc/user/lua.html#luaeval()) 327 | 328 | ### v:lua 329 | 330 | This global Vim variable allows you to call Lua functions in the global namespace ([`_G`](https://www.lua.org/manual/5.1/manual.html#pdf-_G)) directly from Vimscript. Again, Vim data types are converted to Lua types and vice versa. 331 | 332 | ```vim 333 | call v:lua.print('Hello from Lua!') 334 | " 'Hello from Lua!' 335 | 336 | let scream = v:lua.string.rep('A', 10) 337 | echo scream 338 | " 'AAAAAAAAAA' 339 | 340 | " How about a nice statusline? 341 | lua << EOF 342 | function _G.statusline() 343 | local filepath = '%f' 344 | local align_section = '%=' 345 | local percentage_through_file = '%p%%' 346 | return string.format( 347 | '%s%s%s', 348 | filepath, 349 | align_section, 350 | percentage_through_file 351 | ) 352 | end 353 | EOF 354 | 355 | set statusline=%!v:lua.statusline() 356 | 357 | " Also works in expression mappings 358 | lua << EOF 359 | function _G.check_back_space() 360 | local col = vim.api.nvim_win_get_cursor(0)[2] 361 | return (col == 0 or vim.api.nvim_get_current_line():sub(col, col):match('%s')) and true 362 | end 363 | EOF 364 | 365 | inoremap 366 | \ pumvisible() ? "\" : 367 | \ v:lua.check_back_space() ? "\" : 368 | \ completion#trigger_completion() 369 | 370 | " Call a function from a Lua module by using single quotes and omitting parentheses: 371 | call v:lua.require'module'.foo() 372 | ``` 373 | 374 | See also: 375 | - [`:help v:lua`](https://neovim.io/doc/user/eval.html#v:lua) 376 | - [`:help v:lua-call`](https://neovim.io/doc/user/lua.html#v:lua-call) 377 | 378 | #### Caveats 379 | 380 | This variable can only be used to call functions. The following will always throw an error: 381 | 382 | ```vim 383 | " Aliasing functions doesn't work 384 | let LuaPrint = v:lua.print 385 | 386 | " Accessing dictionaries doesn't work 387 | echo v:lua.some_global_dict['key'] 388 | 389 | " Using a function as a value doesn't work 390 | echo map([1, 2, 3], v:lua.global_callback) 391 | ``` 392 | 393 | ### Tips 394 | 395 | You can get Lua syntax highlighting inside .vim files by putting `let g:vimsyn_embed = 'l'` in your configuration file. See [`:help g:vimsyn_embed`](https://neovim.io/doc/user/syntax.html#g:vimsyn_embed) for more on this option. 396 | 397 | ## The vim namespace 398 | 399 | Neovim exposes a global `vim` variable which serves as an entry point to interact with its APIs from Lua. It provides users with an extended "standard library" of functions as well as various sub-modules. 400 | 401 | Some notable functions and modules include: 402 | 403 | - `vim.inspect`: transform Lua objects into human-readable strings (useful for inspecting tables) 404 | - `vim.regex`: use Vim regexes from Lua 405 | - `vim.api`: module that exposes API functions (the same API used by remote plugins) 406 | - `vim.ui`: overridable UI functions that can be leveraged by plugins 407 | - `vim.loop`: module that exposes the functionality of Neovim's event-loop (using LibUV) 408 | - `vim.lsp`: module that controls the built-in LSP client 409 | - `vim.treesitter`: module that exposes the functionality of the tree-sitter library 410 | 411 | This list is by no means comprehensive. If you wish to know more about what's made available by the `vim` variable, [`:help lua-stdlib`](https://neovim.io/doc/user/lua.html#lua-stdlib) and [`:help lua-vim`](https://neovim.io/doc/user/lua.html#lua-vim) are the way to go. Alternatively, you can do `:lua print(vim.inspect(vim))` to get a list of every module. API functions are documented under [`:help api-global`](https://neovim.io/doc/user/api.html#api-global). 412 | 413 | #### Tips 414 | 415 | Writing `print(vim.inspect(x))` every time you want to inspect the contents of an object can get pretty tedious. It might be worthwhile to have a global wrapper function somewhere in your configuration (in Neovim 0.7.0+, this function is built-in, see [`:help vim.pretty_print()`](https://neovim.io/doc/user/lua.html#vim.pretty_print())): 416 | 417 | ```lua 418 | function _G.put(...) 419 | local objects = {} 420 | for i = 1, select('#', ...) do 421 | local v = select(i, ...) 422 | table.insert(objects, vim.inspect(v)) 423 | end 424 | 425 | print(table.concat(objects, '\n')) 426 | return ... 427 | end 428 | ``` 429 | 430 | You can then inspect the contents of an object very quickly in your code or from the command-line: 431 | 432 | ```lua 433 | put({1, 2, 3}) 434 | ``` 435 | 436 | ```vim 437 | :lua put(vim.loop) 438 | ``` 439 | 440 | Alternatively, you can use the `:lua` command to pretty-print a Lua expression by prefixing it with `=` (Neovim 0.7+ only): 441 | ```vim 442 | :lua =vim.loop 443 | ``` 444 | 445 | Additionally, you may find that built-in Lua functions are sometimes lacking compared to what you would find in other languages (for example `os.clock()` only returns a value in seconds, not milliseconds). Be sure to look at the Neovim stdlib (and `vim.fn`, more on that later), it probably has what you're looking for. 446 | 447 | ## Using Vimscript from Lua 448 | 449 | ### vim.api.nvim_eval() 450 | 451 | This function evaluates a Vimscript expression string and returns its value. Vimscript data types are automatically converted to Lua types (and vice versa). 452 | 453 | It is the Lua equivalent of the `luaeval()` function in Vimscript 454 | 455 | ```lua 456 | -- Data types are converted correctly 457 | print(vim.api.nvim_eval('1 + 1')) -- 2 458 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 459 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" } 460 | print(vim.api.nvim_eval('v:true')) -- true 461 | print(vim.api.nvim_eval('v:null')) -- nil 462 | ``` 463 | 464 | #### Caveats 465 | 466 | Unlike `luaeval()`, `vim.api.nvim_eval()` does not provide an implicit `_A` variable to pass data to the expression. 467 | 468 | ### vim.api.nvim_exec() 469 | 470 | This function evaluates a chunk of Vimscript code. It takes in a string containing the source code to execute and a boolean to determine whether the output of the code should be returned by the function (you can then store the output in a variable, for example). 471 | 472 | ```lua 473 | local result = vim.api.nvim_exec( 474 | [[ 475 | let s:mytext = 'hello world' 476 | 477 | function! s:MyFunction(text) 478 | echo a:text 479 | endfunction 480 | 481 | call s:MyFunction(s:mytext) 482 | ]], 483 | true) 484 | 485 | print(result) -- 'hello world' 486 | ``` 487 | 488 | #### Caveats 489 | 490 | `nvim_exec` does not support script-local variables (`s:`) prior to Neovim 0.6.0 491 | 492 | ### vim.api.nvim_command() 493 | 494 | This function executes an ex command. It takes in a string containing the command to execute. 495 | 496 | ```lua 497 | vim.api.nvim_command('new') 498 | vim.api.nvim_command('wincmd H') 499 | vim.api.nvim_command('set nonumber') 500 | vim.api.nvim_command('%s/foo/bar/g') 501 | ``` 502 | 503 | ### vim.cmd() 504 | 505 | Alias for `vim.api.nvim_exec()`. Only the command argument is needed, `output` is always set to `false`. 506 | 507 | ```lua 508 | vim.cmd('buffers') 509 | vim.cmd([[ 510 | let g:multiline_list = [ 511 | \ 1, 512 | \ 2, 513 | \ 3, 514 | \ ] 515 | 516 | echo g:multiline_list 517 | ]]) 518 | ``` 519 | 520 | #### Tips 521 | 522 | Since you have to pass strings to these functions, you often end up having to escape backslashes: 523 | 524 | ```lua 525 | vim.cmd('%s/\\Vfoo/bar/g') 526 | ``` 527 | 528 | Double bracketed strings are easier to use as they do not require escaping characters: 529 | 530 | ```lua 531 | vim.cmd([[%s/\Vfoo/bar/g]]) 532 | ``` 533 | 534 | ### vim.api.nvim_replace_termcodes() 535 | 536 | This API function allows you to escape terminal codes and Vim keycodes. 537 | 538 | You may have come across mappings like this one: 539 | 540 | ```vim 541 | inoremap pumvisible() ? "\" : "\" 542 | ``` 543 | 544 | Trying to do the same in Lua can prove to be a challenge. You might be tempted to do it like this: 545 | 546 | ```lua 547 | function _G.smart_tab() 548 | return vim.fn.pumvisible() == 1 and [[\]] or [[\]] 549 | end 550 | 551 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 552 | ``` 553 | 554 | only to find out that the mapping inserts `\` and `\` literally... 555 | 556 | Being able to escape keycodes is actually a Vimscript feature. Aside from the usual escape sequences like `\r`, `\42` or `\x10` that are common to many programming languages, Vimscript `expr-quotes` (strings surrounded with double quotes) allow you to escape the human-readable representation of Vim keycodes. 557 | 558 | Lua doesn't have such a feature built-in. Fortunately, Neovim has an API function for escaping terminal codes and keycodes: `nvim_replace_termcodes()` 559 | 560 | ```lua 561 | print(vim.api.nvim_replace_termcodes('', true, true, true)) 562 | ``` 563 | 564 | This is a little verbose. Making a reusable wrapper can help: 565 | 566 | ```lua 567 | -- The function is called `t` for `termcodes`. 568 | -- You don't have to call it that, but I find the terseness convenient 569 | local function t(str) 570 | -- Adjust boolean arguments as needed 571 | return vim.api.nvim_replace_termcodes(str, true, true, true) 572 | end 573 | 574 | print(t'') 575 | ``` 576 | 577 | Coming back to our earlier example, this should now work as expected: 578 | 579 | ```lua 580 | local function t(str) 581 | return vim.api.nvim_replace_termcodes(str, true, true, true) 582 | end 583 | 584 | function _G.smart_tab() 585 | return vim.fn.pumvisible() == 1 and t'' or t'' 586 | end 587 | 588 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 589 | ``` 590 | 591 | This is not necessary with `vim.keymap.set()` as it automatically transforms vim keycodes returned by Lua functions in `expr` mappings by default: 592 | 593 | ```lua 594 | vim.keymap.set('i', '', function() 595 | return vim.fn.pumvisible() == 1 and '' or '' 596 | end, {expr = true}) 597 | ``` 598 | 599 | See also: 600 | 601 | - [`:help keycodes`](https://neovim.io/doc/user/intro.html#keycodes) 602 | - [`:help expr-quote`](https://neovim.io/doc/user/eval.html#expr-quote) 603 | - [`:help nvim_replace_termcodes()`](https://neovim.io/doc/user/api.html#nvim_replace_termcodes()) 604 | 605 | ## Managing vim options 606 | 607 | ### Using api functions 608 | 609 | Neovim provides a set of API functions to either set an option or get its current value: 610 | 611 | - Global options: 612 | - [`vim.api.nvim_set_option()`](https://neovim.io/doc/user/api.html#nvim_set_option()) 613 | - [`vim.api.nvim_get_option()`](https://neovim.io/doc/user/api.html#nvim_get_option()) 614 | - Buffer-local options: 615 | - [`vim.api.nvim_buf_set_option()`](https://neovim.io/doc/user/api.html#nvim_buf_set_option()) 616 | - [`vim.api.nvim_buf_get_option()`](https://neovim.io/doc/user/api.html#nvim_buf_get_option()) 617 | - Window-local options: 618 | - [`vim.api.nvim_win_set_option()`](https://neovim.io/doc/user/api.html#nvim_win_set_option()) 619 | - [`vim.api.nvim_win_get_option()`](https://neovim.io/doc/user/api.html#nvim_win_get_option()) 620 | 621 | They take a string containing the name of the option to set/get as well as the value you want to set it to. 622 | 623 | Boolean options (like `(no)number`) have to be set to either `true` or `false`: 624 | 625 | ```lua 626 | vim.api.nvim_set_option('smarttab', false) 627 | print(vim.api.nvim_get_option('smarttab')) -- false 628 | ``` 629 | 630 | Unsurprisingly, string options have to be set to a string: 631 | 632 | ```lua 633 | vim.api.nvim_set_option('selection', 'exclusive') 634 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 635 | ``` 636 | 637 | Number options accept a number: 638 | 639 | ```lua 640 | vim.api.nvim_set_option('updatetime', 3000) 641 | print(vim.api.nvim_get_option('updatetime')) -- 3000 642 | ``` 643 | 644 | Buffer-local and window-local options also need a buffer number or a window number (using `0` will set/get the option for the current buffer/window): 645 | 646 | ```lua 647 | vim.api.nvim_win_set_option(0, 'number', true) 648 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 649 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 650 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 651 | ``` 652 | 653 | ### Using meta-accessors 654 | 655 | A few meta-accessors are available if you want to set options in a more "idiomatic" way. They essentially wrap the above API functions and allow you to manipulate options as if they were variables: 656 | 657 | - [`vim.o`](https://neovim.io/doc/user/lua.html#vim.o): behaves like `:let &{option-name}` 658 | - [`vim.go`](https://neovim.io/doc/user/lua.html#vim.go): behaves like `:let &g:{option-name}` 659 | - [`vim.bo`](https://neovim.io/doc/user/lua.html#vim.bo): behaves like `:let &l:{option-name}` for buffer-local options 660 | - [`vim.wo`](https://neovim.io/doc/user/lua.html#vim.wo): behaves like `:let &l:{option-name}` for window-local options 661 | 662 | ```lua 663 | vim.o.smarttab = false -- let &smarttab = v:false 664 | print(vim.o.smarttab) -- false 665 | vim.o.isfname = vim.o.isfname .. ',@-@' -- on Linux: let &isfname = &isfname .. ',@-@' 666 | print(vim.o.isfname) -- '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@' 667 | 668 | vim.bo.shiftwidth = 4 669 | print(vim.bo.shiftwidth) -- 4 670 | ``` 671 | 672 | You can specify a number for buffer-local and window-local options. If no number is given, the current buffer/window is used: 673 | 674 | ```lua 675 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 'expandtab', true) 676 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 'number', true) 677 | ``` 678 | 679 | These wrappers also have more sophisticated `vim.opt*` variants that provide convenient mechanisms for setting options in Lua. They're similar to what you might be used to in your `init.vim`: 680 | 681 | - `vim.opt`: behaves like `:set` 682 | - `vim.opt_global`: behaves like `:setglobal` 683 | - `vim.opt_local`: behaves like `:setlocal` 684 | 685 | ```lua 686 | vim.opt.smarttab = false 687 | print(vim.opt.smarttab:get()) -- false 688 | ``` 689 | 690 | Some options can be set using Lua tables: 691 | 692 | ```lua 693 | vim.opt.completeopt = {'menuone', 'noselect'} 694 | print(vim.inspect(vim.opt.completeopt:get())) -- { "menuone", "noselect" } 695 | ``` 696 | 697 | Wrappers for list-like, map-like and set-like options also come with methods and metamethods that work similarly to their `:set+=`, `:set^=` and `:set-=` counterparts in Vimscript. 698 | 699 | ```lua 700 | vim.opt.shortmess:append({ I = true }) 701 | -- alternative form: 702 | vim.opt.shortmess = vim.opt.shortmess + { I = true } 703 | 704 | vim.opt.whichwrap:remove({ 'b', 's' }) 705 | -- alternative form: 706 | vim.opt.whichwrap = vim.opt.whichwrap - { 'b', 's' } 707 | ``` 708 | 709 | Be sure to look at [`:help vim.opt`](https://neovim.io/doc/user/lua.html#vim.opt) for more information. 710 | 711 | See also: 712 | - [`:help lua-vim-options`](https://neovim.io/doc/user/lua.html#lua-vim-options) 713 | 714 | ## Managing vim internal variables 715 | 716 | ### Using api functions 717 | 718 | Much like options, internal variables have their own set of API functions: 719 | 720 | - Global variables (`g:`): 721 | - [`vim.api.nvim_set_var()`](https://neovim.io/doc/user/api.html#nvim_set_var()) 722 | - [`vim.api.nvim_get_var()`](https://neovim.io/doc/user/api.html#nvim_get_var()) 723 | - [`vim.api.nvim_del_var()`](https://neovim.io/doc/user/api.html#nvim_del_var()) 724 | - Buffer variables (`b:`): 725 | - [`vim.api.nvim_buf_set_var()`](https://neovim.io/doc/user/api.html#nvim_buf_set_var()) 726 | - [`vim.api.nvim_buf_get_var()`](https://neovim.io/doc/user/api.html#nvim_buf_get_var()) 727 | - [`vim.api.nvim_buf_del_var()`](https://neovim.io/doc/user/api.html#nvim_buf_del_var()) 728 | - Window variables (`w:`): 729 | - [`vim.api.nvim_win_set_var()`](https://neovim.io/doc/user/api.html#nvim_win_set_var()) 730 | - [`vim.api.nvim_win_get_var()`](https://neovim.io/doc/user/api.html#nvim_win_get_var()) 731 | - [`vim.api.nvim_win_del_var()`](https://neovim.io/doc/user/api.html#nvim_win_del_var()) 732 | - Tabpage variables (`t:`): 733 | - [`vim.api.nvim_tabpage_set_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_set_var()) 734 | - [`vim.api.nvim_tabpage_get_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_get_var()) 735 | - [`vim.api.nvim_tabpage_del_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_del_var()) 736 | - Predefined Vim variables (`v:`): 737 | - [`vim.api.nvim_set_vvar()`](https://neovim.io/doc/user/api.html#nvim_set_vvar()) 738 | - [`vim.api.nvim_get_vvar()`](https://neovim.io/doc/user/api.html#nvim_get_vvar()) 739 | 740 | With the exception of predefined Vim variables, they can also be deleted (the `:unlet` command is the equivalent in Vimscript). Local variables (`l:`), script variables (`s:`) and function arguments (`a:`) cannot be manipulated as they only make sense in the context of a Vim script, Lua has its own scoping rules. 741 | 742 | If you are unfamiliar with what these variables do, [`:help internal-variables`](https://neovim.io/doc/user/eval.html#internal-variables) describes them in detail. 743 | 744 | These functions take a string containing the name of the variable to set/get/delete as well as the value you want to set it to. 745 | 746 | ```lua 747 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 300 }) 748 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- { key1 = "value", key2 = 300 } 749 | vim.api.nvim_del_var('some_global_variable') 750 | ``` 751 | 752 | Variables that are scoped to a buffer, a window or a tabpage also receive a number (using `0` will set/get/delete the variable for the current buffer/window/tabpage): 753 | 754 | ```lua 755 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 756 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 757 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 758 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 'hello world' 759 | vim.api.nvim_win_del_var(0, 'some_window_variable') 760 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 761 | ``` 762 | 763 | ### Using meta-accessors 764 | 765 | Internal variables can be manipulated more intuitively using these meta-accessors: 766 | 767 | - [`vim.g`](https://neovim.io/doc/user/lua.html#vim.g): global variables 768 | - [`vim.b`](https://neovim.io/doc/user/lua.html#vim.b): buffer variables 769 | - [`vim.w`](https://neovim.io/doc/user/lua.html#vim.w): window variables 770 | - [`vim.t`](https://neovim.io/doc/user/lua.html#vim.t): tabpage variables 771 | - [`vim.v`](https://neovim.io/doc/user/lua.html#vim.v): predefined Vim variables 772 | - [`vim.env`](https://neovim.io/doc/user/lua.html#vim.env): environment variables 773 | 774 | ```lua 775 | vim.g.some_global_variable = { 776 | key1 = 'value', 777 | key2 = 300 778 | } 779 | 780 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", key2 = 300 } 781 | 782 | -- target a specific buffer/window/tabpage (Neovim 0.6+) 783 | vim.b[2].myvar = 1 784 | ``` 785 | 786 | Some variable names may contain characters that cannot be used for identifiers in Lua. You can still manipulate these variables by using this syntax: `vim.g['my#variable']`. 787 | 788 | To delete one of these variables, simply assign `nil` to it: 789 | 790 | ```lua 791 | vim.g.some_global_variable = nil 792 | ``` 793 | 794 | See also: 795 | - [`:help lua-vim-variables`](https://neovim.io/doc/user/lua.html#lua-vim-variables) 796 | 797 | #### Caveats 798 | 799 | You cannot add/update/delete keys from a dictionary stored in one of these variables. For example, this snippet of Vimscript code does not work as expected: 800 | 801 | ```vim 802 | let g:variable = {} 803 | lua vim.g.variable.key = 'a' 804 | echo g:variable 805 | " {} 806 | ``` 807 | 808 | You can use a temporary variable as a workaround: 809 | 810 | ```vim 811 | let g:variable = {} 812 | lua << EOF 813 | local tmp = vim.g.variable 814 | tmp.key = 'a' 815 | vim.g.variable = tmp 816 | EOF 817 | echo g:variable 818 | " {'key': 'a'} 819 | ``` 820 | 821 | This is a known issue: 822 | 823 | - [Issue #12544](https://github.com/neovim/neovim/issues/12544) 824 | 825 | ## Calling Vimscript functions 826 | 827 | ### vim.fn.{function}() 828 | 829 | `vim.fn` can be used to call a Vimscript function. Data types are converted back and forth from Lua to Vimscript. 830 | 831 | ```lua 832 | print(vim.fn.printf('Hello from %s', 'Lua')) 833 | 834 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 835 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 836 | 837 | local function print_stdout(chan_id, data, name) 838 | print(data[1]) 839 | end 840 | 841 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 842 | ``` 843 | 844 | Hashes (`#`) are not valid characters for identifiers in Lua, so autoload functions have to be called with this syntax: 845 | 846 | ```lua 847 | vim.fn['my#autoload#function']() 848 | ``` 849 | 850 | The functionality of `vim.fn` is identical to `vim.call`, but allows a more Lua-like syntax. 851 | 852 | It is distinct from `vim.api.nvim_call_function` in that converting Vim/Lua objects is automatic: `vim.api.nvim_call_function` returns a table for floating point numbers and does not accept Lua closures while `vim.fn` handles these types transparently. 853 | 854 | See also: 855 | - [`:help vim.fn`](https://neovim.io/doc/user/lua.html#vim.fn) 856 | 857 | #### Tips 858 | 859 | Neovim has an extensive library of powerful built-in functions that are very useful for plugins. See [`:help vim-function`](https://neovim.io/doc/user/eval.html#vim-function) for an alphabetical list and [`:help function-list`](https://neovim.io/doc/user/usr_41.html#function-list) for a list of functions grouped by topic. 860 | 861 | Neovim API functions can be used directly through `vim.api.{..}`. See [`:help api`](https://neovim.io/doc/user/api.html#API) for information. 862 | 863 | #### Caveats 864 | 865 | Some Vim functions that should return a boolean return `1` or `0` instead. This isn't a problem in Vimscript as `1` is truthy and `0` falsy, enabling constructs like these: 866 | 867 | ```vim 868 | if has('nvim') 869 | " do something... 870 | endif 871 | ``` 872 | 873 | In Lua however, only `false` and `nil` are considered falsy, numbers always evaluate to `true` no matter their value. You have to explicitly check for `1` or `0`: 874 | 875 | ```lua 876 | if vim.fn.has('nvim') == 1 then 877 | -- do something... 878 | end 879 | ``` 880 | 881 | ## Defining mappings 882 | 883 | ### API functions 884 | 885 | Neovim provides a list of API functions to set, get and delete mappings: 886 | 887 | - Global mappings: 888 | - [`vim.api.nvim_set_keymap()`](https://neovim.io/doc/user/api.html#nvim_set_keymap()) 889 | - [`vim.api.nvim_get_keymap()`](https://neovim.io/doc/user/api.html#nvim_get_keymap()) 890 | - [`vim.api.nvim_del_keymap()`](https://neovim.io/doc/user/api.html#nvim_del_keymap()) 891 | - Buffer-local mappings: 892 | - [`vim.api.nvim_buf_set_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_set_keymap()) 893 | - [`vim.api.nvim_buf_get_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_get_keymap()) 894 | - [`vim.api.nvim_buf_del_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_del_keymap()) 895 | 896 | Let's start with `vim.api.nvim_set_keymap()` and `vim.api.nvim_buf_set_keymap()` 897 | 898 | The first argument passed to the function is a string containing the name of the mode for which the mapping will take effect: 899 | 900 | | String value | Help page | Affected modes | Vimscript equivalent | 901 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 902 | | `''` (an empty string) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 903 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 904 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 905 | | `'s'` | `mapmode-s` | Select | `:smap` | 906 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 907 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 908 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 909 | | `'i'` | `mapmode-i` | Insert | `:imap` | 910 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 911 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 912 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 913 | 914 | The second argument is a string containing the left-hand side of the mapping (the key or set of keys that trigger the command defined in the mapping). An empty string is equivalent to ``, which disables a key. 915 | 916 | The third argument is a string containing the right-hand side of the mapping (the command to execute). 917 | 918 | The final argument is a table containing boolean options for the mapping as defined in [`:help :map-arguments`](https://neovim.io/doc/user/map.html#:map-arguments) (including `noremap` and excluding `buffer`). Since Neovim 0.7.0, you can also pass a `callback` option to invoke a Lua function instead of the right-hand side when executing the mapping. 919 | 920 | Buffer-local mappings also take a buffer number as their first argument (`0` sets the mapping for the current buffer). 921 | 922 | ```lua 923 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', { noremap = true, silent = true }) 924 | -- :nnoremap :set hlsearch 925 | vim.api.nvim_set_keymap('n', 'tegf', [[lua require('telescope.builtin').git_files()]], { noremap = true, silent = true }) 926 | -- :nnoremap tegf lua require('telescope.builtin').git_files() 927 | 928 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : "ggcc"', { noremap = true, expr = true }) 929 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 930 | 931 | vim.api.nvim_set_keymap('n', 'ex', '', { 932 | noremap = true, 933 | callback = function() 934 | print('My example') 935 | end, 936 | -- Since Lua function don't have a useful string representation, you can use the "desc" option to document your mapping 937 | desc = 'Prints "My example" in the message area', 938 | }) 939 | ``` 940 | 941 | `vim.api.nvim_get_keymap()` takes a string containing the shortname of the mode for which you want the list of mappings (see table above). The return value is a table containing all global mappings for the mode. 942 | 943 | ```lua 944 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 945 | -- :verbose nmap 946 | ``` 947 | 948 | `vim.api.nvim_buf_get_keymap()` takes an additional buffer number as its first argument (`0` will get mapppings for the current bufffer) 949 | 950 | ```lua 951 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 952 | -- :verbose imap 953 | ``` 954 | 955 | `vim.api.nvim_del_keymap()` takes a mode and the left-hand side of a mapping. 956 | 957 | ```lua 958 | vim.api.nvim_del_keymap('n', '') 959 | -- :nunmap 960 | ``` 961 | 962 | Again, `vim.api.nvim_buf_del_keymap()`, takes a buffer number as its first argument, with `0` representing the current buffer. 963 | 964 | ```lua 965 | vim.api.nvim_buf_del_keymap(0, 'i', '') 966 | -- :iunmap 967 | ``` 968 | 969 | ### vim.keymap 970 | 971 | :warning: The functions discussed in this section are only available in Neovim 0.7.0+ 972 | 973 | Neovim provides two functions to set/del mappings: 974 | - [`vim.keymap.set()`](https://neovim.io/doc/user/lua.html#vim.keymap.set()) 975 | - [`vim.keymap.del()`](https://neovim.io/doc/user/lua.html#vim.keymap.del()) 976 | 977 | These are similar to the above API functions with added syntactic sugar. 978 | 979 | `vim.keymap.set()` takes a string as its first argument. It can also be a table of strings to define mappings for multiple modes at once: 980 | 981 | ```lua 982 | vim.keymap.set('n', 'ex1', 'lua vim.notify("Example 1")') 983 | vim.keymap.set({'n', 'c'}, 'ex2', 'lua vim.notify("Example 2")') 984 | ``` 985 | 986 | The second argument is the left-hand side of the mapping. 987 | 988 | The third argument is the right-hand side of the mapping, which can either be a string or a Lua function: 989 | 990 | ```lua 991 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"') 992 | vim.keymap.set('n', 'ex2', function() print("Example 2") end) 993 | vim.keymap.set('n', 'pl1', require('plugin').plugin_action) 994 | -- To avoid the startup cost of requiring the module, you can wrap it in a function to require it lazily when invoking the mapping: 995 | vim.keymap.set('n', 'pl2', function() require('plugin').plugin_action() end) 996 | ``` 997 | 998 | The fourth (optional) argument is a table of options that correspond to the options passed to `vim.api.nvim_set_keymap()`, with a few additions (see [`:help vim.keymap.set()`](https://neovim.io/doc/user/lua.html#vim.keymap.set()) for the full list). 999 | 1000 | ```lua 1001 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"', {buffer = true}) 1002 | vim.keymap.set('n', 'ex2', function() print('Example 2') end, {desc = 'Prints "Example 2" to the message area'}) 1003 | ``` 1004 | 1005 | Defining keymaps with a Lua function is different from using a string. The usual way to show information about a keymap like `:nmap ex1` will not output useful information (the string itself), but instead only show `Lua function`. It is recommended to add a `desc` key to describe the behavior of your keymap. This is especially important for documenting plugin mappings so users can understand the usage of the keymap more easily. 1006 | 1007 | An interesting feature of this API is that it irons out some historical quirks of Vim mappings: 1008 | - Mappings are `noremap` by default, except when the `rhs` is a `` mapping. This means you rarely have to think about whether a mapping should be recursive or not: 1009 | ```lua 1010 | vim.keymap.set('n', 'test1', 'echo "test"') 1011 | -- :nnoremap test echo "test" 1012 | 1013 | -- If you DO want the mapping to be recursive, set the "remap" option to "true" 1014 | vim.keymap.set('n', '>', ']', {remap = true}) 1015 | -- :nmap > ] 1016 | 1017 | -- mappings don't work unless they're recursive, vim.keymap.set() handles that for you automatically 1018 | vim.keymap.set('n', 'plug', '(plugin)') 1019 | -- :nmap plug (plugin) 1020 | ``` 1021 | - In `expr` mappings, `nvim_replace_termcodes()` is automatically applied to strings returned from Lua functions: 1022 | ```lua 1023 | vim.keymap.set('i', '', function() 1024 | return vim.fn.pumvisible == 1 and '' or '' 1025 | end, {expr = true}) 1026 | ``` 1027 | 1028 | See also: 1029 | - [`:help recursive_mapping`](https://neovim.io/doc/user/map.html#recursive_mapping) 1030 | 1031 | `vim.keymap.del()` works the same way but deletes mappings instead: 1032 | 1033 | ```lua 1034 | vim.keymap.del('n', 'ex1') 1035 | vim.keymap.del({'n', 'c'}, 'ex2', {buffer = true}) 1036 | ``` 1037 | 1038 | ## Defining user commands 1039 | 1040 | :warning: The API functions discussed in this section are only available in Neovim 0.7.0+ 1041 | 1042 | Neovim provides API functions for user-defined commands: 1043 | 1044 | - Global user commands: 1045 | - [`vim.api.nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command()) 1046 | - [`vim.api.nvim_del_user_command()`](https://neovim.io/doc/user/api.html#nvim_del_user_command()) 1047 | - Buffer-local user commands: 1048 | - [`vim.api.nvim_buf_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_buf_create_user_command()) 1049 | - [`vim.api.nvim_buf_del_user_command()`](https://neovim.io/doc/user/api.html#nvim_buf_del_user_command()) 1050 | 1051 | Let's start with `vim.api.nvim_create_user_command()` 1052 | 1053 | The first argument passed to this function is the name of the command (which must start with an uppercase letter). 1054 | 1055 | The second argument is the code to execute when invoking said command. It can either be: 1056 | 1057 | A string (in which case it will be executed as Vimscript). You can use escape sequences like ``, ``, etc. like you would with `:command` 1058 | ```lua 1059 | vim.api.nvim_create_user_command('Upper', 'echo toupper()', { nargs = 1 }) 1060 | -- :command! -nargs=1 Upper echo toupper() 1061 | 1062 | vim.cmd('Upper hello world') -- prints "HELLO WORLD" 1063 | ``` 1064 | 1065 | Or a Lua function. It receives a dictionary-like table that contains the data normally provided by escape sequences (see [`:help nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command()) for a list of available keys) 1066 | ```lua 1067 | vim.api.nvim_create_user_command( 1068 | 'Upper', 1069 | function(opts) 1070 | print(string.upper(opts.args)) 1071 | end, 1072 | { nargs = 1 } 1073 | ) 1074 | ``` 1075 | 1076 | The third argument lets you pass command attributes as a table (see [`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes)). Since you can already define buffer-local user commands with `vim.api.nvim_buf_create_user_command()`, `-buffer` is not a valid attribute. 1077 | 1078 | Two additional attributes are available: 1079 | - `desc` allows you to control what gets displayed when you run `:command {cmd}` on a command defined as a Lua callback. Similarly to keymaps, it is recommended to add a `desc` key to commands defined as Lua functions. 1080 | - `force` is equivalent to calling `:command!` and replaces a command if one with the same name already exists. It is true by default, unlike its Vimscript equivalent. 1081 | 1082 | The `-complete` attribute can take a Lua function in addition to the attributes listed in [`:help :command-complete`](https://neovim.io/doc/user/map.html#:command-complete). 1083 | 1084 | ```lua 1085 | vim.api.nvim_create_user_command('Upper', function() end, { 1086 | nargs = 1, 1087 | complete = function(ArgLead, CmdLine, CursorPos) 1088 | -- return completion candidates as a list-like table 1089 | return { 'foo', 'bar', 'baz' } 1090 | end, 1091 | }) 1092 | ``` 1093 | 1094 | Buffer-local user commands also take a buffer number as their first argument. This is an advantage over `-buffer` which can only define a command for the current buffer. 1095 | 1096 | ```lua 1097 | vim.api.nvim_buf_create_user_command(4, 'Upper', function() end, {}) 1098 | ``` 1099 | 1100 | `vim.api.nvim_del_user_command()` takes a command name. 1101 | 1102 | ```lua 1103 | vim.api.nvim_del_user_command('Upper') 1104 | -- :delcommand Upper 1105 | ``` 1106 | 1107 | Again, `vim.api.nvim_buf_del_user_command()`, takes a buffer number as its first argument, with `0` representing the current buffer. 1108 | 1109 | ```lua 1110 | vim.api.nvim_buf_del_user_command(4, 'Upper') 1111 | ``` 1112 | 1113 | See also: 1114 | - [`:help nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command()) 1115 | - [`:help 40.2`](https://neovim.io/doc/user/usr_40.html#40.2) 1116 | - [`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes) 1117 | 1118 | ### Caveats 1119 | 1120 | The `-complete=custom` attribute automatically filters completion candidates and has built-in wildcard ([`:help wildcard`](https://neovim.io/doc/user/editing.html#wildcard)) support: 1121 | 1122 | ```vim 1123 | function! s:completion_function(ArgLead, CmdLine, CursorPos) abort 1124 | return join([ 1125 | \ 'strawberry', 1126 | \ 'star', 1127 | \ 'stellar', 1128 | \ ], "\n") 1129 | endfunction 1130 | 1131 | command! -nargs=1 -complete=custom,s:completion_function Test echo 1132 | " Typing `:Test st[ae]` returns "star" and "stellar" 1133 | ``` 1134 | 1135 | Passing a Lua function to `complete` makes it behave like `customlist` which leaves filtering up to the user: 1136 | 1137 | ```lua 1138 | vim.api.nvim_create_user_command('Test', function() end, { 1139 | nargs = 1, 1140 | complete = function(ArgLead, CmdLine, CursorPos) 1141 | return { 1142 | 'strawberry', 1143 | 'star', 1144 | 'stellar', 1145 | } 1146 | end, 1147 | }) 1148 | 1149 | -- Typing `:Test z` returns all the completion results because the list was not filtered 1150 | ``` 1151 | 1152 | ## Defining autocommands 1153 | 1154 | (this section is a work in progress) 1155 | 1156 | Neovim 0.7.0 has API functions for autocommands. See `:help api-autocmd` for details 1157 | 1158 | - [Pull request #14661](https://github.com/neovim/neovim/pull/14661) (lua: autocmds take 2) 1159 | 1160 | ## Defining highlights 1161 | 1162 | (this section is a work in progress) 1163 | 1164 | Neovim 0.7.0 has API functions for highlight groups. See also: 1165 | 1166 | - [`:help nvim_set_hl()`](https://neovim.io/doc/user/api.html#nvim_set_hl()) 1167 | - [`:help nvim_get_hl_by_id()`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_id()) 1168 | - [`:help nvim_get_hl_by_name()`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_name()) 1169 | 1170 | ## General tips and recommendations 1171 | 1172 | ### Reloading cached modules 1173 | 1174 | In Lua, the `require()` function caches modules. This is a good thing for performance, but it can make working on plugins a bit cumbersome because modules are not updated on subsequent `require()` calls. 1175 | 1176 | If you'd like to refresh the cache for a particular module, you have to modify the `package.loaded` global table: 1177 | 1178 | ```lua 1179 | package.loaded['modname'] = nil 1180 | require('modname') -- loads an updated version of module 'modname' 1181 | ``` 1182 | 1183 | The [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) plugin has a [custom function](https://github.com/nvim-lua/plenary.nvim/blob/master/lua/plenary/reload.lua) that does this for you. 1184 | 1185 | ### Don't pad Lua strings! 1186 | 1187 | When using double bracketed strings, resist the temptation to pad them! While it is fine to do in contexts where spaces are ignored, it can cause hard to debug issues when whitespace is significant: 1188 | 1189 | ```lua 1190 | vim.api.nvim_set_keymap('n', 'f', [[ call foo() ]], {noremap = true}) 1191 | ``` 1192 | 1193 | In the above example, `f` is mapped to `call foo()` instead of `call foo()`. 1194 | 1195 | ### Notes about Vimscript <-> Lua type conversion 1196 | 1197 | #### Converting a variable creates a copy: 1198 | You can't directly interact with the reference to a Vim object from Lua or a Lua object from Vimscript. 1199 | For example, the `map()` function in Vimscript modifies a variable in place: 1200 | 1201 | ```vim 1202 | let s:list = [1, 2, 3] 1203 | let s:newlist = map(s:list, {_, v -> v * 2}) 1204 | 1205 | echo s:list 1206 | " [2, 4, 6] 1207 | echo s:newlist 1208 | " [2, 4, 6] 1209 | echo s:list is# s:newlist 1210 | " 1 1211 | ``` 1212 | 1213 | Using this function from Lua creates a copy instead: 1214 | 1215 | ```lua 1216 | local tbl = {1, 2, 3} 1217 | local newtbl = vim.fn.map(tbl, function(_, v) return v * 2 end) 1218 | 1219 | print(vim.inspect(tbl)) -- { 1, 2, 3 } 1220 | print(vim.inspect(newtbl)) -- { 2, 4, 6 } 1221 | print(tbl == newtbl) -- false 1222 | ``` 1223 | 1224 | #### Conversion is not always possible 1225 | This mostly affects functions and tables: 1226 | 1227 | Lua tables that are a mix between a List and a Dictionary can't be converted: 1228 | 1229 | ```lua 1230 | print(vim.fn.count({1, 1, number = 1}, 1)) 1231 | -- E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys 1232 | ``` 1233 | 1234 | While you can call Vim functions in Lua with `vim.fn`, you can't hold references to them. This can cause surprising behaviors: 1235 | 1236 | ```lua 1237 | local FugitiveHead = vim.fn.funcref('FugitiveHead') 1238 | print(FugitiveHead) -- vim.NIL 1239 | 1240 | vim.cmd("let g:test_dict = {'test_lambda': {-> 1}}") 1241 | print(vim.g.test_dict.test_lambda) -- nil 1242 | print(vim.inspect(vim.g.test_dict)) -- {} 1243 | ``` 1244 | 1245 | Passing Lua functions to Vim functions is OK, storing them in Vim variables is not (fixed in Neovim 0.7.0+): 1246 | 1247 | ```lua 1248 | -- This works: 1249 | vim.fn.jobstart({'ls'}, { 1250 | on_stdout = function(chan_id, data, name) 1251 | print(vim.inspect(data)) 1252 | end 1253 | }) 1254 | 1255 | -- This doesn't: 1256 | vim.g.test_dict = {test_lambda = function() return 1 end} -- Error: Cannot convert given lua type 1257 | ``` 1258 | 1259 | Note however that doing the same from Vimscript with `luaeval()` **does** work: 1260 | 1261 | ```vim 1262 | let g:test_dict = {'test_lambda': luaeval('function() return 1 end')} 1263 | echo g:test_dict 1264 | " {'test_lambda': function('4714')} 1265 | ``` 1266 | 1267 | #### Vim booleans 1268 | A common pattern in Vim scripts is to use `1` or `0` instead of proper booleans. Indeed, Vim did not have a separate boolean type until version 7.4.1154. 1269 | 1270 | Lua booleans are converted to actual booleans in Vimscript, not numbers: 1271 | 1272 | ```vim 1273 | lua vim.g.lua_true = true 1274 | echo g:lua_true 1275 | " v:true 1276 | lua vim.g.lua_false = false 1277 | echo g:lua_false 1278 | " v:false 1279 | ``` 1280 | 1281 | ### Setting up linters/language servers 1282 | 1283 | If you're using linters and/or language servers to get diagnostics and autocompletion for Lua projects, you may have to configure Neovim-specific settings for them. Here are a few recommended settings for popular tools: 1284 | 1285 | #### luacheck 1286 | 1287 | You can get [luacheck](https://github.com/mpeterv/luacheck/) to recognize the `vim` global by putting this configuration in `~/.luacheckrc` (or `$XDG_CONFIG_HOME/luacheck/.luacheckrc`): 1288 | 1289 | ```lua 1290 | globals = { 1291 | "vim", 1292 | } 1293 | ``` 1294 | 1295 | The [Alloyed/lua-lsp](https://github.com/Alloyed/lua-lsp/) language server uses `luacheck` to provide linting and reads the same file. 1296 | 1297 | For more information on how to configure `luacheck`, please refer to its [documentation](https://luacheck.readthedocs.io/en/stable/config.html) 1298 | 1299 | #### sumneko/lua-language-server 1300 | 1301 | The [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) repository contains [instructions to configure sumneko/lua-language-server](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#sumneko_lua) (the example uses the built-in LSP client but the configuration should be identical for other LSP client implementations). 1302 | 1303 | For more information on how to configure [sumneko/lua-language-server](https://github.com/sumneko/lua-language-server/) see ["Setting"](https://github.com/sumneko/lua-language-server/wiki/Setting) 1304 | 1305 | #### coc.nvim 1306 | 1307 | The [rafcamlet/coc-nvim-lua](https://github.com/rafcamlet/coc-nvim-lua/) completion source for [coc.nvim](https://github.com/neoclide/coc.nvim/) provides completion items for the Neovim stdlib. 1308 | 1309 | ### Debugging Lua code 1310 | 1311 | You can debug Lua code running in a separate Neovim instance with [jbyuki/one-small-step-for-vimkind](https://github.com/jbyuki/one-small-step-for-vimkind) 1312 | 1313 | The plugin uses the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/). Connecting to a debug adapter requires a DAP client like [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap/) or [puremourning/vimspector](https://github.com/puremourning/vimspector/). 1314 | 1315 | ### Debugging Lua mappings/commands/autocommands 1316 | 1317 | The `:verbose` command allows you to see where a mapping/command/autocommand was defined: 1318 | 1319 | ```vim 1320 | :verbose map m 1321 | ``` 1322 | 1323 | ```text 1324 | n m_ * echo 'example' 1325 | Last set from ~/.config/nvim/init.vim line 26 1326 | ``` 1327 | 1328 | By default, this feature is disabled in Lua for performance reasons. You can enable it by starting Neovim with a verbose level greater than 0: 1329 | 1330 | ```sh 1331 | nvim -V1 1332 | ``` 1333 | 1334 | See also: 1335 | - [`:help 'verbose'`](https://neovim.io/doc/user/options.html#'verbose') 1336 | - [`:help -V`](https://neovim.io/doc/user/starting.html#-V) 1337 | - [neovim/neovim#15079](https://github.com/neovim/neovim/pull/15079) 1338 | 1339 | ### Testing Lua code 1340 | 1341 | - [plenary.nvim: test harness](https://github.com/nvim-lua/plenary.nvim/#plenarytest_harness) 1342 | - [notomo/vusted](https://github.com/notomo/vusted) 1343 | 1344 | ### Using Luarocks packages 1345 | 1346 | [wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim) supports Luarocks packages. Instructions for how to set this up are available in the [README](https://github.com/wbthomason/packer.nvim/#luarocks-support) 1347 | 1348 | ## Miscellaneous 1349 | 1350 | ### vim.loop 1351 | 1352 | `vim.loop` is the module that exposes the LibUV API. Some resources: 1353 | 1354 | - [Official documentation for LibUV](https://docs.libuv.org/en/v1.x/) 1355 | - [Luv documentation](https://github.com/luvit/luv/blob/master/docs.md) 1356 | - [teukka.tech - Using LibUV in Neovim](https://teukka.tech/posts/2020-01-07-vimloop/) 1357 | 1358 | See also: 1359 | - [`:help vim.loop`](https://neovim.io/doc/user/lua.html#vim.loop) 1360 | 1361 | ### vim.lsp 1362 | 1363 | `vim.lsp` is the module that controls the built-in LSP client. The [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) repository contains default configurations for popular language servers. 1364 | 1365 | The behavior of the client can be configured using "lsp-handlers". For more information: 1366 | - [`:help lsp-handler`](https://neovim.io/doc/user/lsp.html#lsp-handler) 1367 | - [neovim/neovim#12655](https://github.com/neovim/neovim/pull/12655) 1368 | - [How to migrate from diagnostic-nvim](https://github.com/nvim-lua/diagnostic-nvim/issues/73#issue-737897078) 1369 | 1370 | You may also want to take a look at [plugins built around the LSP client](https://github.com/rockerBOO/awesome-neovim#lsp) 1371 | 1372 | See also: 1373 | - [`:help lsp`](https://neovim.io/doc/user/lsp.html#LSP) 1374 | 1375 | ### vim.treesitter 1376 | 1377 | `vim.treesitter` is the module that controls the integration of the [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) library in Neovim. If you want to know more about Tree-sitter, you may be interested in this [presentation (38:37)](https://www.youtube.com/watch?v=Jes3bD6P0To). 1378 | 1379 | The [nvim-treesitter](https://github.com/nvim-treesitter/) organisation hosts various plugins taking advantage of the library. 1380 | 1381 | See also: 1382 | - [`:help lua-treesitter`](https://neovim.io/doc/user/treesitter.html#lua-treesitter) 1383 | 1384 | ### Transpilers 1385 | 1386 | One advantage of using Lua is that you don't actually have to write Lua code! There is a multitude of transpilers available for the language. 1387 | 1388 | - [Moonscript](https://moonscript.org/) 1389 | 1390 | Probably one of the most well-known transpilers for Lua. Adds a lots of convenient features like classes, list comprehensions or function literals. The [svermeulen/nvim-moonmaker](https://github.com/svermeulen/nvim-moonmaker) plugin allows you to write Neovim plugins and configuration directly in Moonscript. 1391 | 1392 | - [Fennel](https://fennel-lang.org/) 1393 | 1394 | A lisp that compiles to Lua. You can write configuration and plugins for Neovim in Fennel with the [Olical/aniseed](https://github.com/Olical/aniseed) or the [Hotpot](https://github.com/rktjmp/hotpot.nvim) plugin. Additionally, the [Olical/conjure](https://github.com/Olical/conjure) plugin provides an interactive development environment that supports Fennel (among other languages). 1395 | 1396 | - [Teal](https://github.com/teal-language/tl) 1397 | 1398 | The name Teal comes from pronouncing TL (typed lua). This is exactly what it tries to do - add strong typing to lua while otherwise remaining close to standard lua syntax. The [nvim-teal-maker](https://github.com/svermeulen/nvim-teal-maker) plugin can be used to write Neovim plugins or configuration files directly in Teal 1399 | 1400 | Other interesting projects: 1401 | - [TypeScriptToLua/TypeScriptToLua](https://github.com/TypeScriptToLua/TypeScriptToLua) 1402 | - [Haxe](https://haxe.org/) 1403 | - [SwadicalRag/wasm2lua](https://github.com/SwadicalRag/wasm2lua) 1404 | - [hengestone/lua-languages](https://github.com/hengestone/lua-languages) 1405 | --------------------------------------------------------------------------------