nvim-laurel provides a set of macros for Neovim config, inspired by the builtin Nvim Lua-Vimscript bridge on metatable and by good old Vim script.
Each macro might be more flexible than documented, but of course, undocumented usages are subject to change without notifications.
The terminology is introduced to describe the interfaces of nvim-laurel rather than a standard one.
An abbreviation of left-hand-side.
An abbreviation of right-hand-side.
Hash function, where $1 through $9 and $... are available as the
argument. $ is an alias for $1. Read the official
Fennel reference
for the detail.
An alias of sequential table [].
An alias of key/value table {}.
It describes the {type} value must be neither symbol nor list in compile
time. For example,
:foobaris abare-string.(.. :foo :bar)is not abare-string.[:foo :bar]is both abare-sequenceand abare-string[].[baz]wherebazis either symbol or list is abare-sequence, but not abare-string[].(icollect [_ val (ipairs [:foo :bar])] val)is neither abare-sequencenorbare-string[].
It represents {name} is omittable rather than nilable in nvim-laurel
contexts.
It is kv-table {} option for the API functions, vim.api.nvim_foo(). Unless
otherwise noted, this option has the following features:
- It only accepts the same key/value described in
api.txt. - Its values have the highest priority over those set in the other arguments if conflicted.
An alternative form for api-opts. Unless otherwise noted, this option has
the following features:
-
It is bare-sequence
[], but is interpreted as if kv-table{}in the following manner:- Items for keys must be bare-strings; items for values can be of any type.
- Boolean key/value for
api-optsis set totrueby key itself; the other keys expects the next items as their values respectively. - To set
falseto boolean key/value, set it inapi-optsinstead.
-
It is intended as shorthand; for complicated usage, use
api-optsinstead or use them together. -
It could accept some additional keys which are unavailable in
api-opts. -
(since v0.7.4) The
:desckey can be omitted if the description is written in the first argument ofextra-optsand does not match against any other keys ofextra-opts.(Note that
autocmd!additionally has a minor exception. Please refer to the inline link for details.)
The symbols are reserved to be used as arguments in lists of nvim-laurel
macros to extend their functionalities.
(Since v0.5.3)
A reserved symbol to set Vim script callback in symbol or list.
Basically, symbol and list are interpreted as Lua callback function in the
lists of nvim-laurel macros.
With &vim in the list of nvim-laurel macro, they are interpreted as Vim
script command.
List of macros in which &vim makes sense:
(Since v0.6.1)
A reserved symbol to set default values of api-opts fields.
It indicates that the bare kv-table next to the symbol &default-opts
contains default values for api-opts, but it also interprets the additional
keys available in extra-opts.
To set boolean option, it requires to set to either true or
false in spite of the syntax of extra-opts itself.
See also its Anti-Patterns.
List of macros in which &default-opts is available:
Note that quote position depends on where the wrapper macros are defined:
-
To define a wrapper
macroto be expanded in the same file, quote the entirelistof the imported macro (and unquote as you need). For example,;; in foobar.fnl (import-macros {: map!} :laurel.macros) (macro buf-map! [...] `(map! &default-opts {:buffer 0} ,...)) (buf-map! :lhs :rhs)
-
To define a wrapper
functionto be imported as a macro in another file, just quote&default-opts. For example,;; in my/macros.fnl (local {: map!} (require :laurel.macros)) (fn buf-map! [...] (map! `&default-opts {:buffer 0} ...)) {: buf-map!}
;; in foobar.fnl (another file) (import-macros {: buf-map!} :my.macros) (buf-map! :lhs :rhs)
Create or get an augroup, or override existing augroup.
(&default-opts is available.)
; Only this format returns the augroup id.
(augroup! name ?api-opts-for-augroup)
(augroup! name ?api-opts-for-augroup
[events ?pattern ?extra-opts callback ?api-opts]
...)
(augroup! name ?api-opts-for-augroup
;; Wrap args in `autocmd!` or `au!` instead of brackets.
(autocmd! events ?pattern ?extra-opts callback ?api-opts)
...)-
?api-opts-for-augroup: (kv-table):h nvim_create_augroup(). You cannot use macro/function namedau!orautocmd!here. Additional options:always-return-id(boolean; default:true) Iftrue, theaugroup!macro should return theaugroupid regardless ofautocmd!lists inside. Iffalse, the return value is not guaranteed.
-
name: (string) The name of autocmd group. -
events: (string|string[]) The event or events to register this autocmd. -
?pattern: (bare-sequence|*) Patterns to match against. To setpatternin symbol or list, set it in eitherextra-optsorapi-optsinstead. The first pattern in string cannot be any of the keys used in?extra-opts. The symbol*is available to imply pattern"*"here. -
?extra-opts: (bare-sequence) Additional option:buffer: (number?) Create command in the buffer of the next value. Without 0 or no following number, create autocmd to current buffer by itself.
Note: The
:desckey can be omitted if the description is written in the first argument ofextra-optsand does not match against any other keys ofextra-opts. However, unlike other macros, if?patternis also omitted,autocmd!additionally requires at least one otherextra-optskey to omit:desc. -
callback: (string|function) Set either callback function or Ex command. A callback is interpreted as Lua function by default. To set Ex command, you have three options:- Set it in bare-string.
- Insert
&vimsymbol just before the callback. - Name the first symbol for the callback to match
^<.+>in Lua pattern.
Note: Set
vim.fn.foobarto call Vim script functionfoobarwithout table argument fromnvim_create_autocmd(); on the other hand, set#(vim.fn.foobar $)to callfoobarwith the table argument. -
?api-opts: (kv-table):h nvim_create_autocmd().
(augroup! :sample-augroup {:always-return-id false}
[:TextYankPost #(vim.highlight.on_yank {:timeout 450 :on_visual false})]
(autocmd! [:InsertEnter :InsertLeave]
[:buffer :desc "call foo#bar() without any args"] vim.fn.foo#bar)
(autocmd! :VimEnter * [:once :nested :desc "call baz#qux() with <amatch>"]
#(vim.fn.baz#qux $.match))
(autocmd! :LspAttach *
#(au! $.group :CursorHold [:buffer $.buf]
vim.lsp.buf.document_highlight)))
(case (augroup! :lazy-augroup
(au! [:BufRead] * #(do-something-to-buf $.buf)))
group (when vim.v.vim_did_enter
;; Apply the autocmd to each buf already loaded before the augroup
;; is created.
(fn apply-lazy-augroup! [buffer]
(vim.api.nvim_exec_autocmds :BufRead {: group : buffer}))
(each [_ buf (ipairs (vim.api.nvim_list_bufs))]
(vim.api.nvim_buf_call buf apply-lazy-augroup!))))is equivalent to
augroup sample-augroup
autocmd!
autocmd TextYankPost * lua vim.highlight.on_yank {timeout=450, on_visual=false}
autocmd InsertEnter,InsertLeave <buffer> call foo#bar()
autocmd VimEnter * ++once ++nested call baz#qux(expand('<amatch>'))
autocmd LspAttach * au sample-augroup CursorHold <buffer>
\ lua vim.lsp.buf.document_highlight()
augroup END
augroup lazy-augroup
autocmd!
autocmd BufRead * lua do_something_to_buf(vim.fn.expand('<abuf>'))
augroup END
if v:vim_did_enter
bufdo doautocmd lazy-augroup BufRead
endiflocal id = vim.api.nvim_create_augroup("sample-augroup", {})
vim.api.nvim_create_autocmd("TextYankPost", {
group = id,
callback = function()
vim.highlight.on_yank({ timeout = 450, on_visual = false })
end,
})
vim.api.nvim_create_autocmd({ "InsertEnter", "InsertLeave" }, {
group = id,
buffer = 0,
desc = "call foo#bar() without any args",
callback = "foo#bar",
})
vim.api.nvim_create_autocmd("VimEnter", {
group = id,
once = true,
nested = true,
desc = "call baz#qux() with <amatch>",
callback = function(a)
vim.fn["baz#qux"](a.match)
end,
})
vim.api.nvim_create_autocmd("LspAttach", {
group = id,
callback = function(a)
vim.api.nvim_create_autocmd("CursorHold", {
group = a.group,
buffer = a.buf,
callback = vim.lsp.buf.document_highlight,
})
end,
})
local group = vim.api.nvim_create_augroup("lazy-augroup", {})
vim.api.nvim_create_autocmd("BufRead", {
group = group,
callback = function(a)
do_something_to_buf(a.buf)
end,
})
if vim.v.vim_did_enter then
local function apply_lazy_augroup(buffer)
vim.api.nvim_exec_autocmds("BufRead", {
group = group,
buffer = buffer,
})
do_something_to_buf(buffer)
end
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
vim.api.nvim_buf_call(buf, apply_lazy_augroup)
end
endc.f. autocmd!
Create an autocmd.
(&default-opts is available.)
; Just as an alias of `nvim_create_autocmd()`.
(autocmd! events api-opts)
(autocmd! name-or-id events ?pattern ?extra-opts callback ?api-opts)name-or-id: (string|integer|nil) The autocmd group name or id to match against. It is necessary unlikenvim_create_autocmd()unless thisautocmd!macro is within eitheraugroup!. Set it tonilto defineautocmds affiliated with no augroup.
See augroup! for the rest.
An alias of autocmd!.
(&default-opts is available.)
Map lhs to rhs in modes, non-recursively by default.
(&default-opts is available.)
(map! modes ?extra-opts lhs rhs ?api-opts)
(map! modes lhs ?extra-opts rhs ?api-opts)-
modes: (string|string[]) Mode short-name (map command prefix:"n","i","v","x", …) or"!"for:map!, or empty string for:map. As long as in bare-string, multi modes can be set in a string like:noxinstead of[:n :o :x]. -
?extra-opts: (bare-sequence) Additional option:buffer: (number?) Maplhsto a buffer of the next value. With0or with no following value, create autocmd to current buffer.literal: Disablereplace_keycodes, which is automatically enabled whenexpris set inextra-opts.remap: Make the mapping recursive. This is the inverse of the "noremap" option fromnvim_set_keymap().wait: Disablenowaitinextra-opts; will NOT disablenowaitinapi-opts. Useful in wrapper macro which setnowaitwith&default-opts.
Note: The
:desckey can be omitted if the description is written in the first argument ofextra-optsand does not match against any other keys ofextra-opts. -
lhs: (string) Left-hand-side of the mapping. -
rhs: (string|function) Right-hand-side of the mapping. Set either callback function or Key sequence. A callback is interpreted as Lua function by default. To set Ex command, you have three options:- Set it in bare-string.
- Insert
&vimsymbol just before the callback. - Name the first symbol for the callback to match
^<.+>in Lua pattern.
-
?api-opts: (kv-table):h nvim_set_keymap().
(map! :i :jk :<Esc>)
(map! :n :lhs [:desc "call foo#bar()"] #(vim.fn.foo#bar))
(map! [:n :x] [:remap :expr :literal] :d
"&readonly ? '<Plug>(readonly-d)' : '<Plug>(noreadonly-d)'")
(map! [:n :x] [:remap :expr] :u
#(if vim.bo.readonly
"<Plug>(readonly-u)"
"<Plug>(noreadonly-u)"))is equivalent to
inoremap jk <Esc>
nnoremap lhs <Cmd>call foo#bar()<CR>
nmap <expr> d &readonly ? "\<Plug>(readonly-d)" : "\<Plug>(noreadonly-d)"
xmap <expr> u &readonly ? "\<Plug>(readonly-u)" : "\<Plug>(noreadonly-u)"vim.api.nvim_set_keymap("i", "jk", "<Esc>", {})
vim.api.nvim_set_keymap("n", "lhs", "", {
-- callback = vim.fn["foo#bar"], -- If you don't care autoload.
callback = function()
vim.fn["foo#bar"]()
end,
})
vim.api.nvim_set_keymap(
"n",
"d",
"&readonly ? '<Plug>(readonly-d)' : '<Plug>(noreadonly-d)'",
{
expr = true,
replace_keycodes = false,
}
)
vim.api.nvim_set_keymap(
"x",
"d",
"&readonly ? '<Plug>(readonly-d)' : '<Plug>(noreadonly-d)'",
{
expr = true,
replace_keycodes = false,
}
)
vim.api.nvim_set_keymap("n", "u", "", {
expr = true,
callback = function()
return vim.bo.readonly and "<Plug>(readonly-u)" or "<Plug>(noreadonly-u)"
end,
})
vim.api.nvim_set_keymap("x", "u", "", {
expr = true,
callback = function()
return vim.bo.readonly and "<Plug>(readonly-u)" or "<Plug>(noreadonly-u)"
end,
})
-- or with vim.keymap.set wrapper,
vim.keymap.set("i", "jk", "<Esc>")
vim.keymap.set("n", "lhs", function()
vim.fn["foo#bar"]()
end)
vim.keymap.set(
{ "n", "x" },
"d",
"&readonly ? '<Plug>(readonly-d)' : '<Plug>(noreadonly-d)'",
{
remap = true,
expr = true,
replace_keycodes = false,
}
)
vim.keymap.set({ "n", "x" }, "u", function()
return vim.bo.readonly and "<Plug>(readonly-u)" or "<Plug>(noreadonly-u)"
end, {
remap = true,
expr = true,
})Delete keymap.
(unmap! ?bufnr mode lhs)?bufnr: (number) Optional buffer handle, or 0 for current buffer.mode: (string) Mode to unmap.lhs: (string) Left-hand-side key to unmap.
(unmap! :n :foo)
(unmap! 0 :o :bar)
(unmap! 10 :x :baz)is equivalent to
nunmap foo
ounmap <buffer> bar
" No simple command to delete keymap in specific buffer.vim.api.nvim_del_keymap("n", "foo")
vim.api.nvim_buf_del_keymap(0, "o", "bar")
vim.api.nvim_buf_del_keymap(10, "x", "baz")Generate <Cmd>foobar<CR> in string. Useful for rhs in keymap macro.
(<Cmd> text)text: (string)
Generate :<C-u>foobar<CR> in string. Useful for rhs in keymap macro.
(<C-u> text)text: (string)
(Inspired by :let)
Set value to the Vim variable
(g, b, w, t, v, env),
or option
(o, go, bo, wo, opt, opt_local, opt_global).
It can also append, prepend, or remove, value the Vim option
in the scopes: opt, opt_local, opt_global.
This is an optimized replacement of vim.o, vim.bo, ...,
vim.opt, vim.opt_local, vim.opt_global,
and vim.g, vim.b, and so on.
Note: There is no plan to support option prefix either no or inv; instead,
set false or (not vim.go.foo) respectively.
(let! scope name ?val)
(let! scope name ?flag ?val)
;; only in the scopes: "bo", "wo", "b", "w", or "t"
(let! scope ?id name ?flag ?val)scope: ("g"|"b"|"w"|"t"|"v"|"env"|"o"|"go"|"bo"|"wo"|"opt"|"opt_local"|"opt_global") One of the scopes.?id: (integer) Location handle, or 0 for current location. Only available in the scopes"b","w", or"t".name: (string) Option name. As long as the option name is bare-string, option name is case-insensitive; you can improve readability a bit with camelCase/PascalCase. Since:h {option}is also case-insensitive,(setlocal! :keywordPrg ":help")for fennel still makes sense. TypeKon an option name to open the vim help file at the tag.?flag: (+|^|-|?) Omittable flag in symbol. Set one of+,^,-, or?to append, prepend, remove, or get, option value. While?to get value is available in all thescope, the other flags are only available in the scopes"opt","opt_local", or"opt_global".?val: (boolean|number|string|table) New option value. If not provided, the value is supposed to betrue(experimental). It does not work with?idargument.
(let! :o :number)
(let! :opt_global :completeOpt [:menu :menuone :noselect])
(let! :bo :formatOptions [:1 :2 :c :B])
(let! :wo :listChars {:space :_ :tab: ">~"})
(let! :opt :colorColumn + :+1)
(let! :opt :rtp ^ [:/path/to/another/dir])
(let! :b :foo "bar")
(let! :bo :fileType "vim")
;; buf id is optional
(local buf (vim.api.nvim_get_current_buf))
(let! :b buf :baz "qux")
(let! :bo buf :fileType "lua")
(local scope :bo)
(let! scope :filetype :fennel)
(local opt :wrap)
(let! :opt opt false)
(local val :yes)
(let! :opt :signColumn val)is equivalent to
set number
setglobal completeopt=menu,menuone,noselect
call setbufvar(0, '&formatoptions', '12cB')
call setwinvar(0, '&listchars', 'space:_,tab:>~')
set colorcolumn+=+1
set rtp^=/path/to/another/dir
let b:foo = 'bar'
setlocal filetype=vim
let buf = bufnr()
call setbufvar(buf, 'baz', 'qux')
call setbufvar(buf, '&filetype', 'lua')
let val = 'yes'
let &signcolumn = val
let opt = 'wrap'
execute 'set no'. optvim.api.nvim_set_option_value("number", true, {})
vim.api.nvim_set_option_value("completeopt", "menu,menuone,noselect", {
scope = "global",
})
vim.api.nvim_set_option_value("formatoptions", "12cB", { buf = 0 })
vim.api.nvim_set_option_value("listchars", "space:_,tab:>~", { win = 0 })
vim.api.nvim_buf_set_var(0, "foo", "bar")
vim.api.nvim_buf_set_option(0, "filetype", "vim")
local buf vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_var(buf, "baz", "qux")
vim.api.nvim_buf_set_option(buf, "filetype", "lua")
local scope = "bo"
vim[scope].filetype = "fennel"
local opt = "wrap"
vim.api.nvim_set_option_value(opt, false, {})
local val = "yes"
vim.opt.signcolumn = val
-- Or just with Vim-Lua bridge wrapper,
vim.o.number = true
vim.opt_global.completeopt = { "menu", "menuone", "noselect" }
vim.bo.formatoptions = "12cB"
vim.wo.listchars = {
space = "_",
tab = ">~",
}
vim.opt.colorcolumn:append("+1")
vim.opt.rtp:prepend("/path/to/another/dir")
local scope = "bo"
vim[scope].filetype = "fennel"
local opt = "wrap"
vim.opt[opt] = false
local val = "yes"
vim.opt.signcolumn = val(The deprecation was withdrawn.)
Set, append, prepend, or remove, value to the option. Almost equivalent to
:set in Vim script.
Or you can use let! macro instead.
(set! name ?flag ?val)name: (string) Option name. As long as the option name is bare-string, option name is case-insensitive; you can improve readability a bit with camelCase/PascalCase. Since:h {option}is also case-insensitive,(setlocal! :keywordPrg ":help")for fennel still makes sense.?flag: (symbol) Omittable flag. Set one of+,^, or-to append, prepend, or remove, value to the option.?val: (boolean|number|string|table) New option value. If not provided, the value is supposed to betrue(experimental).
(The deprecation was withdrawn.)
Set, append, prepend, or remove, global value to the option. Almost equivalent
to :setglobal in Vim script.
Or you can use let! macro instead.
(setglobal! name ?flag ?val)See set! for the details.
(The deprecation was withdrawn.)
Set, append, prepend, or remove, local value to the option. Almost equivalent
to :setlocal in Vim script.
Or you can use let! macro instead.
(setlocal! name ?flag ?val)See set! for the details.
(The deprecation was withdrawn.)
Alias of setglobal!.
Or you can use let! macro instead.
(go! name value)(The deprecation was withdrawn.)
Set a buffer option value. :h nvim_buf_set_option().
Or you can use let! macro instead.
(bo! ?id name value)?id: (integer) Buffer handle, or 0 for current buffer.name: (string) Option name. Case-insensitive as long as in bare-string.value: (any) Option value.
(bo! :fileType :fennel)
(bo! 10 :bufType :nofile)is equivalent to
vim.api.nvim_buf_set_option(0, "filetype", "fennel")
vim.api.nvim_buf_set_option(10, "buftype", "nofile")
-- Or with `vim.bo`
vim.bo.filetype = "fennel"
vim.bo[10].buftype = "nofile"call setbufvar(0, '&filetype', 'fennel')
call setbufvar(10, '&buftype', 'nofile')(The deprecation was withdrawn.)
Set a window option value. :h nvim_win_set_option().
Or you can use let! macro instead.
(wo! ?id name value)?id: (integer) Window handle, or 0 for current window.name: (string) Option name. Case-insensitive as long as in bare-string.value: (any) Option value.
(wo! :number false)
(wo! 10 :signColumn :no)is equivalent to
vim.api.nvim_win_set_option(0, "number", false)
vim.api.nvim_win_set_option(10, "signcolumn", "no")
-- Or with `vim.wo`
vim.wo.number = false
vim.wo[10].signcolumn = "no"call setwinvar(0, '&number', v:false)
call setwinvar(10, '&signcolumn', 'no')(The deprecation was withdrawn.)
Set global (g:) editor variable.
Or you can use let! macro instead.
(g! name val)name: (string) Variable name.val: (any) Variable value.
(The deprecation was withdrawn.)
Set buffer-scoped (b:) variable for the current buffer. Can be indexed with
an integer to access variables for specific buffer.
Or you can use let! macro instead.
(b! ?id name val)?id: (integer) Buffer handle, or 0 for current buffer.name: (string) Variable name.val: (any) Variable value.
(b! :foo :bar)
(b! 8 :baz :qux)is equivalent to
vim.api.nvim_buf_set_var(0, "foo", "bar")
vim.api.nvim_buf_set_var(8, "foo", "bar")
-- Or with `vim.b`,
vim.b.foo = "bar"
vim.b[8].baz = "qux"let b:foo = 'bar'
call setbufvar(8, 'baz', 'qux')(The deprecation was withdrawn.)
Set window-scoped (w:) variable for the current window. Can be indexed with
an integer to access variables for specific window.
Or you can use let! macro instead.
(w! ?id name val)?id: (integer) Window handle, or 0 for current window.name: (string) Variable name.val: (any) Variable value.
(The deprecation was withdrawn.)
Set tabpage-scoped (t:) variable for the current tabpage. Can be indexed
with an integer to access variables for specific tabpage.
Or you can use let! macro instead.
(t! ?id name val)?id: (integer) Tabpage handle, or 0 for current tabpage.name: (string) Variable name.val: (any) Variable value.
(The deprecation was withdrawn.)
Set v: variable if not readonly.
Or you can use let! macro instead.
(v! name val)name: (string) Variable name.val: (any) Variable value.
(The deprecation was withdrawn.)
Set environment variable in the editor session.
Or you can use let! macro instead.
(env! name val)name: (string) Variable name. A bare-string can starts with$(ignored internally), which helpsgfjump to the path.val: (any) Variable value.
(env! :$NVIM_CACHE_HOME (vim.fn.stdpath :cache))
(env! :$NVIM_CONFIG_HOME (vim.fn.stdpath :config))
(env! :$NVIM_DATA_HOME (vim.fn.stdpath :data))
(env! :$NVIM_STATE_HOME (vim.fn.stdpath :state))
(env! :$PLUGIN_CACHE_HOME (vim.fs.normalize :$NVIM_CACHE_HOME/to/plugin/home))is equivalent to
vim.env.NVIM_CACHE_HOME = vim.fn.stdpath "cache"
vim.env.NVIM_CONFIG_HOME = vim.fn.stdpath "config"
vim.env.NVIM_DATA_HOME = vim.fn.stdpath "data"
vim.env.NVIM_STATE_HOME = vim.fn.stdpath "state"
vim.env.PLUGIN_CACHE_HOME = vim.fs.normalize "$NVIM_CACHE_HOME/to/plugin/home"let $NVIM_CACHE_HOME = stdpath('cache')
let $NVIM_CONFIG_HOME = stdpath('config')
let $NVIM_DATA_HOME = stdpath('data')
let $NVIM_STATE_HOME = stdpath('state')
let $PLUGIN_CACHE_HOME = expand('$NVIM_CACHE_HOME/to/plugin/home')Create a user command.
(&default-opts is available.)
(command! ?extra-opts name command ?api-opts)
(command! name ?extra-opts command ?api-opts)-
?extra-opts: (bare-sequence) Optional command attributes. Additional attributes:buffer: Create command in the buffer of the next value. Without 0 or no following number, create autocmd to current buffer by itself.
Note: The
:desckey can be omitted if the description is written in the first argument ofextra-optsand does not match against any other keys ofextra-opts. -
name: (string) Name of the new user command. It must begin with an uppercase letter. -
command: (string|function) Replacement command. -
?api-opts: (kv-table) Optional command attributes. The same asoptsfornvim_create_user_command().
(command! :SayHello "echo 'Hello world!'")
(command! :Salute [:bar :buffer :desc "Salute!"] #(print "Hello world!"))is equivalent to
command! SayHello echo 'Hello world!'
command! -bar -buffer Salute echo 'Hello world!'vim.api.nvim_create_user_command("SayHello", "echo 'Hello world!'", {})
vim.api.nvim_buf_create_user_command(0, "Salute", function()
print("Hello world!")
end, {
bar = true,
desc = "Salute!",
}):h feedkeys()
(feedkeys! string ?flags)(feedkeys! :foo<CR> :ni)
(feedkeys! :foo<lt>CR> :ni)is equivalent to
call feedkeys("foo\<CR>", 'ni')
call feedkeys('foo<CR>', 'ni')vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes("foo<CR>", true, true, true),
"ni",
false
)
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes("foo<lt>CR>", true, true, true),
"ni",
false
)Set a highlight group.
(&default-opts is available.)
(highlight! ?ns-id name api-opts)?ns-id: (number) Namespace id for this highlightnvim_create_namespace().name: (string) Highlight group name, e.g., "ErrorMsg".api-opts: (kv-table) Highlight definition map.:h nvim_set_hl(). As long as the keys are bare-strings,ctermattribute map can containfg/bginstead ofctermfg/ctermbgkey.
(highlight! :Foo {:fg "#8d9eb2"
:bold true
:italic true
:ctermfg 103
:cterm {:bold true :italic true}})
;; or (as long as `api-opts` keys are bare-strings)
(highlight! :Foo {:fg "#8d9eb2"
:bold true
:italic true
:cterm {:fg 103 :bold true :italic true}})is equivalent to
highlight! Foo guifg=#8d9eb2 gui=bold,italic ctermfg=103 cterm=bold,italicvim.api.nvim_set_hl(0, "Foo", {
fg = "#8d9eb2",
ctermfg = 103,
bold = true,
italic = true,
cterm = {
bold = true,
italic = true,
},
})An alias of highlight!.
(&default-opts is available.)
This project nvim-laurel follows Semantic Versioning 2.0.0. It should issue at least one version prior to a version where deprecated features are removed, i.e., before any breaking changes.
If you were unfortunately in trouble due to some breaking changes, please read The Last Resort. If you get deprecation notices, g:laurel_deprecated and its guidance would help you.
It's strongly recommended to manage your vimrc by version control system like
git; otherwise, breaking changes on nvim-laurel could lead you to a dead end
where you could not launch nvim with any part of your vimrc until you resolve
them.
Before introducing how to avoid breaking changes, it is necessary to describe how to resolve the dead end, where you have few or none of Lua files because you have unexpectedly recompiled all the Fennel files that includes some features removed from nvim-laurel. Breaking Changes could prevent you from launching nvim itself. In this case, you have two choices:
-
Downgrade nvim-laurel according to Semantic Versioning 2.0.0; then, update your vimrc with deprecation notices of nvim-laurel. You should know the path where you download nvim-laurel: if you have lazy.nvim manage the version of nvim-laurel, it should be downloaded to
stdpath('config') .. '/lazy/nvim-laurel'by default; packer.nvim, tostdpath('data') .. '/pack/packer/start/nvim-laurel'. Downgrade it bygit checkout <tag>in your local nvim-laurel repository. -
Update your vimrcs anyway apart from your vimrc with the -u flag, e.g., run
nvim -u NONEin your terminal.
This variable is designed to help you update your codes with Quickfix. It will collect lines where deprecated features are detected.
Note: It's strongly recommended to compile your Fennel codes with
--correlate flag because the detection runs on compiled Lua codes at
runtime.
-
Make sure you can update your vimrcs on stable environment: launch multiple instances of Neovim which have already loaded your stable config, i.e., detached from the unstable vimrcs about to undergoing changes.
-
Update deprecated features
This is a list of useful commands:
Here is a basic example to rename deprecated macro
old-macroto new compatible macronew-macro. Please adjust commands yourself as necessary. You don't have to do it in the smartest way, of course. Slow and steady wins the race.:cexpr g:laurel_deprecated " Reset Quickfix list. :packadd cfilter " Enable builtin cfilter. `:h :Cfilter` for the details. :Cfilter /old-macro/ " Pick up related detections. :cfdo! %s/(old-macro /(new-macro /gec " Roughly update macro names. :cfdo update
-
Nowadays, your vimrcs are supposed to be under git control...
:cd ~/.config/nvim " Make sure current directory is in your config repository. :!git reset --mixed HEAD :cfdo !git add % :!git commit -m 'refactor(laurel): update macros'
See CHANGELOG.md, including the previous breaking changes.