add Click History: Page Picker
should help ease overly detailed records.
Even so, it still navigates by default to the last click on that page.
One can modify it to jump on page hierarchy rather than page@pos.
local function getTimes()
local t = datastore.get({"ClickTimes", "!"}) or {}
return t.Ctimes or 1
end
local function setTimes(n)
datastore.set({"ClickTimes", "!"}, { Ctimes = n })
end
local function getBrowse()
local b = datastore.get({"ClickBrowse", "!"})
if b then return b end
local ct = getTimes()
b = { index = ct, max = ct - 1, active = false }
datastore.set({"ClickBrowse", "!"}, b)
return b
end
local function setBrowse(b)
datastore.set({"ClickBrowse", "!"}, b)
end
local function getRef(idx)
local rec = datastore.get({"ClickHistory", tostring(idx)}) or {}
return rec.ref
end
local function getTimeString(idx)
local rec = datastore.get({"ClickHistory", tostring(idx)}) or {}
if rec.tstr and rec.tstr ~= "" then
return rec.tstr
end
if rec.ts then
return os.date("%Y-%m-%d %H:%M:%S", rec.ts)
end
return nil
end
local function setRef(idx, ref)
local now = os.time()
datastore.set(
{"ClickHistory", tostring(idx)},
{
ref = ref,
-- ts = now,
tstr = os.date("%Y-%m-%d %H:%M:%S", now),
}
)
end
local function clearAllHistory()
local Ctimes = getTimes()
for i = 1, Ctimes do
datastore.delete({"ClickHistory", tostring(i)})
end
setTimes(1)
setBrowse({ index = 1, max = 0, active = false })
end
local enableTruncateDuringBrowse = false
local function appendHistory(ref)
local Ctimes = getTimes()
local lastRef = getRef(Ctimes - 1)
if lastRef and lastRef == ref then
return
end
local browse = getBrowse()
if enableTruncateDuringBrowse and browse.active and browse.index <= browse.max then
for i = browse.index + 1, browse.max do
datastore.delete({"ClickHistory", tostring(i)})
end
Ctimes = browse.index + 1
setTimes(Ctimes)
browse.index = Ctimes
browse.max = Ctimes
setBrowse(browse)
end
setRef(Ctimes, ref)
setTimes(Ctimes + 1)
local newTimes = Ctimes + 1
setBrowse({ index = newTimes, max = newTimes - 1, active = false })
end
local function navigateIndex(idx)
local ref = getRef(idx)
if not ref then
return false
end
editor.navigate(ref)
local pos = tonumber(ref:match("@(.*)$"))
if pos then
editor.moveCursor(pos, true)
end
return true
end
local function ensureBrowseSession()
local b = getBrowse()
if not b.active then
local Ctimes = getTimes()
b.max = Ctimes - 1
b.index = Ctimes
b.active = true
setBrowse(b)
end
return getBrowse()
end
-- add:Get/Set Record Mode
-- nil/false: `Click` to record (default)
-- true: `Ctrl + Click` to record
local function getRecordMode()
local ClickHistoryMode = datastore.get({"ClickHistoryMode", "!"}) or {}
return ClickHistoryMode.currentMode or false
end
event.listen {
name = "page:click",
run = function(e)
local d = e.data or {}
local pageName = editor.getCurrentPage()
local pos = d.pos
if not pageName or not pos then return end
local ref = string.format("%s@%d", pageName, pos)
local ctrlRecordMode = getRecordMode()
if ctrlRecordMode then
if d.ctrlKey then
appendHistory(ref)
editor.moveCursor(pos, true)
editor.flashNotification("pos @ " .. tostring(pos))
end
else
if d.ctrlKey then
editor.moveCursor(pos, true)
editor.flashNotification("pos @ " .. tostring(pos))
else
appendHistory(ref)
end
end
end
}
command.define {
name = "Click History: Toggle Mode",
key = "Ctrl-Shift-m",
priority = 1,
run = function()
local currentMode = getRecordMode()
local newMode = not currentMode
datastore.set({"ClickHistoryMode", "!"}, {currentMode = newMode})
if newMode then
editor.flashNotification("Mode switched: [Ctrl + Click] to record history.")
else
editor.flashNotification("Mode switched: [Click] to record history.")
end
end,
}
command.define {
name = "Click History: Back",
run = function()
local b = ensureBrowseSession()
if b.max < 1 then
editor.flashNotification("No history", "warning")
return
end
if b.index > b.max + 1 then
b.index = b.max + 1
end
b.index = math.max(b.index - 1, 1)
setBrowse(b)
if navigateIndex(b.index) then
editor.flashNotification(string.format("Back: %d / %d", b.index, b.max))
end
end,
key = "Shift-Alt-ArrowLeft",
mac = "Shift-Alt-ArrowLeft",
priority = 1,
}
command.define {
name = "Click History: Forward",
run = function()
local b = ensureBrowseSession()
if b.max < 1 then
editor.flashNotification("No history", "warning")
return
end
b.index = math.min(b.index + 1, b.max)
setBrowse(b)
if navigateIndex(b.index) then
editor.flashNotification(string.format("Forward: %d / %d", b.index, b.max))
end
end,
key = "Shift-Alt-ArrowRight",
mac = "Shift-Alt-ArrowRight",
priority = 1,
}
command.define {
name = "Click History: End",
run = function()
local Ctimes = getTimes()
local max = Ctimes - 1
if max < 1 then
editor.flashNotification("No history", "warning")
return
end
setBrowse({ index = max, max = max, active = false })
if navigateIndex(max) then
editor.flashNotification(string.format("End: %d / %d", max, max))
end
end,
key = "Ctrl-Shift-Alt-ArrowRight",
mac = "Ctrl-Shift-Alt-ArrowRight",
priority = 1,
}
command.define {
name = "Click History: Start",
run = function()
local b = ensureBrowseSession()
if b.max < 1 then
editor.flashNotification("No history", "warning")
return
end
b.index = 1
setBrowse(b)
if navigateIndex(1) then
editor.flashNotification(string.format("Start: 1 / %d", b.max))
end
end,
key = "Ctrl-Shift-Alt-ArrowLeft",
mac = "Ctrl-Shift-Alt-ArrowLeft",
priority = 1,
}
command.define {
name = "Click History: Clear",
run = function()
clearAllHistory()
editor.flashNotification("Click History cleared.", "info")
end,
key = "Ctrl-Shift-Alt-Delete",
mac = "Ctrl-Shift-Alt-Delete",
priority = 1,
}
local Ctimes = getTimes()
setBrowse({ index = Ctimes, max = Ctimes - 1, active = false })
------------------------------------------------------------
-- Click History: Cursor Picker Implementation
------------------------------------------------------------
command.define {
name = "Click History: Cursor Picker",
run = function()
local Ctimes = getTimes()
local max = Ctimes - 1
if max < 1 then
editor.flashNotification("No click history found.", "warning")
return
end
local historyItems = {}
for i = max, 1, -1 do
local ref = getRef(i)
if ref then
local pageName, pos = ref:match("^(.*)@(%d+)$")
local displayName = ref
local tstr = getTimeString(i) or ""
if pageName and tstr then
displayName = string.format("%d 🖱️ %s", i, pageName)
else
displayName = string.format("%d. %s", i, ref)
end
table.insert(historyItems, {
id = i,
name = displayName,
description = tstr .. " 📍 " .. pos,
ref = ref
})
end
end
local sel = editor.filterBox(
"Back to",
historyItems,
"Select a Click History...",
"Page @ Pos where you Once Clicked"
)
if sel then
local b = ensureBrowseSession()
b.index = sel.id
setBrowse(b)
if navigateIndex(sel.id) then
editor.flashNotification(string.format("Jumped to history: %d / %d", sel.id, max))
end
end
end,
key = "Ctrl-Alt-h",
priority = 1,
}
------------------------------------------------------------
-- Click History: Page Picker Implementation
------------------------------------------------------------
command.define {
name = "Click History: Page Picker",
run = function()
local Ctimes = getTimes()
local max = Ctimes - 1
if max < 1 then
editor.flashNotification("No click history found.", "warning")
return
end
local historyItems, seen = {}, {}
for i = max, 1, -1 do
local ref = getRef(i)
if ref then
local pageName, pos = ref:match("^(.*)@(%d+)$")
if not seen[pageName] then
seen[pageName] = true
local displayName = ref
local tstr = getTimeString(i) or ""
if pageName and tstr then
displayName = string.format("%d 🖱️ %s", i, pageName)
else
displayName = string.format("%d. %s", i, ref)
end
table.insert(historyItems, {
id = i,
name = displayName,
description = tstr .. " 📍 " .. pos,
ref = ref
})
end
end
end
local sel = editor.filterBox(
"Back to",
historyItems,
"Select a Click History...",
"Page @ Pos where you Once Clicked"
)
if sel then
local b = ensureBrowseSession()
b.index = sel.id
setBrowse(b)
if navigateIndex(sel.id) then
editor.flashNotification(string.format("Jumped to history: %d / %d", sel.id, max))
end
end
end,
key = "Shift-Alt-h",
priority = 1,
}
``

