From 6f7e56d75e4e6b56acd0478b631adeb62f18e0d4 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Wed, 12 Aug 2026 22:08:48 +0200 Subject: [PATCH] Fix crash loop on bib entries with the cite key on its own line BibTeX does not require the cite key to share a line with "@type{", and OpenReview's "Cite" export puts it on the next line: @inproceedings{ key2025, title={x} } parse_type() matches the remainder of the "@type{" line against [[\v^([^, ]*)\s*,\s*(.*)]], which requires both the key and a comma. On such an entry the remainder is empty, matchlist() returns {}, and matches[2] / matches[3] are both nil. The `self.empty(matches[3])` guard should catch that, but empty() has no branch for a nil argument and falls through returning nil, so the guard fails open. parse_entry() is then called with nil, and cmp_vimtex#count() raises E706 (its try/catch only handles E712). Because indexing runs on a repeating timer, the uncaught error aborts the callback before timer:stop() is reached, so it fires again and again, cascading into "table index is nil" at self.result[v.cite_key] and then arithmetic on a nil self.lnum. One such entry makes the session unusable. Fix by deferring the cite-key lookup to parse_entry() when parse_type() cannot find it, and by returning true from empty() for nil so the existing guards behave as intended. Verified against a 55-entry bibliography containing one such entry: it now indexes cleanly and produces a key set identical to the one the unpatched parser produces after the entry is reformatted onto one line. Fixes #29 Co-Authored-By: Claude Opus 5 (1M context) --- lua/cmp_vimtex/parser.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lua/cmp_vimtex/parser.lua b/lua/cmp_vimtex/parser.lua index 8ef09a0..9e40fe1 100644 --- a/lua/cmp_vimtex/parser.lua +++ b/lua/cmp_vimtex/parser.lua @@ -208,6 +208,19 @@ parser.parse_string = function(self, line) end parser.parse_entry = function(self, line) + -- The cite key is not required to share a line with "@type{" (this is how + -- OpenReview exports its BibTeX). When parse_type could not find it, pick + -- it up from the first subsequent line that supplies it. + if self.current.cite_key == nil then + local key = vim.fn['matchlist'](line, [[\v^\s*([^, ]+)\s*,\s*(.*)]]) + if self.empty(key) then + self.current.body = self.current.body .. line + return false + end + self.current.cite_key = key[2] + line = key[3] + end + self.current.level = self.current.level + vim.fn['cmp_vimtex#count'](line, '{') - vim.fn['cmp_vimtex#count'](line, '}') if self.current.level > 0 then self.current.body = self.current.body .. line @@ -329,6 +342,10 @@ parser.empty = function(list) return false end end + + -- nil (e.g. an out-of-range matchlist() result) counts as empty; without + -- this the guards above silently fall through on a nil argument. + return true end return parser