nu_command/debug/
metadata.rs1use super::util::{build_metadata_record, extend_record_with_metadata};
2use nu_engine::command_prelude::*;
3use nu_protocol::{
4 PipelineMetadata,
5 ast::{Expr, Expression},
6};
7
8#[derive(Clone)]
9pub struct Metadata;
10
11impl Command for Metadata {
12 fn name(&self) -> &str {
13 "metadata"
14 }
15
16 fn description(&self) -> &str {
17 "Get the metadata for items in the stream."
18 }
19
20 fn signature(&self) -> nu_protocol::Signature {
21 Signature::build("metadata")
22 .input_output_types(vec![(Type::Any, Type::record())])
23 .allow_variants_without_examples(true)
24 .optional(
25 "expression",
26 SyntaxShape::Any,
27 "The expression you want metadata for.",
28 )
29 .category(Category::Debug)
30 }
31
32 fn requires_ast_for_arguments(&self) -> bool {
33 true
34 }
35
36 fn run(
37 &self,
38 engine_state: &EngineState,
39 stack: &mut Stack,
40 call: &Call,
41 input: PipelineData,
42 ) -> Result<PipelineData, ShellError> {
43 let arg = call.positional_nth(stack, 0);
44 let head = call.head;
45
46 match arg {
47 Some(Expression {
48 expr: Expr::FullCellPath(full_cell_path),
49 span,
50 ..
51 }) => {
52 if full_cell_path.tail.is_empty() {
53 match &full_cell_path.head {
54 Expression {
55 expr: Expr::Var(var_id),
56 ..
57 } => {
58 let origin = stack.get_var_with_origin(*var_id, *span)?;
59
60 Ok(build_metadata_record_value(
61 &origin,
62 input.metadata().as_ref(),
63 head,
64 )
65 .into_pipeline_data())
66 }
67 _ => {
68 let val: Value = call.req(engine_state, stack, 0)?;
69 Ok(
70 build_metadata_record_value(&val, input.metadata().as_ref(), head)
71 .into_pipeline_data(),
72 )
73 }
74 }
75 } else {
76 let val: Value = call.req(engine_state, stack, 0)?;
77 Ok(
78 build_metadata_record_value(&val, input.metadata().as_ref(), head)
79 .into_pipeline_data(),
80 )
81 }
82 }
83 Some(_) => {
84 let val: Value = call.req(engine_state, stack, 0)?;
85 Ok(
86 build_metadata_record_value(&val, input.metadata().as_ref(), head)
87 .into_pipeline_data(),
88 )
89 }
90 None => Ok(
91 Value::record(build_metadata_record(input.metadata().as_ref(), head), head)
92 .into_pipeline_data(),
93 ),
94 }
95 }
96
97 fn examples(&self) -> Vec<Example> {
98 vec![
99 Example {
100 description: "Get the metadata of a variable",
101 example: "let a = 42; metadata $a",
102 result: None,
103 },
104 Example {
105 description: "Get the metadata of the input",
106 example: "ls | metadata",
107 result: None,
108 },
109 ]
110 }
111}
112
113fn build_metadata_record_value(
114 arg: &Value,
115 metadata: Option<&PipelineMetadata>,
116 head: Span,
117) -> Value {
118 let mut record = Record::new();
119
120 let span = arg.span();
121 record.push(
122 "span",
123 Value::record(
124 record! {
125 "start" => Value::int(span.start as i64,span),
126 "end" => Value::int(span.end as i64, span),
127 },
128 head,
129 ),
130 );
131
132 Value::record(extend_record_with_metadata(record, metadata, head), head)
133}
134
135#[cfg(test)]
136mod test {
137 use super::*;
138
139 #[test]
140 fn test_examples() {
141 use crate::test_examples;
142
143 test_examples(Metadata {})
144 }
145}