Skip to content

feat: add only_render_image_at_cursor_mode #208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ require("image").setup({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline", -- "inline" or "popup"
filetypes = { "markdown", "vimwiki" }, -- markdown extensions (ie. quarto) can go here
},
neorg = {
Expand Down
17 changes: 5 additions & 12 deletions lua/image/integrations/css.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@ return document.create_document_integration({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline",
filetypes = { "css", "sass", "scss" },
},
query_buffer_images = function(buffer)
local buf = buffer or vim.api.nvim_get_current_buf()

local parser = vim.treesitter.get_parser(buf, "css")
local root = parser:parse()[1]:root()
local query = vim.treesitter.query.parse(
"css",
'(call_expression (function_name) @name (#eq? @name "url"))'
)
local query = vim.treesitter.query.parse("css", '(call_expression (function_name) @name (#eq? @name "url"))')

local images = {}

Expand All @@ -27,17 +25,12 @@ return document.create_document_integration({
if capture == "name" then
---@diagnostic disable-next-line: unused-local
local start_row, start_col, end_row, end_col = node:range()
local line = vim.api.nvim_buf_get_lines(
buf,
end_row,
end_row + 1,
false
)[1]
local line = vim.api.nvim_buf_get_lines(buf, end_row, end_row + 1, false)[1]

local path = line:sub(start_col):gsub(".*url%([\"'](.-)[\"']%).*$", "%1")

-- search for path relative to webroot
if path:sub(1,1) == "/" then
if path:sub(1, 1) == "/" then
path = vim.fs.find(path:sub(2), {
upward = true,
path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
Expand All @@ -60,5 +53,5 @@ return document.create_document_integration({
end

return images
end
end,
})
15 changes: 5 additions & 10 deletions lua/image/integrations/html.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ return document.create_document_integration({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline",
filetypes = { "html", "xhtml", "htm" },
},
query_buffer_images = function(buffer)
Expand All @@ -15,8 +16,7 @@ return document.create_document_integration({
local root = parser:parse()[1]:root()
local query = vim.treesitter.query.parse(
"html",
'(attribute (attribute_name) @name (#eq? @name "src")'
.. ' (quoted_attribute_value))'
'(attribute (attribute_name) @name (#eq? @name "src")' .. " (quoted_attribute_value))"
)

local images = {}
Expand All @@ -28,17 +28,12 @@ return document.create_document_integration({
if capture == "name" then
---@diagnostic disable-next-line: unused-local
local start_row, start_col, end_row, end_col = node:range()
local line = vim.api.nvim_buf_get_lines(
buf,
end_row,
end_row + 1,
false
)[1]
local line = vim.api.nvim_buf_get_lines(buf, end_row, end_row + 1, false)[1]

local path = line:sub(start_col):gsub(".*src=[\"'](.-)[\"'].*$", "%1")

-- search for path relative to webroot
if path:sub(1,1) == "/" then
if path:sub(1, 1) == "/" then
path = vim.fs.find(path:sub(2), {
upward = true,
path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
Expand All @@ -61,5 +56,5 @@ return document.create_document_integration({
end

return images
end
end,
})
1 change: 1 addition & 0 deletions lua/image/integrations/markdown.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ return document.create_document_integration({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline",
filetypes = { "markdown", "vimwiki" },
},
query_buffer_images = function(buffer)
Expand Down
1 change: 1 addition & 0 deletions lua/image/integrations/neorg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ return document.create_document_integration({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline",
filetypes = { "norg" },
},
query_buffer_images = function(buffer)
Expand Down
1 change: 1 addition & 0 deletions lua/image/integrations/syslang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ return document.create_document_integration({
clear_in_insert_mode = false,
download_remote_images = true,
only_render_image_at_cursor = false,
only_render_image_at_cursor_mode = "inline",
filetypes = { "syslang" },
},
query_buffer_images = function(buffer)
Expand Down
64 changes: 37 additions & 27 deletions lua/image/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,19 @@ local render = function(image)
if utils.offsets.get_border_shape(window.id).left > 0 then bounds.right = bounds.right + 1 end

-- global max window width/height percentage
if type(state.options.max_width_window_percentage) == "number" then
width =
math.min(width, math.floor((window.width - global_offsets.x) * state.options.max_width_window_percentage / 100))
end
if type(state.options.max_height_window_percentage) == "number" then
height = math.min(
height,
math.floor((window.height - global_offsets.y) * state.options.max_height_window_percentage / 100)
)
if not image.ignore_global_max_size then
if type(state.options.max_width_window_percentage) == "number" then
width = math.min(
width,
math.floor((window.width - global_offsets.x) * state.options.max_width_window_percentage / 100)
)
end
if type(state.options.max_height_window_percentage) == "number" then
height = math.min(
height,
math.floor((window.height - global_offsets.y) * state.options.max_height_window_percentage / 100)
)
end
end
end

Expand All @@ -137,8 +141,10 @@ local render = function(image)
-- )

-- global max width/height
if type(state.options.max_width) == "number" then width = math.min(width, state.options.max_width) end
if type(state.options.max_height) == "number" then height = math.min(height, state.options.max_height) end
if not image.ignore_global_max_size then
if type(state.options.max_width) == "number" then width = math.min(width, state.options.max_width) end
if type(state.options.max_height) == "number" then height = math.min(height, state.options.max_height) end
end

width, height = utils.math.adjust_to_aspect_ratio(term_size, image.image_width, image.image_height, width, height)

Expand All @@ -149,9 +155,7 @@ local render = function(image)
local absolute_x = original_x + x_offset + window_offset_x
local absolute_y = original_y + y_offset + window_offset_y

if image.with_virtual_padding then
absolute_y = absolute_y + 1
end
if image.with_virtual_padding then absolute_y = absolute_y + 1 end

local prevent_rendering = false

Expand Down Expand Up @@ -276,7 +280,8 @@ local render = function(image)

local conceallevel = vim.wo[image.window].conceallevel
-- TODO: account for conceal cursor?
local conceal_current_line = vim.api.nvim_win_get_cursor(image.window)[1] ~= original_x and conceallevel > 0
local conceal_current_line = vim.api.nvim_win_get_cursor(image.window)[1] ~= original_x
and conceallevel > 0
if details.conceal and details.end_col and conceal_current_line then
-- remove width b/c this is removing space
for i = extmark[3], details.end_col do
Expand Down Expand Up @@ -320,10 +325,10 @@ local render = function(image)

-- clear out of bounds images
if
absolute_y + height <= bounds.top
or absolute_y >= bounds.bottom + (vim.o.laststatus == 2 and 1 or 0)
or absolute_x + width <= bounds.left
or absolute_x >= bounds.right
absolute_y + height <= bounds.top
or absolute_y >= bounds.bottom + (vim.o.laststatus == 2 and 1 or 0)
or absolute_x + width <= bounds.left
or absolute_x >= bounds.right
then
if image.is_rendered then
-- utils.debug("deleting out of bounds image", { id = image.id, x = absolute_x, y = absolute_y, width = width, height = height, bounds = bounds })
Expand Down Expand Up @@ -389,7 +394,12 @@ local render = function(image)
resized_image:set_format("png")
resized_image:scale(pixel_width, pixel_height)

local tmp_path = state.tmp_dir .. "/" .. utils.base64.encode(image.id) .. "-resized-" .. resize_hash .. ".png"
local tmp_path = state.tmp_dir
.. "/"
.. utils.base64.encode(image.id)
.. "-resized-"
.. resize_hash
.. ".png"
resized_image:write(tmp_path)
resized_image:destroy()

Expand Down Expand Up @@ -444,13 +454,13 @@ local render = function(image)
end

if
image.is_rendered
and image.rendered_geometry.x == rendered_geometry.x
and image.rendered_geometry.y == rendered_geometry.y
and image.rendered_geometry.width == rendered_geometry.width
and image.rendered_geometry.height == rendered_geometry.height
and image.crop_hash == initial_crop_hash
and image.resize_hash == initial_resize_hash
image.is_rendered
and image.rendered_geometry.x == rendered_geometry.x
and image.rendered_geometry.y == rendered_geometry.y
and image.rendered_geometry.width == rendered_geometry.width
and image.rendered_geometry.height == rendered_geometry.height
and image.crop_hash == initial_crop_hash
and image.resize_hash == initial_resize_hash
then
-- utils.debug("skipping render", image.id)
return true
Expand Down
57 changes: 53 additions & 4 deletions lua/image/utils/document.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ local create_document_integration = function(config)
if config.debug then utils.log("[" .. config.name .. "]", ...) end
end

local popup_window = nil

local render = vim.schedule_wrap(
---@param ctx IntegrationContext
function(ctx)
Expand Down Expand Up @@ -85,10 +87,57 @@ local create_document_integration = function(config)
-- render images from queue
for _, item in ipairs(image_queue) do
local render_image = function(image)
image:render({
x = item.match.range.start_col,
y = item.match.range.start_row,
})
if ctx.options.only_render_image_at_cursor and ctx.options.only_render_image_at_cursor_mode == "popup" then
if popup_window ~= nil then return end

-- Create a floating window for the image
local term_size = utils.term.get_size()
local width, height = utils.math.adjust_to_aspect_ratio(
term_size,
image.image_width,
image.image_height,
term_size.screen_cols / 2,
0
)
local win_config = {
relative = "cursor",
row = 1,
col = 0,
width = width,
height = height,
style = "minimal",
border = "single",
}
local buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].filetype = "image_nvim_popup"
local win = vim.api.nvim_open_win(buf, false, win_config)
popup_window = win

image.ignore_global_max_size = true
image.window = win
image.buffer = buf
image:render({
x = 0,
y = 1,
width = width,
height = height,
})

-- Close the floating window when the cursor moves
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
callback = function()
if vim.api.nvim_win_is_valid(win) then vim.api.nvim_win_close(win, true) end
image:clear()
popup_window = nil
end,
once = true,
})
else
image:render({
x = item.match.range.start_col,
y = item.match.range.start_row,
})
end
end

if is_remote_url(item.match.url) then
Expand Down
2 changes: 2 additions & 0 deletions lua/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
---@field download_remote_images? boolean
---@field clear_in_insert_mode? boolean
---@field only_render_image_at_cursor? boolean
---@field only_render_image_at_cursor_mode? "inline"|"popup"
---@field filetypes? string[]
---@field resolve_image_path? function

Expand Down Expand Up @@ -116,6 +117,7 @@
---@field hue fun(self: Image, hue: number)
---@field namespace? string
---@field extmark? { id: number, row: number, col: number }
---@field ignore_global_max_size? boolean

-- wish proper generics were a thing here
---@class IntegrationContext
Expand Down
Loading