Module
require('module')
require('directory/module')
require('directory.module')require키워드를 통해 모듈을 불러올 수 있다/,.를 통해서 경로를 구분할 수 있다
TIP
init.lua 파일이 있다면
require('directory')형태로 모듈을 불러올 수 있다.
pcall
local ok, _ = pcall(require, 'module_with_error')
if not ok then
-- not loaded
endpcall()함수를 사용하여 현재 실행중인 스크립트가 어떠한 에러로 인해 스크립트가 종료되는 것을 방지할 수 있다.
lua, luado
:lua <lua script>
:luado <lua script>CmdLine을 통해서 lua를 실행할 수 있다.
:lua: 각각의 스코프를 가지고 있으며 외부에서 접근할 수 없다
:lua local foo = 1
:lua print(foo)
" prints 'nil' instead of '1':luado: 현재 버퍼에 라인들의 특정한 범위를 대상으로 루아 코드를 실행한다
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
aaaaaa
// CmdLine
// :luado if linenr % 2 == 0 then return line:upper() end
aaaaaa
AAAAAA
aaaaaa
AAAAAA
aaaaaa
AAAAAA
aaaaaa
AAAAAA
aaaaaaTIP
버퍼(Buffer)는 파일의 내용을 메모리에 불러와 수정할 수 있는 임시 작업 공간이다.
luaeval
luaeval() 함수는 인자로 입력 받은 문자열을 루아 표현식 변경하여 값을 도출하고 그 값을 리턴한다.
" 결과값을 변수에 담을 수 있습니다.
let variable = luaeval('1 + 1')
echo variable
" 2
let concat = luaeval('"Lua".." is ".."awesome"')
echo concat
" 'Lua is awesome'
" 루아의 리스트 형태의 테이블은 빔의 리스트로 변환됩니다.
let list = luaeval('{1, 2, 3, 4}')
echo list[0]
" 1
echo list[1]
" 2
" 알림 루아의 테이블은 1부터 인덱싱 되지만 빔의 리스트는 0부터입니다.
" 딕셔너리 형태의 테이블은 빔의 딕셔너리로 변환됩니다.
let dict = luaeval('{foo = "bar", baz = "qux"}')
echo dict.foo
" 'bar'두 번째 인자를 통해서 데이터를 전달할 수 있다.
echo luaeval('_A[1] + _A[2]', [1,1])v:lua
v:lua는 루아의 전역 공간(_G)에 존재하는 함수들을 vim script에서 접근할 수 있게 해준다.
function _G.call_hello_world()
print("Hello World")
end위의 함수를 CmdLine에서 call v:lua.call_hello_world()로 호출할 수 있다.
_G
A global variable (not a function) that holds the global environment (that is, _G._G = _G). Lua itself does not use this variable; changing its value does not affect any environment, nor vice-versa. (Use setfenv to change environments.)
알아두면 좋을 모듈
vim.inspect: lua object를 읽기 편한 문자열로 변환하는 모듈vim.regex: lua에서 vim regex를 사용할 수 있는 모듈vim.api: API 함수들을 사용할 수 있는 모듈vim.ui: 오버라이드 가능한 UI 함수들vim.loop: neovim의 event-loop의 기능을 사용할 수 있는 모듈(libuv 사용)vim.lsp: 내장 LSP 클라이언트에 접근할 수 있는 모듈vim.treesitter:tree-sitter라이브러리 기능을 사용할 수 있는 모듈
커스텀 유틸리티
nvim에서 자신이 만든 유틸리티 모듈을 사용하고 싶다면 파일 생성 후 init.lua에 모듈을 불러와주면 된다.
-- utils/put.lua
function _G.put(...)
local objects = {}
for i = 1, select("#", ...) do
local v = select(i, ...)
table.insert(objects, vim.inspect(v))
end
print(table.concat(objects, "\n"))
return ...
endrequire("utils.put")
require("config.lazy")Lua에서 Vim script 사용 방법
vim.api.nvim_eval()
-- 데이터 타입 변환 예
print(vim.api.nvim_eval('1 + 1')) -- 2
print(vim.inspect(vim.api.nvim_eval('[1, 2, 3]'))) -- { 1, 2, 3 }
print(vim.inspect(vim.api.nvim_eval('{"foo": "bar", "baz": "qux"}'))) -- { baz = "qux", foo = "bar" }
print(vim.api.nvim_eval('v:true')) -- true
print(vim.api.nvim_eval('v:null')) -- nil해당 함수는 Vim script 표현식을 평가하고 값을 리턴한다.
>
luaeva()과 동일하지만 표현식에 데이터를 넘길 수 있는 변수_A를 제공하지 않는다.
vim.api.nvim_command()
vim.api.nvim_command('new')
vim.api.nvim_command('wincmd H')
vim.api.nvim_command('set nonumber')
vim.api.nvim_command('%s/foo/bar/g')해당 함수는 인자로 입력 받은 문자열로 된 커맨드를 실행할 수 있다.
vim.cmd()
해당 함수는 커맨드 vim.api.nvim_exec()함수와 같이 vim script 코드 조각을 평가할 수 있다.
vim.cmd([[%s/\Vfoo/bar/g]])vim.api.nvim_replace_termcodes()
해당 함수는 터미널 코드와 vim 키코드를 escape 할 수 있게 해준다.
// vim script
inoremap <expr> <Tab> pumvisible() ? "\<C-N>" : "\<Tab>"local function t(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
function _G.smart_tab()
return vim.fn.pumvisible() == 1 and t'<C-N>' or t'<Tab>'
end
vim.api.nvim_set_keymap('i', '<Tab>', 'v:lua.smart_tab()', {expr = true, noremap = true})두 예시 모두 동일한 기능을 한다. t()함수 내부의 nvim_replace_termcodes()를 통해서 t'<Key>'와 같은 문법으로 escape를 해줄 수 있다.
더 편리한 방법은 vim.keymap.set() 함수를 사용하는 것이다. 해당 함수는 opts의 expr이 true일 경우 자동적으로 키코드를 변환해주기 때문에 따로 escape 처리할 필요가 없다.
vim.keymap.set('i', '<Tab>', function()
return vim.fn.pumvisible() == 1 and '<C-N>' or '<Tab>'
end, {expr = true})Keymap
Vim에는 다양한 Mode가 존재한다. 특정한 Mode에 따라서 vim.keymap을 통해서 키를 조작할 수 있다.
Arguments
{mode}: Mode prefix{lhs}: 맵핑할 키{rhs}: 맵핑한 키를 통해 실행할 command 또는 lua funciton
Option
key를 맵핑할 때 4번째 인자에 옵션을 지정할 수 있다.
-
buffer: 특정 버퍼(0또는true이면 현재 버퍼를 의미) -
silent:true이면 에러 메시지를 출력하지 않는다 -
expr:true이면{rhs}를 실행하지 않고return값을 실행한다. “표현식을 평가”해서 실행한다고 생각하면 된다vim.keymap.set('c', '<down>', function() if vim.fn.pumvisible() == 1 then return '<c-n>' end return '<down>' end, { expr = true }) -
desc: 설명 -
remap: 맵핑된 키에 대한 (비)재귀적 여부. 기본값은 비재귀적이다
(Non)recursive
- Non-recursive(default) :
vim.keymap.set()을 통해서 키를 맵핑하면 다른 맵핑된{rhs}는 실행되지 않는다 - recursive : 다른 맵핑된
{rhs}실행을 허용한다
-- Non-recursive mapping (default behavior)
vim.keymap.set('n', '<leader>a', ':echo "Hello"<CR>')
-- Recursive mapping
vim.keymap.set('n', '<leader>b', '<leader>a', { remap = true }){remap = true}로 설정하게 되면 <leader>b를 누르면 <leader>a가 실행되고 :echo "Hello"<CR>이 실행되게 된다. 반대로 기본값으로 설정하게 되면 :echo "Hello"<CR>는 실행되지 않는다.
TIP
noremap을 통해서도 Non-recursive가 적용된 키 맵핑을 할 수 있다.vim.keymap.set()을 사용한 것과 동일하다.
Mode
| String value | Help page | Affected modes | Vimscript equivalent |
|---|---|---|---|
'' (an empty string) | mapmode-nvo | Normal, Visual, Select, Operator-pending | :map |
'n' | mapmode-n | Normal | :nmap |
'v' | mapmode-v | Visual and Select | :vmap |
's' | mapmode-s | Select | :smap |
'x' | mapmode-x | Visual | :xmap |
'o' | mapmode-o | Operator-pending | :omap |
'!' | mapmode-ic | Insert and Command-line | :map! |
'i' | mapmode-i | Insert | :imap |
'l' | mapmode-l | Insert, Command-line, Lang-Arg | :lmap |
'c' | mapmode-c | Command-line | :cmap |
't' | mapmode-t | Terminal | :tmap |
vim.keymap.set()
vim.keymap.set('n', '<Leader>ex1', '<Cmd>lua vim.notify("Example 1")<CR>')
vim.keymap.set({'n', 'c'}, '<Leader>ex2', '<Cmd>lua vim.notify("Example 2")<CR>')
vim.keymap.set('i', '<Tab>', function()
return vim.fn.pumvisible == 1 and '<C-N>' or '<Tab>'
end, {expr = true})vim.keymap.del()
vim.keymap.del('n', '<Leader>ex1')
vim.keymap.del({'n', 'c'}, '<Leader>ex2', {buffer = true})Commands

vim.cmd() 함수를 통해서 cmdline에 직접적으로 값을 넣어 실행할 수 있다.
vim.cmd("echo 'hello world'")또한 [[ ]]를 이용하여 다수의 커맨드를 실행시킬 수 있으며, literal string도 가능하다.
vim.cmd([[%s/\Vfoo/bar/g]]) -- literal string
vim.cmd([[
highlight Error guibg=red
highlight link Warning Error
]])Function
Vim은 vim.fn을 통하여 Vimscript function을 lua에서 호출할 수 있다.
print(vim.fn.printf('Hello from %s', 'Lua'))
local reversed_list = vim.fn.reverse({ 'a', 'b', 'c' })
vim.print(reversed_list) -- { "c", "b", "a" }
local function print_stdout(chan_id, data, name)
print(data[1])
endVariable
Vim에는 global, buffer, window, tab, predefined, env의 환경에서 변수를 설정할 수 있다.
vim.g: 전역 변수vim.b: 현재 버퍼의 변수vim.w: 현재 윈도우의 변수vim.t: 현재 탭 페이지의 변수vim.v: 미리 정의된 변수vim.env: 에디터 세션 내의 정의한 환경 변수
Data type
데이터 타입에 대해서는 자동적으로 변경된다.
vim.g.some_global_variables = {
key1 = 'value',
key2 = 300
}
vim.print(vim.g.some_global_variables.key2) -- 300Target specific something
숫자를 통해서 특정 buffer, window, tabpage에 접근할 수 있다.
vim.b[2].myvar = 1 -- set myvar for buffer number 2
vim.w[1005].myothervar = true -- set myothervar for window ID 1005Can access a property using #
아래의 코드와 같이 #을 통해서 변수 프로퍼티에 접근할 수 있다.
vim.g['my#variable'] = 1Delete a variable
변수를 삭제할 때는 nil을 할당해주면 된다.
vim.g['my#variable'] = nilOption
vim.opt를 통해서 옵션에 대한 설정을 할 수 있다. vim의 옵션에는 set number, set cursorline, set smarttab 등을 지정할 수 있다.
vim.opt.smarttab = true
vim.opt.smarttab = false또한 vim.o를 통해서도 다음과 같이 특정 환경의 옵션을 지정할 수 있다.
vim.o::set과 동일하다vim.go: 전역 옵션vim.bo: 버퍼 스코프 옵션vim.wo: 윈도우 스코프 옵션