Files
nuwiki/crates/nuwiki-lsp/src/commands.rs
T

52 lines
1.9 KiB
Rust
Raw Normal View History

//! `workspace/executeCommand` dispatcher.
//!
//! Phase 13 lands the router + the first command. Phases 1417 register
//! their own commands here. Each handler returns the `WorkspaceEdit` it
//! wants applied; the `Backend` calls `client.apply_edit` after the call.
//!
//! Phase 13 surface:
//! - `nuwiki.file.delete` — args: `{ "uri": <Url> }`
use serde::Deserialize;
use tower_lsp::lsp_types::{Url, WorkspaceEdit};
use crate::edits::{op_delete, WorkspaceEditBuilder};
use crate::Backend;
/// All commands the server advertises in `ExecuteCommandOptions.commands`.
/// Keep this in lock-step with the match arms in `execute` below — adding
/// here without a handler will fail at runtime; adding a handler without
/// listing here means the client won't see it as available.
pub const COMMANDS: &[&str] = &["nuwiki.file.delete"];
/// Dispatch an `executeCommand` request. Returns `Ok(None)` for commands
/// that don't produce a `WorkspaceEdit` (e.g. read-only queries); returns
/// `Err` with a human-readable message for unknown commands or bad args
/// — the LSP backend logs it and returns `null` to the client.
pub(crate) async fn execute(
_backend: &Backend,
command: &str,
args: Vec<serde_json::Value>,
) -> Result<Option<WorkspaceEdit>, String> {
match command {
"nuwiki.file.delete" => file_delete(args),
other => Err(format!("unknown nuwiki command: {other}")),
}
}
fn file_delete(args: Vec<serde_json::Value>) -> Result<Option<WorkspaceEdit>, String> {
#[derive(Deserialize)]
struct Args {
uri: Url,
}
let raw = args
.into_iter()
.next()
.ok_or_else(|| "nuwiki.file.delete: missing arguments".to_string())?;
let parsed: Args = serde_json::from_value(raw)
.map_err(|e| format!("nuwiki.file.delete: invalid args — {e}"))?;
let mut builder = WorkspaceEditBuilder::new();
builder.file_op(op_delete(parsed.uri));
Ok(Some(builder.build()))
}