-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Hello!
I'd like to propose an enhancement: rendering single-line LaTeX equations
directly inline, rather than using virtual lines above the text. While the
current virtual line approach is functional, it often consumes significant
vertical space and can be distracting, especially for short equations.
My suggestion is to integrate these equations directly into the text flow,
which would significantly improve readability and document compactness.
Here are visual examples demonstrating the difference:
Before:

After:

I've implemented a prototype to demonstrate this idea and serve as a starting
point:
---@param root TSNode
---@return render.md.Mark[]
function Handler:run(root)
if self.context:skip(self.config) then
return {}
end
if vim.fn.executable(self.config.converter) ~= 1 then
log.add('debug', 'ConverterNotFound', self.config.converter)
return {}
end
local node = Node.new(self.context.buf, root)
log.node('latex', node)
local indent = self:indent(node.start_row, node.start_col)
local lines = iter.list.map(self:expressions(node), function(expression)
local line = vim.list_extend({}, indent) ---@type render.md.mark.Line
line[#line + 1] = { expression, self.config.highlight }
return line
end)
local marks = Marks.new(self.context, true)
if #lines == 1 then
marks:add(true, node.start_row, node.start_col, {
end_row = node.end_row,
end_col = node.end_col,
virt_text = lines[1],
virt_text_pos = 'inline',
conceal = '',
})
return marks:get()
end
local above = self.config.position == 'above'
local row = above and node.start_row or node.end_row
marks:add('virtual_lines', row, 0, {
virt_lines = lines,
virt_lines_above = above,
})
return marks:get()
end
---@private
---@param node render.md.Node
---@return string[]
function Handler:expressions(node)
local lines = str.split(self:convert(node.text), '\n', true)
if #lines == 1 then
return lines
end
local col = node.start_col
local _, first = node:line('first', 0)
local prefix = str.pad(first and str.width(first:sub(1, col)) or col)
local width = vim.fn.max(iter.list.map(lines, str.width))
local result = {} ---@type string[]
for _ = 1, self.config.top_pad do
result[#result + 1] = ''
end
for _, line in ipairs(lines) do
local suffix = str.pad(width - str.width(line))
result[#result + 1] = prefix .. line .. suffix
end
for _ = 1, self.config.bottom_pad do
result[#result + 1] = ''
end
return result
end
Further Observations and Challenges (regarding multi-line equations):
I also explored applying a similar inline approach to multi-line LaTeX
equations but encountered several challenges:
- Challenge: Detecting End of File/Last Formula: While the line break logic
(if cur_start_row ~= node.start_row
) worked, I couldn't find a reliable
mechanism to detect the very last formula in a file. The absence of a clear
end-of-file indicator (e.g.,nil
) or a subscribable event prevented me from
correctly rendering the final group of equations. - Usability for Multi-line Equations: Furthermore, for multi-line
equations, strict inline rendering isn't always ideal. Ideally, it would be
great to have full rendering visible during editing (e.g., displaying the
equation as a virtual line when the cursor hovers over it). However, I
haven't found a simple and performant solution for such interactive
rendering.
I'd appreciate your thoughts on this proposal and any insights or suggestions
regarding the multi-line challenges, especially detecting the end of a formula
block or file.
P.S. I used AI to help formulate this issue, aiming for maximum clarity and
precision, as my English proficiency sometimes hinders expressing nuanced
ideas. I hope this is acceptable.