mrjones2014 / legendary.nvim

🗺️ A legend for your keymaps, commands, and autocmds, integrates with which-key.nvim, lazy.nvim, and more.
MIT License
1.14k stars 19 forks source link

[Bug]: Visual mode is not preserved #375

Closed notEvil closed 1 year ago

notEvil commented 1 year ago

Similar Issues

Neovim Version

NVIM v0.9.1
Build type: Release
LuaJIT 2.1.0-beta3

Steps to Reproduce

  1. Define a function
  2. Select a range linewise (V)
  3. Start legendary with require('legendary').find()
  4. Execute the function

Expected Behavior

Selection is still linewise

Actual Behavior

Selection is per character (v)

Minimal Configuration to Reproduce

local root = vim.fn.fnamemodify('./.repro', ':p')

-- set stdpaths to use .repro
for _, name in ipairs({ 'config', 'data', 'state', 'cache' }) do
  vim.env[('XDG_%s_HOME'):format(name:upper())] = root .. '/' .. name
end

-- bootstrap lazy
local lazypath = root .. '/plugins/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    '--single-branch',
    'https://github.com/folke/lazy.nvim.git',
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  -- do not remove the colorscheme! it makes testing nicer
  'folke/tokyonight.nvim',
  {
    'mrjones2014/legendary.nvim',
    dependencies = {
      'nvim-telescope/telescope.nvim',
      'stevearc/dressing.nvim',
    },
  },
  -- add any other pugins here
}

require('lazy').setup(plugins, {
  root = root .. '/plugins',
})

require('dressing').setup()

require('legendary').setup({
  funcs={
    {function() print(vim.fn.mode()) end, description='Function'},
  },
})

-- add anything else here
vim.opt.termguicolors = true
-- do not remove the colorscheme! it makes testing nicer
vim.cmd([[colorscheme tokyonight]])

Output from :LegendaryLog

:LegendaryLog output (click to expand) ``` [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Preparing to execute selected item [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Performing SQL transaction with following data: { params = { where = { item_id = "' Function'" } }, query = { cmd = 1, cmd_data = "timestamps" } } [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Performing SQL transaction with following data: { params = { item_id = "' Function'" }, query = { cmd = 4, cmd_data = "INSERT INTO timestamps (item_id, timestamp) values(:item_id, julianday('now'));" } } [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Performing SQL transaction with following data: { params = { where = { item_id = "' Function'" } }, query = { cmd = 1, cmd_data = "item_count" } } [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Updating item with ID "' Function'" [Mi 21 Jun 2023 13:04:15 CEST][legendary.nvim] Updating scoring data for selected item. [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Took 0.118704 ms to filter items in context. [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Computed item scores: { ["':LegendaryLogLevel Convenience command to set log level'"] = 10, ["' Function'"] = 10, ["' Toggle comment'"] = 100, ["'Toggle case'"] = 10 } [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Performing SQL transaction with following data: { params = {}, query = { cmd = 4, cmd_data = "SELECT id, item_id, CAST((julianday('now') - julianday(timestamp)) * 24 * 60 AS INTEGER) AS age FROM timestamps;" } } [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Performing SQL transaction with following data: { params = {}, query = { cmd = 1, cmd_data = "item_count" } } [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Frecency database initialized. [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Initializing frecency database... [Mi 21 Jun 2023 13:04:13 CEST][legendary.nvim] Launching select UI [Mi 21 Jun 2023 13:04:01 CEST][legendary.nvim] setup() parsed and applied all configuration. ```

Additional Details and/or Screenshots

I narrowed the issue down to:

https://github.com/mrjones2014/legendary.nvim/blob/6a3b2411146432f83ef44c7980d7a2b20f7a39ce/lua/legendary/ui/init.lua#L82 seems to hard abort visual mode (unlike pressing Escape) and the subsequent https://github.com/mrjones2014/legendary.nvim/blob/6a3b2411146432f83ef44c7980d7a2b20f7a39ce/lua/legendary/api/executor.lua#L40 doesn't use the correct mode.

Workaround: before calling require('legendary').find(), execute <esc>gv

mrjones2014 commented 1 year ago

to clarify, is the issue that we need to make a distinction between visual and visual-block mode?

notEvil commented 1 year ago

No, the issue wouldn't exist if visual mode would be cancelled like pressing Escape. I don't know if this is expected behavior, and where it originates (legendary, telescope or even neovim).

mrjones2014 commented 1 year ago

I'm still not sure I entirely understand what the issue is precisely.

notEvil commented 1 year ago

I'll try to be more precise. Consider the function provided above. If entering Legendary from linewise visual mode, it is in characterwise visual mode when the function is executed. The reason is that somehow visual mode is aborted in a way that doesn't set the marks and the mode. This is different from the usual behavior where leaving visual mode using Escape will set the marks and the mode, so gv can recreate the visual selection. Since this is not the case, you end up with the correct marks because you get them yourself using get_marks, and set them before executing the function. However, the mode is lost and gv uses the mode that was last used (defaults to v).

I've not seen a single function that aborts visual mode in such a way, and would assume that its a bug, somewhere. In any case, the mode is important.

mrjones2014 commented 1 year ago

Ah, yes, I think I get it now, thanks for elaborating. Part of the issue here is that vim.ui.select() I think always exits visual mode, and doesn’t seem to set marks when doing so, so I’ve got some workarounds in the code to try to set them manually.

there may be a better way to do this, like exiting visual mode purposefully in a way that does properly set the marks before attempting to call vim.ui.select().

I’ll do some research.

mrjones2014 commented 1 year ago

Hmm, I'm unable to reproduce. Is this not the intended behavior?

CleanShot 2023-06-23 at 10 20 31

notEvil commented 1 year ago

You have to start Legendary from a visual mode that wasn't the last. So the most precise steps are:

  1. select something characterwise
  2. escape
  3. select something linewise
  4. open legendary
  5. ...

Then, the mode will change back to characterwise.

If the mode in 1 matches the one in 3, you don't see the effect.