From f39ca5df232cb6e70b1932b7444840acf42cf87b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 5 Jul 2023 19:47:43 +0200 Subject: refactor(defaults): use vim.region for visual star (*,#) Problem: The parent commit added a new vim.get_visual_selection() function to improve visual star. But that is redundant with vim.region(). Any current limitations of vim.region() should be fixed instead of adding a new function. Solution: Delete vim.get_visual_selection(). Use vim.region() to get the visual selection. TODO: fails with visual "block" selections. --- runtime/lua/vim/_editor.lua | 107 ++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 74 deletions(-) (limited to 'runtime/lua/vim/_editor.lua') diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index e00d512a2a..6f701e9ae9 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -535,55 +535,6 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive) return region end ---- Gets the content of the visual selection. ---- ---- The result is either a string or, if {list} is `true`, a list of strings. ---- If not in any |visual-mode|, `nil` is returned. ---- ---- @param list boolean|nil ---- Return a list of strings instead of a string. See |getreg()|. ---- Defaults to `false`. ---- @param append_empty boolean|nil ---- Append an empty string to the result when in |linewise-visual| mode and {list} is `true`. ---- This will preserve the trailing newline of the selection when the result is concatenated with `"\n"`. ---- Defaults to `false`. ---- @return string|table -function vim.get_visual_selection(list, append_empty) - list = list or false - append_empty = append_empty or false - - local mode = vim.api.nvim_get_mode().mode - if mode ~= 'v' and mode ~= 'V' and mode:byte() ~= 22 then - return nil - end - - local reg_name_unnamed = '"' - local reg_name_yank = '0' - - local reg_info_unnamed = vim.fn.getreginfo(reg_name_unnamed) - local reg_info_yank = vim.fn.getreginfo(reg_name_yank) - local opt_clipboard = vim.o.clipboard - local opt_report = vim.o.report - - vim.o.clipboard = '' - vim.o.report = vim.v.maxcol - - vim.api.nvim_feedkeys('y', 'nx', false) - - local yanked = vim.fn.getreg(reg_name_yank, 1, list) - - vim.fn.setreg(reg_name_unnamed, reg_info_unnamed) - vim.fn.setreg(reg_name_yank, reg_info_yank) - vim.o.clipboard = opt_clipboard - vim.o.report = opt_report - - if list and append_empty and mode == 'V' then - table.insert(yanked, '') - end - - return yanked -end - --- Defers calling {fn} until {timeout} ms passes. --- --- Use to do a one-shot timer that calls {fn} @@ -1034,7 +985,7 @@ end --- Defaults to "Nvim". ---@param backtrace boolean|nil Prints backtrace. Defaults to true. --- ----@return Deprecated message, or nil if no message was shown. +---@return string|nil # Deprecated message, or nil if no message was shown. function vim.deprecate(name, alternative, version, plugin, backtrace) local msg = ('%s is deprecated'):format(name) plugin = plugin or 'Nvim' @@ -1049,9 +1000,7 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) if displayed and backtrace ~= false then vim.notify(debug.traceback('', 2):sub(2), vim.log.levels.WARN) end - if displayed then - return msg - end + return displayed and msg or nil end --- Create builtin mappings (incl. menus). @@ -1060,27 +1009,37 @@ function vim._init_default_mappings() -- mappings ---@private - local function _search_for_visual_selection(search_prefix) - if search_prefix ~= '/' and search_prefix ~= '?' then - return + 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 - -- Escape these characters - local replacements = { - [search_prefix] = [[\]] .. search_prefix, - [ [[\]] ] = [[\\]], - ['\t'] = [[\t]], - ['\n'] = [[\n]], - } - local pattern = '[' .. table.concat(vim.tbl_keys(replacements), '') .. ']' - local visual_selection = vim.get_visual_selection(false) - local escaped_visual_selection = string.gsub(visual_selection, pattern, replacements) - local search_cmd = search_prefix .. [[\V]] .. escaped_visual_selection .. '\n' + return chunks + end + + ---@private + local function _visual_search(cmd) + assert(cmd == '/' or cmd == '?') + vim.api.nvim_feedkeys('\27', 'nx', true) -- Escape visual mode. + local region = vim.region(0, "'<", "'>", vim.fn.visualmode(), vim.o.selection == 'inclusive') + local chunks = region_chunks(region) + local esc_chunks = vim + .iter(chunks) + :map(function(v) + return vim.fn.escape(v, [[/\]]) + end) + :totable() + local esc_pat = table.concat(esc_chunks, [[\n]]) + local search_cmd = ([[%s\V%s%s]]):format(cmd, esc_pat, '\n') vim.api.nvim_feedkeys(search_cmd, 'nx', true) end ---@private local function map(mode, lhs, rhs) - vim.keymap.set(mode, lhs, rhs, { noremap = true, desc = 'Nvim builtin' }) + vim.keymap.set(mode, lhs, rhs, { desc = 'Nvim builtin' }) end map('n', 'Y', 'y$') @@ -1088,12 +1047,12 @@ function vim._init_default_mappings() map('n', '', 'nohlsearchdiffupdatenormal! ') map('i', '', 'u') map('i', '', 'u') - map('x', '*', function() - _search_for_visual_selection('/') - end) - map('x', '#', function() - _search_for_visual_selection('?') - end) + vim.keymap.set('x', '*', function() + _visual_search('/') + end, { desc = 'Nvim builtin', silent = true }) + vim.keymap.set('x', '#', function() + _visual_search('?') + end, { desc = 'Nvim builtin', silent = true }) -- Use : instead of so that ranges are supported. #19365 map('n', '&', ':&&') -- cgit