Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: get_signs is broken on nightly #2039

Closed
3 tasks done
amaanq opened this issue Nov 19, 2023 · 11 comments · Fixed by #2095
Closed
3 tasks done

bug: get_signs is broken on nightly #2039

amaanq opened this issue Nov 19, 2023 · 11 comments · Fixed by #2095
Labels
bug Something isn't working

Comments

@amaanq
Copy link
Contributor

amaanq commented Nov 19, 2023

Did you check docs and existing issues?

  • I have read all the LazyVim docs
  • I have searched the existing issues of LazyVim
  • I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

v0.10.0-dev-1600+ga84b454eb

Operating system/version

Arch Linux x86_64 6.6.1-zen1-1-zen

Describe the bug

Something in Neovim changed w.r.t. signs, I'm not sure what it implies but it causes a slew of errors in Neovim

E5108: Error executing lua /home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:16: attempt to index local 'ret' (a nil value)
stack traceback:
	/home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:16: in function </home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:13>
	vim/shared.lua: in function 'tbl_map'
	/home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:13: in function 'get_signs'
	/home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:98: in function </home/amaanq/projects/LazyVim/lua/lazyvim/util/ui.lua:87>

Steps To Reproduce

  1. Use Neovim nightly
  2. Open a file

Expected Behavior

No error

Repro

-- DO NOT change the paths and don't remove the colorscheme
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", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  "folke/LazyVim",
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here
@amaanq amaanq added the bug Something isn't working label Nov 19, 2023
@lkhphuc
Copy link
Contributor

lkhphuc commented Nov 19, 2023

Likely the reason: neovim/neovim#25724

@bouvettem17
Copy link

@amaanq
One fix I found to this, although I'm not sure if it's the most optimal is simply adding a nil check on the ret value in the M.get_signs() function within the LazyVim/lua/LazyVim/util/ui.lua class. (You can find this in you lazy install at the ~/.local/share/nvim/lazy if you are on mac)

function M.get_signs(buf, lnum)
  -- Get regular signs
  ---@type Sign[]
  local signs = vim.tbl_map(function(sign)
    ---@type Sign
    local ret = vim.fn.sign_getdefined(sign.name)[1]
    print(sign.name)
    if ret ~= nil then --------------| Lines in Question
      ret.priority = sign.priority --|
      return ret                   --|
    end -----------------------------|
  end, vim.fn.sign_getplaced(buf, { group = "*", lnum = lnum })[1].signs)

  -- Get extmark signs
  local extmarks = vim.api.nvim_buf_get_extmarks(
    buf,
    -1,
    { lnum - 1, 0 },
    { lnum - 1, -1 },
    { details = true, type = "sign" }
  )
  for _, extmark in pairs(extmarks) do
    signs[#signs + 1] = {
      name = extmark[4].sign_hl_group or "",
      text = extmark[4].sign_text,
      texthl = extmark[4].sign_hl_group,
      priority = extmark[4].priority,
    }
  end

This still has the gitsigns show up in the statuscolumn (i'm guessing because of the for loop for extmarks below this tbl_map) but stops that error from happening. I'm look into diagnosing actual what the logic difference is and if there is a cleaner fix but this hopefully should work for you in the meantime.

@luukvbaal
Copy link

luukvbaal commented Nov 20, 2023

With neovim/neovim#25724 merged, sign_getplaced() can be used to fetch both legacy and extmark signs. Extmark signs will have a nil name field.

nvim_buf_get_extmarks() will also return legacy signs now. I'm hoping neovim/neovim#26105 gets merged soon, which will mean returned legacy signs will have a non-nil name field. (Personally I'm waiting for that to update statuscol.nvim.)

@bouvettem17
Copy link

Ok so I think i understand but would really appreciate it if you could verify if my thought process is correct. So before the neovim/neovim#25724 update to nvim the sign_getplaced() in this block

  local signs = vim.tbl_map(function(sign)
    ---@type Sign
    local ret = vim.fn.sign_getdefined(sign.name)[1]
    ret.priority = sign.priority
    return ret
  end, vim.fn.sign_getplaced(buf, { group = "*", lnum = lnum })[1].signs)

wouldn't retrieve the extmark signs, thus the sign_getdefined() would be able to retrieve the corresponding signs without having to worry about not finding one (since they are placed), therefore there is no need for a nil check for the ret variable. However now that the extmark signs are also being retrieved by the sign_getplaced(), the sign_getdefined() isn't able to retrieve them because the extmarks have nil name fields which results in ret being nil in some cases. But after neovim/neovim/#26105 is merged in, then the name fields for extmarks won't be nil, meaning sign_getdefined() should be able to retrieve them without issue meaning ret won't need the nil check again. Is this the right thought process? I'm new to actually looking behind the scenes at lazy and nvim in general so just trying to understand what's going on.

If it is, and as a side question, does this mean after the new functionality is fully implemented that the usage surrounding nvim_buf_get_extmarks() in the full function that I posted in my previous comment would be redundant since the sign_getplaced() will be able to handle the extmarks that are currently being handled by that code?

Thanks so much!

@luukvbaal
Copy link

luukvbaal commented Nov 20, 2023

Correct, sign_getplaced() and nvim_buf_get_extmarks(..., {type="sign"}) now return all placed signs. Legacy signs are defined and have a name attached to them that can be passed to sign_getdefined(). Extmark signs on the other hand do not (unfortunately so in my opinion). One should take care not to pass nil when mapping sign_getplaced() to sign_getdefined().

If it is, and as a side question, does this mean after the new functionality is fully implemented that the usage surrounding nvim_buf_get_extmarks() in the full function that I posted in my previous comment would be redundant since the sign_getplaced() will be able to handle the extmarks that are currently being handled by that code?

Indeed, this was one of the motivations for neovim/neovim#25724. Either nvim_buf_get_extmarks() or sign_getplaced() will suffice to fetch all placed signs. I would recommend getting rid of sign_getplaced() when neovim/neovim#26105 is merged. The details array that nvim_buf_get_extmarks() returns already contains the sign properties so there is no need to map to sign_getdefined().

@bouvettem17
Copy link

Awesome, thanks so much for explaining that, really appreciate it!

@yriveiro
Copy link

neovim/neovim#25724 get merged and now lazyvim is having a lot of errors.

Example:

E5108: Error executing lua ...o/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/ui.lua:16: attempt to index local 'ret' (a nil value)
stack traceback:
        ...o/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/ui.lua:16: in function 'func'
        vim/shared.lua:238: in function 'tbl_map'
        ...o/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/ui.lua:13: in function 'get_signs'
        ...o/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/ui.lua:98: in function <...o/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/ui.lua:87>
        [C]: in function 'ui_detach'
        .../.local/share/nvim/lazy/noice.nvim/lua/noice/ui/init.lua:127: in function 'disable'
        ...iro/.local/share/nvim/lazy/noice.nvim/lua/noice/init.lua:45: in function 'disable'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/init.lua:290: in function 'panic'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:59: in function <...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:56>
        [C]: in function 'pcall'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:144: in function <...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:143>
        ...
        [C]: in function 'xpcall'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:149: in function 'try'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/view/init.lua:140: in function 'display'
        .../share/nvim/lazy/noice.nvim/lua/noice/message/router.lua:215: in function <.../share/nvim/lazy/noice.nvim/lua/noice/message/router.lua:155>
        [C]: in function 'xpcall'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:149: in function <...local/share/nvim/lazy/noice.nvim/lua/noice/util/call.lua:134>
        [C]: in function 'pcall'
        ...local/share/nvim/lazy/noice.nvim/lua/noice/util/init.lua:120: in function 'fn'
        vim/_editor.lua:587: in function 'fn'
        vim/_editor.lua:343: in function <vim/_editor.lua:342>

@georgeguimaraes
Copy link
Contributor

Thanks for the workaround @bouvettem17. At least I can run neovim head!

@idr4n
Copy link

idr4n commented Nov 22, 2023

Based on a discussion in the statuscol plugin, using _extmark_signs = false in gitsigns solves the issue for me, at least temporarily:

{
    "lewis6991/gitsigns.nvim",
    opts = {
      _extmark_signs = false,
    },
}

@dpetka2001
Copy link
Contributor

neovim/neovim#26105 got merged, so maybe Folke would like to consider @luukvbaal's comment with how he will proceed solving this.

@lvimuser
Copy link

This should be enough, then?

function M.get_signs(buf, lnum)
   -- Get regular signs
   ---@type Sign[]
-  local signs = vim.tbl_map(function(sign)
-    ---@type Sign
-    local ret = vim.fn.sign_getdefined(sign.name)[1]
-    ret.priority = sign.priority
-    return ret
-  end, vim.fn.sign_getplaced(buf, { group = "*", lnum = lnum })[1].signs)
+  local signs = {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants