Support stdin/out for CLI; use friendlier CLI error messages; clarify replacement character usage
This commit is contained in:
parent
28aa3ea972
commit
90148f5f9b
|
@ -380,7 +380,7 @@ Spaces are removed between attributes if possible.
|
|||
|
||||
Entities are decoded if valid (see relevant parsing section) and their decoded characters as UTF-8 is shorter or equal in length.
|
||||
|
||||
Numeric entities that do not refer to a valid [Unicode Scalar Value](https://www.unicode.org/glossary/#unicode_scalar_value) are decoded to U+FFFD REPLACEMENT CHARACTER.
|
||||
Numeric entities that do not refer to a valid [Unicode Scalar Value](https://www.unicode.org/glossary/#unicode_scalar_value) are replaced with the [replacement character](https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character).
|
||||
|
||||
If an entity is unintentionally formed after decoding, the leading ampersand is encoded, e.g. `&` becomes `&`. This is done as `&` is equal to or shorter than all other entity representations of characters part of an entity (`[&#a-zA-Z0-9;]`), and there is no other conflicting entity name that starts with `amp`.
|
||||
|
||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -1,33 +1,54 @@
|
|||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{Read, stdin, stdout, Write};
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
use hyperbuild::{hyperbuild_friendly, FriendlyError};
|
||||
use hyperbuild::{FriendlyError, hyperbuild_friendly};
|
||||
|
||||
#[derive(StructOpt)]
|
||||
struct Cli {
|
||||
#[structopt(short, long, parse(from_os_str))]
|
||||
src: std::path::PathBuf,
|
||||
src: Option<std::path::PathBuf>,
|
||||
#[structopt(short, long, parse(from_os_str))]
|
||||
out: std::path::PathBuf,
|
||||
out: Option<std::path::PathBuf>,
|
||||
}
|
||||
|
||||
macro_rules! io_expect {
|
||||
($expr:expr, $msg:literal) => {
|
||||
match $expr {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", $msg);
|
||||
eprintln!("{}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Cli::from_args();
|
||||
let mut code = Vec::<u8>::new();
|
||||
let mut src_file = File::open(args.src).expect("could not open source file");
|
||||
src_file.read_to_end(&mut code).expect("could not read source file");
|
||||
let mut src_file: Box<dyn Read> = match args.src {
|
||||
Some(p) => Box::new(io_expect!(File::open(p), "could not open source file")),
|
||||
None => Box::new(stdin()),
|
||||
};
|
||||
io_expect!(src_file.read_to_end(&mut code), "could not load source code");
|
||||
match hyperbuild_friendly(&mut code) {
|
||||
Ok(out_len) => {
|
||||
let mut out_file = File::create(args.out).expect("could not open output file");
|
||||
out_file.write_all(&code[..out_len]).expect("could not write to output file");
|
||||
let mut out_file: Box<dyn Write> = match args.out {
|
||||
Some(p) => Box::new(io_expect!(File::create(p), "could not open output file")),
|
||||
None => Box::new(stdout()),
|
||||
};
|
||||
io_expect!(out_file.write_all(&code[..out_len]), "could not save minified code");
|
||||
}
|
||||
Err(FriendlyError { position, message, code_context }) => {
|
||||
eprintln!("Failed at character {}:", position);
|
||||
eprintln!("{}", message);
|
||||
eprintln!("The output file has not been touched.");
|
||||
eprintln!("-----");
|
||||
if args.out.is_some() {
|
||||
eprintln!("The output file has not been touched.");
|
||||
};
|
||||
eprintln!("--------");
|
||||
eprintln!("{}", code_context);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue