Skip to content

Commit

Permalink
fix: Improved LaTex renderer
Browse files Browse the repository at this point in the history
Ref: #177
  • Loading branch information
OXY2DEV committed Nov 3, 2024
1 parent 8885d5f commit 2f6faac
Show file tree
Hide file tree
Showing 2 changed files with 786 additions and 29 deletions.
200 changes: 184 additions & 16 deletions lua/markview/parsers/latex.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
--- HTML parser for `markview.nvim`
local latex = {};

local utils = require("markview.utils")

local function bulk_gsub (text, gsubs)
local _o = text or "";

for _, g in ipairs(gsubs) do
g = utils.escape_string(g);
_o = _o:gsub(g, "");
end

return _o;
end

local function within_text_mode(TSNode)
while TSNode do
if TSNode:type() == "text_mode" then
return true;
end

TSNode = TSNode:parent();
end

return false;
end

--- Queried contents
---@type table[]
latex.content = {};
Expand All @@ -20,15 +45,19 @@ end

---@type markview.parsers.function
latex.parenthasis = function (buffer, TSNode, text, range)
local conceal = false;
local line = vim.api.nvim_buf_get_lines(buffer, range.row_start, range.row_start + 1, false)[1];
local before = line:sub(0, range.col_start);

if text[1]:match("^%{(%d*)%}$") or text[1]:match("^%{[%d%a]%}$") then
conceal = true;
if within_text_mode(TSNode) then return; end

if before:match("%^$") or before:match("%_$") then
return;
elseif before:match("%\\(%a+)$") or before:match("%}%s*$") then
return;
end

latex.insert({
class = "latex_bracket",
conceal = conceal,

text = text,

Expand All @@ -37,7 +66,9 @@ latex.parenthasis = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.escaped = function (buffer, TSNode, text, range)
latex.escaped = function (_, TSNode, text, range)
if within_text_mode(TSNode) then return; end

latex.insert({
class = "latex_escaped",

Expand All @@ -48,9 +79,25 @@ latex.escaped = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.symbol = function (buffer, TSNode, text, range)
latex.symbol = function (_, TSNode, text, range)
local node = TSNode;
local style;

while node do
if node:type() == "text_mode" then
return;
elseif vim.list_contains({ "subscript", "superscript" }, node:type()) then
style = node:type() .. "s";
break;
end

node = node:parent();
end

latex.insert({
class = "latex_symbol",
name = text[1]:sub(2),
style = style,

text = text,

Expand All @@ -64,6 +111,8 @@ latex.command = function (buffer, TSNode, text, range)
local nodes = TSNode:field("arg");
local command = text[1]:match("^\\([^%{%s]+)");

if within_text_mode(TSNode) then return; end

for _, arg in ipairs(nodes) do
table.insert(args, {
text = vim.treesitter.get_node_text(arg, buffer),
Expand All @@ -83,9 +132,28 @@ latex.command = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.block = function (buffer, TSNode, text, range)
latex.block = function (buffer, _, text, range)
local from, to = vim.api.nvim_buf_get_lines(buffer, range.row_start, range.row_start + 1, false)[1]:sub(0, range.col_start), vim.api.nvim_buf_get_lines(buffer, range.row_end, range.row_end + 1, false)[1]:sub(0, range.col_end);
local inline, closed = false, true;

if
not from:match("^(%s*)$") or not to:match("^(%s*)%$%$$")
then
inline = true;
elseif
not text[1]:match("%$%$$")
then
inline = true;
end

if not text[#text]:match("%$%$$") then
closed = false;
end

latex.insert({
class = "latex_block",
inline = inline,
closed = closed,

text = text,

Expand All @@ -94,9 +162,16 @@ latex.block = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.inline = function (buffer, TSNode, text, range)
latex.inline = function (_, _, text, range)
local closed = true;

if not text[#text]:match("%$$") then
closed = false;
end

latex.insert({
class = "latex_inline",
closed = closed,

text = text,

Expand All @@ -105,9 +180,46 @@ latex.inline = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.superscript = function (buffer, TSNode, text, range)
latex.superscript = function (_, TSNode, text, range)
local node = TSNode;
local level, preview = 0, true;

local supported_symbols = {
"\\alpha",
"\\beta",
"\\gamma",
"\\delta",
"\\epsilon",
"\\theta",
"\\iota",
"\\Phi",
"\\varphi",
"\\chi"
}

for _, line in ipairs(text) do
if bulk_gsub(line, supported_symbols):match("%\\") then
preview = false;
break;
end
end

while node do
if node:type() == "text_mode" then
return;
elseif node:type() == "superscript" then
level = level + 1;
end

node = node:parent();
end

latex.insert({
class = "latex_superscript",
parenthasis = text[1]:match("^%^%{") ~= nil,

preview = preview,
level = level,

text = text,

Expand All @@ -116,9 +228,41 @@ latex.superscript = function (buffer, TSNode, text, range)
end

---@type markview.parsers.function
latex.subscript = function (buffer, TSNode, text, range)
latex.subscript = function (_, TSNode, text, range)
local node = TSNode;
local level, preview = 0, true;

local supported_symbols = {
"\\beta",
"\\gamma",
"\\rho",
"\\epsilon",
"\\chi"
}

for _, line in ipairs(text) do
if bulk_gsub(line, supported_symbols):match("%\\") then
preview = false;
break;
end
end

while node do
if node:type() == "text_mode" then
return;
elseif node:type() == "subscript" then
level = level + 1;
end

node = node:parent();
end

latex.insert({
class = "latex_subscript",
parenthasis = text[1]:match("^%_%{") ~= nil,

preview = preview,
level = level,

text = text,

Expand All @@ -140,17 +284,35 @@ end
---@type markview.parsers.function
latex.font = function (buffer, TSNode, text, range)
local cmd = TSNode:field("command")[1];
if within_text_mode(TSNode) then return; end

if not cmd then
return;
end

_, range.font_start, _, range.font_end = cmd:range();

latex.insert({
class = "latex_font",
font = vim.treesitter.get_node_text(cmd, buffer):gsub("\\", ""),
name = vim.treesitter.get_node_text(cmd, buffer):gsub("\\", ""),

text = text,

range = range
})
end

---@type markview.parsers.function
latex.word = function (_, TSNode, text, range)
if within_text_mode(TSNode) then return; end

latex.insert({
class = "latex_word",
text = text,
range = range
})
end

latex.parse = function (buffer, TSTree, from, to)
-- Clear the previous contents
latex.sorted = {};
Expand All @@ -159,18 +321,24 @@ latex.parse = function (buffer, TSTree, from, to)
local scanned_queries = vim.treesitter.query.parse("latex", [[
((curly_group) @latex.parenthasis)
([(operator) (word)] @latex.word
(#match? @latex.word "^[^\\\\]+$"))
((generic_command
.
command: (
((command_name) @escaped.name)
(#match? @escaped.name "^\\.$")
(#match? @escaped.name "^\\\\.$")
)
.
) @latex.escaped)
((generic_command
.
command: (command_name)
command: (
((command_name) @symbol.name)
(#match? @symbol.name "^\\\\[a-zA-Z]+$")
)
.
) @latex.symbol)
Expand All @@ -184,7 +352,7 @@ latex.parse = function (buffer, TSTree, from, to)
.
command: (
(command_name) @font.cmd
(#match? @font.cmd "^\\math")
(#match? @font.cmd "^\\\\math")
)
arg: (curly_group)
.
Expand All @@ -196,9 +364,9 @@ latex.parse = function (buffer, TSTree, from, to)
((text_mode) @latex.text)
((superscript) @superscript)
((superscript) @latex.superscript)
((subscript) @subscript)
((subscript) @latex.subscript)
]]);

for capture_id, capture_node, _, _ in scanned_queries:iter_captures(TSTree:root(), buffer, from, to) do
Expand Down
Loading

0 comments on commit 2f6faac

Please sign in to comment.