--- Daily journal (tech-spec ยง8). `journal.open_or_create` is idempotent (the --- node id is deterministic in (owner, date)), so opening today's note twice is --- safe. local rpc = require("heph.rpc") local util = require("heph.util") local M = {} --- Open (creating if absent) the journal for `date` (default: today), in a --- buffer. Returns the node. function M.open(date) date = date or util.iso_today() local node = rpc.call("journal.open_or_create", { date = date }) require("heph.node").open(node.id) return node end local function iso_to_time(iso) local y, m, d = iso:match("(%d+)-(%d+)-(%d+)") return os.time({ year = tonumber(y), month = tonumber(m), day = tonumber(d), hour = 12 }) end --- Entries for the `n` most recent days ending at `today` (ISO; default today), --- newest first. Each: `{ date, node|nil, exists }`. Journals are titled by --- their ISO date, so each day resolves directly. function M.recent_entries(n, today) today = (today and #today > 0) and today or util.iso_today() local t0 = iso_to_time(today) local entries = {} for i = 0, n - 1 do local date = os.date("%Y-%m-%d", t0 - i * 86400) local node = rpc.call("node.resolve", { title = date }) entries[#entries + 1] = { date = date, node = node, exists = node ~= nil } end return entries end --- Pick among recent journal days โ€” existing days preview their content, new --- days show `@create` โ€” and open the chosen day's journal (creating if new). function M.pick(opts) opts = opts or {} local days = opts.days or (require("heph").config or {}).journal_days or 7 require("heph.picker").select(M.recent_entries(days), { prompt = "heph journals", format = function(e) return e.exists and e.date or (e.date .. " @create") end, preview = function(e) if e.exists and e.node and e.node.body and #e.node.body > 0 then return vim.split(e.node.body, "\n", { plain = true }) end return { "@create โ€” new journal for " .. e.date } end, }, function(e) if e then M.open(e.date) end end) end return M