HEXER(1)

๐Ÿ“ฆ
version 1.0.7 ยท 3 versions
, in arch rolling, fedora 43, fedora 44, ubuntu resolute, ubuntu stonking

๐Ÿ’– HEXER(1) โ€” General Commands Manual ๐Ÿ’–

okay bestie, sit down, hydrate, and let me tell you about hexer ๐Ÿ’… this is the binary file editor page and it's lowkey iconic.


โœจ NAME โœจ

hexer โ€” a binary file editor ๐Ÿฆ‹ (that's it, that's the name, short and slay)


๐ŸŒธ SYNOPSIS ๐ŸŒธ

hexer [options] [file [...]]

๐ŸŽ€ DESCRIPTION ๐ŸŽ€

so hexer is a multi-buffer editor for viewing and manipulating binary files. it's giving main character energy in the hex-editing world fr fr.

โš ๏ธ it can't (and honestly shouldn't) be used for editing block devices, because it tries to load the whole entire file into a buffer. it should work for diskettes tho ๐Ÿ’พ

the most important features, no cap:

  • multi buffers ๐Ÿ‘‘
  • multi level undo โ†ฉ๏ธ
  • command line editing with completion โœจ
  • binary regular expressions (more on that later, iykyk)

the user interface is kept similar to vi, so if you already know how to use vi, you'll get started easily. literally built different but familiar ๐Ÿซถ


๐Ÿ’œ OPTIONS ๐Ÿ’œ

  • -R, --readonly โ€” bestie this one is just sitting there in the manual with no description attached, so i'm not gonna invent one for you ๐Ÿ™ˆ it's listed, that's what we know.
  • -v, --view โ€” edit files in read only mode ๐Ÿ”’
  • -r, --recover filename โ€” recover the file filename after a crash. (not implemented) ๐Ÿ˜ญ yeah. it's not implemented. we move.
  • -c, --command command โ€” start the editing session by executing the editor command command. if command contains spaces, it must be surrounded by double quotes. and yes, you can stack them on the command line:
hexer -c command1 -c command2 ...
  • -t, --tite โ€” turn off the usage of the termcap/terminfo ti/te sequence ๐ŸŒˆ
  • -h, --help โ€” display a short help message and exit ๐Ÿซก
  • -V, --version โ€” display program version information and exit โญ
  • -F, --features โ€” list the features supported by the program and exit ๐Ÿ”ฅ
  • +command โ€” this is equivalent to the -c option. same vibe, different outfit ๐Ÿ’…
๐Ÿ“Œ Note: the long options are not available on all systems. so if a long option ghosts you, it's not you, it's the system.

๐Ÿงš CUSTOMIZING ๐Ÿงš

the editor reads its startup commands from the file ~/.hexerrc ๐Ÿ  (another startup file may be specified by setting the environment variable HEXERRC).

here's the tea on parsing:

  • empty lines are ignored ๐Ÿซง
  • lines starting with a "-character (double quote) are ignored ๐Ÿซง
  • it is not possible to have a command and a comment in the same line. pick a lane bestie, one or the other ๐Ÿ’€

๐Ÿ‘‘ EDITOR COMMANDS ๐Ÿ‘‘

as in vi, there are several editing modes โœจ

๐Ÿฆ‹ Command Mode ๐Ÿฆ‹

some commands in Command Mode can take a numeric argument. to enter a numeric argument just type the (decimal) number. the number will be echoed at the bottom line of the screen as you type ๐Ÿ“บ

  • to enter an octal number, type a 0 as the first digit
  • to enter a hexadecimal number, type 0x (this is not a problem, because the x-command with a zero counter wouldn't make sense anyway ๐Ÿ’…)

some of the commands can take a visually selected area as an argument (see subsection Visual Mode).

  • b โ€” move backwards to the beginning of a word.
  • e โ€” move to the end of a word.
  • G โ€” if a numeric argument n is given, move the cursor to position n. if no argument is specified, set the position to the end of the buffer. the first byte in the buffer is at position 0, so the command to move to the beginning of the buffer is 0G. ๐Ÿ˜Œ
  • Control-G โ€” display the buffer name, size, status and the current position at the bottom line.
  • h j k l โ€” move the cursor. the arrow keys work as well ๐Ÿน the numeric argument (if specified) determines the number rows or columns the cursor will move. different from vi: the cursor can be positioned behind the last byte in the buffer. bold. iconic.
  • i โ€” enter Insert Mode (see below) at the current position of the point. if a numeric argument n is given, the typed text will be inserted n times. Note: moving the cursor (using the arrow keys) will discard the numeric argument.
  • n โ€” move to the next match using the current RE. this is equivalent to typing /, <Return>.
  • N โ€” move to the previous match using the current RE. this is equivalent to typing ?, <Return>.
  • Control-O โ€” paste over. copy the kill buffer to the current position overwriting the contents of the current buffer. if a numeric argument n is given, the kill buffer is pasted n times.
  • p โ€” paste. insert the kill buffer at the current position. if a numeric argument n is given, the kill buffer is pasted n times.
  • r โ€” replace a single byte using the Replace Mode. if an area is selected, all bytes in the selected area are replaced. if a numeric argument is given, the specified number of bytes is replaced.
  • R โ€” enter Replace Mode (see below). if a numeric argument n is given, the replace command is repeated n times. Note: moving the cursor (using the arrow keys) will discard the numeric argument.
  • Control-R โ€” redo the last undo ๐Ÿ”
  • u โ€” undo the last change to the current buffer โ†ฉ๏ธ

whenever possible hexer creates a file name.hexer in the current directory (the swapfile) for each buffer visited (where name is the name of the buffer) ๐Ÿ’พ all changes made to the buffer name are stored in that file, so it is possible to undo (and redo) all changes made to the buffer. if the swapfile can't be created, the undo list is stored in the memory. no swapfile? we cope ๐Ÿซ 

  • v โ€” enter Visual Mode (see below). visual selection of areas.
  • w โ€” move forward to the beginning of a word.
  • x โ€” delete the byte under the cursor. if a numeric argument n is given, n bytes are deleted. in Visual Mode, the selected area is deleted. Note: the bytes deleted using the x-command are not copied to the kill buffer. gone. vanished. ๐Ÿ’€
  • Control-X โ€” the same as the x-command, but the bytes deleted are copied to the kill buffer ๐Ÿ—‘๏ธโœจ
  • y โ€” yank. yank the byte under the cursor into the kill buffer. if a numeric argument n is given, n bytes are yanked into the kill buffer. in Visual Mode, the selected area is copied to the kill buffer.
  • zb โ€” place the cursor in the bottom line of the screen.
  • zt โ€” place the cursor in the top line of the screen.
  • zz โ€” place the cursor in the middle line of the screen.
๐Ÿ“Œ note that the commands zb, zt and zz don't change the position in the file โ€” only the screen is scrolled (if necessary). it's giving camera work, not plot development ๐ŸŽฅ
  • : โ€” enter Exh Mode (see below). the Exh Mode is similar to the ex-mode in vi, but not compatible. if an area is selected, the bounds of the selection are copied to the command line.
  • / โ€” search forward through the buffer using a RE (regular expression). if no RE is specified, the RE given in the previous /- or ?-command is reused.
๐Ÿ“Œ Note: the REs in hexer are a little bit different from regular expressions in vi (see section REGULAR EXPRESSIONS).
  • ? โ€” search reverse using a regular expression.
  • . โ€” repeat the last change to the buffer at the current position. this means that if the previous command deleted n bytes and replaced them by m other bytes (n or m may be zero), the .-command will do exactly the same at the current position in the file ๐Ÿ”
  • < โ€” shift the hex column left n bytes, where n is the (optional) numeric argument. Note that the <-command only changes the way the buffer is displayed in the hex column, the buffer itself is kept unchanged. it's a filter bestie, not a surgery ๐Ÿ’…
  • > โ€” shift the hex column right n bytes.
  • Control-^ โ€” switch to the alternate buffer (see below).
  • % โ€” enter a calculator command (see section CALCULATOR).

๐ŸŒˆ Visual Mode ๐ŸŒˆ

select an area on the buffer. you can enter the Visual Mode by using the v-command or by specifying an area in Exh Mode. the selection starts at the cursor position when entering the Visual Mode and ends at the current cursor position ๐Ÿ“

you can leave the Visual Mode without performing a command on the selected area by pressing v or Escape. to perform a command on the selected area simply enter the command as if you where in Command Mode. commands that can't use the selection will ignore it ๐Ÿ™ˆ

as in Command Mode, it is possible to specify a numeric argument. commands that can take the selection as an argument will ignore the numeric argument. so the selection eats the number. periodt.


๐ŸŒธ Insert Mode ๐ŸŒธ

in Insert Mode the bytes you type are inserted at the current position of the cursor โŒจ๏ธ

  • at any time, you can toggle the active column (hex column or text column) by pressing the TAB key.
  • if the hex column is active the bytes are entered as two digit hex numbers ๐Ÿ”ข
  • if the text column is active, the bytes are entered as ASCII text ๐Ÿ”ค
  • the Delete or BackSpace key deletes the previously inserted byte. if the hex column is active, the previously inserted nibble (hex digit) is deleted.
  • it is not possible to delete more bytes than have been inserted in the current insert command ๐Ÿšซ

while in Insert Mode, you can move the cursor using the arrow keys. Note that moving the cursor discards the numeric argument given to the insert command ๐Ÿ™ˆ

to leave the Insert Mode, type Escape. if a numeric argument n was given to the insert command and is hasn't been discarded by a cursor movement, the typed bytes are inserted n times ๐Ÿ”‚


๐Ÿ’œ Replace Mode ๐Ÿ’œ

in Replace Mode you replace the bytes under the cursor as you type โœ๏ธ hitting BackSpace restores the original contents of the buffer. the effect of a numeric argument is similar to the Insert Mode: the typed bytes are replaced n times. as in Insert Mode, moving the cursor using the arrow keys discards the numeric argument ๐Ÿ™ˆ


๐ŸŽ€ Exh Mode ๐ŸŽ€

the Exh Mode in hexer is kept similar to the ex-mode in vi. typically, an exh command looks like:

:area command arguments
  • perform the command command on the area area.
:command arguments
  • perform the command command at the current position.
:area
  • select the area area.
:position
  • move the cursor to position position.

an area may be defined as:

position1,position2
  • the area starts at position1 and ends at position2 (inclusive).
position
  • the area selects one byte at position
%
  • the area selects the entire buffer.

a position may be defined as:

  • offset โ€” a decimal, octal (prefixed with 0) or hex (prefixed with 0x) number.
  • . โ€” the beginning of the buffer.
  • $ โ€” the end of the buffer.
  • /regexp/ โ€” a regular expression (see section REGULAR EXPRESSIONS). the buffer is searched forward starting at the current position. if a match was found, the current position is set to the position of the match ๐Ÿ”
  • ?regexp? โ€” searches the buffer backwards, like a little rewind of the vibes ๐Ÿ”„

Commands may be abbreviated with a unique prefix of the command, and some commands can even be abbreviated with a single character, even if that character isn't a unique prefix of the command name. Currently the following commands are supported:

  • s, substitute โ€” Synopsis: area s /regexp/replace/flags

Search for the regular expression regexp and replace it with replace (see section REGULAR EXPRESSIONS). replace may contain \ references to subexpressions of regexp. flags:

  • g: global, this flag is ignored (it doesn't make sense in a binary editor, bestie, it's giving redundant ๐Ÿ’€).
  • c: confirm, ask the user to confirm each substitution.

(Note that the / character used as separator could be any character, it's just common practice to use /.) Trailing separators may be omitted. If area is omitted, the whole buffer is searched.

  • w, write โ€” Synopsis: area w filename

Write area to the file filename. If area is omitted, the whole buffer is written to the file, and if filename is omitted, the filename associated with the buffer is used. saving your work, we love to see it ๐Ÿ’พ

  • r, read โ€” Synopsis: position r filename

Insert the contents of the file filename at position. If position is omitted, the current position is used.

  • e, edit โ€” Synopsis: e name or: e #

Change to buffer name. If there is no such buffer, hexer tries to open a file named name and load it into a new buffer. If name is a hash sign (#), the alternate buffer is selected. On success the current buffer becomes the alternate buffer. โœจ

  • b, buffer โ€” Synopsis: b name or: b

Change to buffer name. On success the current buffer becomes the alternate buffer. If name is omitted, a list of all buffers is displayed.

  • n, next โ€” Select the next buffer in the buffer list. โžก๏ธ
  • N, previous โ€” Select the previous buffer in the buffer list. โฌ…๏ธ
  • S, skip โ€” Select the next unvisited buffer in the buffer list.
  • rewind โ€” Select the first buffer in the buffer list. โช
  • wall โ€” Write all unsaved buffers. the group-project saver fr fr
  • c, close โ€” Synopsis: c name or: c! name or: c or: c!

Close the buffer name. If name is omitted, the current buffer is closed. If the buffer has been modified, but not saved, it can't be closed using a :c-command; use :c! to override. careful, that override is a real one ๐Ÿ™ˆ

  • h, help โ€” View an online help text. ๐Ÿซถ
  • q, quit โ€” Synopsis: q name or: q! name or: q or: q!

Close all buffers and exit the editor. If an opened buffer has been modified, but not saved, the :q-command can't be performed; use :q! to override. no cap, that ! is the only thing standing between you and losing everything ๐Ÿ˜ญ

  • map / imap / vmap โ€” Synopsis: map from to or: imap from to or: vmap from to

The key sequence from is mapped to to. To enter special keys (e.g. function keys), mask them using Control-V. :map affects the Command Mode only, :imap affects the Insert Mode only and :vmap affects the Visual Mode only. It is not possible to re-map key sequences on the command line editor.

  • unmap / iunmap / vunmap โ€” Synopsis: unmap from or: iunmap from or: vunmap from

Delete a key mapping created with :map, :imap or :vmap.

  • set โ€” Synopsis: set variable [...] or: set variable=value [...] or: set novariable [...] or: set

There are not too many variables that could be modified, this might change though. The following variables can be used: iso (bool): display the whole ISO-8859/1 character set; ascii (bool): display ASCII characters only; TERM (string): the name of the terminal; maxmatch (number), specialnl (bool): see section REGULAR EXPRESSIONS. :set called without an argument lists all variables and values. ๐Ÿ‘‘

  • d, delete โ€” Synopsis: area d

Delete all bytes in area. The deleted bytes are copied to the kill buffer. ๐Ÿ—‘๏ธ

  • y, yank โ€” Synopsis: area y

Copy the bytes in area to the kill buffer.

  • version โ€” Display the version number of hexer.
  • zz โ€” Place the cursor in the middle line of the screen. Note that the screen is scrolled (if necessary); the cursor position is kept unchanged.
  • zt โ€” Place the cursor in the top line of the screen. โฌ†๏ธ
  • zb โ€” Place the cursor in the bottom line of the screen. โฌ‡๏ธ
  • wq โ€” The same as :x.
  • x, exit โ€” Save all buffers and exit the editor. clean exit, main character energy ๐Ÿ’…

If a command is called and can't use the given positions, areas or arguments, the additional positions, areas, arguments are ignored. Conditional commands: It is possible to specify a list of terminal names for which the given command should be executed. The syntax is:

:terminals:command

where terminals is a colon-separated list of terminal names. The command is executed if and only if the value of TERM is in the list. I.e. you could have a command like

:xterm:set iso

in your .hexerrc-file (use the ISO character set only if working on an xterm).

๐Ÿฆ‹ Cursor Motion ๐Ÿฆ‹

In Command Mode, Insert Mode, Replace Mode and Visual Mode, you can use the following cursor motion commands:

  • Arrow Keys โ€” Move the cursor.
  • Control-F โ€” Move forward one page.
  • Control-B โ€” Move back one page.
  • Control-D โ€” Move forward half a page.
  • Control-U โ€” Move back half a page.

โœจ COMMAND LINE EDITING โœจ

On the command line you can use the following commands:

  • UpArrow DownArrow โ€” Move up and down through the history of the current context. ๐Ÿ•ฐ๏ธ
  • LeftArrow RightArrow โ€” Move the cursor.
  • Control-A โ€” Move the cursor to the beginning of the line.
  • Control-E โ€” Move the cursor to the end of the line.
  • Control-K โ€” Delete all characters from the current cursor position up to the end of the line.
  • Control-U โ€” Delete all characters from the beginning of the line up to the current cursor position.
  • Delete / BackSpace โ€” Delete the character left of the cursor.
  • Control-D โ€” Delete the character under the cursor.
  • Enter Return โ€” Accept the line. โœ…
  • Escape โ€” Discard the line. Note: This is different from vi. not me getting jumpscared by this after years of vi ๐Ÿ˜ญ
  • TAB โ€” Try to complete currently typed word. If the completion is not unique, the word is completed as far as unique. If the TAB key is hit twice on the same position, a list of all possible completions is displayed. ๐ŸŒˆ

๐ŸŒธ REGULAR EXPRESSIONS ๐ŸŒธ

In this section it is assumed that you are familiar with REs (regular expressions). In most applications (egrep, vi, ...) REs work on lines, that means it is not possible to use a RE containing a line break (newline character). In hexer, the buffer is not split up into distinct lines and a newline character is considered to be a normal character, now here's the problem: imagine searching for "a.*b" in a 5 MB file, this would take very long (might be up to several minutes on a slow machine). That's why there's a maxmatch limit (a repeat operator matches at most maxmatch occurrences of its operand). The default value of maxmatch is 1024, but it may be customized using the :set-command. For simple expressions (expressions for which the length of the match can be determined from the expression) it is possible to override the maxmatch limit by doubling the * or + operator, e.g. "a.**b" or "foo\(bar\)\+\+".

Note that the context specifiers ^/$ (beginning/end of a line) and \</\> (beginning/end of a word) are available and actually do what you expect. If you don't want the atoms . and [^...] to match the newline character you can set the specialnl option using the :set-command.

To enter a special character, you can use the standard C \-escape sequences. To enter a character using its octal code, use a \o-prefix followed by up to three octal digits. (C-style octal escapes are not supported, because \0, ... \9 are interpreted as back-references to subexpressions of the RE.) To enter a character using it's hex code, type a \x-prefix followed by up to two hex digits; decimal codes can be entered using a \d-prefix followed by up to three decimal digits. It is possible to enter strings of codes by doubling the base specifier, e.g. "\xxfe ff 5a 7e" or "\oo276 277 132 176". Note that such a string is treated as an atom, i.e. the RE "\xxff fe*" matches any number (< maxmatch) of repetitions of ff fe. ๐Ÿงš

It is possible to use all kinds of character \-escapes (escapes representing a single character) within []-ranges. Within a range, the o selecting an octal base for the escape may be omitted, since back-references within a range don't make sense. When specifying a minimum and/or maximum number of repetitions using the \{,}-operator, the numbers may be given in decimal (no prefix), octal (0-prefix) or hex (0x-prefix). If no maximum number is specified and the operand is not a simple expression, at most maxmatch matches will be found. ๐Ÿ’–

๐Ÿงฎ CALCULATOR ๐Ÿงฎ

okay so this is the part where hexer just casually has a whole calculator built in?? bestie it's called myc and it can do literally every operation C can do. no cap. it's giving "editor that also does your math homework" energy ๐Ÿ’…

to run a myc command you just type a % (percent) sign and then an expression in infix notation. yes you can use parentheses, go wild with them, they're not gonna judge you ๐Ÿซถ

so myc understands these binary infix operators, listed from highest priority to lowest:

  • ** โ€” power ๐Ÿ”ฅ
  • * โ€” multiply
  • / โ€” divide
  • % โ€” modulo
  • + โ€” add
  • - โ€” subtract
  • << โ€” shift left
  • >> โ€” shift right
  • < โ€” less
  • <= โ€” less or equal
  • > โ€” greater
  • >= โ€” greater or equal
  • == โ€” equal
  • != โ€” not equal
  • & โ€” arithmetical and
  • | โ€” arithmetical or
  • ^ โ€” arithmetical exclusive or
  • && โ€” logical and
  • || โ€” logical or
  • = โ€” assign

and these unary prefix operators:

  • - โ€” negate, unary minus
  • ! โ€” logical not
  • ~ โ€” bitwise complement

and now for the data types, bestie, there are three:

  • boolean
  • integer โ€” 32 bit
  • float โ€” 64 bit, equivalent to C double
โš ๏ธ heads up: on some esoteric platforms the precision of integer and float may be different. so like, don't come for me if you're on a weird rock running hexer, okay? ๐Ÿ’€

and here's the iconic part โ€” just like in C, the result of a division depends on the data types of the operands. an integer divided by an integer yields an integer. so if you want the result to be a float, make sure one of the operands is a float, like:

4/7.

instead of 4/7, or

a/(b+0.)

instead of a/b.

the power operation returns a float if the result is too large to fit in an integer. it simply cannot contain the slay, so it switches types โœจ

and where does your little math moment go? the result of a calculation is stored in the special variables $$ and $n where n is the number of the command. yes ma'am, it remembers what you did ๐Ÿ‘‘


๐Ÿ› BUGS ๐Ÿ›

probably. ๐Ÿ˜ญ not me being honest on main. please report bugs to demetrio@cs.uni-sb.de.


hexer is not in the public domain, but it is freely distributable. it may be used for any non-commercial purpose. see file COPYRIGHT for details. read the fine print bestie, it's literally one file away ๐Ÿ“„


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Sascha Demetrio

demetrio@cs.uni-sb.de


and that's a wrap on the hexer manual, babe ๐ŸŽ€ this was Hexer 1.0.7, dated April 24, 2020 โ€” vintage but still eating, fr fr. now go edit something iconic ๐Ÿ’–โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from