diff --git a/README.md b/README.md index d760d3c..b156110 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Plugin to improve viewing Markdown files in Neovim - Block quotes: replace leading `>` with provided icon - Tables: replace border characters, does NOT automatically align - [Callouts](https://github.com/orgs/community/discussions/16925) - - Base set as well as custom ones + - Github & Obsidian out of the box, supports user defined as well - Custom checkbox states, function similar to `callouts` - `LaTeX` blocks: renders formulas if `latex` parser and `pylatexenc` are installed - Disable rendering when file is larger than provided value @@ -172,18 +172,21 @@ require('render-markdown').setup({ -- The 'level' is used to index into the array using a cycle -- The result is left padded with spaces to hide any additional '#' icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' }, + -- Added to the sign column + -- The 'level' is used to index into the array using a cycle + signs = { '󰫎 ' }, -- The 'level' is used to index into the array using a clamp -- Highlight for the heading icon and extends through the entire line backgrounds = { 'DiffAdd', 'DiffChange', 'DiffDelete' }, -- The 'level' is used to index into the array using a clamp - -- Highlight for the heading icon only + -- Highlight for the heading and sign icons foregrounds = { 'markdownH1', 'markdownH2', 'markdownH3', 'markdownH4', 'markdownH5', 'markdownH6' }, }, code = { -- Determines how code blocks & inline code are rendered: -- none: disables all rendering -- normal: adds highlight group to code blocks & inline code - -- language: adds language icon & name above code blocks + -- language: adds language icon to sign column and icon + name above code blocks -- full: normal + language style = 'full', -- Highlight for code blocks & inline code @@ -326,11 +329,14 @@ require('render-markdown').setup({ -- The 'level' is used to index into the array using a cycle -- The result is left padded with spaces to hide any additional '#' icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' }, + -- Added to the sign column + -- The 'level' is used to index into the array using a cycle + signs = { '󰫎 ' }, -- The 'level' is used to index into the array using a clamp -- Highlight for the heading icon and extends through the entire line backgrounds = { 'DiffAdd', 'DiffChange', 'DiffDelete' }, -- The 'level' is used to index into the array using a clamp - -- Highlight for the heading icon only + -- Highlight for the heading and sign icons foregrounds = { 'markdownH1', 'markdownH2', 'markdownH3', 'markdownH4', 'markdownH5', 'markdownH6' }, }, }) @@ -344,7 +350,7 @@ require('render-markdown').setup({ -- Determines how code blocks & inline code are rendered: -- none: disables all rendering -- normal: adds highlight group to code blocks & inline code - -- language: adds language icon & name above code blocks + -- language: adds language icon to sign column and icon + name above code blocks -- full: normal + language style = 'full', -- Highlight for code blocks & inline code diff --git a/demo/box_dash_quote.gif b/demo/box_dash_quote.gif index 307134c..5edd664 100644 Binary files a/demo/box_dash_quote.gif and b/demo/box_dash_quote.gif differ diff --git a/demo/callout.gif b/demo/callout.gif index b7c3286..461fbbb 100644 Binary files a/demo/callout.gif and b/demo/callout.gif differ diff --git a/demo/heading_code.gif b/demo/heading_code.gif index 7f1da65..9b9c5bb 100644 Binary files a/demo/heading_code.gif and b/demo/heading_code.gif differ diff --git a/demo/latex.gif b/demo/latex.gif index 16c329c..5eadeb1 100644 Binary files a/demo/latex.gif and b/demo/latex.gif differ diff --git a/demo/list_table.gif b/demo/list_table.gif index 9b2db6b..795ca04 100644 Binary files a/demo/list_table.gif and b/demo/list_table.gif differ diff --git a/doc/render-markdown.txt b/doc/render-markdown.txt index 16757e7..717aec8 100644 --- a/doc/render-markdown.txt +++ b/doc/render-markdown.txt @@ -54,7 +54,7 @@ Plugin to improve viewing Markdown files in Neovim - Block quotes: replace leading `>` with provided icon - Tables: replace border characters, does NOT automatically align - Callouts - - Base set as well as custom ones + - Github & Obsidian out of the box, supports user defined as well - Custom checkbox states, function similar to `callouts` - `LaTeX` blocks: renders formulas if `latex` parser and `pylatexenc` are installed - Disable rendering when file is larger than provided value @@ -208,18 +208,21 @@ Full Default Configuration ~ -- The 'level' is used to index into the array using a cycle -- The result is left padded with spaces to hide any additional '#' icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' }, + -- Added to the sign column + -- The 'level' is used to index into the array using a cycle + signs = { '󰫎 ' }, -- The 'level' is used to index into the array using a clamp -- Highlight for the heading icon and extends through the entire line backgrounds = { 'DiffAdd', 'DiffChange', 'DiffDelete' }, -- The 'level' is used to index into the array using a clamp - -- Highlight for the heading icon only + -- Highlight for the heading and sign icons foregrounds = { 'markdownH1', 'markdownH2', 'markdownH3', 'markdownH4', 'markdownH5', 'markdownH6' }, }, code = { -- Determines how code blocks & inline code are rendered: -- none: disables all rendering -- normal: adds highlight group to code blocks & inline code - -- language: adds language icon & name above code blocks + -- language: adds language icon to sign column and icon + name above code blocks -- full: normal + language style = 'full', -- Highlight for code blocks & inline code @@ -361,11 +364,14 @@ HEADINGS *render-markdown-setup-headings* -- The 'level' is used to index into the array using a cycle -- The result is left padded with spaces to hide any additional '#' icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' }, + -- Added to the sign column + -- The 'level' is used to index into the array using a cycle + signs = { '󰫎 ' }, -- The 'level' is used to index into the array using a clamp -- Highlight for the heading icon and extends through the entire line backgrounds = { 'DiffAdd', 'DiffChange', 'DiffDelete' }, -- The 'level' is used to index into the array using a clamp - -- Highlight for the heading icon only + -- Highlight for the heading and sign icons foregrounds = { 'markdownH1', 'markdownH2', 'markdownH3', 'markdownH4', 'markdownH5', 'markdownH6' }, }, }) @@ -380,7 +386,7 @@ CODE BLOCKS *render-markdown-setup-code-blocks* -- Determines how code blocks & inline code are rendered: -- none: disables all rendering -- normal: adds highlight group to code blocks & inline code - -- language: adds language icon & name above code blocks + -- language: adds language icon to sign column and icon + name above code blocks -- full: normal + language style = 'full', -- Highlight for code blocks & inline code diff --git a/lua/render-markdown/handler/markdown.lua b/lua/render-markdown/handler/markdown.lua index 3f9cd48..92d041f 100644 --- a/lua/render-markdown/handler/markdown.lua +++ b/lua/render-markdown/handler/markdown.lua @@ -48,6 +48,13 @@ M.render_node = function(namespace, buf, capture, node) virt_text_pos = 'overlay', hl_eol = true, }) + + vim.api.nvim_buf_set_extmark(buf, namespace, start_row, start_col, { + end_row = end_row, + end_col = end_col, + sign_text = list.cycle(heading.signs, level), + sign_hl_group = foreground, + }) elseif capture == 'dash' then local dash = state.config.dash local width = vim.api.nvim_win_get_width(util.buf_to_win(buf)) @@ -72,14 +79,20 @@ M.render_node = function(namespace, buf, capture, node) if not vim.tbl_contains({ 'language', 'full' }, code.style) then return end - -- Requires inline extmarks - if not util.has_10 then - return - end local icon, icon_highlight = icons.get(value) if icon == nil or icon_highlight == nil then return end + vim.api.nvim_buf_set_extmark(buf, namespace, start_row, start_col, { + end_row = end_row, + end_col = end_col, + sign_text = icon, + sign_hl_group = icon_highlight, + }) + -- Requires inline extmarks + if not util.has_10 then + return + end local highlight = { icon_highlight } if code.style == 'full' then highlight = { icon_highlight, code.highlight } diff --git a/lua/render-markdown/health.lua b/lua/render-markdown/health.lua index 3e903c5..a9c4e89 100644 --- a/lua/render-markdown/health.lua +++ b/lua/render-markdown/health.lua @@ -144,10 +144,12 @@ function M.check_config(config) local heading = config.heading append_errors('heading', { icons = { heading.icons, 'table' }, + signs = { heading.signs, 'table' }, backgrounds = { heading.backgrounds, 'table' }, foregrounds = { heading.foregrounds, 'table' }, }) all_strings('heading.icons', heading.icons) + all_strings('heading.signs', heading.signs) all_strings('heading.backgrounds', heading.backgrounds) all_strings('heading.foregrounds', heading.foregrounds) diff --git a/lua/render-markdown/init.lua b/lua/render-markdown/init.lua index 19fc7f5..d7f2668 100644 --- a/lua/render-markdown/init.lua +++ b/lua/render-markdown/init.lua @@ -42,6 +42,7 @@ local M = {} ---@class render.md.UserHeading ---@field public icons? string[] +---@field public signs? string[] ---@field public backgrounds? string[] ---@field public foregrounds? string[] @@ -145,18 +146,21 @@ M.default_config = { -- The 'level' is used to index into the array using a cycle -- The result is left padded with spaces to hide any additional '#' icons = { '󰲡 ', '󰲣 ', '󰲥 ', '󰲧 ', '󰲩 ', '󰲫 ' }, + -- Added to the sign column + -- The 'level' is used to index into the array using a cycle + signs = { '󰫎 ' }, -- The 'level' is used to index into the array using a clamp -- Highlight for the heading icon and extends through the entire line backgrounds = { 'DiffAdd', 'DiffChange', 'DiffDelete' }, -- The 'level' is used to index into the array using a clamp - -- Highlight for the heading icon only + -- Highlight for the heading and sign icons foregrounds = { 'markdownH1', 'markdownH2', 'markdownH3', 'markdownH4', 'markdownH5', 'markdownH6' }, }, code = { -- Determines how code blocks & inline code are rendered: -- none: disables all rendering -- normal: adds highlight group to code blocks & inline code - -- language: adds language icon & name above code blocks + -- language: adds language icon to sign column and icon + name above code blocks -- full: normal + language style = 'full', -- Highlight for code blocks & inline code diff --git a/lua/render-markdown/types.lua b/lua/render-markdown/types.lua index fed3841..da5f5e6 100644 --- a/lua/render-markdown/types.lua +++ b/lua/render-markdown/types.lua @@ -29,6 +29,7 @@ ---@class render.md.Heading ---@field public icons string[] +---@field public signs string[] ---@field public backgrounds string[] ---@field public foregrounds string[] diff --git a/scripts/update.py b/scripts/update.py index ef335f8..4d2acab 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -72,9 +72,8 @@ def update_readme(init_file: Path, readme_file: Path) -> None: parameters: list[str] = ["heading", "code", "dash", "bullet"] parameters.extend(["checkbox", "quote", "pipe_table", "callout"]) for parameter in parameters: - parameter = f"{parameter} = " - old_param = get_code_block(readme_file, parameter, 2) - new_param = wrap_setup(get_config_for(new_config, parameter)) + old_param = get_code_block(readme_file, f"\n {parameter} = ", 2) + new_param = wrap_setup(get_config_for(new_config, f"{parameter} = ")) text = text.replace(old_param, new_param) readme_file.write_text(text) diff --git a/tests/box_dash_quote_spec.lua b/tests/box_dash_quote_spec.lua index 24eabcc..cef5418 100644 --- a/tests/box_dash_quote_spec.lua +++ b/tests/box_dash_quote_spec.lua @@ -17,6 +17,12 @@ async_tests.describe('box_dash_quote.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Checkboxes diff --git a/tests/callout_spec.lua b/tests/callout_spec.lua index 4092c4e..5c402ca 100644 --- a/tests/callout_spec.lua +++ b/tests/callout_spec.lua @@ -19,6 +19,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { note_start, note_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { note_start + 2, note_start + 2 }, @@ -71,6 +77,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { tip_start, tip_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { tip_start + 2, tip_start + 2 }, @@ -104,6 +116,12 @@ async_tests.describe('callout.md', function() hl_eol = true, hl_group = 'ColorColumn', }, + { + row = { tip_start + 4, tip_start + 4 }, + col = { 5, 8 }, + sign_text = '󰢱 ', + sign_hl_group = 'MiniIconsAzure', + }, { row = { tip_start + 4 }, col = { 5 }, @@ -135,6 +153,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { important_start, important_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { important_start + 2, important_start + 2 }, @@ -169,6 +193,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { warning_start, warning_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { warning_start + 2, warning_start + 2 }, @@ -203,6 +233,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { caution_start, caution_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { caution_start + 2, caution_start + 2 }, @@ -237,6 +273,12 @@ async_tests.describe('callout.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { bug_start, bug_start }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, -- Quote start { row = { bug_start + 2, bug_start + 2 }, diff --git a/tests/custom_handler_spec.lua b/tests/custom_handler_spec.lua index e81e7bd..49268d9 100644 --- a/tests/custom_handler_spec.lua +++ b/tests/custom_handler_spec.lua @@ -29,6 +29,12 @@ async_tests.describe('custom_handler.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, { row = { 0, 0 }, col = { 9, 18 }, @@ -62,6 +68,12 @@ async_tests.describe('custom_handler.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Backslash escapes @@ -104,6 +116,12 @@ async_tests.describe('custom_handler.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, { row = { 0, 0 }, col = { 9, 18 }, diff --git a/tests/heading_code_spec.lua b/tests/heading_code_spec.lua index 4f8d836..4e6eda1 100644 --- a/tests/heading_code_spec.lua +++ b/tests/heading_code_spec.lua @@ -17,6 +17,12 @@ async_tests.describe('heading_code.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, { row = { 2, 3 }, col = { 0, 0 }, @@ -25,6 +31,12 @@ async_tests.describe('heading_code.md', function() virt_text = { { ' 󰲥 ', { 'markdownH3', 'DiffDelete' } } }, virt_text_pos = 'overlay', }, + { + row = { 2, 2 }, + col = { 0, 3 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH3', + }, { row = { 4, 5 }, col = { 0, 0 }, @@ -33,6 +45,12 @@ async_tests.describe('heading_code.md', function() virt_text = { { ' 󰲧 ', { 'markdownH4', 'DiffDelete' } } }, virt_text_pos = 'overlay', }, + { + row = { 4, 4 }, + col = { 0, 4 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH4', + }, { row = { 6, 7 }, col = { 0, 0 }, @@ -41,6 +59,12 @@ async_tests.describe('heading_code.md', function() virt_text = { { ' 󰲩 ', { 'markdownH5', 'DiffDelete' } } }, virt_text_pos = 'overlay', }, + { + row = { 6, 6 }, + col = { 0, 5 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH5', + }, { row = { 8, 9 }, col = { 0, 0 }, @@ -49,6 +73,12 @@ async_tests.describe('heading_code.md', function() virt_text = { { ' 󰲫 ', { 'markdownH6', 'DiffDelete' } } }, virt_text_pos = 'overlay', }, + { + row = { 8, 8 }, + col = { 0, 6 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH6', + }, }) -- Code block @@ -59,6 +89,12 @@ async_tests.describe('heading_code.md', function() hl_eol = true, hl_group = 'ColorColumn', }, + { + row = { 10, 10 }, + col = { 3, 9 }, + sign_text = '󰌠 ', + sign_hl_group = 'MiniIconsYellow', + }, { row = { 10 }, col = { 3 }, diff --git a/tests/latex_spec.lua b/tests/latex_spec.lua index 807b5a0..24eaf30 100644 --- a/tests/latex_spec.lua +++ b/tests/latex_spec.lua @@ -33,6 +33,12 @@ async_tests.describe('latex.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) vim.list_extend(expected, { diff --git a/tests/list_table_spec.lua b/tests/list_table_spec.lua index daaf586..a7c4adf 100644 --- a/tests/list_table_spec.lua +++ b/tests/list_table_spec.lua @@ -17,6 +17,12 @@ async_tests.describe('list_table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Unordered list @@ -96,6 +102,12 @@ async_tests.describe('list_table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 11, 11 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Table heading @@ -108,6 +120,12 @@ async_tests.describe('list_table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 17, 17 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) local markdown_table = { diff --git a/tests/table_spec.lua b/tests/table_spec.lua index 668fa80..9e38278 100644 --- a/tests/table_spec.lua +++ b/tests/table_spec.lua @@ -17,6 +17,12 @@ async_tests.describe('table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) local table_with_inline = { @@ -72,6 +78,12 @@ async_tests.describe('table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 6, 6 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) local table_no_inline = { @@ -144,6 +156,12 @@ async_tests.describe('table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 0, 0 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Table with inline @@ -238,6 +256,12 @@ async_tests.describe('table.md', function() virt_text = { { '󰲡 ', { 'markdownH1', 'DiffAdd' } } }, virt_text_pos = 'overlay', }, + { + row = { 6, 6 }, + col = { 0, 1 }, + sign_text = '󰫎 ', + sign_hl_group = 'markdownH1', + }, }) -- Table no inline diff --git a/tests/util.lua b/tests/util.lua index ef3c725..e7a9287 100644 --- a/tests/util.lua +++ b/tests/util.lua @@ -13,6 +13,8 @@ local eq = assert.are.same ---@field virt_text_pos? string ---@field virt_lines? { [1]: string, [2]: string }[][] ---@field virt_lines_above? boolean +---@field sign_text? string +---@field sign_hl_group? string local M = {} @@ -41,6 +43,8 @@ M.get_actual_marks = function() virt_text_pos = details.virt_text_pos, virt_lines = details.virt_lines, virt_lines_above = details.virt_lines_above, + sign_text = details.sign_text, + sign_hl_group = details.sign_hl_group, } table.insert(actual, mark_info) end