mirror of
https://github.com/sharkdp/hexyl.git
synced 2026-10-26 20:16:31 +00:00
Implement character table control and codepage 437 option
This commit is contained in:
1 parent
663e4c19ff
commit
6a230d34a4
2 files changed
+80
-5
No files matched your search
+56
-4
@@ -21,6 +21,29 @@ const COLOR_ASCII_OTHER: &[u8] = colors::Green::ANSI_FG.as_bytes();
|
|||||||
const COLOR_NONASCII: &[u8] = colors::Yellow::ANSI_FG.as_bytes();
|
const COLOR_NONASCII: &[u8] = colors::Yellow::ANSI_FG.as_bytes();
|
||||||
const COLOR_RESET: &[u8] = colors::Default::ANSI_FG.as_bytes();
|
const COLOR_RESET: &[u8] = colors::Default::ANSI_FG.as_bytes();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const CP437: [char; 256] = [
|
||||||
|
// use https://en.wikipedia.org/w/index.php?title=Code_page_437&oldid=978947122
|
||||||
|
// not ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT
|
||||||
|
// because we want the graphic versions of 01h–1Fh + 7Fh
|
||||||
|
'⋄','☺','☻','♥','♦','♣','♠','•','◘','○','◙','♂','♀','♪','♫','☼',
|
||||||
|
'►','◄','↕','‼','¶','§','▬','↨','↑','↓','→','←','∟','↔','▲','▼',
|
||||||
|
' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
|
||||||
|
'@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
|
||||||
|
'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
|
||||||
|
'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
|
||||||
|
'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','⌂',
|
||||||
|
'Ç','ü','é','â','ä','à','å','ç','ê','ë','è','ï','î','ì','Ä','Å',
|
||||||
|
'É','æ','Æ','ô','ö','ò','û','ù','ÿ','Ö','Ü','¢','£','¥','₧','ƒ',
|
||||||
|
'á','í','ó','ú','ñ','Ñ','ª','º','¿','⌐','¬','½','¼','¡','«','»',
|
||||||
|
'░','▒','▓','│','┤','╡','╢','╖','╕','╣','║','╗','╝','╜','╛','┐',
|
||||||
|
'└','┴','┬','├','─','┼','╞','╟','╚','╔','╩','╦','╠','═','╬','╧',
|
||||||
|
'╨','╤','╥','╙','╘','╒','╓','╫','╪','┘','┌','█','▄','▌','▐','▀',
|
||||||
|
'α','ß','Γ','π','Σ','σ','µ','τ','Φ','Θ','Ω','δ','∞','φ','ε','∩',
|
||||||
|
'≡','±','≥','≤','⌠','⌡','÷','≈','°','∙','·','√','ⁿ','²','■',' ',
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ByteCategory {
|
pub enum ByteCategory {
|
||||||
Null,
|
Null,
|
||||||
@@ -30,6 +53,12 @@ pub enum ByteCategory {
|
|||||||
NonAscii,
|
NonAscii,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum CharTable {
|
||||||
|
AsciiOnly,
|
||||||
|
CP437,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Endianness {
|
pub enum Endianness {
|
||||||
Little,
|
Little,
|
||||||
@@ -74,17 +103,27 @@ impl Byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_char(self) -> char {
|
fn as_char(self, char_table: CharTable) -> char {
|
||||||
use crate::ByteCategory::*;
|
use crate::ByteCategory::*;
|
||||||
|
match char_table {
|
||||||
match self.category() {
|
CharTable::AsciiOnly => match self.category() {
|
||||||
Null => '⋄',
|
Null => '⋄',
|
||||||
AsciiPrintable => self.0 as char,
|
AsciiPrintable => self.0 as char,
|
||||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||||
AsciiWhitespace => '_',
|
AsciiWhitespace => '_',
|
||||||
AsciiOther => '•',
|
AsciiOther => '•',
|
||||||
NonAscii => '×',
|
NonAscii => '×',
|
||||||
|
},
|
||||||
|
CharTable::CP437 => CP437[self.0.to_ne_bytes()[0] as usize],
|
||||||
}
|
}
|
||||||
|
// match self.category() {
|
||||||
|
// Null => '⋄',
|
||||||
|
// AsciiPrintable => self.0 as char,
|
||||||
|
// AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||||
|
// AsciiWhitespace => '_',
|
||||||
|
// AsciiOther => '•',
|
||||||
|
// NonAscii => '×',
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,6 +206,7 @@ pub struct PrinterBuilder<'a, Writer: Write> {
|
|||||||
group_size: u8,
|
group_size: u8,
|
||||||
base: Base,
|
base: Base,
|
||||||
endianness: Endianness,
|
endianness: Endianness,
|
||||||
|
char_table: CharTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||||
@@ -182,6 +222,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
|||||||
group_size: 1,
|
group_size: 1,
|
||||||
base: Base::Hexadecimal,
|
base: Base::Hexadecimal,
|
||||||
endianness: Endianness::Big,
|
endianness: Endianness::Big,
|
||||||
|
char_table: CharTable::AsciiOnly,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +271,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn char_table(mut self, char_table: CharTable) -> Self {
|
||||||
|
self.char_table = char_table;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Printer<'a, Writer> {
|
pub fn build(self) -> Printer<'a, Writer> {
|
||||||
Printer::new(
|
Printer::new(
|
||||||
self.writer,
|
self.writer,
|
||||||
@@ -242,6 +288,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
|||||||
self.group_size,
|
self.group_size,
|
||||||
self.base,
|
self.base,
|
||||||
self.endianness,
|
self.endianness,
|
||||||
|
self.char_table,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,6 +332,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
|||||||
group_size: u8,
|
group_size: u8,
|
||||||
base: Base,
|
base: Base,
|
||||||
endianness: Endianness,
|
endianness: Endianness,
|
||||||
|
char_table: CharTable,
|
||||||
) -> Printer<'a, Writer> {
|
) -> Printer<'a, Writer> {
|
||||||
Printer {
|
Printer {
|
||||||
idx: 0,
|
idx: 0,
|
||||||
@@ -304,7 +352,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
byte_char_panel: (0u8..=u8::MAX)
|
byte_char_panel: (0u8..=u8::MAX)
|
||||||
.map(|i| format!("{}", Byte(i).as_char()))
|
.map(|i| format!("{}", Byte(i).as_char(char_table)))
|
||||||
.collect(),
|
.collect(),
|
||||||
byte_hex_panel_g: (0u8..=u8::MAX).map(|i| format!("{i:02x}")).collect(),
|
byte_hex_panel_g: (0u8..=u8::MAX).map(|i| format!("{i:02x}")).collect(),
|
||||||
squeezer: if use_squeeze {
|
squeezer: if use_squeeze {
|
||||||
@@ -732,6 +780,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
Base::Hexadecimal,
|
Base::Hexadecimal,
|
||||||
Endianness::Big,
|
Endianness::Big,
|
||||||
|
CharTable::AsciiOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
printer.print_all(input).unwrap();
|
printer.print_all(input).unwrap();
|
||||||
@@ -787,6 +836,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
Base::Hexadecimal,
|
Base::Hexadecimal,
|
||||||
Endianness::Big,
|
Endianness::Big,
|
||||||
|
CharTable::AsciiOnly,
|
||||||
);
|
);
|
||||||
printer.display_offset(0xdeadbeef);
|
printer.display_offset(0xdeadbeef);
|
||||||
|
|
||||||
@@ -821,6 +871,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
Base::Hexadecimal,
|
Base::Hexadecimal,
|
||||||
Endianness::Big,
|
Endianness::Big,
|
||||||
|
CharTable::AsciiOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
printer.print_all(input).unwrap();
|
printer.print_all(input).unwrap();
|
||||||
@@ -881,6 +932,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
Base::Hexadecimal,
|
Base::Hexadecimal,
|
||||||
Endianness::Big,
|
Endianness::Big,
|
||||||
|
CharTable::AsciiOnly,
|
||||||
);
|
);
|
||||||
|
|
||||||
printer.print_all(input).unwrap();
|
printer.print_all(input).unwrap();
|
||||||
|
|||||||
+24
-1
@@ -17,7 +17,7 @@ use thiserror::Error as ThisError;
|
|||||||
|
|
||||||
use terminal_size::terminal_size;
|
use terminal_size::terminal_size;
|
||||||
|
|
||||||
use hexyl::{Base, BorderStyle, Endianness, Input, PrinterBuilder};
|
use hexyl::{Base, BorderStyle, CharTable, Endianness, Input, PrinterBuilder};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@@ -212,6 +212,17 @@ fn run() -> Result<()> {
|
|||||||
.hide(true)
|
.hide(true)
|
||||||
.help("An alias for '--endianness=little'."),
|
.help("An alias for '--endianness=little'."),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("character_table")
|
||||||
|
.long("character_table")
|
||||||
|
.value_name("FORMAT")
|
||||||
|
.value_parser(["codepage-437", "ascii-only"])
|
||||||
|
.help(
|
||||||
|
"The character table that should be used. 'ascii-only' \
|
||||||
|
will show dots for non-ASCII characters, and 'codepage-437 \
|
||||||
|
will use Code page 437 for those characters."
|
||||||
|
),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("base")
|
Arg::new("base")
|
||||||
.short('b')
|
.short('b')
|
||||||
@@ -469,6 +480,17 @@ fn run() -> Result<()> {
|
|||||||
("big", _) => Endianness::Big,
|
("big", _) => Endianness::Big,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let char_table = match matches
|
||||||
|
.get_one::<String>("character_table")
|
||||||
|
.unwrap_or(&String::from("ascii-only"))
|
||||||
|
.as_ref()
|
||||||
|
{
|
||||||
|
"ascii-only" => CharTable::AsciiOnly,
|
||||||
|
"codepage-437" => CharTable::CP437,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut stdout_lock = BufWriter::new(stdout.lock());
|
let mut stdout_lock = BufWriter::new(stdout.lock());
|
||||||
|
|
||||||
@@ -482,6 +504,7 @@ fn run() -> Result<()> {
|
|||||||
.group_size(group_size)
|
.group_size(group_size)
|
||||||
.with_base(base)
|
.with_base(base)
|
||||||
.endianness(endianness)
|
.endianness(endianness)
|
||||||
|
.char_table(char_table)
|
||||||
.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))?;
|
||||||
|
|||||||
Reference in new issue
Block a user