Using lua api (nvim) we can do:
line, col = unpack(vim.api.nvim_win_get_cursor(0))
vim.cmd [[ normal 4X]]
vim.cmd [[ normal u]]
vim.api.nvim_win_set_cursor({0}, {line , col})
The first line saves line and column, the second line erases 4 chars, the third one gets back one action and the last one restores the line and cursor positions.
Your question helped me improve a function called "preserve":
function _G.preserve(cmd)
local cmd = string.format('keepjumps keeppatterns execute %q', cmd)
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
vim.api.nvim_command(cmd)
local lastline = vim.fn.line('$')
if line > lastline then
line = lastline
end
vim.api.nvim_win_set_cursor({0}, {line , col})
end
The function win_get_cursor
gives us more precise information. you could also create marks like @maxim-kim suggested.
As we can use this function to squeeze blank lines we are using an if statement to ensure the line will neve be beond the buffer last line.
Here a function to squeeze blank lines using the above function, in this case I placed the function at ~/.config/nvim/lua/tools.lua
local M = {}
M.squeeze_blank_lines = function()
-- references: https://vi.stackexchange.com/posts/26304/revisions
local old_query = vim.fn.getreg('/') -- save search register
preserve('sil! 1,.s/^\\n\\{2,}/\\r/gn') -- set current search count number
local result = vim.fn.searchcount({maxcount = 1000, timeout = 500}).current
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
preserve('sil! keepp keepj %s/^\\n\\{2,}/\\r/ge')
preserve('sil! keepp keepj %s/\\v($\\n\\s*)+%$/\\r/e')
if result > 0 then
vim.api.nvim_win_set_cursor({0}, {(line - result), col})
end
vim.fn.setreg('/', old_query) -- restore search register
end
return M
Some more features that make use of the "preserve"
vim.cmd([[cnoreab cls Cls]])
vim.cmd([[command! Cls lua preserve('%s/\\s\\+$//ge')]])
vim.cmd([[command! Reindent lua preserve("sil keepj normal! gg=G")]])
Now you can use cls
to remove trailing spaces, Reindent
, and many other things you came up with.
-- keep cursor position when joinig lines
-- undo keeps cursor position (at least line)
local opts = { noremap=true, silent=true }
buf_set_keymap('n', 'J', ':lua preserve(":join")<cr>', opts)
buf_set_keymap('n', 'u', ':lua preserve(":undo")<cr>', opts)
buf_set_keymap('n', '<c-s>', [[:lua preserve("%s/\\s\\+$//ge")<cr>]])
With all these things your macros could become horrible, so I have an alias to open vim with not plugins or autocommands:
alias vinone="nvim -u NONE -U NONE -N -i NONE -c 'nnoremap <Space> /'"
I am mentioning this because sometimes we fix one thing and cause other problems. Read also about noautocmd
:sil! argdo :noautocmd norm! @a