Skip to content

Commit ea0fb87

Browse files
committed
feat(typst): Added org indent for sections with headings
Closes #501
1 parent dbf74b6 commit ea0fb87

8 files changed

Lines changed: 152 additions & 6 deletions

File tree

doc/markview.nvim-typst.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,13 @@ headings *markview.nvim-typst.headings*
135135
---
136136
---@field enable boolean Enable rendering of Headings.
137137
---
138-
---@field shift_width integer Amount of spaces to shift per heading level.
139138
---@field [string] headings.typst Heading level configuration(name format: "heading_%d", %d = heading level).
139+
---
140+
---@field shift_width integer Amount of spaces to add before the text for teach heading level.
141+
---
142+
---@field org_indent? boolean Enables `Org mode` like section indentation. Disabled by default.
143+
---@field org_shift_width? integer Amount of `org_shift_char` to add per heading level.
144+
---@field org_shift_char? string Character used for indenting/shifting the sections.
140145
<
141146

142147
Changes how headings are shown.

lua/markview/config/typst.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---@type markview.config.typst
12
return {
23
enable = true,
34

@@ -65,7 +66,11 @@ return {
6566
style = "icon",
6667

6768
icon = "󰎴 ", hl = "MarkviewHeading6",
68-
}
69+
},
70+
71+
org_indent = false,
72+
org_shift_char = " ",
73+
org_shift_width = 1,
6974
},
7075

7176
labels = {

lua/markview/parsers/markdown.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ markdown.atx_heading = function (buffer, TSNode, text, range)
6060
6161
Each `atx_heading` creates a `section` in the document.
6262
By checking the depth of a `section` & it's sibling `section`s
63-
we cab determine the level of a heading.
63+
we can determine the level of a heading.
6464
6565
Level format: 1.1.1.1
6666
They are calculated like so,

lua/markview/parsers/typst.lua

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,42 @@ typst.idet = function (_, TSNode, text, range)
483483
});
484484
end
485485

486+
---@param buffer integer
487+
---@param TSNode table
488+
---@param text string[]
489+
---@param range markview.parsed.typst.sections.range
490+
typst.section = function (buffer, TSNode, text, range)
491+
local heading = TSNode:child(0);
492+
local heading_text = vim.treesitter.get_node_text(heading, buffer);
493+
494+
---@type TSNode?
495+
local content = heading:next_sibling();
496+
local org_end = range.row_end;
497+
498+
if content then
499+
local child = content:named_child(0);
500+
501+
while child do
502+
if child:type() == "section" then
503+
org_end = -1 + child:range();
504+
break;
505+
end
506+
507+
child = child:next_named_sibling();
508+
end
509+
end
510+
511+
range.org_end = org_end;
512+
513+
table.insert(typst.content, {
514+
class = "typst_section",
515+
level = heading_text:match("^%s*(=+)"):len(),
516+
517+
text = text,
518+
range = range
519+
});
520+
end
521+
486522
--- Parser for typst.
487523
---@param buffer integer
488524
---@param TSTree table
@@ -500,6 +536,9 @@ typst.parse = function (buffer, TSTree, from, to)
500536
typst.content = {};
501537

502538
local scanned_queries = vim.treesitter.query.parse("typst", [[
539+
((section
540+
(heading)) @typst.section)
541+
503542
((attach
504543
sub: (_) @typst.subscript))
505544

lua/markview/renderers/typst.lua

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,21 @@ typst.heading = function (buffer, item)
425425
line_hl_group = utils.set_hl(config.hl)
426426
});
427427
elseif config.style == "icon" then
428+
local shift_width = main_config.shift_width or 0;
429+
local shift_char = " ";
430+
428431
vim.api.nvim_buf_set_extmark(buffer, typst.ns, range.row_start, range.col_start, {
429432
undo_restore = false, invalidate = true,
430433
end_col = range.col_start + item.level + 1,
434+
431435
conceal = "",
436+
432437
sign_text = config.sign,
433438
sign_hl_group = utils.set_hl(config.sign_hl),
439+
434440
virt_text_pos = "inline",
435441
virt_text = {
436-
{ string.rep(" ", item.level * spec.get({ "typst", "headings", "shift_width" }, { fallback = 1 })) },
442+
{ string.rep(shift_char, (item.level - 1) * shift_width) },
437443
{ config.icon or "", utils.set_hl(config.icon_hl or config.hl) },
438444
},
439445
line_hl_group = utils.set_hl(config.hl),
@@ -1569,6 +1575,68 @@ typst.text = function (buffer, item)
15691575
});
15701576
end
15711577

1578+
--- Render org mode like section indentations.
1579+
---@param buffer integer
1580+
---@param item markview.parsed.typst.sections
1581+
typst.section = function (buffer, item)
1582+
---@type markview.config.typst.headings?
1583+
local main_config = spec.get({ "typst", "headings" }, { fallback = nil, eval_args = { buffer, item } });
1584+
1585+
if main_config == nil then
1586+
return;
1587+
elseif main_config.org_indent ~= true then
1588+
--- Org indent mode disabled.
1589+
return;
1590+
end
1591+
1592+
local shift_width = main_config.org_shift_width or main_config.shift_width or 0;
1593+
local shift_char = main_config.org_shift_char or " ";
1594+
1595+
local range = item.range;
1596+
1597+
for l = range.row_start + 1, range.org_end do
1598+
vim.api.nvim_buf_set_extmark(buffer, typst.ns, l, 0, {
1599+
undo_restore = false, invalidate = true,
1600+
1601+
virt_text_pos = "inline",
1602+
virt_text = {
1603+
{
1604+
string.rep(
1605+
shift_char,
1606+
math.max(
1607+
0,
1608+
shift_width * (item.level - 1)
1609+
)
1610+
)
1611+
}
1612+
},
1613+
1614+
right_gravity = false,
1615+
hl_mode = "combine"
1616+
});
1617+
end
1618+
1619+
---@type integer, integer Start & end fold level.
1620+
local foldlevel_s, foldlevel_e;
1621+
1622+
vim.api.nvim_buf_call(buffer, function ()
1623+
foldlevel_s = vim.fn.foldlevel(range.row_start + 1);
1624+
foldlevel_e = vim.fn.foldlevel(range.row_end + 1);
1625+
end)
1626+
1627+
if foldlevel_s ~= 0 or foldlevel_e ~= 0 then
1628+
--- Text was folded.
1629+
return;
1630+
end
1631+
1632+
local win = utils.buf_getwin(buffer);
1633+
1634+
if win and main_config.org_indent_wrap == true and vim.wo[win].wrap == true then
1635+
--- When `wrap` is enabled, run post-processing effects.
1636+
table.insert(typst.cache, item);
1637+
end
1638+
end
1639+
15721640
--- Renders typst previews.
15731641
---@param buffer integer
15741642
---@param content markview.parsed.typst[]

lua/markview/types/parsers/typst.lua

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,27 @@
210210

211211
------------------------------------------------------------------------------
212212

213+
--- Used for Org-indent.
214+
---@class markview.parsed.typst.sections
215+
---
216+
---@field class "typst_section"
217+
---@field level integer
218+
---
219+
---@field text string[]
220+
---@field range markview.parsed.typst.sections.range
221+
222+
223+
---@class markview.parsed.typst.sections.range
224+
---
225+
---@field row_start integer
226+
---@field row_end integer
227+
---@field col_start integer
228+
---@field col_end integer
229+
---
230+
---@field org_end integer Line where `Org indent` should end.
231+
232+
------------------------------------------------------------------------------
233+
213234
---@alias markview.parsed.typst
214235
---| markview.parsed.typst.code_block
215236
---| markview.parsed.typst.code_spans
@@ -222,6 +243,7 @@
222243
---| markview.parsed.typst.raw_blocks
223244
---| markview.parsed.typst.raw_spans
224245
---| markview.parsed.typst.reference_links
246+
---| markview.parsed.typst.sections
225247
---| markview.parsed.typst.strong
226248
---| markview.parsed.typst.subscripts
227249
---| markview.parsed.typst.superscripts
@@ -251,3 +273,5 @@
251273
---@field typst_emphasis markview.parsed.typst.emphasis[]
252274
---@field typst_strong markview.parsed.typst.strong[]
253275
---@field typst_text markview.parsed.typst.text[]
276+
---@field typst_section markview.parsed.typst.sections[]
277+

lua/markview/types/renderers/typst.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,13 @@
7676
---
7777
---@field enable boolean Enable rendering of Headings.
7878
---
79-
---@field shift_width integer Amount of spaces to shift per heading level.
8079
---@field [string] headings.typst Heading level configuration(name format: "heading_%d", %d = heading level).
80+
---
81+
---@field shift_width integer Amount of spaces to add before the text for teach heading level.
82+
---
83+
---@field org_indent? boolean Enables `Org mode` like section indentation. Disabled by default.
84+
---@field org_shift_width? integer Amount of `org_shift_char` to add per heading level.
85+
---@field org_shift_char? string Character used for indenting/shifting the sections.
8186

8287

8388
--- Configuration options for each typst heading level.

markview.nvim.wiki

0 commit comments

Comments
 (0)