Support byte grouping

This commit is contained in:
RinHizakura authored and David Peter committed 2022-11-26 13:07:06 +01:00
1 parent 9106b899b2
commit 179c8f40a2
4 files changed
+75 -12

No files matched your search

+1
View File
@@ -18,6 +18,7 @@ fn main() {
.with_border_style(BorderStyle::Unicode) .with_border_style(BorderStyle::Unicode)
.enable_squeezing(false) .enable_squeezing(false)
.num_panels(2) .num_panels(2)
.num_group_bytes(1)
.build(); .build();
printer.print_all(&input[..]).unwrap(); printer.print_all(&input[..]).unwrap();
} }
+32 -1
View File
@@ -4,7 +4,7 @@ extern crate clap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io::{self, prelude::*, BufWriter, SeekFrom}; use std::io::{self, prelude::*, BufWriter, SeekFrom};
use std::num::{NonZeroI64, NonZeroU64}; use std::num::{NonZeroI64, NonZeroU64, NonZeroU8};
use clap::builder::ArgPredicate; use clap::builder::ArgPredicate;
use clap::{crate_name, crate_version, Arg, ArgAction, ColorChoice, Command}; use clap::{crate_name, crate_version, Arg, ArgAction, ColorChoice, Command};
@@ -166,6 +166,17 @@ fn run() -> Result<(), AnyhowError> {
based on the current terminal width", based on the current terminal width",
), ),
) )
.arg(
Arg::new("group_bytes")
.short('g')
.takes_value(true)
.value_name("N")
.help(
"Sets the number of octets per group to be displayed. \
The possible option will be 1, 2, 4, 8, otherwise it will be set \
to 1 by default.",
),
)
.arg( .arg(
Arg::new("terminal_width") Arg::new("terminal_width")
.long("terminal-width") .long("terminal-width")
@@ -337,6 +348,25 @@ fn run() -> Result<(), AnyhowError> {
2 2
}; };
let group_bytes = if let Some(group_bytes) = matches
.value_of("group_bytes")
.map(|s| {
s.parse::<NonZeroU8>().map(u8::from).context(anyhow!(
"failed to parse `-g` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
if (group_bytes <= 8) && ((group_bytes & (group_bytes - 1)) == 0) {
group_bytes
} else {
1
}
} else {
1
};
let stdout = io::stdout(); let stdout = io::stdout();
let mut stdout_lock = BufWriter::new(stdout.lock()); let mut stdout_lock = BufWriter::new(stdout.lock());
@@ -347,6 +377,7 @@ fn run() -> Result<(), AnyhowError> {
.with_border_style(border_style) .with_border_style(border_style)
.enable_squeezing(squeeze) .enable_squeezing(squeeze)
.num_panels(panels) .num_panels(panels)
.num_group_bytes(group_bytes)
.build(); .build();
printer.display_offset(skip_offset + display_offset); printer.display_offset(skip_offset + display_offset);
printer.print_all(&mut reader).map_err(|e| anyhow!(e))?; printer.print_all(&mut reader).map_err(|e| anyhow!(e))?;
+40 -9
View File
@@ -150,6 +150,7 @@ pub struct PrinterBuilder<'a, Writer: Write> {
border_style: BorderStyle, border_style: BorderStyle,
use_squeeze: bool, use_squeeze: bool,
panels: u64, panels: u64,
group_bytes: u8,
} }
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
@@ -162,6 +163,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
border_style: BorderStyle::Unicode, border_style: BorderStyle::Unicode,
use_squeeze: true, use_squeeze: true,
panels: 2, panels: 2,
group_bytes: 1,
} }
} }
@@ -195,6 +197,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
self self
} }
pub fn num_group_bytes(mut self, num: u8) -> Self {
self.group_bytes = num;
self
}
pub fn build(self) -> Printer<'a, Writer> { pub fn build(self) -> Printer<'a, Writer> {
Printer::new( Printer::new(
self.writer, self.writer,
@@ -204,6 +211,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
self.border_style, self.border_style,
self.use_squeeze, self.use_squeeze,
self.panels, self.panels,
self.group_bytes,
) )
} }
} }
@@ -226,6 +234,8 @@ pub struct Printer<'a, Writer: Write> {
/// The number of panels to draw. /// The number of panels to draw.
panels: u64, panels: u64,
squeeze_byte: usize, squeeze_byte: usize,
/// The number of octets per group.
group_bytes: u8,
} }
impl<'a, Writer: Write> Printer<'a, Writer> { impl<'a, Writer: Write> Printer<'a, Writer> {
@@ -237,6 +247,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
border_style: BorderStyle, border_style: BorderStyle,
use_squeeze: bool, use_squeeze: bool,
panels: u64, panels: u64,
group_bytes: u8,
) -> Printer<'a, Writer> { ) -> Printer<'a, Writer> {
Printer { Printer {
idx: 0, idx: 0,
@@ -295,6 +306,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
display_offset: 0, display_offset: 0,
panels, panels,
squeeze_byte: 0x00, squeeze_byte: 0x00,
group_bytes,
} }
} }
@@ -303,13 +315,21 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self self
} }
fn panel_sz(&self) -> usize {
// add one to include the trailing space of a group
let group_sz = 2 * self.group_bytes as usize + 1;
let group_per_panel = 8 / self.group_bytes as usize;
// add one to include the leading space
1 + group_sz * group_per_panel
}
fn write_border(&mut self, border_elements: BorderElements) -> io::Result<()> { fn write_border(&mut self, border_elements: BorderElements) -> io::Result<()> {
let h = border_elements.horizontal_line; let h = border_elements.horizontal_line;
let c = border_elements.column_separator; let c = border_elements.column_separator;
let l = border_elements.left_corner; let l = border_elements.left_corner;
let r = border_elements.right_corner; let r = border_elements.right_corner;
let h8 = h.to_string().repeat(8); let h8 = h.to_string().repeat(8);
let h25 = h.to_string().repeat(25); let h_repeat = h.to_string().repeat(self.panel_sz());
if self.show_position_panel { if self.show_position_panel {
write!(self.writer, "{l}{h8}{c}", l = l, c = c, h8 = h8).ok(); write!(self.writer, "{l}{h8}{c}", l = l, c = c, h8 = h8).ok();
@@ -318,12 +338,12 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
} }
for _ in 0..self.panels - 1 { for _ in 0..self.panels - 1 {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok(); write!(self.writer, "{h_repeat}{c}", h_repeat = h_repeat, c = c).ok();
} }
if self.show_char_panel { if self.show_char_panel {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok(); write!(self.writer, "{h_repeat}{c}", h_repeat = h_repeat, c = c).ok();
} else { } else {
write!(self.writer, "{h25}", h25 = h25).ok(); write!(self.writer, "{h_repeat}", h_repeat = h_repeat).ok();
} }
if self.show_char_panel { if self.show_char_panel {
@@ -433,13 +453,17 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.writer self.writer
.write_all(self.byte_char_panel_g[b'*' as usize].as_bytes())?; .write_all(self.byte_char_panel_g[b'*' as usize].as_bytes())?;
} else { } else {
self.writer.write_all(b" ")?; if i % (self.group_bytes as usize) == 0 {
self.writer.write_all(b" ")?;
}
} }
self.writer.write_all(b" ")?; self.writer.write_all(b" ")?;
} }
Squeezer::Delete => self.writer.write_all(b" ")?, Squeezer::Delete => self.writer.write_all(b" ")?,
Squeezer::Ignore | Squeezer::Disabled => { Squeezer::Ignore | Squeezer::Disabled => {
self.writer.write_all(b" ")?; if i % (self.group_bytes as usize) == 0 {
self.writer.write_all(b" ")?;
}
self.writer self.writer
.write_all(self.byte_hex_panel[b as usize].as_bytes())?; .write_all(self.byte_hex_panel[b as usize].as_bytes())?;
} }
@@ -562,8 +586,11 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
} }
write!( write!(
self.writer, self.writer,
"{0:2}{1:24}{0}{0:>26}", "{0:2}{1:2$}{0}{0:>3$}",
"│", "No content to print" "│",
"No content",
self.panel_sz() - 1,
self.panel_sz() + 1,
)?; )?;
if self.show_char_panel { if self.show_char_panel {
write!(self.writer, "{0:>9}{0:>9}", "│")?; write!(self.writer, "{0:>9}{0:>9}", "│")?;
@@ -614,6 +641,7 @@ mod tests {
BorderStyle::Unicode, BorderStyle::Unicode,
true, true,
2, 2,
1,
); );
printer.print_all(input).unwrap(); printer.print_all(input).unwrap();
@@ -627,7 +655,7 @@ mod tests {
let input = io::empty(); let input = io::empty();
let expected_string = "\ let expected_string = "\
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐ ┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│ │ No content to print │ │ │ │ │ │ No content │ │ │ │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘ └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
" "
.to_owned(); .to_owned();
@@ -666,6 +694,7 @@ mod tests {
BorderStyle::Unicode, BorderStyle::Unicode,
true, true,
2, 2,
1,
); );
printer.display_offset(0xdeadbeef); printer.display_offset(0xdeadbeef);
@@ -697,6 +726,7 @@ mod tests {
BorderStyle::Unicode, BorderStyle::Unicode,
true, true,
4, 4,
1,
); );
printer.print_all(input).unwrap(); printer.print_all(input).unwrap();
@@ -754,6 +784,7 @@ mod tests {
BorderStyle::Unicode, BorderStyle::Unicode,
true, true,
3, 3,
1,
); );
printer.print_all(input).unwrap(); printer.print_all(input).unwrap();
+2 -2
View File
@@ -51,7 +51,7 @@ mod basic {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│ │ No content to print │ │ │ │\n\ │ │ No content │ │ │ │\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }
@@ -140,7 +140,7 @@ mod skip {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│ │ No content to print │ │ │ │\n\ │ │ No content │ │ │ │\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }