From a2e80dc867e242a08ab11ad3a1970fd8745ea0be Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Tue, 20 Dec 2022 18:35:45 -0500 Subject: [PATCH] Add sleep applet --- src/cli.rs | 10 ++++++---- src/cmd/bootstrap/mod.rs | 3 ++- src/cmd/echo/mod.rs | 5 +++-- src/cmd/false/mod.rs | 3 ++- src/cmd/head/mod.rs | 13 +++++++------ src/cmd/hostname/mod.rs | 16 ++++++++-------- src/cmd/mod.rs | 2 +- src/cmd/sleep/mod.rs | 35 +++++++++++++++++++++++++++++++++++ src/cmd/true/mod.rs | 3 ++- src/lib.rs | 1 + 10 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index fad6464..de73306 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,5 +1,5 @@ -use crate::cmd::{bootstrap, echo, head, hostname, r#false, r#true}; -use clap::{value_parser, Arg, ArgAction, Command}; +use crate::cmd::{bootstrap, echo, head, hostname, r#false, r#true, sleep}; +use clap::Command; pub fn run() { let matches = Command::new("shitbox") @@ -12,14 +12,16 @@ pub fn run() { r#false::cli(), head::cli(), hostname::cli(), + sleep::cli(), r#true::cli(), ]) .get_matches(); match matches.subcommand() { Some(("echo", _matches)) => echo::run(), Some(("false", _matches)) => r#false::run(), - Some(("head", matches)) => head::run(&matches), - Some(("hostname", matches)) => hostname::run(&matches), + Some(("head", matches)) => head::run(matches), + Some(("hostname", matches)) => hostname::run(matches), + Some(("sleep", matches)) => sleep::run(matches), Some(("true", _matches)) => r#true::run(), _ => {} } diff --git a/src/cmd/bootstrap/mod.rs b/src/cmd/bootstrap/mod.rs index cf60ed8..14d5514 100644 --- a/src/cmd/bootstrap/mod.rs +++ b/src/cmd/bootstrap/mod.rs @@ -1,5 +1,6 @@ -use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; +use clap::{value_parser, Arg, ArgMatches, Command}; +#[must_use] pub fn cli() -> Command { Command::new("bootstrap") .version(env!("CARGO_PKG_VERSION")) diff --git a/src/cmd/echo/mod.rs b/src/cmd/echo/mod.rs index fa07c67..2a37d3c 100644 --- a/src/cmd/echo/mod.rs +++ b/src/cmd/echo/mod.rs @@ -4,6 +4,7 @@ use std::env; pub const PATH: Path = Path::Bin; +#[must_use] pub fn cli() -> Command { Command::new("echo") .about("Display a line of text") @@ -30,9 +31,9 @@ pub fn run() { let i = if n { idx + 1 } else { idx }; for (index, arg) in args.iter().enumerate().skip(i) { if index < len - 1 { - print!("{} ", arg); + print!("{arg} "); } else { - print!("{}", arg); + print!("{arg}"); } } if !n { diff --git a/src/cmd/false/mod.rs b/src/cmd/false/mod.rs index 8079e28..fedfb50 100644 --- a/src/cmd/false/mod.rs +++ b/src/cmd/false/mod.rs @@ -1,9 +1,10 @@ -use clap::Command; use crate::Path; +use clap::Command; use std::process; pub const PATH: Path = Path::Bin; +#[must_use] pub fn cli() -> Command { Command::new("false") .about("Does nothing unsuccessfully") diff --git a/src/cmd/head/mod.rs b/src/cmd/head/mod.rs index 142d3f2..b25f08c 100644 --- a/src/cmd/head/mod.rs +++ b/src/cmd/head/mod.rs @@ -1,11 +1,12 @@ -use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use crate::Path; +use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use std::fs; use std::io::{stdin, Read}; use std::process; pub const PATH: Path = Path::Bin; +#[must_use] pub fn cli() -> Command { Command::new("head") .version(env!("CARGO_PKG_VERSION")) @@ -51,7 +52,7 @@ fn head(file: &str, count: usize, header: bool, bytes: bool) { match stdin().read_to_string(&mut contents) { Ok(_) => true, Err(e) => { - eprintln!("head: {}", e); + eprintln!("head: {e}"); process::exit(1); } }; @@ -60,18 +61,18 @@ fn head(file: &str, count: usize, header: bool, bytes: bool) { contents = match buf { Ok(c) => c, Err(e) => { - eprintln!("head: {}", e); + eprintln!("head: {e}"); process::exit(1); } }; } if header { - println!("==> {} <==", file); + println!("==> {file} <=="); } if bytes { for (index, char) in contents.chars().into_iter().enumerate() { if index < count { - print!("{}", char); + print!("{char}"); } else { println!(); return; @@ -81,7 +82,7 @@ fn head(file: &str, count: usize, header: bool, bytes: bool) { } else { for (index, line) in contents.lines().into_iter().enumerate() { if index < count { - println!("{}", line); + println!("{line}"); } else { return; } diff --git a/src/cmd/hostname/mod.rs b/src/cmd/hostname/mod.rs index 4933cf6..893680b 100644 --- a/src/cmd/hostname/mod.rs +++ b/src/cmd/hostname/mod.rs @@ -1,9 +1,10 @@ -use clap::{Arg, Command, ArgMatches, ArgAction}; use crate::Path; -use std::{io, process}; +use clap::{Arg, ArgAction, ArgMatches, Command}; +use std::process; pub const PATH: Path = Path::Bin; +#[must_use] pub fn cli() -> Command { Command::new("hostname") .version(env!("CARGO_PKG_VERSION")) @@ -34,12 +35,11 @@ pub fn run(matches: &ArgMatches) { if matches.get_flag("STRIP") { println!( "{}", - match hostname.to_string_lossy().split('.').next() { - Some(c) => c, - None => { - eprintln!("hostname: missing operand"); - process::exit(1); - } + if let Some(s) = hostname.to_string_lossy().split('.').next() { + s + } else { + eprintln!("hostname: missing operand"); + process::exit(1); } ); } else { diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index d3f558a..95c0f89 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -16,6 +16,6 @@ mod mv; mod pwd; mod rm; mod rmdir; -mod sleep; +pub mod sleep; mod sync; pub mod r#true; diff --git a/src/cmd/sleep/mod.rs b/src/cmd/sleep/mod.rs index 8b13789..c22cf81 100644 --- a/src/cmd/sleep/mod.rs +++ b/src/cmd/sleep/mod.rs @@ -1 +1,36 @@ +use crate::Path; +use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; +use std::{env, thread, time::Duration}; +pub const PATH: Path = Path::Bin; + +#[must_use] +pub fn cli() -> Command { + Command::new("sleep") + .about("Suspend execution for an interval of time") + .long_about( + "The sleep utility suspends execution for a minimum of the specified number of seconds.\n\ + This number must be positive and may contain a decimal fraction.\n\ + sleep is commonly used to schedule the execution of other commands" + ) + .version(env!("CARGO_PKG_VERSION")) + .author(env!("CARGO_PKG_AUTHORS")) + .arg( + Arg::new("seconds") + .help("The number of seconds to sleep") + .num_args(1) + .value_parser(value_parser!(f64)) + .required(true) + .action(ArgAction::Set) + ) +} + +#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] +pub fn run(matches: &ArgMatches) { + if let Some(raw) = matches.get_one::("seconds") { + let seconds = *raw as u64; + let nanos = ((raw % 1.0) * 10e-9) as u32; + let s = Duration::new(seconds, nanos); + thread::sleep(s); + } +} diff --git a/src/cmd/true/mod.rs b/src/cmd/true/mod.rs index effdbe8..0b5b64c 100644 --- a/src/cmd/true/mod.rs +++ b/src/cmd/true/mod.rs @@ -1,9 +1,10 @@ -use clap::Command; use crate::Path; +use clap::Command; use std::process; pub const PATH: Path = Path::Bin; +#[must_use] pub fn cli() -> Command { Command::new("true") .about("Does nothing successfully") diff --git a/src/lib.rs b/src/lib.rs index cf06962..089f2bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub fn run() { "hostname" => cmd::hostname::run(&cmd::hostname::cli().get_matches()), "true" => cmd::r#true::run(), "shitbox" => cli::run(), + "sleep" => cmd::sleep::run(&cmd::sleep::cli().get_matches()), _ => unimplemented!(), } }