snacks.nvim icon indicating copy to clipboard operation
snacks.nvim copied to clipboard

bug: Wrong Cursor Position when using `Snacks.picker.keymaps()`

Open ricoberger opened this issue 1 week ago • 0 comments

Did you check docs and existing issues?

  • [x] I have read all the snacks.nvim docs
  • [x] I have updated the plugin to the latest version before submitting this issue
  • [x] I have searched the existing issues of snacks.nvim
  • [x] I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

v0.10.4

Operating system/version

macOS 15.3.1

Describe the bug

Hi, when using Snacks.picker.keymaps() it looks like the cursor is moved one column to the left before the keymap is executed.

Steps To Reproduce

I have K mapped to hover the LSP documentation, when I select the keymap via Snacks.picker.keymaps() it displays the wrong documentation.

E.g. when the cursor is over the P in kong.Parse and the keymap is selected via Snacks.picker.keymaps() it should show the documentation for the Parse function, but instead it will show the documentation for the kong package. Which would also be displayed when the cursor is at the . in kong.Parse and pressing K.

package main

import (
	"github.com/alecthomas/kong"
)

func main() {
	ctx := kong.Parse(&cli)
	err := ctx.Run()
	ctx.FatalIfErrorf(err)
}

Not sure if it helps, but I noticed the same behavior when implementing a custom picker which uses the action function from the dashboard to execute a keymap on selection.

Code
-- See 
-- - https://www.reddit.com/r/neovim/comments/1ircbgt/handy_toolbox_using_snacks_custom_picker/
-- - https://github.com/mslalith/dotfiles/blob/9279acb63f63a0a8b011c949b7c9c6c5bdc55dc3/roles/neovim/files/lua/ms/snacks/toolbox/init.lua
local M = {}

local commands = {
  {
    name = "LSP: Hover Documentation",
    action = "K",
  },
}

-- See https://github.com/folke/snacks.nvim/blob/acedb16ad76ba0b5d4761372ca71057aa9486adb/lua/snacks/dashboard.lua#L292
local function run_action(action)
  if type(action) == "string" then
    if action:find("^:") then
      return vim.cmd(action:sub(2))
    else
      local keys = vim.api.nvim_replace_termcodes(action, true, true, true)
      return vim.api.nvim_feedkeys(keys, "tm", true)
    end
  end
  action()
end

local function get_items()
  local items = {}
  for i, v in ipairs(commands) do
    local item = {
      idx = i,
      text = v.name,
      name = v.name,
      action = v.action,
      divider = v.name == "-",
    }
    table.insert(items, item)
  end
  return items
end

function M.show_commands()
  local last_idx = 0
  local items = get_items()

  Snacks.picker({
    title = "Commands",
    source = "@commands",
    layout = {
      preset = "default",
      preview = false,
    },
    items = items,
    format = function(item, picker)
      local width = picker.layout.opts.layout.width * vim.o.columns
      width = math.floor(width)
      width = (width / 10) * 10 - 4

      local text = items[item.idx].divider and string.rep(item.text, width) or item.text

      return {
        { text, item.text_hl },
      }
    end,
    on_change = function(picker, item)
      if items[item.idx].divider then
        if last_idx < item.idx then
          picker:action("list_down")
        else
          picker:action("list_up")
        end
      end
      last_idx = item.idx
    end,
    confirm = function(picker, item)
      picker:close()
      run_action(items[item.idx].action)
    end,
  })
end

return M

Expected Behavior

The cursor shouldn't be moved to the left before the selected keymap is executed.

Repro

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

require("lazy.minit").repro({
  spec = {
    {
      "folke/snacks.nvim",
      keys = {
        {
          "<leader>fk",
          function()
            Snacks.picker.keymaps()
          end,
          desc = "Keymaps",
        },
      },
      opts = {
        picker = {
          enabled = true,
        },
      },
    },
    -- add any other plugins here
    {
      "neovim/nvim-lspconfig",
      event = { "BufReadPre", "BufNewFile" },
      opts = {
        servers = {
          gopls = {},
        },
      },
      config = function(_, opts)
        local lspconfig = require("lspconfig")
        for server, config in pairs(opts.servers) do
          lspconfig[server].setup(config)
        end

        vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover Documentation" })
      end,
    },
  },
})

ricoberger avatar Feb 17 '25 21:02 ricoberger