mirror of
https://github.com/folke/snacks.nvim
synced 2025-07-12 15:45:09 +00:00
feat(image): configurable templates for math expressions. Closes #1338
This commit is contained in:
parent
6922aab01f
commit
e039139291
3 changed files with 61 additions and 31 deletions
|
@ -41,13 +41,11 @@ M.transforms = {
|
||||||
if not img.content then
|
if not img.content then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local fg = Snacks.util.color("SnacksImageMath") or "#000000"
|
img.content = Snacks.picker.util.tpl(Snacks.image.config.math.typst.tpl, {
|
||||||
img.content = ([[
|
color = Snacks.util.color("SnacksImageMath") or "#000000",
|
||||||
#set page(width: auto, height: auto, margin: (x: 2pt, y: 2pt))
|
header = M.get_header(ctx.buf),
|
||||||
#show math.equation.where(block: false): set text(top-edge: "bounds", bottom-edge: "bounds")
|
content = img.content,
|
||||||
#set text(size: 12pt, fill: rgb("%s"))
|
}, { indent = true, prefix = "$" })
|
||||||
%s
|
|
||||||
%s]]):format(fg, M.get_header(ctx.buf), img.content)
|
|
||||||
end,
|
end,
|
||||||
latex = function(img, ctx)
|
latex = function(img, ctx)
|
||||||
if not img.content then
|
if not img.content then
|
||||||
|
@ -62,7 +60,7 @@ M.transforms = {
|
||||||
content = ("\\[%s\\]"):format(content)
|
content = ("\\[%s\\]"):format(content)
|
||||||
end
|
end
|
||||||
local packages = { "xcolor" }
|
local packages = { "xcolor" }
|
||||||
vim.list_extend(packages, Snacks.image.config.convert.math.packages)
|
vim.list_extend(packages, Snacks.image.config.math.latex.packages)
|
||||||
for _, line in ipairs(vim.api.nvim_buf_get_lines(ctx.buf, 0, -1, false)) do
|
for _, line in ipairs(vim.api.nvim_buf_get_lines(ctx.buf, 0, -1, false)) do
|
||||||
if line:find("\\usepackage") then
|
if line:find("\\usepackage") then
|
||||||
for _, p in ipairs(vim.split(line:match("{(.-)}") or "", ",%s*")) do
|
for _, p in ipairs(vim.split(line:match("{(.-)}") or "", ",%s*")) do
|
||||||
|
@ -73,17 +71,13 @@ M.transforms = {
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(packages)
|
table.sort(packages)
|
||||||
local fs = Snacks.image.config.convert.math.font_size or "large"
|
img.content = Snacks.picker.util.tpl(Snacks.image.config.math.latex.tpl, {
|
||||||
img.content = ([[
|
font_size = Snacks.image.config.math.latex.font_size or "large",
|
||||||
\documentclass[preview,border=2pt,varwidth,12pt]{standalone}
|
packages = table.concat(packages, ", "),
|
||||||
\usepackage{%s}
|
header = M.get_header(ctx.buf),
|
||||||
\begin{document}
|
color = fg:upper():sub(2),
|
||||||
%s
|
content = content,
|
||||||
{ \%s \selectfont
|
}, { indent = true, prefix = "$" })
|
||||||
\color[HTML]{%s}
|
|
||||||
%s}
|
|
||||||
\end{document}
|
|
||||||
]]):format(table.concat(packages, ", "), M.get_header(ctx.buf), fs, fg:upper():sub(2), content)
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +227,7 @@ function M._img(ctx)
|
||||||
if img.src then
|
if img.src then
|
||||||
img.src = M.resolve(ctx.buf, img.src)
|
img.src = M.resolve(ctx.buf, img.src)
|
||||||
end
|
end
|
||||||
if not Snacks.image.config.doc.math and img.ext and img.ext:find("math") then
|
if not Snacks.image.config.math.enabled and img.ext and img.ext:find("math") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if img.content and not img.src then
|
if img.content and not img.src then
|
||||||
|
|
|
@ -68,7 +68,6 @@ local defaults = {
|
||||||
-- enable image viewer for documents
|
-- enable image viewer for documents
|
||||||
-- a treesitter parser must be available for the enabled languages.
|
-- a treesitter parser must be available for the enabled languages.
|
||||||
enabled = true,
|
enabled = true,
|
||||||
math = true, -- enable math expression rendering
|
|
||||||
-- render the image inline in the buffer
|
-- render the image inline in the buffer
|
||||||
-- if your env doesn't support unicode placeholders, this will be disabled
|
-- if your env doesn't support unicode placeholders, this will be disabled
|
||||||
-- takes precedence over `opts.float` on supported terminals
|
-- takes precedence over `opts.float` on supported terminals
|
||||||
|
@ -105,12 +104,6 @@ local defaults = {
|
||||||
---@class snacks.image.convert.Config
|
---@class snacks.image.convert.Config
|
||||||
convert = {
|
convert = {
|
||||||
notify = true, -- show a notification on error
|
notify = true, -- show a notification on error
|
||||||
math = {
|
|
||||||
font_size = "Large", -- see https://www.sascha-frank.com/latex-font-size.html
|
|
||||||
-- for latex documents, the doc packages are included automatically,
|
|
||||||
-- but you can add more packages here. Useful for markdown documents.
|
|
||||||
packages = { "amsmath", "amssymb", "amsfonts", "amscd", "mathtools" },
|
|
||||||
},
|
|
||||||
---@type snacks.image.args
|
---@type snacks.image.args
|
||||||
mermaid = function()
|
mermaid = function()
|
||||||
local theme = vim.o.background == "light" and "neutral" or "dark"
|
local theme = vim.o.background == "light" and "neutral" or "dark"
|
||||||
|
@ -124,6 +117,36 @@ local defaults = {
|
||||||
pdf = { "-density", 192, "{src}[0]", "-background", "white", "-alpha", "remove", "-trim" },
|
pdf = { "-density", 192, "{src}[0]", "-background", "white", "-alpha", "remove", "-trim" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
math = {
|
||||||
|
enabled = true, -- enable math expression rendering
|
||||||
|
-- in the templates below, `${header}` comes from any section in your document,
|
||||||
|
-- between a start/end header comment. Comment syntax is language-specific.
|
||||||
|
-- * start comment: `// snacks: header start`
|
||||||
|
-- * end comment: `// snacks: header end`
|
||||||
|
typst = {
|
||||||
|
tpl = [[
|
||||||
|
#set page(width: auto, height: auto, margin: (x: 2pt, y: 2pt))
|
||||||
|
#show math.equation.where(block: false): set text(top-edge: "bounds", bottom-edge: "bounds")
|
||||||
|
#set text(size: 12pt, fill: rgb("${color}"))
|
||||||
|
${header}
|
||||||
|
${content}]],
|
||||||
|
},
|
||||||
|
latex = {
|
||||||
|
font_size = "Large", -- see https://www.sascha-frank.com/latex-font-size.html
|
||||||
|
-- for latex documents, the doc packages are included automatically,
|
||||||
|
-- but you can add more packages here. Useful for markdown documents.
|
||||||
|
packages = { "amsmath", "amssymb", "amsfonts", "amscd", "mathtools" },
|
||||||
|
tpl = [[
|
||||||
|
\documentclass[preview,border=2pt,varwidth,12pt]{standalone}
|
||||||
|
\usepackage{${packages}}
|
||||||
|
\begin{document}
|
||||||
|
${header}
|
||||||
|
{ \${font_size} \selectfont
|
||||||
|
\color[HTML]{${color}}
|
||||||
|
${content}}
|
||||||
|
\end{document}]],
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
M.config = Snacks.config.get("image", defaults)
|
M.config = Snacks.config.get("image", defaults)
|
||||||
|
|
||||||
|
|
|
@ -172,13 +172,15 @@ end
|
||||||
|
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param data table<string, string>
|
---@param data table<string, string>
|
||||||
function M.tpl(str, data)
|
---@param opts? {prefix?: string, indent?: boolean, offset?: number[]}
|
||||||
return (
|
function M.tpl(str, data, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local ret = (
|
||||||
str:gsub(
|
str:gsub(
|
||||||
"(%b{})",
|
"(" .. vim.pesc(opts.prefix or "") .. "%b{}" .. ")",
|
||||||
---@param w string
|
---@param w string
|
||||||
function(w)
|
function(w)
|
||||||
local inner = w:sub(2, -2)
|
local inner = w:sub(2 + #(opts.prefix or ""), -2)
|
||||||
local key, default = inner:match("^(.-):(.*)$")
|
local key, default = inner:match("^(.-):(.*)$")
|
||||||
local ret = data[key or inner]
|
local ret = data[key or inner]
|
||||||
if ret == "" and default then
|
if ret == "" and default then
|
||||||
|
@ -188,6 +190,17 @@ function M.tpl(str, data)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if opts.indent then
|
||||||
|
local lines = vim.split(ret:gsub("\t", " "), "\n", { plain = true })
|
||||||
|
local indent = 1000
|
||||||
|
for _, line in ipairs(lines) do
|
||||||
|
indent = math.min(indent, line:find("%S") or 1000)
|
||||||
|
end
|
||||||
|
for l, line in ipairs(lines) do
|
||||||
|
lines[l] = line:sub(indent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param str string
|
---@param str string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue