hexyl is a simple hex viewer for the terminal. It uses a colored output to distinguish different categories of bytes

Overview

CICD

hexyl is a simple hex viewer for the terminal. It uses a colored output to distinguish different categories of bytes (NULL bytes, printable ASCII characters, ASCII whitespace characters, other ASCII characters and non-ASCII).

Preview

Installation

On Ubuntu

... and other Debian-based Linux distributions.

If you run Ubuntu 19.10 (Eoan Ermine) or newer, you can install the officially maintained package:

sudo apt install hexyl

If you use an older version of Ubuntu, you can download the latest .deb package from the release page and install it via:

sudo dpkg -i hexyl_0.9.0_amd64.deb  # adapt version number and architecture

On Debian

If you run Debian Buster or newer, you can install the officially maintained Debian package:

sudo apt-get install hexyl

If you run an older version of Debian, see above for instructions on how to manually install hexyl.

On Arch Linux

You can install hexyl from the official package repository:

pacman -S hexyl

On Void Linux

xbps-install hexyl

On Gentoo Linux

Available in dm9pZCAq overlay

sudo eselect repository enable dm9pZCAq
sudo emerge --sync dm9pZCAq
sudo emerge sys-apps/hexyl::dm9pZCAq

On macOS

Via Homebrew:

brew install hexyl

...or via MacPorts:

sudo port install hexyl

On FreeBSD

pkg install hexyl

on Termux

pkg install hexyl

or

apt install hexyl

Via Nix

nix-env -i hexyl

Via Guix

guix package -i hexyl

Or add the hexyl package in the list of packages to be installed in your system configuration (e.g., /etc/config.scm).

On other distributions

Check out the release page for binary builds.

On Windows

Check out the release page for binary builds. Alternatively, install from source via cargo, snap or scoop (see below). Make sure that you use a terminal that supports ANSI escape sequences (like ConHost v2 since Windows 10 1703 or Windows Terminal since Windows 10 1903).

Via cargo

If you have Rust 1.46 or higher, you can install hexyl from source via cargo:

cargo install hexyl

Via snap package

sudo snap install hexyl

Get it from the Snap Store

Via Scoop

scoop install hexyl

License

Licensed under either of

at your option.

Comments
  • Adds --columns for Print using custom width #13

    Adds --columns for Print using custom width #13

    This pull request fixes #13 partially by adding the --columns option to manually set the number of columns. The default is 2 as with previous behavior.

    Some notes:

    • the short option is -w not -c as that option is already reserved for --bytes
    • it passes cargo test
    • I could have added the option to automatically set columns to terminal width, but that would require adding another dependency
    opened by sharifhsn 20
  • Options for reading between two offsets

    Options for reading between two offsets

    The -n/--length flag is a great feature -- good especially for quickly checking if file headers match something. Another use case I can think of for limited output is inspecting, say, an entire block of some data from a file that's been dumped from a disk. Let's say I'm using Linux and reading the first block of a disk somewhere to determine its contents manually:

    $ hexyl -n 512 "$disk_dump"
    // Some output here...
    

    I read the output and discover that there's an MBR at the beginning, with the first partition starting at logical block address 1. Sweet, let's mosey on over to 0x200 and read another block. I could implement this by using dd:

    $ input_file="_viminfo" block_size=512 block_num=1
    $ dd bs="$block_size" status=none skip="$block_num" count="$block_size" if="$input_file" \
        | hexyl
    

    ...but there's two issues with this:

    • dd isn't usually available on Windows machines!
    • Because we're using stdin, we can't get the correct set of offsets -- the "file" starts at 0x0 regardless of what parameters I gave dd.

    Perhaps something like this spitballed set of options might help:

    $ hexyl \
        --start 512      \ # Could also be written as 
                         \ #
                         \ # Could be bikeshed to `--begin`?
                         \
        --length 512     \
                         \
                         \ # One could use an end offset instead of a length:
        # --end 1024     \ # Could also be written as `-e 0x300
    

    Having something similar to bat's --range could also be really handy, especially when combined with relative offsets (positive and negative):

    $ hexyl --range 512:+512 # same as using `--skip 512 --length 512`
    $ hexyl --range=-512: # read the last block
    $ hexyl --block-size 4096 -1block: # like above, but use the block unit
    $ hexyl --range 32:-32 # cut out a common header and footer for the input stream we don't care about
    

    I would be more than happy to push implementation of this, since I've great personal interest in allowing more of my reverse engineering flow in the terminal. Let me know if you want me to hack on it!

    Unresolved questions

    • ~~Adding several more arguments that accept offsets/sizes might add pressure to create a system of units/radices a la xxd for the appropriate arguments. Where should the line be drawn in terms of what this project is willing to support?~~ We've added support for xb and xib with #44. That's as far as we've decided to go right now.
    enhancement 
    opened by ErichDonGubler 20
  • Add hexyl.1 man page to source tree?

    Add hexyl.1 man page to source tree?

    Hi,

    Thank you for a new release. I was looking into updating the package for NetBSD and realized the man page is provided in markdown. Would it possible to provide the man page in the man page Unix format, i.e. like hexyl.1 or hexyl.1.gz ? It would be desirable to avoid the need of external build dependencies for a simple man page.

    TIA

    opened by 0323pin 18
  • Various performance optimizations

    Various performance optimizations

    I did some profiling of hexyl using cargo flamegraph and identified some key performance optimizations that could be made.

    The three methods that take up the most time are:

    • write_all into the buffer and then stdout
    • format! call in print_position_panel
    • multiple uses of the write! and writeln! macro in print_* functions

    flamegraph

    The three commits in the pull request address these three issues.

    The first replaces the manual buffers used by hexyl for reading and writing by BufReader and BufWriter, respectively. This required some major refactoring of code because of the way that buffer_line and raw_line were used. I feel that the refactoring was appropriate and made the code much easier to read, so it was worth it even without performance optimizations. With this addition, here is the benchmark:

    | Command | Mean [s] | Min [s] | Max [s] | Relative | |:---|---:|---:|---:|---:| | hexyl data | 1.068 ± 0.015 | 1.045 | 1.084 | 1.23 ± 0.03 | | hexyl --no-squeezing data | 1.073 ± 0.035 | 1.041 | 1.164 | 1.23 ± 0.04 | | target/release/hexyl data | 0.895 ± 0.019 | 0.871 | 0.917 | 1.03 ± 0.03 | | target/release/hexyl --no-squeezing data | 0.871 ± 0.013 | 0.851 | 0.899 | 1.00 |

    The second commit replaces the format! call in print_position_panel with a workaround. Previously, the function would take the position and format it as hexademical, then painted it if color was enabled. This was expensive! In order to avoid this, I used the same strategy as with the byte_hex_panel and byte_char_panel and precomputed the values in the new function so they would only be created once through byte_hex_panel_g and byte_char_panel_g. This adds a tiny amount of overhead to the startup but it's invisible in profiling. Here is the benchmark with both the first and second commit:

    | Command | Mean [s] | Min [s] | Max [s] | Relative | |:---|---:|---:|---:|---:| | hexyl data | 1.181 ± 0.025 | 1.135 | 1.215 | 1.67 ± 0.05 | | hexyl --no-squeezing data | 1.122 ± 0.024 | 1.091 | 1.165 | 1.59 ± 0.05 | | target/release/hexyl data | 0.738 ± 0.015 | 0.713 | 0.767 | 1.04 ± 0.03 | | target/release/hexyl --no-squeezing data | 0.706 ± 0.014 | 0.687 | 0.729 | 1.00 |

    The last and most dramatic optimization was the elimination of the write! macro sprinkled throughout the three print methods that are repeated every line, replacing it with the more direct write_all method on self.writer. This wasn't actually too difficult, because all of the write! macro calls didn't use any formatting machinery. I didn't remove every use of write! because profiling shows that it wasn't important outside of the loop. Here is the benchmark with all of these commits:

    | Command | Mean [s] | Min [s] | Max [s] | Relative | |:---|---:|---:|---:|---:| | hexyl data | 1.062 ± 0.027 | 1.024 | 1.101 | 3.69 ± 0.11 | | hexyl --no-squeezing data | 1.072 ± 0.011 | 1.060 | 1.099 | 3.73 ± 0.07 | | target/release/hexyl data | 0.332 ± 0.007 | 0.323 | 0.343 | 1.15 ± 0.03 | | target/release/hexyl --no-squeezing data | 0.287 ± 0.005 | 0.282 | 0.299 | 1.00 |

    And here is the final flamegraph:

    flamegraph

    opened by sharifhsn 17
  • Interrupting hexyl with ^C leaves ugly remnant

    Interrupting hexyl with ^C leaves ugly remnant

    screenshot

    It should probably handle SIGINT and terminate the output as if it was EOF (but maybe with some mark):

    │00001410│ 57 37 f9 ae 0b ae 6c 8a ┊ df 0e d8 20 15 f1 d7 f6 │W7×ו×l×┊×•× •×××│
    │00001420│ a5 5e 99 b0 bd bf 22 a7 ┊ b2 e0 ab ^C             | ×^×××"×┊×××^C   |
    
    enhancement help wanted 
    opened by vi 17
  • Measure rendering performance in terminals

    Measure rendering performance in terminals

    We've been benchmarking the performance of the tool without considering the rendering performance of the terminal. Specifically, I'm thinking about how we turn colors on and off again for every single hex pair and textual character. Ideally we wouldn't turn colors off if the next printed hex/char uses the same color.

    I'm not really sure how to programmatically measure the terminal performance (and of course performance would change for different terminals), but it's worth at least trying to measure. Optimizing our color usages would be more overhead on our side and therefore slow down our benchmark (though perhaps not significantly) but if it produces faster rendering it might be worth it.

    At the very least, we could investigate not printing the style suffix for each character, under the assumption that the style prefix for the next character will suffice (and then just printing the suffix prior to printing a frame character).

    opened by lilyball 17
  • Units of measurement of bytes?

    Units of measurement of bytes?

    | Unit | Implemented? | Description | Examples | Suggested implementation | | ------- | ------------ | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | Decimal | [x] | A decimal integer, which is equivalent to specifying a single byte unit for the count. | 23, 1024 | u64::from_str(...) | | Hex | [x] Implemented in #45. | A hexadecimal integer. Specified with a leading 0x. | 0x17, 0x100 | u64::from_str_radix(...) | | Blocks | [ ] | A single block, which is by default 512 bytes but configurable via config flag. | -b 512 -n 1block

    N.B: one cannot use a block unit to define the block size. | Add a flag to optionally define block size, then check for a trailing block when parsing numbers. Multiply by block size. | | Bytes | [ ] | A byte size familiar to most IT professionals. Specified by B at the end of the count, and can include an optional magnitudinal spec like kilobytes (K) or megabytes (M). |

    • 23B: 23 bytes
    • 9KB: 9 kilobytes
    | Implement a regex of the form (?P<count>\d+)(?P<magnitude_unit>[KM]?)B. |

    Other open questions

    • Should the block unit, which might be controversial, be scoped into another issue?
    • Should a single leading - or + sign be supported?
      • Not sure how + is useful -- xxd's manual states that for the -s option + is useful only for stdin. Not sure what that means, though.
    enhancement question 
    opened by ErichDonGubler 16
  • Add --color flag to disable ANSI sequences

    Add --color flag to disable ANSI sequences

    When printing the output of hexyl to a file (hexyl file.exe > file.txt), the file.txt file gets polluted by the ANSI escape sequences. Checking whether the application has been launched from inside the terminal or not, allows you to decide whether or not to use them.

    I don't have access to a Windows machine, but atty claims that it has been tested on Windows.

    opened by bennetthardwick 14
  • brew install failure

    brew install failure

    > brew install hexyl
    Updating Homebrew...
    ==> Auto-updated Homebrew!
    Updated 3 taps (homebrew/cask-versions, homebrew/core and homebrew/cask).
    ==> Updated Formulae
    bash ✔               brew-php-switcher    fonttools            mariadb              telegraf
    libidn2 ✔            buildifier           grv                  mercurial            tor
    wget ✔               chakra               hcloud               mutt                 urdfdom_headers
    alexjs               citus                jabba                neofetch             vegeta
    amqp-cpp             clang-format         jenkins              nvm                  whois
    aws-sdk-cpp          conan                kitchen-sync         picard-tools         wtf
    azure-cli            console_bridge       libphonenumber       rabbitmq             yarn
    bat                  emscripten           libpsl               serverless
    bettercap            erlang@20            lmod                 sox
    bitrise              exploitdb            lxc                  swiftlint
    
    /usr/local/Homebrew/Library/Homebrew/config.rb:39:in `initialize': no implicit conversion of nil into String (TypeError)
            from /usr/local/Homebrew/Library/Homebrew/config.rb:39:in `new'
            from /usr/local/Homebrew/Library/Homebrew/config.rb:39:in `<top (required)>'
            from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.3.7/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
            from /usr/local/Homebrew/Library/Homebrew/vendor/portable-ruby/2.3.7/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
            from /usr/local/Homebrew/Library/Homebrew/global.rb:25:in `<top (required)>'
            from /usr/local/Homebrew/Library/Homebrew/brew.rb:13:in `require_relative'
            from /usr/local/Homebrew/Library/Homebrew/brew.rb:13:in `<main>'
    
    > hexyl
    -bash: hexyl: command not found
    

    macOS High Sierra Version ~10.13.16~ 10.13.6

    MacBook Pro

    help wanted 
    opened by jtpereyda 14
  • Bad background color on rxvt-unicode

    Bad background color on rxvt-unicode

    Hi there, Thank you for this tool.

    There is a background color making it difficult to see the characters on rxvt-unicode only.

    rxvt-unicode with default settings: urxvt

    maybe that looks not a big problem, but when I have dark terminal theme, that make it difficult to see: urxvt-black

    That background color not appear on other terminals, just rxvt-unicode.

    enhancement 
    opened by garywill 14
  • Automatic paging?

    Automatic paging?

    While using it for large file, the output will scrolling long-long time , and piping to more will output bad string . So, please add pager to output .

    opened by wxy 13
  • experiment: Sparse file support

    experiment: Sparse file support

    I decided to take a stab at #89 just to see how feasible it is. In order to facilitate this, I have temporarily changed the API of print_all to take Input with a new generic Box <dyn Read> variant as a fallback.

    So far, this implementation is only able to use sparseness when there is non-sparse content at the end of the file, and the rest of the file, including the start, is sparse. Otherwise, it will cause strange errors.

    It also only works for Linux, because this was the simplest OS to implement sparse support for.

    How to test this:

    truncate -s 16G startzero
    echo "Lorem ipsum" >> startzero
    cargo run --release -- startzero
    

    The position will be slightly wrong but it will finish extremely quickly.

    Tasks:

    • [x] correct position indexing
    • [x] handle fully sparse files
    • [x] handle when the file starts with non-sparse data
    • [x] handle non-sparse data interspersed in files (this might work already to some extent)
    • [x] fully support Linux (caveat: does not work with BufReader)
    • [ ] fully support Windows
    • [ ] fully support MacOS
    opened by sharifhsn 2
  • Add more formatting options

    Add more formatting options

    Adds the following options:

    • --hex-inner-separator none Removes the inner separator from the hex display
    • --text-inner-separator none Removes the inner separator from the text display
    • --outer-border none Removes the outer border (including header, footer and left border, but currently leaves right border in)

    TODO:

    • [ ] Confirm naming of options and associated variables, structs etc.
    • [ ] Confirm documentation in --help for new options
    • [ ] Add changes to CHANGELOG.MD
    • [ ] Add tests for new options
    • [x] Check existing tests haven't broken
    opened by Aaron-Rumpler 9
  • Argument `--display-offset` does not accept negative numbers, contrary to its helptext description.

    Argument `--display-offset` does not accept negative numbers, contrary to its helptext description.

    The hexyl --help description for the --block-size argument goes as follows:

        -o, --display-offset <N>    Add N bytes to the displayed file position. The
                                    N argument can also include a unit (see
                                    `--length` for details)
                                    A negative value is valid and calculates an
                                    offset relative to the end of the file.
    

    However, when I attempt to run dd if=/dev/urandom bs=16 count=32 2>/dev/null | hexyl --skip=0xFF --display-offset=-0x2F, hexyl prints the following error:

    Error: failed to parse `--display-offset` arg "-0x2F" as byte count
    
    Caused by:
        negative offset specified, but only positive offsets (counts) are accepted in this context
    

    Note: I'm doing a class assignment regarding creating tests (from scratch) for an open-source command line program, and I chose hexyl for it. You might have a couple more of these on the way, depending on what the assignment brings to light :)

    enhancement 
    opened by eth-p 4
  • Other sizes of data (group size and Endianness)

    Other sizes of data (group size and Endianness)

    I frequently have to dump data files (ADC output, for example) that don't just have byte-oriented data. It would be nice to be able to specify data width in the dump so I get the hex data grouped in the natural data size instead of having to do the little-endian two-step and mentally group indistinguishable bytes by 2 or 4 or whatever. Something like:

    --word-size=1 (uint8_t, default) --word-size=2 (uint16_t) --word-size=4 (uint32_t) --word-size=8 (uint64_t) --word-size=16 (uint128_t)

    That covers the common-ish types. If you want to be really brave you could do weird crap like 3-byte or 17 byte, but that is likely low return on investment.

    Not all such data is little-endian, so an extra flag for those cases where word-size > 1 would be:

    --little-endian (default) --big-endian

    Also, interpretation could be signed or unsigned

    --signed --unsigned (default)

    Of course with this you'd drop the byte-oriented colouration (but maybe with --signed you'd highlight negative numbers in red or something).

    enhancement help wanted 
    opened by ACleverDisguise 7
  • Handle sparse files

    Handle sparse files

    Because hexyl truncates repeating sections, it would be nice to be able to have hexyl quickly skip over these sections instead of scanning them byte-by-byte.

    opened by clarfonthey 7
Releases(v0.12.0)
Owner
David Peter
David Peter
Simple macros to write colored and formatted text to a terminal. Based on `termcolor`, thus also cross-platform.

Bunt: simple macro-based terminal colors and styles bunt offers macros to easily print colored and formatted text to a terminal. It is just a convenie

Lukas Kalbertodt 202 Dec 22, 2022
Make beautiful colored code listings in LaTeX with the power of TreeSitter.

What is this? This is a CLI tool that consumes TreeSitter's output and transforms it into LaTeX code that will produce syntax-colored code listing. If

Tomáš Lebeda 11 Sep 4, 2023
Simple terminal alignment viewer

Alen Simple terminal sequence alignment viewer. What is Alen? It's a command-like program to view DNA or protein alignments in FASTA formats. Alen is

Jakob Nybo Nissen 51 Dec 19, 2022
Cork is a simple command-line calculator, mainly targeted towards people who deal with hex numbers

Cork is a simple command-line calculator, mainly targeted towards people who deal with hex numbers. It deals only with integer arithmetic. Expressions may involve mixed bases (limited to decimal, hexadecimal, octal and binary numbers). The global output format may be set to a particular radix - by default it is hex.

Deep Majumder 50 Dec 22, 2022
A terminal UI to edit bytes by the nibble.

heh The HEx Helper is a cross-platform terminal UI used for modifying file data in hex or ASCII. It aims to replicate some of the look of hexyl while

nathan 285 Dec 18, 2022
Parse hex colors to tui::style::Color

Color -> Tui Parse hex colors to tui rgb colors #c3f111 -> Color::Rgb(195,241,17) Note that the indexed colors are NOT HEX #142 -> Color::Indexed(142)

Uttarayan Mondal 1 Nov 8, 2021
A user-friendly re-implementation of existing hex tools in Rust

Hex A project to create alternate (and more user friendly) versions of existing hex tools. The project can be installed as a extension to the github-c

Sohom Datta 6 Sep 27, 2022
convert nostr keys and note-ids between hex and bech32

Key-Convertr People are copy-pasting nostr private keys into webpages to convert between the original hex-encoding and bech32-encoding (specified in N

Rijndael 14 Jan 9, 2023
A simple cross-platform easy to use STL Viewer with GUI and CLI options

Stlvi STL viewer written in Rust. This project is still in development. It is available in both CLI and GUI mode. Supported OS Linux Windows Mac Scree

Mantresh Khurana 4 Mar 2, 2023
Cross-platform Rust library for coloring and formatting terminal output

Coloring terminal output Documentation term-painter is a cross-platform (i.e. also non-ANSI terminals) Rust library for coloring and formatting termin

Lukas Kalbertodt 75 Jul 28, 2022
A CLI tool to copy-paste different Ipsums from your terminal

Lorem clipsum Explore the docs » View Demo · Report Bug · Request Feature Table of Contents About The Project Built With Usage Contributing Contact Ab

Schrödinger Hat 9 May 30, 2023
Terminal UI for leetcode. Lets you browse questions through different topics. View, solve, run and submit questions from TUI.

Leetcode TUI Use Leetcode in your terminal. Why this TUI: My motivation for creating leetcode-tui stemmed from my preference for tools that are lightw

Akarsh 8 Aug 10, 2023
Terminal UI to chat with large language models (LLM) using different model backends, and integrations with your favourite editors!

Oatmeal Terminal UI to chat with large language models (LLM) using different model backends, and integrations with your favourite editors! Overview In

Dustin Blackman 88 Dec 4, 2023
A terminal clock that uses 7-segment display characters

Seven-segment clock (7clock) 7clock.3.mp4 This is a clock for terminals that uses the Unicode seven-segment display characters added in Unicode 13.0.

Wesley Moore 4 Nov 11, 2022
Encode and decode dynamically constructed values of arbitrary shapes to/from SCALE bytes

scale-value · This crate provides a Value type, which is a runtime representation that is compatible with scale_info::TypeDef. It somewhat analogous t

Parity Technologies 15 Jun 24, 2023
A rust crate to view a structure as raw bytes (&[u8])

rawbytes A Rust crate to view a structure as a plain byte array (&[u8]). Super simple. Tiny. Zero dependencies. This is a safer interface to slice::fr

Frank Denis 4 Sep 7, 2023
Patch binary file using IDA signatures and defined replacement bytes in YAML.

fabricbin Patch binary file using IDA signatures and defined replacement bytes in YAML. Install: cargo install --git https://github.com/makindotcc/fab

makin 3 Oct 24, 2023
Base 32 + 64 encoding and decoding identifiers + bytes in rust, quickly

fast32 Base32 and base64 encoding in Rust. Primarily for integer (u64, u128) and UUID identifiers (behind feature uuid), as well as arbitrary byte arr

Chris Rogus 9 Dec 18, 2023
TUI image viewer

Picterm TUI image viewer install $ cargo install picterm or $ git clone https://github.com/ksk001100/picterm $ cd picterm $ cargo install --path . usa

Keisuke Toyota 41 Dec 31, 2022