Skip to main content
3 of 4
added 632 characters in body
SergioAraujo
  • 1.2k
  • 11
  • 13

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)

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
SergioAraujo
  • 1.2k
  • 11
  • 13