Skip to content

Commit 453b01b

Browse files
committed
Improve list formatting logic
1 parent 415ee07 commit 453b01b

File tree

1 file changed

+32
-30
lines changed

1 file changed

+32
-30
lines changed

crates/ark/src/data_explorer/format.rs

+32-30
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use harp::vector::NumericVector;
3030
use harp::vector::Vector;
3131
use libr::SEXP;
3232
use libr::*;
33+
use stdext::unwrap;
3334

3435
use crate::modules::ARK_ENVS;
3536

@@ -91,42 +92,43 @@ fn format_object(x: SEXP) -> Vec<FormattedValue> {
9192
Err(_) => return unknown_format(x),
9293
};
9394

95+
let formatted = formatted.into_iter().map(|v| {
96+
// `base::format` defaults to using `trim=FALSE`
97+
// So it will add spaces to the end of the strings causing all elements of the vector
98+
// to have the same fixed width. We don't want this behavior in the data explorer,
99+
// We tried passing `trim=TRUE` but this is unfortunately not supported for eg. `factors`:
100+
// > format(factor(c("aaaa", "a")), trim = TRUE)
101+
// [1] "aaaa" "a "
102+
//
103+
// So we will just trim the spaces manually, which is not ideal, but it's better than
104+
// having the values misaligned
105+
FormattedValue::Value(v.trim_matches(|x| x == ' ').to_string())
106+
});
107+
94108
// But we also want to show special value codes. We call `base::is.na()` to dispatch
95109
// the `is.na()` function and then replace those with `FormattedValues::NA`.
96110
let is_na = RFunction::from("is_na_checked")
97111
.add(x)
98112
.call_in(ARK_ENVS.positron_ns);
99113

100-
match is_na {
101-
Ok(is_na) => {
102-
formatted
103-
.into_iter()
104-
.zip(unsafe { LogicalVector::new_unchecked(is_na.sexp).iter() })
105-
.map(|(v, is_na)| {
106-
// We don't expect is.na to return NA's, but if it happens, we treat it as false
107-
if is_na.unwrap_or(false) {
108-
FormattedValue::NA
109-
} else {
110-
// `base::format` defaults to using `trim=FALSE`
111-
// So it will add spaces to the end of the strings causing all elements of the vector
112-
// to have the same fixed width. We don't want this behavior in the data explorer,
113-
// We tried passing `trim=TRUE` but this is unfortunately not supported for eg. `factors`:
114-
// > format(factor(c("aaaa", "a")), trim = TRUE)
115-
// [1] "aaaa" "a "
116-
//
117-
// So we will just trim the spaces manually, which is not ideal, but it's better than
118-
// having the values misaligned
119-
FormattedValue::Value(v.trim_matches(|x| x == ' ').to_string())
120-
}
121-
})
122-
.collect()
123-
},
124-
Err(_) => {
125-
// If we fail to get the is.na() values we will just return the formatted values
126-
// without additional treatments.
127-
formatted.into_iter().map(FormattedValue::Value).collect()
128-
},
129-
}
114+
let is_na = unwrap!(is_na, Err(_) => {
115+
// If we fail to evaluate `is.na()` we will just return the formatted values
116+
// as is.
117+
return formatted.collect();
118+
});
119+
120+
unsafe { LogicalVector::new_unchecked(is_na.sexp) }
121+
.iter()
122+
.zip(formatted)
123+
.map(|(is_na, v)| {
124+
// We don't expect is.na to return NA's, but if it happens, we treat it as false
125+
// and return the formatted values as is.
126+
match is_na.unwrap_or(false) {
127+
true => FormattedValue::NA,
128+
false => v,
129+
}
130+
})
131+
.collect()
130132
}
131133

132134
fn format_list(x: SEXP) -> Vec<FormattedValue> {

0 commit comments

Comments
 (0)