shitbox/src/cmd/echo/mod.rs
Nathan Fisher fb389fd309 Simplify subcommand parsing:
- one match statement to return a `Box<dyn Cmd>`
- one array containing all command names
Only two places to register new commands (besides their module), both in
crate::cmd::mod.rs. Also removes `once_cell` crate dependency.

Replace `base64` crate dependency with `data_encoding::BASE64` so that
both base32 and base64 commands use the same crate.
2023-01-06 23:41:02 -05:00

66 lines
1.6 KiB
Rust

use super::Cmd;
use crate::Path;
use clap::{Arg, Command};
use std::{env, error::Error};
#[derive(Debug)]
pub struct Echo {
name: &'static str,
path: Option<Path>,
}
impl Default for Echo {
fn default() -> Self {
Self {
name: "echo",
path: Some(crate::Path::Bin),
}
}
}
impl Cmd for Echo {
fn name(&self) -> &str {
self.name
}
fn cli(&self) -> clap::Command {
Command::new(self.name)
.about("Display a line of text")
.long_about("Echo the STRING(s) to standard output")
.author("Nathan Fisher")
.args([
Arg::new("inline")
.short('n')
.help("Do not output a trailing newline"),
Arg::new("STRING").num_args(1..),
])
}
fn run(&self, _matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
let idx = match crate::progname() {
Some(s) if s.as_str() == self.name() => 1,
Some(_) => 2,
None => unreachable!(),
};
let len = args.len();
let n = len > idx && args[idx] == "-n";
let i = if n { idx + 1 } else { idx };
for (index, arg) in args.iter().enumerate().skip(i) {
if index < len - 1 {
print!("{arg} ");
} else {
print!("{arg}");
}
}
if !n {
println!();
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
self.path
}
}