forked from extern/nushell
[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`
79 lines
2.0 KiB
Rust
79 lines
2.0 KiB
Rust
use nu_plugin::{EngineInterface, EvaluatedCall, LabeledError, SimplePluginCommand};
|
|
use nu_protocol::{
|
|
record, Category, CustomValue, PluginSignature, ShellError, Span, SyntaxShape, Value,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::CustomValuePlugin;
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct DropCheckValue {
|
|
pub(crate) msg: String,
|
|
}
|
|
|
|
impl DropCheckValue {
|
|
pub(crate) fn new(msg: String) -> DropCheckValue {
|
|
DropCheckValue { msg }
|
|
}
|
|
|
|
pub(crate) fn into_value(self, span: Span) -> Value {
|
|
Value::custom_value(Box::new(self), span)
|
|
}
|
|
|
|
pub(crate) fn notify(&self) {
|
|
eprintln!("DropCheckValue was dropped: {}", self.msg);
|
|
}
|
|
}
|
|
|
|
#[typetag::serde]
|
|
impl CustomValue for DropCheckValue {
|
|
fn clone_value(&self, span: Span) -> Value {
|
|
self.clone().into_value(span)
|
|
}
|
|
|
|
fn type_name(&self) -> String {
|
|
"DropCheckValue".into()
|
|
}
|
|
|
|
fn to_base_value(&self, span: Span) -> Result<Value, ShellError> {
|
|
Ok(Value::record(
|
|
record! {
|
|
"msg" => Value::string(&self.msg, span)
|
|
},
|
|
span,
|
|
))
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn notify_plugin_on_drop(&self) -> bool {
|
|
// This is what causes Nushell to let us know when the value is dropped
|
|
true
|
|
}
|
|
}
|
|
|
|
pub struct DropCheck;
|
|
|
|
impl SimplePluginCommand for DropCheck {
|
|
type Plugin = CustomValuePlugin;
|
|
|
|
fn signature(&self) -> nu_protocol::PluginSignature {
|
|
PluginSignature::build("custom-value drop-check")
|
|
.usage("Generates a custom value that prints a message when dropped")
|
|
.required("msg", SyntaxShape::String, "the message to print on drop")
|
|
.category(Category::Experimental)
|
|
}
|
|
|
|
fn run(
|
|
&self,
|
|
_plugin: &Self::Plugin,
|
|
_engine: &EngineInterface,
|
|
call: &EvaluatedCall,
|
|
_input: &Value,
|
|
) -> Result<Value, LabeledError> {
|
|
Ok(DropCheckValue::new(call.req(0)?).into_value(call.head))
|
|
}
|
|
}
|