xs/nu/commands/
head_command.rs

1use nu_engine::CallExt;
2use nu_protocol::engine::{Call, Command, EngineState, Stack};
3use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape, Type};
4
5use crate::nu::util;
6use crate::store::Store;
7
8#[derive(Clone)]
9pub struct HeadCommand {
10    store: Store,
11    context_id: scru128::Scru128Id,
12}
13
14impl HeadCommand {
15    pub fn new(store: Store, context_id: scru128::Scru128Id) -> Self {
16        Self { store, context_id }
17    }
18}
19
20impl Command for HeadCommand {
21    fn name(&self) -> &str {
22        ".head"
23    }
24
25    fn signature(&self) -> Signature {
26        Signature::build(".head")
27            .input_output_types(vec![(Type::Nothing, Type::Any)])
28            .required("topic", SyntaxShape::String, "topic to get head frame from")
29            .named(
30                "context",
31                SyntaxShape::String,
32                "context ID (defaults to system context)",
33                None,
34            )
35            .category(Category::Experimental)
36    }
37
38    fn description(&self) -> &str {
39        "get the most recent frame for a topic"
40    }
41
42    fn run(
43        &self,
44        engine_state: &EngineState,
45        stack: &mut Stack,
46        call: &Call,
47        _input: PipelineData,
48    ) -> Result<PipelineData, ShellError> {
49        let topic: String = call.req(engine_state, stack, 0)?;
50        let context_str: Option<String> = call.get_flag(engine_state, stack, "context")?;
51        let context_id = if let Some(ctx) = context_str {
52            ctx.parse::<scru128::Scru128Id>()
53                .map_err(|e| ShellError::GenericError {
54                    error: "Invalid context ID".into(),
55                    msg: e.to_string(),
56                    span: Some(call.head),
57                    help: None,
58                    inner: vec![],
59                })?
60        } else {
61            self.context_id
62        };
63        let span = call.head;
64
65        if let Some(frame) = self.store.head(&topic, context_id) {
66            Ok(PipelineData::Value(
67                util::frame_to_value(&frame, span),
68                None,
69            ))
70        } else {
71            Ok(PipelineData::Empty)
72        }
73    }
74}