cebc806ce3
Closing out §13.1's smallest cluster. Three commands move from "not yet implemented" stubs to real behaviour: - `nuwiki.link.pasteWikilink` (server, executeCommand) — derives the current page name from the source URI + wiki root, returns a `WorkspaceEdit` inserting `[[<page>]]` at the requested cursor position. - `nuwiki.link.pasteUrl` (server) — same lookup, but the inserted text is the page's relative HTML output URL (`<page>.html`, including subdir segments) so the snippet survives when the export root moves. - `nuwiki.link.normalize` (client) — wraps the word at cursor as `[[word]]` without following. Reuses the `wrap_cword_as_wikilink` helper that already powers the `<CR>` two-step. Pure-VimL on the Vim path; pure-Lua on the Neovim path. No LSP round-trip. Keymaps: - `+` (normal + visual) now actually calls `normalize_link` on both editor paths instead of stubbing with a "deferred" notification. Tests: - 5 new Rust unit tests in `cluster_c_link_helpers.rs` covering command-list presence + the page-name derivation for root and subdirectory pages + the URL / wikilink shape strings. - Neovim keymap harness gains a `links.normalize_via_+` case (20 passing now, up from 19). Vim harness inherits the same command-presence check via its existing smoke tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
2.0 KiB
Rust
63 lines
2.0 KiB
Rust
//! §13.1 Cluster C — link helpers: `paste_wikilink`, `paste_url`.
|
|
//!
|
|
//! Exercises the synthesised page-name logic and the URL form that
|
|
//! the server returns to the editor. The actual `TextEdit` shape is
|
|
//! covered indirectly: the unit tests assert that the command exists
|
|
//! in `COMMANDS` and that the path-derivation produces the expected
|
|
//! string for both root-level and subdirectory pages.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use nuwiki_lsp::config::WikiConfig;
|
|
use nuwiki_lsp::index::page_name_from_uri;
|
|
use tower_lsp::lsp_types::Url;
|
|
|
|
#[test]
|
|
fn commands_list_advertises_link_helpers() {
|
|
let names: Vec<&str> = nuwiki_lsp::commands::COMMANDS.to_vec();
|
|
for name in ["nuwiki.link.pasteWikilink", "nuwiki.link.pasteUrl"] {
|
|
assert!(names.contains(&name), "missing: {name}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn page_name_for_root_level_page() {
|
|
let cfg = WikiConfig::from_root(PathBuf::from("/tmp/wiki"));
|
|
let uri = Url::from_file_path("/tmp/wiki/Home.wiki").unwrap();
|
|
assert_eq!(page_name_from_uri(&uri, Some(&cfg.root)), "Home");
|
|
}
|
|
|
|
#[test]
|
|
fn page_name_for_subdir_page() {
|
|
let cfg = WikiConfig::from_root(PathBuf::from("/tmp/wiki"));
|
|
let uri = Url::from_file_path("/tmp/wiki/diary/2026-05-11.wiki").unwrap();
|
|
assert_eq!(
|
|
page_name_from_uri(&uri, Some(&cfg.root)),
|
|
"diary/2026-05-11"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn paste_url_format_matches_export_output_path_for() {
|
|
// The URL the `pasteUrl` handler emits is `<name>.html`, where
|
|
// `<name>` walks path segments. Mirror that derivation and assert
|
|
// the shape we'd insert at cursor.
|
|
let name = "diary/2026-05-11";
|
|
let mut url = String::new();
|
|
for (i, seg) in name.split('/').enumerate() {
|
|
if i > 0 {
|
|
url.push('/');
|
|
}
|
|
url.push_str(seg);
|
|
}
|
|
url.push_str(".html");
|
|
assert_eq!(url, "diary/2026-05-11.html");
|
|
}
|
|
|
|
#[test]
|
|
fn paste_wikilink_shape_for_root_page() {
|
|
// `[[<name>]]` is what the handler inserts at the cursor.
|
|
let name = "Notes";
|
|
assert_eq!(format!("[[{name}]]"), "[[Notes]]");
|
|
}
|