So here's my take on persistent folding, mixed from code at the first posting and Persistent folding: how to use space-style to hide a particular attribute? - #10 by Platinum :
Similar to Tom I add the marker
, but by using the editor:fold and editor:unfold events, so I do not need to remember a separate shortcut and it works independently of the type of the item to be folded.
Platinums code to restore the state worked fine, I just added await to editor.getCursor() to fix the issue with nil
persFold = persFold or {} -- define namespace for persistent fold supporting functions
persFold.marker = "⬇️"
function persFold.lineStart(pageText, pos)
-- Return the starting position of the line of the current page containing position pos
-- Get the content of the page text up to pos
local pageTextToPos = string.sub(pageText, 1, pos)
-- Reverse it
local pageTextToPosReversed = string.reverse(pageTextToPos)
-- Find the number of characters before the first new line character
local posPositionInLine, _ = string.find(pageTextToPosReversed, "\n")
-- Subtract that number from pos
--local startOfLine = pos - posPositionInLine
if posPositionInLine then
return pos - (posPositionInLine - 2)
else
return 1
end
end
function persFold.lineLength(pageText, startOfLine)
local pageTextFromStartOfLine = string.sub(pageText, startOfLine)
local lineLength, _ = string.find(pageTextFromStartOfLine, "\n") - 1
return lineLength
end
function persFold.lineText(pageText, pos)
-- Return the text of the line of the current page containing position pos
-- Find the end of the current line, or the end of the page if it's the last line
local startOfLine = persFold.lineStart(pageText, pos)
local lineLength = persFold.lineLength(pageText, startOfLine)
if lineLength == -1 then
lineLength = string.len(pageText) - startOfLine + 1
end
local lineText = string.sub(pageText, startOfLine, startOfLine + lineLength - 1)
return lineText
end
function persFold.togglerMarker(toggleOn)
local pageText = editor.getText()
if not pageText then
return
end
local cursorPositionInPage = editor.getCursor()
-- Get the text, starting position and length of the current line
local currentLineText = persFold.lineText(pageText, cursorPositionInPage)
local currentLineStart = persFold.lineStart(pageText,cursorPositionInPage)
local currentLineLength = persFold.lineLength(pageText,currentLineStart)
local nextLineStart = currentLineStart + currentLineLength
local marked = string.sub(currentLineText,currentLineLength - string.len(persFold.marker) + 1, currentLineLength) == persFold.marker
if toggleOn == 1 and not marked then
-- add marker
editor.insertAtPos(persFold.marker, nextLineStart - 1)
elseif toggleOn == 0 and marked then
-- If yes, remove marker
editor.replaceRange(nextLineStart - 1 - string.len(persFold.marker), nextLineStart - 1, "")
end
end
-- add marker when folding (Ctl-. Ctl-.)
event.listen{
name = "editor:fold",
run = function()
persFold.togglerMarker(1)
end
}
-- remove marker when folding (Ctl-. Ctl-.)
event.listen{
name = "editor:unfold",
run = function()
persFold.togglerMarker(0)
end
}
-- Event listener to fold up marked bullets on page load
event.listen{
name = "editor:pageLoaded",
run = function()
local text = editor.getText()
if not text then
return
end
-- Save cursor position
local originalCursor = await editor.getCursor()
local lineNum = 0
for line in (text .. "\n"):gmatch("(.-)\n") do
lineNum = lineNum + 1
-- Simple substring match
if line:find(persFold.marker .. "$", 1) then
-- Move cursor to the line so the folding can be done
editor.moveCursorToLine(lineNum, 1, false)
-- Fold the block at cursor
editor.fold()
end
end
-- Restore cursor
if originalCursor != nil then
editor.setCursor(originalCursor)
end
end
}