Non-buggy Keymap to Search and Replace Word Under Cursor

Goal:
I’d like to create a keymap in Neovim to search and replace the word under my cursor.

Attempts:
According to this Vim Wiki, you can use something like:
:nnoremap <Leader>s :%s/\<<C-r><C-w>\>/

Using the Whichkey plugin, most of my mappings look like, e.g.:
["c"] = { "<cmd>bdelete<CR>", "Close Buffer" }
where the leader is <Space> (defined elsewhere) and <Space>+c here would run the command bdelete.

I initially created a keymap like:
[":"] = { "<cmd>%s/<C-r><C-w>/", "Change Word" }
but when I’d run it, I’d get error E5520 because apparently <cmd> commands must terminate with <CR>. In this case, I don’t want to terminate with <CR> because I want to be able to type the replacement text.

Next, I changed the keymap to use : instead of <cmd>, e.g.:
[":"] = { ":%s/<C-r><C-w>/", "Change Word" }
This technically works, but it’s a little buggy. First, it seems somewhat laggy compared to <cmd>. And second, when I run it, the command doesn’t get displayed until I move the cursor.

bugginess

Does anyone have any suggestions about this?

What about using vim.fn.expand("<cword>")?

Interesting, any idea how to use vim.fn.expand(<cword>) in a keymap?

I tried:
[":"] = { ":%s/vim.fn.expand('<cword>')/", "Change Word" }
and
[":"] = { ":%s/" .. vim.fn.expand('<cword>') .. "/", "Change Word" }

but neither worked.

Here is something I use to open current words help file.

open_help_tab = function(help_cmd, topic)
	cmd.tabe()
	local winnr = api.nvim_get_current_win()
	cmd(help_cmd .. " " .. topic)
	api.nvim_win_close(winnr, false)
end

help_select = function()
	ui.input({ prompt = "Open help for> " }, function(input)
		if not input then
			return
		end
		open_help_tab("help", input)
	end)
end

help_word = function()
	local current_word = u.current_word()
	open_help_tab("help", current_word)
end

u.current_word() is just a helper function to expand cword

Then you can create a key map that calls a lua function

I actually create a user command first then I keymap that. That way I can use the user command if I want or just use key binding.

My config: GitHub - catgoose/nvim

1 Like

You can use the following keymap:

vim.keymap.set("n", "<Leader>c", [[:%s/<C-r><C-w>//g<Left><Left>]])
  • <C-r><C-w>: Pastes the word under the cursor into the search field.
  • g flag: Replaces all occurrences of the word in each line.
  • <Left><Left>: Moves cursor back two spaces for you to type the replacement.
1 Like

Thanks for the suggestion @mroavi!

What you proposed is essentially what I had (and seems to be subject to the same issues), though I like the addition of /g<Left><Left> which I didn’t know about.

In my case for whatever reason, I had to remove the brackets because they were causing issues with the keymap.

Hmm, I see. On my computer, it works great. You could try testing this mapping on a clean Neovim instance (nvim --clean) and see if the issues are still there. If not, then it’s likely that the mapping clashes with other plugins or configurations.

To start a clean Neovim instance, you can run nvim --clean from the terminal. Once Neovim is open, you can define the mapping by entering the following command:

:lua vim.keymap.set("n", "<Leader>c", [[:%s/<C-r><C-w>//g<Left><Left>]])

After defining the mapping, try it out to see if the issue is still there.

1 Like

Thanks again @mroavi!

Your command worked perfectly in a clean instance of nvim so there must be something screwy with how I’ve configured whichkey or something. I’ll investigate. Thanks for the help!

1 Like