hadronized / hop.nvim

Neovim motions on speed!
Other
2.47k stars 137 forks source link

How do I get hop to work with vscode neovim? #349

Closed 55Cancri closed 1 year ago

55Cancri commented 1 year ago

In my init.lua I have:

require("base") -- general settings
require("highlights") -- colourscheme and other highlights
require("keymaps") -- keymaps
require("plugins") -- plugins
require("hop") -- hop
require("bootstrap") -- packer auto-installer

print("✔ nvim loaded")
print(vim.inspect(package.loaded['hop']))

In base.lua, I have:

local g = vim.g
local o = vim.o
local opt = vim.opt

-- Map <leader> to space
g.mapleader = ' '
g.maplocalleader = ' '

In keymaps.lua, I have:

map("n", "<leader>w", ":HopWord<cr>")
map("n", "<leader>W", ":HopWordMW<cr>")
map("n", "f", ":HopChar1<cr>")
map("n", "F", ":HopChar1CurrentLine<cr>")

In plugins.lua, I have:

-- ...packer setup
  local status, packer = pcall(require, "packer")
  if not status then
    return

  end

  return packer.startup(function(use)

    use {
        'phaazon/hop.nvim',
        branch = 'v2', -- optional but strongly recommended
        -- config = [[require('hop')]],
        -- config = function()
        -- -- you can configure Hop the way you like here; see :h hop-config
        --   require'hop'.setup {}
        -- end
    }

    if packer_bootstrap then
      require("packer").sync()
    end
  end)

In hop.lua I have:

local setup, hop = pcall(require, "hop")

if not setup then
  return
end

hop.setup { keys = "etovxqpdygfblzhckisuran" }

And finally I am using the vscode neovim extension. From reddit and other sources, I've heard that some people have managed to get it to work with this extension while others have not.

When I load vscode, I see the following output:

✔ nvim loaded
true
nil

The true is from the init.lua and means that hop was loaded, however, when I then press <space>w, I get the error:

E492: Not an editor command: HopWord

which means the hop commands did not load? Please help. I would like an easymotion style navigation flow for vscode neovim where it annotates places to jump to after pressing the spacebar. Here is the same question on stackoverflow: https://stackoverflow.com/questions/74946509/how-do-i-get-hop-to-work-with-vscode-neovim?noredirect=1#comment132277242_74946509

quantumfate commented 1 year ago

You would probably have to fork this project and call VSCodeSetTextDecorations where the hints are applied to the ui. You can see that in the easymotion fork for vscode that instead writing to the buffer you will call VSCodeSetTextDecorations. But the problem here is that fortunately hop doesn't mess with the buffer at all, so the same steps to integrate hop to vscode like you would in easymotion don't apply here.

quantumfate commented 1 year ago

Can you link the other sources you mentioned where people made hop work in vscode? I would like to look into them. I don't think that vscode is a scope of this project but if it works we could at least open a section for vscode in the readme.

quantumfate commented 1 year ago

Also note that I think that you are calling the mappings wrong. Can you try

local keymap = vim.api.nvim_set_keymap

keymap("n", "<leader>w", "<Plug>(HopWord)")
keymap("n", "<leader>W", "<Plug>(HopWordMW)")
keymap("n", "f", "<Plug>(HopChar1)")
keymap("n", "F", "<Plug>(HopChar1CurrentLine)")

instead of

map("n", "<leader>w", ":HopWord<cr>")
map("n", "<leader>W", ":HopWordMW<cr>")
map("n", "f", ":HopChar1<cr>")
map("n", "F", ":HopChar1CurrentLine<cr>")

If hop really doesn't write to the buffer this might work out of the box as it would send the command directly to neovim. Refer to how I made easymotion work in vscode I am also just sourcing specific plugins and keymaps.

quantumfate commented 1 year ago

EDIT: IT WORKS!

local status_ok, hop = pcall(require, "hop")
if not status_ok then
  return
end

-- remap default vim bindings
local opts = { silent = true , noremap=false }
local keymap = vim.api.nvim_set_keymap
hop.setup {
  keys = 'etovxqpdygfblzhckisuran'
}
local directions = require('hop.hint').HintDirection
vim.keymap.set('', 'f', function()
  hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true })
end, {remap=true})
vim.keymap.set('', 'F', function()
  hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true })
end, {remap=true})
vim.keymap.set('', 't', function()
  hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true, hint_offset = -1 })
end, {remap=true})
vim.keymap.set('', 'T', function()
  hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true, hint_offset = 1 })
end, {remap=true})

Refer to my implementation to figure out how I integrate it in vscode. @55Cancri

image

image

quantumfate commented 1 year ago

Here is a better way to set the keybindings. You also don't have to write any particular configuration for vscode or neovim as the same configuration works for both. I only load some keybindings conditionally when I am in vscode

local status_ok, hop = pcall(require, "hop")
if not status_ok then
  return
end

hop.setup {
  keys = 'etovxqpdygfblzhckisuran'
}

local opts = { 
  silent = true, 
  noremap=true,
  callback=nil,
  desc=nil,
}

local keymap = vim.api.nvim_set_keymap
local directions = require('hop.hint').HintDirection

local bindings = {
    { 
      mode = 'n',
      mapping = 'f', 
      desc = '',
      func = function() hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true }) end
    },
    { 
      mode = 'n', 
      mapping = 'F',
      desc = '',
      func = function() hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true }) end
    },
    {
      mode = 'n', 
      mapping = 't',
      desc = '',
      func = function() hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true, hint_offset = -1 }) end
    },
    {
      mode = 'n', 
      mapping = 'T',
      desc = '',
      func = function() hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true, hint_offset = 1 }) end
    },
}

table.foreach(bindings, function(idx, binding) 
  opts.callback = binding.func
  opts.desc = binding.desc
  keymap(binding.mode, binding.mapping, '', opts)
end)
55Cancri commented 1 year ago

@quantumfate Sorry I'm late but thank you so much for your response! Out the gate, what you suggested did not work for me at all. However, you inspired me tonight to sit down and redo this nvim config from the ground up, and after some youtube videos and articles, I finally got hop working in vscode.

Some things I had to learn:

Here is how my barebones nvim.init file looks like:

local vim = vim

-- use plug instead of packer and assign to variable Plug
local Plug = vim.fn['plug#']

-- install plug.vim using the following command: curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
-- https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim.call('plug#begin', '~/.vim/autoload/plug.vim')

-- install hop
Plug("phaazon/hop.nvim")
vim.call('plug#end')

-- setup hop
local hop = require'hop'
hop.setup { keys = "etovxqpdygfblzhckisuran" }

-- assign hop word highlight to the letter f in all vim modes
vim.keymap.set('', 'f', function()
  hop.hint_words()
end, { remap=true })

-- log all installed lua packages including hop to see available functions
print(vim.inspect(package.loaded))

Now I just press f in vscode and I get beautiful letter highlights. I can then press a letter and the cursor jumps instantly. Here's a screenshot to demo that behavior in vscode.

image Simply beautiful 🥲

Again, thank you so much for your help and willingness to look into this issue and I'm sorry for getting back to you so late!

P.S. For reference for myself and others later, the following youtube video and article where instrumental in helping wade through the obscure forest that is nvim + vim + lua + hop + vscode