Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions lua/hlchunk/mods/chunk/chunk_conf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local BaseConf = require("hlchunk.mods.base_mod.base_conf")
---@field textobject? string
---@field max_file_size? number
---@field error_sign? boolean
---@field node_type_styles? table<string, table> mapping of node type patterns to style

---@class HlChunk.ChunkConf : HlChunk.BaseConf
---@field use_treesitter boolean
Expand All @@ -16,6 +17,7 @@ local BaseConf = require("hlchunk.mods.base_mod.base_conf")
---@field error_sign boolean
---@field duration number
---@field delay number
---@field node_type_styles table<string, table> mapping of node type patterns to style
---@overload fun(conf?: table): HlChunk.ChunkConf
local ChunkConf = class(BaseConf, function(self, conf)
local default_conf = {
Expand All @@ -38,6 +40,21 @@ local ChunkConf = class(BaseConf, function(self, conf)
error_sign = true,
duration = 200,
delay = 300,
-- Node type to style mapping (patterns matched against treesitter node type)
-- If a node type matches multiple patterns, first match wins
-- If no match, falls back to default style[1]
node_type_styles = {
-- Example config (users can override):
-- ["^func"] = { fg = "#99aee5" }, -- functions: blue
-- ["^if"] = { fg = "#c2a2e3" }, -- conditionals: purple
-- ["else"] = { fg = "#c2a2e3" }, -- else: purple
-- ["^for"] = { fg = "#fbdf90" }, -- for loops: yellow
-- ["^while"] = { fg = "#fbdf90" }, -- while loops: yellow
-- ["try"] = { fg = "#9fe8c3" }, -- try/catch: green
-- ["except"] = { fg = "#9fe8c3" }, -- except: green
-- ["catch"] = { fg = "#9fe8c3" }, -- catch: green
-- ["class"] = { fg = "#ef8891" }, -- classes: red
},
}
conf = vim.tbl_deep_extend("force", default_conf, conf or {}) --[[@as HlChunk.ChunkConf]]
BaseConf.init(self, conf)
Expand All @@ -50,6 +67,7 @@ local ChunkConf = class(BaseConf, function(self, conf)
self.error_sign = conf.error_sign
self.duration = conf.duration
self.delay = conf.delay
self.node_type_styles = conf.node_type_styles
end)

return ChunkConf
38 changes: 37 additions & 1 deletion lua/hlchunk/mods/chunk/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ local rangeFromTo = chunkHelper.rangeFromTo
local utf8Split = chunkHelper.utf8Split
local shallowCmp = chunkHelper.shallowCmp

-- Counter for dynamically created highlight groups
local hl_group_counter = 0

---@class HlChunk.ChunkMetaInfo : HlChunk.MetaInfo
---@field task HlChunk.LoopTask | nil
---@field pre_virt_text_list string[]
Expand Down Expand Up @@ -121,6 +124,37 @@ function ChunkMod:get_chunk_data(range, virt_text_list, row_list, virt_text_win_
end
end

--- Get the highlight group for a given node type
--- Matches node_type against patterns in node_type_styles config
---@param node_type string|nil the treesitter node type
---@param is_error boolean whether the chunk has an error
---@return string highlight group name
function ChunkMod:get_hl_group_for_node_type(node_type, is_error)
-- If error, always use error style
if is_error then
return "HLChunk2"
end

-- If no node type or no node_type_styles configured, use default
if not node_type or not self.conf.node_type_styles or vim.tbl_isempty(self.conf.node_type_styles) then
return "HLChunk1"
end

-- Try to match node_type against configured patterns
for pattern, style in pairs(self.conf.node_type_styles) do
if node_type:find(pattern) then
-- Create a dynamic highlight group for this style
hl_group_counter = hl_group_counter + 1
local hl_name = "HLChunkNodeType" .. hl_group_counter
api.nvim_set_hl(0, hl_name, style)
return hl_name
end
end

-- No match, use default
return "HLChunk1"
end

function ChunkMod:render(range, opts)
opts = opts or { error = false, lazy = false }
if not self:shouldRender(range.bufnr) then
Expand Down Expand Up @@ -148,10 +182,12 @@ function ChunkMod:render(range, opts)

local row_opts = {
virt_text_pos = "overlay",
virt_text_repeat_linebreak = true,
hl_mode = "combine",
priority = 100,
}
local text_hl = opts.error and "HLChunk2" or "HLChunk1"
-- Get highlight based on node type (or error/default)
local text_hl = self:get_hl_group_for_node_type(range.node_type, opts.error)
if self.conf.delay == 0 or opts.lazy == false then
for i, vt in ipairs(virt_text_list) do
row_opts.virt_text = { { vt, text_hl } }
Expand Down
4 changes: 2 additions & 2 deletions lua/hlchunk/utils/chunkHelper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ local function get_chunk_range_by_treesitter(pos)
local node_start, _, node_end, _ = cursor_node:range()
if node_start ~= node_end and is_suit_type(node_type) then
return cursor_node:has_error() and chunkHelper.CHUNK_RANGE_RET.CHUNK_ERR or chunkHelper.CHUNK_RANGE_RET.OK,
Scope(pos.bufnr, node_start, node_end)
Scope(pos.bufnr, node_start, node_end, node_type)
end
local parent_node = cursor_node:parent()
if parent_node == cursor_node then
break
end
cursor_node = parent_node
end
return chunkHelper.CHUNK_RANGE_RET.NO_CHUNK, Scope(pos.bufnr, -1, -1)
return chunkHelper.CHUNK_RANGE_RET.NO_CHUNK, Scope(pos.bufnr, -1, -1, nil)
end

---@param opts? {pos: HlChunk.Pos, use_treesitter: boolean}
Expand Down
6 changes: 4 additions & 2 deletions lua/hlchunk/utils/scope.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
---@field bufnr number
---@field start number
---@field finish number
---@overload fun(bufnr: number, start: number, finish: number): HlChunk.Scope
---@field node_type? string treesitter node type (e.g., "function", "if_statement", "for_loop")
---@overload fun(bufnr: number, start: number, finish: number, node_type?: string): HlChunk.Scope
---0-indexing, include start and finish
-- local Scope = class(constructor)
local function Scope(bufnr, start, finish)
local function Scope(bufnr, start, finish, node_type)
return {
bufnr = bufnr,
start = start,
finish = finish,
node_type = node_type,
}
end

Expand Down
1 change: 1 addition & 0 deletions lua/hlchunk/utils/ts_node_type/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local M = {}
M.cpp = require("hlchunk.utils.ts_node_type.cpp")
M.css = require("hlchunk.utils.ts_node_type.css")
M.lua = require("hlchunk.utils.ts_node_type.lua")
M.nix = require("hlchunk.utils.ts_node_type.nix")
M.rust = require("hlchunk.utils.ts_node_type.rust")
M.yaml = require("hlchunk.utils.ts_node_type.yaml")
M.zig = require("hlchunk.utils.ts_node_type.zig")
Expand Down
17 changes: 17 additions & 0 deletions lua/hlchunk/utils/ts_node_type/nix.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- Nix-specific treesitter node types for hlchunk
-- Covers: let expressions, attribute sets, lambda functions, with expressions, etc.
-- Format: node_type = true (table with keys, not array)
return {
let_expression = true, -- let ... in ...
attrset_expression = true, -- { ... }
rec_attrset_expression = true, -- rec { ... }
list_expression = true, -- [ ... ]
lambda_expression = true, -- arg: body
function_expression = true, -- { args }: body
with_expression = true, -- with ...; ...
if_expression = true, -- if ... then ... else ...
assert_expression = true, -- assert ...; ...
binding = true, -- name = value;
inherit = true, -- inherit ...;
inherit_from = true, -- inherit (...) ...;
}