Adds squeeze support

The squeeze feature is implement as for hexdump. Reoccurring lines will
be squeezed together and visualized with an asterisk. Further hexyl
received an additional command line argument '-v|--no-squeezing' to
disable squeezing. Squeezing is enabled by default.

If the squeezing goes until the end of the input data, an empty line
with address next to last line will be printed to indicate the highest
address (again similar to hexdump).
This commit is contained in:
Armin Widegreen authored and David Peter committed 2019-04-13 18:19:15 +02:00
1 parent 2c7c857ccc
commit 6978f7a277
2 files changed
+344 -21

No files matched your search

+84 -21
View File
@@ -4,6 +4,8 @@ extern crate ansi_term;
extern crate atty;
extern crate ctrlc;
mod squeezer;
use std::fs::File;
use std::io::{self, prelude::*, StdoutLock};
use std::sync::atomic::{AtomicBool, Ordering};
@@ -15,6 +17,7 @@ use ansi_term::Color;
use ansi_term::Color::Fixed;
use atty::Stream;
use squeezer::{SqueezeAction, Squeezer};
const BUFFER_SIZE: usize = 256;
@@ -159,10 +162,16 @@ struct Printer<'a> {
header_was_printed: bool,
byte_hex_table: Vec<String>,
byte_char_table: Vec<String>,
squeezer: Squeezer,
}
impl<'a> Printer<'a> {
fn new(stdout: StdoutLock, show_color: bool, border_style: BorderStyle) -> Printer {
fn new(
stdout: StdoutLock,
show_color: bool,
border_style: BorderStyle,
use_squeeze: bool,
) -> Printer {
Printer {
idx: 1,
raw_line: vec![],
@@ -191,6 +200,7 @@ impl<'a> Printer<'a> {
}
})
.collect(),
squeezer: Squeezer::new(use_squeeze),
}
}
@@ -232,32 +242,38 @@ impl<'a> Printer<'a> {
}
}
fn print_position_indicator(&mut self) {
if !self.header_was_printed {
self.header();
self.header_was_printed = true;
}
let style = COLOR_OFFSET.normal();
let byte_index = format!("{:08x}", self.idx - 1);
let formatted_string = if self.show_color {
format!("{}", style.paint(byte_index))
} else {
byte_index
};
let _ = write!(
&mut self.buffer_line,
"{}{}{} ",
self.border_style.outer_sep(),
formatted_string,
self.border_style.outer_sep()
);
}
fn print_byte(&mut self, b: u8) -> io::Result<()> {
if self.idx % 16 == 1 {
if !self.header_was_printed {
self.header();
self.header_was_printed = true;
}
let style = COLOR_OFFSET.normal();
let byte_index = format!("{:08x}", self.idx - 1);
let formatted_string = if self.show_color {
format!("{}", style.paint(byte_index))
} else {
byte_index
};
let _ = write!(
&mut self.buffer_line,
"{}{}{} ",
self.border_style.outer_sep(),
formatted_string,
self.border_style.outer_sep()
);
self.print_position_indicator();
}
write!(&mut self.buffer_line, "{}", self.byte_hex_table[b as usize])?;
self.raw_line.push(b);
self.squeezer.process(&b, &self.idx);
match self.idx % 16 {
8 => {
let _ = write!(&mut self.buffer_line, "{} ", self.border_style.inner_sep());
@@ -277,6 +293,20 @@ impl<'a> Printer<'a> {
let len = self.raw_line.len();
if len == 0 {
if self.squeezer.active() {
self.print_position_indicator();
let _ = writeln!(
&mut self.buffer_line,
"{0:1$}{4}{0:2$}{5}{0:3$}{4}{0:3$}{5}",
"",
24,
25,
8,
self.border_style.inner_sep(),
self.border_style.outer_sep(),
);
self.stdout.write_all(&self.buffer_line)?;
}
return Ok(());
}
@@ -334,6 +364,27 @@ impl<'a> Printer<'a> {
self.border_style.outer_sep()
);
}
match self.squeezer.action() {
SqueezeAction::Print => {
self.buffer_line.clear();
let style = COLOR_OFFSET.normal();
let _ = writeln!(
&mut self.buffer_line,
"{5}{0}{1:2$}{5}{1:3$}{6}{1:3$}{5}{1:4$}{6}{1:4$}{5}",
style.paint("*"),
"",
7,
25,
8,
self.border_style.outer_sep(),
self.border_style.inner_sep(),
);
}
SqueezeAction::Delete => self.buffer_line.clear(),
SqueezeAction::Ignore => (),
}
self.stdout.write_all(&self.buffer_line)?;
self.raw_line.clear();
@@ -368,6 +419,16 @@ fn run() -> Result<(), Box<::std::error::Error>> {
.value_name("N")
.help("An alias for -n/--length"),
)
.arg(
Arg::with_name("nosqueezing")
.short("v")
.long("no-squeezing")
.help(
"Displays all input data. Otherwise any number of groups of output \
lines which would be identical to the preceding group of lines, are \
replaced with a line comprised of a single asterisk.",
),
)
.arg(
Arg::with_name("color")
.long("color")
@@ -422,6 +483,8 @@ fn run() -> Result<(), Box<::std::error::Error>> {
_ => BorderStyle::None,
};
let squeeze = !matches.is_present("nosqueezing");
// Set up Ctrl-C handler
let cancelled = Arc::new(AtomicBool::new(false));
let c = cancelled.clone();
@@ -432,7 +495,7 @@ fn run() -> Result<(), Box<::std::error::Error>> {
.expect("Error setting Ctrl-C handler");
let stdout = io::stdout();
let mut printer = Printer::new(stdout.lock(), show_color, border_style);
let mut printer = Printer::new(stdout.lock(), show_color, border_style, squeeze);
let mut buffer = [0; BUFFER_SIZE];
'mainloop: loop {