feat(nvim-core): implement nvim_set_extmark for rich virtual text UI feedback
- Added nvim_set_extmark tool schema and handler - Implemented lua bridge using vim.api.nvim_buf_set_extmark to dynamically overlay ghost text and highlight groups onto active buffers
This commit is contained in:
1 parent
ea735003e2
commit
6a89f50cf2
1 file changed
+60
@@ -510,6 +510,31 @@ async fn set_nvim_diagnostics(line: i64, message: &str) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_nvim_extmark(line: i64, text: &str, hl_group: &str) -> Result<(), String> {
|
||||
let escaped_text = text.replace('\\', "\\\\").replace('"', "\\\"");
|
||||
let lua_script = format!(
|
||||
r#"
|
||||
local ns = vim.api.nvim_create_namespace("gemini_extmarks")
|
||||
local opts = {{
|
||||
virt_text = {{{{"{escaped_text}", "{hl_group}"}}}},
|
||||
virt_text_pos = "eol",
|
||||
}}
|
||||
vim.api.nvim_buf_set_extmark(0, ns, {line} - 1, 0, opts)
|
||||
"#
|
||||
);
|
||||
|
||||
call_nvim_method(
|
||||
"nvim_exec_lua",
|
||||
vec![
|
||||
rmpv::Value::String(lua_script.into()),
|
||||
rmpv::Value::Array(vec![]),
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rmpv_to_json(val: &rmpv::Value) -> serde_json::Value {
|
||||
match val {
|
||||
rmpv::Value::Nil => serde_json::Value::Null,
|
||||
@@ -731,6 +756,19 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
"required": ["line", "message"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_set_extmark",
|
||||
"description": "Add virtual text (ghost text) to a specific line in the buffer to give the user rich UI feedback",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"line": { "type": "integer" },
|
||||
"text": { "type": "string" },
|
||||
"highlight_group": { "type": "string", "description": "Optional. E.g., 'DiagnosticVirtualTextInfo', 'Comment'" }
|
||||
},
|
||||
"required": ["line", "text"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_list_buffers",
|
||||
"description": "List all open buffers in Neovim",
|
||||
@@ -952,6 +990,28 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
send_error(id, -32602, "Missing 'line' or 'message'").await;
|
||||
}
|
||||
}
|
||||
"nvim_set_extmark" => {
|
||||
if let (Some(line), Some(text)) = (
|
||||
args.get("line").and_then(serde_json::Value::as_i64),
|
||||
args.get("text").and_then(|v| v.as_str()),
|
||||
) {
|
||||
let hl_group = args
|
||||
.get("highlight_group")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("Comment");
|
||||
match set_nvim_extmark(line, text, hl_group).await {
|
||||
Ok(()) => {
|
||||
send_text_result!(
|
||||
id.clone(),
|
||||
format!("Successfully set extmark on line {}", line)
|
||||
);
|
||||
}
|
||||
Err(e) => send_error(id, -32603, &e).await,
|
||||
}
|
||||
} else {
|
||||
send_error(id, -32602, "Missing 'line' or 'text'").await;
|
||||
}
|
||||
}
|
||||
"nvim_list_buffers" => {
|
||||
let lua_code = r"
|
||||
local bufs = vim.api.nvim_list_bufs()
|
||||
|
||||
Reference in new issue
Block a user