Created
January 6, 2026 21:42
-
-
Save ltriant/53a7eafda1197d31de4a70b1b929c53a to your computer and use it in GitHub Desktop.
simple hex viewer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env raku | |
| # hexdump.raku -- simple hex viewer | |
| # @[email protected] | |
| # no-color.org | |
| my constant $NO_COLOR = %*ENV<NO_COLOR>:exists; | |
| my $color_reset = "\x1b[0m"; | |
| my $color_bold = "\x1b[1m"; | |
| sub color_black(Str $s) { "\x1b[90m" ~ $s ~ $color_reset } | |
| sub color_red(Str $s) { "\x1b[91m" ~ $s ~ $color_reset } | |
| sub color_green(Str $s) { "\x1b[92m" ~ $s ~ $color_reset } | |
| sub color_yellow(Str $s) { "\x1b[93m" ~ $s ~ $color_reset } | |
| sub color_blue(Str $s) { "\x1b[94m" ~ $s ~ $color_reset } | |
| sub color_purple(Str $s) { "\x1b[95m" ~ $s ~ $color_reset } | |
| sub color_cyan(Str $s) { "\x1b[96m" ~ $s ~ $color_reset } | |
| sub color_white(Str $s) { "\x1b[97m" ~ $s ~ $color_reset } | |
| sub color_printable(Str $s) { | |
| $NO_COLOR | |
| ?? $color_bold ~ $s ~ $color_reset | |
| !! $color_bold ~ color_yellow($s) | |
| } | |
| sub color_nonprintable(Str $s) { | |
| $NO_COLOR ?? $s !! color_black($s) | |
| } | |
| my $offset = 0; | |
| my $total_size = 0; | |
| my constant $MAX_LINE_LENGTH = 16 * 2 + 7; | |
| sub hexdump(@octets) { | |
| $total_size += @octets.elems; | |
| for @octets.rotor(16, :partial) -> @bits { | |
| my $lineLength = 0; | |
| my $line; | |
| $line ~= sprintf "%08x \x2502 ", $offset; | |
| for @bits.kv -> $i, $bit { | |
| my $c = $bit.ord.fmt("%02x"); | |
| $line ~= sprintf "%02s%s", | |
| $bit ~~ /^<print>$/ | |
| ?? color_printable($c) | |
| !! color_nonprintable($c), | |
| $i !%% 2 ?? " " !! ""; | |
| $lineLength += 2 + ($i !%% 2 ?? 1 !! 0); | |
| } | |
| if (@bits.elems < 16) { | |
| $line ~= " " x ($MAX_LINE_LENGTH - $lineLength + 1); | |
| } | |
| $line ~= "\x2502 "; | |
| for @bits -> $bit { | |
| if ($bit ~~ /^<print>$/) { | |
| $line ~= color_printable($bit); | |
| } else { | |
| $line ~= color_nonprintable("."); | |
| } | |
| } | |
| $line ~= "\n"; | |
| print $line; | |
| $offset += @bits.elems; | |
| } | |
| } | |
| unit sub MAIN(); | |
| # How many bytes to read from stdin at any time | |
| my constant $BUF_SIZE = 16 * 512; # 8192 bytes / 8KB | |
| my @bytes; | |
| repeat { | |
| @bytes = $*IN.read($BUF_SIZE).list.map(*.chr).Array; | |
| hexdump(@bytes); | |
| } while (@bytes.elems == $BUF_SIZE); | |
| printf "\nTotal size: %d %s\n", $total_size, $total_size == 1 ?? "byte" !! "bytes"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment