blink.cmp icon indicating copy to clipboard operation
blink.cmp copied to clipboard

Fixed help text autocompletion error

Open Polynominal opened this issue 1 month ago • 2 comments

Fixed help text autocompletion error. would occur at :h usage after typing the first character

I presume it worked at some point in the past and wasn't tested after one refactor or another

Thanks for the plugin, it's nice and fast

Polynominal avatar Nov 26 '25 07:11 Polynominal

Thanks for the PR!

Adding a defensive safeguard makes sense to prevent edge case errors but the way flatten is called in the help module, it normally receives an array of tags. So, I'm curious how it could possibly receive a string there. I haven't encountered any errors using :help. Do you have a way to reproduce this?

soifou avatar Nov 26 '25 11:11 soifou

I managed to trace it down, its indeed to do with my config I have changed lua strings to act like they do in other languages eg they can be indexed such as

local text = "text"
if(text[1] == "t") -- evaluates to True

however under normal circumstances

local text = "text"
if(text[1] == nil) -- evaluates to True

this is done via

local meta = getmetatable("")
local oldindex = meta.__index
meta.__index = function(self,i,...)
    if type(i) == "number" then
        return string.sub(self,i,i)
    end
    return rawget(oldindex,i)
end

so when you do

if t[1] == nil then return t end

this will evaluate to true (as t[1] is nil) if 't' is a string without the operator overloading however with it, it will evaluate to False hence interpreting 't' as a table

I am not sure regarding performance implication of runtime type checking vs indexing in lua, but I presume it's more sane to check if t is a string

Note that after some testing, t is never actually a string unless the operator overload is in place and I havent found exactly where it's causing the issue but if you are using indexing as a means of type checking it could be all over the place.

To reproduce the bug simply put this into your init.lua

local meta = getmetatable("")
local oldindex = meta.__index
meta.__index = function(self,i,...)
    if type(i) == "number" then
        return string.sub(self,i,i)
    end
    return rawget(oldindex,i)
end

Polynominal avatar Nov 26 '25 20:11 Polynominal

Sorry about the delay! I'm going to close this PR, because we can't support global string metatable overrides, they break iterators and other plugins.

That said, I refactored the help source to use vim.iter(...):flatten():totable() instead of the custom flatten() function. This handles nested arrays safely, preserves normal behavior, and also works with your string-indexing hack without needing any global Lua modifications.

So your setup should work now, and normal users aren't affected. Really appreciate you digging into this and explaining the issue clearly!

soifou avatar Dec 14 '25 01:12 soifou