├── .gitattributes ├── scripts ├── docgen.sh ├── sections_tags.awk └── to_vimdoc.sed ├── README.md └── doc └── nvim-lua-guide.txt /.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 | -------------------------------------------------------------------------------- /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*```$/ 369 | \ pumvisible() ? "\" : 370 | \ v:lua.check_back_space() ? "\" : 371 | \ completion#trigger_completion() 372 | 373 | " 작은 따옴표를 사용하고 괄호를 생략하여 루아 모듈에서 함수 호출: 374 | call v:lua.require'module'.foo() 375 | ``` 376 | 377 | 자세한 정보: 378 | - [`:help v:lua`](https://neovim.io/doc/user/eval.html#v:lua) 379 | - [`:help v:lua-call`](https://neovim.io/doc/user/lua.html#v:lua-call) 380 | 381 | #### 경고 382 | 383 | 이 변수는 함수들을 호출하는 데에만 쓰여질 수 있습니다. 다음 예시들에서는 항상 에러가 발생할 것입니다: 384 | 385 | ```vim 386 | " 함수들을 aliasing 하는 것은 작동하지 않습니다. 387 | let LuaPrint = v:lua.print 388 | 389 | " 딕셔너리에 접근하는 것은 작동하지 않습니다. 390 | echo v:lua.some_global_dict['key'] 391 | 392 | " 함수를 값으로 사용하는 것은 작동하지 않습니다. 393 | echo map([1, 2, 3], v:lua.global_callback) 394 | ``` 395 | 396 | ### 유용한 팁 397 | 398 | .vim 파일들 안에서 루아 신택스 하이라이팅을 보려면 `let g:vimsyn_enbed = 'l'`을 설정 파일에 적으면 됩니다. 399 | 더 자세한 정보는 [`:help g: vimsyn_embed`](https://neovim.io/doc/user/syntax.html#g:vimsyn_embed)를 보세요. 400 | 401 | ## 빔 이름공간 (The vim namespace) 402 | 403 | 루아로 빔의 API와 소통하기 위해 네오빔은 전역 변수 `vim`을 진입점으로 제공하고 있습니다. 이는 사용자들에게 확장된 "standard library" 함수들과 다양한 서브모듈들을 제공합니다. 404 | 405 | 알아둘만한 함수와 모듈들: 406 | 407 | - `vim.inspect`: 루아 오브젝트를 읽기 편한 문자열로 변환합니다. (table 값을 봐야할 때 유용합니다) 408 | - `vim.regex`: 루아에서 빔의 regex를 사용할 수 있습니다. 409 | - `vim.api`: API 함수들을 사용할 수 있는 모듈입니다. (원격 플러그인들이 사용하는 API와 동일합니다) 410 | - `vim.ui`: override 가능한 UI 함수들입니다. 플러그인에서 사용하면 좋습니다. 411 | - `vim.loop`: 네오빔의 event-loop의 기능을 사용할 수 있는 모듈입니다. (libUV를 사용하고 있습니다) 412 | - `vim.lsp`: 내장 LSP 클라이언트를 컨트롤할 수 있는 모듈입니다. 413 | - `vim.treesitter`: tree-sitter 라이브러리의 기능을 사용할 수 있는 모듈입니다. 414 | 415 | 이 목록이 전부는 아닙니다. `vim` 변수로 가능한 것들에 대해 더 알아보고 싶으시면 [`:help lua-stdlib`](https://neovim.io/doc/user/lua.html#lua-stdlib)와 [`:help lua-vim`](https://neovim.io/doc/user/lua.html#lua-vim)을 보시면 좋습니다. 또 `:lua print(vim.inspect(vim))`을 입력하시면 가능한 모든 모듈의 리스트를 보실 수 있습니다. API 함수들은 [`:help api-global`](https://neovim.io/doc/user/api.html#api-global)로 문서를 보실 수 있습니다. 416 | 417 | #### 유용한 팁 418 | 419 | 오브젝트를 확인하고 싶을 때마다 `print(vim.inspect(x))`를 적어야 하는 것은 조금 귀찮습니다. 설정 파일에 전역 wrapper 함수를 만들어 두는 것도 좋을 것 같습니다. (Neovim 0.7.0+ 부터는 이런 함수가 내장되어 있습니다. [`:help vim.pretty_print()`](https://neovim.io/doc/user/lua.html#vim.pretty_print())를 확인해 보세요.) 420 | 421 | ```lua 422 | function _G.put(...) 423 | local objects = {} 424 | for i = 1, select('#', ...) do 425 | local v = select(i, ...) 426 | table.insert(objects, vim.inspect(v)) 427 | end 428 | 429 | print(table.concat(objects, '\n')) 430 | return ... 431 | end 432 | ``` 433 | 434 | 이제 오브젝트의 내용물들을 쉽게 확인해볼 수 있습니다. 코드와 명령줄에서 다음과 같이 사용할 수 있습니다: 435 | 436 | ```lua 437 | put({1, 2, 3}) 438 | ``` 439 | 440 | ```vim 441 | :lua put(vim.loop) 442 | ``` 443 | 444 | 또는 `:lua` 명령어 앞에 `=`를 붙이는 것으로 루아 표현식을 보기 쉽게 프린트할 수도 있습니다. (Neovim 0.7+ 이상만): 445 | ```vim 446 | :lua =vim.loop 447 | ``` 448 | 449 | 어떨 때는 루아의 빌트인 함수들이 다른 언어들에 비해 좀 부족하게 느껴질 수 있습니다. (예를 들면 `os.clock()`같은 경우 milliseconds가 아닌 seconds만 리턴합니다.) 그럴 때는 Neovim의 stdlib(그리고 `vim.fn` - 후에 설명합니다)을 찾아보세요. 거기 원하는 것들이 있을지도 모릅니다. 450 | 451 | 452 | ## 루아에서 빔스크립트 사용하기 453 | 454 | ### vim.api.nvim_eval() 455 | 456 | 이 함수는 빔스크립트 표현식을 평가하고 값을 리턴합니다. 빔스크립트의 데이터 타입들은 자동적으로 루아 타입으로 변환됩니다. 457 | 458 | 빔스크립트에서의 `luaeval()` 함수와 동일합니다. 459 | 460 | ```lua 461 | -- 데이터 타입 변환 예 462 | print(vim.api.nvim_eval('1 + 1')) -- 2 463 | print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 } 464 | print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" } 465 | print(vim.api.nvim_eval('v:true')) -- true 466 | print(vim.api.nvim_eval('v:null')) -- nil 467 | ``` 468 | 469 | #### 경고 470 | 471 | `luaeval()`과 다르게 `vim.api.nvim_eval()`은 표현식에 데이터를 넘길 수 있는 변수 `_A`를 제공하지 않습니다. 472 | 473 | ### vim.api.nvim_exec() 474 | 475 | 이 함수는 빔스크립트 코드 조각을 평가합니다. 실행할 소스 코드 문자열과 코드의 결과를 리턴할지 정하는 boolean 값을 인자로 받습니다. (결과값을 변수에 할당하는 것도 가능합니다). 476 | 477 | ```lua 478 | local result = vim.api.nvim_exec( 479 | [[ 480 | let s:mytext = 'hello world' 481 | 482 | function! s:MyFunction(text) 483 | echo a:text 484 | endfunction 485 | 486 | call s:MyFunction(s:mytext) 487 | ]], 488 | true) 489 | 490 | print(result) -- 'hello world' 491 | ``` 492 | 493 | #### 경고 494 | 495 | Neovim 0.6.0 이전 버전의 경우 `nvim_exec`이 script-local 변수 (`s:`)를 지원하지 않습니다. 496 | 497 | ### vim.api.nvim_command() 498 | 499 | 이 함수는 ex 커맨드를 실행합니다. 인자로 실행할 명령어를 포함한 문자열을 받습니다. 500 | 501 | ```lua 502 | vim.api.nvim_command('new') 503 | vim.api.nvim_command('wincmd H') 504 | vim.api.nvim_command('set nonumber') 505 | vim.api.nvim_command('%s/foo/bar/g') 506 | ``` 507 | 508 | ### vim.cmd() 509 | 510 | `vim.api.nvim_exec()`의 alias입니다. 커맨드 인자만 필요로 합니다. `output`은 항상 `false`로 지정되어 있습니다. 511 | 512 | ```lua 513 | vim.cmd('buffers') 514 | vim.cmd([[ 515 | let g:multiline_list = [ 516 | \ 1, 517 | \ 2, 518 | \ 3, 519 | \ ] 520 | 521 | echo g:multiline_list 522 | ]]) 523 | ``` 524 | 525 | #### 유용한 팁 526 | 527 | 이 함수들에는 문자열을 넘겨야 함으로, 종종 다음과 같이 백슬래시를 같이 사용해야 하는 경우가 있습니다: 528 | 529 | ```lua 530 | vim.cmd('%s/\\Vfoo/bar/g') 531 | ``` 532 | 533 | 하지만 이중 중괄호를 사용한 문자열은 특수 문자 앞에 백슬래시를 넣지 않아도 되기 때문에 조금 더 쉬워집니다: 534 | 535 | ```lua 536 | vim.cmd([[%s/\Vfoo/bar/g]]) 537 | ``` 538 | 539 | ### vim.api.nvim_replace_termcodes() 540 | 541 | 이 API 함수는 터미널 코드와 빔 키코드를 escape 할 수 있게 해줍니다. 542 | 543 | 빔스크립트로 쓴 다음과 같은 키 매핑이 있습니다: 544 | 545 | ```vim 546 | inoremap pumvisible() ? "\" : "\" 547 | ``` 548 | 549 | 같은 기능을 하는 루아 함수를 만들어봅시다. 다음과 같이 작성하고 싶을 수 있습니다: 550 | 551 | ```lua 552 | function _G.smart_tab() 553 | return vim.fn.pumvisible() == 1 and [[\]] or [[\]] 554 | end 555 | 556 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 557 | ``` 558 | 559 | 매핑이 문자 그대로 `\`과 `\`를 입력하는지 알아내기만 하면 됩니다. 560 | 561 | 키코드를 escape 할 수 있는 것은 빔스크립트의 기능입니다. 많은 프로그래밍 언어에서 흔히 볼 수 있는 `\r`, `\42`, `\x10` 같은 보통의 escape 시퀀스들를 제외하고, 빔스크립트의 `expr-quotes` (큰 따옴표로 둘러쌓인 문자열)은 빔 키코드들을 사람이 읽을 수 있게 표기할 수 있습니다. 562 | 563 | 루아는 이와 같은 기능을 빌트인으로 가지고 있지 않습니다. 하지만 Neovim에는 같은 기능을 할 수 있는 API 함수가 있습니다: `nvim_replace_termcodes()` 564 | 565 | ```lua 566 | print(vim.api.nvim_replace_termcodes('', true, true, true)) 567 | ``` 568 | 569 | 조금 장황합니다. 다시 사용하기 쉽게 한 번 더 감싸면 편할 것 같습니다: 570 | 571 | ```lua 572 | -- 이 함수는 `termcodes`의 `t`로 부르기로 했습니다. 573 | -- 저와 똑같이 이름 지을 필요는 없습니다. 저는 간결한 것이 편했습니다. 574 | local function t(str) 575 | -- 필요한대로 boolean 인자들을 조정합니다. 576 | return vim.api.nvim_replace_termcodes(str, true, true, true) 577 | end 578 | 579 | print(t'') 580 | ``` 581 | 582 | 이전의 예시로 다시 돌아와보면, 이제 우리가 원하는대로 작동해야 할 것입니다: 583 | 584 | ```lua 585 | local function t(str) 586 | return vim.api.nvim_replace_termcodes(str, true, true, true) 587 | end 588 | 589 | function _G.smart_tab() 590 | return vim.fn.pumvisible() == 1 and t'' or t'' 591 | end 592 | 593 | vim.api.nvim_set_keymap('i', '', 'v:lua.smart_tab()', {expr = true, noremap = true}) 594 | ``` 595 | 596 | `vim.keymap.set()`를 사용할 때 opts의 expr이 true일 경우(default) 자동적으로 키코드들을 변환해주기 때문에 위의 과정들이 필요 없습니다: 597 | 598 | ```lua 599 | vim.keymap.set('i', '', function() 600 | return vim.fn.pumvisible() == 1 and '' or '' 601 | end, {expr = true}) 602 | ``` 603 | 604 | 자세한 정보: 605 | 606 | - [`:help keycodes`](https://neovim.io/doc/user/intro.html#keycodes) 607 | - [`:help expr-quote`](https://neovim.io/doc/user/eval.html#expr-quote) 608 | - [`:help nvim_replace_termcodes()`](https://neovim.io/doc/user/api.html#nvim_replace_termcodes()) 609 | 610 | ## 빔 옵션 관리하기 611 | 612 | ### api 함수들 사용하기 613 | 614 | Neovim은 옵션을 지정하거나 현재 지정된 값을 가져오는 API 함수들을 제공하고 있습니다: 615 | 616 | - Global options: 617 | - [`vim.api.nvim_set_option()`](https://neovim.io/doc/user/api.html#nvim_set_option()) 618 | - [`vim.api.nvim_get_option()`](https://neovim.io/doc/user/api.html#nvim_get_option()) 619 | - Buffer-local options: 620 | - [`vim.api.nvim_buf_set_option()`](https://neovim.io/doc/user/api.html#nvim_buf_set_option()) 621 | - [`vim.api.nvim_buf_get_option()`](https://neovim.io/doc/user/api.html#nvim_buf_get_option()) 622 | - Window-local options: 623 | - [`vim.api.nvim_win_set_option()`](https://neovim.io/doc/user/api.html#nvim_win_set_option()) 624 | - [`vim.api.nvim_win_get_option()`](https://neovim.io/doc/user/api.html#nvim_win_get_option()) 625 | 626 | set/get할 옵션의 이름을 포함한 문자열과 set하고 싶은 값을 인자로 받습니다. 627 | 628 | `(no)number`와 같은 boolean 옵션들은 `true`나 `false`를 받습니다: 629 | 630 | ```lua 631 | vim.api.nvim_set_option('smarttab', false) 632 | print(vim.api.nvim_get_option('smarttab')) -- false 633 | ``` 634 | 635 | 당연히 문자열 옵션들은 문자열을 인자로 받습니다: 636 | 637 | ```lua 638 | vim.api.nvim_set_option('selection', 'exclusive') 639 | print(vim.api.nvim_get_option('selection')) -- 'exclusive' 640 | ``` 641 | 642 | 숫자 옵션들은 숫자를 받습니다: 643 | 644 | ```lua 645 | vim.api.nvim_set_option('updatetime', 3000) 646 | print(vim.api.nvim_get_option('updatetime')) -- 3000 647 | ``` 648 | 649 | 버퍼-로컬, 윈도우-로컬 옵션들은 버퍼 넘버나 윈도우 넘버를 옵션으로 받습니다. (`0`를 사용하면 현재 buffer/window로 set/get할 수 있습니다): 650 | 651 | ```lua 652 | vim.api.nvim_win_set_option(0, 'number', true) 653 | vim.api.nvim_buf_set_option(10, 'shiftwidth', 4) 654 | print(vim.api.nvim_win_get_option(0, 'number')) -- true 655 | print(vim.api.nvim_buf_get_option(10, 'shiftwidth')) -- 4 656 | ``` 657 | 658 | ### 메타-접근자(meta-accessors)들 사용하기 659 | 660 | 몇몇 메타-접근자는 옵션 세팅을 좀 더 "관용적"으로 할 수 있게 도와줍니다. 이것들은 본질적으로 위의 API 함수들을 감싸둔 것과 같으며 옵션들을 변수처럼 조작할 수 있게 합니다. 661 | 662 | - [`vim.o`](https://neovim.io/doc/user/lua.html#vim.o): `:let &{option-name}`과 같습니다. 663 | - [`vim.go`](https://neovim.io/doc/user/lua.html#vim.go): `:let &g:{option-name}`과 같습니다. 664 | - [`vim.bo`](https://neovim.io/doc/user/lua.html#vim.bo): 버퍼-로컬 `:let &l:{option-name}`과 같습니다. 665 | - [`vim.wo`](https://neovim.io/doc/user/lua.html#vim.wo): 윈도우-로컬 `:let &l:{option-name}`과 같습니다. 666 | 667 | ```lua 668 | vim.o.smarttab = false -- let &smarttab = v:false 669 | print(vim.o.smarttab) -- false 670 | vim.o.isfname = vim.o.isfname .. ',@-@' -- on Linux: let &isfname = &isfname .. ',@-@' 671 | print(vim.o.isfname) -- '@,48-57,/,.,-,_,+,,,#,$,%,~,=,@-@' 672 | 673 | vim.bo.shiftwidth = 4 674 | print(vim.bo.shiftwidth) -- 4 675 | ``` 676 | 677 | 버퍼-로컬과 윈도우-로컬 옵션의 경우 숫자를 지정할 수 있습니다. 숫자가 주어지지 않으면 현재 버퍼/윈도우가 사용됩니다: 678 | 679 | ```lua 680 | vim.bo[4].expandtab = true -- same as vim.api.nvim_buf_set_option(4, 'expandtab', true) 681 | vim.wo.number = true -- same as vim.api.nvim_win_set_option(0, 'number', true) 682 | ``` 683 | 684 | 이들 wrapper들 중에는 좀 더 정교한 조작을 할 수 있는 `vim.opt*` 변수들이 있습니다. 루아에서 옵션을 세팅하기 조금 더 편리한 메카니즘을 제공합니다. 이는 `init.vim`에서 작성하던 방식과 유사할 수 있습니다. 685 | 686 | - `vim.opt`: behaves like `:set` 687 | - `vim.opt_global`: behaves like `:setglobal` 688 | - `vim.opt_local`: behaves like `:setlocal` 689 | 690 | ```lua 691 | vim.opt.smarttab = false 692 | print(vim.opt.smarttab:get()) -- false 693 | ``` 694 | 695 | 몇몇 옵션들은 루아 테이블을 사용해 세팅됩니다: 696 | 697 | ```lua 698 | vim.opt.completeopt = {'menuone', 'noselect'} 699 | print(vim.inspect(vim.opt.completeopt:get())) -- { "menuone", "noselect" } 700 | ``` 701 | 702 | 리스트, 맵, 셋과 비슷한 옵션들을 위한 wrapper들도 제공됩니다. 빔스크립트의 `:set+=`, `:set^=`, `:set-=`와 비슷하게 동작하는 메소드와 메타메소드들이 있습니다. 703 | 704 | ```lua 705 | vim.opt.shortmess:append({ I = true }) 706 | -- alternative form: 707 | vim.opt.shortmess = vim.opt.shortmess + { I = true } 708 | 709 | vim.opt.whichwrap:remove({ 'b', 's' }) 710 | -- alternative form: 711 | vim.opt.whichwrap = vim.opt.whichwrap - { 'b', 's' } 712 | ``` 713 | 714 | 더 자세한 정보는 [`:help vim.opt`](https://neovim.io/doc/user/lua.html#vim.opt)를 확인해보세요. 715 | 716 | 자세한 정보: 717 | - [`:help lua-vim-options`](https://neovim.io/doc/user/lua.html#lua-vim-options) 718 | 719 | ## 빔의 내부 변수들을 관리하기 720 | 721 | ### api 함수들 사용하기 722 | 723 | 옵션들과 같이, 내부 변수들도 다음과 같은 API 함수들이 있습니다: 724 | 725 | - Global variables (`g:`): 726 | - [`vim.api.nvim_set_var()`](https://neovim.io/doc/user/api.html#nvim_set_var()) 727 | - [`vim.api.nvim_get_var()`](https://neovim.io/doc/user/api.html#nvim_get_var()) 728 | - [`vim.api.nvim_del_var()`](https://neovim.io/doc/user/api.html#nvim_del_var()) 729 | - Buffer variables (`b:`): 730 | - [`vim.api.nvim_buf_set_var()`](https://neovim.io/doc/user/api.html#nvim_buf_set_var()) 731 | - [`vim.api.nvim_buf_get_var()`](https://neovim.io/doc/user/api.html#nvim_buf_get_var()) 732 | - [`vim.api.nvim_buf_del_var()`](https://neovim.io/doc/user/api.html#nvim_buf_del_var()) 733 | - Window variables (`w:`): 734 | - [`vim.api.nvim_win_set_var()`](https://neovim.io/doc/user/api.html#nvim_win_set_var()) 735 | - [`vim.api.nvim_win_get_var()`](https://neovim.io/doc/user/api.html#nvim_win_get_var()) 736 | - [`vim.api.nvim_win_del_var()`](https://neovim.io/doc/user/api.html#nvim_win_del_var()) 737 | - Tabpage variables (`t:`): 738 | - [`vim.api.nvim_tabpage_set_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_set_var()) 739 | - [`vim.api.nvim_tabpage_get_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_get_var()) 740 | - [`vim.api.nvim_tabpage_del_var()`](https://neovim.io/doc/user/api.html#nvim_tabpage_del_var()) 741 | - Predefined Vim variables (`v:`): 742 | - [`vim.api.nvim_set_vvar()`](https://neovim.io/doc/user/api.html#nvim_set_vvar()) 743 | - [`vim.api.nvim_get_vvar()`](https://neovim.io/doc/user/api.html#nvim_get_vvar()) 744 | 745 | 미리 정의된 빔 변수를 제외한 다른 변수는 삭제도 가능합니다(빔스크립트에서는 `:unlet` 커맨드와 같습니다). 로컬 변수 (`l:`), 스크립트 변수 (`s:`), 746 | 함수 인자 (`a:`)는 조작할 수 없습니다. 이것들은 빔스크립트의 문맥에서만 의미가 있고, 루아는 다른 스코핑 규칙을 가지고 있습니다. 747 | 748 | 이런 변수들과 친숙하지 않다면 [`:help internal-variables`](https://neovim.io/doc/user/eval.html#internal-variables)를 보시면 좀 더 자세한 설명을 읽을 수 있습니다. 749 | 750 | 이 함수들은 set/get/delete 할 변수명을 포함한 문자열, 할당할 값을 인자로 받습니다. 751 | 752 | ```lua 753 | vim.api.nvim_set_var('some_global_variable', { key1 = 'value', key2 = 300 }) 754 | print(vim.inspect(vim.api.nvim_get_var('some_global_variable'))) -- { key1 = "value", key2 = 300 } 755 | vim.api.nvim_del_var('some_global_variable') 756 | ``` 757 | 758 | 버퍼 로컬 변수들, 창이나 탭 로컬 변수들은 숫자를 받습니다 (`0`을 사용하면 현재 buffer/window/tabpage에 set/get/delete 될 것입니다): 759 | 760 | ```lua 761 | vim.api.nvim_win_set_var(0, 'some_window_variable', 2500) 762 | vim.api.nvim_tab_set_var(3, 'some_tabpage_variable', 'hello world') 763 | print(vim.api.nvim_win_get_var(0, 'some_window_variable')) -- 2500 764 | print(vim.api.nvim_buf_get_var(3, 'some_tabpage_variable')) -- 'hello world' 765 | vim.api.nvim_win_del_var(0, 'some_window_variable') 766 | vim.api.nvim_buf_del_var(3, 'some_tabpage_variable') 767 | ``` 768 | 769 | ### 메타-접근자 사용하기 770 | 771 | 내부 변수들은 다음과 같은 meta-accessor들로 좀 더 직관적으로 조작할 수 있습니다. 772 | 773 | - [`vim.g`](https://neovim.io/doc/user/lua.html#vim.g): global variables 774 | - [`vim.b`](https://neovim.io/doc/user/lua.html#vim.b): buffer variables 775 | - [`vim.w`](https://neovim.io/doc/user/lua.html#vim.w): window variables 776 | - [`vim.t`](https://neovim.io/doc/user/lua.html#vim.t): tabpage variables 777 | - [`vim.v`](https://neovim.io/doc/user/lua.html#vim.v): predefined Vim variables 778 | - [`vim.env`](https://neovim.io/doc/user/lua.html#vim.env): environment variables 779 | 780 | ```lua 781 | vim.g.some_global_variable = { 782 | key1 = 'value', 783 | key2 = 300 784 | } 785 | 786 | print(vim.inspect(vim.g.some_global_variable)) -- { key1 = "value", key2 = 300 } 787 | 788 | -- target a specific buffer/window/tabpage (Neovim 0.6+) 789 | -- 특정 buffer/window/tabpage를 지정하기 (Neovim 0.6+) 790 | vim.b[2].myvar = 1 791 | ``` 792 | 793 | 몇몇 변수 이름들은 루아에서 식별자로 사용될 수 없는 문자들을 포함하고 있을수도 있습니다. 그래도 다음 문법을 사용하면 조작할 수 있습니다:`vim.g['my#variable']`. 794 | 795 | 다음 변수들을 삭제하기 위해서는 단순히 `nil`을 할당하면 됩니다: 796 | 797 | ```lua 798 | vim.g.some_global_variable = nil 799 | ``` 800 | 801 | 자세한 정보: 802 | - [`:help lua-vim-variables`](https://neovim.io/doc/user/lua.html#lua-vim-variables) 803 | 804 | #### 경고 805 | 806 | 이 변수들에 저장된 딕셔너리의 키들은 add/update/delete 할 수 없습니다. 예를 들어 다음 빔스크립트 snippet 코드는 예상한대로 작동하지 않습니다: 807 | 808 | ```vim 809 | let g:variable = {} 810 | lua vim.g.variable.key = 'a' 811 | echo g:variable 812 | " {} 813 | ``` 814 | 815 | 하지만 임시 변수를 사용하여 돌아갈 수 있습니다. 816 | 817 | ```vim 818 | let g:variable = {} 819 | lua << EOF 820 | local tmp = vim.g.variable 821 | tmp.key = 'a' 822 | vim.g.variable = tmp 823 | EOF 824 | echo g:variable 825 | " {'key': 'a'} 826 | ``` 827 | 828 | 알려진 이슈입니다: 829 | 830 | - [Issue #12544](https://github.com/neovim/neovim/issues/12544) 831 | 832 | ## 빔스크립트 함수 호출하기 833 | 834 | ### vim.fn.{function}() 835 | 836 | `vim.fn`는 빔스크립트 함수를 호출하는데 사용됩니다. 데이터 타입들은 루아, 빔스크립트 양측으로 자동 변환됩니다. 837 | 838 | ```lua 839 | print(vim.fn.printf('Hello from %s', 'Lua')) 840 | 841 | local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' }) 842 | print(vim.inspect(reversed_list)) -- { "c", "b", "a" } 843 | 844 | local function print_stdout(chan_id, data, name) 845 | print(data[1]) 846 | end 847 | 848 | vim.fn.jobstart('ls', { on_stdout = print_stdout }) 849 | ``` 850 | 851 | 해시(`#`)는 루아에서 식별자로 사용할 수 없는 문자이기 때문에 autoload 함수들은 다음 문법으로 불러야 합니다. 852 | 853 | ```lua 854 | vim.fn['my#autoload#function']() 855 | ``` 856 | 857 | `vim.fn`과 `vim.call`은 기능상으로 동일하지만 좀 더 루아같은 문법을 사용할 수 있습니다. 858 | 859 | 860 | Vim/Lua 오브젝트 변환이 자동적이란 점에 있어서 `vim.api.nvim_call_function`과는 구별됩니다: 861 | `vim.api.nvim_call_function`은 부동 소수점 숫자 테이블을 리턴하며 루아의 클로저를 받지 않습니다. 반면 `vim.fn`는 이러한 타입들을 투명하게 다룹니다. 862 | 863 | 자세한 정보: 864 | - [`:help vim.fn`](https://neovim.io/doc/user/lua.html#vim.fn) 865 | 866 | #### 유용한 팁 867 | 868 | 네오빔에는 플러그인을 위해 유용하고 강력한 빌트인 함수 라이브러리가 있습니다. [`:help vim-function`](https://neovim.io/doc/user/eval.html#vim-function)를 보면 알파벳 순의 함수들을 확인할 수 있고 [`:help function-list`](https://neovim.io/doc/user/usr_41.html#function-list)를 보면 주제별로 구분된 함수 리스트를 확인할 수 있습니다. 869 | 870 | 네오빔 API 함수들은 `vim.api.{..}`를 통해 직접 사용 가능합니다. [:help api](https://neovim.io/doc/user/api.html#API)로 확인하실 수 있습니다. 871 | 872 | #### 경고 873 | 874 | boolean을 반환해야 하는 일부 빔 함수들은 `1` 또는 `0` 을 반환합니다. 빔스크립트에서 `1`은 참(truthy), `0`은 거짓(falsy)이기 때문에 문제되지 않습니다. 다음과 같이 구성할 수 있습니다: 875 | 876 | ```vim 877 | if has('nvim') 878 | " do something... 879 | endif 880 | ``` 881 | 882 | 하지만 루아에서는 `false`와 `nil`을 제외한 모든 타입이 `true`입니다. 따라서 명시적으로 `1`과 `0`을 체크해줘야 합니다. 883 | 884 | ```lua 885 | if vim.fn.has('nvim') == 1 then 886 | -- do something... 887 | end 888 | ``` 889 | 890 | ## 키 매핑 정의하기 891 | 892 | ### API 함수들 893 | 894 | 네오빔은 키 매핑을 set, get, delete 하기 위한 API 함수들을 제공합니다: 895 | 896 | - Global mappings: 897 | - [`vim.api.nvim_set_keymap()`](https://neovim.io/doc/user/api.html#nvim_set_keymap()) 898 | - [`vim.api.nvim_get_keymap()`](https://neovim.io/doc/user/api.html#nvim_get_keymap()) 899 | - [`vim.api.nvim_del_keymap()`](https://neovim.io/doc/user/api.html#nvim_del_keymap()) 900 | - Buffer-local mappings: 901 | - [`vim.api.nvim_buf_set_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_set_keymap()) 902 | - [`vim.api.nvim_buf_get_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_get_keymap()) 903 | - [`vim.api.nvim_buf_del_keymap()`](https://neovim.io/doc/user/api.html#nvim_buf_del_keymap()) 904 | 905 | `vim.api.nvim_set_keymap()`과 `vim.api.nvim_buf_set_keymap()`부터 시작합시다. 906 | 907 | 함수에 전달된 첫 번째 인수는 매핑이 적용될 모드의 이름을 포함하는 문자열입니다. 908 | 909 | | String value | Help page | Affected modes | Vimscript equivalent | 910 | | ---------------------- | ------------- | ---------------------------------------- | -------------------- | 911 | | `''` (an empty string) | `mapmode-nvo` | Normal, Visual, Select, Operator-pending | `:map` | 912 | | `'n'` | `mapmode-n` | Normal | `:nmap` | 913 | | `'v'` | `mapmode-v` | Visual and Select | `:vmap` | 914 | | `'s'` | `mapmode-s` | Select | `:smap` | 915 | | `'x'` | `mapmode-x` | Visual | `:xmap` | 916 | | `'o'` | `mapmode-o` | Operator-pending | `:omap` | 917 | | `'!'` | `mapmode-ic` | Insert and Command-line | `:map!` | 918 | | `'i'` | `mapmode-i` | Insert | `:imap` | 919 | | `'l'` | `mapmode-l` | Insert, Command-line, Lang-Arg | `:lmap` | 920 | | `'c'` | `mapmode-c` | Command-line | `:cmap` | 921 | | `'t'` | `mapmode-t` | Terminal | `:tmap` | 922 | 923 | 두 번째 인수는 왼쪽편의 매핑(매핑에 정의된 명령을 트리거할 키나 키조합)을 포함한 문자열을 받습니다. 빈 문자열은 키를 비활성화 하는 ``과 동일합니다. 924 | 925 | 셋째 인수는 오른편의 매핑(실행할 명령)을 포함한 문자열입니다. 926 | 927 | 마지막 인수는 boolean 옵션들을 포함한 테이블입니다. 상세한 옵션은 [`:help :map-arguments`](https://neovim.io/doc/user/map.html#:map-arguments)에 정의되어 있습니다. (`noremap` 포함 `buffer` 제외). Neovim 0.7.0 버전부터는 매핑을 실행할 때 오른편 매핑 대신 `callback` 옵션으로 루아 함수를 부를 수도 있습니다. 928 | 929 | 버퍼-로컬 매핑들은 버퍼 숫자를 첫 번째 인수로 받습니다 (`0`은 현재 버퍼로 지정됩니다). 930 | 931 | ```lua 932 | vim.api.nvim_set_keymap('n', '', ':set hlsearch!', { noremap = true, silent = true }) 933 | -- :nnoremap :set hlsearch 934 | vim.api.nvim_set_keymap('n', 'tegf', [[lua require('telescope.builtin').git_files()]], { noremap = true, silent = true }) 935 | -- :nnoremap tegf lua require('telescope.builtin').git_files() 936 | 937 | vim.api.nvim_buf_set_keymap(0, '', 'cc', 'line(".") == 1 ? "cc" : "ggcc"', { noremap = true, expr = true }) 938 | -- :noremap cc line('.') == 1 ? 'cc' : 'ggcc' 939 | 940 | vim.api.nvim_set_keymap('n', 'ex', '', { 941 | noremap = true, 942 | callback = function() 943 | print('My example') 944 | end, 945 | -- 루아 함수에는 유용한 문자열 표현이 없기 때문에, "desc" 옵션을 통해 매핑을 문서화 할 수 있습니다. 946 | desc = 'Prints "My example" in the message area', 947 | }) 948 | ``` 949 | 950 | `vim.api.nvim_get_keymap()`은 모드의 짧은 이름 문자열(위의 테이블 참고)을 인수로 받고 해당 모드에 포함된 매핑들을 테이블로 반환합니다. 951 | 952 | 953 | ```lua 954 | print(vim.inspect(vim.api.nvim_get_keymap('n'))) 955 | -- :verbose nmap 956 | ``` 957 | 958 | `vim.api.nvim_buf_get_keymap()`는 추가로 버퍼 숫자를 첫 번째 인수에 받습니다. (`0`은 현재 버퍼의 모든 매핑을 불러옵니다) 959 | 960 | 961 | ```lua 962 | print(vim.inspect(vim.api.nvim_buf_get_keymap(0, 'i'))) 963 | -- :verbose imap 964 | ``` 965 | 966 | `vim.api.nvim_del_keymap()`는 모드와 지우고 싶은 매핑(키)를 인수로 받습니다. 967 | 968 | ```lua 969 | vim.api.nvim_del_keymap('n', '') 970 | -- :nunmap 971 | ``` 972 | 973 | 또 `vim.api.nvim_buf_del_keymap()`는 첫 번째 인수로 버퍼 숫자를 받고 `0`은 현재 버퍼를 의미합니다. 974 | 975 | ```lua 976 | vim.api.nvim_buf_del_keymap(0, 'i', '') 977 | -- :iunmap 978 | ``` 979 | 980 | ### vim.keymap 981 | 982 | :주의: 이 섹션에서 이야기되는 함수들은 Neovim 0.7.0+ 버전부터 사용할 수 있습니다. 983 | 984 | 네오빔은 다음 두 함수들을 매핑을 set/del 하는 작업에 제공합니다. 985 | - [`vim.keymap.set()`](https://neovim.io/doc/user/lua.html#vim.keymap.set()) 986 | - [`vim.keymap.del()`](https://neovim.io/doc/user/lua.html#vim.keymap.del()) 987 | 988 | 이것들은 위 API 함수들과 비슷하지만 약간의 구문 설탕(syntactic sugar)가 추가되어 있습니다. 989 | 990 | `vim.keymap.set()`는 문자열을 첫번째 인수로 받습니다. 여러 모드를 한 번에 정의하기 위해서는 문자열 테이블(List-like)을 사용합니다: 991 | 992 | ```lua 993 | vim.keymap.set('n', 'ex1', 'lua vim.notify("Example 1")') 994 | vim.keymap.set({'n', 'c'}, 'ex2', 'lua vim.notify("Example 2")') 995 | ``` 996 | 997 | 두 번째 인수로는 매핑할 키(lhs)를 받습니다. 998 | 999 | 세 번째 인수는 실행할 명령(rhs)으로 문자열 혹은 루아 함수를 받습니다. 1000 | 1001 | ```lua 1002 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"') 1003 | vim.keymap.set('n', 'ex2', function() print("Example 2") end) 1004 | vim.keymap.set('n', 'pl1', require('plugin').plugin_action) 1005 | -- 모듈을 불러올 때 드는 시작 비용을 피하기 위해 require를 function으로 감싸 매핑을 호출할 때 실행되도록 할 수 있습니다: 1006 | vim.keymap.set('n', 'pl2', function() require('plugin').plugin_action() end) 1007 | ``` 1008 | 1009 | 네 번째 (optional) 인수는 `vim.api.nvim_set_keymap()`에 전해지는 옵션 테이블에 대응되며, 몇 가지 추가된 것([`:help vim.keymap.set()`](https://neovim.io/doc/user/lua.html#vim.keymap.set())에 전체 리스트)들이 있습니다. 1010 | 1011 | ```lua 1012 | vim.keymap.set('n', 'ex1', 'echomsg "Example 1"', {buffer = true}) 1013 | vim.keymap.set('n', 'ex2', function() print('Example 2') end, {desc = 'Prints "Example 2" to the message area'}) 1014 | ``` 1015 | 1016 | 루아 함수로 키맵을 정의하는 것은 문자열을 사용하는 것과 다릅니다. `:nmap ex1` 과 같은 키맵에 대한 정보를 보는 보통의 방법은 유용한 정보(문자열 자체)를 보여주지 않습니다. `Lua function`만 보여줍니다. 키맵을 설명하는 `desc` 키를 추가하는 것이 권장됩니다. 특히 플러그인 매핑들은 사용자들이 키맵을 좀 더 쉽게 이해할 수 있게 돕기 때문에 중요합니다. 1017 | 1018 | 이 API에는 기존 빔 키맵의 역사적인 단점을 개선하는 흥미로운 기능이 있습니다: 1019 | - 매핑은 `rhs`가 `` 매핑일 때를 제외하고는 `noremap`이 기본입니다. 이 말은 매핑이 재귀적이어야 하는지 아닌지를 생각할 일이 잘 없다는 뜻입니다: 1020 | ```lua 1021 | vim.keymap.set('n', 'test1', 'echo "test"') 1022 | -- :nnoremap test echo "test" 1023 | 1024 | -- 이 매핑이 재귀적으로 적용되길 바란다면 "remap" 옵션을 "true"로 적으면 됩니다. 1025 | vim.keymap.set('n', '>', ']', {remap = true}) 1026 | -- :nmap > ] 1027 | 1028 | -- 매핑들은 재귀적이지 않으면 작동하지 않습니다. vim.keymap.set()은 이를 자동으로 처리합니다. 1029 | vim.keymap.set('n', 'plug', '(plugin)') 1030 | -- :nmap plug (plugin) 1031 | ``` 1032 | - `expr` 매핑에서는, `nvim_replace_termcodes()`는 루아 함수에서 반환된 문자열에 자동으로 적용됩니다: 1033 | ```lua 1034 | vim.keymap.set('i', '', function() 1035 | return vim.fn.pumvisible == 1 and '' or '' 1036 | end, {expr = true}) 1037 | ``` 1038 | 1039 | 자세한 정보: 1040 | - [`:help recursive_mapping`](https://neovim.io/doc/user/map.html#recursive_mapping) 1041 | 1042 | `vim.keymap.del()` 같은 방식으로 작동하지만 매핑을 삭제합니다: 1043 | 1044 | ```lua 1045 | vim.keymap.del('n', 'ex1') 1046 | vim.keymap.del({'n', 'c'}, 'ex2', {buffer = true}) 1047 | ``` 1048 | 1049 | ## 사용자 커맨드 정의하기 1050 | 1051 | :주의: 이 섹션에서 이야기되는 API 함수들은 Neovim 0.7.0+ 에서만 사용할 수 있습니다. 1052 | 1053 | Neovim은 사용자 정의 커맨드를 위한 API 함수들을 제공합니다: 1054 | 1055 | - Global user commands: 1056 | - [`vim.api.nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command()) 1057 | - [`vim.api.nvim_del_user_command()`](https://neovim.io/doc/user/api.html#nvim_del_user_command()) 1058 | - Buffer-local user commands: 1059 | - [`vim.api.nvim_buf_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_buf_create_user_command()) 1060 | - [`vim.api.nvim_buf_del_user_command()`](https://neovim.io/doc/user/api.html#nvim_buf_del_user_command()) 1061 | 1062 | `vim.api.nvim_create_user_command()`부터 시작해봅시다. 1063 | 1064 | 첫 번째 인수는 커맨드의 (대문자로 시작하는) 이름입니다. 1065 | 1066 | 두 번째 인수는 커맨드를 불러왔을 때 실행할 코드입니다. 이는 둘 중 하나입니다: 1067 | 1068 | 문자열(일 경우 빔스크립트로 실행). `:command`처럼 ``, `` 등과 같은 escape 시퀀스를 사용할 수 있습니다. 1069 | 1070 | ```lua 1071 | vim.api.nvim_create_user_command('Upper', 'echo toupper()', { nargs = 1 }) 1072 | -- :command! -nargs=1 Upper echo toupper() 1073 | 1074 | vim.cmd('Upper hello world') -- prints "HELLO WORLD" 1075 | ``` 1076 | 1077 | 혹은 루아 함수. 루아 함수는 보통 escape 시퀀스에서 제공되는 데이터를 포함한 딕셔너리 테이블을 받습니다. ([`:help nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command())에서 가능한 키 목록을 볼 수 있습니다) 1078 | 1079 | ```lua 1080 | vim.api.nvim_create_user_command( 1081 | 'Upper', 1082 | function(opts) 1083 | print(string.upper(opts.args)) 1084 | end, 1085 | { nargs = 1 } 1086 | ) 1087 | ``` 1088 | 1089 | 세 번째 인수는 커맨드 속성을 테이블로 받습니다([`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes)). 1090 | 이미 `vim.api.nvim_buf_create_user_command()`로 버퍼-로컬 사용자 커맨드를 정의할 수 있기 때문에 `-buffer`는 유효한 속성이 아닙니다. 1091 | 1092 | 두 개의 추가적으로 가능한 속성들: 1093 | - `desc`는 루아 콜백으로 정의된 명령에서 `:command {cmd}`를 실행할 때 표시될 내용을 제어합니다. 키맵과 비슷한 이유로 `desc` 키를 추가하는 것이 권장됩니다. 1094 | 1095 | - `force`는 `:command!`와 같습니다. 그리고 같은 이름의 커맨드가 이미 있다면 교체합니다. 대응되는 빔스크립트와 다르게 기본적으로 true입니다. 1096 | 1097 | `-comlpete` 속성은 [`:help :command-complete`](https://neovim.io/doc/user/map.html#:command-complete)에 있는 속성 리스트에 추가로 루아 함수를 받습니다. 1098 | 1099 | ```lua 1100 | vim.api.nvim_create_user_command('Upper', function() end, { 1101 | nargs = 1, 1102 | complete = function(ArgLead, CmdLine, CursorPos) 1103 | -- 완성 후보들을 리스트 테이브로 반환합니다. 1104 | return { 'foo', 'bar', 'baz' } 1105 | end, 1106 | }) 1107 | ``` 1108 | 1109 | 버퍼 로컬 유저 커맨드는 버퍼 숫자를 첫 번째 인수로 받습니다. 이는 `-buffer`가 현재 버퍼에만 커맨드를 정의할 수 있는 것에 비해 장점이 있습니다. 1110 | 1111 | ```lua 1112 | vim.api.nvim_buf_create_user_command(4, 'Upper', function() end, {}) 1113 | ``` 1114 | 1115 | `vim.api.nvim_del_user_command()`는 커맨드 이름을 받습니다. 1116 | 1117 | ```lua 1118 | vim.api.nvim_del_user_command('Upper') 1119 | -- :delcommand Upper 1120 | ``` 1121 | 1122 | `vim.api.nvim_buf_del_user_command()`는 버퍼 숫자를 첫 번째 인수로 받고, `0`은 현 버퍼를 의미합니다. 1123 | 1124 | ```lua 1125 | vim.api.nvim_buf_del_user_command(4, 'Upper') 1126 | ``` 1127 | 1128 | 자세한 정보: 1129 | - [`:help nvim_create_user_command()`](https://neovim.io/doc/user/api.html#nvim_create_user_command()) 1130 | - [`:help 40.2`](https://neovim.io/doc/user/usr_40.html#40.2) 1131 | - [`:help command-attributes`](https://neovim.io/doc/user/map.html#command-attributes) 1132 | 1133 | ### 경고 1134 | 1135 | `-complete=custom` 속성은 자동완성 후보들을 자동적으로 필터링 하고 빌트인 와일드 카드([`:help wildcard`](https://neovim.io/doc/user/editing.html#wildcard))를 지원합니다: 1136 | 1137 | ```vim 1138 | function! s:completion_function(ArgLead, CmdLine, CursorPos) abort 1139 | return join([ 1140 | \ 'strawberry', 1141 | \ 'star', 1142 | \ 'stellar', 1143 | \ ], "\n") 1144 | endfunction 1145 | 1146 | command! -nargs=1 -complete=custom,s:completion_function Test echo 1147 | " Typing `:Test st[ae]` returns "star" and "stellar" 1148 | ``` 1149 | 1150 | 루아 함수를 `complete`에 넘기는 것은 `customplist`처럼 작동합니다. 이는 필터링을 사용자에게 맡깁니다: 1151 | 1152 | ```lua 1153 | vim.api.nvim_create_user_command('Test', function() end, { 1154 | nargs = 1, 1155 | complete = function(ArgLead, CmdLine, CursorPos) 1156 | return { 1157 | 'strawberry', 1158 | 'star', 1159 | 'stellar', 1160 | } 1161 | end, 1162 | }) 1163 | 1164 | -- Typing `:Test z` returns all the completion results because the list was not filtered 1165 | ``` 1166 | 1167 | ## autocommands 정의하기 1168 | 1169 | (이 섹션은 현재 작업 중입니다) 1170 | 1171 | 네오빔 0.7.0+ 에는 autocommands를 위한 API 함수들이 있습니다. (`:help api-autocmd`에 상세한 설명이 있습니다.) 1172 | 1173 | - [Pull request #14661](https://github.com/neovim/neovim/pull/14661) (lua: autocmds take 2) 1174 | 1175 | ## highlights 정의하기 1176 | 1177 | (이 섹션은 현재 작업 중입니다) 1178 | 1179 | 네오빔 0.7.0+ 에는 highlight 그룹을 위한 API 함수들이 있습니다. 자세한 정보: 1180 | 1181 | - [`:help nvim_set_hl()`](https://neovim.io/doc/user/api.html#nvim_set_hl()) 1182 | - [`:help nvim_get_hl_by_id()`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_id()) 1183 | - [`:help nvim_get_hl_by_name()`](https://neovim.io/doc/user/api.html#nvim_get_hl_by_name()) 1184 | 1185 | ## 일반적인 팁과 추천 사항들 1186 | 1187 | ### 캐시 모듈들 리로딩하기 1188 | 1189 | 루아에서 `require()` 함수는 모듈을 캐시합니다. 퍼포먼스를 위해서는 좋지만 플러그인을 만들때는 조금 성가실 수 있습니다. `require()`를 다시 부를 때 모듈이 업데이트 되지 않기 때문입니다. 1190 | 1191 | 만약 특정 모듈의 캐시를 새로고침 하고 싶다면 전역 테이블인 `package.loaded`를 수정해야 합니다: 1192 | 1193 | ```lua 1194 | package.loaded['modname'] = nil 1195 | require('modname') -- 'modname' 모듈의 업데이트된 버전을 로드합니다. 1196 | ``` 1197 | 1198 | [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) 플러그인에는 이걸 대신해주는 [커스텀 함수](https://github.com/nvim-lua/plenary.nvim/blob/master/lua/plenary/reload.lua)가 있습니다. 1199 | 1200 | 1201 | ### 루아 문자열 양 끝에 공백을 넣지 마세요! 1202 | 1203 | 이중 중괄호 스트링을 사용할 때 양 끝에 공백 문자를 넣지 마세요. 스페이스가 무시되는 맥락에서는 괜찮지만, whitespace가 의미있을 때는 디버깅 하기 어려운 문제를 일으킬 수 있습니다: 1204 | 1205 | ```lua 1206 | vim.api.nvim_set_keymap('n', 'f', [[ call foo() ]], {noremap = true}) 1207 | ``` 1208 | 1209 | 위의 예에서 `f`는 `call foo()` 대신 `call foo()`로 매핑됩니다. 1210 | 1211 | ### 빔스크립트 <-> 루아 타입 변환에 대해 알아둘 점 1212 | 1213 | #### 변수를 변환하는 것은 copy를 생성합니다: 1214 | 빔스크립트에서 루아 오브젝트, 혹은 루아에서 빔 오브젝트에 대한 참조와 직접 상호 작용할 수 없습니다. 1215 | 1216 | 예를 들어, 빔스크립트의 `map()` 함수는 변수를 그 자리에서 수정합니다: 1217 | 1218 | ```vim 1219 | let s:list = [1, 2, 3] 1220 | let s:newlist = map(s:list, {_, v -> v * 2}) 1221 | 1222 | echo s:list 1223 | " [2, 4, 6] 1224 | echo s:newlist 1225 | " [2, 4, 6] 1226 | echo s:list is# s:newlist 1227 | " 1 1228 | ``` 1229 | 1230 | 루아에서 이 함수를 사용할 때는 카피를 만듭니다: 1231 | 1232 | ```lua 1233 | local tbl = {1, 2, 3} 1234 | local newtbl = vim.fn.map(tbl, function(_, v) return v * 2 end) 1235 | 1236 | print(vim.inspect(tbl)) -- { 1, 2, 3 } 1237 | print(vim.inspect(newtbl)) -- { 2, 4, 6 } 1238 | print(tbl == newtbl) -- false 1239 | ``` 1240 | 1241 | #### 변환이 항상 가능한 것은 아닙니다 1242 | 이는 보통 함수와 테이블에 영향을 줍니다: 1243 | 1244 | 리스트와 딕셔너리가 같이 혼합된 루아 테이블은 변환될 수 없습니다: 1245 | 1246 | ```lua 1247 | print(vim.fn.count({1, 1, number = 1}, 1)) 1248 | -- E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys 1249 | ``` 1250 | 1251 | 루아에서 빔 함수를 `vim.fn`으로 호출할 수 있지만 참조를 갖고 있을 수는 없습니다. 이로 인해 다음과 같은 이상한 동작이 발생할 수 있습니다: 1252 | 1253 | ```lua 1254 | local FugitiveHead = vim.fn.funcref('FugitiveHead') 1255 | print(FugitiveHead) -- vim.NIL 1256 | 1257 | vim.cmd("let g:test_dict = {'test_lambda': {-> 1}}") 1258 | print(vim.g.test_dict.test_lambda) -- nil 1259 | print(vim.inspect(vim.g.test_dict)) -- {} 1260 | ``` 1261 | 1262 | 빔 함수에 루아 함수를 넘기는 것은 됩니다. 하지만 빔 변수에 저장하는 것은 안됩니다. (Neovim 0.7.0+ 에서 고쳐짐): 1263 | 1264 | ```lua 1265 | -- 이건 작동하지만: 1266 | vim.fn.jobstart({'ls'}, { 1267 | on_stdout = function(chan_id, data, name) 1268 | print(vim.inspect(data)) 1269 | end 1270 | }) 1271 | 1272 | -- 이건 안됩니다: 1273 | vim.g.test_dict = {test_lambda = function() return 1 end} -- Error: Cannot convert given lua type 1274 | ``` 1275 | 1276 | 하지만 빔스크립트에서 `luaeval()`을 사용할 때는 동일한 작업을 하면 **잘** 작동합니다: 1277 | 1278 | ```vim 1279 | let g:test_dict = {'test_lambda': luaeval('function() return 1 end')} 1280 | echo g:test_dict 1281 | " {'test_lambda': function('4714')} 1282 | ``` 1283 | 1284 | #### Vim booleans 1285 | 빔 스크립트에서 흔한 패턴은 `1`이나 `0`을 제대로 된 boolean 값 대신 사용하는 것입니다. 사실 빔에는 7.4.1154 버전까지 별도의 boolean 타입이 없었습니다. 1286 | 1287 | 루아 boolean은 빔스크립트의 실제 boolean 타입으로 변환됩니다. 숫자가 아니라요: 1288 | 1289 | ```vim 1290 | lua vim.g.lua_true = true 1291 | echo g:lua_true 1292 | " v:true 1293 | lua vim.g.lua_false = false 1294 | echo g:lua_false 1295 | " v:false 1296 | ``` 1297 | 1298 | ### Linters/Lanuage servers 설정하기 1299 | 1300 | 루아 프로젝트에 diagnostics와 autocompletion를 적용하기 위해 린터나 랭귀지 서버를 사용한다면 네오빔 특정 세팅을 설정해줘야 합니다. 여기 자주 사용되는 도구들을 위한 추천하는 세팅이 몇 개 있습니다: 1301 | 1302 | #### luacheck 1303 | 1304 | [luacheck](https://github.com/mpeterv/luacheck/)은 `vim` 전역 변수를 인식할 수 있게 해줍니다. 다음 설정을 `~/.luacheckrc` (혹은 `$XDG_CONFIG_HOME/luacheck/.luacheckrc`)에 넣어주세요: 1305 | 1306 | ```lua 1307 | globals = { 1308 | "vim", 1309 | } 1310 | ``` 1311 | 1312 | [Alloyed/lua-lsp](https://github.com/Alloyed/lua-lsp/) language server는 `luacheck`을 사용하여 linting을 제공하고 같은 파일을 읽습니다. 1313 | 1314 | 1315 | `luacheck`에 대한 더 자세한 정보는 이 [문서](https://luacheck.readthedocs.io/en/stable/config.html)를 보시면 됩니다. 1316 | 1317 | 1318 | #### sumneko/lua-language-server 1319 | 1320 | 1321 | [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) 리포지터리는 [sumneko/lua-language-server 구성 지침](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#sumneko_lua)을 포함하고 있습니다(이 예시는 빌트인 LSP 클라이언트를 사용하고 있지만 구성은 다른 LSP 클라이언트 구현체들과 동일할 겁니다). 1322 | 1323 | [sumneko/lua-language-server](https://github.com/sumneko/lua-language-server/) 설정하는 더 상세한 설명은 ["Setting"](https://github.com/sumneko/lua-language-server/wiki/Setting)를 보세요. 1324 | 1325 | 1326 | #### coc.nvim 1327 | 1328 | [rafcamlet/coc-nvim-lua](https://github.com/rafcamlet/coc-nvim-lua/)는 [coc.nvim](https://github.com/neoclide/coc.nvim/)을 위한 자동완성 소스입니다. Neovim stdlib에 자동완성 항목들을 제공합니다. 1329 | 1330 | ### 루아 코드 디버깅하기 1331 | 1332 | [jbyuki/one-small-step-for-vimkind](https://github.com/jbyuki/one-small-step-for-vimkind)로 루아 코드를 별도의 네오빔 인스턴스로 실행하여 디버깅할 수 있습니다. 1333 | 1334 | 1335 | 이 플러그인은 [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/)을 사용합니다. 디버그 어댑터에 연결하는 것은 [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap/)이나 [puremourning/vimspector](https://github.com/puremourning/vimspector/) 같은 DAP 클라이언트를 필요로 합니다. 1336 | 1337 | 1338 | ### 루아 매핑/커맨드/오토커맨드 디버깅 1339 | 1340 | `:verbose` 커맨드는 어디에 mapping/command/autocommand가 정의되어 있는지 확인할 수 있게 해줍니다: 1341 | 1342 | ```vim 1343 | :verbose map m 1344 | ``` 1345 | 1346 | ```text 1347 | n m_ * echo 'example' 1348 | Last set from ~/.config/nvim/init.vim line 26 1349 | ``` 1350 | 1351 | 루아에서 이 기능은 성능 상의 이유 때문에 기본적으로 비활성화 되어 있습니다. Neovim을 시작할 때 verbose 레벨을 0보다 크게 줌으로서 활성화시킬 수 있습니다: 1352 | 1353 | ```sh 1354 | nvim -V1 1355 | ``` 1356 | 1357 | 자세한 정보: 1358 | - [`:help 'verbose'`](https://neovim.io/doc/user/options.html#'verbose') 1359 | - [`:help -V`](https://neovim.io/doc/user/starting.html#-V) 1360 | - [neovim/neovim#15079](https://github.com/neovim/neovim/pull/15079) 1361 | 1362 | ### 루아 코드 테스팅 1363 | 1364 | - [plenary.nvim: test harness](https://github.com/nvim-lua/plenary.nvim/#plenarytest_harness) 1365 | - [notomo/vusted](https://github.com/notomo/vusted) 1366 | 1367 | ### Luarocks 패키지 사용하기 1368 | 1369 | [wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim)는 Luarocks 패키지를 지원합니다. [README](https://github.com/wbthomason/packer.nvim/#luarocks-support)에 세팅 방법에 대한 지침이 있습니다. 1370 | 1371 | ## 그 외 1372 | 1373 | ### vim.loop 1374 | 1375 | `vim.loop` 은 LibUV API를 사용할 수 있는 모듈입니다. 리소스들: 1376 | 1377 | - [Official documentation for LibUV](https://docs.libuv.org/en/v1.x/) 1378 | - [Luv documentation](https://github.com/luvit/luv/blob/master/docs.md) 1379 | - [teukka.tech - Using LibUV in Neovim](https://teukka.tech/posts/2020-01-07-vimloop/) 1380 | 1381 | 자세한 정보: 1382 | - [`:help vim.loop`](https://neovim.io/doc/user/lua.html#vim.loop) 1383 | 1384 | ### vim.lsp 1385 | 1386 | `vim.lsp`는 빌트인 LSP 클라이언트를 제어하는 모듈입니다. [neovim/nvim-lspconfig](https://github.com/neovim/nvim-lspconfig/) 리포지터리에 자주 쓰이는 language server들의 기본 설정 방법을 설명하고 있습니다. 1387 | 1388 | 클라이언트 동작은 "lsp-handlers"를 사용해 구성할 수 있습니다. 자세한 정보: 1389 | - [`:help lsp-handler`](https://neovim.io/doc/user/lsp.html#lsp-handler) 1390 | - [neovim/neovim#12655](https://github.com/neovim/neovim/pull/12655) 1391 | - [How to migrate from diagnostic-nvim](https://github.com/nvim-lua/diagnostic-nvim/issues/73#issue-737897078) 1392 | 1393 | [lsp client를 중심으로 개발된 플러그인](https://github.com/rockerBOO/awesome-neovim#lsp)들은 여기서 확인하실 수 있습니다. 1394 | 1395 | 자세한 정보: 1396 | - [`:help lsp`](https://neovim.io/doc/user/lsp.html#LSP) 1397 | 1398 | ### vim.treesitter 1399 | 1400 | `vim.treesitter`는 Neovim [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) 라이브러리의 통합을 제어하는 모듈입니다. Tree-sitter에 대해 더 자세히 알고 싶다면 다음 [프레젠테이션 (38:37)](https://www.youtube.com/watch?v=Jes3bD6P0To)을 참조하세요. 1401 | 1402 | 1403 | [nvim-treesitter](https://github.com/nvim-treesitter/) 조직은 이 라이브러리를 활용한 다양한 플러그인들을 제공합니다. 1404 | 1405 | 자세한 정보: 1406 | - [`:help lua-treesitter`](https://neovim.io/doc/user/treesitter.html#lua-treesitter) 1407 | 1408 | ### Transpilers 1409 | 1410 | 루아 사용의 이점 중 하나는 꼭 루아 코드로 작성하지 않아도 된다는 것입니다! 루아를 위한 다양한 트랜스파일러들이 있습니다. 1411 | 1412 | - [Moonscript](https://moonscript.org/) 1413 | 1414 | 아마 가장 잘 알려진 루아 트랜스파일러입니다. 클래스, 배열 이해(list comprehension), 함수 리터럴 같은 편리한 기능들을 많이 제공하고 있습니다. [svermeulen/nvim-moonmaker](https://github.com/svermeulen/nvim-moonmaker) 플러그인은 네오빔 플러그인과 설정을 Moonscript에서 바로 할 수 있도록 해줍니다. 1415 | 1416 | - [Fennel](https://fennel-lang.org/) 1417 | 1418 | 루아로 컴파일되는 리습입니다. [Olical/aniseed](https://github.com/Olical/aniseed) 혹은 [Hotpot](https://github.com/rktjmp/hotpot.nvim) 플러그인을 사용하면 네오빔을 위한 구성과 플러그인 작성을 Fennel로 할 수 있습니다. 추가적으로 [Olical/conjure](https://github.com/Olical/conjure) 플러그인은 Fennel을(다른 리습 계열 언어들과 함께) 지원하는 IDE를 제공합니다. 1419 | 1420 | - [Teal](https://github.com/teal-language/tl) 1421 | 1422 | Teal은 TL(typed lua)로 발음됩니다. 스탠다드 루아 구문을 그대로 유지하면서 강타입 시스템을 지원하는 언어입니다. [nvim-teal-maker](https://github.com/svermeulen/nvim-teal-maker) 플러그인으로 Teal을 사용해 네오빔 플러그인, 구성을 작성할 수 있습니다. 1423 | 1424 | 다른 흥미로운 프로젝트들: 1425 | - [TypeScriptToLua/TypeScriptToLua](https://github.com/TypeScriptToLua/TypeScriptToLua) 1426 | - [Haxe](https://haxe.org/) 1427 | - [SwadicalRag/wasm2lua](https://github.com/SwadicalRag/wasm2lua) 1428 | - [hengestone/lua-languages](https://github.com/hengestone/lua-languages) 1429 | -------------------------------------------------------------------------------- /doc/nvim-lua-guide.txt: -------------------------------------------------------------------------------- 1 | *nvim-lua-guide.txt* Getting started using Lua in Neovim 2 | 3 | ============================================================================== 4 | INTRODUCTION 5 | *luaguide-introduction* 6 | 7 | The integration of Lua: https://www.youtube.com/watch?v=IP3J56sKtn0 8 | as a first-class language inside Neovim: 9 | https://github.com/neovim/neovim/wiki/FAQ#why-embed-lua-instead-of-x 10 | is shaping up to be one of its killer features. 11 | However, the amount of teaching material for learning how to write 12 | plugins in Lua is not as large as what you would find for writing them 13 | in Vimscript. This is an attempt at providing some basic information to 14 | get people started. 15 | 16 | This guide assumes you are using at least version 0.5 of Neovim. 17 | 18 | Learning Lua~ 19 | 20 | If you are not already familiar with the language, there are plenty of 21 | resources to get started: 22 | 23 | - The Learn X in Y minutes page about Lua: 24 | https://learnxinyminutes.com/docs/lua/ should give you a quick overview 25 | of the basics 26 | - This guide: 27 | https://github.com/medwatt/Notes/blob/main/Lua/Lua_Quick_Guide.ipynb 28 | is also a good resource for getting started quickly 29 | - If videos are more to your liking, Derek Banas has a 1-hour tutorial 30 | on the language: https://www.youtube.com/watch?v=iMacxZQMPXs 31 | - Want something a little more interactive with runnable examples? Try 32 | the LuaScript tutorial: https://www.luascript.dev/learn 33 | - The lua-users wiki: http://lua-users.org/wiki/LuaDirectory is full 34 | of useful information on all kinds of Lua-related topics 35 | - The official reference manual for Lua: https://www.lua.org/manual/5.1/ 36 | should give you the most comprehensive tour of the language exists as 37 | a Vimdoc plugin if you want to read it from the comfort of your editor: 38 | milisims/nvim-luaref: https://github.com/milisims/nvim-luaref 39 | 40 | It should also be noted that Lua is a very clean and simple language. It 41 | is easy to learn, especially if you have experience with similar scripting 42 | languages like JavaScript. You may already know more Lua than you realise! 43 | 44 | Note: the version of Lua that Neovim embeds is LuaJIT: 45 | https://staff.fnwi.uva.nl/h.vandermeer/docs/lua/luajit/luajit_intro.html 46 | 2.1.0, which maintains compatibility with Lua 5.1. 47 | 48 | Existing tutorials for writing Lua in Neovim~ 49 | 50 | A few tutorials have already been written to help people write plugins 51 | in Lua. Some of them helped quite a bit when writing this guide. Many 52 | thanks to their authors. 53 | 54 | - teukka.tech - From init.vim to init.lua: 55 | https://teukka.tech/luanvim.html 56 | - dev.to - How to write neovim plugins in Lua: 57 | https://dev.to/2nit/how-to-write-neovim-plugins-in-lua-5cca 58 | - dev.to - How to make UI for neovim plugins in Lua: 59 | https://dev.to/2nit/how-to-make-ui-for-neovim-plugins-in-lua-3b6e 60 | - ms-jpq - Neovim Async Tutorial: 61 | https://github.com/ms-jpq/neovim-async-tutorial 62 | - oroques.dev - Neovim 0.5 features and the switch to init.lua: 63 | https://oroques.dev/notes/neovim-init/ 64 | - Building A Vim Statusline from Scratch - jdhao's blog: 65 | https://jdhao.github.io/2019/11/03/vim_custom_statusline/ 66 | - Configuring Neovim using Lua: https://icyphox.sh/blog/nvim-lua/ 67 | - Devlog | Everything you need to know to configure neovim using lua: 68 | https://vonheikemen.github.io/devlog/tools/configuring-neovim-using-lua/ 69 | 70 | Companion plugins~ 71 | 72 | - Vimpeccable: https://github.com/svermeulen/vimpeccable - Plugin to 73 | help write your .vimrc in Lua 74 | - plenary.nvim: https://github.com/nvim-lua/plenary.nvim - All the 75 | lua functions I don't want to write twice 76 | - popup.nvim: https://github.com/nvim-lua/popup.nvim - An implementation 77 | of the Popup API from vim in Neovim 78 | - nvim_utils: https://github.com/norcalli/nvim_utils 79 | - nvim-luadev: https://github.com/bfredl/nvim-luadev - REPL/debug 80 | console for nvim lua plugins 81 | - nvim-luapad: https://github.com/rafcamlet/nvim-luapad - Interactive 82 | real time neovim scratchpad for embedded lua engine 83 | - nlua.nvim: https://github.com/tjdevries/nlua.nvim - Lua Development 84 | for Neovim 85 | - BetterLua.vim: https://github.com/euclidianAce/BetterLua.vim - 86 | Better Lua syntax highlighting in Vim/NeoVim 87 | 88 | ============================================================================== 89 | WHERE TO PUT LUA FILES 90 | *luaguide-where-to-put-lua-files* 91 | 92 | init.lua~ 93 | 94 | Neovim supports loading an `init.lua` file for configuration instead of 95 | the usual `init.vim`. 96 | 97 | Note: `init.lua` is of course _completely_ optional. Support 98 | for `init.vim` is not going away and is still a valid option for 99 | configuration. Do keep in mind that some features are not 100% exposed 100 | to Lua yet. 101 | 102 | See also: 103 | - |config| 104 | 105 | Modules~ 106 | 107 | Lua modules are found inside a `lua/` folder in your `'runtimepath'` 108 | (for most users, this will mean `~/.config/nvim/lua` on \*nix systems 109 | and `~/AppData/Local/nvim/lua` on Windows). You can `require()` files 110 | in this folder as Lua modules. 111 | 112 | Let's take the following folder structure as an example: 113 | 114 | > 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 | --------------------------------------------------------------------------------