Variables: Edit Data Set's Name field renames the data set

Squashed from #5121 onto main.
This commit is contained in:
dotCooCoo
2026-11-02 12:04:22 +07:00
committed by bflatastic
parent 899a4c2bcb
commit ab0072a39e
4 changed files with 125 additions and 7 deletions
+20 -4
View File
@@ -400,18 +400,34 @@ fn dataset_new(s: &mut Session, p: &Value) -> Result<Value> {
}
/// Replace a dataset's values. A variable left out of `values` loses its value in this row,
/// so the dataset ends up holding exactly what the call asked for.
/// so the dataset ends up holding exactly what the call asked for. With `newName` the row is
/// also renamed, in the same undo step, as `dataset.rename` would rename it.
fn dataset_set(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "dataset.set";
let name = var_name(p, C)?;
let values = values_param(&s.doc()?.doc.variables, p, C)?;
let to = match p.get("newName") {
None | Some(Value::Null) => name.clone(),
Some(v) => named(v.as_str(), "newName", C)?,
};
let st = s.doc()?;
if st.doc.variables.dataset(&name).is_none() {
return Err(bad(C, format!("no dataset named `{name}`")));
}
if to != name && st.doc.variables.dataset(&to).is_some() {
return Err(bad(C, format!("dataset `{to}` already exists")));
}
let values = values_param(&st.doc.variables, p, C)?;
let (set, removed) = edit_variables(s, "Edit Data Set", |v| {
let ds = v.datasets.iter_mut().find(|x| x.name == name).ok_or_else(|| bad(C, format!("no dataset named `{name}`")))?;
let removed: Vec<String> = ds.values.keys().filter(|k| !values.contains_key(*k)).cloned().collect();
ds.values = values.clone();
ds.name = to.clone();
if v.active_dataset.as_deref() == Some(name.as_str()) {
v.active_dataset = Some(to.clone());
}
Ok((values.len(), removed))
})?;
Ok(json!({"name": name, "values": set, "removed": removed}))
Ok(json!({"name": to, "values": set, "removed": removed}))
}
fn dataset_rename(s: &mut Session, p: &Value) -> Result<Value> {
@@ -736,7 +752,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Edit Data Set…",
["Window", "Variables"],
None,
"{name, values?: {variable: value}} replace a dataset's values; a variable left out loses its value in this row → {values, removed}",
"{name, newName?, values?: {variable: value}} replace a dataset's values; a variable left out loses its value in this row. `newName` also renames the dataset in the same undo step, refused when another dataset has that name → {name, values, removed}",
has_doc,
dataset_set
),
+31
View File
@@ -851,6 +851,37 @@ fn dataset_set_replaces_the_row_and_reports_what_it_dropped() {
assert_eq!(plain(&s, t), "z");
}
/// `newName` renames the row in the same step as its values change, and keeps it active.
#[test]
fn dataset_set_with_a_new_name_renames_the_row() {
let mut s = session();
s.execute("variable.define", &json!({"name": "Name", "kind": "text"})).unwrap();
s.execute("dataset.new", &json!({"name": "D", "values": {"Name": "y"}})).unwrap();
s.execute("dataset.new", &json!({"name": "E", "values": {"Name": "e"}})).unwrap();
s.execute("dataset.select", &json!({"name": "D"})).unwrap();
let undo = s.doc().unwrap().history.undo.len();
let v = s.execute("dataset.set", &json!({"name": "D", "newName": "Spring", "values": {"Name": "z"}})).unwrap();
assert_eq!(v["name"], "Spring");
let sets = s.execute("dataset.list", &json!({})).unwrap();
assert_eq!((sets["datasets"][0]["name"].clone(), sets["active"].clone()), (json!("Spring"), json!("Spring")));
assert_eq!(sets["datasets"][0]["values"], json!({"Name": {"text": "z"}}));
assert_eq!(s.doc().unwrap().history.undo.len(), undo + 1, "one undo step");
// Its own name is no rename; another row's name, or an empty one, is refused and changes nothing.
s.execute("dataset.set", &json!({"name": "Spring", "newName": "Spring", "values": {"Name": "z"}})).unwrap();
for bad in [json!("E"), json!(""), json!(3)] {
assert!(s.execute("dataset.set", &json!({"name": "Spring", "newName": bad, "values": {"Name": "x"}})).is_err(), "{bad}");
}
let sets = s.execute("dataset.list", &json!({})).unwrap();
assert_eq!(sets["datasets"][0]["values"], json!({"Name": {"text": "z"}}));
assert_eq!(sets["datasets"][1]["values"], json!({"Name": {"text": "e"}}));
s.execute("edit.undo", &json!({})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(s.execute("dataset.list", &json!({})).unwrap()["active"], "D", "undo puts the name back");
}
#[test]
fn bad_variables_requests_are_errors_not_panics() {
let mut s = session();