- add:
Toggle Record Mode
- default:
Click to record
- switch:
Ctrl + Click to record — then Click does nothing, as you wish 
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 Picker Implementation
------------------------------------------------------------
command.define {
name = "Click History: Pick",
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,
}