WIP: project the evaluated value; yank copies it
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:
@@ -282,6 +282,7 @@ fn cell_display(
|
|||||||
numeric: matches!(value, Some(CellValue::Number(_))),
|
numeric: matches!(value, Some(CellValue::Number(_))),
|
||||||
error: matches!(value, Some(CellValue::Error(_))),
|
error: matches!(value, Some(CellValue::Error(_))),
|
||||||
id: cell_id(app, layout, row, col),
|
id: cell_id(app, layout, row, col),
|
||||||
|
value: value.clone(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let key = layout.cell_key(row, col);
|
let key = layout.cell_key(row, col);
|
||||||
@@ -293,6 +294,7 @@ fn cell_display(
|
|||||||
// The *unformatted* value the TUI seeds its edit buffer from. Projecting it
|
// The *unformatted* value the TUI seeds its edit buffer from. Projecting it
|
||||||
// beats a client un-formatting `text` (gotcha 47).
|
// beats a client un-formatting `text` (gotcha 47).
|
||||||
edit_text: key.map(|key| app.display_value_in(layout, &key)),
|
edit_text: key.map(|key| app.display_value_in(layout, &key)),
|
||||||
|
value: value.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
|
use improvise_core::model::cell::CellValue;
|
||||||
use improvise_core::model::record::{AggregateHash, RecordHash};
|
use improvise_core::model::record::{AggregateHash, RecordHash};
|
||||||
use improvise_core::view::Axis;
|
use improvise_core::view::Axis;
|
||||||
use improvise_core::view::layout::PageAxis;
|
use improvise_core::view::layout::PageAxis;
|
||||||
@@ -64,9 +65,9 @@ pub enum CreateKind {
|
|||||||
Category,
|
Category,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// One cell as the client draws it. Deliberately not a `CellValue` — the
|
/// One cell as the client draws it. Drawn from `text`, never from `value` — the
|
||||||
/// formatting has already happened, and re-deriving it is how ends drift.
|
/// formatting has already happened, and re-deriving it is how ends drift.
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct CellDisplay {
|
pub struct CellDisplay {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
/// Right-align numerics, left-align text — decided by the server, which
|
/// Right-align numerics, left-align text — decided by the server, which
|
||||||
@@ -80,6 +81,9 @@ pub struct CellDisplay {
|
|||||||
/// What an editor should start with — the value as the user last
|
/// What an editor should start with — the value as the user last
|
||||||
/// **typed** it, not as it is drawn. The difference corrupts data (§3).
|
/// **typed** it, not as it is drawn. The difference corrupts data (§3).
|
||||||
pub edit_text: Option<String>,
|
pub edit_text: Option<String>,
|
||||||
|
/// The value the host evaluated here, unrounded and untyped-by-text: what
|
||||||
|
/// `yank` copies. Neither `text` nor `edit_text` can be re-parsed into it (§3).
|
||||||
|
pub value: Option<CellValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CellDisplay {
|
impl CellDisplay {
|
||||||
@@ -98,6 +102,7 @@ impl CellDisplay {
|
|||||||
numeric: true,
|
numeric: true,
|
||||||
error: false,
|
error: false,
|
||||||
id: None,
|
id: None,
|
||||||
|
value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +115,7 @@ impl CellDisplay {
|
|||||||
error: true,
|
error: true,
|
||||||
id: None,
|
id: None,
|
||||||
edit_text: None,
|
edit_text: None,
|
||||||
|
value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,7 +422,7 @@ fn shows(items: &[&Vec<String>], idx: usize, first_rendered: usize, level: usize
|
|||||||
|
|
||||||
/// The grid widget's copy of the visible cells (improvise-n10), indexed by
|
/// The grid widget's copy of the visible cells (improvise-n10), indexed by
|
||||||
/// position within the **viewport** and never by `CellKey`.
|
/// position within the **viewport** and never by `CellKey`.
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct GridCache {
|
pub struct GridCache {
|
||||||
/// The row axis's frame: levels, label tuples and groups. **Not** a list
|
/// The row axis's frame: levels, label tuples and groups. **Not** a list
|
||||||
/// of strings — see [`AxisFrame`].
|
/// of strings — see [`AxisFrame`].
|
||||||
@@ -563,7 +569,7 @@ enum LabelAxis {
|
|||||||
|
|
||||||
/// What can change about the grid: cell values, the frames that name them,
|
/// What can change about the grid: cell values, the frames that name them,
|
||||||
/// the widths, the totals, the page bar and the extent.
|
/// the widths, the totals, the page bar and the extent.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GridUpdate {
|
pub enum GridUpdate {
|
||||||
/// Display values for cells, by viewport position.
|
/// Display values for cells, by viewport position.
|
||||||
Cells(Vec<((usize, usize), CellDisplay)>),
|
Cells(Vec<((usize, usize), CellDisplay)>),
|
||||||
|
|||||||
@@ -530,12 +530,10 @@ fn composed(
|
|||||||
state,
|
state,
|
||||||
ModelCommand::ClearCell(record_cell_at_cursor(state)?),
|
ModelCommand::ClearCell(record_cell_at_cursor(state)?),
|
||||||
)?]),
|
)?]),
|
||||||
// `YankCell::execute`: the value, then the status. `edit_text` is
|
// `YankCell::execute`: the value, then the status. The projected
|
||||||
// what the host evaluated, which is what the TUI yanks.
|
// value, never text re-parsed: improvise-dsxq.
|
||||||
"yank" => Some(vec![
|
"yank" => Some(vec![
|
||||||
Command::SetYanked(typed(
|
Command::SetYanked(cell_at_cursor(state)?.value.clone()),
|
||||||
cell_at_cursor(state)?.edit_text.as_deref().unwrap_or(""),
|
|
||||||
)),
|
|
||||||
Command::SetStatus("Yanked".to_string()),
|
Command::SetStatus("Yanked".to_string()),
|
||||||
]),
|
]),
|
||||||
"paste" => Some(match state.view.yanked.clone() {
|
"paste" => Some(match state.view.yanked.clone() {
|
||||||
@@ -3139,6 +3137,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn yy_yanks_the_cell_under_the_cursor_and_p_pastes_what_it_yanked() {
|
fn yy_yanks_the_cell_under_the_cursor_and_p_pastes_what_it_yanked() {
|
||||||
let mut state = client_on(record_cell());
|
let mut state = client_on(record_cell());
|
||||||
|
state.grid.cells[0][0].value = Some(CellValue::Number(1200.0));
|
||||||
arm(&mut state, ev(KeyCode::Char('y')));
|
arm(&mut state, ev(KeyCode::Char('y')));
|
||||||
let KeyOutcome::Local(yank) = resolve(&state, ev(KeyCode::Char('y'))) else {
|
let KeyOutcome::Local(yank) = resolve(&state, ev(KeyCode::Char('y'))) else {
|
||||||
panic!("`yy` is bound to yank");
|
panic!("`yy` is bound to yank");
|
||||||
|
|||||||
Reference in New Issue
Block a user