1use colored::*;
3use std::io;
4use std::io::Read;
5use std::os::unix::ffi::OsStringExt;
6use encoding::types::EncodingRef;
7use clap::{Arg, App};
8use crate::decoding::DecodedString;
9
10const LABEL_SIZE: u16 = 7; pub fn parse_command_line() -> (Vec<EncodingRef>, Vec<u8>) {
13 let matches = App::new("string-inspector")
14 .version("0.0.1")
15 .about("Inspects unicode strings")
16 .arg(Arg::with_name("text")
17 .index(1)
18 .multiple(true))
19 .arg(Arg::with_name("encoding")
20 .short("e")
21 .long("encoding")
22 .value_name("ENCODING")
23 .multiple(true)
24 .number_of_values(1)
25 .possible_values(&["utf8", "latin1"])
26 .default_value("utf8")
27 .help("Encoding to include in the output")
28 .takes_value(true))
29
30 .get_matches();
31
32 let encodings: Vec<EncodingRef> = matches.values_of("encoding").unwrap()
33 .map(|e| encoding::label::encoding_from_whatwg_label(e).unwrap())
34 .collect();
35
36 let text = matches.values_of_os("text");
37
38 let buffer = match text {
39 Some(args) => {
40 let mut arg_bytes: Vec<Vec<u8>> = Vec::new();
41 for arg in args {
42 arg_bytes.push(arg.to_owned().into_vec());
43 }
44
45 arg_bytes.join(&0x20)
46 }
47 None => {
48 eprintln!("No arguments passed to program: reading text from standard input...");
49 let mut result: Vec<u8> = Vec::new();
50 io::stdin().read_to_end(&mut result).expect("Unable to read from stdin");
51 result
52 }
53 };
54
55 (encodings, buffer)
56}
57
58pub fn display_decoding(decoding: &DecodedString, max_line_width: usize) {
59 println!("[{}]", decoding.encoding.name());
60
61 let chunks = decoding.wrap_lines(max_line_width - LABEL_SIZE as usize);
62 let mut first = true;
63
64 for chunk in chunks.iter() {
65 if first {
66 first = false;
67 } else {
68 println!("");
69 }
70
71 print!("bytes: ");
72 println!("{}", chunk.format_bytes());
73
74 print!("chars: ");
75 println!("{}", chunk.format_characters());
76 }
77
78 println!("");
79 println!("{}", highlight_non_ascii(&decoding.to_string()));
80}
81
82pub fn display_decodings(decodings: &Vec<DecodedString>, max_line_width: usize) {
83 let mut first = true;
84 for decoded_string in decodings.iter() {
85 if first {
86 first = false;
87 } else {
88 println!("");
89 }
90 display_decoding(&decoded_string, max_line_width);
91 }
92}
93
94fn highlight_non_ascii(input: &str) -> String {
95 let mut output = String::new();
96
97 for character in input.chars() {
98 if character.is_ascii() {
99 output.push_str(&character.to_string().green().to_string());
100 } else {
101 output.push_str(&character.to_string().red().to_string());
102 }
103 }
104
105 output
106}