Skip to content

Commit

Permalink
fix: fix non displayed diagnostic when in last line, fix arrow highlight
Browse files Browse the repository at this point in the history
  • Loading branch information
rachartier committed Jul 13, 2024
1 parent abe21bf commit 06d4249
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 255 deletions.
218 changes: 218 additions & 0 deletions lua/tiny-inline-diagnostic/chunck.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
local M = {}

local extmarks = require('tiny-inline-diagnostic.extmarks')
local utils = require('tiny-inline-diagnostic.utils')


--- Function to calculates the maximum width from a list of chunks.
--- @param chunks table: A table representing the chunks of a diagnostic message.
--- @return number: The maximum width among all chunks.
function M.get_max_width_from_chunks(chunks)
local max_chunk_line_length = 0

for i = 1, #chunks do
if #chunks[i] > max_chunk_line_length then
max_chunk_line_length = #chunks[i]
end
end

return max_chunk_line_length
end

--- Function to generates a header for a diagnostic message chunk.
--- @param message string: The diagnostic message.
--- @param num_chunks number: The total number of chunks the message is split into.
--- @param opts table: The options table, which includes signs for the diagnostic message.
--- @param diag_hi string: The highlight group for the diagnostic message.
--- @param diag_inv_hi string: The highlight group for the diagnostic signs.
--- @return table: A table representing the virtual text array for the diagnostic message header.
function M.get_header_from_chunk(
message,
index_diag,
num_chunks,
need_to_be_under,
opts,
diag_hi,
diag_inv_hi
)
local virt_texts = {}

virt_texts = {
{ opts.signs.left, diag_inv_hi },
{ opts.signs.diag, diag_hi }
}

if not need_to_be_under and index_diag > 1 then
table.insert(virt_texts, 1, { string.rep(" ", #opts.signs.arrow - 2), diag_inv_hi })
end

-- if need_to_be_under then
-- virt_texts = {
-- { string.rep(" ", #opts.signs.arrow - 1) .. " ", diag_inv_hi },
-- { opts.signs.diag, diag_hi },
-- }
-- end

local text_after_message = " "

if num_chunks == 1 then
vim.list_extend(virt_texts, {
{ " " .. message .. " ", diag_hi },
{ opts.signs.right, diag_inv_hi },
})
else
vim.list_extend(virt_texts, {
{ " " .. message .. text_after_message, diag_hi },
{ string.rep(" ", #opts.signs.right), diag_inv_hi },
})
end

return virt_texts
end

--- Function to generates the body for a diagnostic message chunk.
--- @param chunk string: The chunk of the diagnostic message.
--- @param opts table: The options table, which includes signs for the diagnostic message.
--- @param need_to_be_under boolean: A flag indicating whether the arrow needs to point upwards.
--- @param diag_hi string: The highlight group for the diagnostic message.
--- @param diag_inv_hi string: The highlight group for the diagnostic signs.
--- @param is_last boolean: A flag indicating whether the chunk is the last one.
--- @return table: A table representing the virtual text array for the diagnostic message body.
function M.get_body_from_chunk(
chunk,
opts,
need_to_be_under,
diag_hi,
diag_inv_hi,
is_last
)
local vertical_sign = opts.signs.vertical

if is_last then
vertical_sign = opts.signs.vertical_end
end

local chunk_virtual_texts = {
{ vertical_sign, diag_hi },
{ " " .. chunk, diag_hi },
{ " ", diag_hi },
}

if not need_to_be_under then
table.insert(chunk_virtual_texts, 1, { string.rep(" ", #opts.signs.arrow - 1), diag_inv_hi })
else
table.insert(chunk_virtual_texts, 1, { " ", diag_inv_hi })
end

if is_last then
vim.list_extend(chunk_virtual_texts, {
{ opts.signs.right, diag_inv_hi },
})
end

return chunk_virtual_texts
end

function M.get_arrow_from_chunk(
offset,
cursorpos,
opts,
need_to_be_under
)
local arrow = opts.signs.arrow
local chunck = {}

if need_to_be_under then
arrow = opts.signs.up_arrow
chunck = {
{ " ", "None" },
{ arrow, "TinyInlineDiagnosticVirtualTextArrow" },
}
else
chunck = { arrow, "TinyInlineDiagnosticVirtualTextArrow" }
end

return chunck
end

--- Function to splits a diagnostic message into chunks for overflow handling.
--- @param message string: The diagnostic message.
--- @param offset number: The offset from the start of the line to the diagnostic position.
--- @param need_to_be_under boolean: A flag indicating whether the diagnostic message needs to be displayed under the line.
--- @param line_length number: The length of the line where the diagnostic message is.
--- @param win_width number: The width of the window where the diagnostic message is displayed.
--- @param opts table: The options table, which includes signs for the diagnostic message and the softwrap option.
--- @return table, boolean: A table representing the chunks of the diagnostic message, and a boolean indicating whether the message needs to be displayed under the line.
function M.get_message_chunks_for_overflow(
message,
offset,
need_to_be_under,
win_width,
opts
)
local signs_total_text_len = #opts.signs.arrow + #opts.signs.right + #opts.signs.left + #opts.signs.diag + 4

local distance = win_width - offset - signs_total_text_len

if distance < opts.options.softwrap then
need_to_be_under = true
distance = win_width - signs_total_text_len
end

local message_chunk = {}
message_chunk = utils.wrap_text(message, distance)

return message_chunk, need_to_be_under
end

function M.get_chunks(opts, diag, plugin_offset, curline, buf)
local win_width = vim.api.nvim_win_get_width(0)
local line_length = #vim.api.nvim_get_current_line()
local offset = 0
local need_to_be_under = false
local win_option_wrap_enabled = vim.api.nvim_get_option_value("wrap", { win = 0 })

local chunks = { diag.message }

local other_extmarks_offset = extmarks.handle_other_extmarks(
opts,
buf,
curline,
line_length
)

if win_option_wrap_enabled then
if line_length > win_width - opts.options.softwrap then
need_to_be_under = true
end
end

if opts.options.break_line.enabled == true then
chunks = {}
chunks = utils.wrap_text(diag.message, opts.options.break_line.after)
elseif opts.options.overflow.mode == "wrap" then
if need_to_be_under then
offset = 0
else
offset = line_length
end

chunks, need_to_be_under = M.get_message_chunks_for_overflow(
diag.message,
offset + plugin_offset + other_extmarks_offset,
need_to_be_under,
win_width, opts
)
elseif opts.options.overflow.position == "none" then
chunks = { " " .. diag.message }
end


return chunks, {
offset = offset,
offset_win_col = other_extmarks_offset + plugin_offset,
need_to_be_under = need_to_be_under
}
end

return M
Loading

0 comments on commit 06d4249

Please sign in to comment.