hephaestus/heph.nvim/lua/heph/command.lua
Erich Blume 9249ca46a1
Some checks failed
Build / validate (pull_request) Failing after 4m13s
heph.nvim: follow-or-create wiki links + :Heph doc
Pressing <CR> on a [[wiki-link]] whose target doesn't exist now creates a doc
with that title and opens it (the zettelkasten gesture), and materializes the
source's backlink: if the source has unsaved edits, saving re-extracts and
links it (and persists the edits); otherwise the wiki link is added directly
(a no-op re-save wouldn't re-extract). Adds :Heph doc <title> to create a
standalone wiki entry. e2e covers both the saved-source and just-typed-source
paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 11:07:09 -07:00

137 lines
3.9 KiB
Lua

--- The `:Heph <subcommand>` user-command surface. Tactical/Organizational task
--- views (next/list/capture/...) arrive with slice 11b; this is the knowledge-
--- base core (journal, links).
local M = {}
local ATTENTIONS = { "white", "orange", "red", "blue" }
--- subcommand -> handler(args: string[])
M.subs = {
-- knowledge base
today = function()
require("heph.journal").open()
end,
journal = function(args)
require("heph.journal").open(args[1])
end,
follow = function()
require("heph.link").follow()
end,
open = function(args)
if args[1] then
require("heph.node").open(args[1])
end
end,
doc = function(args)
local title = table.concat(args, " ")
if #title == 0 then
require("heph.util").notify("usage: :Heph doc <title>", vim.log.levels.WARN)
return
end
local node = require("heph.rpc").call("node.create", { kind = "doc", title = title, body = "" })
require("heph.node").open(node.id)
end,
search = function(args)
local query = table.concat(args, " ")
if #query == 0 then
require("heph.util").notify("usage: :Heph search <query>", vim.log.levels.WARN)
return
end
local nodes = require("heph.rpc").call("search", { query = query })
require("heph.picker").select(nodes, {
prompt = "heph search: " .. query,
format = function(n)
return string.format("[%s] %s", n.kind, n.title)
end,
}, function(choice)
if choice then
require("heph.node").open(choice.id)
end
end)
end,
-- tasks
next = function(args)
require("heph.view").next({ scope = args[1] })
end,
list = function(args)
require("heph.view").list({ attention = args[1] })
end,
capture = function(args)
local title = table.concat(args, " ")
if #title == 0 then
require("heph.util").notify("usage: :Heph capture <title>", vim.log.levels.WARN)
return
end
require("heph.picker").select(ATTENTIONS, { prompt = "attention for: " .. title }, function(attention)
require("heph.task").capture(title, { attention = attention })
require("heph.util").notify("captured: " .. title)
end)
end,
attention = function(args)
if args[1] then
require("heph.task").set_attention_current(args[1])
else
require("heph.picker").select(ATTENTIONS, { prompt = "attention" }, function(choice)
if choice then
require("heph.task").set_attention_current(choice)
end
end)
end
end,
done = function()
require("heph.task").set_state_current("done")
end,
drop = function()
require("heph.task").set_state_current("dropped")
end,
skip = function()
require("heph.task").skip_current()
end,
promote = function(args)
require("heph.task").promote_under_cursor({ attention = args[1] })
end,
log = function(args)
require("heph.task").log_append_current(table.concat(args, " "))
end,
}
--- `:Heph` entry point.
function M.run(opts)
local args = opts.fargs
local sub = args[1]
if not sub then
require("heph.util").notify("usage: :Heph <" .. table.concat(M.names(), "|") .. ">", vim.log.levels.WARN)
return
end
local handler = M.subs[sub]
if not handler then
require("heph.util").notify("unknown subcommand: " .. sub, vim.log.levels.ERROR)
return
end
local ok, err = pcall(handler, vim.list_slice(args, 2))
if not ok then
require("heph.util").notify(tostring(err), vim.log.levels.ERROR)
end
end
--- Sorted subcommand names.
function M.names()
local names = vim.tbl_keys(M.subs)
table.sort(names)
return names
end
--- Completion: subcommand names at the first position.
function M.complete(arglead, cmdline, _cursorpos)
-- Only complete the subcommand token (first arg after :Heph).
if cmdline:match("^%s*Heph%s+%S*$") then
return vim.tbl_filter(function(n)
return n:find(arglead, 1, true) == 1
end, M.names())
end
return {}
end
return M