From 734365723ba6020312d35bd4bf7fec8988829aef Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Tue, 12 Jul 2022 11:39:24 -0400 Subject: [PATCH] Adds --columns for Print using custom width #13 --- examples/simple.rs | 2 + src/bin/hexyl.rs | 25 +++++++- src/lib.rs | 146 ++++++++++++++++++++++----------------------- src/squeezer.rs | 34 +++++------ 4 files changed, 114 insertions(+), 93 deletions(-) diff --git a/examples/simple.rs b/examples/simple.rs index 2c551cb..d4ab8c4 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -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(); } diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index 6d628fa..a25ae7f 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -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::().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))?; diff --git a/src/lib.rs b/src/lib.rs index e23bc50..578d15b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,6 +154,8 @@ pub struct Printer<'a, Writer: Write> { byte_char_panel: Vec, 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(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> = - 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(); diff --git a/src/squeezer.rs b/src/squeezer.rs index fb2100c..fb1d52a 100644 --- a/src/squeezer.rs +++ b/src/squeezer.rs @@ -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();