从 omnifunc 调用时 getbufline 缺少当前行

getbufline missing current line when called from an omnifunc

我目前正在尝试为 vim 编写一个插件,它将允许我为给定语言定义一个自定义的 omnifunc。

我几乎可以做到这一点,除了当我调用 getbufline(为了获取当前缓冲区的内容)时,结果包含一个空行而不是当前行的内容。

这是我目前使用的函数:

function! statemachine#GetCurrBuffContents()
  return join(getbufline(bufname('%'), 1, "$"), "\n")
endfunction

奇怪的是,如果我通过 echom statemachine#GetCurrBuffContents() 从 vim 调用我的函数,那么我会看到预期的输出,即每行由 \n 分隔字符。

示例: 缓冲区包含以下内容

input signal x
out

state State2
if x == false goto State2
end

如果我在光标位于第 2 行时按 c-x c-o(触发 omnicompletion),我会看到以下内容(我在我的插件中回显):

input signal x^@^@^@state State2^@if x == false goto State2^@end

如果我 运行 echom statemachine#GetCurrBuffContents(),我会看到以下内容:

input signal x^@input^@^@state State2^@if x == false goto State2^@end

相关代码如下: https://github.com/scottopell/vim-statemachine/blob/3c3c3803f24031cce676e3988daaff12c269142a/autoload/statemachine.vim#L33

编辑:现在它已修复,这是我当前正在使用的代码。请参阅 Ingor 关于为什么存在该代码的回答

在Vim第二次调用补全函数(cp.:help complete-functions)获取候选列表之前,Vim删除完成基础(由第一次调用确定)。这样做的好处是缓冲区搜索(大多数完成所做的)不包括当前位置(它只会自行完成)。您的示例在光标前只有一个单词,因此您看到 "entire line" 消失了。

如果确实需要context的"full"缓冲区内容,需要在当前位置手动拼接base;基地已经传回给你了。但是大多数当前缓冲区完成不会将整个缓冲区抓取到一个字符串中,而是使用 search() 来(暂时且不可见地)在实际缓冲区中四处移动光标以获得匹配项。你可以看看我的CompleteHelper plugin这样的实用函数

PS:可以用getline(1, "$")代替getbufline(bufname('%'), 1, "$")