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