diff --git a/README.md b/README.md index 59bd961..c07afa7 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@
+
@@ -80,6 +81,7 @@ Core features, + Highly customisable! You can change almost anything using the config! + Dynamic `highlight groups` that automatically updates with the colorscheme! + `Callout`, `checkbox` completions for `blink.cmp` & `nvim-cmp`. ++ Works with `tree-sitter injections` too! @@ -104,6 +106,32 @@ Also see, Expand to see complete feature list +#### Fancy comments, + + + +> Comments are still experimental! The original parser only supports basic features. + +Conventional commit style comments with support for a subset of `markdown` & `vimdoc`. See [integrations#fancy-comments](https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-fancy-comments) For more info. + +Supported syntax, + ++ Tasks(e.g. `feat`, `TODO` etc.) ++ Task scopes. + +Extra syntax(needs external parser), + ++ `**Bold**` ++ `*Italic*` ++ `Code` ++ `'Quoted_text'` ++ `"Double quoted text"` ++ `@mentions` ++ `issues/reference#52` ++ `https://example.com` ++ `|help-section|` ++ Code blocks + #### HTML, @@ -372,6 +400,7 @@ Parsers, - `markdown` - `markdown_inline` +- `comment`(optional) - `html`(optional) - `latex`(optional) - `typst`(optional) diff --git a/doc/markview.nvim-comment.txt b/doc/markview.nvim-comment.txt new file mode 100644 index 0000000..df8de5e --- /dev/null +++ b/doc/markview.nvim-comment.txt @@ -0,0 +1,1197 @@ +*markview.nvim-comment* đŸ§© HTML options for `markview` + +demo {img:1} + +>lua + --[[ Configuration for `comments`. ]] + ---@class markview.config.comment + --- + ---@field enable boolean Enable **comment** rendering. + --- + ---@field autolinks markview.config.comment.autolinks + ---@field code_blocks markview.config.comment.code_blocks + ---@field inline_codes markview.config.comment.inline_codes + ---@field issues markview.config.comment.issues + ---@field mentions markview.config.comment.mentions + ---@field taglinks markview.config.comment.taglinks + ---@field tasks markview.config.comment.tasks + ---@field task_scopes markview.config.comment.task_scopes + ---@field urls markview.config.comment.urls +< + +▋  Warning +▋ Fancy comments are experimental at the moment. Single line comments like +▋ these, +▋ +>lua + -- feat: Some comment +< + +▋ May not be correctly rendered when in large groups. Use multi-line +▋ comments(e.g. `--[[ ... ]]`, `/* ... */`) for these. +▋ This is a Neovim issue with tree-sitter injections in general and not a plugin +▋ issue! + +-------------------------------------------------------------------------------- +enable *markview.nvim-comment.enable* + +>lua + enable = true +< + +Enable rendering of fancy comments. + +-------------------------------------------------------------------------------- +autolinks *markview.nvim-comment.autolinks* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of ``. + +See default ~ +configuration ~ + +>lua + autolinks = { + enable = true, + + default = { + icon = "ó°‹œ ", + hl = "MarkviewPalette6", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = "îȘ„ ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = "ï€Ź ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = "ï†Ą ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = "îȘ„ ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁎 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆩 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = "ïˆș ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, +< + +Each autolink type has the following options. + +>lua + ---@class markview.config.comments.autolinks.opts + --- + ---@field corner_left? string Left corner. + ---@field corner_left_hl? string Highlight group for the left corner. + --- + ---@field padding_left? string Left padding(added after `corner_left`). + ---@field padding_left_hl? string Highlight group for the left padding. + --- + ---@field icon? string Icon(added after `padding_left`). + ---@field icon_hl? string Highlight group for the icon. + --- + --[[ Text to show instead of the `autolink`.]] + ---@field text? + ---| string + ---| function(buffer: integer, item: markview.parsed.comment.autolinks): string + ---@field text_hl? string Highlight group for the shown text. + --- + ---@field hl? string Default highlight group(used by `*_hl` options when they are not set). + --- + ---@field padding_right? string Right padding. + ---@field padding_right_hl? string Highlight group for the right padding. + --- + ---@field corner_right? string Right corner(added after `padding_right`). + ---@field corner_right_hl? string Highlight group for the right corner. +< + +-------------------------------------------------------------------------------- +code_blocks *markview.nvim-comment.code_blocks* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of `fenced code blocks`. + +See default ~ +configuration ~ + +>lua + code_blocks = { + enable = true, + + border_hl = "MarkviewCode", + info_hl = "MarkviewCodeInfo", + + label_direction = "right", + label_hl = nil, + + min_width = 60, + pad_amount = 2, + pad_char = " ", + + default = { + block_hl = "MarkviewCode", + pad_hl = "MarkviewCode" + }, + + ["diff"] = { + block_hl = function (_, line) + if line:match("^%+") then + return "MarkviewPalette4"; + elseif line:match("^%-") then + return "MarkviewPalette1"; + else + return "MarkviewCode"; + end + end, + pad_hl = "MarkviewCode" + }, + + style = "block", + sign = true, + }, +< + +-------------------------------------------------------------------------------- +inline_codes *markview.nvim-comment.inline_codes* + +>lua + --- Configuration for autolinks. + ---@class markview.config.comment.autolinks + --- + ---@field enable boolean Enable rendering of ``s. + --- + ---@field default markview.config.comments.autolinks.opts Default configuration. + ---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. +< + +Enable rendering of `inline codes`. + +See default ~ +configuration ~ + +>lua + inline_codes = { + padding_left = " ", + padding_right = " ", + + hl = "MarkviewInlineCode", + }, +< + +-------------------------------------------------------------------------------- +issues *markview.nvim-comment.issues* + +>lua + --- Configuration for issues. + ---@class markview.config.comment.issues + --- + ---@field enable boolean Enable rendering of `#issue`s. + --- + ---@field default markview.config.__inline Default configuration for issues. + ---@field [string] markview.config.__inline Configuration for issues whose text matches with the key's pattern. +< + +Enable rendering of `inline codes`. + +See default ~ +configuration ~ + +>lua + issues = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette2", + }, + }, +< + +Each issue type has inline options {1}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +mentions *markview.nvim-comment.mentions* + +>lua + --- Configuration for mentions. + ---@class markview.config.comment.mentions + --- + ---@field enable boolean Enable rendering of `@mention`s. + --- + ---@field default markview.config.__inline Default configuration for mentions. + ---@field [string] markview.config.__inline Configuration for mentions whose text matches with the key's pattern. +< + +Enable rendering of `@mentions`. + +See default ~ +configuration ~ + +>lua + mentions = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette5", + }, + }, +< + +Each mention type has inline options {2}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +taglinks *markview.nvim-comment.taglinks* + +>lua + --- Configuration for taglinks. + ---@class markview.config.comment.taglinks + --- + ---@field enable boolean Enable rendering of `|taglink|`s. + --- + ---@field default markview.config.__inline Default configuration. + ---@field [string] markview.config.__inline Configuration for taglinks matching the key's pattern. +< + +Enable rendering of `|taglinks|`. + +See default ~ +configuration ~ + +>lua + taglinks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + }, +< + +Each taglink type has inline options {3}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +tasks *markview.nvim-comment.tasks* + +>lua + ---@class markview.config.comment.tasks + --- + ---@field enable boolean + --- + ---@field default markview.config.comment.tasks.opts + ---@field [string] markview.config.comment.tasks.opts +< + +Enable rendering of `tasks`. + +See default ~ +configuration ~ + +>lua + tasks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰄰 ", + + hl = "MarkviewPalette1", + }, + + ["^feat"] = { + padding_left = " ", + padding_right = " ", + + icon = "󱕅 ", + + hl = "MarkviewPalette7", + }, + + praise = { + padding_left = " ", + padding_right = " ", + + icon = "󱄋 ", + + hl = "MarkviewPalette3", + }, + + ["^suggest"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰣖 ", + + hl = "MarkviewPalette2", + }, + + thought = { + padding_left = " ", + padding_right = " ", + + icon = "󰧑 ", + + hl = "MarkviewPalette0", + }, + + note = { + padding_left = " ", + padding_right = " ", + + icon = "ó° ź ", + + hl = "MarkviewPalette5", + }, + + ["^info"] = { + padding_left = " ", + padding_right = " ", + + icon = "ó°‹Œ ", + + hl = "MarkviewPalette0", + }, + + xxx = { + padding_left = " ", + padding_right = " ", + + icon = "ó°“œ ", + + hl = "MarkviewPalette0", + }, + + ["^nit"] = { + padding_left = " ", + padding_right = " ", + + icon = "ó°©° ", + + hl = "MarkviewPalette6", + }, + + ["^warn"] = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette3", + }, + + fix = { + padding_left = " ", + padding_right = " ", + + icon = "󰁚 ", + + hl = "MarkviewPalette7", + }, + + hack = { + padding_left = " ", + padding_right = " ", + + icon = "󱍔 ", + + hl = "MarkviewPalette1", + }, + + typo = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette0", + }, + + wip = { + padding_left = " ", + padding_right = " ", + + icon = "󰩖 ", + + hl = "MarkviewPalette2", + }, + + issue = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette1", + }, + + ["error"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰅙 ", + + hl = "MarkviewPalette1", + }, + + fixme = { + padding_left = " ", + padding_right = " ", + + icon = "ó°¶Ż ", + + hl = "MarkviewPalette4", + }, + + deprecated = { + padding_left = " ", + padding_right = " ", + + icon = "󰩆 ", + + hl = "MarkviewPalette1", + }, + }, +< + +Each task type has inline options {4}, unless explicitly mentioned otherwise. + +-------------------------------------------------------------------------------- +task_scopes *markview.nvim-comment.task_scopes* + +>lua + --- Configuration for task_scopes. + ---@class markview.config.comment.task_scopes + --- + ---@field enable boolean Enable rendering of `task scope`s. + --- + ---@field default markview.config.__inline Default configuration for mentions. + ---@field [string] markview.config.__inline Configuration for scopes matching the key's pattern. +< + +Enable rendering of `task_scopes`. + +See default ~ +configuration ~ + +>lua + task_scopes = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "ó°ˆČ ", + + hl = "MarkviewPalette4", + }, + }, +< + +Each task scope type has inline options {5}, unless explicitly mentioned +otherwise. + +-------------------------------------------------------------------------------- +urls *markview.nvim-comment.urls* + +>lua + --- Configuration for URLs. + ---@class markview.config.comment.urls + --- + ---@field enable boolean Enable rendering of `URL`s. + --- + ---@field default markview.config.comments.urls.opts Default configuration for URLs. + ---@field [string] markview.config.comments.urls.opts Configuration for URLs whose text matches with the key's pattern. +< + +Enable rendering of `urls`. + +See default ~ +configuration ~ + +>lua + urls = { + enable = true, + + default = { + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = "îȘ„ ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = "ï€Ź ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = "ï†Ą ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = "îȘ„ ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁎 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆩 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = "ïˆș ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, +< + +Each URL type has inline options {6}, unless explicitly mentioned otherwise. + + ╶────────────────────────────────────────────────────────────────────────────╎ + +-------------------------------------------------------------------------------- +Inline syntax + +Inline elements support most of these options. + +>lua + ---@class markview.config.__inline + --- + ---@field enable? boolean Only valid if it's a top level option, Used for disabling previews. + ---@field virtual? boolean In `inline_codes`, when `true` masks the text with a virtual text(useful if the line has a background). + --- + ---@field corner_left? string Left corner. + ---@field corner_left_hl? string Highlight group for the left corner. + --- + ---@field padding_left? string Left padding(added after `corner_left`). + ---@field padding_left_hl? string Highlight group for the left padding. + --- + ---@field icon? string Icon(added after `padding_left`). + ---@field icon_hl? string Highlight group for the icon. + --- + ---@field hl? string Default highlight group(used by `*_hl` options when they are not set). + --- + ---@field padding_right? string Right padding. + ---@field padding_right_hl? string Highlight group for the right padding. + --- + ---@field corner_right? string Right corner(added after `padding_right`). + ---@field corner_right_hl? string Highlight group for the right corner. + --- + --- + --- + ---@field block_hl? string Only for `block_references`, highlight group for the block name. + ---@field file_hl? string Only for `block_references`, highlight group for the file name. +< + +Links ~ + +1: #inline-syntax +2: #inline-syntax +3: #inline-syntax +4: #inline-syntax +5: #inline-syntax +6: #inline-syntax + +Images ~ + +1: ./images/comment/markview.nvim-comment.injection.png + +vim:ft=help:textwidth=80:tabstop=4:noexpandtab: diff --git a/doc/markview.nvim-experimental.txt b/doc/markview.nvim-experimental.txt index bd87639..ed7937d 100644 --- a/doc/markview.nvim-experimental.txt +++ b/doc/markview.nvim-experimental.txt @@ -4,6 +4,8 @@ --- Experimental options. ---@class markview.config.experimental --- + ---@field fancy_comments boolean When `true`, enables preview on **all buffers** with an active `tree-sitter parser`. + --- ---@field date_formats string[] List of lua patterns for detecting date in YAML. ---@field date_time_formats string[] List of lua patterns for detecting date & time in YAML. --- @@ -17,6 +19,12 @@ ---@field linewise_ignore_org_indent? boolean Prevents indentation of sections from being cleared in `linewise_hybrid_mode`. < +-------------------------------------------------------------------------------- +fancy_comments *markview.nvim-experimental.fancy_comments* + +When true enables `fancy comment rendering`. See [integrations#fancy_comments]() +for more information. + -------------------------------------------------------------------------------- date_formats *markview.nvim-experimental.date_formats* diff --git a/doc/markview.nvim-integrations.txt b/doc/markview.nvim-integrations.txt index bdc6f90..a21d3b6 100644 --- a/doc/markview.nvim-integrations.txt +++ b/doc/markview.nvim-integrations.txt @@ -113,6 +113,23 @@ You can use `markview.nvim` to prettify the LSP hover window. You can see an example here {6}. +-------------------------------------------------------------------------------- +📩 Fancy comments *markview.nvim-integrations.nvim-fancy_comments* + +▋  Attention +▋ This will remap `gx` by default! Set preview.map_gx {7} to `false` to +▋ overwrite this behavior. + +Conventional commit style commits can be rendered by `markview.nvim`. + +Demo {img:2} + +For this you would need a `comment` parser. You can use either, + +◆ stsewd/tree-sitter-comment {8}, which supports some simple syntax. +◆ OXY2DEV/tree-sitter-comment {9}, which also supports a subset of `markdown` & + `vimdoc`. See [installation](). + Links ~ 1: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations @@ -121,9 +138,13 @@ Links ~ 4: `markview.nvim-markdown.headings` 5: `markview.nvim-markdown.list_items` 6: https://gist.github.com/OXY2DEV/645c90df32095a8a397735d0be646452 +7: `markview.nvim-preview.map_gx` +8: https://github.com/stsewd/tree-sitter-comment +9: https://github.com/OXY2DEV/tree-sitter-comment Images ~ 1: ./images/markview.nvim-lsp_hover.png +2: ./images/comments/markview.nvim-comment.png vim:ft=help:textwidth=80:tabstop=4:noexpandtab: diff --git a/doc/markview.nvim-preview.txt b/doc/markview.nvim-preview.txt index ddfe0ba..617bd93 100644 --- a/doc/markview.nvim-preview.txt +++ b/doc/markview.nvim-preview.txt @@ -23,7 +23,7 @@ ---@field ignore_buftypes? string[] Buftypes that should be ignored(e.g. nofile). ---@field raw_previews? markview.config.preview.raw Options that will show up as raw in hybrid mode. --- - ---@field condition? fun(buffer: integer): boolean Condition to check if a buffer should be attached or not. + ---@field condition? fun(buffer: integer): boolean? Condition to check if a buffer should be attached or not. Overrides `preview.filetypes` & `preview.ignore_buftypes`. If `nil` is returned, `preview.filetypes` & `preview.ignore_buftypes` are checked. --- ---@field modes? string[] Vim-modes where previews will be shown. ---@field hybrid_modes? string[] Vim-modes where `hybrid mode` is enabled. Options that should/shouldn't be previewed in `hybrid_modes`. @@ -160,6 +160,7 @@ raw_previews *markview.nvim-preview.raw_previews* --- in `hybrid mode`. ---@class markview.config.preview.raw --- + ---@field comment? markview.config.preview.raw.comment[] ---@field html? markview.config.preview.raw.html[] ---@field latex? markview.config.preview.raw.latex[] ---@field markdown? markview.config.preview.raw.markdown[] @@ -196,11 +197,36 @@ condition *markview.nvim-preview.condition* A function that returns a boolean indicating if a buffer should be attached to. +▋  Important +▋ This will disable filetypes {9} & ignore_buftypes {8}. + ▋ ó°‹œ Note -▋ This is run after filetypes {9} & ignore_buftypes {8} is checked. +▋ The function may return `nil`. In which case, filetypes {11} & ignore_buftypes +▋ {10} will be checked. Useful if you need sophisticated logic for buffer attaching. +For example, this is the default value. It attaches to any buffer that has +`tree-sitter` parser available when experimental.fancy_comments {12} is set to +`true`. + +>lua + condition = function (buffer) + local is_enabled = spec.get({ "experimental", "fancy_comments" }, { + fallback = false, + }); + + if not is_enabled then + return false; + end + + local success, parser = pcall(vim.treesitter.get_parser, buffer); + if success and parser ~= nil then + return true; + end + end, +< + -------------------------------------------------------------------------------- modes *markview.nvim-preview.modes* @@ -220,7 +246,7 @@ hybrid_modes *markview.nvim-preview.hybrid_modes* Modes where `hybrid mode` will be shown. ▋  Important -▋ The mode must also be preset in modes {10} for this to take effect! +▋ The mode must also be preset in modes {13} for this to take effect! ╭──────────────────────┬──────────────────────╼ │ │ `hybrid_modes = {}` │ @@ -238,7 +264,7 @@ linewise_hybrid_mode *markview.nvim-preview.linewise_hybrid_mode* linewise_hybrid_mode = false, < -Enables `linewise` hybrid mode. edit_range {11} is used to control the number of +Enables `linewise` hybrid mode. edit_range {14} is used to control the number of lines to clear around each cursor. ╭──────────────────────┬──────────────────────╼ @@ -267,7 +293,7 @@ Maximum number of lines a buffer can have for it to be rendered completely. ▋ cause lag when opening the buffer. If the line count is larger than this value, the buffer will be partially drawn. -draw_range {12} is used to control the number of lines drawn around each cursor. +draw_range {15} is used to control the number of lines drawn around each cursor. -------------------------------------------------------------------------------- draw_range *markview.nvim-preview.draw_range* @@ -291,10 +317,10 @@ edit_range *markview.nvim-preview.edit_range* < Number of lines above & below each cursor that are considered being edited. Only -useful in hybrid_modes {13}. +useful in hybrid_modes {16}. ▋  Important -▋ When linewise_hybrid_mode {14} is `false`, a Node only needs to partially be +▋ When linewise_hybrid_mode {17} is `false`, a Node only needs to partially be ▋ within the range for it to be considered being edited. ▋ So, things such as List items, Block quotes etc. may clear more lines than the ▋ specified amount. @@ -317,20 +343,23 @@ Window options for the `splitview` window. Passed directly to `nvim_open_win()`. Links ~ -1: #-preview-options -2: ./Experimental.md#prefer_nvim -3: ./Experimental.md#file_open_command -4: ./Experimental.md#prefer_nvim -5: #ignore_buftypes -6: #ignore_buftypes -7: #hybrid_modes -8: #ignore_buftypes -9: #filetypes -10: #modes -11: #edit_range -12: #draw_range -13: #hybrid_modes -14: #linewise_hybrid_mode +1: `markview.nvim-preview` +2: `markview.nvim-experimental.prefer_nvim` +3: `markview.nvim-experimental.file_open_command` +4: `markview.nvim-experimental.prefer_nvim` +5: `markview.nvim-preview.ignore_buftypes` +6: `markview.nvim-preview.ignore_buftypes` +7: `markview.nvim-preview.modes` +8: `markview.nvim-preview.ignore_buftypes` +9: `markview.nvim-preview.filetypes` +10: `markview.nvim-preview.ignore_buftypes` +11: `markview.nvim-preview.filetypes` +12: `markview.nvim-experimental.fancy_comments` +13: `markview.nvim-preview.modes` +14: `markview.nvim-preview.edit_range` +15: `markview.nvim-preview.draw_range` +16: `markview.nvim-preview.modes` +17: `markview.nvim-preview.linewise_hybrid_mode` Images ~ diff --git a/doc/markview.nvim.txt b/doc/markview.nvim.txt index 4317ad2..cf7508e 100644 --- a/doc/markview.nvim.txt +++ b/doc/markview.nvim.txt @@ -8,7 +8,7 @@ │ wrap {img:2} │ nowrap {img:3} │ ╰─────────────────┮──────────────────╯ - Image {img:5} Image {img:4} + Image {img:6} Image {img:5} Image {img:4} 📚 Wiki {3} | đŸ§© Extras {2} | 📩 Presets {1} @@ -26,6 +26,7 @@ Core features, ◇ Highly customisable! You can change almost anything using the config! ◇ Dynamic `highlight groups` that automatically updates with the colorscheme! ◇ `Callout`, `checkbox` completions for `blink.cmp` & `nvim-cmp`. +◇ Works with `tree-sitter injections` too! -------------------------------------------------------------------------------- Table of contents @@ -37,9 +38,37 @@ Table of contents đŸ§© Extras ............................................... |markview.nvim-extras| 📩 Presets ............................................. |markview.nvim-presets| +Fancy comments, ~ + +Image {img:7} + +▋ Comments are still experimental! The original parser only supports basic +▋ features. + +Conventional commit style comments with support for a subset of `markdown` & +`vimdoc`. See integrations#fancy-comments {6} For more info. + +Supported syntax, + +◇ Tasks(e.g. `feat`, `TODO` etc.) +◇ Task scopes. + +Extra syntax(needs external parser), + +◇ `**Bold**` +◇ `*Italic*` +◇ `Code` +◇ `'Quoted_text'` +◇ `"Double quoted text"` +◇ `@mentions` +◇ `issues/reference#52` +◇ `https://example.com` +◇ `|help-section|` +◇ Code blocks + HTML, ~ -Image {img:6} +Image {img:8} ◇ Customizable previews for `container` & `void` elements. ◇ Supports the following container elements out of the box, @@ -63,7 +92,7 @@ Image {img:6} LaTeX, ~ -Image {img:7} +Image {img:9} ◇ Supports basic LaTeX syntax, ◇ Math blocks(typically `$$...$$`) & inline math(typically `$...$`). @@ -133,7 +162,7 @@ Image {img:7} Markdown, ~ -Image {img:8} +Image {img:10} ◇ Supports basic markdown(Github-flavored) syntax, ◇ Block quotes(with support for `callouts` & titles). @@ -162,7 +191,7 @@ Image {img:8} ◇ `Org-mode` like indentation for headings. -Image {img:9} +Image {img:11} ◇ Obsidian/PKM extended syntax support, ◇ Block reference links. @@ -178,7 +207,7 @@ Image {img:9} Typst, ~ -Image {img:10} +Image {img:12} ◇ Supports the following items, ◇ Code blocks. @@ -206,7 +235,7 @@ Image {img:10} YAML, ~ -Image {img:11} +Image {img:13} ◇ Custom property icons. ◇ Custom property scope decorations. @@ -229,8 +258,8 @@ Hybrid mode ~ ╭──────────────────────┬──────────────────────╼ │ Normal hybrid mode │ Linewise hybrid mode │ ├──────────────────────┌─────────────────────── -│ hybrid_mode {img:12} │ linewise_hybrid_mode │ -│ │ {img:13} │ +│ hybrid_mode {img:14} │ linewise_hybrid_mode │ +│ │ {img:15} │ ╰──────────────────────┮──────────────────────╯ ◇ Node-based edit range(default). @@ -254,7 +283,7 @@ Internal Icon provider features, ◇ 708 different filetype configuration. ◇ Dynamic highlight groups for matching the colorscheme. -Image {img:14} +Image {img:16} ◇ You can use `:Markview traceShow` to see what the plugin has been doing(including how long some of them took). @@ -290,8 +319,8 @@ External icon providers, } < -◆ mini.icons {6} -◆ nvim-web-devicons {7} +◆ mini.icons {7} +◆ nvim-web-devicons {8} Parsers, @@ -308,6 +337,7 @@ Parsers, ◆ `markdown` ◆ `markdown_inline` +◆ `comment`(optional) ◆ `html`(optional) ◆ `latex`(optional) ◆ `typst`(optional) @@ -340,7 +370,7 @@ Add this to your plugin list. ▋ cause more time for the previews to load when starting Neovim! The plugin should be loaded after your colorscheme to ensure the correct -highlight groups are used. See integrations.transparent_colorschemes {8} if you +highlight groups are used. See integrations.transparent_colorschemes {9} if you use a transparent colorscheme and the colors don't look right. >lua @@ -389,7 +419,7 @@ use a transparent colorscheme and the colors don't look right. đŸ“„ GitHub release ~ -Tagged releases can be found in the release page {9}. +Tagged releases can be found in the release page {10}. ▋ ó°‹œ Note ▋ `Github releases` may sometimes be slightly behind `main`. @@ -409,7 +439,7 @@ Tagged releases can be found in the release page {9}. -------------------------------------------------------------------------------- 🧭 Usage -You can find more usage recipes here {10}. +You can find more usage recipes here {11}. -------------------------------------------------------------------------------- 🎇 Commands *markview.nvim-commands* @@ -553,27 +583,30 @@ Links ~ 3: https://github.com/OXY2DEV/markview.nvim/wiki/Home 4: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-nowrap 5: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-wrap -6: https://github.com/nvim-mini/mini.icons -7: https://github.com/nvim-tree/nvim-web-devicons -8: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-transparent-colorschemes -9: https://github.com/OXY2DEV/markview.nvim/releases -10: |markview.nvim-usage| +6: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-fancy-comments +7: https://github.com/nvim-mini/mini.icons +8: https://github.com/nvim-tree/nvim-web-devicons +9: https://github.com/OXY2DEV/markview.nvim/wiki/Integrations#-transparent-colorschemes +10: https://github.com/OXY2DEV/markview.nvim/releases +11: |markview.nvim-usage| Images ~ 1: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview.png 2: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-wrap.png 3: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-nowrap.png -4: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-hybrid_mode.png -5: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview_2.png -6: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/html-tokyonight_night.png -7: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/latex-cyberdream.png -8: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown-catppuccin_mocha.png -9: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown_inline-nightfly.png -10: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/typst-kanagawa_wave.png -11: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/yaml-material_palenight.png -12: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/hybrid_mode.png -13: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/linewise_hybrid_mode.png -14: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/traceback.png +4: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-comment.png +5: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-hybrid_mode.png +6: https://github.com/OXY2DEV/markview.nvim/blob/images/v27/markview.nvim-splitview_2.png +7: https://github.com/OXY2DEV/markview.nvim/wiki/images/comment/markview.nvim-comment.injection.png +8: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/html-tokyonight_night.png +9: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/latex-cyberdream.png +10: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown-catppuccin_mocha.png +11: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/markdown_inline-nightfly.png +12: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/typst-kanagawa_wave.png +13: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/yaml-material_palenight.png +14: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/hybrid_mode.png +15: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/wiki/linewise_hybrid_mode.png +16: https://github.com/OXY2DEV/markview.nvim/blob/images/v25/repo/traceback.png vim:ft=help:textwidth=80:tabstop=4:noexpandtab: diff --git a/doc/tags b/doc/tags index fad81fd..959bcad 100644 --- a/doc/tags +++ b/doc/tags @@ -3,12 +3,24 @@ markview.nvim markview.nvim.txt /*markview.nvim* markview.nvim-advanced markview.nvim-advanced.txt /*markview.nvim-advanced* markview.nvim-autocmds markview.nvim-autocmds.txt /*markview.nvim-autocmds* markview.nvim-commands markview.nvim.txt /*markview.nvim-commands* +markview.nvim-comment markview.nvim-comment.txt /*markview.nvim-comment* +markview.nvim-comment.autolinks markview.nvim-comment.txt /*markview.nvim-comment.autolinks* +markview.nvim-comment.code_blocks markview.nvim-comment.txt /*markview.nvim-comment.code_blocks* +markview.nvim-comment.enable markview.nvim-comment.txt /*markview.nvim-comment.enable* +markview.nvim-comment.inline_codes markview.nvim-comment.txt /*markview.nvim-comment.inline_codes* +markview.nvim-comment.issues markview.nvim-comment.txt /*markview.nvim-comment.issues* +markview.nvim-comment.mentions markview.nvim-comment.txt /*markview.nvim-comment.mentions* +markview.nvim-comment.taglinks markview.nvim-comment.txt /*markview.nvim-comment.taglinks* +markview.nvim-comment.task_scopes markview.nvim-comment.txt /*markview.nvim-comment.task_scopes* +markview.nvim-comment.tasks markview.nvim-comment.txt /*markview.nvim-comment.tasks* +markview.nvim-comment.urls markview.nvim-comment.txt /*markview.nvim-comment.urls* markview.nvim-config markview.nvim-config.txt /*markview.nvim-config* markview.nvim-contribute markview.nvim.txt /*markview.nvim-contribute* markview.nvim-dev.txt markview.nvim-dev.txt /*markview.nvim-dev.txt* markview.nvim-experimental markview.nvim-experimental.txt /*markview.nvim-experimental* markview.nvim-experimental.date_formats markview.nvim-experimental.txt /*markview.nvim-experimental.date_formats* markview.nvim-experimental.date_time_formats markview.nvim-experimental.txt /*markview.nvim-experimental.date_time_formats* +markview.nvim-experimental.fancy_comments markview.nvim-experimental.txt /*markview.nvim-experimental.fancy_comments* markview.nvim-experimental.file_open_command markview.nvim-experimental.txt /*markview.nvim-experimental.file_open_command* markview.nvim-experimental.linewise_ignore_org_indent markview.nvim-experimental.txt /*markview.nvim-experimental.linewise_ignore_org_indent* markview.nvim-experimental.list_empty_line_tolerance markview.nvim-experimental.txt /*markview.nvim-experimental.list_empty_line_tolerance* @@ -30,6 +42,7 @@ markview.nvim-integrations.blink-cmp markview.nvim-integrations.txt /*markview.n markview.nvim-integrations.color_blending markview.nvim-integrations.txt /*markview.nvim-integrations.color_blending* markview.nvim-integrations.gx markview.nvim-integrations.txt /*markview.nvim-integrations.gx* markview.nvim-integrations.nowrap markview.nvim-integrations.txt /*markview.nvim-integrations.nowrap* +markview.nvim-integrations.nvim-fancy_comments markview.nvim-integrations.txt /*markview.nvim-integrations.nvim-fancy_comments* markview.nvim-integrations.transparent_colorschemes markview.nvim-integrations.txt /*markview.nvim-integrations.transparent_colorschemes* markview.nvim-integrations.wrap markview.nvim-integrations.txt /*markview.nvim-integrations.wrap* markview.nvim-latex markview.nvim-latex.txt /*markview.nvim-latex* diff --git a/lua/markview/autocmds.lua b/lua/markview/autocmds.lua index c5f5494..e709c9a 100644 --- a/lua/markview/autocmds.lua +++ b/lua/markview/autocmds.lua @@ -86,15 +86,27 @@ autocmds.should_detach = function (args) local condition = spec.get({ "preview", "condition" }, { eval_args = { args.buf } }); - if vim.list_contains(ignore_bt, bt) == true then - return true; - elseif vim.list_contains(attach_ft, ft) == false then - return true; - elseif condition == false then - return true; + --[[ + feat: Attaching to buffers. + + If condition is `true`(either `preview.condition = true` or the evaluated function value is `true`), attach to `buffer`. + + Otherwise, check if the **buftype** is included in `preview.ignore_buftypes`. If it is then we don't attach to `buffer`. + Then check if the **filetype** is included in `preview.filetypes`. IF it is we attach to `buffer`. + ]] + if condition == nil then + -- No condition specified. + + if vim.list_contains(ignore_bt, bt) == true then + --- Ignored buffer type. + return true; + elseif vim.list_contains(attach_ft, ft) == false then + --- Ignored file type. + return true; + end end - return false; + return condition == false; ---|fE end @@ -183,13 +195,26 @@ autocmds.bufHandle = function (args) local condition = spec.get({ "preview", "condition" }, { eval_args = { args.buf }, ignore_enable = true }); - if vim.list_contains(ignore_bt, bt) == true then - --- Ignored buffer type. - return; - elseif vim.list_contains(attach_ft, ft) == false then - --- Ignored file type. - return; + --[[ + feat: Attaching to buffers. + + If condition is `true`(either `preview.condition = true` or the evaluated function value is `true`), attach to `buffer`. + + Otherwise, check if the **buftype** is included in `preview.ignore_buftypes`. If it is then we don't attach to `buffer`. + Then check if the **filetype** is included in `preview.filetypes`. IF it is we attach to `buffer`. + ]] + if condition == nil then + -- No condition specified. + + if vim.list_contains(ignore_bt, bt) == true then + --- Ignored buffer type. + return; + elseif vim.list_contains(attach_ft, ft) == false then + --- Ignored file type. + return; + end elseif condition == false then + -- Condition not met. return; end diff --git a/lua/markview/config/comment.lua b/lua/markview/config/comment.lua new file mode 100644 index 0000000..f24b666 --- /dev/null +++ b/lua/markview/config/comment.lua @@ -0,0 +1,904 @@ +local function normalize_str(str) + if type(str) ~= "string" then + return ""; + end + + return string.lower(str):gsub("^%l", string.upper); +end + + +---@type markview.config.comment +return { + enable = true, + + autolinks = { + enable = true, + + default = { + icon = "ó°‹œ ", + hl = "MarkviewPalette6", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = "îȘ„ ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = "ï€Ź ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = "ï†Ą ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = "îȘ„ ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁎 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆩 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = "ïˆș ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, + + bolds = { + enable = true, + }, + + code_blocks = { + enable = true, + + border_hl = "MarkviewCode", + info_hl = "MarkviewCodeInfo", + + label_direction = "right", + label_hl = nil, + + min_width = 60, + pad_amount = 2, + pad_char = " ", + + default = { + block_hl = "MarkviewCode", + pad_hl = "MarkviewCode" + }, + + ["diff"] = { + block_hl = function (_, line) + if line:match("^%+") then + return "MarkviewPalette4"; + elseif line:match("^%-") then + return "MarkviewPalette1"; + else + return "MarkviewCode"; + end + end, + pad_hl = "MarkviewCode" + }, + + style = "block", + sign = true, + }, + + inline_codes = { + padding_left = " ", + padding_right = " ", + + hl = "MarkviewInlineCode", + }, + + issues = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette2", + }, + }, + + italics = { + enable = true, + }, + + mentions = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette5", + }, + }, + + taglinks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + }, + + tasks = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "󰄰 ", + + hl = "MarkviewPalette1", + }, + + ["^feat"] = { + padding_left = " ", + padding_right = " ", + + icon = "󱕅 ", + + hl = "MarkviewPalette7", + }, + + praise = { + padding_left = " ", + padding_right = " ", + + icon = "󱄋 ", + + hl = "MarkviewPalette3", + }, + + ["^suggest"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰣖 ", + + hl = "MarkviewPalette2", + }, + + thought = { + padding_left = " ", + padding_right = " ", + + icon = "󰧑 ", + + hl = "MarkviewPalette0", + }, + + note = { + padding_left = " ", + padding_right = " ", + + icon = "ó° ź ", + + hl = "MarkviewPalette5", + }, + + ["^info"] = { + padding_left = " ", + padding_right = " ", + + icon = "ó°‹Œ ", + + hl = "MarkviewPalette0", + }, + + xxx = { + padding_left = " ", + padding_right = " ", + + icon = "ó°“œ ", + + hl = "MarkviewPalette0", + }, + + ["^nit"] = { + padding_left = " ", + padding_right = " ", + + icon = "ó°©° ", + + hl = "MarkviewPalette6", + }, + + ["^warn"] = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette3", + }, + + fix = { + padding_left = " ", + padding_right = " ", + + icon = "󰁚 ", + + hl = "MarkviewPalette7", + }, + + hack = { + padding_left = " ", + padding_right = " ", + + icon = "󱍔 ", + + hl = "MarkviewPalette1", + }, + + typo = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette0", + }, + + wip = { + padding_left = " ", + padding_right = " ", + + icon = "󰩖 ", + + hl = "MarkviewPalette2", + }, + + issue = { + padding_left = " ", + padding_right = " ", + + icon = " ", + + hl = "MarkviewPalette1", + }, + + ["error"] = { + padding_left = " ", + padding_right = " ", + + icon = "󰅙 ", + + hl = "MarkviewPalette1", + }, + + fixme = { + padding_left = " ", + padding_right = " ", + + icon = "ó°¶Ż ", + + hl = "MarkviewPalette4", + }, + + deprecated = { + padding_left = " ", + padding_right = " ", + + icon = "󰩆 ", + + hl = "MarkviewPalette1", + }, + }, + + task_scopes = { + enable = true, + + default = { + padding_left = " ", + padding_right = " ", + + icon = "ó°ˆČ ", + + hl = "MarkviewPalette4", + }, + }, + + urls = { + enable = true, + + default = { + icon = "󰌷 ", + + hl = "MarkviewHyperlink", + }, + + ---|fS + + --NOTE(@OXY2DEV): Github sites. + + ["github%.com/[%a%d%-%_%.]+%/?$"] = { + --- github.com/ + icon = "îȘ„ ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/?$"] = { + --- github.com// + icon = "󰳐 ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/?$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/tree/[%a%d%-%_%.]+%/?$"] = { + --- github.com///tree/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + local repo, branch = string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)/tree/([%a%d%-%_%.]+)%/?$"); + return repo .. " at " .. branch; + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+%/?$"] = { + --- github.com///commits/ + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+/commits/[%a%d%-%_%.]+)%/?$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/releases$"] = { + --- github.com///releases + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Releases ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/releases$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/tags$"] = { + --- github.com///tags + icon = "ï€Ź ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Tags ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/tags$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/issues$"] = { + --- github.com///issues + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Issues ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/issues$"); + end + }, + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/pulls$"] = { + --- github.com///pulls + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Pull requests ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/pulls$"); + end + }, + + ["github%.com/[%a%d%-%_%.]+/[%a%d%-%_%.]+%/wiki$"] = { + --- github.com///wiki + icon = " ", + hl = "MarkviewPalette0Fg", + + text = function (_, item) + return "Wiki ‱ " .. string.match(item.destination, "github%.com/([%a%d%-%_%.]+/[%a%d%-%_%.]+)%/wiki$"); + end + }, + + --- NOTE(@OXY2DEV): Commonly used sites by programmers. + + ["developer%.mozilla%.org"] = { + priority = -9999, + + icon = "󰖟 ", + hl = "MarkviewPalette5Fg" + }, + + ["w3schools%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette4Fg" + }, + + ["stackoverflow%.com"] = { + priority = -9999, + + icon = "󰓌 ", + hl = "MarkviewPalette2Fg" + }, + + ["reddit%.com"] = { + priority = -9999, + + icon = "ï†Ą ", + hl = "MarkviewPalette2Fg" + }, + + ["github%.com"] = { + priority = -9999, + + icon = "îȘ„ ", + hl = "MarkviewPalette6Fg" + }, + + ["gitlab%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["dev%.to"] = { + priority = -9999, + + icon = "󱁎 ", + hl = "MarkviewPalette0Fg" + }, + + ["codepen%.io"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette6Fg" + }, + + ["replit%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["jsfiddle%.net"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette5Fg" + }, + + ["npmjs%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette0Fg" + }, + + ["pypi%.org"] = { + priority = -9999, + + icon = "󰆩 ", + hl = "MarkviewPalette0Fg" + }, + + ["mvnrepository%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette1Fg" + }, + + ["medium%.com"] = { + priority = -9999, + + icon = "ïˆș ", + hl = "MarkviewPalette6Fg" + }, + + ["linkedin%.com"] = { + priority = -9999, + + icon = "󰌻 ", + hl = "MarkviewPalette5Fg" + }, + + ["news%.ycombinator%.com"] = { + priority = -9999, + + icon = " ", + hl = "MarkviewPalette2Fg" + }, + + ["neovim%.io/doc/user/.*#%_?.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file, tag = string.match(item.destination, "neovim%.io/doc/user/(.*)#%_?(.*)$"); + --- The actual website seems to show + --- _ in the site name so, we won't + --- be replacing `_`s with ` `s. + file = string.gsub(file, "%.html$", ""); + + return string.format("%s(%s) - Neovim docs", normalize_str(file), tag); + end + }, + ["neovim%.io/doc/user/.*$"] = { + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + + text = function (_, item) + local file = string.match(item.destination, "neovim%.io/doc/user/(.*)$"); + file = string.gsub(file, "%.html$", ""); + + return string.format("%s - Neovim docs", normalize_str(file)); + end + }, + + ["github%.com/vim/vim"] = { + priority = -100, + + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["github%.com/neovim/neovim"] = { + priority = -100, + + icon = "ïŻ ", + hl = "MarkviewPalette4Fg", + }, + + ["vim%.org"] = { + icon = " ", + hl = "MarkviewPalette4Fg", + }, + + ["luals%.github%.io/wiki/?.*$"] = { + icon = " ", + hl = "MarkviewPalette5Fg", + + text = function (_, item) + if string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$") then + local page_mappings = { + annotations = { + ["as"] = "@as", + ["alias"] = "@alias", + ["async"] = "@async", + ["cast"] = "@cast", + ["class"] = "@class", + ["deprecated"] = "@deprecated", + ["diagnostic"] = "@diagnostic", + ["enum"] = "@enum", + ["field"] = "@field", + ["generic"] = "@generic", + ["meta"] = "@meta", + ["module"] = "@module", + ["nodiscard"] = "@nodiscard", + ["operator"] = "@operator", + ["overload"] = "@overload", + ["package"] = "@package", + ["param"] = "@param", + ["see"] = "@see", + ["source"] = "@source", + ["type"] = "@type", + ["vaarg"] = "@vaarg", + ["version"] = "@version" + } + }; + + local page, section = string.match(item.destination, "luals%.github%.io/wiki/(.-)/#(.+)$"); + + if page_mappings[page] and page_mappings[page][section] then + section = page_mappings[page][section]; + else + section = normalize_str(string.gsub(section, "%-", " ")); + end + + return string.format("%s(%s) | Lua Language Server", normalize_str(page), section); + elseif string.match(item.destination, "") then + local page = string.match(item.destination, "luals%.github%.io/wiki/(.-)/?$"); + + return string.format("%s | Lua Language Server", normalize_str(page)); + else + return item.destination; + end + end + }, + + ---|fE + }, +}; diff --git a/lua/markview/filetypes.lua b/lua/markview/filetypes.lua index 34115c5..41e4baa 100644 --- a/lua/markview/filetypes.lua +++ b/lua/markview/filetypes.lua @@ -781,7 +781,7 @@ fts.get = function (ft) end local this_conf = fts.styles[_ft] or fts.styles[ft] or fts.styles.default; - conf.name = this_conf.name or string.gsub(ft, "^%w", string.upper) or "Unknown"; + conf.name = this_conf.name or ( type(ft) == "string" and string.gsub(ft, "^%w", string.upper) or "Unknown" ); return conf; end diff --git a/lua/markview/parser.lua b/lua/markview/parser.lua index fa73912..aa7a82b 100644 --- a/lua/markview/parser.lua +++ b/lua/markview/parser.lua @@ -99,6 +99,7 @@ parser.init = function (buffer, from, to, cache) ---|fS local _parsers = { + comment = require("markview.parsers.comment"); markdown = require("markview.parsers.markdown"); markdown_inline = require("markview.parsers.markdown_inline"); html = require("markview.parsers.html"); diff --git a/lua/markview/parsers/comment.lua b/lua/markview/parsers/comment.lua new file mode 100644 index 0000000..053df4a --- /dev/null +++ b/lua/markview/parsers/comment.lua @@ -0,0 +1,552 @@ +--- HTML parser for `markview.nvim`. +local comment = {}; + +--- Queried contents +---@type table[] +comment.content = {}; + +--- Queried contents, but sorted +---@type markview.parsed.comment_sorted +---@diagnostic disable-next-line: missing-fields +comment.sorted = {} + +--[[ Wrapper for `table.insert()`. ]] +---@param data table +comment.insert = function (data) + table.insert(comment.content, data); + + if not comment.sorted[data.class] then + comment.sorted[data.class] = {}; + end + + table.insert(comment.sorted[data.class], data); +end + +--[[ +Conventional commit style tasks. + +```comment +feat: Added comment parser. +``` +]] +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.comment.tasks.range +comment.task = function (buffer, TSNode, text, range) + ---|fS + + local kind = TSNode:field("type")[1]; + + for child in TSNode:iter_children() do + if child:type() == ":" then + _, _, range.label_row_end, range.label_col_end = child:range(); + end + end + + if not kind then + return; + end + + range.kind = { kind:range(); }; + + comment.insert({ + class = "comment_task", + kind = vim.treesitter.get_node_text(kind, buffer, {}), + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +Conventional commit style tasks(for the original parser). + +```comment +feat: Added comment parser. +``` +]] +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.comment.tasks.range +comment.tag = function (buffer, TSNode, text, range) + ---|fS + + local kind; + + for child in TSNode:iter_children() do + if child:type() == "name" then + kind = child; + range.kind = { child:range() }; + + range.label_row_end = range.row_start; + range.label_col_end = range.kind[4] + 1; -- `:` is part of the label! + elseif child:type() == "user" then + local user_range = { child:range() }; + + range.label_row_end = range.row_start; + range.label_col_end = user_range[4] + 2; -- `:` is part of the label! + + -- Add special syntax support for scope text. + comment.tag_scope(buffer, child, { vim.treesitter.get_node_text(child, buffer, {}) }, user_range); + end + end + + if not kind then + return; + end + + comment.insert({ + class = "comment_task", + kind = vim.treesitter.get_node_text(kind, buffer, {}), + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +Conventional commit style task scope(for the original parser). + +```comment +feat(scope): Added comment parser. +``` +]] +---@param buffer integer +---@param _ TSNode +---@param text string[] +---@param root_range markview.parsed.comment.tasks.range +comment.tag_scope = function (buffer, _, text, root_range) + ---|fS + + local lpeg = vim.lpeg; + + local function as_wspace (m) return { kind = "space", value = m }; end + local function as_comma (m) return { kind = "comma", value = m }; end + + local function as_issue (m) return { kind = "issue", value = m }; end + local function as_mention (m) return { kind = "mention", value = m }; end + local function as_word (m) return { kind = "word", value = m }; end + + local space = lpeg.C( lpeg.S(" \t\n\r") ) / as_wspace; + local comma = lpeg.C( lpeg.P(",") ) / as_comma; + + local walnum = lpeg.R("az", "AZ", "09"); + local non_wspacse = 1 - ( space + comma ); + local word = lpeg.C( walnum * (non_wspacse^0) ) / as_word; + + local mention = lpeg.C( lpeg.P("@") * (non_wspacse^1) ) / as_mention; + + local num_issue = lpeg.C( lpeg.P("#") * ( lpeg.R("09") ^ 1 ) ) / as_issue; + + local invalid_cahrs = space + lpeg.P("#"); + local issue_name = lpeg.R("az", "AZ", "09") * (1 - invalid_cahrs)^0; + local desc_issue = lpeg.C( issue_name * lpeg.P("#") * ( lpeg.R("09") ^ 1 ) ) / as_issue; + + local token = space + comma + desc_issue + num_issue + mention + word; + + --[[ + A scope may contain one or more `token`s separated by `,` & *whitespaces*. + + Valid tokens may be any of, + + - Mentions(`@foo`). + - Issue reference(`#48`, `OXY2DEV/markview.nvim#48`). + - Keyword(must start with a letter). + ]] + local scope = lpeg.Ct(token^0); + + local col_start = root_range[2]; + + for _, item in ipairs(lpeg.match(scope, text[1] or "")) do + if item.kind == "word" then + comment.task_scope(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + elseif item.kind == "issue" then + comment.issue(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + elseif item.kind == "mention" then + comment.mention(buffer, nil, { item.value }, { + row_start = root_range[1], + col_start = col_start, + + row_end = root_range[3], + col_end = col_start + #item.value, + }); + end + + col_start = col_start + #item.value; + end + + ---|fE +end + +--[[ +Conventional commit style task scope. + +```comment +feat(scope): Added comment parser. +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.task_scope = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_task_scope", + + text = text, + range = range, + }); + + ---|fE +end + +---@param text string[] +---@param range markview.parsed.range +comment.bold = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_bold", + + text = text, + range = range, + }); + + ---|fE +end + +---@param text string[] +---@param range markview.parsed.range +comment.italic = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_italic", + + text = text, + range = range, + }); + + ---|fE +end + +---@param text string[] +---@param range markview.parsed.range +comment.inline_code = function (_, _, text, range) + comment.insert({ + class = "comment_inline_code", + + text = text, + range = range, + }); +end + +--[[ +Markdown-style fenced code blocks. + +```lua +vim.print("Hello, Neovim!"); +``` +]] +---@param buffer integer +---@param TSNode TSNode +---@param text string[] +---@param range markview.parsed.comment.code_blocks.range +comment.code_block = function (buffer, TSNode, text, range) + ---|fS + + local uses_tab = false; + + local lang = TSNode:field("language")[1]; + local language; + + if lang then + language = vim.treesitter.get_node_text(lang, buffer, {}); + range.language = { lang:range() }; + end + + for _, line in ipairs(text) do + if string.match(line, "\t") then + uses_tab = true; + break; + end + end + + ---@type TSNode, TSNode? + local start_delim, end_delim; + + for child in TSNode:iter_children() do + if child:type() == "start_delimiter" then + start_delim = child; + local delim = vim.treesitter.get_node_text(child, buffer, {}); + + range.start_delim = { child:range() }; + range.start_delim[2] = range.start_delim[2] + #string.match(delim, "^%s*"); + elseif child:type() == "end_delimiter" then + end_delim = child; + local delim = vim.treesitter.get_node_text(child, buffer, {}); + + range.end_delim = { child:range() }; + range.end_delim[2] = range.end_delim[2] + #string.match(delim, "^%s*"); + end + end + + comment.insert({ + class = "comment_code_block", + uses_tab = uses_tab, + + language = language, + info_string = nil, + delimiters = { + start_delim and vim.treesitter.get_node_text(start_delim, buffer) or "", + end_delim and vim.treesitter.get_node_text(end_delim, buffer) or "", + }, + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +Issue reference. + +It may be of any of the following format(s), + +- Numeric(`#99`). +- Descriptive(`owner/repo#99`). + +```comment +OXY2DEV/markview.nvim#48 +#48 +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.issue = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_issue", + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +User handle mention. + +```comment +See, @username +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.mention = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_mention", + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +URL. + +```comment +www.example.com +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.url = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_url", + destination = text[1] or "", + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +Markdown-like autolinks. + +```comment +Mail to +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.autolink = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_autolink", + destination = string.gsub(text[1] or "", "^%<", ""):gsub("%>$", ""), + + text = text, + range = range, + }); + + ---|fE +end + +--[[ +Vimdoc-like help tag links. + +```comment +See |intro.txt| +``` +]] +---@param text string[] +---@param range markview.parsed.range +comment.taglink = function (_, _, text, range) + ---|fS + + comment.insert({ + class = "comment_taglink", + + text = text, + range = range, + }); + + ---|fE +end + +---@param buffer integer +---@param TSTree table +---@param from integer? +---@param to integer? +---@return markview.parsed.comment[] +---@return markview.parsed.comment_sorted +comment.parse = function (buffer, TSTree, from, to) + ---|fS + + ---@diagnostic disable-next-line: missing-fields + comment.sorted = {}; + comment.content = {}; + + local scanned_queries; + + if pcall(vim.treesitter.query.parse, "comment", "(source) @test") then + scanned_queries = vim.treesitter.query.parse("comment", [[ + (tag) @comment.tag ; Task. + (uri) @comment.url + ]]); + else + scanned_queries = vim.treesitter.query.parse("comment", [[ + (task) @comment.task + + (task_scope + (word) @comment.task_scope) + + (bold) @comment.bold + (italic) @comment.italic + + (code) @comment.inline_code + (code_block) @comment.code_block + + (issue_reference) @comment.issue + (mention) @comment.mention + (url) @comment.url + (autolink) @comment.autolink + (taglink) @comment.taglink + ]]); + end + + for capture_id, capture_node, _, _ in scanned_queries:iter_captures(TSTree:root(), buffer, from, to) do + local capture_name = scanned_queries.captures[capture_id]; + + if not capture_name:match("^comment%.") then + goto continue; + end + + ---@type string? + local capture_text = vim.treesitter.get_node_text(capture_node, buffer); + local r_start, c_start, r_end, c_end = capture_node:range(); + + if capture_text == nil then + goto continue; + end + + if not capture_text:match("\n$") then + capture_text = capture_text .. "\n"; + end + + local lines = {}; + + for line in capture_text:gmatch("(.-)\n") do + table.insert(lines, line); + end + + ---@type boolean, string + local success, error = pcall( + comment[capture_name:gsub("^comment%.", "")], + + buffer, + capture_node, + lines, + { + row_start = r_start, + col_start = c_start, + + row_end = r_end, + col_end = c_end + } + ); + + if success == false then + require("markview.health").print({ + kind = "ERR", + + from = "parsers/comment.lua", + fn = "parse()", + + message = { + { tostring(error), "DiagnosticError" } + } + }); + end + + ::continue:: + end + + return comment.content, comment.sorted; + + ---|fE +end + +return comment; + diff --git a/lua/markview/renderer.lua b/lua/markview/renderer.lua index 41fbcc9..3beaf54 100644 --- a/lua/markview/renderer.lua +++ b/lua/markview/renderer.lua @@ -15,6 +15,17 @@ renderer.__filter_cache = { renderer.option_maps = { ---|fS + comment = { + autolinks = { "comment_autolink" }, + code_blocks = { "comment_code_block" }, + inline_codes = { "comment_inline_code" }, + issues = { "comment_issue" }, + mentions = { "comment_mention" }, + taglinks = { "comment_taglink" }, + task_scopes = { "comment_task_scope" }, + tasks = { "comment_task" }, + urls = { "comment_url" }, + }, html = { container_elements = { "html_container_element" }, headings = { "html_heading" }, @@ -34,31 +45,30 @@ renderer.option_maps = { }, markdown = { block_quotes = { "markdown_block_quote" }, + checkboxes = { "markdown_checkbox" }, code_blocks = { "markdown_code_block" }, headings = { "markdown_atx_heading", "markdown_setext_heading" }, horizontal_rules = { "markdown_hr" }, list_items = { "markdown_list_item" }, metadata_minus = { "markdown_metadata_minus" }, metadata_plus = { "markdown_metadata_plus" }, - tables = { "markdown_table" }, reference_definitions = { "markdown_link_ref_definition" }, - - checkboxes = { "markdown_checkbox" }, + tables = { "markdown_table" }, }, markdown_inline = { + block_references = { "inline_link_block_ref" }, checkboxes = { "inline_checkbox" }, - inline_codes = { "inline_code_span" }, + emails = { "inline_link_email" }, + embed_files = { "inline_embed_files" }, entities = { "inline_entity" }, escapes = { "inline_escaped" }, footnotes = { "inline_footnote" }, highlights = { "inline_highlight" }, - block_references = { "inline_link_block_ref" }, - embed_files = { "inline_embed_files" }, - emails = { "inline_link_email" }, hyperlinks = { "inline_link_hyperlink", "inline_link_shortcut" }, images = { "inline_link_image" }, - uri_autolinks = { "inline_link_uri_autolink" }, + inline_codes = { "inline_code_span" }, internal_links = { "inline_link_internal" }, + uri_autolinks = { "inline_link_uri_autolink" }, }, typst = { code_blocks = { "typst_code_block" }, @@ -67,16 +77,16 @@ renderer.option_maps = { headings = { "typst_heading" }, labels = { "typst_label" }, list_items = { "typst_list_item" }, - reference_links = { "typst_link_ref" }, - url_links = { "typst_link_url" }, math_blocks = { "typst_math_blocks" }, math_spans = { "typst_math_spans" }, raw_blocks = { "typst_raw_block" }, raw_spans = { "typst_raw_span" }, + reference_links = { "typst_link_ref" }, subscripts = { "typst_subscript" }, superscripts = { "typst_superscript" }, symbols = { "typst_symbol" }, terms = { "typst_terms" }, + url_links = { "typst_link_url" }, }, yaml = { properties = { "yaml_property" }, @@ -356,6 +366,7 @@ renderer.render = function (buffer, parsed_content) ---|fS local _renderers = { + comment = require("markview.renderers.comment"), html = require("markview.renderers.html"), markdown = require("markview.renderers.markdown"), markdown_inline = require("markview.renderers.markdown_inline"), @@ -459,6 +470,7 @@ renderer.clear = function (buffer, from, to, hybrid_mode) ---|fS local _renderers = { + comment = require("markview.renderers.comment"); html = require("markview.renderers.html"); markdown = require("markview.renderers.markdown"); markdown_inline = require("markview.renderers.markdown_inline"); diff --git a/lua/markview/renderers/comment.lua b/lua/markview/renderers/comment.lua new file mode 100644 index 0000000..1774275 --- /dev/null +++ b/lua/markview/renderers/comment.lua @@ -0,0 +1,986 @@ +local comment = {}; + +local utils = require("markview.utils"); +local spec = require("markview.spec"); + +comment.ns = vim.api.nvim_create_namespace("markview/comment"); + +---@param buffer integer +---@param item markview.parsed.comment.autolinks +comment.autolink = function (buffer, item) + ---|fS + + ---@type markview.config.comment.autolinks? + local main_config = spec.get({ "comment", "autolinks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comments.autolinks.opts? + local config = utils.match(main_config, item.destination or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = config.text and range.col_end - 1 or range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) }, + config.text and { config.text, utils.set_hl(config.text_hl or config.hl) } or nil, + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.tasks +comment.task = function (buffer, item) + ---|fS + + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "tasks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.tasks.opts? + local config = utils.match(main_config, item.kind, { + case_insensitive = true, + + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + local row_end = range.label_row_end or range.kind[3]; + local col_end = range.label_col_end or range.kind[4]; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.kind[1], range.kind[2], { + undo_restore = false, invalidate = true, + end_row = row_end, + end_col = col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, row_end, col_end - 1, { + undo_restore = false, invalidate = true, + end_col = col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + if config.desc_hl then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, row_end, col_end, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.desc_hl) + }); + end + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.task_scopes +comment.task_scope = function (buffer, item) + ---|fS + + ---@type markview.config.comment.task_scopes? + local main_config = spec.get({ "comment", "task_scopes" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.__inline? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.issues +comment.issue = function (buffer, item) + ---|fS + + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "issues" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.tasks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.mentions +comment.mention = function (buffer, item) + ---|fS + + ---@type markview.config.comment.tasks? + local main_config = spec.get({ "comment", "mentions" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comment.tasks.opts? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.inline_code = function (buffer, item) + ---|fS + + ---@type markview.config.comment.inline_codes? + local config = spec.get({ "comment", "inline_codes" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +--- Renders fenced code blocks. +---@param buffer integer +---@param item markview.parsed.comment.code_blocks +comment.code_block = function (buffer, item) + ---|fS + + ---@type markview.config.comment.code_blocks? + local config = spec.get({ "comment", "code_blocks" }, { fallback = nil, eval_args = { buffer, item } }); + + local delims = item.delimiters; + local range = item.range; + + if not config then + return; + end + + local decorations = require("markview.filetypes").get(item.language); + local label = { string.format(" %s%s ", decorations.icon, decorations.name), config.label_hl or decorations.icon_hl }; + local win = utils.buf_getwin(buffer); + + --- Gets highlight configuration for a line. + ---@param line string + ---@return markview.config.comment.code_blocks.opts + local function get_line_config(line) + local line_conf = utils.match(config, item.language, { + eval_args = { buffer, line }, + def_fallback = { + block_hl = config.border_hl, + pad_hl = config.border_hl + }, + fallback = { + block_hl = config.border_hl, + pad_hl = config.border_hl + } + }); + + return line_conf; + end + + --[[ *Basic* rendering of `code blocks`. ]] + local function render_simple() + ---|fS + + ---@cast config markview.config.comment.code_blocks.simple + + local conceal_from = range.start_delim[2]; + local conceal_to = range.col_start + #(item.text[1] or ""); + + if config.label_direction == nil or config.label_direction == "left" then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, conceal_from, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "", + + sign_text = config.sign == true and decorations.sign or nil, + sign_hl_group = utils.set_hl(config.sign_hl or decorations.sign_hl), + + virt_text_pos = "inline", + virt_text = { label }, + + line_hl_group = utils.set_hl(config.border_hl) + }); + else + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, conceal_from, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "", + + sign_text = config.sign == true and decorations.sign or nil, + sign_hl_group = utils.set_hl(config.sign_hl or decorations.sign_hl), + + virt_text_pos = "right_align", + virt_text = { label }, + + line_hl_group = utils.set_hl(config.border_hl) + }); + end + + --- Background + for l = range.row_start + 1, range.row_end - 1 do + local line = item.text[(l - range.row_start) + 1]; + local line_config = get_line_config(line); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, l, 0, { + undo_restore = false, invalidate = true, + end_row = l, + + line_hl_group = utils.set_hl(line_config.block_hl --[[ @as string ]]) + }); + end + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, (range.col_start + #item.text[#item.text]) - #delims[2], { + undo_restore = false, invalidate = true, + end_col = range.col_start + #item.text[#item.text], + conceal = "", + + line_hl_group = utils.set_hl(config.border_hl) + }); + + ---|fE + end + + --- Renders block style code blocks. + local function render_block () + ---|fS + + ---@cast config markview.config.comment.code_blocks.block + + ---|fS "chunk: Calculate various widths" + + local pad_amount = config.pad_amount or 0; + local block_width = config.min_width or 60; + + local pad_char = config.pad_char or " "; + + ---@type integer[] Visual width of lines. + local line_widths = {}; + + for l, line in ipairs(item.text) do + local final = require("markview.renderers.markdown").get_visual_text:init(decorations.name, line); + + if l ~= 1 and l ~= #item.text then + table.insert(line_widths, vim.fn.strdisplaywidth(final)); + + if vim.fn.strdisplaywidth(final) > (block_width - (2 * pad_amount)) then + block_width = vim.fn.strdisplaywidth(final) + (2 * pad_amount); + end + end + end + + local label_width = utils.virt_len({ label }); + + ---|fE + + local delim_conceal_from = range.start_delim[2]; + local conceal_to = range.col_start + #(item.text[1] or ""); + + ---|fS "chunk: Top border" + + local left_padding = pad_amount; + + local pad_width = vim.fn.strdisplaywidth( + string.rep(pad_char, left_padding) + ); + + -- Hide the leading `backticks`s. + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + + end_col = conceal_to, + conceal = "" + }); + + if config.label_direction == "right" then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, delim_conceal_from, { + virt_text_pos = "inline", + virt_text = { + { + string.rep(" " or pad_char, left_padding), + utils.set_hl(config.border_hl) + } + } + }); + else + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start + #item.text[1], { + virt_text_pos = "inline", + virt_text = { + { + string.rep(" " or pad_char, left_padding), + utils.set_hl(config.border_hl) + } + } + }); + end + + -- Calculating the amount of spacing to add, + -- 1. Used space = label width(`label_width`) + padding size(`pad_width`). + -- 2. Total block width - Used space + local spacing = block_width - (label_width + pad_width); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start + #item.text[1], { + virt_text_pos = "inline", + virt_text = { + { + string.rep(pad_char, spacing), + utils.set_hl(config.border_hl) + }, + } + }); + + ---|fS "chunk: Place label" + + local top_border = { + }; + + if config.label_direction == "right" then + top_border.col_start = range.start_delim[2] + #item.text[1]; + else + top_border.col_start = range.start_delim[4]; + end + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, top_border.col_start, { + virt_text_pos = "inline", + virt_text = { label } + }); + + ---|fE + + ---|fE + + --- Line padding + for l, width in ipairs(line_widths) do + local line = item.text[l + 1]; + local line_config = get_line_config(line); + + if width ~= 0 then + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, line ~= "" and range.col_start or 0, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + } + }, + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, range.col_start + #line, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", math.max(0, block_width - (( 2 * pad_amount) + width))), + utils.set_hl(line_config.block_hl --[[ @as string ]]) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + } + }, + }); + + --- Background + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + #line, + + hl_group = utils.set_hl(line_config.block_hl --[[ @as string ]]) + }); + else + local buf_line = vim.api.nvim_buf_get_lines(buffer, range.row_start + l, range.row_start + l + 1, false)[1]; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start + l, #buf_line, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", math.max(0, range.col_start - #buf_line)) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + }, + { + string.rep(" ", math.max(0, block_width - (2 * pad_amount))), + utils.set_hl(line_config.block_hl --[[ @as string ]]) + }, + { + string.rep(" ", pad_amount), + utils.set_hl(line_config.pad_hl --[[ @as string ]]) + }, + }, + }); + end + end + + --- Render bottom + local end_delim_conceal_from = range.end_delim[2] + #string.match(item.delimiters[2], "^%s*"); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, end_delim_conceal_from, { + undo_restore = false, invalidate = true, + end_col = range.col_start + #item.text[#item.text], + conceal = "" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, end_delim_conceal_from, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { + string.rep(" ", block_width), + utils.set_hl(config.border_hl) + } + } + }); + + ---|fE + end + + if not win or config.style == "simple" or item.uses_tab or ( vim.o.wrap == true or vim.wo[win].wrap == true ) then + render_simple(); + elseif config.style == "block" then + render_block() + end + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.urls +comment.url = function (buffer, item) + ---|fS + + ---@type markview.config.comment.urls? + local main_config = spec.get({ "comment", "urls" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.comments.urls.opts? + local config = utils.match(main_config, item.destination or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = config.text and range.col_end or nil, + conceal = config.text and "" or nil, + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) }, + config.text and { config.text, utils.set_hl(config.text_hl or config.hl) } or nil, + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end, { + undo_restore = false, invalidate = true, + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.taglinks +comment.taglink = function (buffer, item) + ---|fS + + ---@type markview.config.comment.taglinks? + local main_config = spec.get({ "comment", "taglinks" }, { fallback = nil }); + + if not main_config then + return; + end + + ---@type markview.config.__inline? + local config = utils.match(main_config, item.text[1] or "", { + ignore_keys = { "enable" }, + eval_args = { buffer, item } + }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.bold = function (buffer, item) + ---|fS + + ---@type markview.config.comment.bolds? + local config = spec.get({ "comment", "bolds" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 2, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 2, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +---@param buffer integer +---@param item markview.parsed.comment.inline_codes +comment.italic = function (buffer, item) + ---|fS + + ---@type markview.config.comment.italics? + local config = spec.get({ "comment", "italics" }, { fallback = nil }); + + if not config then + return; + end + + local range = item.range; + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_col = range.col_start + 1, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.corner_left or "", utils.set_hl(config.corner_left_hl or config.hl) }, + { config.padding_left or "", utils.set_hl(config.padding_left_hl or config.hl) }, + + { config.icon or "", utils.set_hl(config.icon_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_start, range.col_start, { + undo_restore = false, invalidate = true, + end_row = range.row_end, + end_col = range.col_end, + + hl_group = utils.set_hl(config.hl) + }); + + vim.api.nvim_buf_set_extmark(buffer, comment.ns, range.row_end, range.col_end - 1, { + undo_restore = false, invalidate = true, + end_col = range.col_end, + conceal = "", + + virt_text_pos = "inline", + virt_text = { + { config.padding_right or "", utils.set_hl(config.padding_right_hl or config.hl) }, + { config.corner_right or "", utils.set_hl(config.corner_right_hl or config.hl) } + }, + + hl_mode = "combine" + }); + + ---|fE +end + +--- Renders fancy comments +---@param buffer integer +---@param content markview.parsed.comment[] +comment.render = function (buffer, content) + ---|fS + + local custom = spec.get({ "renderers" }, { fallback = {} }); + + for _, item in ipairs(content or {}) do + local success, err; + + if custom[item.class] then + success, err = pcall(custom[item.class], comment.ns, buffer, item); + else + success, err = pcall(comment[item.class:gsub("^comment_", "")], buffer, item); + end + + if success == false then + require("markview.health").print({ + kind = "ERR", + + from = "renderers/comment.lua", + fn = "render() -> " .. item.class, + + message = { + { tostring(err), "DiagnosticError" } + } + }); + end + end + + ---|fE +end + +--- Clears decorations of fancy comments +---@param buffer integer +---@param from integer +---@param to integer +comment.clear = function (buffer, from, to) + vim.api.nvim_buf_clear_namespace(buffer, comment.ns, from or 0, to or -1); +end + +return comment; diff --git a/lua/markview/spec.lua b/lua/markview/spec.lua index f69294c..d35690f 100644 --- a/lua/markview/spec.lua +++ b/lua/markview/spec.lua @@ -8,6 +8,8 @@ local spec = {}; ---@type markview.config spec.default = { experimental = { + fancy_comments = false, + date_formats = { "^%d%d%d%d%-%d%d%-%d%d$", --- YYYY-MM-DD "^%d%d%-%d%d%-%d%d%d%d$", --- DD-MM-YYYY, MM-DD-YYYY @@ -187,8 +189,23 @@ spec.default = { debounce = 150, icon_provider = "internal", - filetypes = { "markdown", "quarto", "rmd", "typst" }, + filetypes = { "markdown", "quarto", "rmd", "typst", }, ignore_buftypes = { "nofile" }, + condition = function (buffer) + local is_enabled = spec.get({ "experimental", "fancy_comments" }, { + fallback = false, + }); + + if not is_enabled then + return false; + end + + local success, parser = pcall(vim.treesitter.get_parser, buffer); + if success and parser ~= nil then + return true; + end + end, + raw_previews = {}, modes = { "n", "no", "c" }, @@ -210,6 +227,7 @@ spec.default = { ---@type string[] Properties that should be sourced *externally*. spec.__external_config = { + "comment", "html", "markdown", "markdown_inline", diff --git a/lua/markview/types/experimental.lua b/lua/markview/types/experimental.lua index c693694..ac3356a 100644 --- a/lua/markview/types/experimental.lua +++ b/lua/markview/types/experimental.lua @@ -3,6 +3,8 @@ --- Experimental options. ---@class markview.config.experimental --- +---@field fancy_comments boolean When `true`, enables preview on **all buffers** with an active `tree-sitter parser`. +--- ---@field date_formats string[] List of lua patterns for detecting date in YAML. ---@field date_time_formats string[] List of lua patterns for detecting date & time in YAML. --- diff --git a/lua/markview/types/markview.lua b/lua/markview/types/markview.lua index ecc1f72..c814423 100644 --- a/lua/markview/types/markview.lua +++ b/lua/markview/types/markview.lua @@ -100,6 +100,7 @@ --- Maps a `node_type` to an option name. ---@class markview.renderer.option_maps --- +---@field comment markview.renderer.option_map ---@field html markview.renderer.option_map ---@field latex markview.renderer.option_map ---@field markdown markview.renderer.option_map diff --git a/lua/markview/types/parsers/comment.lua b/lua/markview/types/parsers/comment.lua new file mode 100644 index 0000000..b2a6f83 --- /dev/null +++ b/lua/markview/types/parsers/comment.lua @@ -0,0 +1,158 @@ +---@meta + +------------------------------------------------------------------------------ + +--[[ +An autolink. + +```comment + +``` +]] +---@class markview.parsed.comment.autolinks +--- +---@field class "comment_autolink" +---@field destination string Text between `<>`. +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- A `task`. +---@class markview.parsed.comment.tasks +--- +---@field class "comment_task" +--- +---@field kind string Type of task(e.g. `feat`, `TODO` etc.) +---@field text string +---@field range markview.parsed.comment.tasks.range + + +---@class markview.parsed.comment.tasks.range +--- +---@field label_row_end? integer End row of a label(A label may be like `foo:`, `bar(topic):`). +---@field label_col_end? integer End column of a label(A label may be like `foo:`, `bar(topic):`). +--- +---@field kind integer[] Range of the `task kind`(result of `{ TSNode:range() }`). +--- +---@field row_start integer +---@field row_end integer +---@field col_start integer +---@field col_end integer + +------------------------------------------------------------------------------ + +--- A `task` scope. +---@class markview.parsed.comment.task_scopes +--- +---@field class "comment_task_scopes" +--- +---@field text string +---@field range markview.parsed.comment.tasks.range + +------------------------------------------------------------------------------ + +--- An issue reference. +---@class markview.parsed.comment.issues +--- +---@field class "comment_issue" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- An URL. +---@class markview.parsed.comment.urls +--- +---@field class "comment_url" +---@field destination string +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- A taglink. +---@class markview.parsed.comment.taglinks +--- +---@field class "comment_taglink" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- A mention. +---@class markview.parsed.comment.mentions +--- +---@field class "comment_mention" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +--- A mention. +---@class markview.parsed.comment.inline_codes +--- +---@field class "comment_inline_code" +--- +---@field text string +---@field range markview.parsed.range + +------------------------------------------------------------------------------ + +---@class markview.parsed.comment.code_blocks +--- +---@field class "markdown_code_block" +---@field uses_tab boolean Does the code block use tab inside it? Used for switching render style. +--- +---@field delimiters [ string, string ] Code block delimiters(```). +---@field language string? Language string(typically after ```). +---@field info_string string? Extra information(typically after the language). +--- +---@field text string[] +---@field range markview.parsed.comment.code_blocks.range + + +---@class markview.parsed.comment.code_blocks.range +--- +---@field start_delim integer[] Range of the **start** delimiter. +---@field end_delim? integer[] Range of the **end** delimiter. +--- +---@field row_start integer +---@field row_end integer +---@field col_start integer +---@field col_end integer +--- +---@field language? integer[] Range of the language string. +---@field info_string? integer[] Range of info string. + +------------------------------------------------------------------------------ + +---@alias markview.parsed.comment +---| markview.parsed.comment.autolinks +---| markview.parsed.comment.code_blocks +---| markview.parsed.comment.inline_codes +---| markview.parsed.comment.issues +---| markview.parsed.comment.mentions +---| markview.parsed.comment.taglinks +---| markview.parsed.comment.tasks +---| markview.parsed.comment.task_scopes +---| markview.parsed.comment.urls + + +---@class markview.parsed.comment_sorted +--- +---@field autolinks markview.parsed.comment.autolinks[] +---@field code_blocks markview.parsed.comment.code_blocks[] +---@field inline_codes markview.parsed.comment.inline_codes[] +---@field issues markview.parsed.comment.issues[] +---@field mentions markview.parsed.comment.mentions[] +---@field taglinks markview.parsed.comment.taglinks[] +---@field tasks markview.parsed.comment.tasks[] +---@field task_scopes markview.parsed.comment.task_scopes[] +---@field urls markview.parsed.comment.urls[] + diff --git a/lua/markview/types/preview.lua b/lua/markview/types/preview.lua index 9f4888a..dfa5574 100644 --- a/lua/markview/types/preview.lua +++ b/lua/markview/types/preview.lua @@ -22,7 +22,7 @@ ---@field ignore_buftypes? string[] Buftypes that should be ignored(e.g. nofile). ---@field raw_previews? markview.config.preview.raw Options that will show up as raw in hybrid mode. --- ----@field condition? fun(buffer: integer): boolean Condition to check if a buffer should be attached or not. +---@field condition? fun(buffer: integer): boolean? Condition to check if a buffer should be attached or not. Overrides `preview.filetypes` & `preview.ignore_buftypes`. If `nil` is returned, `preview.filetypes` & `preview.ignore_buftypes` are checked. --- ---@field modes? string[] Vim-modes where previews will be shown. ---@field hybrid_modes? string[] Vim-modes where `hybrid mode` is enabled. Options that should/shouldn't be previewed in `hybrid_modes`. @@ -58,6 +58,7 @@ --- in `hybrid mode`. ---@class markview.config.preview.raw --- +---@field comment? markview.config.preview.raw.comment[] ---@field html? markview.config.preview.raw.html[] ---@field latex? markview.config.preview.raw.latex[] ---@field markdown? markview.config.preview.raw.markdown[] @@ -65,6 +66,27 @@ ---@field typst? markview.config.preview.raw.typst[] ---@field yaml? markview.config.preview.raw.yaml[] +---@alias markview.config.preview.raw.comment +---| "!autolinks" +---| "!code_blocks" +---| "!inline_codes" +---| "!issues" +---| "!mentions" +---| "!taglinks" +---| "!task_scopes" +---| "!tasks" +---| "!urls" +--- +---| "autolinks" +---| "code_blocks" +---| "inline_codes" +---| "issues" +---| "mentions" +---| "taglinks" +---| "task_scopes" +---| "tasks" +---| "urls" + ---@alias markview.config.preview.raw.html ---| "!container_elements" ---| "!headings" diff --git a/lua/markview/types/renderers/comment.lua b/lua/markview/types/renderers/comment.lua new file mode 100644 index 0000000..53afc21 --- /dev/null +++ b/lua/markview/types/renderers/comment.lua @@ -0,0 +1,226 @@ +---@meta + +------------------------------------------------------------------------------ + +--[[ Configuration for `comments`. ]] +---@class markview.config.comment +--- +---@field enable boolean Enable **comment** rendering. +--- +---@field autolinks markview.config.comment.autolinks +---@field code_blocks markview.config.comment.code_blocks +---@field inline_codes markview.config.comment.inline_codes +---@field issues markview.config.comment.issues +---@field mentions markview.config.comment.mentions +---@field taglinks markview.config.comment.taglinks +---@field tasks markview.config.comment.tasks +---@field task_scopes markview.config.comment.task_scopes +---@field urls markview.config.comment.urls + +------------------------------------------------------------------------------ + +---@class markview.config.comment.tasks +--- +---@field enable boolean +--- +---@field default markview.config.comment.tasks.opts +---@field [string] markview.config.comment.tasks.opts + + +---@class markview.config.comment.tasks.opts markview.config.__inline +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +---@field desc_hl? string Highlight group for the `description`. +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. + +------------------------------------------------------------------------------ + +---@alias markview.config.comment.inline_codes markview.config.__inline + +------------------------------------------------------------------------------ + +--- Configuration for code blocks. +---@alias markview.config.comment.code_blocks +---| markview.config.comment.code_blocks.simple +---| markview.config.comment.code_blocks.block + + +---@class markview.config.comment.code_blocks.simple +--- +---@field enable boolean Enable rendering of code blocks. +--- +---@field border_hl? string Highlight group for borders. +---@field info_hl? string Highlight group for the info string. +--- +---@field label_direction? "left" | "right" Position of the language & icon. +---@field label_hl? string Highlight group for the label. +--- +---@field sign? boolean Enables signs for the code block? +---@field sign_hl? string Highlight group for the sign. +--- +---@field style "simple" Only highlights the line. Enabled when `wrap` is enabled. +--- +---@field default markview.config.comment.code_blocks.opts +---@field [string] markview.config.comment.code_blocks.opts + + +---@class markview.config.comment.code_blocks.block +--- +---@field enable boolean Enable rendering of code blocks. +--- +---@field border_hl? string Highlight group for borders. +---@field info_hl? string Highlight group for the info string. +--- +---@field label_direction? "left" | "right" Position of the language & icon. +---@field label_hl? string Highlight group for the label. +--- +---@field min_width? integer Minimum width of the code block. +---@field pad_amount? integer Number of `pad_char`s to add on the left & right side of the code block. +---@field pad_char? string Character used as padding. +--- +---@field sign? boolean Enables signs for the code block? +---@field sign_hl? string Highlight group for the sign. +--- +---@field style "block" Creates a block around the code block. Disabled when `wrap` is enabled. +--- +---@field default markview.config.comment.code_blocks.opts +---@field [string] markview.config.comment.code_blocks.opts + + +--[[ Configuration for highlighting `lines` inside a code block. ]] +---@class markview.config.comment.code_blocks.opts +--- +---@field block_hl +---| string Highlight group for the background of the line. +---| fun(buffer: integer, line: string): string? Takes `line` & the `buffer` containing it and returns a highlight group for the line. +---@field pad_hl +---| string Highlight group for the padding of the line. +---| fun(buffer: integer, line: string): string? Takes `line` & the `buffer` containing it and returns a highlight group for the padding.. + +------------------------------------------------------------------------------ + +--- Configuration for issues. +---@class markview.config.comment.issues +--- +---@field enable boolean Enable rendering of `#issue`s. +--- +---@field default markview.config.__inline Default configuration for issues. +---@field [string] markview.config.__inline Configuration for issues whose text matches with the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for mentions. +---@class markview.config.comment.mentions +--- +---@field enable boolean Enable rendering of `@mention`s. +--- +---@field default markview.config.__inline Default configuration for mentions. +---@field [string] markview.config.__inline Configuration for mentions whose text matches with the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for task_scopes. +---@class markview.config.comment.task_scopes +--- +---@field enable boolean Enable rendering of `task scope`s. +--- +---@field default markview.config.__inline Default configuration for mentions. +---@field [string] markview.config.__inline Configuration for scopes matching the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for URLs. +---@class markview.config.comment.urls +--- +---@field enable boolean Enable rendering of `URL`s. +--- +---@field default markview.config.comments.urls.opts Default configuration for URLs. +---@field [string] markview.config.comments.urls.opts Configuration for URLs whose text matches with the key's pattern. + + +---@class markview.config.comments.urls.opts +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +--[[ Text to show instead of the `autolink`.]] +---@field text? +---| string +---| function(buffer: integer, item: markview.parsed.comment.autolinks): string +---@field text_hl? string Highlight group for the shown text. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. + + +------------------------------------------------------------------------------ + +--- Configuration for taglinks. +---@class markview.config.comment.taglinks +--- +---@field enable boolean Enable rendering of `|taglink|`s. +--- +---@field default markview.config.__inline Default configuration. +---@field [string] markview.config.__inline Configuration for taglinks matching the key's pattern. + +------------------------------------------------------------------------------ + +--- Configuration for autolinks. +---@class markview.config.comment.autolinks +--- +---@field enable boolean Enable rendering of ``s. +--- +---@field default markview.config.comments.autolinks.opts Default configuration. +---@field [string] markview.config.comments.autolinks.opts Configuration for autolinks matching the key's pattern. + + +---@class markview.config.comments.autolinks.opts +--- +---@field corner_left? string Left corner. +---@field corner_left_hl? string Highlight group for the left corner. +--- +---@field padding_left? string Left padding(added after `corner_left`). +---@field padding_left_hl? string Highlight group for the left padding. +--- +---@field icon? string Icon(added after `padding_left`). +---@field icon_hl? string Highlight group for the icon. +--- +--[[ Text to show instead of the `autolink`.]] +---@field text? +---| string +---| function(buffer: integer, item: markview.parsed.comment.autolinks): string +---@field text_hl? string Highlight group for the shown text. +--- +---@field hl? string Default highlight group(used by `*_hl` options when they are not set). +--- +---@field padding_right? string Right padding. +---@field padding_right_hl? string Highlight group for the right padding. +--- +---@field corner_right? string Right corner(added after `padding_right`). +---@field corner_right_hl? string Highlight group for the right corner. + diff --git a/lua/markview/utils.lua b/lua/markview/utils.lua index 2acd916..50f5a65 100644 --- a/lua/markview/utils.lua +++ b/lua/markview/utils.lua @@ -287,11 +287,20 @@ utils.create_user_command_class = function (config) return class; end +---@class markview.utils.match.opts +--- +---@field case_insensitive? boolean +---@field def_fallback? any +---@field default? boolean +---@field eval_args any[] +---@field ignore_keys? any[] +---@field key_mod? string + --- Gets a config from a list of config tables. --- NOTE, {name} will be used to index the config. ---@param config table ---@param name string ----@param opts { key_mod: string?, default: boolean, def_fallback: any?, eval_args: any[], ignore_keys?: any[] } +---@param opts markview.utils.match.opts ---@return any utils.match = function (config, name, opts) config = config or {}; @@ -347,15 +356,22 @@ utils.match = function (config, name, opts) local function is_valid (value, pattern) local ignore = opts.ignore_keys or { "enable" }; + + local _value = value; local _pattern = pattern; if opts.key_mod then _pattern = string.format(opts.key_mod, _pattern); end + if opts.case_insensitive and type(_value) == "string" then + _value = string.lower(_value); + _pattern = string.lower(_pattern); + end + if vim.list_contains(ignore, pattern) then return false; - elseif string.match(value, _pattern) then + elseif string.match(_value, _pattern) then return true; else return false; diff --git a/markview.nvim.wiki b/markview.nvim.wiki index 2f6e9a4..df2d1c2 160000 --- a/markview.nvim.wiki +++ b/markview.nvim.wiki @@ -1 +1 @@ -Subproject commit 2f6e9a41e27163e59fba3513eafd9ec156d13d71 +Subproject commit df2d1c2f2e1820b5e8dd81e5360e3699a0c98581 diff --git a/test/comment.lua b/test/comment.lua new file mode 100644 index 0000000..057def4 --- /dev/null +++ b/test/comment.lua @@ -0,0 +1,32 @@ +--[[ +feat(@OXY2DEV): Tree-sitter parser for `Conventional comments`. + +A `tree-sitter` parser for **conventional comments** that supports a subset of `markdown`. +It can be used as an injected language for other parsers(e.g. for comments). + +The parser currently supports, + + ‱ **Bold** + ‱ *Italic* + ‱ `Code` + ‱ 'Quoted_text' + ‱ "Double quoted text" + ‱ @mentions + ‱ issues/reference#52 + ‱ https://example.com + ‱ |help-section| + +```lua +print("Hello, world!"); +``` + +With support for *common comment topics* such as, + +todo: Some task. +FIXME: Fix some *issues*. + +NOTE(grammar, @OXY2DEV): Add features to grammar. + +Author: @OXY2DEV +]] +local a = 1;