#[macro_use]
extern crate clap;
#[macro_use]
extern crate unic_cli;
use std::io::{self, Write};
use clap::{Arg, ErrorKind};
use unic_cli::{parsers, writers, Result};
unic_arg_enum! {
#[derive(Debug)]
enum InputFormat {
Plain,
Codepoint,
Codepoints,
Utf8Hex,
Utf16Hex
}
}
macro_rules! input_formats_help {
() => {
"INPUT FORMATS:
plain [default] Plain Unicode characters
codepoints Unicode codepoints (hex)
utf8-hex UTF-8 bytes (hex)
utf16-hex UTF-16 words (hex)
"
};
}
unic_arg_enum! {
#[derive(Debug)]
enum OutputFormat {
Plain,
Codepoint,
Codepoints,
Utf8Hex,
Utf16Hex,
BracesEscape,
Js6Escape,
RustEscape,
BracesEscapeAll,
Js6EscapeAll,
RustEscapeAll,
BracesEscapeControl,
Js6EscapeControl,
RustEscapeControl
}
}
macro_rules! output_formats_help {
() => {
"OUTPUT FORMATS:
plain [default] Plain Unicode characters
codepoints Unicode codepoints (hex)
utf8-hex UTF-8 bytes (hex)
utf16-hex UTF-16 words (hex)
braces-escape String literal with \\u{...} escapes for
| js6-escape control and non-ASCII characters
| rust-escape
braces-escape-all String literal with \\u{...} escapes for
| js6-escape-all all characters
| rust-escape-all
braces-escape-control String literal with \\u{...} escapes for
| js6-escape-control control characters
| rust-escape-control
"
};
}
fn main() {
run().expect("IO Error");
}
fn run() -> Result<()> {
let app = app_from_crate!()
.about(concat!(
env!("CARGO_PKG_DESCRIPTION"),
"\n\n",
"Write arguments to the standard output",
))
.arg(
Arg::with_name("no_newline")
.short("n")
.long("no-newline")
.help("No trailing newline"),
)
.arg(
Arg::with_name("STRINGS")
.multiple(true)
.help("Input strings (expected valid Unicode)"),
)
.arg(
Arg::with_name("input_format")
.short("i")
.long("input")
.takes_value(true)
.value_name("FORMAT")
.help("Specify input format (see list below)"),
)
.arg(
Arg::with_name("output_format")
.short("o")
.long("output")
.takes_value(true)
.value_name("FORMAT")
.help("Specify output format (see list below)"),
)
.after_help(concat!(input_formats_help!(), "\n", output_formats_help!()));
let matches = app.get_matches();
let input: String = matches
.values_of("STRINGS")
.unwrap_or_default()
.collect::<Vec<&str>>()
.join(" ");
let input_format =
value_t!(matches, "input_format", InputFormat).unwrap_or_else(|err| match err.kind {
ErrorKind::ValueValidation => {
eprintln!("{}", matches.usage());
err.exit();
}
_ => InputFormat::Plain,
});
let string: String = match input_format {
InputFormat::Plain => input,
InputFormat::Codepoint | InputFormat::Codepoints => parsers::codepoints(&input),
InputFormat::Utf8Hex => parsers::utf8_hex(&input),
InputFormat::Utf16Hex => parsers::utf16_hex(&input),
};
let chars = string.chars();
let mut output = io::stdout();
let output_format =
value_t!(matches, "output_format", OutputFormat).unwrap_or_else(|err| match err.kind {
ErrorKind::ValueValidation => err.exit(),
_ => OutputFormat::Plain,
});
match output_format {
OutputFormat::Plain => write!(output, "{}", string)?,
OutputFormat::Codepoint | OutputFormat::Codepoints => {
writers::write_as_codepoints(&mut output, chars)?
}
OutputFormat::Utf8Hex => writers::write_as_utf8_hex(&mut output, chars)?,
OutputFormat::Utf16Hex => writers::write_as_utf16_hex(&mut output, chars)?,
OutputFormat::BracesEscape | OutputFormat::Js6Escape | OutputFormat::RustEscape => {
writers::write_with_control_n_unicode_braces_escape(&mut output, chars)?
}
OutputFormat::BracesEscapeAll
| OutputFormat::Js6EscapeAll
| OutputFormat::RustEscapeAll => writers::write_with_all_braces_escape(&mut output, chars)?,
OutputFormat::BracesEscapeControl
| OutputFormat::Js6EscapeControl
| OutputFormat::RustEscapeControl => {
writers::write_with_control_braces_escape(&mut output, chars)?
}
};
if !matches.is_present("no_newline") {
writeln!(output)?;
}
Ok(())
}