Adds --columns for Print using custom width #13

This commit is contained in:
Sharif Haason authored and David Peter committed 2022-09-11 21:45:06 +02:00
1 parent 55cf7b034c
commit b9348ffb1d
4 files changed
+114 -93

No files matched your search

+2
View File
@@ -16,6 +16,7 @@ fn main() {
let show_position_panel = true;
let use_squeezing = false;
let border_style = BorderStyle::Unicode;
let columns = 2;
let mut printer = Printer::new(
&mut handle,
@@ -24,6 +25,7 @@ fn main() {
show_position_panel,
border_style,
use_squeezing,
columns,
);
printer.print_all(&input[..]).unwrap();
}
+24 -1
View File
@@ -4,7 +4,7 @@ extern crate clap;
use std::convert::TryFrom;
use std::fs::File;
use std::io::{self, prelude::*, SeekFrom};
use std::num::NonZeroI64;
use std::num::{NonZeroI64, NonZeroU8};
use clap::{crate_name, crate_version, AppSettings, Arg, ColorChoice, Command};
@@ -149,6 +149,17 @@ fn run() -> Result<(), AnyhowError> {
A negative value is valid and calculates an offset relative to the \
end of the file.",
),
)
.arg(
Arg::new("columns")
.short('w')
.long("columns")
.takes_value(true)
.value_name("N")
.help(
"Sets the number of hex data columns to be displayed. \
Cannot be used with other width-setting options.",
),
);
let matches = command.get_matches();
@@ -267,6 +278,17 @@ fn run() -> Result<(), AnyhowError> {
.transpose()?
.unwrap_or(0);
let columns = matches
.value_of("columns")
.map(|s| {
s.parse::<NonZeroU8>().map(u8::from).context(anyhow!(
"failed to parse `--columns` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
.unwrap_or(2);
let stdout = io::stdout();
let mut stdout_lock = stdout.lock();
@@ -277,6 +299,7 @@ fn run() -> Result<(), AnyhowError> {
show_position_panel,
border_style,
squeeze,
columns,
);
printer.display_offset(skip_offset + display_offset);
printer.print_all(&mut reader).map_err(|e| anyhow!(e))?;
+71 -75
View File
@@ -154,6 +154,8 @@ pub struct Printer<'a, Writer: Write> {
byte_char_panel: Vec<String>,
squeezer: Squeezer,
display_offset: u64,
/// The number of panels to draw.
columns: u8,
}
impl<'a, Writer: Write> Printer<'a, Writer> {
@@ -164,6 +166,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
show_position_panel: bool,
border_style: BorderStyle,
use_squeeze: bool,
columns: u8,
) -> Printer<'a, Writer> {
Printer {
idx: 1,
@@ -175,7 +178,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
show_position_panel,
border_style,
header_was_printed: false,
byte_hex_panel: (0u8..=u8::max_value())
byte_hex_panel: (0u8..=u8::MAX)
.map(|i| {
let byte_hex = format!("{:02x} ", i);
if show_color {
@@ -187,7 +190,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
.collect(),
byte_char_panel: show_char_panel
.then(|| {
(0u8..=u8::max_value())
(0u8..=u8::MAX)
.map(|i| {
let byte_char = format!("{}", Byte(i).as_char());
if show_color {
@@ -199,8 +202,9 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
.collect()
})
.unwrap_or_default(),
squeezer: Squeezer::new(use_squeeze),
squeezer: Squeezer::new(use_squeeze, 8 * columns as u64),
display_offset: 0,
columns,
}
}
@@ -223,10 +227,20 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
write!(self.writer, "{}", l).ok();
}
write!(self.writer, "{h25}{c}{h25}", c = c, h25 = h25).ok();
for _ in 0..self.columns - 1 {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok();
}
if self.show_char_panel {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok();
} else {
write!(self.writer, "{h25}", h25 = h25).ok();
}
if self.show_char_panel {
writeln!(self.writer, "{c}{h8}{c}{h8}{r}", c = c, h8 = h8, r = r).ok();
for _ in 0..self.columns - 1 {
write!(self.writer, "{h8}{c}", h8 = h8, c = c).ok();
}
writeln!(self.writer, "{h8}{r}", h8 = h8, r = r).ok();
} else {
writeln!(self.writer, "{r}", r = r).ok();
}
@@ -287,36 +301,25 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.byte_char_panel[b as usize]
);
if idx == 8 {
if idx % 8 == 0 && idx % (u64::from(self.columns * 8)) != 0 {
let _ = write!(&mut self.buffer_line, "{}", self.border_style.inner_sep());
}
idx += 1;
}
if len < 8 {
let _ = writeln!(
&mut self.buffer_line,
"{0:1$}{3}{0:2$}{4}",
"",
8 - len,
8,
self.border_style.inner_sep(),
self.border_style.outer_sep(),
);
} else {
let _ = writeln!(
&mut self.buffer_line,
"{0:1$}{2}",
"",
16 - len,
self.border_style.outer_sep()
);
if len < usize::from(8 * self.columns) {
let _ = write!(&mut self.buffer_line, "{0:1$}", "", 8 - len % 8);
for _ in 0..(usize::from(8 * self.columns) - (len + (8 - len % 8))) / 8 {
let _ = write!(&mut self.buffer_line, "{2}{0:1$}", "", 8, self.border_style.inner_sep());
}
}
let _ = writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep());
}
pub fn print_byte(&mut self, b: u8) -> io::Result<()> {
if self.idx % 16 == 1 {
if self.idx % u64::from(self.columns * 8) == 1 {
self.print_header();
self.print_position_panel();
}
@@ -326,14 +329,10 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.squeezer.process(b, self.idx);
match self.idx % 16 {
8 => {
let _ = write!(&mut self.buffer_line, "{} ", self.border_style.inner_sep());
}
0 => {
self.print_textline()?;
}
_ => {}
if self.idx % u64::from(self.columns * 8) == 0 {
self.print_textline()?;
} else if self.idx % 8 == 0 {
let _ = write!(&mut self.buffer_line, "{} ", self.border_style.inner_sep());
}
self.idx += 1;
@@ -347,16 +346,15 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
if len == 0 {
if self.squeezer.active() {
self.print_position_panel();
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(),
);
write!(&mut self.buffer_line, "{0:1$}", "", 24)?;
for _ in 0..self.columns - 1 {
write!(&mut self.buffer_line, "{2}{0:1$}", "", 25, self.border_style.inner_sep())?;
}
write!(&mut self.buffer_line, "{2}{0:1$}", "", 8, self.border_style.outer_sep())?;
for _ in 0..self.columns - 1 {
write!(&mut self.buffer_line, "{2}{0:1$}", "", 8, self.border_style.inner_sep())?;
}
writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
self.writer.write_all(&self.buffer_line)?;
}
return Ok(());
@@ -364,28 +362,17 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
let squeeze_action = self.squeezer.action();
// print empty space on last line
if squeeze_action != SqueezeAction::Delete {
if len < 8 {
let _ = write!(
&mut self.buffer_line,
"{0:1$}{3}{0:2$}{4}",
"",
3 * (8 - len),
1 + 3 * 8,
self.border_style.inner_sep(),
self.border_style.outer_sep(),
);
} else {
let _ = write!(
&mut self.buffer_line,
"{0:1$}{2}",
"",
3 * (16 - len),
self.border_style.outer_sep()
);
if len < usize::from(8 * self.columns) {
write!(&mut self.buffer_line, "{0:1$}", "", 3 * (8 - len % 8))?;
// dbg!(usize::from(8 * self.columns) - (len + (8 - len % 8)));
for _ in 0..(usize::from(8 * self.columns) - (len + (8 - len % 8))) / 8 {
write!(&mut self.buffer_line, "{2}{0:1$}", "", 1 + 3 * 8, self.border_style.inner_sep())?;
}
}
write!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
}
self.print_char_panel();
match squeeze_action {
@@ -397,17 +384,26 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
} else {
String::from("*")
};
let _ = writeln!(
&mut self.buffer_line,
"{5}{0}{1:2$}{5}{1:3$}{6}{1:3$}{5}{1:4$}{6}{1:4$}{5}",
asterisk,
"",
7,
25,
8,
self.border_style.outer_sep(),
self.border_style.inner_sep(),
);
write!(&mut self.buffer_line, "{3}{0}{1:2$}{3}", asterisk, "", 7, self.border_style.outer_sep())?;
for i in 0..self.columns {
write!(&mut self.buffer_line, "{0:1$}", "", 25)?;
if i != self.columns - 1 {
write!(&mut self.buffer_line, "{}", self.border_style.inner_sep())?;
} else {
write!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
}
}
for i in 0..self.columns {
write!(&mut self.buffer_line, "{0:1$}", "", 8)?;
if i != self.columns - 1 {
write!(&mut self.buffer_line, "{}", self.border_style.inner_sep())?;
} else {
writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
}
}
}
SqueezeAction::Delete => self.buffer_line.clear(),
SqueezeAction::Ignore => (),
@@ -484,7 +480,7 @@ mod tests {
fn assert_print_all_output<Reader: Read>(input: Reader, expected_string: String) {
let mut output = vec![];
let mut printer = Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true);
let mut printer = Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true, 2);
printer.print_all(input).unwrap();
@@ -529,7 +525,7 @@ mod tests {
let mut output = vec![];
let mut printer: Printer<Vec<u8>> =
Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true);
Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true, 2);
printer.display_offset(0xdeadbeef);
printer.print_all(input).unwrap();
+17 -17
View File
@@ -22,6 +22,7 @@ enum SqueezeState {
pub struct Squeezer {
state: SqueezeState,
byte: u8,
lsize: u64,
}
#[derive(Debug, PartialEq)]
@@ -31,11 +32,8 @@ pub enum SqueezeAction {
Delete,
}
/// line size
const LSIZE: u64 = 16;
impl Squeezer {
pub fn new(enabled: bool) -> Squeezer {
pub fn new(enabled: bool, lsize: u64) -> Squeezer {
Squeezer {
state: if enabled {
SqueezeState::Probe
@@ -43,6 +41,7 @@ impl Squeezer {
SqueezeState::Disabled
},
byte: 0,
lsize,
}
}
@@ -53,7 +52,7 @@ impl Squeezer {
}
let eq = b == self.byte;
if i % LSIZE == 0 {
if i % self.lsize == 0 {
if !eq {
self.state = Probe;
} else {
@@ -68,9 +67,9 @@ impl Squeezer {
};
}
} else if !eq {
if i % LSIZE == 1 {
if i % self.lsize == 1 {
self.state = Probe;
} else if i % LSIZE != 1 {
} else if i % self.lsize != 1 {
self.state = NoSqueeze;
}
}
@@ -111,13 +110,14 @@ impl Squeezer {
mod tests {
use super::*;
const LSIZE_USIZE: usize = LSIZE as usize;
const LSIZE: u64 = 16;
const LSIZE_USIZE: usize = 16;
#[test]
fn three_same_lines() {
const LINES: usize = 3;
let v = vec![0u8; LINES * LSIZE_USIZE];
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -144,7 +144,7 @@ mod tests {
fn incomplete_while_squeeze() {
// fourth line only has 12 bytes and should be printed
let v = vec![0u8; 3 * LSIZE_USIZE + 12];
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -175,7 +175,7 @@ mod tests {
v.extend(vec![1u8; 16]);
v.extend(vec![2u8; 16]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -206,7 +206,7 @@ mod tests {
let mut v = vec![0u8; (LINES - 1) * LSIZE_USIZE];
v.extend(vec![1u8; 16]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -237,7 +237,7 @@ mod tests {
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -270,7 +270,7 @@ mod tests {
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -309,7 +309,7 @@ mod tests {
v.extend(vec![20u8; 16]); // print
v.extend(vec![0u8; 12]); // print, only 12 bytes
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -351,7 +351,7 @@ mod tests {
v.extend(vec![20u8; 16]);
v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
@@ -383,7 +383,7 @@ mod tests {
v.extend(vec![20u8; 15]);
v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true);
let mut s = Squeezer::new(true, LSIZE);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();