diff --git a/CHANGELOG.md b/CHANGELOG.md index fcb36a9..951cdca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Added +- The diff view highlights code embedded in another language with that language's parser, not only the file's own grammar + +## [0.2.0] — 2026-10-09 + +### Added + - `dw` in the diff or the panel shows a partly staged file's changes since staging, works as a toggle - `ds` in the panel or the diff previews the commit: only the staged changes, each diffed against `HEAD`, also works as a toggle - `s` and `u` act on a hunk the index holds only part of, and the diff winbar tallies staged and partial hunks diff --git a/lua/differ/syntax/init.lua b/lua/differ/syntax/init.lua index cb4790e..22e20ad 100644 --- a/lua/differ/syntax/init.lua +++ b/lua/differ/syntax/init.lua @@ -13,8 +13,16 @@ local M = {} local ns = vim.api.nvim_create_namespace("differ.syntax") -- layering: syntax foreground sits *under* the diff line background (paint --- uses 100) and word-level spans (200), so the diff state always reads on top +-- uses 100) and word-level spans (200), so the diff state always reads on top. +-- an injected layer sits one above its host, capped short of the diff layer, so +-- embedded code wins where the host also captures the region it was lifted from local PRIORITY = 90 +local MAX_DEPTH_BUMP = 9 + +-- ceiling for parsing injections. the primary tree is still parsed above it, so a +-- generated file keeps its tag/keyword level highlighting without paying for +-- injection discovery over the whole tree +local INJECTION_MAX_BYTES = 512 * 1024 -- resolve a treesitter language for `path`, or nil when there's no filetype, no -- mapped language, or the parser isn't installed, in which case the pass is @@ -39,10 +47,88 @@ local function resolve_lang(path) return lang end --- parse `text` and collect highlight captures in source coordinates. mirrors the --- core highlighter: hl group is `@.`, captures named `_…` are --- internal and skipped. multi-line captures are clipped to one entry per line; --- injections (embedded languages) are deferred for v1, only the primary tree +-- treesitter handles are typed `any`: there's no nvim type library on the +-- typecheck path, so naming TSTree/TSNode/Query would only be an undefined alias +---@class differ.SyntaxLayer +---@field tree any -- TSTree +---@field lang string +---@field query any -- vim.treesitter.Query +---@field priority integer + +-- flatten a language tree into paint layers, host before its injections so +-- embedded code is applied over the region the host lifted it from. one injected +-- language holds one layer per region, not one per language, so a file with three +-- `