-
Notifications
You must be signed in to change notification settings - Fork 111
Expand file tree
/
Copy pathmarks.lua
More file actions
147 lines (132 loc) · 4.29 KB
/
marks.lua
File metadata and controls
147 lines (132 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
local compat = require('render-markdown.lib.compat')
local log = require('render-markdown.core.log')
local str = require('render-markdown.lib.str')
---@class (exact) render.md.Mark
---@field modes? render.md.Modes
---@field conceal render.md.mark.Conceal
---@field start_row integer
---@field start_col integer
---@field opts render.md.mark.Opts
---@alias render.md.mark.Conceal boolean|render.md.Element
---@class render.md.mark.Opts: vim.api.keyset.set_extmark
---@field hl_mode? 'replace'|'combine'|'blend'
---@field virt_text? render.md.mark.Line
---@field virt_text_pos? 'eol'|'eol_right_align'|'inline'|'overlay'
---@field virt_lines? render.md.mark.Line[]
---@alias render.md.mark.Line render.md.mark.Text[]
---@class (exact) render.md.mark.Text
---@field [1] string text
---@field [2] render.md.mark.Hl highlight
---@alias render.md.mark.Hl string|string[]
---@class render.md.Marks
---@field private context render.md.request.Context
---@field private update boolean
---@field private marks render.md.Mark[]
local Marks = {}
Marks.__index = Marks
---@param context render.md.request.Context
---@param update boolean
---@return render.md.Marks
function Marks.new(context, update)
local self = setmetatable({}, Marks)
self.context = context
self.update = update
self.marks = {}
return self
end
---@return render.md.Mark[]
function Marks:get()
return self.marks
end
---@param config render.md.base.Config
---@param conceal render.md.mark.Conceal
---@param node render.md.Node
---@param opts render.md.mark.Opts
---@return boolean
function Marks:start(config, conceal, node, opts)
return self:add(config, conceal, node.start_row, node.start_col, opts)
end
---@param config render.md.base.Config
---@param conceal render.md.mark.Conceal
---@param node? render.md.Node
---@param opts render.md.mark.Opts
---@param offset? Range4
---@return boolean
function Marks:over(config, conceal, node, opts, offset)
if not node then
return false
end
offset = offset or { 0, 0, 0, 0 }
local start_row = node.start_row + offset[1]
local start_col = node.start_col + offset[2]
opts.end_row = node.end_row + offset[3]
opts.end_col = node.end_col + offset[4]
return self:add(config, conceal, start_row, start_col, opts)
end
---@param config render.md.base.Config
---@param conceal render.md.mark.Conceal
---@param start_row integer
---@param start_col integer
---@param opts render.md.mark.Opts
---@return boolean
function Marks:add(config, conceal, start_row, start_col, opts)
---@type render.md.Mark
local mark = {
modes = config.render_modes,
conceal = conceal,
start_row = start_row,
start_col = start_col,
opts = opts,
}
local feature, min_version = self:validate(mark.opts)
if feature and min_version then
local message = feature .. ' requires neovim >= ' .. min_version
log.add('error', 'Mark', message, mark)
return false
end
log.add('trace', 'Mark', mark)
if self.update then
self:run_update(mark)
end
self.marks[#self.marks + 1] = mark
return true
end
---@private
---@param opts render.md.mark.Opts
---@return string?, string?
function Marks:validate(opts)
if not compat.has_10 then
if opts.virt_text_pos == 'inline' then
return "virt_text_pos = 'inline'", '0.10.0'
end
if opts.virt_text_repeat_linebreak then
return 'virt_text_repeat_linebreak', '0.10.0'
end
end
if not compat.has_11 then
if opts.virt_text_pos == 'eol_right_align' then
return "virt_text_pos = 'eol_right_align'", '0.11.0'
end
if opts.conceal_lines then
return 'conceal_lines', '0.11.0'
end
end
return nil, nil
end
---@private
---@param mark render.md.Mark
function Marks:run_update(mark)
local row, start_col, opts = mark.start_row, mark.start_col, mark.opts
if opts.conceal then
local end_col = assert(opts.end_col, 'conceal requires end_col')
self.context.conceal:add(row, { start_col, end_col, opts.conceal, 1 })
end
if opts.virt_text_pos == 'inline' then
self.context.offset:add(row, {
col = start_col,
width = str.line_width(opts.virt_text),
virt_text = opts.virt_text or {},
})
end
end
return Marks