Skip to main content

xs/nu/commands/
last_command.rs

1use nu_engine::CallExt;
2use nu_protocol::engine::{Call, Command, EngineState, Stack};
3use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape, Type, Value};
4
5use crate::nu::util;
6use crate::store::{ReadOptions, Store};
7
8#[derive(Clone)]
9pub struct LastCommand {
10    store: Store,
11}
12
13impl LastCommand {
14    pub fn new(store: Store) -> Self {
15        Self { store }
16    }
17}
18
19impl Command for LastCommand {
20    fn name(&self) -> &str {
21        ".last"
22    }
23
24    fn signature(&self) -> Signature {
25        Signature::build(".last")
26            .input_output_types(vec![(Type::Nothing, Type::Any)])
27            .optional(
28                "topic",
29                SyntaxShape::String,
30                "topic to get most recent frame from (default: all topics)",
31            )
32            .named(
33                "last",
34                SyntaxShape::Int,
35                "number of frames to return",
36                Some('n'),
37            )
38            .category(Category::Experimental)
39    }
40
41    fn description(&self) -> &str {
42        "get the most recent frame(s) for a topic"
43    }
44
45    fn run(
46        &self,
47        engine_state: &EngineState,
48        stack: &mut Stack,
49        call: &Call,
50        _input: PipelineData,
51    ) -> Result<PipelineData, ShellError> {
52        let topic: Option<String> = call.opt(engine_state, stack, 0)?;
53        let n: usize = call
54            .get_flag::<i64>(engine_state, stack, "last")?
55            .map(|v| v as usize)
56            .unwrap_or(1);
57        let span = call.head;
58
59        let options = ReadOptions::builder().last(n).maybe_topic(topic).build();
60
61        let frames: Vec<Value> = self
62            .store
63            .read_sync(options)
64            .map(|frame| util::frame_to_value(&frame, span))
65            .collect();
66
67        if frames.is_empty() {
68            Ok(PipelineData::Empty)
69        } else if frames.len() == 1 {
70            Ok(PipelineData::Value(
71                frames.into_iter().next().unwrap(),
72                None,
73            ))
74        } else {
75            Ok(PipelineData::Value(Value::list(frames, span), None))
76        }
77    }
78}