diff --git a/crates/engine/src/cmd/edit.rs b/crates/engine/src/cmd/edit.rs index 74fb504..102c669 100644 --- a/crates/engine/src/cmd/edit.rs +++ b/crates/engine/src/cmd/edit.rs @@ -219,11 +219,8 @@ fn cell_set(s: &mut Session, p: &Json) -> Result { Some(c) => c, None => s.doc()?.selection.active, }; - let input = str_param(p, "input") - .or_else(|| str_param(p, "value")) - .map(str::to_string) - .or_else(|| p.get("value").map(json_to_input)) - .ok_or_else(|| bad("cell.set", "missing `input` (or `value`)"))?; + // Both spellings take a string, number or boolean, as typed (#697). + let input = p.get("input").or_else(|| p.get("value")).map(json_to_input).ok_or_else(|| bad("cell.set", "missing `input` (or `value`)"))?; let array = bool_param(p, "array").unwrap_or(false); let d = s.doc()?; if let Some(sh) = d.wb.sheet(sheet) @@ -1597,6 +1594,23 @@ fn begin_edit(s: &mut Session, _: &Json) -> Result { mod tests { use super::*; + #[test] + fn cell_set_takes_numbers_for_input_and_value() { + // #697: a JSON number for `input` used to clear the cell instead of entering it. + let mut s = Session::new(); + s.new_workbook(); + s.execute("cell.set", json!({"cell": "A1", "input": 123.5})).unwrap(); + s.execute("cell.set", json!({"cell": "A2", "value": 77})).unwrap(); + s.execute("cell.set", json!({"cell": "A3", "input": true})).unwrap(); + s.execute("cell.set", json!({"cell": "A4", "input": "=A1+A2"})).unwrap(); + let get = |s: &mut Session, a: &str| s.execute("cell.get", json!({"cell": a})).unwrap(); + assert_eq!(get(&mut s, "A1")["value"], json!(123.5)); + assert_eq!(get(&mut s, "A2")["value"], json!(77.0)); + assert_eq!(get(&mut s, "A3")["value"], json!(true)); + assert_eq!(get(&mut s, "A4")["value"], json!(200.5)); + assert!(s.execute("cell.set", json!({"cell": "A5"})).is_err()); + } + #[test] fn legacy_array_entry() { let mut s = Session::new(); diff --git a/crates/mcp/src/tests.rs b/crates/mcp/src/tests.rs index ccb9c0f..de6bbc6 100644 --- a/crates/mcp/src/tests.rs +++ b/crates/mcp/src/tests.rs @@ -202,6 +202,9 @@ fn basic_tools() { assert!(f.as_array().unwrap().iter().any(|x| x["name"] == "VLOOKUP")); assert_eq!(ok(&mut s, "evaluate_formula", json!({"formula": "SUM(1,2,3)"}))["result"], json!(6.0)); ok(&mut s, "set_cell", json!({"cell": "A1", "input": "5"})); + // #697: a number for `input` is entered, not rejected or cleared. + ok(&mut s, "set_cell", json!({"cell": "B1", "input": 42.5})); + assert_eq!(ok(&mut s, "get_cell", json!({"cell": "B1"}))["value"], json!(42.5)); ok(&mut s, "execute_command", json!({"command": "cell.set", "params": {"cell": "A2", "input": "=A1*2"}})); assert_eq!(ok(&mut s, "get_cell", json!({"cell": "A2"}))["value"], json!(10.0)); assert_eq!(ok(&mut s, "evaluate_formula", json!({"formula": "=A1+A2", "cell": "C1"}))["result"], json!(15.0)); diff --git a/crates/mcp/src/tools.rs b/crates/mcp/src/tools.rs index 71fbdf4..e6322f0 100644 --- a/crates/mcp/src/tools.rs +++ b/crates/mcp/src/tools.rs @@ -180,7 +180,7 @@ pub fn tool_definitions() -> Vec { "Enter one cell exactly as if typed: a number, text, or a formula starting with = (\"=AVERAGE(B2:B9)\"). \ Dependent cells recalculate. Returns the command result; use get_cell to read the computed value.", obj( - json!({"cell": string("Cell, e.g. \"B7\" or \"Sheet2!C3\""), "input": string("Typed input: number, text or =formula")}), + json!({"cell": string("Cell, e.g. \"B7\" or \"Sheet2!C3\""), "input": {"type": ["string", "number", "boolean"], "description": "Typed input: number, text or =formula"}}), &["cell", "input"], ), false,