Add nvim hop post

This commit is contained in:
Kaan Barmore-Genc 2025-02-15 19:26:37 +00:00
parent 51c0ca17f1
commit 21bda7be53

View file

@ -0,0 +1,49 @@
---
title: '"Jump to matching first letter of the word" in neovim'
date: 2025-02-15T13:00:00Z
description: 'hop.nvim lets you jump to the first letter of a word, but highlights all words. I put together some code to only highlight words starting with a particular letter.'
---
I've been using neovim more and more recently. I first started experimenting with using vim, then just installed nvim, and now I'm using it with VSCode through [VSCode Neovim](https://marketplace.visualstudio.com/items?itemName=asvetliakov.vscode-neovim).
Now, I really like coding without touching my mouse at all, but I dislike navigating code by line numbers. So I installed [hop.nvim](https://github.com/smoka7/hop.nvim/tree/efe58182f71fbe592f82fb211ab026f2819e855d), which highlights points in the file with letters, and lets you jump to any highlighted point by typing some letters. You can have it literally highlight every character in the file, but it also comes with cool features like highlighting all the first letters of words.
I had one complaint with that though: when you highlight all words, that means you'll need to type 2 or 3 characters to get to the word you want.
Or you can have it highlight all letters matching a letter you typed, but that also ends up with a lot of matches and might require you to type 2-3 characters afterwards to get to the correct spot.
That made me think, what if you combined both of these?
If you type in a letter and highlight all words starting with that letter, that will result in far fewer matches than both methods.
Hop doesn't come with a feature like that, but it luckily has a regex matching feature. So I implemented some code to do that! Here's that code:
```lua
return {
'smoka7/hop.nvim',
version = "*",
opts = {
keys = 'etovxqpdygfblzhckisuran'
},
config = function()
local hop = require('hop')
hop.setup()
vim.keymap.set('', '<C-f>', function ()
vim.api.nvim_echo({{" Enter letter: ", "Normal"}}, false, {})
local char = vim.fn.nr2char(vim.fn.getchar())
if not char:match('^[%w%p]$') then
vim.api.nvim_echo({{" Invalid input!", "ErrorMsg"}}, false, {})
return
end
vim.api.nvim_echo({}, false, {})
-- Matches all instances of the provided character that are preceded by whitespace, a special character, or start of a line.
local pattern = '\\%(\\_^\\|[[:space:]{}.|><!@#$%^&*()-_+=`~;:,/?\\[\\]"\']\\)\\@<=[' .. char:lower() .. char:upper() .. ']'
hop.hint_patterns({}, pattern)
end, {remap=true})
end
}
```
This works exactly how I wanted it! The matching is slightly different from the built-in "HopWords" one. For example, the built-in will ignore the `5` in `1234.5678`.
But if you type 5, my code above will match that.
This is not a problem because the combination of "start of word" and "typed character" already narrows it down enough that you won't end up with an excessive number of matches. I also do prefer it this way!