Make custom value type handling more consistent (#12230)

[Context on
Discord](https://discord.com/channels/601130461678272522/855947301380947968/1219425984990806207)

# Description

- Rename `CustomValue::value_string()` to `type_name()` to reflect its
usage better.
- Change print behavior to always call `to_base_value()` first, to give
the custom value better control over the output.
- Change `describe --detailed` to show the type name as the subtype,
rather than trying to describe the base value.
- Change custom `Type` to use `type_name()` rather than `typetag_name()`
to make things like `PluginCustomValue` more transparent

One question: should `describe --detailed` still include a description
of the base value somewhere? I'm torn on it, it seems possibly useful
for some things (maybe sqlite databases?), but having `describe -d` not
include the custom type name anywhere felt weird. Another option would
be to add another method to `CustomValue` for info to be displayed in
`describe`, so that it can be more type-specific?

# User-Facing Changes
Everything above has implications for printing and `describe` on custom
values

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
This commit is contained in:
Devyn Cairns
2024-03-19 03:09:59 -07:00
committed by GitHub
parent 931f522616
commit 6795ad7e33
19 changed files with 51 additions and 45 deletions

View File

@ -13,8 +13,10 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
//fn category(&self) -> Category;
/// Define string representation of the custom value
fn value_string(&self) -> String;
/// The friendly type name to show for the custom value, e.g. in `describe` and in error
/// messages. This does not have to be the same as the name of the struct or enum, but
/// conventionally often is.
fn type_name(&self) -> String;
/// Converts the custom value to a base nushell value.
///
@ -34,7 +36,7 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
) -> Result<Value, ShellError> {
let _ = (self_span, index);
Err(ShellError::IncompatiblePathAccess {
type_name: self.value_string(),
type_name: self.type_name(),
span: path_span,
})
}
@ -48,7 +50,7 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
) -> Result<Value, ShellError> {
let _ = (self_span, column_name);
Err(ShellError::IncompatiblePathAccess {
type_name: self.value_string(),
type_name: self.type_name(),
span: path_span,
})
}

View File

@ -831,7 +831,7 @@ impl Value {
Value::Error { .. } => Type::Error,
Value::Binary { .. } => Type::Binary,
Value::CellPath { .. } => Type::CellPath,
Value::CustomValue { val, .. } => Type::Custom(val.typetag_name().into()),
Value::CustomValue { val, .. } => Type::Custom(val.type_name()),
}
}
@ -947,7 +947,12 @@ impl Value {
Value::Error { error, .. } => format!("{error:?}"),
Value::Binary { val, .. } => format!("{val:?}"),
Value::CellPath { val, .. } => val.to_string(),
Value::CustomValue { val, .. } => val.value_string(),
// If we fail to collapse the custom value, just print <{type_name}> - failure is not
// that critical here
Value::CustomValue { val, .. } => val
.to_base_value(span)
.map(|val| val.to_expanded_string(separator, config))
.unwrap_or_else(|_| format!("<{}>", val.type_name())),
}
}