-
Notifications
You must be signed in to change notification settings - Fork 407
Nvim-cmp's keyword_pattern and Vimtex's Omnifunc #2786
Description
Description
Vimtex support in nvim-cmp is an issue which has been extensively discussed. These are just some of the related issues:
- Support for nvim-cmp. #2215
cmp-omnisource not displayed whennvim_lspis enabled hrsh7th/nvim-cmp#833- Erorr when using keyword_pattern hrsh7th/nvim-cmp#1170
- Omni Completion (offset?) issues hrsh7th/nvim-cmp#652
- Vimtex support isn't complete hrsh7th/cmp-omni#1
- vimtex support hrsh7th/nvim-cmp#258
The problem explained in those issues dealt mainly with the Vimtex-provided neocomplete pattern (https://github.com/lervag/vimtex/blob/master/autoload/vimtex/re.vim#L35), why it didn't work, and why cite-completion wasn't triggered automatically (i.e. the completion menu appeared) as soon as a \cite{ statement was typed.
I may have found some workarounds and/or hints towards a possible solution. I'll explain them in order:
-
Cite-completion isn't triggered automatically as soon as a
\cite{statement is issued. Differently from other engines, with nvim-cmp the user first has to type a character to have the menu pop up and show bilbiographic references. This is obviously annoying, as the user may not always remember, at the top of his head, exactly which reference to insert (or the key name). A workaround which I don't think was ever discussed is to use atrigger_characterin nvim-cmp's configuration, as such:{ name = "omni", trigger_characters = { "{" } }, -
Correctness of the Vimtex-provided Neocomplete pattern. When the discussions in the previously linked issues were held, the validity of said pattern was questioned and, if I recall correctly, noone ever managed to make it work with nvim-cmp. The pattern, though, is indeed correct. This can be tested by opening the following file in Neovim and sourcing (
:so):vim.g.regex = [=[\%(]=] .. [=[\v\\%(]=] .. [=[%(\a*cite|Cite)\a*\*?%(\s*\[[^]]*\]){0,2}\s*\{[^}]*]=] .. [=[|%(\a*cites|Cites)%(\s*\([^)]*\)){0,2}]=] .. [=[%(%(\s*\[[^]]*\]){0,2}\s*\{[^}]*\})*]=] .. [=[%(\s*\[[^]]*\]){0,2}\s*\{[^}]*]=] .. [=[|bibentry\s*\{[^}]*]=] .. [=[|%(text|block)cquote\*?%(\s*\[[^]]*\]){0,2}\s*\{[^}]*]=] .. [=[|%(for|hy)\w*cquote\*?\{[^}]*}%(\s*\[[^]]*\]){0,2}\s*\{[^}]*]=] .. [=[|defbibentryset\{[^}]*}\{[^}]*]=] .. [=[|\a*ref%(\s*\{[^}]*|range\s*\{[^,}]*%(}\{)?)]=] .. [=[|hyperref\s*\[[^]]*]=] .. [=[|includegraphics\*?%(\s*\[[^]]*\]){0,2}\s*\{[^}]*]=] .. [=[|%(include%(only)?|input|subfile)\s*\{[^}]*]=] .. [=[|([cpdr]?(gls|Gls|GLS)|acr|Acr|ACR)\a*\s*\{[^}]*]=] .. [=[|(ac|Ac|AC)\s*\{[^}]*]=] .. [=[|includepdf%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|includestandalone%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|%(usepackage|RequirePackage|PassOptionsToPackage)%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|documentclass%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|begin%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|end%(\s*\[[^]]*\])?\s*\{[^}]*]=] .. [=[|\a*]=] .. [=[)]=] local regex_1 = vim.regex(vim.g.regex) local match_str = [=[noise \cite{]=] vim.print(regex_1:match_str(match_str))
-
And now the hardest issue: Making that pattern work with nvim-cmp. I've only partially achieved this goal, and I write this issue with the hope that someone more expert than me will be able to help.
First thing, nvim-cmp modifies the
keyword_patternprovided by the user:
https://github.com/hrsh7th/nvim-cmp/blob/5dce1b778b85c717f6614e3f4da45e9f19f54435/lua/cmp/context.lua#L77return pattern.offset([[\%(]] .. keyword_pattern .. [[\)\m$]], self.cursor_before_line) or self.cursor.col
This is necessary to ensure that only the last-typed text will be matched, as discussed in Custom completion source - completion popup not showing up hrsh7th/nvim-cmp#1273. The problem is that such a modification assumes to be in magic mode, whilst the keyword pattern we would be using set
\vvery-magic mode. This can be fixed by either adding a\mat the end of the pattern we pass to nvim-cmp, as such.. [=[|\a*]=] .. [=[)]=] .. [=[\m]=]
or by correcting nvim-cmp's handling. I still haven't made a PR, but it should be like this:
return pattern.offset([[\%(]] .. keyword_pattern .. [[\m\)$]], self.cursor_before_line) or self.cursor.col
After making such an addition, nvim-cmp still doesn't match. It took me multiple hours of debugging but, by modifying cmp/source.lua
+ local offset = ctx:get_offset(self:get_keyword_pattern()) + 1 - local offset = ctx:get_offset(self:get_keyword_pattern())
nvim-cmp start finally to match correctly and show the completion menu. The issue I've found is that the completion menu, with such a modification, doesn't appear after typing a
\cite{statement. I've tried to troubleshoot this, but I'm not a programmer and the code in that nvim-cmp's function is just too complicated for me.
If someone who has the expertise would like to help, I'd be happy to contribute where I can. I honestly hope that we will, finally, be able to solve this stubborn issue.
Finally, sorry for bearing with me 'till the end of this message.
VimtexInfo
System info:
OS: Linux 6.4.12-arch1-1
Vim version: NVIM v0.9.1
Has clientserver: true
Servername: /run/user/1000/nvim.896581.0
VimTeX project: a
base: a.tex
root: /home/mike
tex: /home/mike/a.tex
main parser: current file verified
document class: article
compiler: latexmk
engine: -pdf
options:
-verbose
-file-line-error
-synctex=1
-interaction=nonstopmode
callback: 1
continuous: 1
executable: latexmk
viewer: Zathura
xwin id: 0
qf method: LaTeX logfile