Skip to content

Commit a00090a

Browse files
Merge pull request #76 from wcampbell0x2a/add-hexdump-colors
Add hexdump colors
2 parents bec8bd4 + b6aa7fa commit a00090a

File tree

2 files changed

+50
-23
lines changed

2 files changed

+50
-23
lines changed

Diff for: src/ui/hexdump.rs

+49-23
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
11
use ratatui::{
22
layout::{Constraint, Flex, Layout, Rect},
33
style::{Color, Style, Stylize},
4+
text::{Line, Span},
45
widgets::{Block, Borders, Clear, Paragraph, Scrollbar, ScrollbarOrientation},
56
Frame,
67
};
78

89
use crate::App;
910

10-
use super::{ORANGE, SCROLL_CONTROL_TEXT, YELLOW};
11+
use super::{BLUE, DARK_GRAY, GREEN, ORANGE, SCROLL_CONTROL_TEXT, YELLOW};
1112

12-
fn to_hexdump_str(data: &[u8]) -> String {
13-
data.chunks(16)
14-
.enumerate()
15-
.map(|(i, chunk)| {
16-
let address = format!("{:08x}:", i * 16);
17-
let hex_values =
18-
chunk.iter().map(|byte| format!("{:02x}", byte)).collect::<Vec<_>>().join(" ");
19-
let ascii_values = chunk
20-
.iter()
21-
.map(|&byte| if byte.is_ascii_graphic() { byte as char } else { '.' })
22-
.collect::<String>();
23-
format!("{:<10} {:48} |{}|", address, hex_values, ascii_values)
24-
})
25-
.collect::<Vec<_>>()
26-
.join("\n")
13+
fn to_hexdump_str(buffer: &[u8]) -> Vec<Line> {
14+
let mut lines = Vec::new();
15+
for (offset, chunk) in buffer.chunks(16).enumerate() {
16+
let mut hex_spans = Vec::new();
17+
// bytes
18+
for byte in chunk.iter() {
19+
let color = color(*byte);
20+
hex_spans.push(Span::styled(format!("{:02x} ", byte), Style::default().fg(color)));
21+
}
22+
23+
// ascii
24+
hex_spans.push(Span::raw("| "));
25+
for byte in chunk.iter() {
26+
let ascii_char = if byte.is_ascii_graphic() { *byte as char } else { '.' };
27+
let color = color(*byte);
28+
hex_spans.push(Span::styled(ascii_char.to_string(), Style::default().fg(color)));
29+
}
30+
31+
let line = Line::from_iter(
32+
vec![Span::raw(format!("{:08x}: ", offset * 16)), Span::raw("")]
33+
.into_iter()
34+
.chain(hex_spans),
35+
);
36+
37+
lines.push(line);
38+
}
39+
40+
lines
41+
}
42+
43+
fn color(byte: u8) -> Color {
44+
if byte == 0x00 {
45+
DARK_GRAY
46+
} else if byte.is_ascii_graphic() {
47+
BLUE
48+
} else if byte.is_ascii_whitespace() {
49+
GREEN
50+
} else if byte.is_ascii() {
51+
ORANGE
52+
} else {
53+
YELLOW
54+
}
2755
}
2856

2957
fn popup_area(area: Rect, percent_x: u16) -> Rect {
@@ -49,18 +77,16 @@ pub fn draw_hexdump(app: &mut App, f: &mut Frame, hexdump: Rect, show_popup: boo
4977
pos = format!("(0x{:02x?})", r.0);
5078
let data = &r.1;
5179

52-
let data = to_hexdump_str(data);
53-
let lines = data.lines();
54-
let len = lines.count();
80+
let lines = to_hexdump_str(data);
81+
let len = lines.len();
5582

5683
let max = hexdump.height;
5784
let skip = if len <= max as usize { 0 } else { app.hexdump_scroll };
85+
let lines: Vec<Line> = lines.into_iter().skip(skip).collect();
5886
app.hexdump_scroll_state = app.hexdump_scroll_state.content_length(len);
87+
let paragraph =
88+
Paragraph::new(lines).block(block(&pos)).style(Style::default().fg(Color::White));
5989

60-
let lines: Vec<&str> = data.lines().skip(skip).collect();
61-
let paragraph = Paragraph::new(lines.join("\n"))
62-
.block(block(&pos))
63-
.style(Style::default().fg(Color::White));
6490
f.render_widget(paragraph, hexdump);
6591
f.render_stateful_widget(
6692
Scrollbar::new(ScrollbarOrientation::VerticalRight),

Diff for: src/ui/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const ORANGE: Color = Color::Rgb(0xff, 0x8f, 0x40);
2323
const YELLOW: Color = Color::Rgb(0xe6, 0xb4, 0x50);
2424
const GREEN: Color = Color::Rgb(0xaa, 0xd9, 0x4c);
2525
const RED: Color = Color::Rgb(0xff, 0x33, 0x33);
26+
const DARK_GRAY: Color = Color::Rgb(0x20, 0x27, 0x34);
2627

2728
const HEAP_COLOR: Color = GREEN;
2829
const STACK_COLOR: Color = PURPLE;

0 commit comments

Comments
 (0)