added comments and cleaned code
This commit is contained in:
parent
37702c02e3
commit
c0171c0986
@ -1,3 +1,5 @@
|
|||||||
|
//! Constant values
|
||||||
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -30,6 +32,8 @@ If -e is in effect, the following sequences are recognized:
|
|||||||
\0NNN byte with octal value NNN (1 to 3 digits)
|
\0NNN byte with octal value NNN (1 to 3 digits)
|
||||||
\xHH byte with hexadecimal value HH (1 to 2 digits)
|
\xHH byte with hexadecimal value HH (1 to 2 digits)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
/// Special characters, that can be replaced without further logic
|
||||||
pub const SIMPLE_SPECIAL_SEQUENCES: [(&str, &str); 8] = [
|
pub const SIMPLE_SPECIAL_SEQUENCES: [(&str, &str); 8] = [
|
||||||
(r#"\a"#, "\x07"),
|
(r#"\a"#, "\x07"),
|
||||||
(r#"\b"#, "\x08"),
|
(r#"\b"#, "\x08"),
|
||||||
@ -41,6 +45,7 @@ pub const SIMPLE_SPECIAL_SEQUENCES: [(&str, &str); 8] = [
|
|||||||
(r#"\v"#, "\x0b"),
|
(r#"\v"#, "\x0b"),
|
||||||
];
|
];
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
// \NNN or \0NNN with N in octal
|
||||||
pub static ref OCTAL_REGEX: Regex = Regex::new(r#"\\(?:([1-7][0-7]{0,2}|0[0-7]{0,3}))"#)
|
pub static ref OCTAL_REGEX: Regex = Regex::new(r#"\\(?:([1-7][0-7]{0,2}|0[0-7]{0,3}))"#)
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|e| {
|
|e| {
|
||||||
@ -52,7 +57,8 @@ lazy_static! {
|
|||||||
},
|
},
|
||||||
|v| v
|
|v| v
|
||||||
);
|
);
|
||||||
pub static ref HEX_REGEX: Regex = Regex::new(r#"\\x([0-9A-F]{0,2})"#).map_or_else(
|
// \xFF with F in octal
|
||||||
|
pub static ref HEX_REGEX: Regex = Regex::new(r#"\\x([0-9A-F]{1,2})"#).map_or_else(
|
||||||
|e| {
|
|e| {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"programming error: cannot compile regex pattern for hex regex match: {}",
|
"programming error: cannot compile regex pattern for hex regex match: {}",
|
||||||
|
42
src/main.rs
42
src/main.rs
@ -1,3 +1,5 @@
|
|||||||
|
//! Basic rewrite of the echo GNU core utility, maintaining compatability
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env::args,
|
env::args,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
@ -8,6 +10,7 @@ mod consts;
|
|||||||
|
|
||||||
use crate::consts::{HELP_DIALOG, HEX_REGEX, OCTAL_REGEX, SIMPLE_SPECIAL_SEQUENCES, VERSION};
|
use crate::consts::{HELP_DIALOG, HEX_REGEX, OCTAL_REGEX, SIMPLE_SPECIAL_SEQUENCES, VERSION};
|
||||||
|
|
||||||
|
/// Settings to be read from cli
|
||||||
struct Settings {
|
struct Settings {
|
||||||
trailing_newline: bool,
|
trailing_newline: bool,
|
||||||
interpret_backslash_escapes: bool,
|
interpret_backslash_escapes: bool,
|
||||||
@ -22,6 +25,7 @@ impl Default for Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces escaped octal representations with corresponding characters
|
||||||
fn replace_octal(string: String) -> String {
|
fn replace_octal(string: String) -> String {
|
||||||
let mut res = string;
|
let mut res = string;
|
||||||
while let Some(captures) = OCTAL_REGEX.captures(
|
while let Some(captures) = OCTAL_REGEX.captures(
|
||||||
@ -29,19 +33,12 @@ fn replace_octal(string: String) -> String {
|
|||||||
&res.clone(),
|
&res.clone(),
|
||||||
) {
|
) {
|
||||||
if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) {
|
if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) {
|
||||||
let mut contents = capture.as_str();
|
|
||||||
if contents.is_empty() {
|
|
||||||
contents = "0" // GNU echo interprets \0 as \00
|
|
||||||
}
|
|
||||||
res = format!(
|
res = format!(
|
||||||
"{}{}",
|
"{}{}{}",
|
||||||
&res[..entire_match.start()],
|
&res[..entire_match.start()],
|
||||||
OCTAL_REGEX.replace(
|
&u8::from_str_radix(capture.as_str(), 8)
|
||||||
&res[entire_match.start()..],
|
.map_or_else(|_| 255 as char, |v| v as char),
|
||||||
&u8::from_str_radix(contents, 8)
|
&res[entire_match.end()..],
|
||||||
.map_or_else(|_| 255 as char, |v| v as char)
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("error matching octal regex. aborting");
|
println!("error matching octal regex. aborting");
|
||||||
@ -51,29 +48,20 @@ fn replace_octal(string: String) -> String {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces escaped hex representations with corresponding characters
|
||||||
fn replace_hex(string: String) -> String {
|
fn replace_hex(string: String) -> String {
|
||||||
let mut res = string;
|
let mut res = string;
|
||||||
let mut search_at = 0;
|
while let Some(captures) = HEX_REGEX.captures(
|
||||||
while let Some(captures) = HEX_REGEX.captures_at(
|
|
||||||
#[allow(clippy::redundant_clone)]
|
#[allow(clippy::redundant_clone)]
|
||||||
&res.clone(),
|
&res.clone(),
|
||||||
search_at,
|
|
||||||
) {
|
) {
|
||||||
if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) {
|
if let (Some(entire_match), Some(capture)) = (captures.get(0), captures.get(1)) {
|
||||||
let contents = capture.as_str();
|
|
||||||
if contents.is_empty() {
|
|
||||||
search_at = entire_match.end();
|
|
||||||
continue; // GNU echo does not interpret \x
|
|
||||||
}
|
|
||||||
res = format!(
|
res = format!(
|
||||||
"{}{}",
|
"{}{}{}",
|
||||||
&res[..entire_match.start()],
|
&res[..entire_match.start()],
|
||||||
HEX_REGEX.replace(
|
&u8::from_str_radix(capture.as_str(), 16)
|
||||||
&res[entire_match.start()..],
|
.map_or_else(|_| 255 as char, |v| v as char),
|
||||||
&u8::from_str_radix(contents, 16)
|
&res[entire_match.end()..],
|
||||||
.map_or_else(|_| 255 as char, |v| v as char)
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("error matching hex regex. aborting");
|
println!("error matching hex regex. aborting");
|
||||||
@ -83,6 +71,7 @@ fn replace_hex(string: String) -> String {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format passed argument based on settings
|
||||||
fn format_arg(arg: String, settings: &mut Settings) -> String {
|
fn format_arg(arg: String, settings: &mut Settings) -> String {
|
||||||
if settings.interpret_backslash_escapes {
|
if settings.interpret_backslash_escapes {
|
||||||
let mut res = arg;
|
let mut res = arg;
|
||||||
@ -116,6 +105,7 @@ fn format_arg(arg: String, settings: &mut Settings) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write string to stdout as unicode characters
|
||||||
fn write_as_unicode(string: String) {
|
fn write_as_unicode(string: String) {
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
if let Err(e) = stdout.lock().write_all(
|
if let Err(e) = stdout.lock().write_all(
|
||||||
|
Loading…
Reference in New Issue
Block a user