mirror of
https://github.com/sharkdp/hexyl.git
synced 2026-10-30 09:05:54 +00:00
Add new braille character table and color schemes (#247)
* Add new braille character table and color schemes * Add character for tab and change color for 0x7f --------- Co-authored-by: David Peter <mail@david-peter.de>
This commit is contained in:
1 parent
9ef7c346dd
commit
f2547aed69
4 files changed
+179
-14
No files matched your search
+93
-13
@@ -43,6 +43,24 @@ pub enum CharacterTable {
|
||||
/// Uses code page 437 (for non-ASCII bytes).
|
||||
#[value(name = "codepage-437")]
|
||||
CP437,
|
||||
|
||||
/// Uses braille characters for non-printable bytes.
|
||||
Braille,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, ValueEnum)]
|
||||
#[non_exhaustive]
|
||||
pub enum ColorScheme {
|
||||
/// Show the default colors: bright black for NULL bytes, green for ASCII
|
||||
/// space characters and non-printable ASCII, cyan for printable ASCII characters,
|
||||
/// and yellow for non-ASCII bytes.
|
||||
#[default]
|
||||
Default,
|
||||
|
||||
/// Show bright black for NULL bytes, cyan for printable ASCII characters, a gradient
|
||||
/// from pink to violet for non-printable ASCII characters and a heatmap-like gradient
|
||||
/// from red to yellow to white for non-ASCII bytes.
|
||||
Gradient,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, ValueEnum)]
|
||||
@@ -81,14 +99,29 @@ impl Byte {
|
||||
}
|
||||
}
|
||||
|
||||
fn color(self) -> &'static [u8] {
|
||||
fn color(self, color_scheme: ColorScheme) -> &'static [u8] {
|
||||
use crate::ByteCategory::*;
|
||||
match self.category() {
|
||||
Null => COLOR_NULL.as_bytes(),
|
||||
AsciiPrintable => COLOR_ASCII_PRINTABLE.as_bytes(),
|
||||
AsciiWhitespace => COLOR_ASCII_WHITESPACE.as_bytes(),
|
||||
AsciiOther => COLOR_ASCII_OTHER.as_bytes(),
|
||||
NonAscii => COLOR_NONASCII.as_bytes(),
|
||||
match color_scheme {
|
||||
ColorScheme::Default => match self.category() {
|
||||
Null => COLOR_NULL.as_bytes(),
|
||||
AsciiPrintable => COLOR_ASCII_PRINTABLE.as_bytes(),
|
||||
AsciiWhitespace => COLOR_ASCII_WHITESPACE.as_bytes(),
|
||||
AsciiOther => COLOR_ASCII_OTHER.as_bytes(),
|
||||
NonAscii => COLOR_NONASCII.as_bytes(),
|
||||
},
|
||||
ColorScheme::Gradient => match self.category() {
|
||||
Null => COLOR_NULL_RGB,
|
||||
AsciiWhitespace if self.0 == b' ' => &COLOR_GRADIENT_ASCII_PRINTABLE[0],
|
||||
AsciiPrintable => &COLOR_GRADIENT_ASCII_PRINTABLE[(self.0 - b' ') as usize],
|
||||
AsciiWhitespace | AsciiOther => {
|
||||
if self.0 == 0x7f {
|
||||
COLOR_DEL
|
||||
} else {
|
||||
&COLOR_GRADIENT_ASCII_NONPRINTABLE[self.0 as usize - 1]
|
||||
}
|
||||
}
|
||||
NonAscii => &COLOR_GRADIENT_NONASCII[(self.0 - 128) as usize],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +146,37 @@ impl Byte {
|
||||
},
|
||||
CharacterTable::CP1047 => CP1047[self.0 as usize],
|
||||
CharacterTable::CP437 => CP437[self.0 as usize],
|
||||
CharacterTable::Braille => match self.category() {
|
||||
// null is important enough to get its own symbol
|
||||
Null => '⋄',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == b' ' => ' ',
|
||||
// `\t`, `\n` and `\r` are important enough to get their own symbols
|
||||
AsciiWhitespace if self.0 == b'\t' => '→',
|
||||
AsciiWhitespace if self.0 == b'\n' => '↵',
|
||||
AsciiWhitespace if self.0 == b'\r' => '←',
|
||||
AsciiWhitespace | AsciiOther | NonAscii => {
|
||||
/// Adjust the bits from the original number to a new number.
|
||||
///
|
||||
/// Bit positions in braille are adjusted as follows:
|
||||
///
|
||||
/// ```text
|
||||
/// 0 3 => 0 1
|
||||
/// 1 4 => 2 3
|
||||
/// 2 5 => 4 5
|
||||
/// 6 7 => 6 7
|
||||
/// ```
|
||||
fn to_braille_bits(byte: u8) -> u8 {
|
||||
let mut out = 0;
|
||||
for (from, to) in [0, 3, 1, 4, 2, 5, 6, 7].into_iter().enumerate() {
|
||||
out |= (byte >> from & 1) << to;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
char::from_u32(0x2800 + to_braille_bits(self.0) as u32).unwrap()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,6 +267,7 @@ pub struct PrinterBuilder<'a, Writer: Write> {
|
||||
base: Base,
|
||||
endianness: Endianness,
|
||||
character_table: CharacterTable,
|
||||
color_scheme: ColorScheme,
|
||||
}
|
||||
|
||||
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
@@ -219,6 +284,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
base: Base::Hexadecimal,
|
||||
endianness: Endianness::Big,
|
||||
character_table: CharacterTable::Default,
|
||||
color_scheme: ColorScheme::Default,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +338,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn color_scheme(mut self, color_scheme: ColorScheme) -> Self {
|
||||
self.color_scheme = color_scheme;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Printer<'a, Writer> {
|
||||
Printer::new(
|
||||
self.writer,
|
||||
@@ -285,6 +356,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
self.base,
|
||||
self.endianness,
|
||||
self.character_table,
|
||||
self.color_scheme,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -298,6 +370,7 @@ pub struct Printer<'a, Writer: Write> {
|
||||
show_position_panel: bool,
|
||||
show_color: bool,
|
||||
curr_color: Option<&'static [u8]>,
|
||||
color_scheme: ColorScheme,
|
||||
border_style: BorderStyle,
|
||||
byte_hex_panel: Vec<String>,
|
||||
byte_char_panel: Vec<String>,
|
||||
@@ -329,6 +402,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
base: Base,
|
||||
endianness: Endianness,
|
||||
character_table: CharacterTable,
|
||||
color_scheme: ColorScheme,
|
||||
) -> Printer<'a, Writer> {
|
||||
Printer {
|
||||
idx: 0,
|
||||
@@ -338,6 +412,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
show_position_panel,
|
||||
show_color,
|
||||
curr_color: None,
|
||||
color_scheme,
|
||||
border_style,
|
||||
byte_hex_panel: (0u8..=u8::MAX)
|
||||
.map(|i| match base {
|
||||
@@ -481,9 +556,10 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
Squeezer::Print | Squeezer::Delete => self.writer.write_all(b" ")?,
|
||||
Squeezer::Ignore | Squeezer::Disabled => {
|
||||
if let Some(&b) = self.line_buf.get(i as usize) {
|
||||
if self.show_color && self.curr_color != Some(Byte(b).color()) {
|
||||
self.writer.write_all(Byte(b).color())?;
|
||||
self.curr_color = Some(Byte(b).color());
|
||||
if self.show_color && self.curr_color != Some(Byte(b).color(self.color_scheme))
|
||||
{
|
||||
self.writer.write_all(Byte(b).color(self.color_scheme))?;
|
||||
self.curr_color = Some(Byte(b).color(self.color_scheme));
|
||||
}
|
||||
self.writer
|
||||
.write_all(self.byte_char_panel[b as usize].as_bytes())?;
|
||||
@@ -550,9 +626,9 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
if i % (self.group_size as usize) == 0 {
|
||||
self.writer.write_all(b" ")?;
|
||||
}
|
||||
if self.show_color && self.curr_color != Some(Byte(b).color()) {
|
||||
self.writer.write_all(Byte(b).color())?;
|
||||
self.curr_color = Some(Byte(b).color());
|
||||
if self.show_color && self.curr_color != Some(Byte(b).color(self.color_scheme)) {
|
||||
self.writer.write_all(Byte(b).color(self.color_scheme))?;
|
||||
self.curr_color = Some(Byte(b).color(self.color_scheme));
|
||||
}
|
||||
self.writer
|
||||
.write_all(self.byte_hex_panel[b as usize].as_bytes())?;
|
||||
@@ -780,6 +856,7 @@ mod tests {
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
ColorScheme::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
@@ -836,6 +913,7 @@ mod tests {
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
ColorScheme::Default,
|
||||
);
|
||||
printer.display_offset(0xdeadbeef);
|
||||
|
||||
@@ -871,6 +949,7 @@ mod tests {
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
ColorScheme::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
@@ -932,6 +1011,7 @@ mod tests {
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
ColorScheme::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
|
||||
Reference in new issue
Block a user