nu_command/platform/
sleep.rs1use nu_engine::command_prelude::*;
2
3use std::{
4 thread,
5 time::{Duration, Instant},
6};
7
8const CTRL_C_CHECK_INTERVAL: Duration = Duration::from_millis(100);
9
10#[derive(Clone)]
11pub struct Sleep;
12
13impl Command for Sleep {
14 fn name(&self) -> &str {
15 "sleep"
16 }
17
18 fn description(&self) -> &str {
19 "Delay for a specified amount of time."
20 }
21
22 fn signature(&self) -> Signature {
23 Signature::build("sleep")
24 .input_output_types(vec![(Type::Nothing, Type::Nothing)])
25 .required("duration", SyntaxShape::Duration, "Time to sleep.")
26 .rest("rest", SyntaxShape::Duration, "Additional time.")
27 .category(Category::Platform)
28 }
29
30 fn search_terms(&self) -> Vec<&str> {
31 vec!["delay", "wait", "timer"]
32 }
33
34 fn run(
35 &self,
36 engine_state: &EngineState,
37 stack: &mut Stack,
38 call: &Call,
39 _input: PipelineData,
40 ) -> Result<PipelineData, ShellError> {
41 fn duration_from_i64(val: i64) -> Duration {
42 Duration::from_nanos(if val < 0 { 0 } else { val as u64 })
43 }
44
45 let duration: i64 = call.req(engine_state, stack, 0)?;
46 let rest: Vec<i64> = call.rest(engine_state, stack, 1)?;
47
48 let total_dur =
49 duration_from_i64(duration) + rest.into_iter().map(duration_from_i64).sum::<Duration>();
50 let deadline = Instant::now() + total_dur;
51
52 loop {
53 let time_until_deadline = deadline.saturating_duration_since(Instant::now());
55 if time_until_deadline.is_zero() {
56 break;
57 }
58 thread::sleep(CTRL_C_CHECK_INTERVAL.min(time_until_deadline));
59 engine_state.signals().check(call.head)?;
60 }
61
62 Ok(Value::nothing(call.head).into_pipeline_data())
63 }
64
65 fn examples(&self) -> Vec<Example> {
66 vec![
67 Example {
68 description: "Sleep for 1sec",
69 example: "sleep 1sec",
70 result: Some(Value::nothing(Span::test_data())),
71 },
72 Example {
73 description: "Use multiple arguments to write a duration with multiple units, which is unsupported by duration literals",
74 example: "sleep 1min 30sec",
75 result: None,
76 },
77 Example {
78 description: "Send output after 1sec",
79 example: "sleep 1sec; echo done",
80 result: None,
81 },
82 ]
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::Sleep;
89
90 #[test]
91 fn examples_work_as_expected() {
92 use crate::test_examples;
93 use std::time::Instant;
94
95 let start = Instant::now();
96 test_examples(Sleep {});
97
98 let elapsed = start.elapsed();
99
100 assert!(elapsed >= std::time::Duration::from_secs(1));
102 assert!(elapsed < std::time::Duration::from_secs(2));
103 }
104}