-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathecho.rs
95 lines (83 loc) · 2.29 KB
/
echo.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
//
// Copyright (c) 2024 Jeff Garzik
//
// This file is part of the posixutils-rs project covered under
// the MIT License. For the full license text, please see the LICENSE
// file in the root directory of this project.
// SPDX-License-Identifier: MIT
//
// TODO:
// - echo needs to translate backslash-escaped octal numbers:
// ```
// \0num
// Write an 8-bit value that is the 0, 1, 2 or 3-digit octal number _num_.
//
use gettextrs::{bind_textdomain_codeset, setlocale, textdomain, LocaleCategory};
use std::io::{self, Write};
fn translate_str(skip_nl: bool, s: &str) -> String {
let mut output = String::with_capacity(s.len());
let mut in_bs = false;
let mut nl = true;
for ch in s.chars() {
if ch == '\\' {
in_bs = true;
} else if in_bs {
in_bs = false;
match ch {
'a' => {
output.push('\x07');
}
'b' => {
output.push('\x08');
}
'c' => {
nl = false;
break;
}
'f' => {
output.push('\x12');
}
'n' => {
output.push('\n');
}
'r' => {
output.push('\r');
}
't' => {
output.push('\t');
}
'v' => {
output.push('\x11');
}
'\\' => {
output.push('\\');
}
_ => {}
}
} else {
output.push(ch);
}
}
if nl && !skip_nl {
output.push('\n');
}
output
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
setlocale(LocaleCategory::LcAll, "");
textdomain("posixutils-rs")?;
bind_textdomain_codeset("posixutils-rs", "UTF-8")?;
let mut args: Vec<String> = std::env::args().collect();
args.remove(0);
let skip_nl = {
if !args.is_empty() && (args[0] == "-n") {
args.remove(0);
true
} else {
false
}
};
let echo_str = translate_str(skip_nl, &args.join(" "));
io::stdout().write_all(echo_str.as_bytes())?;
Ok(())
}