WIP improvise-6p8q: yank of a coordinate/creating column
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::model::Aggregation;
|
||||
use crate::model::cell::{CellKey, CellValue};
|
||||
use crate::view::synthetic_record_info;
|
||||
use crate::ui::effect::{self, Effect, ViewTarget};
|
||||
use crate::view::synthetic_record_info;
|
||||
|
||||
use super::core::{Cmd, CmdContext};
|
||||
|
||||
@@ -151,7 +151,10 @@ mod tests {
|
||||
fn yy_then_p_in_records_mode_copies_between_real_records() {
|
||||
let mut app = records_app();
|
||||
let (east, west) = (0, 1);
|
||||
assert_eq!(app.layout.record_row(west).unwrap().coords.get("Region"), Some("West"));
|
||||
assert_eq!(
|
||||
app.layout.record_row(west).unwrap().coords.get("Region"),
|
||||
Some("West")
|
||||
);
|
||||
|
||||
app.cursor_mut().selected = (east, col_of(&app, "Cost"));
|
||||
press(&mut app, 'y');
|
||||
@@ -190,6 +193,23 @@ mod tests {
|
||||
assert_eq!(synthetic_cells(&reloaded), Vec::<CellKey>::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yy_on_a_records_coordinate_or_creating_column_yanks_what_is_drawn() {
|
||||
let mut app = records_app();
|
||||
app.view_state.yanked = Some(CellValue::Number(5.5));
|
||||
app.cursor_mut().selected = (1, col_of(&app, "Region"));
|
||||
press(&mut app, 'y');
|
||||
press(&mut app, 'y');
|
||||
assert_eq!(app.view_state.yanked, Some(CellValue::Text("West".into())));
|
||||
app.cursor_mut().selected = (1, col_of(&app, "+"));
|
||||
press(&mut app, 'y');
|
||||
press(&mut app, 'y');
|
||||
assert_eq!(
|
||||
app.view_state.yanked, None,
|
||||
"a blank creating column yanks nothing, as an empty pivot cell does"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn p_on_a_records_column_that_stores_no_value_changes_nothing() {
|
||||
for label in ["Region", "+cat", "+"] {
|
||||
@@ -214,7 +234,10 @@ mod tests {
|
||||
app.cursor_mut().selected = (1, col_of(&app, "Revenue"));
|
||||
press(&mut app, 'p');
|
||||
assert_eq!(
|
||||
app.model_state.workbook.model.get_cell(&record("West", "Revenue")),
|
||||
app.model_state
|
||||
.workbook
|
||||
.model
|
||||
.get_cell(&record("West", "Revenue")),
|
||||
Some(&CellValue::Number(5.5)),
|
||||
"the control never wrote, so the declines above prove nothing"
|
||||
);
|
||||
@@ -238,12 +261,18 @@ mod tests {
|
||||
app.view_state.yanked = Some(CellValue::Number(5.5));
|
||||
app.cursor_mut().selected = (0, col_of(&app, "Cost"));
|
||||
press(&mut app, 'p');
|
||||
assert_eq!(crate::persistence::format_md(&app.model_state.workbook), before);
|
||||
assert_eq!(
|
||||
crate::persistence::format_md(&app.model_state.workbook),
|
||||
before
|
||||
);
|
||||
assert!(
|
||||
app.drill_state.as_ref().unwrap().pending_edits.is_empty(),
|
||||
"a paste was staged as text, which loses the value's type"
|
||||
);
|
||||
assert_eq!(synthetic_cells(&app.model_state.workbook), Vec::<CellKey>::new());
|
||||
assert_eq!(
|
||||
synthetic_cells(&app.model_state.workbook),
|
||||
Vec::<CellKey>::new()
|
||||
);
|
||||
assert!(!app.view_state.status_msg.is_empty(), "declined silently");
|
||||
}
|
||||
|
||||
@@ -257,7 +286,8 @@ mod tests {
|
||||
wb.add_item("Product", "Widget").unwrap();
|
||||
wb.add_item("Product", "Gadget").unwrap();
|
||||
wb.add_item("_Measure", "Revenue").unwrap();
|
||||
wb.active_view_mut().set_axis("Region", crate::view::Axis::Row);
|
||||
wb.active_view_mut()
|
||||
.set_axis("Region", crate::view::Axis::Row);
|
||||
wb.active_view_mut()
|
||||
.set_axis("_Measure", crate::view::Axis::Column);
|
||||
wb.active_view_mut().set_axis("Product", product_axis);
|
||||
@@ -287,9 +317,10 @@ mod tests {
|
||||
let mut app = aggregated_app(crate::view::Axis::Page);
|
||||
press(&mut app, 'p');
|
||||
assert_eq!(
|
||||
app.model_state.workbook.model.get_cell(
|
||||
&record("West", "Revenue").with("Product", "Widget")
|
||||
),
|
||||
app.model_state
|
||||
.workbook
|
||||
.model
|
||||
.get_cell(&record("West", "Revenue").with("Product", "Widget")),
|
||||
Some(&CellValue::Number(5.5))
|
||||
);
|
||||
}
|
||||
@@ -411,7 +442,12 @@ fn paste_into(ctx: &CmdContext, key: &CellKey, value: CellValue) -> Box<dyn Effe
|
||||
}
|
||||
}
|
||||
|
||||
fn paste_into_record(ctx: &CmdContext, row: usize, col: usize, value: CellValue) -> Box<dyn Effect> {
|
||||
fn paste_into_record(
|
||||
ctx: &CmdContext,
|
||||
row: usize,
|
||||
col: usize,
|
||||
value: CellValue,
|
||||
) -> Box<dyn Effect> {
|
||||
match (ctx.layout.record_cell_key(row, col), ctx.has_drill_state) {
|
||||
(Some(_), true) => effect::set_status(PASTE_INSIDE_DRILL),
|
||||
(Some(real), false) => Box::new(effect::SetCell(real, value)),
|
||||
@@ -422,11 +458,7 @@ fn paste_into_record(ctx: &CmdContext, row: usize, col: usize, value: CellValue)
|
||||
/// Whether `key` leaves out a regular category the layout aggregates over.
|
||||
fn aggregates(ctx: &CmdContext, key: &CellKey) -> bool {
|
||||
ctx.none_cats().iter().any(|cat| {
|
||||
key.get(cat).is_none()
|
||||
&& ctx
|
||||
.model
|
||||
.category(cat)
|
||||
.is_some_and(|c| c.kind.is_regular())
|
||||
key.get(cat).is_none() && ctx.model.category(cat).is_some_and(|c| c.kind.is_regular())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -434,7 +466,8 @@ fn is_blank(value: &CellValue) -> bool {
|
||||
matches!(value, CellValue::Text(text) if text.is_empty())
|
||||
}
|
||||
|
||||
const PASTE_ONTO_AGGREGATE: &str = "Cannot paste onto an aggregate — drill in to paste into a record";
|
||||
const PASTE_ONTO_AGGREGATE: &str =
|
||||
"Cannot paste onto an aggregate — drill in to paste into a record";
|
||||
const PASTE_ONTO_NO_VALUE: &str = "Paste lands only on a measure column";
|
||||
const PASTE_INSIDE_DRILL: &str = "Paste is not staged inside a drill — edit the cell instead";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user