diff options
author | Gregory Anders <8965202+gpanders@users.noreply.github.com> | 2023-11-08 09:33:37 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-08 09:33:37 -0600 |
commit | 08847a9ea15a50aba041ee621d71b9884f5fea97 (patch) | |
tree | e6f49ffb4ae072186126968f85d99cd18e9a9e98 | |
parent | 1b0fd377aba3b4d076e4dbfb5adb96866a4982d1 (diff) | |
download | rneovim-08847a9ea15a50aba041ee621d71b9884f5fea97.tar.gz rneovim-08847a9ea15a50aba041ee621d71b9884f5fea97.tar.bz2 rneovim-08847a9ea15a50aba041ee621d71b9884f5fea97.zip |
refactor: move defaults into separate module (#25929)
Move default mappings and autocommands into a separate module and add
comments and docstrings to document each of the defaults.
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 166 | ||||
-rw-r--r-- | runtime/lua/vim/_editor.lua | 150 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 14 | ||||
-rw-r--r-- | src/nvim/main.c | 9 |
5 files changed, 184 insertions, 158 deletions
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua new file mode 100644 index 0000000000..c1b50e6950 --- /dev/null +++ b/runtime/lua/vim/_defaults.lua @@ -0,0 +1,166 @@ +--- Default mappings +do + --- Default maps for * and # in visual mode. + --- + --- See |v_star-default| and |v_#-default| + do + local function region_chunks(region) + local chunks = {} + local maxcol = vim.v.maxcol + for line, cols in vim.spairs(region) do + local endcol = cols[2] == maxcol and -1 or cols[2] + local chunk = vim.api.nvim_buf_get_text(0, line, cols[1], line, endcol, {})[1] + table.insert(chunks, chunk) + end + return chunks + end + + local function _visual_search(cmd) + assert(cmd == '/' or cmd == '?') + local region = vim.region( + 0, + '.', + 'v', + vim.api.nvim_get_mode().mode:sub(1, 1), + vim.o.selection == 'inclusive' + ) + local chunks = region_chunks(region) + local esc_chunks = vim + .iter(chunks) + :map(function(v) + return vim.fn.escape(v, cmd == '/' and [[/\]] or [[?\]]) + end) + :totable() + local esc_pat = table.concat(esc_chunks, [[\n]]) + local search_cmd = ([[%s\V%s%s]]):format(cmd, esc_pat, '\n') + return '\27' .. search_cmd + end + + vim.keymap.set('x', '*', function() + return _visual_search('/') + end, { desc = ':help v_star-default', expr = true, silent = true }) + vim.keymap.set('x', '#', function() + return _visual_search('?') + end, { desc = ':help v_#-default', expr = true, silent = true }) + end + + --- Map Y to y$. This mimics the behavior of D and C. See |Y-default| + vim.keymap.set('n', 'Y', 'y$', { desc = ':help Y-default' }) + + --- Use normal! <C-L> to prevent inserting raw <C-L> when using i_<C-O>. #17473 + --- + --- See |CTRL-L-default| + vim.keymap.set('n', '<C-L>', '<Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>', { + desc = ':help CTRL-L-default', + }) + + --- Set undo points when deleting text in insert mode. + --- + --- See |i_CTRL-U-default| and |i_CTRL-W-default| + vim.keymap.set('i', '<C-U>', '<C-G>u<C-U>', { desc = ':help i_CTRL-U-default' }) + vim.keymap.set('i', '<C-W>', '<C-G>u<C-W>', { desc = ':help i_CTRL-W-default' }) + + --- Use the same flags as the previous substitution with &. + --- + --- Use : instead of <Cmd> so that ranges are supported. #19365 + --- + --- See |&-default| + vim.keymap.set('n', '&', ':&&<CR>', { desc = ':help &-default' }) + + --- Map |gx| to call |vim.ui.open| on the identifier under the cursor + do + -- TODO: use vim.region() when it lands... #13896 #16843 + local function get_visual_selection() + local save_a = vim.fn.getreginfo('a') + vim.cmd([[norm! "ay]]) + local selection = vim.fn.getreg('a', 1) + vim.fn.setreg('a', save_a) + return selection + end + + local function do_open(uri) + local _, err = vim.ui.open(uri) + if err then + vim.notify(err, vim.log.levels.ERROR) + end + end + + local gx_desc = + 'Opens filepath or URI under cursor with the system handler (file explorer, web browser, …)' + vim.keymap.set({ 'n' }, 'gx', function() + do_open(vim.fn.expand('<cfile>')) + end, { desc = gx_desc }) + vim.keymap.set({ 'x' }, 'gx', function() + do_open(get_visual_selection()) + end, { desc = gx_desc }) + end +end + +--- Default menus +do + --- Right click popup menu + -- TODO VimScript, no l10n + vim.cmd([[ + aunmenu * + vnoremenu PopUp.Cut "+x + vnoremenu PopUp.Copy "+y + anoremenu PopUp.Paste "+gP + vnoremenu PopUp.Paste "+P + vnoremenu PopUp.Delete "_x + nnoremenu PopUp.Select\ All ggVG + vnoremenu PopUp.Select\ All gg0oG$ + inoremenu PopUp.Select\ All <C-Home><C-O>VG + anoremenu PopUp.-1- <Nop> + anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> + ]]) +end + +--- Default autocommands. See |default-autocmds| +do + local nvim_terminal_augroup = vim.api.nvim_create_augroup('nvim_terminal', {}) + vim.api.nvim_create_autocmd('BufReadCmd', { + pattern = 'term://*', + group = nvim_terminal_augroup, + desc = 'Treat term:// buffers as terminal buffers', + nested = true, + command = "if !exists('b:term_title')|call termopen(matchstr(expand(\"<amatch>\"), '\\c\\mterm://\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), {'cwd': expand(get(matchlist(expand(\"<amatch>\"), '\\c\\mterm://\\(.\\{-}\\)//'), 1, ''))})", + }) + + vim.api.nvim_create_autocmd({ 'TermClose' }, { + group = nvim_terminal_augroup, + desc = 'Automatically close terminal buffers when started with no arguments and exiting without an error', + callback = function(args) + if vim.v.event.status == 0 then + local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel) + local argv = info.argv or {} + if #argv == 1 and argv[1] == vim.o.shell then + vim.cmd({ cmd = 'bdelete', args = { args.buf }, bang = true }) + end + end + end, + }) + + vim.api.nvim_create_autocmd('CmdwinEnter', { + pattern = '[:>]', + desc = 'Limit syntax sync to maxlines=1 in the command window', + group = vim.api.nvim_create_augroup('nvim_cmdwin', {}), + command = 'syntax sync minlines=1 maxlines=1', + }) + + vim.api.nvim_create_autocmd('SwapExists', { + pattern = '*', + desc = 'Skip the swapfile prompt when the swapfile is owned by a running Nvim process', + group = vim.api.nvim_create_augroup('nvim_swapfile', {}), + callback = function() + local info = vim.fn.swapinfo(vim.v.swapname) + local user = vim.uv.os_get_passwd().username + local iswin = 1 == vim.fn.has('win32') + if info.error or info.pid <= 0 or (not iswin and info.user ~= user) then + vim.v.swapchoice = '' -- Show the prompt. + return + end + vim.v.swapchoice = 'e' -- Choose "(E)dit". + vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid)) + end, + }) +end diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 0bdf0c90a5..98a1ce79ed 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1031,156 +1031,6 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) return displayed and msg or nil end ---- Creates builtin mappings (incl. menus). ---- Called once on startup. -function vim._init_default_mappings() - -- mappings - - local function region_chunks(region) - local chunks = {} - local maxcol = vim.v.maxcol - for line, cols in vim.spairs(region) do - local endcol = cols[2] == maxcol and -1 or cols[2] - local chunk = vim.api.nvim_buf_get_text(0, line, cols[1], line, endcol, {})[1] - table.insert(chunks, chunk) - end - return chunks - end - - local function _visual_search(cmd) - assert(cmd == '/' or cmd == '?') - local region = vim.region( - 0, - '.', - 'v', - vim.api.nvim_get_mode().mode:sub(1, 1), - vim.o.selection == 'inclusive' - ) - local chunks = region_chunks(region) - local esc_chunks = vim - .iter(chunks) - :map(function(v) - return vim.fn.escape(v, cmd == '/' and [[/\]] or [[?\]]) - end) - :totable() - local esc_pat = table.concat(esc_chunks, [[\n]]) - local search_cmd = ([[%s\V%s%s]]):format(cmd, esc_pat, '\n') - return '\27' .. search_cmd - end - - local function map(mode, lhs, rhs) - vim.keymap.set(mode, lhs, rhs, { desc = 'Nvim builtin' }) - end - - map('n', 'Y', 'y$') - -- Use normal! <C-L> to prevent inserting raw <C-L> when using i_<C-O>. #17473 - map('n', '<C-L>', '<Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>') - map('i', '<C-U>', '<C-G>u<C-U>') - map('i', '<C-W>', '<C-G>u<C-W>') - vim.keymap.set('x', '*', function() - return _visual_search('/') - end, { desc = ':help v_star-default', expr = true, silent = true }) - vim.keymap.set('x', '#', function() - return _visual_search('?') - end, { desc = ':help v_#-default', expr = true, silent = true }) - -- Use : instead of <Cmd> so that ranges are supported. #19365 - map('n', '&', ':&&<CR>') - - -- gx - - -- TODO: use vim.region() when it lands... #13896 #16843 - local function get_visual_selection() - local save_a = vim.fn.getreginfo('a') - vim.cmd([[norm! "ay]]) - local selection = vim.fn.getreg('a', 1) - vim.fn.setreg('a', save_a) - return selection - end - - local function do_open(uri) - local _, err = vim.ui.open(uri) - if err then - vim.notify(err, vim.log.levels.ERROR) - end - end - - local gx_desc = - 'Opens filepath or URI under cursor with the system handler (file explorer, web browser, …)' - vim.keymap.set({ 'n' }, 'gx', function() - do_open(vim.fn.expand('<cfile>')) - end, { desc = gx_desc }) - vim.keymap.set({ 'x' }, 'gx', function() - do_open(get_visual_selection()) - end, { desc = gx_desc }) - - -- menus - - -- TODO VimScript, no l10n - vim.cmd([[ - aunmenu * - vnoremenu PopUp.Cut "+x - vnoremenu PopUp.Copy "+y - anoremenu PopUp.Paste "+gP - vnoremenu PopUp.Paste "+P - vnoremenu PopUp.Delete "_x - nnoremenu PopUp.Select\ All ggVG - vnoremenu PopUp.Select\ All gg0oG$ - inoremenu PopUp.Select\ All <C-Home><C-O>VG - anoremenu PopUp.-1- <Nop> - anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> - ]]) -end - -function vim._init_default_autocmds() - local nvim_terminal_augroup = vim.api.nvim_create_augroup('nvim_terminal', {}) - vim.api.nvim_create_autocmd({ 'BufReadCmd' }, { - pattern = 'term://*', - group = nvim_terminal_augroup, - nested = true, - command = "if !exists('b:term_title')|call termopen(matchstr(expand(\"<amatch>\"), '\\c\\mterm://\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), {'cwd': expand(get(matchlist(expand(\"<amatch>\"), '\\c\\mterm://\\(.\\{-}\\)//'), 1, ''))})", - }) - vim.api.nvim_create_autocmd({ 'TermClose' }, { - group = nvim_terminal_augroup, - desc = 'Automatically close terminal buffers when started with no arguments and exiting without an error', - callback = function(args) - if vim.v.event.status == 0 then - local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel) - local argv = info.argv or {} - if #argv == 1 and argv[1] == vim.o.shell then - vim.cmd({ cmd = 'bdelete', args = { args.buf }, bang = true }) - end - end - end, - }) - - vim.api.nvim_create_autocmd({ 'CmdwinEnter' }, { - pattern = '[:>]', - group = vim.api.nvim_create_augroup('nvim_cmdwin', {}), - command = 'syntax sync minlines=1 maxlines=1', - }) - - vim.api.nvim_create_autocmd({ 'SwapExists' }, { - pattern = '*', - group = vim.api.nvim_create_augroup('nvim_swapfile', {}), - callback = function() - local info = vim.fn.swapinfo(vim.v.swapname) - local user = vim.uv.os_get_passwd().username - local iswin = 1 == vim.fn.has('win32') - if info.error or info.pid <= 0 or (not iswin and info.user ~= user) then - vim.v.swapchoice = '' -- Show the prompt. - return - end - vim.v.swapchoice = 'e' -- Choose "(E)dit". - vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid)) - end, - }) -end - -function vim._init_defaults() - vim._init_default_mappings() - vim._init_default_autocmds() -end - require('vim._options') -- Remove at Nvim 1.0 diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index e881214f40..cc5fb25b1e 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -290,6 +290,7 @@ set(LUA_LOADER_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/loader.lua) set(LUA_INSPECT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/inspect.lua) set(LUA_FS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/fs.lua) set(LUA_F_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/F.lua) +set(LUA_DEFAULTS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_defaults.lua) set(LUA_OPTIONS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_options.lua) set(LUA_FILETYPE_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/filetype.lua) set(LUA_INIT_PACKAGES_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_init_packages.lua) @@ -535,6 +536,7 @@ add_custom_command( ${LUA_F_MODULE_SOURCE} "vim.F" ${LUA_KEYMAP_MODULE_SOURCE} "vim.keymap" ${LUA_LOADER_MODULE_SOURCE} "vim.loader" + ${LUA_DEFAULTS_MODULE_SOURCE} "vim._defaults" ${LUA_OPTIONS_MODULE_SOURCE} "vim._options" ${LUA_SHARED_MODULE_SOURCE} "vim.shared" DEPENDS @@ -547,6 +549,7 @@ add_custom_command( ${LUA_F_MODULE_SOURCE} ${LUA_KEYMAP_MODULE_SOURCE} ${LUA_LOADER_MODULE_SOURCE} + ${LUA_DEFAULTS_MODULE_SOURCE} ${LUA_OPTIONS_MODULE_SOURCE} ${LUA_SHARED_MODULE_SOURCE} VERBATIM diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index b389f33d8d..36cb8a6756 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2291,3 +2291,17 @@ plain: kv_printf(str, "<Lua %d>", ref); return str.items; } + +/// Execute the vim._defaults module to set up default mappings and autocommands +void nlua_init_defaults(void) +{ + lua_State *const L = global_lstate; + assert(L); + + lua_getglobal(L, "require"); + lua_pushstring(L, "vim._defaults"); + if (nlua_pcall(L, 1, 0)) { + os_errmsg(lua_tostring(L, -1)); + os_errmsg("\n"); + } +} diff --git a/src/nvim/main.c b/src/nvim/main.c index 433b735c2e..42c98ead66 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -413,14 +413,7 @@ int main(int argc, char **argv) open_script_files(¶ms); - // Default mappings (incl. menus) & autocommands - Error err = ERROR_INIT; - Object o = NLUA_EXEC_STATIC("return vim._init_defaults()", - (Array)ARRAY_DICT_INIT, &err); - assert(!ERROR_SET(&err)); - api_clear_error(&err); - assert(o.type == kObjectTypeNil); - api_free_object(o); + nlua_init_defaults(); TIME_MSG("init default mappings & autocommands"); |