Skip to content

Commit 3dddbb9

Browse files
authored
Improved matrix representation in variables pane (#711)
1 parent 2749a7d commit 3dddbb9

File tree

1 file changed

+72
-48
lines changed

1 file changed

+72
-48
lines changed

crates/ark/src/variables/variable.rs

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -304,43 +304,33 @@ impl WorkspaceVariableDisplayValue {
304304
Self::new(display_value, is_truncated)
305305
}
306306

307-
// TODO: handle higher dimensional arrays, i.e. expand
308-
// recursively from the higher dimension
309307
fn from_matrix(value: SEXP) -> anyhow::Result<Self> {
310-
let formatted = FormattedVector::new(RObject::from(value))?;
311-
312-
let mut display_value = String::from("");
313-
314-
let n_col = match harp::table_info(value) {
315-
Some(info) => info.dims.num_cols,
308+
let (n_row, n_col) = match harp::table_info(value) {
309+
Some(info) => (info.dims.num_cols, info.dims.num_rows),
316310
None => {
317311
log::error!("Failed to get matrix dimensions");
318-
0
312+
(-1, -1)
319313
},
320314
};
321315

322-
display_value.push('[');
323-
for i in 0..n_col {
324-
if i > 0 {
325-
display_value.push_str(", ");
326-
}
316+
let class = match r_classes(value) {
317+
None => String::from(" <matrix>"),
318+
Some(classes) => match classes.get_unchecked(0) {
319+
Some(class) => format!(" <{}>", class),
320+
None => String::from(" <matrix>"),
321+
},
322+
};
327323

328-
display_value.push('[');
329-
for char in formatted
330-
.column_iter_n(i as isize, MAX_DISPLAY_VALUE_LENGTH)?
331-
.join(" ")
332-
.chars()
333-
{
334-
if display_value.len() >= MAX_DISPLAY_VALUE_LENGTH {
335-
return Ok(Self::new(display_value, true));
336-
}
337-
display_value.push(char);
338-
}
339-
display_value.push(']');
340-
}
341-
display_value.push(']');
324+
let value = format!(
325+
"[{} {} x {} {}]{}",
326+
n_row,
327+
plural("row", n_row),
328+
n_col,
329+
plural("column", n_col),
330+
class
331+
);
342332

343-
Ok(Self::new(display_value, false))
333+
Ok(Self::new(value, false))
344334
}
345335

346336
fn from_s4(value: SEXP) -> anyhow::Result<Self> {
@@ -2051,25 +2041,6 @@ mod tests {
20512041
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
20522042
assert_eq!(vars.len(), 1);
20532043
assert_eq!(vars[0].display_value, "\"\"");
2054-
2055-
// Test for the single elment matrix, but with a large character
2056-
let env = Environment::new_empty().unwrap();
2057-
let value = harp::parse_eval_base("matrix(paste(1:5e6, collapse = ' - '))").unwrap();
2058-
env.bind("x".into(), &value);
2059-
let path = vec![];
2060-
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
2061-
assert_eq!(vars.len(), 1);
2062-
assert_eq!(vars[0].display_value.len(), MAX_DISPLAY_VALUE_LENGTH);
2063-
assert_eq!(vars[0].is_truncated, true);
2064-
2065-
// Test for the empty matrix
2066-
let env = Environment::new_empty().unwrap();
2067-
let value = harp::parse_eval_base("matrix(NA, ncol = 0, nrow = 0)").unwrap();
2068-
env.bind("x".into(), &value);
2069-
let path = vec![];
2070-
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
2071-
assert_eq!(vars.len(), 1);
2072-
assert_eq!(vars[0].display_value, "[]");
20732044
});
20742045
}
20752046

@@ -2110,4 +2081,57 @@ mod tests {
21102081
assert_eq!(vars[0].display_value, "<CHARSXP>");
21112082
})
21122083
}
2084+
2085+
#[test]
2086+
fn test_matrix_display() {
2087+
r_task(|| {
2088+
// Test 10x10 matrix
2089+
let env = Environment::new_empty().unwrap();
2090+
let value = harp::parse_eval_base(
2091+
"matrix(paste(1:100, collapse = ' - '), nrow = 10, ncol = 10)",
2092+
)
2093+
.unwrap();
2094+
env.bind("x".into(), &value);
2095+
let path = vec![];
2096+
let vars = PositronVariable::inspect(env.clone().into(), &path).unwrap();
2097+
assert_eq!(vars.len(), 1);
2098+
assert_eq!(vars[0].display_value, "[10 rows x 10 columns] <matrix>");
2099+
2100+
// Test consistency between data.frame and matrix display
2101+
let value = harp::parse_eval_base(
2102+
"data.frame(matrix(paste(1:100, collapse = ' - '), nrow = 10, ncol = 10))",
2103+
)
2104+
.unwrap();
2105+
env.bind("y".into(), &value);
2106+
let path = vec![];
2107+
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
2108+
assert_eq!(vars.len(), 2);
2109+
let display_value_matrix = vars[0].display_value.split('<').next().unwrap();
2110+
let display_value_df = vars[1].display_value.split('<').next().unwrap();
2111+
assert_eq!(display_value_matrix, display_value_df);
2112+
2113+
// Test plurals
2114+
let env = Environment::new_empty().unwrap();
2115+
let value =
2116+
harp::parse_eval_base("matrix(paste(1:100, collapse = ' - '), nrow = 1, ncol = 1)")
2117+
.unwrap();
2118+
env.bind("x".into(), &value);
2119+
let path = vec![];
2120+
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
2121+
assert_eq!(vars.len(), 1);
2122+
assert_eq!(vars[0].display_value, "[1 row x 1 column] <matrix>");
2123+
2124+
// Test class
2125+
let env = Environment::new_empty().unwrap();
2126+
let value = harp::parse_eval_base(
2127+
"structure(matrix(paste(1:100, collapse = ' - '), nrow = 1, ncol = 1), class='foo')",
2128+
)
2129+
.unwrap();
2130+
env.bind("x".into(), &value);
2131+
let path = vec![];
2132+
let vars = PositronVariable::inspect(env.into(), &path).unwrap();
2133+
assert_eq!(vars.len(), 1);
2134+
assert_eq!(vars[0].display_value, "[1 row x 1 column] <foo>");
2135+
})
2136+
}
21132137
}

0 commit comments

Comments
 (0)