Skip to content

Commit

Permalink
Add treesitter highlighting support in cat mode
Browse files Browse the repository at this point in the history
Resolve treesitter highlighting metadata to syntax_id needed by
nvim_get_hl() in group2ansi() which converts highlighting colours to
ANSI escape sequences. Fallback to parsing traditional highlighting if
treesitter metadata is not available.

This also resolves the issue with no syntax highlighting available at
all when treesitter highlighting is active, traditional and treesitter
modes are mutually exclusive; that is no traditional highlighting data
will be available if treesitter is active for a given buffer.

Testing done:
* Observed regular and new functionality displaying C and Bash source
files in cat mode in traditional highlighting then with treesitter
highlighting.
* Confirmed that  syntax highlighting colours while in treesitter mode
match in side by side comparison between nvimpager in cat mode and nvim
edit mode.
  • Loading branch information
adeg committed Apr 1, 2024
1 parent 41d3a3a commit beb8497
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion lua/nvimpager/cat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,41 @@ local function color2escape_8bit(color_number, foreground)
return prefix .. color_number
end

-- Return syntax_id for the given position in the text for it to be
-- converted to ANSI text highlighting by group2ansi() function. Interprets the
-- data structrure returned by inspect_pos() which provides data for both
-- treesitter and vim syntax highlighting. Note that if treesitter is active
-- the syntax table will be empty thus functions like synID() will return 0.
-- When treesitter syntax highlighting is not active, then the treesitter field
-- will be empty (but still present), and syntax-related data will be in 'syntax'.
local function get_syntax_id(lnum, cnum)
local syn_id = 0
local bufnr = nvim.nvim_get_current_buf()

local current_pos_data = vim.inspect_pos(bufnr, lnum-1, cnum-1)
-- treesitter data is available; this automatically means that syntax is empty
if next(current_pos_data.treesitter) ~= nil then
local ts_data = current_pos_data.treesitter
-- The data we need is usually in the last element
local ts_elem = ts_data[#ts_data]
-- Sometimes treesitter metadata capture type 'spell' is the last item,
-- but there's no hl data for us there. So take the item before that.
if string.find(ts_elem.capture, "spell") then
ts_elem = ts_data[#ts_data - 1]
end
syn_id = vim.fn.hlID(ts_elem.hl_group)
-- if no treesitter data is available, fallback to syntax data
elseif next(current_pos_data.syntax) ~= nil then
-- The data we need is usually in the last element
local syntax_data = current_pos_data.syntax[#current_pos_data.syntax]
syn_id = vim.fn.hlID(syntax_data.hl_group)
-- it could be that neither treesitter nor regular syntax data is available
else
syn_id = 0
end
return syn_id
end

-- Compute a ansi escape sequences to render a syntax group on the terminal.
local function group2ansi(groupid)
if cache[groupid] then
Expand Down Expand Up @@ -97,6 +132,16 @@ local function group2ansi(groupid)
if info.italic then escape = escape .. ';3' end
if info.underline then escape = escape .. ';4' end

-- Workaround hack warning: treesitter schemes set editor background in the
-- "Normal" hightlight group which is currently used for fallback when no
-- hl group info available for a given position. This causes spotty background
-- issues as we'll be rendering background only for the parts of the text we
-- don't have a hl group. The workaround is to exclude background color for
-- the default hl group.
if groupid == nvim.nvim_call_function('hlID', {'Normal'}) then
info.background = nil
end

if info.foreground then
escape = escape .. ';' .. color2escape(info.foreground, true)
end
Expand Down Expand Up @@ -185,7 +230,7 @@ local function highlight()
skip_next_char = true
end
else
syntax_id = nvim.nvim_call_function('synID', {lnum, cnum, true})
syntax_id = get_syntax_id(lnum, cnum)
end
end
if syntax_id ~= last_syntax_id then
Expand Down

0 comments on commit beb8497

Please sign in to comment.