nu_command/conversions/into/
value.rs1use std::sync::OnceLock;
2
3use nu_engine::command_prelude::*;
4use nu_protocol::{
5 BlockId, DeprecationEntry, DeprecationType, ReportMode, debugger::WithoutDebug,
6 report_shell_warning,
7};
8
9static DEPRECATED_REDIRECT_BLOCK_ID: OnceLock<BlockId> = OnceLock::new();
11
12#[derive(Clone)]
13pub struct IntoValue;
14
15impl Command for IntoValue {
16 fn name(&self) -> &str {
17 "into value"
18 }
19
20 fn signature(&self) -> Signature {
21 Signature::build(self.name())
22 .description(self.description())
23 .extra_description(self.extra_description())
24 .input_output_type(Type::Any, Type::Any)
25 .category(Category::Conversions)
26 .named(
28 "columns",
29 SyntaxShape::List(Box::new(SyntaxShape::Any)),
30 "list of columns to update",
31 Some('c'),
32 )
33 .switch(
34 "prefer-filesizes",
35 "For ints display them as human-readable file sizes",
36 Some('f'),
37 )
38 }
39
40 fn deprecation_info(&self) -> Vec<DeprecationEntry> {
41 vec![
42 DeprecationEntry {
43 ty: DeprecationType::Flag("columns".to_string()),
44 report_mode: ReportMode::EveryUse,
45 since: Some("0.108.0".into()),
46 expected_removal: Some("0.109.0".into()),
47 help: Some("Use this flag on `detect type`.".into()),
48 },
49 DeprecationEntry {
50 ty: DeprecationType::Flag("prefer-filesizes".to_string()),
51 report_mode: ReportMode::EveryUse,
52 since: Some("0.108.0".into()),
53 expected_removal: Some("0.109.0".into()),
54 help: Some("Use this flag on `detect type`.".into()),
55 },
56 ]
57 }
58
59 fn description(&self) -> &str {
60 "Convert custom values into base values."
61 }
62
63 fn extra_description(&self) -> &str {
64 "Custom values from plugins have a base value representation. \
65 This extracts that base value representation. \
66 For streams use `collect`."
67 }
68
69 fn search_terms(&self) -> Vec<&str> {
70 vec!["custom", "base", "convert", "conversion"]
71 }
72
73 fn examples(&self) -> Vec<Example<'_>> {
74 vec![]
75 }
76
77 fn run(
78 &self,
79 engine_state: &EngineState,
80 stack: &mut Stack,
81 call: &Call,
82 input: PipelineData,
83 ) -> Result<PipelineData, ShellError> {
84 if let PipelineData::Value(v @ Value::Custom { .. }, metadata) = input {
85 let span = v.span();
86 let val = v.into_custom_value()?;
87 return Ok(PipelineData::value(val.to_base_value(span)?, metadata));
88 }
89
90 if let Some(block_id) = DEPRECATED_REDIRECT_BLOCK_ID.get() {
91 report_shell_warning(
92 engine_state,
93 &ShellWarning::Deprecated {
94 dep_type: "Moved Command".into(),
95 label: "Detecting types of tables is moved to `detect types`.".into(),
96 span: call.head,
97 help: Some("Use `update cells {detect type}` instead. In the future this will be a no-op for nushell native values.".into()),
98 report_mode: ReportMode::EveryUse,
99 },
100 );
101
102 let Some(block) = engine_state.try_get_block(*block_id) else {
103 return Err(ShellError::GenericError {
104 error: "Block ID not found".into(),
105 msg: format!("Block ID {} not found in this EngineState", block_id.get()),
106 span: Some(call.head),
107 help: Some("Make sure the same EngineState for IntoValue::add_deprecated_call was used here.".into()),
108 inner: vec![],
109 });
110 };
111 let execution_data =
112 nu_engine::eval_block::<WithoutDebug>(engine_state, stack, block, input)?;
113 return Ok(execution_data.body);
114 }
115
116 Ok(input)
117 }
118}
119
120impl IntoValue {
121 pub fn add_deprecated_call(engine_state: &mut EngineState) {
125 let code = b"update cells {detect type}";
126 let mut working_set = StateWorkingSet::new(engine_state);
127 let block = nu_parser::parse(
128 &mut working_set,
129 Some("`into value` inner redirect"),
130 code,
131 false,
132 );
133 debug_assert!(
134 working_set.parse_errors.is_empty(),
135 "parsing `update cells {{detect type}}` errored"
136 );
137 debug_assert!(
138 working_set.compile_errors.is_empty(),
139 "compiling `update cells {{detect type}}` errored"
140 );
141 let block_id = working_set.add_block(block);
142 if engine_state.merge_delta(working_set.delta).is_err() {
143 log::error!("could not merge delta for deprecated redirect block of `into value`");
144 return;
145 }
146
147 if DEPRECATED_REDIRECT_BLOCK_ID.set(block_id).is_err() {
148 log::error!("could not set block id for deprecated redirect block of `into value`");
149 }
150 }
151}