Pick Headings with CMD-Tree UI
Yet another Navigate: Heading Picker -_-||
-- Pick Headings with CMD-like Tree UI
local function headingsPicker(options)
local text = editor.getText()
local parsed = markdown.parseMarkdown(text)
local nodes = {}
local function detect_level(node)
if node.tag then
local m = string.match(node.tag, "ATXHeading%s*(%d+)")
if m then return tonumber(m) end
end
if node.type then
local m = string.match(node.type, "ATXHeading%s*(%d+)") or string.match(node.type, "Heading(%d+)")
if m then return tonumber(m) end
end
return nil
end
local function node_pos(node)
return node.from or node.pos or node.name
end
for _, n in ipairs(parsed.children or {}) do
local level = detect_level(n)
if level then
local children = {}
if n.children then
for i, c in ipairs(n.children) do
if i > 1 then table.insert(children, c) end
end
end
local parts = {}
for _, c in ipairs(children) do
local rendered = markdown.renderParseTree(c)
if rendered and rendered ~= "" then
table.insert(parts, string.trim(rendered))
end
end
local title = table.concat(parts, "")
if title ~= "" then
table.insert(nodes, {
level = level,
text = title,
pos = node_pos(n)
})
end
end
end
if #nodes == 0 then
editor.flashNotification("No headings found")
return
end
local last_flags = {}
for i = 1, #nodes do
local L = nodes[i].level
local is_last = true
for j = i + 1, #nodes do
if nodes[j].level <= L then
if nodes[j].level == L then
is_last = false
else
is_last = true
end
break
end
end
last_flags[i] = is_last
end
local VERT = "│ "
local BLNK = " "
local TEE = "├─── "
local ELB = "└─── "
local items = {}
local stack = {}
for i = 1, #nodes do
local L = nodes[i].level
local is_last = last_flags[i]
while #stack >= L do table.remove(stack) end
local prefix = ""
for d = 1, #stack do
prefix = prefix .. (stack[d].last and BLNK or VERT)
end
for d = #stack + 1, L - 1 do
prefix = prefix .. BLNK
end
local elbow = is_last and ELB or TEE
local label = prefix .. elbow .. nodes[i].text
table.insert(items, {
name = label,
description = "",
pos = nodes[i].pos
})
table.insert(stack, { level = L, last = is_last })
end
local result = editor.filterBox("Heading Search:", items, "Select a Header")
local page = editor.getCurrentPage()
if result and result.selected and result.selected.value then
local item = result.selected.value
if item.pos then editor.navigate({ page = page, pos = item.pos }) end
elseif result and result.pos then
editor.navigate({ page = page, pos = result.pos })
end
end
command.define({
name = "Navigate: Heading Picker",
key = "Ctrl-Shift-h",
run = function() headingsPicker({}) end
})
Yet another Navigate: Tag Picker -_-||
