mirror of
https://github.com/exoticorn/upkr.git
synced 2026-01-20 19:46:42 +01:00
implement printing heatmap as hexdump
This commit is contained in:
@@ -71,4 +71,93 @@ impl Heatmap {
|
||||
pub fn byte(&self, index: usize) -> u8 {
|
||||
self.data[index]
|
||||
}
|
||||
|
||||
pub fn print_as_hex(&self) -> std::io::Result<()> {
|
||||
use crossterm::{
|
||||
style::{Attribute, Color, Print, SetAttribute, SetBackgroundColor},
|
||||
QueueableCommand,
|
||||
};
|
||||
use std::io::{stdout, Write};
|
||||
|
||||
fn set_color(
|
||||
mut out: impl QueueableCommand,
|
||||
heatmap: &Heatmap,
|
||||
index: usize,
|
||||
num_colors: u16,
|
||||
) -> std::io::Result<()> {
|
||||
let cost = heatmap.cost(index);
|
||||
if num_colors < 256 {
|
||||
let colors = [
|
||||
Color::Red,
|
||||
Color::Yellow,
|
||||
Color::Green,
|
||||
Color::Cyan,
|
||||
Color::Blue,
|
||||
Color::DarkBlue,
|
||||
Color::Black,
|
||||
];
|
||||
let color_index = (3. - cost.log2())
|
||||
.round()
|
||||
.max(0.)
|
||||
.min((colors.len() - 1) as f32) as usize;
|
||||
out.queue(SetBackgroundColor(colors[color_index]))?;
|
||||
} else {
|
||||
let colors = [
|
||||
196, 166, 136, 106, 76, 46, 41, 36, 31, 26, 21, 20, 19, 18, 17, 16,
|
||||
];
|
||||
let color_index = ((3. - cost.log2()) * 2.5)
|
||||
.round()
|
||||
.max(0.)
|
||||
.min((colors.len() - 1) as f32) as usize;
|
||||
out.queue(SetBackgroundColor(Color::AnsiValue(colors[color_index])))?;
|
||||
}
|
||||
out.queue(SetAttribute(if heatmap.is_literal(index) {
|
||||
Attribute::Underlined
|
||||
} else {
|
||||
Attribute::NoUnderline
|
||||
}))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let num_colors = crossterm::style::available_color_count();
|
||||
|
||||
let term_width = crossterm::terminal::size()?.0.min(120) as usize;
|
||||
let bytes_per_row = (term_width - 8) / 4;
|
||||
|
||||
for row_start in (0..self.data.len()).step_by(bytes_per_row) {
|
||||
let row_range = row_start..self.data.len().min(row_start + bytes_per_row);
|
||||
let mut stdout = stdout();
|
||||
|
||||
stdout.queue(Print(&format!("{:04x} ", row_start)))?;
|
||||
|
||||
for i in row_range.clone() {
|
||||
set_color(&mut stdout, self, i, num_colors)?;
|
||||
stdout.queue(Print(&format!("{:02x} ", self.data[i])))?;
|
||||
}
|
||||
|
||||
let num_spaces = 1 + (bytes_per_row - (row_range.end - row_range.start)) * 3;
|
||||
let gap: String = std::iter::repeat(' ').take(num_spaces).collect();
|
||||
stdout
|
||||
.queue(SetAttribute(Attribute::Reset))?
|
||||
.queue(Print(&gap))?;
|
||||
|
||||
for i in row_range.clone() {
|
||||
set_color(&mut stdout, self, i, num_colors)?;
|
||||
let byte = self.data[i];
|
||||
if byte >= 32 && byte < 127 {
|
||||
stdout.queue(Print(format!("{}", byte as char)))?;
|
||||
} else {
|
||||
stdout.queue(Print("."))?;
|
||||
}
|
||||
}
|
||||
|
||||
stdout
|
||||
.queue(SetAttribute(Attribute::Reset))?
|
||||
.queue(Print("\n"))?;
|
||||
|
||||
stdout.flush()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user