generated from eblume/project-template
feat: node.linkable — first-class link targets for the [[ picker (§8.4)
Some checks failed
Build / validate (pull_request) Failing after 8s
Some checks failed
Build / validate (pull_request) Failing after 8s
The picker listed every node, so each task showed up twice (itself + its same-titled canonical-context doc) plus tag/log noise — and the new preview made the duplicates look identical. New `Store::list_linkable_nodes` / `node.linkable` returns non-tombstoned nodes minus `tag`s and the docs that are a task's canonical-context or log attachment (you link the task, not its body). The Telescope picker now sources from it. Tests: a socket test (5 nodes → 2 linkable: task + standalone doc). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1737f8c266
commit
2fc48a1aa9
9 changed files with 57 additions and 3 deletions
|
|
@ -289,6 +289,10 @@ impl Store for LocalStore {
|
|||
nodes::list(&self.conn, &self.owner_id, kind)
|
||||
}
|
||||
|
||||
fn list_linkable_nodes(&self) -> Result<Vec<Node>> {
|
||||
nodes::list_linkable(&self.conn, &self.owner_id)
|
||||
}
|
||||
|
||||
fn journal_open_or_create(&mut self, date: &str) -> Result<Node> {
|
||||
let now = self.clock.now_ms();
|
||||
nodes::open_or_create_journal(&self.conn, &self.owner_id, now, date)
|
||||
|
|
|
|||
|
|
@ -407,6 +407,23 @@ pub(super) fn list(conn: &Connection, owner: &str, kind: Option<NodeKind>) -> Re
|
|||
Ok(rows.collect::<rusqlite::Result<Vec<_>>>()?)
|
||||
}
|
||||
|
||||
/// First-class wiki-link targets (tech-spec §8.4): non-tombstoned nodes, minus
|
||||
/// the internal noise — `tag` nodes, and the `doc` nodes that are a task's
|
||||
/// **canonical-context** or **log** attachment (you link the task, not its
|
||||
/// auto-created body/log). Title-sorted, for the `[[` picker.
|
||||
pub(super) fn list_linkable(conn: &Connection, owner: &str) -> Result<Vec<Node>> {
|
||||
let sql = format!(
|
||||
"SELECT {COLUMNS} FROM nodes
|
||||
WHERE owner_id = ?1 AND tombstoned = 0 AND kind != 'tag'
|
||||
AND id NOT IN (SELECT dst_id FROM links
|
||||
WHERE type IN ('canonical-context', 'log-of') AND tombstoned = 0)
|
||||
ORDER BY title COLLATE NOCASE"
|
||||
);
|
||||
let mut stmt = conn.prepare(&sql)?;
|
||||
let rows = stmt.query_map([owner], from_row)?;
|
||||
Ok(rows.collect::<rusqlite::Result<Vec<_>>>()?)
|
||||
}
|
||||
|
||||
/// A node's aliases (wiki-link names), sorted. Empty until aliases are written.
|
||||
pub(super) fn aliases(conn: &Connection, id: &str) -> Result<Vec<String>> {
|
||||
let mut stmt = conn.prepare("SELECT alias FROM aliases WHERE node_id = ?1 ORDER BY alias")?;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ pub trait Store {
|
|||
/// (tech-spec §6 `node.list`).
|
||||
fn list_nodes(&self, kind: Option<NodeKind>) -> Result<Vec<Node>>;
|
||||
|
||||
/// First-class wiki-link targets (tech-spec §8.4): non-tombstoned nodes
|
||||
/// minus the internal noise — `tag` nodes and the `doc`s that are a task's
|
||||
/// canonical-context or log attachment. Backs the `[[` picker.
|
||||
fn list_linkable_nodes(&self) -> Result<Vec<Node>>;
|
||||
|
||||
/// Resolve a wiki-link target (`[[title]]`) to a node, **exactly** — an
|
||||
/// alias match first, then an exact, owner-scoped, non-tombstoned title
|
||||
/// match; `None` if nothing matches (an unresolved link is allowed, §5).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue