|
1 | 1 | local Context = require('render-markdown.request.context')
|
| 2 | +local Indent = require('render-markdown.lib.indent') |
2 | 3 | local Iter = require('render-markdown.lib.iter')
|
3 | 4 | local Marks = require('render-markdown.lib.marks')
|
4 | 5 | local Node = require('render-markdown.lib.node')
|
5 | 6 | local Str = require('render-markdown.lib.str')
|
6 | 7 | local log = require('render-markdown.core.log')
|
7 | 8 |
|
8 |
| ----@class render.md.handler.Latex: render.md.Handler |
9 |
| -local M = {} |
| 9 | +---@class render.md.handler.buf.Latex |
| 10 | +---@field private context render.md.request.Context |
| 11 | +---@field private config render.md.latex.Config |
| 12 | +local Handler = {} |
| 13 | +Handler.__index = Handler |
10 | 14 |
|
11 | 15 | ---@private
|
12 | 16 | ---@type table<string, string>
|
13 |
| -M.cache = {} |
| 17 | +Handler.cache = {} |
14 | 18 |
|
15 |
| ----@param ctx render.md.handler.Context |
| 19 | +---@param buf integer |
| 20 | +---@return render.md.handler.buf.Latex |
| 21 | +function Handler.new(buf) |
| 22 | + local self = setmetatable({}, Handler) |
| 23 | + self.context = Context.get(buf) |
| 24 | + self.config = self.context.config.latex |
| 25 | + return self |
| 26 | +end |
| 27 | + |
| 28 | +---@param root TSNode |
16 | 29 | ---@return render.md.Mark[]
|
17 |
| -function M.parse(ctx) |
18 |
| - local context = Context.get(ctx.buf) |
19 |
| - local config = context.config.latex |
20 |
| - if context:skip(config) then |
| 30 | +function Handler:run(root) |
| 31 | + if self.context:skip(self.config) then |
21 | 32 | return {}
|
22 | 33 | end
|
23 |
| - if vim.fn.executable(config.converter) ~= 1 then |
24 |
| - log.add('debug', 'executable not found', config.converter) |
| 34 | + if vim.fn.executable(self.config.converter) ~= 1 then |
| 35 | + log.add('debug', 'executable not found', self.config.converter) |
25 | 36 | return {}
|
26 | 37 | end
|
27 | 38 |
|
28 |
| - local node = Node.new(ctx.buf, ctx.root) |
| 39 | + local node = Node.new(self.context.buf, root) |
29 | 40 | log.node('latex', node)
|
30 | 41 |
|
31 |
| - local raw_expression = M.cache[node.text] |
32 |
| - if not raw_expression then |
33 |
| - raw_expression = vim.fn.system(config.converter, node.text) |
34 |
| - if vim.v.shell_error == 1 then |
35 |
| - log.add('error', config.converter, raw_expression) |
36 |
| - raw_expression = 'error' |
37 |
| - end |
38 |
| - M.cache[node.text] = raw_expression |
39 |
| - end |
40 |
| - |
41 |
| - local expressions = {} ---@type string[] |
42 |
| - for _ = 1, config.top_pad do |
43 |
| - expressions[#expressions + 1] = '' |
44 |
| - end |
45 |
| - for _, expression in ipairs(Str.split(raw_expression, '\n', true)) do |
46 |
| - expressions[#expressions + 1] = Str.pad(node.start_col) .. expression |
47 |
| - end |
48 |
| - for _ = 1, config.bottom_pad do |
49 |
| - expressions[#expressions + 1] = '' |
50 |
| - end |
51 |
| - |
52 |
| - local lines = Iter.list.map(expressions, function(expression) |
53 |
| - return { { expression, config.highlight } } |
| 42 | + local indent = self:indent(node.start_row, node.start_col) |
| 43 | + local lines = Iter.list.map(self:expressions(node), function(expression) |
| 44 | + local line = vim.list_extend({}, indent) |
| 45 | + line[#line + 1] = { expression, self.config.highlight } |
| 46 | + return line |
54 | 47 | end)
|
55 | 48 |
|
56 |
| - local above = config.position == 'above' |
| 49 | + local above = self.config.position == 'above' |
57 | 50 | local row = above and node.start_row or node.end_row
|
58 | 51 |
|
59 |
| - local marks = Marks.new(context, true) |
| 52 | + local marks = Marks.new(self.context, true) |
60 | 53 | marks:add(false, row, 0, {
|
61 | 54 | virt_lines = lines,
|
62 | 55 | virt_lines_above = above,
|
63 | 56 | })
|
64 | 57 | return marks:get()
|
65 | 58 | end
|
66 | 59 |
|
| 60 | +---@private |
| 61 | +---@param node render.md.Node |
| 62 | +---@return string[] |
| 63 | +function Handler:expressions(node) |
| 64 | + local result = {} ---@type string[] |
| 65 | + for _ = 1, self.config.top_pad do |
| 66 | + result[#result + 1] = '' |
| 67 | + end |
| 68 | + for _, line in ipairs(self:convert(node.text)) do |
| 69 | + result[#result + 1] = Str.pad(node.start_col) .. line |
| 70 | + end |
| 71 | + for _ = 1, self.config.bottom_pad do |
| 72 | + result[#result + 1] = '' |
| 73 | + end |
| 74 | + return result |
| 75 | +end |
| 76 | + |
| 77 | +---@private |
| 78 | +---@param text string |
| 79 | +---@return string[] |
| 80 | +function Handler:convert(text) |
| 81 | + local result = Handler.cache[text] |
| 82 | + if not result then |
| 83 | + local converter = self.config.converter |
| 84 | + result = vim.fn.system(converter, text) |
| 85 | + if vim.v.shell_error == 1 then |
| 86 | + log.add('error', converter, result) |
| 87 | + result = 'error' |
| 88 | + end |
| 89 | + Handler.cache[text] = result |
| 90 | + end |
| 91 | + return Str.split(result, '\n', true) |
| 92 | +end |
| 93 | + |
| 94 | +---@private |
| 95 | +---@param row integer |
| 96 | +---@param col integer |
| 97 | +---@return render.md.mark.Line |
| 98 | +function Handler:indent(row, col) |
| 99 | + local buf = self.context.buf |
| 100 | + local node = vim.treesitter.get_node({ |
| 101 | + bufnr = buf, |
| 102 | + pos = { row, col }, |
| 103 | + lang = 'markdown', |
| 104 | + }) |
| 105 | + if not node then |
| 106 | + return {} |
| 107 | + end |
| 108 | + return Indent.new(self.context, Node.new(buf, node)):line(true):get() |
| 109 | +end |
| 110 | + |
| 111 | +---@class render.md.handler.Latex: render.md.Handler |
| 112 | +local M = {} |
| 113 | + |
| 114 | +---@param ctx render.md.handler.Context |
| 115 | +---@return render.md.Mark[] |
| 116 | +function M.parse(ctx) |
| 117 | + return Handler.new(ctx.buf):run(ctx.root) |
| 118 | +end |
| 119 | + |
67 | 120 | return M
|
0 commit comments