From 0245996907755bc5c542af96b954ecebcb2eed96 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Wed, 17 Apr 2024 10:00:54 -0400 Subject: [PATCH 01/16] feat: allow fat_headlines to be a function --- doc/headlines.txt | 3 ++- lua/headlines/init.lua | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/headlines.txt b/doc/headlines.txt index f62ecdd..b36c1fa 100644 --- a/doc/headlines.txt +++ b/doc/headlines.txt @@ -315,7 +315,8 @@ bullets *headlines-bullets* ------------------------------------------------------------------------------ fat_headlines *headlines-fat_headlines* - Boolean to turn on fat headlines. + Specifies whether or not to use fat headlines. + Can be a boolean or a function returning a boolean. ------------------------------------------------------------------------------ fat_headline_upper_string *headlines-fat_headline_upper_string* diff --git a/lua/headlines/init.lua b/lua/headlines/init.lua index d7aae01..553b5fc 100644 --- a/lua/headlines/init.lua +++ b/lua/headlines/init.lua @@ -293,7 +293,10 @@ M.refresh = function() hl_eol = true, }) - if c.fat_headlines then + local use_fat_headlines = (type(c.fat_headlines) == "boolean") and c.fat_headlines or + ((type(c.fat_headlines) == "function") and c.fat_headlines() or false) + + if use_fat_headlines then local reverse_hl_group = M.make_reverse_highlight(hl_group) local padding_above = { { c.fat_headline_upper_string:rep(width), reverse_hl_group } } From 891b432f23e8d5671d45498a93a8d57a3df1cf11 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Thu, 18 Apr 2024 12:58:36 -0400 Subject: [PATCH 02/16] feat!: make headlines per buffer --- lua/headlines/headline.lua | 270 +++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 lua/headlines/headline.lua diff --git a/lua/headlines/headline.lua b/lua/headlines/headline.lua new file mode 100644 index 0000000..a4452e7 --- /dev/null +++ b/lua/headlines/headline.lua @@ -0,0 +1,270 @@ +local Headline = {} +Headline.__index = Headline + +--local q = require('vim.treesitter.query') + +local use_legacy_query = vim.fn.has "nvim-0.9.0" ~= 1 +local parse_query_save = function(language, query) + -- vim.treesitter.query.parse_query() is deprecated, use vim.treesitter.query.parse() instead + local ok, parsed_query = + pcall(use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) + if not ok then + return nil + end + return parsed_query +end + +---@class HeadlineConfig +---@field query? Query +---@field headline_highlights? table +---@field bullet_highlights? table +---@field bullets? table +---@field codeblock_highlight? string +---@field dash_highlight? string +---@field quote_highlight? string +---@field quote_string? string +---@field fat_headlines? boolean +---@field fat_headline_upper_string? string +---@field fat_headline_lower_string? string + +---@class Headline +---@field config HeadlineConfig +---@field autocmds table +---@field namespace number + +---@type table +Headline.default_config = { + markdown = { + query = parse_query_save( + "markdown", + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@text.title.1.marker.markdown", + "@text.title.2.marker.markdown", + "@text.title.3.marker.markdown", + "@text.title.4.marker.markdown", + "@text.title.5.marker.markdown", + "@text.title.6.marker.markdown", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + rmd = { + query = parse_query_save( + "markdown", + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] + ), + treesitter_language = "markdown", + headline_highlights = { "Headline" }, + bullet_highlights = { + "@text.title.1.marker.markdown", + "@text.title.2.marker.markdown", + "@text.title.3.marker.markdown", + "@text.title.4.marker.markdown", + "@text.title.5.marker.markdown", + "@text.title.6.marker.markdown", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + norg = { + query = parse_query_save( + "norg", + [[ + [ + (heading1_prefix) + (heading2_prefix) + (heading3_prefix) + (heading4_prefix) + (heading5_prefix) + (heading6_prefix) + ] @headline + + (weak_paragraph_delimiter) @dash + (strong_paragraph_delimiter) @doubledash + + ([(ranged_tag + name: (tag_name) @_name + (#eq? @_name "code") + ) + (ranged_verbatim_tag + name: (tag_name) @_name + (#eq? @_name "code") + )] @codeblock (#offset! @codeblock 0 0 1 0)) + + (quote1_prefix) @quote + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@neorg.headings.1.prefix", + "@neorg.headings.2.prefix", + "@neorg.headings.3.prefix", + "@neorg.headings.4.prefix", + "@neorg.headings.5.prefix", + "@neorg.headings.6.prefix", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + doubledash_highlight = "DoubleDash", + doubledash_string = "=", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + org = { + query = parse_query_save( + "org", + [[ + (headline (stars) @headline) + + ( + (expr) @dash + (#match? @dash "^-----+$") + ) + + (block + name: (expr) @_name + (#match? @_name "(SRC|src)") + ) @codeblock + + (paragraph . (expr) @quote + (#eq? @quote ">") + ) + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@org.headline.level1", + "@org.headline.level2", + "@org.headline.level3", + "@org.headline.level4", + "@org.headline.level5", + "@org.headline.level6", + "@org.headline.level7", + "@org.headline.level8", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, +} + + +---Create a new Headline +---@param conf? table +---@return Headline +function Headline.new(conf) + local config = conf and vim.tbl_deep_extend('force', Headline.default_config[vim.bo.filetype] or {}, conf) + or (Headline.default_config[vim.bo.filetype] or {}) + + local bufnr = vim.api.nvim_get_current_buf() + + local headline = setmetatable({ + config = config, + namespace = 'headline_namespace_' .. bufnr + }, Headline) + + local refresh_autocmd = vim.api.nvim_create_autocmd({ + 'FileChangedShellPost', + 'Syntax', + 'TextChanged', + 'InsertLeave', + 'WinScrolled', + }, { + group = 'Headlines', + buffer = bufnr, + desc = 'Refresh buffer local headline', + callback = function() + headline:refresh() + end, + }) + local delete_autocmd = vim.pi.nvim_create_autocmd({ + 'BufDelete', + }, { + group = 'Headlines', + buffer = bufnr, + desc = 'Delete buffer local headline', + callback = function() + headline:delete() + end, + }) + + headline.autocmds = { + refresh = refresh_autocmd, + delete = delete_autocmd + } + + return headline +end + +function Headline:delete() + vim.api.nvim_del_autocmd(self.autocmds.refresh) + vim.api.nvim_del_autocmd(self.autocmds.delete) +end + +function Headline:refresh() + vim.print('Headline refresh') +end From f31348ba8fcd060f213c2dd5c847f89569ade211 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Thu, 18 Apr 2024 13:14:44 -0400 Subject: [PATCH 03/16] fix!: remove legacy code from init.lua --- lua/headlines/headline.lua | 2 + lua/headlines/init.lua | 394 +------------------------------------ 2 files changed, 4 insertions(+), 392 deletions(-) diff --git a/lua/headlines/headline.lua b/lua/headlines/headline.lua index a4452e7..d1dceb9 100644 --- a/lua/headlines/headline.lua +++ b/lua/headlines/headline.lua @@ -268,3 +268,5 @@ end function Headline:refresh() vim.print('Headline refresh') end + +return Headline diff --git a/lua/headlines/init.lua b/lua/headlines/init.lua index 553b5fc..749af13 100644 --- a/lua/headlines/init.lua +++ b/lua/headlines/init.lua @@ -1,397 +1,7 @@ local M = {} -M.namespace = vim.api.nvim_create_namespace "headlines_namespace" -local q = require "vim.treesitter.query" - -local use_legacy_query = vim.fn.has "nvim-0.9.0" ~= 1 - -local parse_query_save = function(language, query) - -- vim.treesitter.query.parse_query() is deprecated, use vim.treesitter.query.parse() instead - local ok, parsed_query = - pcall(use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) - if not ok then - return nil - end - return parsed_query -end - -M.config = { - markdown = { - query = parse_query_save( - "markdown", - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - rmd = { - query = parse_query_save( - "markdown", - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] - ), - treesitter_language = "markdown", - headline_highlights = { "Headline" }, - bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - norg = { - query = parse_query_save( - "norg", - [[ - [ - (heading1_prefix) - (heading2_prefix) - (heading3_prefix) - (heading4_prefix) - (heading5_prefix) - (heading6_prefix) - ] @headline - - (weak_paragraph_delimiter) @dash - (strong_paragraph_delimiter) @doubledash - - ([(ranged_tag - name: (tag_name) @_name - (#eq? @_name "code") - ) - (ranged_verbatim_tag - name: (tag_name) @_name - (#eq? @_name "code") - )] @codeblock (#offset! @codeblock 0 0 1 0)) - - (quote1_prefix) @quote - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@neorg.headings.1.prefix", - "@neorg.headings.2.prefix", - "@neorg.headings.3.prefix", - "@neorg.headings.4.prefix", - "@neorg.headings.5.prefix", - "@neorg.headings.6.prefix", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - doubledash_highlight = "DoubleDash", - doubledash_string = "=", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - org = { - query = parse_query_save( - "org", - [[ - (headline (stars) @headline) - - ( - (expr) @dash - (#match? @dash "^-----+$") - ) - - (block - name: (expr) @_name - (#match? @_name "(SRC|src)") - ) @codeblock - - (paragraph . (expr) @quote - (#eq? @quote ">") - ) - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@org.headline.level1", - "@org.headline.level2", - "@org.headline.level3", - "@org.headline.level4", - "@org.headline.level5", - "@org.headline.level6", - "@org.headline.level7", - "@org.headline.level8", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, -} - -M.make_reverse_highlight = function(name) - local reverse_name = name .. "Reverse" - - if vim.fn.synIDattr(reverse_name, "fg") ~= "" then - return reverse_name - end - - local highlight = vim.fn.synIDtrans(vim.fn.hlID(name)) - local gui_bg = vim.fn.synIDattr(highlight, "bg", "gui") - local cterm_bg = vim.fn.synIDattr(highlight, "bg", "cterm") - - if gui_bg == "" then - gui_bg = "None" - end - if cterm_bg == "" then - cterm_bg = "None" - end - - vim.cmd(string.format("highlight %s guifg=%s ctermfg=%s", reverse_name, gui_bg or "None", cterm_bg or "None")) - return reverse_name -end - -M.setup = function(config) - config = config or {} - M.config = vim.tbl_deep_extend("force", M.config, config) - - -- tbl_deep_extend does not handle metatables - for filetype, conf in pairs(config) do - if conf.query then - M.config[filetype].query = conf.query - end - end - - vim.cmd [[ - highlight default link Headline ColorColumn - highlight default link CodeBlock ColorColumn - highlight default link Dash LineNr - highlight default link DoubleDash LineNr - highlight default link Quote LineNr - ]] - - vim.cmd [[ - augroup Headlines - autocmd FileChangedShellPost,Syntax,TextChanged,InsertLeave,WinScrolled * lua require('headlines').refresh() - augroup END - ]] -end - -local nvim_buf_set_extmark = function(...) - pcall(vim.api.nvim_buf_set_extmark, ...) -end - -M.refresh = function() - local c = M.config[vim.bo.filetype] - local bufnr = vim.api.nvim_get_current_buf() - vim.api.nvim_buf_clear_namespace(0, M.namespace, 0, -1) - - if not c or not c.query then - return - end - - local language = c.treesitter_language or vim.bo.filetype - local language_tree = vim.treesitter.get_parser(bufnr, language) - local syntax_tree = language_tree:parse() - local root = syntax_tree[1]:root() - local win_view = vim.fn.winsaveview() - local left_offset = win_view.leftcol - local width = vim.api.nvim_win_get_width(0) - local last_fat_headline = -1 - - for _, match, metadata in c.query:iter_matches(root, bufnr) do - for id, node in pairs(match) do - local capture = c.query.captures[id] - local start_row, start_column, end_row, end_column = - unpack(vim.tbl_extend("force", { node:range() }, (metadata[id] or {}).range or {})) - - if capture == "headline" and c.headline_highlights then - -- vim.treesitter.query.get_node_text() is deprecated, use vim.treesitter.get_node_text() instead. - local get_text_function = use_legacy_query and q.get_node_text(node, bufnr) - or vim.treesitter.get_node_text(node, bufnr) - local level = #vim.trim(get_text_function) - local hl_group = c.headline_highlights[math.min(level, #c.headline_highlights)] - local bullet_hl_group = c.bullet_highlights[math.min(level, #c.bullet_highlights)] - - local virt_text = {} - if c.bullets and #c.bullets > 0 then - local bullet = c.bullets[((level - 1) % #c.bullets) + 1] - virt_text[1] = { string.rep(" ", level - 1) .. bullet, { hl_group, bullet_hl_group } } - end - - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - end_col = 0, - end_row = start_row + 1, - hl_group = hl_group, - virt_text = virt_text, - virt_text_pos = "overlay", - hl_eol = true, - }) - - local use_fat_headlines = (type(c.fat_headlines) == "boolean") and c.fat_headlines or - ((type(c.fat_headlines) == "function") and c.fat_headlines() or false) - - if use_fat_headlines then - local reverse_hl_group = M.make_reverse_highlight(hl_group) - - local padding_above = { { c.fat_headline_upper_string:rep(width), reverse_hl_group } } - if start_row > 0 then - local line_above = vim.api.nvim_buf_get_lines(bufnr, start_row - 1, start_row, false)[1] - if line_above == "" and start_row - 1 ~= last_fat_headline then - nvim_buf_set_extmark(bufnr, M.namespace, start_row - 1, 0, { - virt_text = padding_above, - virt_text_pos = "overlay", - virt_text_win_col = 0, - hl_mode = "combine", - }) - else - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - virt_lines_above = true, - virt_lines = { padding_above }, - }) - end - end - - local padding_below = { { c.fat_headline_lower_string:rep(width), reverse_hl_group } } - local line_below = vim.api.nvim_buf_get_lines(bufnr, start_row + 1, start_row + 2, false)[1] - if line_below == "" then - nvim_buf_set_extmark(bufnr, M.namespace, start_row + 1, 0, { - virt_text = padding_below, - virt_text_pos = "overlay", - virt_text_win_col = 0, - hl_mode = "combine", - }) - last_fat_headline = start_row + 1 - else - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - virt_lines = { padding_below }, - }) - end - end - end - - if capture == "dash" and c.dash_highlight and c.dash_string then - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - virt_text = { { c.dash_string:rep(width), c.dash_highlight } }, - virt_text_pos = "overlay", - hl_mode = "combine", - }) - end - - if capture == "doubledash" and c.doubledash_highlight and c.doubledash_string then - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - virt_text = { { c.doubledash_string:rep(width), c.doubledash_highlight } }, - virt_text_pos = "overlay", - hl_mode = "combine", - }) - end - - if capture == "codeblock" and c.codeblock_highlight then - nvim_buf_set_extmark(bufnr, M.namespace, start_row, 0, { - end_col = 0, - end_row = end_row, - hl_group = c.codeblock_highlight, - hl_eol = true, - }) - - local start_line = vim.api.nvim_buf_get_lines(bufnr, start_row, start_row + 1, false)[1] - local _, padding = start_line:find "^ +" - local codeblock_padding = math.max((padding or 0) - left_offset, 0) - - if codeblock_padding > 0 then - for i = start_row, end_row - 1 do - nvim_buf_set_extmark(bufnr, M.namespace, i, 0, { - virt_text = { { string.rep(" ", codeblock_padding), "Normal" } }, - virt_text_win_col = 0, - priority = 1, - }) - end - end - end - - if capture == "quote" and c.quote_highlight and c.quote_string then - if vim.bo.filetype == "markdown" then - local text = vim.api.nvim_buf_get_text(bufnr, start_row, start_column, end_row, end_column, {})[1] - nvim_buf_set_extmark(bufnr, M.namespace, start_row, start_column, { - virt_text = { { text:gsub(">", c.quote_string), c.quote_highlight } }, - virt_text_pos = "overlay", - hl_mode = "combine", - }) - else - nvim_buf_set_extmark(bufnr, M.namespace, start_row, start_column, { - virt_text = { { c.quote_string, c.quote_highlight } }, - virt_text_pos = "overlay", - hl_mode = "combine", - }) - end - end - end - end +function M.setup() + vim.api.nvim_create_augroup('Headline', {}) end return M From 6045f92cd59df0bc78abce755b7bab9c2eb841cd Mon Sep 17 00:00:00 2001 From: River Chubb Date: Fri, 19 Apr 2024 14:53:25 -0400 Subject: [PATCH 04/16] fix: current buffer detection --- lua/headlines/class.lua | 82 +++++++++++ lua/headlines/headline.lua | 272 ------------------------------------- lua/headlines/init.lua | 5 +- 3 files changed, 86 insertions(+), 273 deletions(-) create mode 100644 lua/headlines/class.lua delete mode 100644 lua/headlines/headline.lua diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua new file mode 100644 index 0000000..44070b8 --- /dev/null +++ b/lua/headlines/class.lua @@ -0,0 +1,82 @@ +local Headline = {} +Headline.__index = Headline + +---@class HeadlineConfig +---@field query? Query +---@field headline_highlights? table +---@field bullet_highlights? table +---@field bullets? table +---@field codeblock_highlight? string +---@field dash_highlight? string +---@field quote_highlight? string +---@field quote_string? string +---@field fat_headlines? boolean +---@field fat_headline_upper_string? string +---@field fat_headline_lower_string? string + +---@class Headline +---@field config HeadlineConfig +---@field namespace number +---@field buffer number +---@field autocmds table + +---Create a new Headline +---@param config? table +---@return Headline +function Headline.new(config) + return setmetatable({ + config = config, + namespace = '', + buffer = 0, + autocmds = {} + }, Headline) +end + +---Attach headline to buffer +---@param buffer number +---@return Headline +function Headline:attach(buffer) + local refresh_autocmd = vim.api.nvim_create_autocmd({ + 'FileChangedShellPost', + 'Syntax', + 'TextChanged', + 'InsertLeave', + 'WinScrolled', + }, { + group = 'Headlines', + buffer = buffer, + desc = 'Refresh buffer local headline', + callback = function() + self:refresh() + end, + }) + local delete_autocmd = vim.api.nvim_create_autocmd({ + 'BufDelete', + }, { + group = 'Headlines', + buffer = buffer, + desc = 'Delete buffer local headline', + callback = function() + self:delete() + end, + }) + self.namespace = 'headline_namespace_' .. buffer + self.buffer = buffer + self.autocmds = { + refresh = refresh_autocmd, + delete = delete_autocmd + } + + return self +end + +function Headline:delete() + vim.api.nvim_del_autocmd(self.autocmds.refresh) + vim.api.nvim_del_autocmd(self.autocmds.delete) +end + +function Headline:refresh() + vim.print('Headline refresh: ' .. self.buffer) +end + +return Headline diff --git a/lua/headlines/headline.lua b/lua/headlines/headline.lua deleted file mode 100644 index d1dceb9..0000000 --- a/lua/headlines/headline.lua +++ /dev/null @@ -1,272 +0,0 @@ -local Headline = {} -Headline.__index = Headline - ---local q = require('vim.treesitter.query') - -local use_legacy_query = vim.fn.has "nvim-0.9.0" ~= 1 -local parse_query_save = function(language, query) - -- vim.treesitter.query.parse_query() is deprecated, use vim.treesitter.query.parse() instead - local ok, parsed_query = - pcall(use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) - if not ok then - return nil - end - return parsed_query -end - ----@class HeadlineConfig ----@field query? Query ----@field headline_highlights? table ----@field bullet_highlights? table ----@field bullets? table ----@field codeblock_highlight? string ----@field dash_highlight? string ----@field quote_highlight? string ----@field quote_string? string ----@field fat_headlines? boolean ----@field fat_headline_upper_string? string ----@field fat_headline_lower_string? string - ----@class Headline ----@field config HeadlineConfig ----@field autocmds table ----@field namespace number - ----@type table -Headline.default_config = { - markdown = { - query = parse_query_save( - "markdown", - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - rmd = { - query = parse_query_save( - "markdown", - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] - ), - treesitter_language = "markdown", - headline_highlights = { "Headline" }, - bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - norg = { - query = parse_query_save( - "norg", - [[ - [ - (heading1_prefix) - (heading2_prefix) - (heading3_prefix) - (heading4_prefix) - (heading5_prefix) - (heading6_prefix) - ] @headline - - (weak_paragraph_delimiter) @dash - (strong_paragraph_delimiter) @doubledash - - ([(ranged_tag - name: (tag_name) @_name - (#eq? @_name "code") - ) - (ranged_verbatim_tag - name: (tag_name) @_name - (#eq? @_name "code") - )] @codeblock (#offset! @codeblock 0 0 1 0)) - - (quote1_prefix) @quote - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@neorg.headings.1.prefix", - "@neorg.headings.2.prefix", - "@neorg.headings.3.prefix", - "@neorg.headings.4.prefix", - "@neorg.headings.5.prefix", - "@neorg.headings.6.prefix", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - doubledash_highlight = "DoubleDash", - doubledash_string = "=", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, - org = { - query = parse_query_save( - "org", - [[ - (headline (stars) @headline) - - ( - (expr) @dash - (#match? @dash "^-----+$") - ) - - (block - name: (expr) @_name - (#match? @_name "(SRC|src)") - ) @codeblock - - (paragraph . (expr) @quote - (#eq? @quote ">") - ) - ]] - ), - headline_highlights = { "Headline" }, - bullet_highlights = { - "@org.headline.level1", - "@org.headline.level2", - "@org.headline.level3", - "@org.headline.level4", - "@org.headline.level5", - "@org.headline.level6", - "@org.headline.level7", - "@org.headline.level8", - }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", - fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", - }, -} - - ----Create a new Headline ----@param conf? table ----@return Headline -function Headline.new(conf) - local config = conf and vim.tbl_deep_extend('force', Headline.default_config[vim.bo.filetype] or {}, conf) - or (Headline.default_config[vim.bo.filetype] or {}) - - local bufnr = vim.api.nvim_get_current_buf() - - local headline = setmetatable({ - config = config, - namespace = 'headline_namespace_' .. bufnr - }, Headline) - - local refresh_autocmd = vim.api.nvim_create_autocmd({ - 'FileChangedShellPost', - 'Syntax', - 'TextChanged', - 'InsertLeave', - 'WinScrolled', - }, { - group = 'Headlines', - buffer = bufnr, - desc = 'Refresh buffer local headline', - callback = function() - headline:refresh() - end, - }) - local delete_autocmd = vim.pi.nvim_create_autocmd({ - 'BufDelete', - }, { - group = 'Headlines', - buffer = bufnr, - desc = 'Delete buffer local headline', - callback = function() - headline:delete() - end, - }) - - headline.autocmds = { - refresh = refresh_autocmd, - delete = delete_autocmd - } - - return headline -end - -function Headline:delete() - vim.api.nvim_del_autocmd(self.autocmds.refresh) - vim.api.nvim_del_autocmd(self.autocmds.delete) -end - -function Headline:refresh() - vim.print('Headline refresh') -end - -return Headline diff --git a/lua/headlines/init.lua b/lua/headlines/init.lua index 749af13..62aa571 100644 --- a/lua/headlines/init.lua +++ b/lua/headlines/init.lua @@ -1,7 +1,10 @@ local M = {} function M.setup() - vim.api.nvim_create_augroup('Headline', {}) + vim.api.nvim_create_augroup('Headlines', {}) + vim.api.nvim_set_hl(0, 'Headline', { link = 'ColorColumn' }) + vim.api.nvim_set_hl(0, 'CodeBlock', { link = 'ColorColumn' }) + vim.api.nvim_set_hl(0, 'Dash', { link = 'LineNr' }) end return M From dc9faa72b1edccd0f5d868836bd0737dd8351db8 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sat, 20 Apr 2024 08:21:16 -0400 Subject: [PATCH 05/16] feat: seperate config to it's own file --- lua/headlines/class.lua | 17 +++---------- lua/headlines/config.lua | 51 ++++++++++++++++++++++++++++++++++++++ lua/headlines/renderer.lua | 15 +++++++++++ 3 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 lua/headlines/config.lua create mode 100644 lua/headlines/renderer.lua diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua index 44070b8..f0b5857 100644 --- a/lua/headlines/class.lua +++ b/lua/headlines/class.lua @@ -1,18 +1,7 @@ local Headline = {} Headline.__index = Headline ----@class HeadlineConfig ----@field query? Query ----@field headline_highlights? table ----@field bullet_highlights? table ----@field bullets? table ----@field codeblock_highlight? string ----@field dash_highlight? string ----@field quote_highlight? string ----@field quote_string? string ----@field fat_headlines? boolean ----@field fat_headline_upper_string? string ----@field fat_headline_lower_string? string +local renderer = require('headlines.renderer') ---@class Headline ---@field config HeadlineConfig @@ -60,7 +49,7 @@ function Headline:attach(buffer) self:delete() end, }) - self.namespace = 'headline_namespace_' .. buffer + self.namespace = vim.api.nvim_create_namespace('headline_namespace_' .. buffer) self.buffer = buffer self.autocmds = { refresh = refresh_autocmd, @@ -76,7 +65,7 @@ function Headline:delete() end function Headline:refresh() - vim.print('Headline refresh: ' .. self.buffer) + --renderer.render(self) end return Headline diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua new file mode 100644 index 0000000..29f0e73 --- /dev/null +++ b/lua/headlines/config.lua @@ -0,0 +1,51 @@ +local Config = {} + +---@class HeadlineConfig +---@field query? Query +---@field headline_highlights? table +---@field bullet_highlights? table +---@field bullets? table +---@field codeblock_highlight? string +---@field dash_highlight? string +---@field quote_highlight? string +---@field quote_string? string +---@field fat_headlines? boolean +---@field fat_headline_upper_string? string +---@field fat_headline_lower_string? string + +---Get headline config defaults +---@return table +function Config.defaults() + return { + markdown = {}, + rmd = {}, + norg = {}, + org = {}, + } +end + +---Get headline generic config defaults +---@return HeadlineConfig +function Config.generic_defaults() + return {} +end + +function Config.filetype_defaults(filetype) + local defaults = Config.defaults() + return defaults[filetype] or Config.generic_defaults() +end + +function Config.merge(user_config, default_config) + local merged = {} + + merged = user_config and vim.tbl_deep_extend('force', default_config or {}, user_config) or (default_config or {}) + + -- tbl_deep_extend does not handle metatables + if user_config.query then + merged.query = user_config.query + end + + return merged +end + +return Config diff --git a/lua/headlines/renderer.lua b/lua/headlines/renderer.lua new file mode 100644 index 0000000..2e39b5c --- /dev/null +++ b/lua/headlines/renderer.lua @@ -0,0 +1,15 @@ +local Renderer = {} + +---Render headlines +---@param headline Headline +function Renderer.render(headline) + vim.api.nvim_buf_clear_namespace(headline.buffer, headline.namespace, 0, -1) + vim.api.nvim_buf_set_extmark(headline.buffer, headline.namespace, 0, 0, { + end_row = 1, + end_col = 0, + hl_group = 'Headline', + hl_eol = true, + }) +end + +return Renderer From 377caad6007e87ab9aba61ec76fb8933690fc246 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sat, 20 Apr 2024 12:23:53 -0400 Subject: [PATCH 06/16] fix: config merging --- lua/headlines/class.lua | 8 ++++++-- lua/headlines/config.lua | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua index f0b5857..de47b51 100644 --- a/lua/headlines/class.lua +++ b/lua/headlines/class.lua @@ -2,6 +2,7 @@ local Headline = {} Headline.__index = Headline local renderer = require('headlines.renderer') +local config_manager = require('headlines.config') ---@class Headline ---@field config HeadlineConfig @@ -10,7 +11,7 @@ local renderer = require('headlines.renderer') ---@field autocmds table ---Create a new Headline ----@param config? table +---@param config? HeadlineConfig ---@return Headline function Headline.new(config) return setmetatable({ @@ -49,6 +50,9 @@ function Headline:attach(buffer) self:delete() end, }) + + local filetype = vim.api.nvim_buf_get_option(buffer, 'filetype') + self.config = config_manager.merge(self.config, config_manager.filetype_defaults(filetype)) self.namespace = vim.api.nvim_create_namespace('headline_namespace_' .. buffer) self.buffer = buffer self.autocmds = { @@ -65,7 +69,7 @@ function Headline:delete() end function Headline:refresh() - --renderer.render(self) + renderer.render(self) end return Headline diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua index 29f0e73..2cfe30d 100644 --- a/lua/headlines/config.lua +++ b/lua/headlines/config.lua @@ -30,15 +30,24 @@ function Config.generic_defaults() return {} end +---Get filetype specific headline config defaults. +---If one is not found, then it returns a generic config +---@param filetype string +---@return HeadlineConfig function Config.filetype_defaults(filetype) local defaults = Config.defaults() return defaults[filetype] or Config.generic_defaults() end +---Merge user config with default config. +---Uses user config when applicable, otherwise uses default config +---@param user_config HeadlineConfig +---@param default_config HeadlineConfig +---@return HeadlineConfig function Config.merge(user_config, default_config) local merged = {} - merged = user_config and vim.tbl_deep_extend('force', default_config or {}, user_config) or (default_config or {}) + merged = user_config and vim.tbl_deep_extend('force', default_config, user_config) or default_config -- tbl_deep_extend does not handle metatables if user_config.query then From 717f0add11414747837583f959f246112fb93de1 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sat, 20 Apr 2024 12:31:05 -0400 Subject: [PATCH 07/16] feat: add default configs --- lua/headlines/config.lua | 182 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 4 deletions(-) diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua index 2cfe30d..cf44488 100644 --- a/lua/headlines/config.lua +++ b/lua/headlines/config.lua @@ -1,5 +1,7 @@ local Config = {} +local utils = require('headlines.utils') + ---@class HeadlineConfig ---@field query? Query ---@field headline_highlights? table @@ -17,10 +19,182 @@ local Config = {} ---@return table function Config.defaults() return { - markdown = {}, - rmd = {}, - norg = {}, - org = {}, + markdown = { + query = utils.parse_query_save( + "markdown", + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@text.title.1.marker.markdown", + "@text.title.2.marker.markdown", + "@text.title.3.marker.markdown", + "@text.title.4.marker.markdown", + "@text.title.5.marker.markdown", + "@text.title.6.marker.markdown", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + rmd = { + query = utils.parse_query_save( + "markdown", + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] + ), + treesitter_language = "markdown", + headline_highlights = { "Headline" }, + bullet_highlights = { + "@text.title.1.marker.markdown", + "@text.title.2.marker.markdown", + "@text.title.3.marker.markdown", + "@text.title.4.marker.markdown", + "@text.title.5.marker.markdown", + "@text.title.6.marker.markdown", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + norg = { + query = utils.parse_query_save( + "norg", + [[ + [ + (heading1_prefix) + (heading2_prefix) + (heading3_prefix) + (heading4_prefix) + (heading5_prefix) + (heading6_prefix) + ] @headline + + (weak_paragraph_delimiter) @dash + (strong_paragraph_delimiter) @doubledash + + ([(ranged_tag + name: (tag_name) @_name + (#eq? @_name "code") + ) + (ranged_verbatim_tag + name: (tag_name) @_name + (#eq? @_name "code") + )] @codeblock (#offset! @codeblock 0 0 1 0)) + + (quote1_prefix) @quote + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@neorg.headings.1.prefix", + "@neorg.headings.2.prefix", + "@neorg.headings.3.prefix", + "@neorg.headings.4.prefix", + "@neorg.headings.5.prefix", + "@neorg.headings.6.prefix", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + doubledash_highlight = "DoubleDash", + doubledash_string = "=", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, + org = { + query = utils.parse_query_save( + "org", + [[ + (headline (stars) @headline) + + ( + (expr) @dash + (#match? @dash "^-----+$") + ) + + (block + name: (expr) @_name + (#match? @_name "(SRC|src)") + ) @codeblock + + (paragraph . (expr) @quote + (#eq? @quote ">") + ) + ]] + ), + headline_highlights = { "Headline" }, + bullet_highlights = { + "@org.headline.level1", + "@org.headline.level2", + "@org.headline.level3", + "@org.headline.level4", + "@org.headline.level5", + "@org.headline.level6", + "@org.headline.level7", + "@org.headline.level8", + }, + bullets = { "◉", "○", "✸", "✿" }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + dash_string = "-", + quote_highlight = "Quote", + quote_string = "┃", + fat_headlines = true, + fat_headline_upper_string = "▃", + fat_headline_lower_string = "🬂", + }, } end From 79d1ff6beb9525f3c57a655cf7d8976b01633963 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sat, 20 Apr 2024 13:03:01 -0400 Subject: [PATCH 08/16] fix: swap double quotes with single --- lua/headlines/config.lua | 148 +++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua index cf44488..9b27ec8 100644 --- a/lua/headlines/config.lua +++ b/lua/headlines/config.lua @@ -21,7 +21,7 @@ function Config.defaults() return { markdown = { query = utils.parse_query_save( - "markdown", + 'markdown', [[ (atx_heading [ (atx_h1_marker) @@ -42,28 +42,28 @@ function Config.defaults() (block_quote (block_continuation) @quote) ]] ), - headline_highlights = { "Headline" }, + headline_highlights = { 'Headline' }, bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", + '@text.title.1.marker.markdown', + '@text.title.2.marker.markdown', + '@text.title.3.marker.markdown', + '@text.title.4.marker.markdown', + '@text.title.5.marker.markdown', + '@text.title.6.marker.markdown', }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", + bullets = { '◉', '○', '✸', '✿' }, + codeblock_highlight = 'CodeBlock', + dash_highlight = 'Dash', + dash_string = '-', + quote_highlight = 'Quote', + quote_string = '┃', fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", + fat_headline_upper_string = '▃', + fat_headline_lower_string = '🬂', }, rmd = { query = utils.parse_query_save( - "markdown", + 'markdown', [[ (atx_heading [ (atx_h1_marker) @@ -84,29 +84,29 @@ function Config.defaults() (block_quote (block_continuation) @quote) ]] ), - treesitter_language = "markdown", - headline_highlights = { "Headline" }, + treesitter_language = 'markdown', + headline_highlights = { 'Headline' }, bullet_highlights = { - "@text.title.1.marker.markdown", - "@text.title.2.marker.markdown", - "@text.title.3.marker.markdown", - "@text.title.4.marker.markdown", - "@text.title.5.marker.markdown", - "@text.title.6.marker.markdown", + '@text.title.1.marker.markdown', + '@text.title.2.marker.markdown', + '@text.title.3.marker.markdown', + '@text.title.4.marker.markdown', + '@text.title.5.marker.markdown', + '@text.title.6.marker.markdown', }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", + bullets = { '◉', '○', '✸', '✿' }, + codeblock_highlight = 'CodeBlock', + dash_highlight = 'Dash', + dash_string = '-', + quote_highlight = 'Quote', + quote_string = '┃', fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", + fat_headline_upper_string = '▃', + fat_headline_lower_string = '🬂', }, norg = { query = utils.parse_query_save( - "norg", + 'norg', [[ [ (heading1_prefix) @@ -122,78 +122,78 @@ function Config.defaults() ([(ranged_tag name: (tag_name) @_name - (#eq? @_name "code") + (#eq? @_name 'code') ) (ranged_verbatim_tag name: (tag_name) @_name - (#eq? @_name "code") + (#eq? @_name 'code') )] @codeblock (#offset! @codeblock 0 0 1 0)) (quote1_prefix) @quote ]] ), - headline_highlights = { "Headline" }, + headline_highlights = { 'Headline' }, bullet_highlights = { - "@neorg.headings.1.prefix", - "@neorg.headings.2.prefix", - "@neorg.headings.3.prefix", - "@neorg.headings.4.prefix", - "@neorg.headings.5.prefix", - "@neorg.headings.6.prefix", + '@neorg.headings.1.prefix', + '@neorg.headings.2.prefix', + '@neorg.headings.3.prefix', + '@neorg.headings.4.prefix', + '@neorg.headings.5.prefix', + '@neorg.headings.6.prefix', }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - doubledash_highlight = "DoubleDash", - doubledash_string = "=", - quote_highlight = "Quote", - quote_string = "┃", + bullets = { '◉', '○', '✸', '✿' }, + codeblock_highlight = 'CodeBlock', + dash_highlight = 'Dash', + dash_string = '-', + doubledash_highlight = 'DoubleDash', + doubledash_string = '=', + quote_highlight = 'Quote', + quote_string = '┃', fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", + fat_headline_upper_string = '▃', + fat_headline_lower_string = '🬂', }, org = { query = utils.parse_query_save( - "org", + 'org', [[ (headline (stars) @headline) ( (expr) @dash - (#match? @dash "^-----+$") + (#match? @dash '^-----+$') ) (block name: (expr) @_name - (#match? @_name "(SRC|src)") + (#match? @_name '(SRC|src)') ) @codeblock (paragraph . (expr) @quote - (#eq? @quote ">") + (#eq? @quote '>') ) ]] ), - headline_highlights = { "Headline" }, + headline_highlights = { 'Headline' }, bullet_highlights = { - "@org.headline.level1", - "@org.headline.level2", - "@org.headline.level3", - "@org.headline.level4", - "@org.headline.level5", - "@org.headline.level6", - "@org.headline.level7", - "@org.headline.level8", + '@org.headline.level1', + '@org.headline.level2', + '@org.headline.level3', + '@org.headline.level4', + '@org.headline.level5', + '@org.headline.level6', + '@org.headline.level7', + '@org.headline.level8', }, - bullets = { "◉", "○", "✸", "✿" }, - codeblock_highlight = "CodeBlock", - dash_highlight = "Dash", - dash_string = "-", - quote_highlight = "Quote", - quote_string = "┃", + bullets = { '◉', '○', '✸', '✿' }, + codeblock_highlight = 'CodeBlock', + dash_highlight = 'Dash', + dash_string = '-', + quote_highlight = 'Quote', + quote_string = '┃', fat_headlines = true, - fat_headline_upper_string = "▃", - fat_headline_lower_string = "🬂", + fat_headline_upper_string = '▃', + fat_headline_lower_string = '🬂', }, } end From 7c5b8ab8af7844a807ce5473a48edf766c14381e Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 11:30:01 -0400 Subject: [PATCH 09/16] fix: add parse_query_save function --- lua/headlines/utils.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lua/headlines/utils.lua diff --git a/lua/headlines/utils.lua b/lua/headlines/utils.lua new file mode 100644 index 0000000..9f80cd2 --- /dev/null +++ b/lua/headlines/utils.lua @@ -0,0 +1,18 @@ +local Utils = {} + +local use_legacy_query = (vim.fn.has('nvim-0.9.0') ~= 1) +---Parse treesitter query +---@param language string +---@param query string +---@return Query | nil +function Utils.parse_query_save(language, query) + local ok, parsed_query = pcall(use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) + + if not ok then + return nil + end + + return parsed_query +end + +return Utils From 05e7718de03ab585b52debcdee4118415a1922a2 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 19:12:42 -0400 Subject: [PATCH 10/16] feat: add render function --- lua/headlines/class.lua | 2 + lua/headlines/config.lua | 171 +++++++++++++++++++------------------ lua/headlines/init.lua | 8 +- lua/headlines/renderer.lua | 112 ++++++++++++++++++++++-- lua/headlines/utils.lua | 14 ++- 5 files changed, 213 insertions(+), 94 deletions(-) diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua index de47b51..08101c9 100644 --- a/lua/headlines/class.lua +++ b/lua/headlines/class.lua @@ -60,6 +60,8 @@ function Headline:attach(buffer) delete = delete_autocmd } + self:refresh() + return self end diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua index 9b27ec8..938e203 100644 --- a/lua/headlines/config.lua +++ b/lua/headlines/config.lua @@ -9,11 +9,15 @@ local utils = require('headlines.utils') ---@field bullets? table ---@field codeblock_highlight? string ---@field dash_highlight? string +---@field dash_string? string +---@field doubledash_highlight? string +---@field doubledash_string? string ---@field quote_highlight? string ---@field quote_string? string ---@field fat_headlines? boolean ---@field fat_headline_upper_string? string ---@field fat_headline_lower_string? string +---@field treesitter_language? string ---Get headline config defaults ---@return table @@ -21,26 +25,26 @@ function Config.defaults() return { markdown = { query = utils.parse_query_save( - 'markdown', - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] + 'markdown', + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] ), headline_highlights = { 'Headline' }, bullet_highlights = { @@ -63,26 +67,26 @@ function Config.defaults() }, rmd = { query = utils.parse_query_save( - 'markdown', - [[ - (atx_heading [ - (atx_h1_marker) - (atx_h2_marker) - (atx_h3_marker) - (atx_h4_marker) - (atx_h5_marker) - (atx_h6_marker) - ] @headline) - - (thematic_break) @dash - - (fenced_code_block) @codeblock - - (block_quote_marker) @quote - (block_quote (paragraph (inline (block_continuation) @quote))) - (block_quote (paragraph (block_continuation) @quote)) - (block_quote (block_continuation) @quote) - ]] + 'markdown', + [[ + (atx_heading [ + (atx_h1_marker) + (atx_h2_marker) + (atx_h3_marker) + (atx_h4_marker) + (atx_h5_marker) + (atx_h6_marker) + ] @headline) + + (thematic_break) @dash + + (fenced_code_block) @codeblock + + (block_quote_marker) @quote + (block_quote (paragraph (inline (block_continuation) @quote))) + (block_quote (paragraph (block_continuation) @quote)) + (block_quote (block_continuation) @quote) + ]] ), treesitter_language = 'markdown', headline_highlights = { 'Headline' }, @@ -106,31 +110,31 @@ function Config.defaults() }, norg = { query = utils.parse_query_save( - 'norg', - [[ - [ - (heading1_prefix) - (heading2_prefix) - (heading3_prefix) - (heading4_prefix) - (heading5_prefix) - (heading6_prefix) - ] @headline - - (weak_paragraph_delimiter) @dash - (strong_paragraph_delimiter) @doubledash - - ([(ranged_tag - name: (tag_name) @_name - (#eq? @_name 'code') - ) - (ranged_verbatim_tag - name: (tag_name) @_name - (#eq? @_name 'code') - )] @codeblock (#offset! @codeblock 0 0 1 0)) - - (quote1_prefix) @quote - ]] + 'norg', + [[ + [ + (heading1_prefix) + (heading2_prefix) + (heading3_prefix) + (heading4_prefix) + (heading5_prefix) + (heading6_prefix) + ] @headline + + (weak_paragraph_delimiter) @dash + (strong_paragraph_delimiter) @doubledash + + ([(ranged_tag + name: (tag_name) @_name + (#eq? @_name "code") + ) + (ranged_verbatim_tag + name: (tag_name) @_name + (#eq? @_name "code") + )] @codeblock (#offset! @codeblock 0 0 1 0)) + + (quote1_prefix) @quote + ]] ), headline_highlights = { 'Headline' }, bullet_highlights = { @@ -152,27 +156,28 @@ function Config.defaults() fat_headlines = true, fat_headline_upper_string = '▃', fat_headline_lower_string = '🬂', + treesitter_language = 'norg', }, org = { query = utils.parse_query_save( - 'org', - [[ - (headline (stars) @headline) - - ( - (expr) @dash - (#match? @dash '^-----+$') - ) - - (block - name: (expr) @_name - (#match? @_name '(SRC|src)') - ) @codeblock - - (paragraph . (expr) @quote - (#eq? @quote '>') - ) - ]] + 'org', + [[ + (headline (stars) @headline) + + ( + (expr) @dash + (#match? @dash "^-----+$") + ) + + (block + name: (expr) @_name + (#match? @_name "(SRC|src)") + ) @codeblock + + (paragraph . (expr) @quote + (#eq? @quote ">") + ) + ]] ), headline_highlights = { 'Headline' }, bullet_highlights = { diff --git a/lua/headlines/init.lua b/lua/headlines/init.lua index 62aa571..e09df8a 100644 --- a/lua/headlines/init.lua +++ b/lua/headlines/init.lua @@ -2,9 +2,11 @@ local M = {} function M.setup() vim.api.nvim_create_augroup('Headlines', {}) - vim.api.nvim_set_hl(0, 'Headline', { link = 'ColorColumn' }) - vim.api.nvim_set_hl(0, 'CodeBlock', { link = 'ColorColumn' }) - vim.api.nvim_set_hl(0, 'Dash', { link = 'LineNr' }) + vim.api.nvim_set_hl(0, 'Headline', { default = true, link = 'ColorColumn' }) + vim.api.nvim_set_hl(0, 'CodeBlock', { default = true, link = 'ColorColumn' }) + vim.api.nvim_set_hl(0, 'Dash', { default = true, link = 'LineNr' }) + vim.api.nvim_set_hl(0, 'DoubleDash', { default = true, link = 'LineNr' }) + vim.api.nvim_set_hl(0, 'Qoute', { default = true, link = 'LineNr' }) end return M diff --git a/lua/headlines/renderer.lua b/lua/headlines/renderer.lua index 2e39b5c..5cd103f 100644 --- a/lua/headlines/renderer.lua +++ b/lua/headlines/renderer.lua @@ -1,15 +1,115 @@ local Renderer = {} +local utils = require('headlines.utils') +local treesitter_query = require('vim.treesitter.query') + ---Render headlines ---@param headline Headline function Renderer.render(headline) + local conf = headline.config + vim.print(conf.headline_highlights) vim.api.nvim_buf_clear_namespace(headline.buffer, headline.namespace, 0, -1) - vim.api.nvim_buf_set_extmark(headline.buffer, headline.namespace, 0, 0, { - end_row = 1, - end_col = 0, - hl_group = 'Headline', - hl_eol = true, - }) + + if not conf or not conf.query then + return + end + + local language = conf.treesitter_language or vim.api.nvim_buf_get_option(headline.buffer, 'filetype') + local language_tree = vim.treesitter.get_parser(headline.buffer, language) + local syntax_tree = language_tree:parse() + local root = syntax_tree[1]:root() + local win_view = vim.fn.winsaveview() + local left_offset = win_view.leftcol + local width = vim.api.nvim_win_get_width(0) + local last_fat_headline = -1 + + -- INFO: ignore warning. last two args can be nil + for _, match, metadata in conf.query:iter_matches(root, headline.buffer) do + for id, node in pairs(match) do + local capture = conf.query.captures[id] + local start_row, start_column, end_row, end_column = unpack(vim.tbl_extend('force', { node:range() }, (metadata[id] or {}).range or {})) + + if capture == 'headline' and conf.headline_highlights then + local get_text_function = utils.use_legacy_query and treesitter_query.get_node_text(node, headline.buffer) + or vim.treesitter.get_node_text(node, headline.buffer) + + local level = #vim.trim(get_text_function) + local hl_group = conf.headline_highlights[math.min(level, #conf.headline_highlights)] + local bullet_hl_group = conf.bullet_highlights[math.min(level, #conf.bullet_highlights)] + + local virt_text = {} + if conf.bullets and #conf.bullets > 0 then + local bullet = conf.bullets[((level - 1) % #conf.bullets) + 1] + virt_text[1] = { string.rep(" ", level - 1) .. bullet, { hl_group, bullet_hl_group }} + end + + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + end_col = 0, + end_row = start_row + 1, + hl_group = hl_group, + virt_text = virt_text, + virt_text_pos = 'overlay', + hl_eol = true + }) + end + + if capture == 'dash' and conf.dash_highlight and conf.dash_string then + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + virt_text = { { conf.dash_string:rep(width), conf.dash_highlight } }, + virt_text_pos = 'overlay', + hl_mode = 'combine', + }) + end + + if capture == 'doubledash' and conf.doubledash_highlight and conf.doubledash_string then + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + virt_text = { { conf.doubledash_string:rep(width), conf.doubledash_highlight } }, + virt_text_pos = 'overlay', + hl_mode = 'combine', + }) + end + + if capture == 'codeblock' and conf.codeblock_highlight then + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + end_col = 0, + end_row = end_row, + hl_group = conf.codeblock_highlight, + hl_eol = true, + }) + + local start_line = vim.api.nvim_buf_get_lines(headline.buffer, start_row, start_row + 1, false)[1] + local _, padding = start_line:find '^ +' + local codeblock_padding = math.max((padding or 0) - left_offset, 0) + + if codeblock_padding > 0 then + for i = start_row, end_row - 1 do + utils.set_extmark(headline.buffer, headline.namespace, i, 0, { + virt_text = { { string.rep(' ', codeblock_padding), 'Normal' } }, + virt_text_win_col = 0, + priority = 1, + }) + end + end + end + + if capture == 'quote' and conf.quote_highlight and conf.quote_string then + if vim.api.nvim_buf_get_option(headline.buffer, 'filetype') == 'markdown' then + local text = vim.api.nvim_buf_get_text(headline.buffer, start_row, start_column, end_row, end_column, {})[1] + utils.set_extmark(headline.buffer, headline.namespace, start_row, start_column, { + virt_text = { { text:gsub('>', conf.quote_string), conf.quote_highlight } }, + virt_text_pos = 'overlay', + hl_mode = 'combine', + }) + else + utils.set_extmark(headline.buffer, headline.namespace, start_row, start_column, { + virt_text = { { conf.quote_string, conf.quote_highlight } }, + virt_text_pos = 'overlay', + hl_mode = 'combine', + }) + end + end + end + end end return Renderer diff --git a/lua/headlines/utils.lua b/lua/headlines/utils.lua index 9f80cd2..bd79082 100644 --- a/lua/headlines/utils.lua +++ b/lua/headlines/utils.lua @@ -1,12 +1,12 @@ local Utils = {} -local use_legacy_query = (vim.fn.has('nvim-0.9.0') ~= 1) +Utils.use_legacy_query = (vim.fn.has('nvim-0.9.0') ~= 1) ---Parse treesitter query ---@param language string ---@param query string ---@return Query | nil function Utils.parse_query_save(language, query) - local ok, parsed_query = pcall(use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) + local ok, parsed_query = pcall(Utils.use_legacy_query and vim.treesitter.query.parse_query or vim.treesitter.query.parse, language, query) if not ok then return nil @@ -15,4 +15,14 @@ function Utils.parse_query_save(language, query) return parsed_query end +---Wrapper for nvim_buf_set_extmark with added safety +---@param buffer buffer +---@param ns_id number +---@param line number +---@param col number +---@param opts? table +function Utils.set_extmark(buffer, ns_id, line, col, opts) + pcall(vim.api.nvim_buf_set_extmark, buffer, ns_id, line, col, opts) +end + return Utils From a7137254e0859e3d7fa47a2ba4ca6786af1c3ff3 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 19:29:02 -0400 Subject: [PATCH 11/16] feat: add fat_headlines support --- lua/headlines/renderer.lua | 41 +++++++++++++++++++++++++++++++++++++- lua/headlines/utils.lua | 25 +++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lua/headlines/renderer.lua b/lua/headlines/renderer.lua index 5cd103f..b00b0ce 100644 --- a/lua/headlines/renderer.lua +++ b/lua/headlines/renderer.lua @@ -31,7 +31,7 @@ function Renderer.render(headline) if capture == 'headline' and conf.headline_highlights then local get_text_function = utils.use_legacy_query and treesitter_query.get_node_text(node, headline.buffer) - or vim.treesitter.get_node_text(node, headline.buffer) + or vim.treesitter.get_node_text(node, headline.buffer) local level = #vim.trim(get_text_function) local hl_group = conf.headline_highlights[math.min(level, #conf.headline_highlights)] @@ -51,8 +51,47 @@ function Renderer.render(headline) virt_text_pos = 'overlay', hl_eol = true }) + + if conf.fat_headlines then + local reverse_hl_group = utils.make_reverse_highlight(hl_group) + + local padding_above = { { conf.fat_headline_upper_string:rep(width), reverse_hl_group } } + if start_row > 0 then + local line_above = vim.api.nvim_buf_get_lines(headline.buffer, start_row - 1, start_row, false)[1] + if line_above == "" and start_row - 1 ~= last_fat_headline then + utils.set_extmark(headline.buffer, headline.namespace, start_row - 1, 0, { + virt_text = padding_above, + virt_text_pos = "overlay", + virt_text_win_col = 0, + hl_mode = "combine", + }) + else + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + virt_lines_above = true, + virt_lines = { padding_above }, + }) + end + end + + local padding_below = { { conf.fat_headline_lower_string:rep(width), reverse_hl_group } } + local line_below = vim.api.nvim_buf_get_lines(headline.buffer, start_row + 1, start_row + 2, false)[1] + if line_below == "" then + utils.set_extmark(headline.buffer, headline.namespace, start_row + 1, 0, { + virt_text = padding_below, + virt_text_pos = "overlay", + virt_text_win_col = 0, + hl_mode = "combine", + }) + last_fat_headline = start_row + 1 + else + utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { + virt_lines = { padding_below }, + }) + end + end end + if capture == 'dash' and conf.dash_highlight and conf.dash_string then utils.set_extmark(headline.buffer, headline.namespace, start_row, 0, { virt_text = { { conf.dash_string:rep(width), conf.dash_highlight } }, diff --git a/lua/headlines/utils.lua b/lua/headlines/utils.lua index bd79082..411b66d 100644 --- a/lua/headlines/utils.lua +++ b/lua/headlines/utils.lua @@ -25,4 +25,29 @@ function Utils.set_extmark(buffer, ns_id, line, col, opts) pcall(vim.api.nvim_buf_set_extmark, buffer, ns_id, line, col, opts) end +---Create a new highlight with reverse highlights +---@param name string +---@return string +function Utils.make_reverse_highlight(name) + local reverse_name = name .. "Reverse" + + if vim.fn.synIDattr(reverse_name, "fg") ~= "" then + return reverse_name + end + + local highlight = vim.fn.synIDtrans(vim.fn.hlID(name)) + local gui_bg = vim.fn.synIDattr(highlight, "bg", "gui") + local cterm_bg = vim.fn.synIDattr(highlight, "bg", "cterm") + + if gui_bg == "" then + gui_bg = "None" + end + if cterm_bg == "" then + cterm_bg = "None" + end + + vim.cmd(string.format("highlight %s guifg=%s ctermfg=%s", reverse_name, gui_bg or "None", cterm_bg or "None")) + return reverse_name +end + return Utils From bdd012039f4a1b29ec6596aa8c02597bb0034923 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 19:41:33 -0400 Subject: [PATCH 12/16] feat: add easy attach function --- lua/headlines/class.lua | 4 ++-- lua/headlines/init.lua | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua index 08101c9..c1d4e2a 100644 --- a/lua/headlines/class.lua +++ b/lua/headlines/class.lua @@ -7,7 +7,7 @@ local config_manager = require('headlines.config') ---@class Headline ---@field config HeadlineConfig ---@field namespace number ----@field buffer number +---@field buffer buffer ---@field autocmds table ---Create a new Headline @@ -23,7 +23,7 @@ function Headline.new(config) end ---Attach headline to buffer ----@param buffer number +---@param buffer buffer ---@return Headline function Headline:attach(buffer) local refresh_autocmd = vim.api.nvim_create_autocmd({ diff --git a/lua/headlines/init.lua b/lua/headlines/init.lua index e09df8a..bff48f6 100644 --- a/lua/headlines/init.lua +++ b/lua/headlines/init.lua @@ -9,4 +9,11 @@ function M.setup() vim.api.nvim_set_hl(0, 'Qoute', { default = true, link = 'LineNr' }) end +---Attach headline to buffer +---@param buffer buffer +---@param config table +function M.attach(buffer, config) + require('headlines.class').new(config):attach(buffer) +end + return M From ecd0e4de9ed2fd39cab6615d266944c310db196b Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 19:43:43 -0400 Subject: [PATCH 13/16] doc: revert to old fat_headlines documentation --- doc/headlines.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/headlines.txt b/doc/headlines.txt index b36c1fa..f62ecdd 100644 --- a/doc/headlines.txt +++ b/doc/headlines.txt @@ -315,8 +315,7 @@ bullets *headlines-bullets* ------------------------------------------------------------------------------ fat_headlines *headlines-fat_headlines* - Specifies whether or not to use fat headlines. - Can be a boolean or a function returning a boolean. + Boolean to turn on fat headlines. ------------------------------------------------------------------------------ fat_headline_upper_string *headlines-fat_headline_upper_string* From 9ee7e63131c3d574d72e15edeff820449a5ae35f Mon Sep 17 00:00:00 2001 From: River Chubb Date: Sun, 21 Apr 2024 20:16:56 -0400 Subject: [PATCH 14/16] fix: remove debug code --- lua/headlines/renderer.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/headlines/renderer.lua b/lua/headlines/renderer.lua index b00b0ce..aa3525a 100644 --- a/lua/headlines/renderer.lua +++ b/lua/headlines/renderer.lua @@ -7,7 +7,6 @@ local treesitter_query = require('vim.treesitter.query') ---@param headline Headline function Renderer.render(headline) local conf = headline.config - vim.print(conf.headline_highlights) vim.api.nvim_buf_clear_namespace(headline.buffer, headline.namespace, 0, -1) if not conf or not conf.query then From 86877145d4c476daff1328b4931b3f338ab44a80 Mon Sep 17 00:00:00 2001 From: River Chubb Date: Mon, 22 Apr 2024 09:07:10 -0400 Subject: [PATCH 15/16] chore: remove reassigning of "merged" variable --- lua/headlines/config.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lua/headlines/config.lua b/lua/headlines/config.lua index 938e203..5771010 100644 --- a/lua/headlines/config.lua +++ b/lua/headlines/config.lua @@ -224,9 +224,7 @@ end ---@param default_config HeadlineConfig ---@return HeadlineConfig function Config.merge(user_config, default_config) - local merged = {} - - merged = user_config and vim.tbl_deep_extend('force', default_config, user_config) or default_config + local merged = user_config and vim.tbl_deep_extend('force', default_config, user_config) or default_config -- tbl_deep_extend does not handle metatables if user_config.query then From 97f36b026ea169e84edec86279823b2531cf3afa Mon Sep 17 00:00:00 2001 From: River Chubb Date: Mon, 22 Apr 2024 09:15:58 -0400 Subject: [PATCH 16/16] docs(class): add fields for functions --- lua/headlines/class.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lua/headlines/class.lua b/lua/headlines/class.lua index c1d4e2a..2eb41ed 100644 --- a/lua/headlines/class.lua +++ b/lua/headlines/class.lua @@ -9,6 +9,9 @@ local config_manager = require('headlines.config') ---@field namespace number ---@field buffer buffer ---@field autocmds table +---@field attach fun(self: Headline, buffer: buffer): Headline +---@field delete fun(self: Headline) +---@field refresh fun(self: Headline) ---Create a new Headline ---@param config? HeadlineConfig