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,
:foobar
is abare-string
.(.. :foo :bar)
is not abare-string
.[:foo :bar]
is abare-sequence
and also abare-string[]
.[baz]
wherebaz
is either symbol or list is abare-sequence
, but not abare-string[]
.(icollect [_ val (ipairs [:foo :bar])] val)
is neither abare-sequence
norbare-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-opts
is set totrue
by key itself; the other keys expects the next items as their values respectively. - To set
false
to boolean key/value, set it inapi-opts
instead.
- It is intended as shorthand; for complicated usage, use
api-opts
instead or use them together. - It could accept some additional keys which are unavailable in
api-opts
.
The symbols are reserved to be used as arguments in list
s 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
macro
to be expanded in the same file, quote the entirelist
of 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
function
to 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 an existing augroup.
(&default-opts
is available.)
(augroup! name ?api-opts-for-augroup) ; Only this format returns the augroup id.
(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. -
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 setpattern
in symbol or list, set it in eitherextra-opts
orapi-opts
instead. 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.
-
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
&vim
symbol just before the callback. - Name the first symbol for the callback to match
^<.+>
in Lua pattern.
Note: Set
vim.fn.foobar
to call Vim script functionfoobar
without table argument fromnvim_create_autocmd()
; on the other hand, set#(vim.fn.foobar $)
to callfoobar
with the table argument. -
?api-opts
: (kv-table):h nvim_create_autocmd()
.
(augroup! :sample-augroup
[: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))
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
local 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(args)
vim.fn["baz#qux"](args.match)
end,
})
vim.api.nvim_create_autocmd("LspAttach", {
group = id,
callback = function(args)
vim.api.nvim_create_autocmd("CursorHold", {
group = args.group,
buffer = args.buf,
callback = vim.lsp.buf.document_highlight,
})
end,
})
c.f. autocmd!
Create an autocmd.
(&default-opts
is available.)
(autocmd! events api-opts) ; Just as an alias of `nvim_create_autocmd()`.
(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 tonil
to defineautocmd
s 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:nox
instead of[:n :o :x]
. -
?extra-opts
: (bare-sequence) Additional option:buffer
: (number?) Maplhs
to a buffer of the next value. With0
or with no following value, create autocmd to current buffer.literal
: Disablereplace_keycodes
, which is automatically enabled whenexpr
is set inextra-opts
.remap
: Make the mapping recursive. This is the inverse of the "noremap" option fromnvim_set_keymap()
.wait
: Disablenowait
in extra-opts; will NOT disablenowait
in api-opts. Useful in wrapper macro which setnowait
with&default-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
&vim
symbol 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)
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 scope: "opt", "opt_local", or "opt_global"
(let! scope ?id name ?flag ?val) ; only in the scope: "b", "w", or "t"
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. TypeK
on an option name to open the vim helpfile at the tag.?flag
: (symbol) Omittable flag. Set one of+
,^
, or-
to append, prepend, or remove, value to the option. 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?id
argument.
(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])
(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 val = 'yes'
let &signcolumn = val
let opt = 'wrap'
execute 'set no'. opt
vim.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 })
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
(Subject to be deprecated in favor of let!
)
Set, append, prepend, or remove, value to the option. Almost equivalent to
:set
in Vim script.
(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).
(Subject to be deprecated in favor of let!
)
Set, append, prepend, or remove, global value to the option. Almost equivalent
to :setglobal
in Vim script.
(setglobal! name ?flag ?val)
See set!
for the details.
(Subject to be deprecated in favor of let!
)
Set, append, prepend, or remove, local value to the option. Almost equivalent
to :setlocal
in Vim script.
(setlocal! name ?flag ?val)
See set!
for the details.
(Subject to be deprecated in favor of let!
)
Alias of setglobal!
.
(go! name value)
(Subject to be deprecated in favor of let!
)
Set a buffer option value. :h nvim_buf_set_option()
.
(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')
(Subject to be deprecated in favor of let!
)
Set a window option value. :h nvim_win_set_option()
.
(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')
(Subject to be deprecated in favor of let!
)
Set global (g:
) editor variable.
(g! name val)
name
: (string) Variable name.val
: (any) Variable value.
(Subject to be deprecated in favor of let!
)
Set buffer-scoped (b:
) variable for the current buffer. Can be indexed with
an integer to access variables for specific buffer.
(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')
(Subject to be deprecated in favor of let!
)
Set window-scoped (w:
) variable for the current window. Can be indexed with
an integer to access variables for specific window.
(w! ?id name val)
?id
: (integer) Window handle, or 0 for current window.name
: (string) Variable name.val
: (any) Variable value.
(Subject to be deprecated in favor of let!
)
Set tabpage-scoped (t:
) variable for the current tabpage. Can be indexed
with an integer to access variables for specific tabpage.
(t! ?id name val)
?id
: (integer) Tabpage handle, or 0 for current tabpage.name
: (string) Variable name.val
: (any) Variable value.
(Subject to be deprecated in favor of let!
)
Set v:
variable if not readonly.
(v! name val)
name
: (string) Variable name.val
: (any) Variable value.
(Subject to be deprecated in favor of let!
)
Set environment variable in the editor session.
(env! name val)
name
: (string) Variable name. A bare-string can starts with$
(ignored internally), which helpsgf
jump 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.
-
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 asopts
fornvim_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,cterm
attribute map can containfg
/bg
instead ofctermfg
/ctermbg
key.
(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,italic
nvim_set_nl(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 NONE
in 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-macro
to 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.