Sleep command (#2381)

* Add deserialization of Primitive::Duration; Fixes #2373

* Implement Sleep command

* Add comment saying you should name your rest field "rest"

* Fix typo

* Add documentation for sleep command
This commit is contained in:
Leonhard Kipp 2020-08-21 19:51:29 +02:00 committed by GitHub
parent cb4527fc0d
commit 0dd1403a69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 122 additions and 1 deletions

View File

@ -275,6 +275,7 @@ pub fn create_default_context(
whole_stream_command(Alias), whole_stream_command(Alias),
whole_stream_command(WithEnv), whole_stream_command(WithEnv),
whole_stream_command(Do), whole_stream_command(Do),
whole_stream_command(Sleep),
// Statistics // Statistics
whole_stream_command(Size), whole_stream_command(Size),
whole_stream_command(Count), whole_stream_command(Count),

View File

@ -97,6 +97,7 @@ pub(crate) mod shells;
pub(crate) mod shuffle; pub(crate) mod shuffle;
pub(crate) mod size; pub(crate) mod size;
pub(crate) mod skip; pub(crate) mod skip;
pub(crate) mod sleep;
pub(crate) mod sort_by; pub(crate) mod sort_by;
pub(crate) mod split; pub(crate) mod split;
pub(crate) mod split_by; pub(crate) mod split_by;
@ -227,6 +228,7 @@ pub(crate) use shells::Shells;
pub(crate) use shuffle::Shuffle; pub(crate) use shuffle::Shuffle;
pub(crate) use size::Size; pub(crate) use size::Size;
pub(crate) use skip::{Skip, SkipUntil, SkipWhile}; pub(crate) use skip::{Skip, SkipUntil, SkipWhile};
pub(crate) use sleep::Sleep;
pub(crate) use sort_by::SortBy; pub(crate) use sort_by::SortBy;
pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow}; pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow};
pub(crate) use split_by::SplitBy; pub(crate) use split_by::SplitBy;

View File

@ -0,0 +1,86 @@
use crate::commands::WholeStreamCommand;
use crate::context::CommandRegistry;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Signature, SyntaxShape};
use nu_source::Tagged;
use std::{thread, time};
pub struct Sleep;
#[derive(Deserialize)]
pub struct SleepArgs {
pub dur: Tagged<u64>,
pub rest: Vec<Tagged<u64>>,
}
#[async_trait]
impl WholeStreamCommand for Sleep {
fn name(&self) -> &str {
"sleep"
}
fn signature(&self) -> Signature {
Signature::build("sleep")
.required("duration", SyntaxShape::Unit, "time to sleep")
.rest(SyntaxShape::Unit, "additional time")
}
fn usage(&self) -> &str {
"delay for a specified amount of time"
}
async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
sleep(args, registry).await
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Sleep for 1sec",
example: "sleep 1sec",
result: None,
},
Example {
description: "Sleep for 3sec",
example: "sleep 1sec 1sec 1sec",
result: None,
},
]
}
}
async fn sleep(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let (SleepArgs { dur, rest }, ..) = args.process(&registry).await?;
let total_dur = dur.item + rest.iter().map(|val| val.item).sum::<u64>();
let total_dur = time::Duration::from_nanos(total_dur);
thread::sleep(total_dur);
Ok(OutputStream::empty())
}
#[cfg(test)]
mod tests {
use super::Sleep;
use std::time::Instant;
#[test]
#[ignore]
fn examples_work_as_expected() {
use crate::examples::test as test_examples;
let start = Instant::now();
test_examples(Sleep {});
let elapsed = start.elapsed();
println!("{:?}", elapsed);
assert!(elapsed >= std::time::Duration::from_secs(4));
}
}

View File

@ -412,6 +412,15 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut ConfigDeserializer<'de> {
let i: i64 = int.tagged(value.val.tag).coerce_into("converting to i64")?; let i: i64 = int.tagged(value.val.tag).coerce_into("converting to i64")?;
visit::<Tagged<i64>, _>(i.tagged(tag), name, fields, visitor) visit::<Tagged<i64>, _>(i.tagged(tag), name, fields, visitor)
} }
Value {
value: UntaggedValue::Primitive(Primitive::Duration(big_int)),
..
} => {
let u_int: u64 = big_int
.tagged(value.val.tag)
.coerce_into("converting to u64")?;
visit::<Tagged<u64>, _>(u_int.tagged(tag), name, fields, visitor)
}
Value { Value {
value: UntaggedValue::Primitive(Primitive::Decimal(decimal)), value: UntaggedValue::Primitive(Primitive::Decimal(decimal)),
.. ..

View File

@ -334,7 +334,7 @@ fn parse_unit(lite_arg: &Spanned<String>) -> (SpannedExpression, Option<ParseErr
lhs.pop(); lhs.pop();
} }
// these units are allowed to signed // these units are allowed to be signed
if let Ok(x) = lhs.parse::<i64>() { if let Ok(x) = lhs.parse::<i64>() {
let lhs_span = let lhs_span =
Span::new(lite_arg.span.start(), lite_arg.span.start() + lhs.len()); Span::new(lite_arg.span.start(), lite_arg.span.start() + lhs.len());

View File

@ -293,6 +293,8 @@ impl Signature {
} }
/// Set the type for the "rest" of the positional arguments /// Set the type for the "rest" of the positional arguments
/// Note: Not naming the field in your struct holding the rest values "rest", can
/// cause errors when deserializing
pub fn rest(mut self, ty: SyntaxShape, desc: impl Into<String>) -> Signature { pub fn rest(mut self, ty: SyntaxShape, desc: impl Into<String>) -> Signature {
self.rest_positional = Some((ty, desc.into())); self.rest_positional = Some((ty, desc.into()));
self self

21
docs/commands/sleep.md Normal file
View File

@ -0,0 +1,21 @@
# sleep
Delay for a specified amount of time
Syntax: `sleep <time> [additional_time]...`
## Flags
`-h`, `--help`
Display help message.
## Examples
Sleep for 3 seconds
```shell
> sleep 3sec
```
Sleep for 1 minute and 2 seconds
```shell
> sleep 1sec 1min 1sec
```