-
Notifications
You must be signed in to change notification settings - Fork 0
/
tokio-revchars.rs
104 lines (99 loc) · 4.02 KB
/
tokio-revchars.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! An example of using patharg with lexopt and tokio
//!
//! Run with `cargo run --example tokio-revchars --features examples,tokio`
//!
//! Say you're using lexopt to write a command named "tokio-revchars" that
//! reverses the order of all characters in a file, and you want this command
//! to take a path to a file to read input from and another path for the file
//! to write the output to. Converting the command's arguments to
//! `patharg::InputArg` and `patharg::OutputArg` will make tokio-revchars treat
//! a '-' argument as referring to stdin/stdout, and you'll be able to use the
//! types' methods to read or write from any filepath or standard stream given
//! on the command line.
//!
//! tokio-revchars can then be invoked in the following ways:
//!
//! - `tokio-revchars` — Read input from stdin, write output to stdout
//! - `tokio-revchars file.txt` — Read input from `file.txt`, write output to
//! stdout
//! - `tokio-revchars -` — Read input from stdin, write output to stdout
//! - `tokio-revchars -o out.txt` — Read input from stdin, write output to
//! `out.txt`
//! - `tokio-revchars -o -` — Read input from stdin, write output to stdout
//! - `tokio-revchars -o out.txt file.txt` — Read input from `file.txt`, write
//! output to `out.txt`
//! - `tokio-revchars -o out.txt -` — Read input from stdin, write output to
//! `out.txt`
//! - `tokio-revchars -o - file.txt` — Read input from `file.txt`, write output
//! to stdout
//! - `tokio-revchars -o - -` — Read input from stdin, write output to stdout
use lexopt::{Arg, Parser};
use patharg::{InputArg, OutputArg};
use std::error::Error;
#[derive(Debug, Eq, PartialEq)]
enum Command {
Run {
outfile: OutputArg,
infile: InputArg,
},
Help,
Version,
}
impl Command {
fn from_parser(mut parser: Parser) -> Result<Command, lexopt::Error> {
let mut infile: Option<InputArg> = None;
let mut outfile: Option<OutputArg> = None;
while let Some(arg) = parser.next()? {
match arg {
Arg::Short('h') | Arg::Long("help") => return Ok(Command::Help),
Arg::Short('V') | Arg::Long("version") => return Ok(Command::Version),
Arg::Short('o') | Arg::Long("outfile") => {
outfile = Some(OutputArg::from_arg(parser.value()?));
}
Arg::Value(val) if infile.is_none() => {
infile = Some(InputArg::from_arg(val));
}
_ => return Err(arg.unexpected()),
}
}
Ok(Command::Run {
infile: infile.unwrap_or_default(),
outfile: outfile.unwrap_or_default(),
})
}
async fn run(self) -> std::io::Result<()> {
match self {
Command::Run { infile, outfile } => {
let content = infile.async_read_to_string().await?;
let tnetnoc = content.chars().rev().collect::<String>();
outfile.async_write(tnetnoc).await?;
Ok(())
}
Command::Help => {
println!("Usage: tokio-revchars [-o|--outfile <PATH>] [<PATH>]");
println!();
println!("Reverse the characters in a file");
println!();
println!("Options:");
println!(" -o <PATH>, --outfile <PATH>");
println!(
" The file to write the reversed text to [default: stdout]"
);
println!(" -h, --help Display this help message and exit");
println!(" -V, --version Show the program version and exit");
Ok(())
}
Command::Version => {
println!(
"tokio-revchars: patharg {} example",
env!("CARGO_PKG_VERSION")
);
Ok(())
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
Ok(Command::from_parser(Parser::from_env())?.run().await?)
}