Skip to content
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

fix: wrong ANSI code for moving cursor #29

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[*.lua]
# [basic]

# optional space/tab
indent_style = space
# if indent_style is space, this is valid
indent_size = 4
# if indent_style is tab, this is valid
tab_width = 4
# none/single/double
quote_style = single

continuation_indent = 4

# [operator space]
space_around_math_operator = true

space_around_table_field_list = false

# this mean utf8 length , if this is 'unset' then the line width is no longer checked
# this option decides when to chopdown the code
max_line_length = 120

# optional crlf/lf/cr/auto, if it is 'auto', in windows it is crlf other platforms are lf
# in neovim the value 'auto' is not a valid option, please use 'unset'
end_of_line = lf
30 changes: 15 additions & 15 deletions lua/hologram/base64.lua
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
-- LuaJIT FFI Base64 encoder/decoder
-- LuaJIT FFI Base64 encoder/decoder
-- Copyright (c) 2022 Edward Lufadeju ([email protected])
-- See end of file for license information

local ffi = require('ffi')
local base64 = {}

local b64 = ffi.new('unsigned const char[65]',
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')

function base64.encode(str)
local band, bor, lsh, rsh = bit.band, bit.bor, bit.lshift, bit.rshift
local len = #str
local enc_len = 4 * math.ceil(len / 3) -- (len + 2) // 3 * 4 after Lua 5.3

local src = ffi.new('unsigned const char[?]', len+1, str)
local enc = ffi.new('unsigned char[?]', enc_len+1)
local src = ffi.new('unsigned const char[?]', len + 1, str)
local enc = ffi.new('unsigned char[?]', enc_len + 1)

local i, j = 0, 0
while i < len-2 do
while i < len - 2 do
enc[j] = b64[band(rsh(src[i], 2), 0x3F)]
enc[j+1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i+1], 0xF0), 4))]
enc[j+2] = b64[bor(lsh(band(src[i+1], 0xF), 2), rsh(band(src[i+2], 0xC0), 6))]
enc[j+3] = b64[band(src[i+2], 0x3F)]
i, j = i+3, j+4
enc[j + 1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i + 1], 0xF0), 4))]
enc[j + 2] = b64[bor(lsh(band(src[i + 1], 0xF), 2), rsh(band(src[i + 2], 0xC0), 6))]
enc[j + 3] = b64[band(src[i + 2], 0x3F)]
i, j = i + 3, j + 4
end

if i < len then
enc[j] = b64[band(rsh(src[i], 2), 0x3F)]
if i == len-1 then
enc[j+1] = b64[lsh(band(src[i], 0x3), 4)]
enc[j+2] = 0x3D
if i == len - 1 then
enc[j + 1] = b64[lsh(band(src[i], 0x3), 4)]
enc[j + 2] = 0x3D
else
enc[j+1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i+1], 0xF0), 4))]
enc[j+2] = b64[lsh(band(src[i+1], 0xF), 2)]
enc[j + 1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i + 1], 0xF0), 4))]
enc[j + 2] = b64[lsh(band(src[i + 1], 0xF), 2)]
end
enc[j+3] = 0x3D
enc[j + 3] = 0x3D
end

return ffi.string(enc, enc_len)
Expand Down
27 changes: 16 additions & 11 deletions lua/hologram/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,50 @@ local ffi = require('ffi')
local base64 = require('hologram.base64')
local fs = {}

---@param path string
---@return integer
---@return integer
function fs.get_dims_PNG(path)
local fd = assert(vim.loop.fs_open(path, 'r', 438))
local buf = ffi.new('const unsigned char[?]', 25,
assert(vim.loop.fs_read(fd, 24, 0)))
assert(vim.loop.fs_close(fd))

local width = fs.bytes2int(buf+16)
local height = fs.bytes2int(buf+20)
local width = fs.bytes2int(buf + 16)
local height = fs.bytes2int(buf + 20)
return width, height
end

---@param path string
---@return boolean? # returns nil on error
function fs.check_sig_PNG(path)
local fd = vim.loop.fs_open(path, 'r', 438)
if fd == nil then return end

local sig = ffi.new('const unsigned char[?]', 9,
assert(vim.loop.fs_read(fd, 8, 0)))

return sig[0]==137 and sig[1]==80
and sig[2]==78 and sig[3]==71
and sig[4]==13 and sig[5]==10
and sig[6]==26 and sig[7]==10
return sig[0] == 137 and sig[1] == 80
and sig[2] == 78 and sig[3] == 71
and sig[4] == 13 and sig[5] == 10
and sig[6] == 26 and sig[7] == 10
end

function fs.get_chunked(buf)
local len = ffi.sizeof(buf)
local i, j, chunks = 0, 0, {}
while i < len-4096 do
chunks[j] = ffi.string(buf+i, 4096)
i, j = i+4096, j+1
while i < len - 4096 do
chunks[j] = ffi.string(buf + i, 4096)
i, j = i + 4096, j + 1
end
chunks[j] = ffi.string(buf+i)
chunks[j] = ffi.string(buf + i)
return chunks
end

-- big endian
function fs.bytes2int(bufp)
local bor, lsh = bit.bor, bit.lshift
return bor(lsh(bufp[0],24), lsh(bufp[1],16), lsh(bufp[2],8), bufp[3])
return bor(lsh(bufp[0], 24), lsh(bufp[1], 16), lsh(bufp[2], 8), bufp[3])
end

return fs
74 changes: 58 additions & 16 deletions lua/hologram/image.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ local Image = {
}
Image.__index = Image

-- TODO: proper type definition
---@alias TransmissionType string

---@class NewImageArgs
---@field format integer
---@field transmission_type TransmissionType
---@field data_width integer
---@field data_height integer
---@field data_size integer?
---@field data_offset integer?
---@field image_number integer?
---@field compressed integer?
---@field image_id integer?
---@field placement_id integer?

---@param source string
---@param keys NewImageArgs
---@return unknown
function Image:new(source, keys)
keys = keys or {}
keys = vim.tbl_extend('keep', keys, {
Expand All @@ -35,8 +53,8 @@ function Image:new(source, keys)
keys.data_width, keys.data_height = fs.get_dims_PNG(source)
end
end
local cols = math.ceil(keys.data_width/state.cell_size.x)
local rows = math.ceil(keys.data_height/state.cell_size.y)
local cols = math.ceil(keys.data_width / state.cell_size.x)
local rows = math.ceil(keys.data_height / state.cell_size.y)

keys.action = 't'
keys.quiet = 2
Expand All @@ -54,6 +72,23 @@ function Image:new(source, keys)
return Image.instances[keys.image_id]
end

---@class DisplayArgs
---@field x_offset integer?
---@field y_offset integer?
---@field width integer?
---@field height integer?
---@field cell_x integer?
---@field cell_y integer?
---@field cols integer?
---@field rows integer?
---@field z_index integer?
---@field placement_id integer?

---@param row integer
---@param col integer
---@param buf integer buffer number
---@param keys DisplayArgs
---@return boolean
function Image:display(row, col, buf, keys)
keys = keys or {}
keys = vim.tbl_extend('keep', keys, {
Expand Down Expand Up @@ -86,9 +121,9 @@ function Image:display(row, col, buf, keys)
local y_offset = 0

-- resize
local winwidth = (info.width-info.textoff)
local winwidth = (info.width - info.textoff)
if cols > winwidth then
rows = winwidth * (rows/cols)
rows = winwidth * (rows / cols)
cols = winwidth
end
local row_factor = self.rows / rows
Expand All @@ -97,23 +132,23 @@ function Image:display(row, col, buf, keys)
self:set_vpad(buf, row, info.width, math.ceil(rows))

-- check if visible
if row < info.topline-1 or row > info.botline then
if row < info.topline - 1 or row > info.botline then
return false
end

-- image is cut off top
if row == info.topline-1 then
if row == info.topline - 1 then
local topfill = vim.fn.winsaveview().topfill
local cutoff_rows = math.max(0, rows-topfill)
local cutoff_rows = math.max(0, rows - topfill)
y_offset = cutoff_rows * row_factor * cs.y
rows = topfill
end

-- image is cut off bottom
if row == info.botline then
local screen_row = utils.buf_screenpos(row, 0, win, buf)
local screen_winbot = info.winrow+info.height
local visible_rows = screen_winbot-screen_row
local screen_winbot = info.winrow + info.height
local visible_rows = screen_winbot - screen_row
if visible_rows > 0 then
rows = visible_rows
height = visible_rows * row_factor * cs.y
Expand Down Expand Up @@ -151,6 +186,8 @@ function Image:display(row, col, buf, keys)
return true
end

---@param buf integer buffer number
---@param opts {free: boolean?}
function Image:delete(buf, opts)
opts = opts or {}
opts = vim.tbl_extend('keep', opts, {
Expand All @@ -171,29 +208,34 @@ function Image:delete(buf, opts)
end
end

---@param buf integer buffer number
---@param row integer
---@param cols integer
---@param rows integer
function Image:set_vpad(buf, row, cols, rows)
if self.vpad ~= nil and
self.vpad.row == row and
self.vpad.cols == cols and
if self.vpad ~= nil and
self.vpad.row == row and
self.vpad.cols == cols and
self.vpad.rows == rows then
return
end

local text = string.rep(' ', cols)
local filler = {}
for i=0,rows-1 do
filler[#filler+1] = {{text, ''}}
for _ = 0, rows - 1 do
filler[#filler + 1] = {{text, ''}}
end

vim.api.nvim_buf_set_extmark(buf, vim.g.hologram_extmark_ns, row-1, 0, {
vim.api.nvim_buf_set_extmark(buf, vim.g.hologram_extmark_ns, row - 1, 0, {
id = self.transmit_keys.image_id,
virt_lines = filler,
--virt_lines_leftcol = true,
})

self.vpad = {row=row, cols=cols, rows=rows}
self.vpad = {row = row, cols = cols, rows = rows}
end

---@param buf integer buffer number
function Image:remove_vpad(buf)
if self.vpad ~= nil then
vim.api.nvim_buf_del_extmark(buf, vim.g.hologram_extmark_ns, self.transmit_keys.image_id)
Expand Down
Loading