mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 19:27:44 +02:00
Improve handling of custom values in plugin examples (#12409)
# Description Requested by @ayax79. This makes the custom value behavior more correct, by calling the methods on the plugin to handle the custom values in examples rather than the methods on the custom values themselves. This helps for handle-type custom values (like what he's doing with dataframes). - Equality checking in `PluginTest::test_examples()` changed to use `PluginInterface::custom_value_partial_cmp()` - Base value rendering for `PluginSignature` changed to use `Plugin::custom_value_to_base_value()` - Had to be moved closer to `serve_plugin` for this reason, so the test for writing signatures containing custom values was removed - That behavior should still be tested to some degree, since if custom values are not handled, signatures will fail to parse, so all of the other tests won't work. # User-Facing Changes - `Record::sort_cols()` method added to share functionality required by `PartialCmp`, and it might also be slightly faster - Otherwise, everything should mostly be the same but better. Plugins that don't implement special handling for custom values will still work the same way, because the default implementation is just a pass-through to the `CustomValue` methods. # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib`
This commit is contained in:
@ -2441,15 +2441,28 @@ impl PartialOrd for Value {
|
||||
// reorder cols and vals to make more logically compare.
|
||||
// more general, if two record have same col and values,
|
||||
// the order of cols shouldn't affect the equal property.
|
||||
let (lhs_cols_ordered, lhs_vals_ordered) = reorder_record_inner(lhs);
|
||||
let (rhs_cols_ordered, rhs_vals_ordered) = reorder_record_inner(rhs);
|
||||
let mut lhs = lhs.clone();
|
||||
let mut rhs = rhs.clone();
|
||||
lhs.sort_cols();
|
||||
rhs.sort_cols();
|
||||
|
||||
let result = lhs_cols_ordered.partial_cmp(&rhs_cols_ordered);
|
||||
if result == Some(Ordering::Equal) {
|
||||
lhs_vals_ordered.partial_cmp(&rhs_vals_ordered)
|
||||
} else {
|
||||
result
|
||||
// Check columns first
|
||||
for (a, b) in lhs.columns().zip(rhs.columns()) {
|
||||
let result = a.partial_cmp(b);
|
||||
if result != Some(Ordering::Equal) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Then check the values
|
||||
for (a, b) in lhs.values().zip(rhs.values()) {
|
||||
let result = a.partial_cmp(b);
|
||||
if result != Some(Ordering::Equal) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// If all of the comparisons were equal, then lexicographical order dictates
|
||||
// that the shorter sequence is less than the longer one
|
||||
lhs.len().partial_cmp(&rhs.len())
|
||||
}
|
||||
Value::LazyRecord { val, .. } => {
|
||||
if let Ok(rhs) = val.collect() {
|
||||
@ -3766,12 +3779,6 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn reorder_record_inner(record: &Record) -> (Vec<&String>, Vec<&Value>) {
|
||||
let mut kv_pairs = record.iter().collect::<Vec<_>>();
|
||||
kv_pairs.sort_by_key(|(col, _)| *col);
|
||||
kv_pairs.into_iter().unzip()
|
||||
}
|
||||
|
||||
// TODO: The name of this function is overly broad with partial compatibility
|
||||
// Should be replaced by an explicitly named helper on `Type` (take `Any` into account)
|
||||
fn type_compatible(a: Type, b: Type) -> bool {
|
||||
|
@ -257,6 +257,32 @@ impl Record {
|
||||
iter: self.inner.drain(range),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sort the record by its columns.
|
||||
///
|
||||
/// ```rust
|
||||
/// use nu_protocol::{record, Value};
|
||||
///
|
||||
/// let mut rec = record!(
|
||||
/// "c" => Value::test_string("foo"),
|
||||
/// "b" => Value::test_int(42),
|
||||
/// "a" => Value::test_nothing(),
|
||||
/// );
|
||||
///
|
||||
/// rec.sort_cols();
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// Value::test_record(rec),
|
||||
/// Value::test_record(record!(
|
||||
/// "a" => Value::test_nothing(),
|
||||
/// "b" => Value::test_int(42),
|
||||
/// "c" => Value::test_string("foo"),
|
||||
/// ))
|
||||
/// );
|
||||
/// ```
|
||||
pub fn sort_cols(&mut self) {
|
||||
self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<(String, Value)> for Record {
|
||||
|
Reference in New Issue
Block a user