I rewrote echo
from the manpage to learn Rust, and got the following:
// echo in rust - display a line of text
use std::env;
static HELP: &'static str = "\
echo the STRING(s) to standard output.\n\
-n do not output the trailing newline\n\
-e enable intepretation of backslash escapes\n\
-E disable intepretation of backslash escapes (default)\n\
--help display this help and exit
If -e is in effect, the following sequence are recognized:
\\\\ backslash
\\a alert (BEL)
\\b backspace
\\c produce no futher output
\\e escape
\\f form feed
\\n new line
\\r carriage return
\\t horizontal tab
\\v vertical tab";
fn main() {
let mut args: Vec<String> = env::args().skip(1).collect();
let mut nl: bool = true; // the "-n" flag can be used to indicate no new line
let mut escape: bool = false; // Disable interpreation of backslashes
let mut args_count: usize = 0; // first argument is binary name
for stuff in &args {
if !stuff.starts_with("-") {
break;
}
if stuff == "-n" {
nl = false;
args_count += 1;
}
if stuff == "-e" {
escape = true;
args_count += 1;
}
if stuff == "-E" {
escape = false;
args_count += 1;
}
if stuff == "--help" {
println!("{}", HELP);
return;
}
}
if escape {
for stuff in &mut args[args_count..] {
*stuff = stuff.replace("\\\\", "\\"); // backslashe
*stuff = stuff.replace("\\a", ""); // alert (BEL)
*stuff = stuff.replace("\\b", ""); // backspace
*stuff = stuff.replace("\\c", ""); // produce no further output
*stuff = stuff.replace("\\e", ""); // escape
*stuff = stuff.replace("\\f", ""); // form feed
*stuff = stuff.replace("\\n", ""); // new line
*stuff = stuff.replace("\\r", ""); // carriage return
*stuff = stuff.replace("\\t", ""); // horizontal tab
*stuff = stuff.replace("\\v", ""); // vertical tab
}
}
print!("{}", args[args_count..].join(" "));
if nl {
println!();
}
}
I then had a look at previously asked questions on this topic, and learnt of skip
from here.
I would particularly welcome feedback on string manipulation, notably on the argument parsing (i.e. here, I expect known flags before data to echo), and the if escape
block.
Could the argument parsing be converted to a match
statement, whilst retaining the arg_count
increment and the break
condition?
Another thing I'm unsure of is that I'm first collecting args
and then checking each element within the vector and eventually joining it, using a bunch of for loops.
Is there a more idiomatic way to do so, such as vector subtraction or...?
Lastly, my manpage for echo mentions support for decoding bytes:
\0NNN byte with octal value NNN (1 to 3 digits)
\xHH byte with hexadecimal value HH (1 to 2 digits)
Would you have pointers on how to do this type of operation?