mirror of
https://github.com/sharkdp/hexyl.git
synced 2026-10-26 20:16:31 +00:00
lib: main and run in bin, everything else in lib
This commit is contained in:
1 parent
fb49b633b2
commit
ca8970b5cc
2 files changed
+393
-384
No files matched your search
+4
-384
@@ -5,398 +5,18 @@ use atty;
|
||||
use ctrlc;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, prelude::*, StdoutLock};
|
||||
use std::io::{self, prelude::*};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use clap::{App, AppSettings, Arg};
|
||||
|
||||
use ansi_term::Color;
|
||||
use ansi_term::Color::Fixed;
|
||||
|
||||
use atty::Stream;
|
||||
use hexyl::squeezer::{SqueezeAction, Squeezer};
|
||||
|
||||
use hexyl::{BorderStyle, Printer};
|
||||
|
||||
const BUFFER_SIZE: usize = 256;
|
||||
|
||||
const COLOR_NULL: Color = Fixed(242); // grey
|
||||
const COLOR_OFFSET: Color = Fixed(242); // grey
|
||||
const COLOR_ASCII_PRINTABLE: Color = Color::Cyan;
|
||||
const COLOR_ASCII_WHITESPACE: Color = Color::Green;
|
||||
const COLOR_ASCII_OTHER: Color = Color::Purple;
|
||||
const COLOR_NONASCII: Color = Color::Yellow;
|
||||
|
||||
enum ByteCategory {
|
||||
Null,
|
||||
AsciiPrintable,
|
||||
AsciiWhitespace,
|
||||
AsciiOther,
|
||||
NonAscii,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Byte(u8);
|
||||
|
||||
impl Byte {
|
||||
fn category(self) -> ByteCategory {
|
||||
if self.0 == 0x00 {
|
||||
ByteCategory::Null
|
||||
} else if self.0.is_ascii_alphanumeric()
|
||||
|| self.0.is_ascii_punctuation()
|
||||
|| self.0.is_ascii_graphic()
|
||||
{
|
||||
ByteCategory::AsciiPrintable
|
||||
} else if self.0.is_ascii_whitespace() {
|
||||
ByteCategory::AsciiWhitespace
|
||||
} else if self.0.is_ascii() {
|
||||
ByteCategory::AsciiOther
|
||||
} else {
|
||||
ByteCategory::NonAscii
|
||||
}
|
||||
}
|
||||
|
||||
fn color(self) -> &'static Color {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => &COLOR_NULL,
|
||||
AsciiPrintable => &COLOR_ASCII_PRINTABLE,
|
||||
AsciiWhitespace => &COLOR_ASCII_WHITESPACE,
|
||||
AsciiOther => &COLOR_ASCII_OTHER,
|
||||
NonAscii => &COLOR_NONASCII,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_char(self) -> char {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => '0',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||
AsciiWhitespace => '_',
|
||||
AsciiOther => '•',
|
||||
NonAscii => '×',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BorderElements {
|
||||
left_corner: char,
|
||||
horizontal_line: char,
|
||||
column_separator: char,
|
||||
right_corner: char,
|
||||
}
|
||||
|
||||
enum BorderStyle {
|
||||
Unicode,
|
||||
Ascii,
|
||||
None,
|
||||
}
|
||||
|
||||
impl BorderStyle {
|
||||
fn header_elems(&self) -> Option<BorderElements> {
|
||||
match self {
|
||||
BorderStyle::Unicode => Some(BorderElements {
|
||||
left_corner: '┌',
|
||||
horizontal_line: '─',
|
||||
column_separator: '┬',
|
||||
right_corner: '┐',
|
||||
}),
|
||||
BorderStyle::Ascii => Some(BorderElements {
|
||||
left_corner: '+',
|
||||
horizontal_line: '-',
|
||||
column_separator: '+',
|
||||
right_corner: '+',
|
||||
}),
|
||||
BorderStyle::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn footer_elems(&self) -> Option<BorderElements> {
|
||||
match self {
|
||||
BorderStyle::Unicode => Some(BorderElements {
|
||||
left_corner: '└',
|
||||
horizontal_line: '─',
|
||||
column_separator: '┴',
|
||||
right_corner: '┘',
|
||||
}),
|
||||
BorderStyle::Ascii => Some(BorderElements {
|
||||
left_corner: '+',
|
||||
horizontal_line: '-',
|
||||
column_separator: '+',
|
||||
right_corner: '+',
|
||||
}),
|
||||
BorderStyle::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn outer_sep(&self) -> char {
|
||||
match self {
|
||||
BorderStyle::Unicode => '│',
|
||||
BorderStyle::Ascii => '|',
|
||||
BorderStyle::None => ' ',
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_sep(&self) -> char {
|
||||
match self {
|
||||
BorderStyle::Unicode => '┊',
|
||||
BorderStyle::Ascii => '|',
|
||||
BorderStyle::None => ' ',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Printer<'a> {
|
||||
idx: usize,
|
||||
/// The raw bytes used as input for the current line.
|
||||
raw_line: Vec<u8>,
|
||||
/// The buffered line built with each byte, ready to print to stdout.
|
||||
buffer_line: Vec<u8>,
|
||||
stdout: StdoutLock<'a>,
|
||||
show_color: bool,
|
||||
border_style: BorderStyle,
|
||||
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,
|
||||
use_squeeze: bool,
|
||||
) -> Printer<'_> {
|
||||
Printer {
|
||||
idx: 1,
|
||||
raw_line: vec![],
|
||||
buffer_line: vec![],
|
||||
stdout,
|
||||
show_color,
|
||||
border_style,
|
||||
header_was_printed: false,
|
||||
byte_hex_table: (0u8..=u8::max_value())
|
||||
.map(|i| {
|
||||
let byte_hex = format!("{:02x} ", i);
|
||||
if show_color {
|
||||
Byte(i).color().paint(byte_hex).to_string()
|
||||
} else {
|
||||
byte_hex
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
byte_char_table: (0u8..=u8::max_value())
|
||||
.map(|i| {
|
||||
let byte_char = format!("{}", Byte(i).as_char());
|
||||
if show_color {
|
||||
Byte(i).color().paint(byte_char).to_string()
|
||||
} else {
|
||||
byte_char
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
squeezer: Squeezer::new(use_squeeze),
|
||||
}
|
||||
}
|
||||
|
||||
fn header(&mut self) {
|
||||
if let Some(border_elements) = self.border_style.header_elems() {
|
||||
let h = border_elements.horizontal_line;
|
||||
let h8 = h.to_string().repeat(8);
|
||||
let h25 = h.to_string().repeat(25);
|
||||
|
||||
writeln!(
|
||||
self.stdout,
|
||||
"{l}{h8}{c}{h25}{c}{h25}{c}{h8}{c}{h8}{r}",
|
||||
l = border_elements.left_corner,
|
||||
c = border_elements.column_separator,
|
||||
r = border_elements.right_corner,
|
||||
h8 = h8,
|
||||
h25 = h25
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn footer(&mut self) {
|
||||
if let Some(border_elements) = self.border_style.footer_elems() {
|
||||
let h = border_elements.horizontal_line;
|
||||
let h8 = h.to_string().repeat(8);
|
||||
let h25 = h.to_string().repeat(25);
|
||||
|
||||
writeln!(
|
||||
self.stdout,
|
||||
"{l}{h8}{c}{h25}{c}{h25}{c}{h8}{c}{h8}{r}",
|
||||
l = border_elements.left_corner,
|
||||
c = border_elements.column_separator,
|
||||
r = border_elements.right_corner,
|
||||
h8 = h8,
|
||||
h25 = h25
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
0 => {
|
||||
self.print_textline()?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.idx += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_textline(&mut self) -> io::Result<()> {
|
||||
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(());
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
let mut idx = 1;
|
||||
for &b in self.raw_line.iter() {
|
||||
let _ = write!(
|
||||
&mut self.buffer_line,
|
||||
"{}",
|
||||
self.byte_char_table[b as usize]
|
||||
);
|
||||
|
||||
if idx == 8 {
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
match self.squeezer.action() {
|
||||
SqueezeAction::Print => {
|
||||
self.buffer_line.clear();
|
||||
let style = COLOR_OFFSET.normal();
|
||||
let asterisk = if self.show_color {
|
||||
format!("{}", style.paint("*"))
|
||||
} 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(),
|
||||
);
|
||||
}
|
||||
SqueezeAction::Delete => self.buffer_line.clear(),
|
||||
SqueezeAction::Ignore => (),
|
||||
}
|
||||
|
||||
self.stdout.write_all(&self.buffer_line)?;
|
||||
|
||||
self.raw_line.clear();
|
||||
self.buffer_line.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let app = App::new(crate_name!())
|
||||
.setting(AppSettings::ColorAuto)
|
||||
@@ -524,7 +144,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Finish last line
|
||||
printer.print_textline().ok();
|
||||
if !printer.header_was_printed {
|
||||
if !printer.header_was_printed() {
|
||||
printer.header();
|
||||
}
|
||||
printer.footer();
|
||||
|
||||
+389
@@ -1 +1,390 @@
|
||||
pub mod squeezer;
|
||||
|
||||
use std::io::{self, StdoutLock, Write};
|
||||
|
||||
use ansi_term::Color;
|
||||
use ansi_term::Color::Fixed;
|
||||
|
||||
use squeezer::{SqueezeAction, Squeezer};
|
||||
|
||||
const COLOR_NULL: Color = Fixed(242); // grey
|
||||
const COLOR_OFFSET: Color = Fixed(242); // grey
|
||||
const COLOR_ASCII_PRINTABLE: Color = Color::Cyan;
|
||||
const COLOR_ASCII_WHITESPACE: Color = Color::Green;
|
||||
const COLOR_ASCII_OTHER: Color = Color::Purple;
|
||||
const COLOR_NONASCII: Color = Color::Yellow;
|
||||
|
||||
pub enum ByteCategory {
|
||||
Null,
|
||||
AsciiPrintable,
|
||||
AsciiWhitespace,
|
||||
AsciiOther,
|
||||
NonAscii,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Byte(u8);
|
||||
|
||||
impl Byte {
|
||||
fn category(self) -> ByteCategory {
|
||||
if self.0 == 0x00 {
|
||||
ByteCategory::Null
|
||||
} else if self.0.is_ascii_alphanumeric()
|
||||
|| self.0.is_ascii_punctuation()
|
||||
|| self.0.is_ascii_graphic()
|
||||
{
|
||||
ByteCategory::AsciiPrintable
|
||||
} else if self.0.is_ascii_whitespace() {
|
||||
ByteCategory::AsciiWhitespace
|
||||
} else if self.0.is_ascii() {
|
||||
ByteCategory::AsciiOther
|
||||
} else {
|
||||
ByteCategory::NonAscii
|
||||
}
|
||||
}
|
||||
|
||||
fn color(self) -> &'static Color {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => &COLOR_NULL,
|
||||
AsciiPrintable => &COLOR_ASCII_PRINTABLE,
|
||||
AsciiWhitespace => &COLOR_ASCII_WHITESPACE,
|
||||
AsciiOther => &COLOR_ASCII_OTHER,
|
||||
NonAscii => &COLOR_NONASCII,
|
||||
}
|
||||
}
|
||||
|
||||
fn as_char(self) -> char {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => '0',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||
AsciiWhitespace => '_',
|
||||
AsciiOther => '•',
|
||||
NonAscii => '×',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BorderElements {
|
||||
left_corner: char,
|
||||
horizontal_line: char,
|
||||
column_separator: char,
|
||||
right_corner: char,
|
||||
}
|
||||
|
||||
pub enum BorderStyle {
|
||||
Unicode,
|
||||
Ascii,
|
||||
None,
|
||||
}
|
||||
|
||||
impl BorderStyle {
|
||||
fn header_elems(&self) -> Option<BorderElements> {
|
||||
match self {
|
||||
BorderStyle::Unicode => Some(BorderElements {
|
||||
left_corner: '┌',
|
||||
horizontal_line: '─',
|
||||
column_separator: '┬',
|
||||
right_corner: '┐',
|
||||
}),
|
||||
BorderStyle::Ascii => Some(BorderElements {
|
||||
left_corner: '+',
|
||||
horizontal_line: '-',
|
||||
column_separator: '+',
|
||||
right_corner: '+',
|
||||
}),
|
||||
BorderStyle::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn footer_elems(&self) -> Option<BorderElements> {
|
||||
match self {
|
||||
BorderStyle::Unicode => Some(BorderElements {
|
||||
left_corner: '└',
|
||||
horizontal_line: '─',
|
||||
column_separator: '┴',
|
||||
right_corner: '┘',
|
||||
}),
|
||||
BorderStyle::Ascii => Some(BorderElements {
|
||||
left_corner: '+',
|
||||
horizontal_line: '-',
|
||||
column_separator: '+',
|
||||
right_corner: '+',
|
||||
}),
|
||||
BorderStyle::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn outer_sep(&self) -> char {
|
||||
match self {
|
||||
BorderStyle::Unicode => '│',
|
||||
BorderStyle::Ascii => '|',
|
||||
BorderStyle::None => ' ',
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_sep(&self) -> char {
|
||||
match self {
|
||||
BorderStyle::Unicode => '┊',
|
||||
BorderStyle::Ascii => '|',
|
||||
BorderStyle::None => ' ',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Printer<'a> {
|
||||
idx: usize,
|
||||
/// The raw bytes used as input for the current line.
|
||||
raw_line: Vec<u8>,
|
||||
/// The buffered line built with each byte, ready to print to stdout.
|
||||
buffer_line: Vec<u8>,
|
||||
stdout: StdoutLock<'a>,
|
||||
show_color: bool,
|
||||
border_style: BorderStyle,
|
||||
header_was_printed: bool,
|
||||
byte_hex_table: Vec<String>,
|
||||
byte_char_table: Vec<String>,
|
||||
squeezer: Squeezer,
|
||||
}
|
||||
|
||||
impl<'a> Printer<'a> {
|
||||
pub fn new(
|
||||
stdout: StdoutLock<'_>,
|
||||
show_color: bool,
|
||||
border_style: BorderStyle,
|
||||
use_squeeze: bool,
|
||||
) -> Printer<'_> {
|
||||
Printer {
|
||||
idx: 1,
|
||||
raw_line: vec![],
|
||||
buffer_line: vec![],
|
||||
stdout,
|
||||
show_color,
|
||||
border_style,
|
||||
header_was_printed: false,
|
||||
byte_hex_table: (0u8..=u8::max_value())
|
||||
.map(|i| {
|
||||
let byte_hex = format!("{:02x} ", i);
|
||||
if show_color {
|
||||
Byte(i).color().paint(byte_hex).to_string()
|
||||
} else {
|
||||
byte_hex
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
byte_char_table: (0u8..=u8::max_value())
|
||||
.map(|i| {
|
||||
let byte_char = format!("{}", Byte(i).as_char());
|
||||
if show_color {
|
||||
Byte(i).color().paint(byte_char).to_string()
|
||||
} else {
|
||||
byte_char
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
squeezer: Squeezer::new(use_squeeze),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn header(&mut self) {
|
||||
if let Some(border_elements) = self.border_style.header_elems() {
|
||||
let h = border_elements.horizontal_line;
|
||||
let h8 = h.to_string().repeat(8);
|
||||
let h25 = h.to_string().repeat(25);
|
||||
|
||||
writeln!(
|
||||
self.stdout,
|
||||
"{l}{h8}{c}{h25}{c}{h25}{c}{h8}{c}{h8}{r}",
|
||||
l = border_elements.left_corner,
|
||||
c = border_elements.column_separator,
|
||||
r = border_elements.right_corner,
|
||||
h8 = h8,
|
||||
h25 = h25
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn footer(&mut self) {
|
||||
if let Some(border_elements) = self.border_style.footer_elems() {
|
||||
let h = border_elements.horizontal_line;
|
||||
let h8 = h.to_string().repeat(8);
|
||||
let h25 = h.to_string().repeat(25);
|
||||
|
||||
writeln!(
|
||||
self.stdout,
|
||||
"{l}{h8}{c}{h25}{c}{h25}{c}{h8}{c}{h8}{r}",
|
||||
l = border_elements.left_corner,
|
||||
c = border_elements.column_separator,
|
||||
r = border_elements.right_corner,
|
||||
h8 = h8,
|
||||
h25 = h25
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
pub fn print_byte(&mut self, b: u8) -> io::Result<()> {
|
||||
if self.idx % 16 == 1 {
|
||||
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());
|
||||
}
|
||||
0 => {
|
||||
self.print_textline()?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.idx += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_textline(&mut self) -> io::Result<()> {
|
||||
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(());
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
let mut idx = 1;
|
||||
for &b in self.raw_line.iter() {
|
||||
let _ = write!(
|
||||
&mut self.buffer_line,
|
||||
"{}",
|
||||
self.byte_char_table[b as usize]
|
||||
);
|
||||
|
||||
if idx == 8 {
|
||||
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()
|
||||
);
|
||||
}
|
||||
|
||||
match self.squeezer.action() {
|
||||
SqueezeAction::Print => {
|
||||
self.buffer_line.clear();
|
||||
let style = COLOR_OFFSET.normal();
|
||||
let asterisk = if self.show_color {
|
||||
format!("{}", style.paint("*"))
|
||||
} 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(),
|
||||
);
|
||||
}
|
||||
SqueezeAction::Delete => self.buffer_line.clear(),
|
||||
SqueezeAction::Ignore => (),
|
||||
}
|
||||
|
||||
self.stdout.write_all(&self.buffer_line)?;
|
||||
|
||||
self.raw_line.clear();
|
||||
self.buffer_line.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn header_was_printed(&self) -> bool {
|
||||
self.header_was_printed
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user