feat(generate): insert links/tags sections at the cursor line too
CI / cargo fmt --check (push) Successful in 28s
CI / cargo clippy (push) Successful in 36s
CI / cargo test (push) Successful in 40s
CI / editor keymaps (push) Successful in 1m26s

Extend the cursor-line insertion from :NuwikiTOC to the other buffer
list generators: :NuwikiGenerateLinks and :NuwikiGenerateTagLinks. They
appended at end-of-file; a fresh section now goes at the cursor line
(with a leading blank), matching :NuwikiTOC. An existing section is still
refreshed in place, and the auto_generate_*-on-save hooks are unaffected
(they only ever replace).

Shared section_insert() helper computes the insert position/block for all
three (cursor line clamped to the document, else the per-command fallback:
top of file for TOC, EOF for links/tags). Clients send the 0-based cursor
line; handlers parse it via parse_uri_line_arg and thread it through
links_edit / tag_links_edit. Rebuild variants pass None.

Tests: links_edit_inserts_at_cursor_line + tag_links_edit_inserts_at_cursor_line.
577 passed, clippy clean, keymap harnesses green. Docs updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 01:07:18 +00:00
parent 94cb58064d
commit f0c51fbfcc
7 changed files with 180 additions and 55 deletions
+3 -1
View File
@@ -348,6 +348,7 @@ fn nuwiki_generate_links_lists_all_pages_excluding_current() {
"Generated Links",
1,
0,
None,
None
)
.is_some());
@@ -430,7 +431,8 @@ fn nuwiki_generate_tag_links_builds_section() {
true,
"Generated Tags",
1,
0
0,
None
)
.is_some());
}
+48 -3
View File
@@ -255,6 +255,7 @@ fn tag_links_edit_inserts_when_section_missing() {
"Generated Tags",
1,
0,
None,
)
.expect("got an edit");
let te = &edit.changes.unwrap()[&uri][0];
@@ -264,6 +265,37 @@ fn tag_links_edit_inserts_when_section_missing() {
assert!(te.new_text.contains("[[Alpha]]"));
}
#[test]
fn tag_links_edit_inserts_at_cursor_line() {
// A fresh tags section goes at the cursor line, not the EOF.
let src = "= Notes =\nbody\nmore\n";
let ast = parse(src);
let uri = Url::parse("file:///tmp/p.wiki").unwrap();
let mut snap = BTreeMap::new();
snap.insert("release".to_string(), vec!["Alpha".into()]);
let edit = ops::tag_links_edit(
src,
&ast,
&uri,
Some("release"),
&snap,
true,
"Generated Tags",
1,
0,
Some(1),
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
assert_eq!(te.range.start.line, 1);
assert_eq!(te.range.start.character, 0);
assert!(
te.new_text.starts_with("\n= Tag: release ="),
"got: {:?}",
te.new_text
);
}
#[test]
fn tag_links_edit_replaces_existing_section() {
let src = "= Tag: release =\n- [[Stale]]\n\n= Other =\n";
@@ -281,6 +313,7 @@ fn tag_links_edit_replaces_existing_section() {
"Generated Tags",
1,
0,
None,
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
@@ -296,8 +329,19 @@ fn tag_links_edit_full_index_replaces_existing_tags_section() {
let uri = Url::parse("file:///tmp/p.wiki").unwrap();
let mut snap = BTreeMap::new();
snap.insert("alpha".to_string(), vec!["P".into()]);
let edit = ops::tag_links_edit(src, &ast, &uri, None, &snap, true, "Generated Tags", 1, 0)
.expect("edit");
let edit = ops::tag_links_edit(
src,
&ast,
&uri,
None,
&snap,
true,
"Generated Tags",
1,
0,
None,
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
assert!(te.new_text.contains("== alpha =="));
assert!(!te.new_text.contains("[[old]]"));
@@ -352,7 +396,8 @@ fn tag_links_edit_returns_none_for_unknown_tag() {
true,
"Generated Tags",
1,
0
0,
None
)
.is_none());
}
+34
View File
@@ -597,6 +597,7 @@ fn links_edit_inserts_when_section_absent() {
1,
0,
None,
None,
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
@@ -605,6 +606,37 @@ fn links_edit_inserts_when_section_absent() {
assert!(!te.new_text.contains("[[Home]]"));
}
#[test]
fn links_edit_inserts_at_cursor_line() {
// A fresh Generated Links section goes at the cursor line, not the EOF.
let src = "= Home =\nbody\nmore\n";
let ast = parse(src);
let uri = Url::parse("file:///tmp/page.wiki").unwrap();
let pages = vec!["A".into()];
let edit = ops::links_edit(
src,
&ast,
&uri,
"Home",
&pages,
true,
"Generated Links",
1,
0,
None,
Some(1),
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
assert_eq!(te.range.start.line, 1);
assert_eq!(te.range.start.character, 0);
assert!(
te.new_text.starts_with("\n= Generated Links ="),
"got: {:?}",
te.new_text
);
}
#[test]
fn links_edit_replaces_when_section_present() {
let src = "= Generated Links =\n- [[Stale]]\n\n= Real =\n";
@@ -622,6 +654,7 @@ fn links_edit_replaces_when_section_present() {
1,
0,
None,
None,
)
.expect("edit");
let te = &edit.changes.unwrap()[&uri][0];
@@ -645,6 +678,7 @@ fn links_edit_returns_none_for_empty_page_list() {
"Generated Links",
1,
0,
None,
None
)
.is_none());