From f67f18d949e9f3fef5a2c9c5d21e176d74a7acc8 Mon Sep 17 00:00:00 2001 From: Kristijan Husak Date: Tue, 18 Feb 2025 14:02:33 +0100 Subject: [PATCH] feat(images): add support for image previewing with Snacks --- lua/orgmode/colors/highlighter/init.lua | 1 - .../colors/highlighter/markup/init.lua | 8 +++ .../colors/highlighter/markup/link.lua | 52 +++++++++++++++++-- queries/org/images.scm | 1 + 4 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 queries/org/images.scm diff --git a/lua/orgmode/colors/highlighter/init.lua b/lua/orgmode/colors/highlighter/init.lua index 3ab76aa1b..fada6970a 100644 --- a/lua/orgmode/colors/highlighter/init.lua +++ b/lua/orgmode/colors/highlighter/init.lua @@ -7,7 +7,6 @@ ---@field private _ephemeral boolean ---@field private buffers table local OrgHighlighter = {} -local config = require('orgmode.config') function OrgHighlighter:new() local data = { diff --git a/lua/orgmode/colors/highlighter/markup/init.lua b/lua/orgmode/colors/highlighter/markup/init.lua index 7ff23e960..7d8273113 100644 --- a/lua/orgmode/colors/highlighter/markup/init.lua +++ b/lua/orgmode/colors/highlighter/markup/init.lua @@ -260,4 +260,12 @@ function OrgMarkup:use_ephemeral() return self.highlighter._ephemeral end +function OrgMarkup:get_links_for_line(bufnr, line) + local cache = self.cache[bufnr] + if not cache or not cache[line] then + return + end + return cache[line].highlights.link +end + return OrgMarkup diff --git a/lua/orgmode/colors/highlighter/markup/link.lua b/lua/orgmode/colors/highlighter/markup/link.lua index 05ee5ccb7..37a7ea294 100644 --- a/lua/orgmode/colors/highlighter/markup/link.lua +++ b/lua/orgmode/colors/highlighter/markup/link.lua @@ -8,16 +8,57 @@ local OrgLink = { ['link.end'] = true, }, } +OrgLink.__index = OrgLink ---@param opts { markup: OrgMarkupHighlighter } function OrgLink:new(opts) - local data = { + local this = setmetatable({ markup = opts.markup, has_extmark_url_support = vim.fn.has('nvim-0.10.2') == 1, - } - setmetatable(data, self) - self.__index = self - return data + }, OrgLink) + this:_set_directive() + return this +end + +---@private +function OrgLink:_set_directive() + ---@diagnostic disable-next-line: undefined-field + if not _G.Snacks then + return + end + + vim.treesitter.query.add_directive('org-set-link!', function(match, _, source, pred, metadata) + ---@type TSNode + local capture_id = pred[2] + local node = match[capture_id] + + if not node or not self.has_extmark_url_support then + metadata['image.ignore'] = true + return + end + + local start_row, start_col = node:range() + local line_cache = self.markup:get_links_for_line(source, start_row) + if not line_cache or #line_cache == 0 then + metadata['image.ignore'] = true + return + end + local entry_for_node = vim.tbl_filter(function(item) + return item.url and item.from.start_col == start_col and item.metadata.type == 'link_end' + end, line_cache)[1] + + if not entry_for_node then + metadata['image.ignore'] = true + return + end + + local url = entry_for_node.url + local prefix = url:sub(1, 5) + if prefix == 'file:' then + url = url:sub(6) + end + metadata['image.src'] = url + end, { force = true, all = false }) end ---@param node TSNode @@ -229,6 +270,7 @@ function OrgLink:highlight(highlights, bufnr) conceal = '', }) end + entry.url = link_opts.url -- Conceal the end marker (marked with << and >>) -- [[https://neovim.io][Neovim<<]]>> vim.api.nvim_buf_set_extmark(bufnr, namespace, entry.from.line, entry.to.end_col - 2, { diff --git a/queries/org/images.scm b/queries/org/images.scm new file mode 100644 index 000000000..2930eb7cf --- /dev/null +++ b/queries/org/images.scm @@ -0,0 +1 @@ +((expr "[") @image (#org-set-link! @image))