From 2ad8324092007b51420d8d4e178210c8b1931509 Mon Sep 17 00:00:00 2001 From: Chip Senkbeil Date: Sat, 30 Nov 2024 14:50:08 -0600 Subject: [PATCH] feat(img): add `for_each_chunk` to `vim.image.Image` class Add `for_each_chunk()` for instances of `vim.img.Image`. This method streamlines chunked iteration of image bytes, which is important when working with ssh or tmux and a protocol that supports chunked image rendering such as `iterm2` or `kitty`. --- runtime/lua/vim/img/_image.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/runtime/lua/vim/img/_image.lua b/runtime/lua/vim/img/_image.lua index 30df1b4a71..c8520c639d 100644 --- a/runtime/lua/vim/img/_image.lua +++ b/runtime/lua/vim/img/_image.lua @@ -33,6 +33,37 @@ function M:size() return string.len(self.data or '') end +---Iterates over the chunks of the image, invoking `f` per chunk. +---@param f fun(chunk:string, pos:integer, has_more:boolean) +---@param opts? {size?:integer} +function M:for_each_chunk(f, opts) + opts = opts or {} + + -- Chunk size, defaulting to 4k + local chunk_size = opts.size or 4096 + + local data = self.data + if not data then + return + end + + local pos = 1 + local len = string.len(data) + while pos <= len do + -- Get our next chunk from [pos, pos + chunk_size) + local end_pos = pos + chunk_size - 1 + local chunk = data:sub(pos, end_pos) + + -- If we have a chunk available, invoke our callback + if string.len(chunk) > 0 then + local has_more = end_pos + 1 <= len + pcall(f, chunk, pos, has_more) + end + + pos = end_pos + 1 + end +end + ---Displays the image within the terminal used by neovim. ---@param opts? vim.img.Opts function M:show(opts)