Skip to content

grep preview highlight logic diverges from core query parser semantics #331

@LocNguyenSGU

Description

@LocNguyenSGU

Summary

The grep preview highlight logic in lua/fff/location_utils.lua appears to re-parse the query using a simplified Lua heuristic instead of using the same parsed grep text semantics as the Rust query parser.

As a result, preview highlighting can diverge from the actual grep query behavior when the query contains multiple text tokens, constraints, or escaped constraint-like tokens.

Current Behavior

In lua/fff/location_utils.lua, the preview highlight code derives search_text like this:

local parts = vim.split(query, '%s+')
local text_parts = {}
for _, part in ipairs(parts) do
  if part ~= '' and not part:match('^[%*!/]') and not part:match('^%.') then
    table.insert(text_parts, part)
  end
end
if #text_parts > 0 then search_text = text_parts[1] end

This means the preview highlighter effectively uses only the first non-constraint-looking token.

But the Rust parser builds grep text differently. In crates/fff-query-parser/src/parser.rs:

pub fn grep_text(&self) -> String {
    match &self.fuzzy_query {
        FuzzyQuery::Empty => String::new(),
        FuzzyQuery::Text(t) => strip_leading_backslash(t).to_string(),
        FuzzyQuery::Parts(parts) => parts
            .iter()
            .map(|t| strip_leading_backslash(t))
            .collect::<Vec<_>>()
            .join(" "),
    }
}

So the effective grep text is based on the parsed non-constraint text parts, joined back together, with escaped constraint tokens handled according to parser rules.

Why this is a problem

The preview UI and the core parser can disagree about what the actual search text is.

That can produce incorrect highlight behavior for queries such as:

  • *.rs TODO fixme
  • /src/ init config
  • !test foo bar
  • \\*.rs literal

In those cases, the result set may be produced using the parser's real grep text semantics, while preview highlighting only tracks the first remaining token (for example just TODO instead of TODO fixme).

Expected Behavior

Preview highlighting should use the same parsed grep text semantics as the core query parser, rather than re-implementing a simplified constraint-strip heuristic in Lua.

That would keep the preview UI aligned with actual grep matching behavior.

Evidence

Preview heuristic in Lua

lua/fff/location_utils.lua:

local parts = vim.split(query, '%s+')
local text_parts = {}
for _, part in ipairs(parts) do
  if part ~= '' and not part:match('^[%*!/]') and not part:match('^%.') then
    table.insert(text_parts, part)
  end
end
if #text_parts > 0 then search_text = text_parts[1] end

Core grep text semantics in Rust

crates/fff-query-parser/src/parser.rs:

pub fn grep_text(&self) -> String {
    match &self.fuzzy_query {
        FuzzyQuery::Empty => String::new(),
        FuzzyQuery::Text(t) => strip_leading_backslash(t).to_string(),
        FuzzyQuery::Parts(parts) => parts
            .iter()
            .map(|t| strip_leading_backslash(t))
            .collect::<Vec<_>>()
            .join(" "),
    }
}

Reproduction

  1. Open a grep result in preview mode.
  2. Use a query that contains both constraints and multiple text tokens, for example:
    • *.rs TODO fixme
    • /src/ init config
    • !test foo bar
  3. Compare:
    • the actual result selection behavior
    • the text highlighted in the preview
  4. Observe that the preview highlight logic appears to be driven by a simplified first-token heuristic instead of the parser's effective grep text.

Duplicate Check

  • Open issues checked: no direct match found
  • Closed issues checked: no direct match found
  • Recent PRs checked: no direct match found

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions