This rewrites the look of the interactive horizontal histogram in Rizin -
the output of `p==v`, `p==ev`, `p==mv`, `p==0v`, `p==fv`, `p==pv`, `p==zv`,
`p==Sv` and the analysis-based interactive variants. It closes#6365 and
#4431 in full, and now sits on top of the recently merged static-histogram
PR (#6427) so it reuses the new RzHistogramOptions struct and its helpers.
Five sub-tasks from #6365:
- Context-aware vertical ruler with up to 5 anchor labels (top, bottom,
quarter, half, three-quarter) honouring opts->value_min..value_max,
value_precision, value_scale and value_unit. Reuses the static
helpers compute_ruler_gutter, render_ruler_gutter, label_value_at and
select_ruler_label_rows so visual and static stay consistent.
- X-axis byte-offset ruler at the bottom: `^` ticks every (addr_w + 3)
cols followed by absolute byte offsets computed from opts->offpos +
realj * blocksize.
- Cursor offset + percentage shown right-aligned on the status line, with
"Index N data V" on the left.
- Top minimap: Unicode block characters (▁▂▃▄▅▆▇█) for the density of
each slice of the whole data, plus a ┏━━━┓ window indicator showing the
visible slice. Always rendered when the new `scr.hist.minimap` config
is true. When the terminal is wide (hist->w > 200) the minimap shrinks
by 43 columns to make room for a two-line `px 0x20`-style hex preview
panel on the right showing the 32 bytes at the cursor's file offset.
Each byte is wrapped in its px-style colour code (b0x00 / b0x7f /
b0xff / btext / other) when opts->color is set, matching rz_print's
rz_print_byte_color exactly. A trailing safety pad keeps the canvas
from clipping the last byte of the first hex row.
- Missing-half bug on `p==v` when the cursor is at offset 0 fixed by
clamping `adder` to [0, histogramwidth - span]. The old expression
`barnumber + 1 - histogramwidth/(zoom*2)` was always negative for the
default barnumber=0, causing the rendering loop to read `data[-N]`
(segfault on large files, missing left half on small ones).
Cursor visibility:
- The cursor column is drawn as a CONTINUOUS vertical line connecting two
plain markers at the top and bottom, ALWAYS exactly one character wide.
The line itself uses the dedicated `wordhl` palette colour (default
red background, configurable via `ec wordhl ...`), drawn on every
chart row so the cursor is always a full-height vertical strip. The
markers (`▼` at the top and `▲` at the bottom, or ASCII `v` / `^`
when scr.utf8=false) are intentionally left un-highlighted so they
read as a clean pair of arrows pointing at the cursor column.
- The cursor screen column is computed up-front (j_cursor) by inverting
the data-to-column map (rel * zoom * width / histogramwidth). Two
distinct widening bugs are avoided this way:
1. sizeofonebar > 1 (high zoom) - each data index spans several
screen columns; only j == j_cursor && kbar == 0 renders as the
cursor, the remaining kbar columns fall through to the gradient.
2. histogramwidth < width (chart much wider than data) - several
adjacent screen columns map to the same data index via integer
truncation; only the j_cursor column may render as the cursor.
Interactive keybindings & live config:
- The `:` hotkey drops into rz_core_visual_prompt_input, matching the
rest of Rizin's visual modes. Lets the user run arbitrary rizin
commands without leaving the histogram.
- The `?` help text now uses the same colour-coded format as the
visual / visual-bit-editor modes (rz_core_visual_append_help with
pal.args for keys and pal.help for descriptions), shown via
rz_cons_less_str.
- The config-driven opts (scr.hist.minimap, scr.hist.block, scr.utf8,
scr.color, hex.offset) are re-read on every redraw via
refresh_visual_opts_from_config, so `:` `e scr.hist.minimap=true`
<Enter> takes effect immediately without having to quit and re-enter.
The canvas's `color` field is refreshed alongside so `scr.color`
changes take effect on the same redraw.
Hex preview panel:
- When the terminal is wide (hist->w > 200) and the minimap is enabled,
the visual mode shows a two-line hex preview on the right of the
minimap rows: 32 bytes at the cursor's file offset, formatted as 8
pairs of 2 bytes separated by spaces (`abcd ef00 1234 5678 ...`),
matching `px 0x20` minus the header / offsets / ASCII column. The
bytes are fetched live via rz_io_read_at_mapped each redraw, so
moving the cursor (`h` / `l`) updates the preview.
- Each byte gets its px-style colour code: green for 0x00, red for
0xff, yellow for 0x7f, btext (white) for printable ASCII, "other"
(magenta) for non-printable. Mirrors rz_print_byte_color so the
histogram preview reads consistently with `px`.
- A trailing safety pad keeps the canvas from clipping the last hex
byte of the first row (a side effect of UTF-8 minimap glyphs
interacting with the canvas's width tracking when the row fills
the canvas exactly).
- Implemented via two new fields on RzHistogramInteractive
(`cursor_bytes`, `cursor_bytes_len`) that the caller fills in just
before the render call and clears right after. The minimap helper
grows two extra parameters that the visual function passes through;
when the panel is disabled (narrow terminal, no cursor_bytes, or
shrinking the minimap would leave it < 40 cols) the helper falls
back to the previous full-width minimap.
Closes#4431 in full:
- The negative-offset crash above is the immediate segfault from the
bug report.
- `print_histogram_bytes` now samples one byte per block instead of
reading nblocks contiguous bytes from core->offset. For an 8 GB file
shown across 80 bars the original code rendered the first 80 bytes
of the file; the new code samples at offsets brange->from + i *
blocksize so the chart represents the full span.
- The inner `int i` in the column-aggregation loop is renamed to `k`
to drop the shadow over the outer `size_t i`.
Refactor on the cmd_print.c side:
- New default_visual_opts(core, offset) returns an RZ_OWN
RzHistogramOptions* pre-populated for the visual commands (ruler=true,
minimap from scr.hist.minimap, offpos from caller, palette and
screen-mode toggles from config via refresh_visual_opts_from_config).
The nine print_visual_bytes call sites now build opts via this helper,
then pass it to print_visual_bytes which takes ownership. Entropy
sets value_max=8 / value_precision=1 / data_f=fdata so the visual
histogram shows the Shannon range matching the static side.
- `print_visual_bytes(core, opts, data, brange)` now propagates opts
cleanup along every error path; rz_histogram_interactive_new no
longer leaves a heap-allocated opts pointer dangling. The redraw loop
fetches 32 cursor bytes via rz_io_read_at_mapped, points
hist->cursor_bytes at a stack buffer for the call, then NULLs it
back so the next iteration's fetch is independent.
- RzHistogramInteractive gains `blocksize`, `cursor_bytes` and
`cursor_bytes_len` fields.
New config option:
- `scr.hist.minimap` (bool, default true) controls whether the top
minimap is shown for p==v / p==ev. Surfaces as `opts->minimap` and
is honoured by `rz_histogram_interactive_horizontal`. When true,
the minimap is ALWAYS rendered (provided there's room) - even when
the chart already shows the full data, in which case the window
indicator spans the whole map. Changes via `:` `e scr.hist.minimap=...`
<Enter> are picked up on the very next redraw.
Tests (33 total, 10 new for the visual side):
- test_histogram_interactive_horizontal_basic - smoke test with
barnumber=0 (pins the #4431 crash regression).
- test_histogram_interactive_horizontal_ruler_percent - fractional
labels with value_max=100 / value_scale=0.01 / unit="%".
- test_histogram_interactive_horizontal_ruler_default - the legacy
0..255 byte ruler.
- test_histogram_interactive_horizontal_no_negative_adder - covers
`p==v` at offset 0 on a small data set.
- test_histogram_interactive_horizontal_percent - status-line percent
indicator present.
- test_histogram_interactive_horizontal_cursor_markers - the ▼/▲
cursor markers (and ASCII v/^ fallback) appear on the cursor column,
left un-highlighted.
- test_histogram_interactive_horizontal_cursor_full_line - the cursor
bar is rendered on every chart row between the markers regardless
of the data threshold (continuous vertical line).
- test_histogram_interactive_horizontal_cursor_width - pins single-
char width across BOTH cursor-widening bugs: high zoom (sizeofonebar
> 1) AND chart wider than data (histogramwidth < width).
- test_histogram_interactive_horizontal_minimap_toggle - pins the
scr.hist.minimap gating across {zoomed, not zoomed} when
opts->minimap=true / =false.
- test_histogram_interactive_horizontal_hex_preview - 4 cases: wide
terminal + cursor_bytes shows the hex panel; narrow terminal
suppresses it; missing cursor_bytes suppresses it; colour mode
emits ANSI escape sequences for the bytes.
Both p== integration tests in test/db/cmd/cmd_print pass with their
regenerated EXPECT blocks (the per-block sampling change moves the
visible bars for small buffers).
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
Close two long-standing issues against the static horizontal histogram
(`p==`, `p==e`, `p==0` and the rest of the `p==X` family). Add the
`scr.hist.width` / `scr.hist.height` config options (closes#6372),
both clamped via RZ_MIN() against the current terminal size with a
defensive sanity floor. Make the Y-axis ruler context-aware (closes
#5290) via new `value_min` / `value_max` / `value_unit` fields on
`RzHistogramOptions` and rescale each datum from its ut8 storage into
the vmin..vmax display range before thresholding, which also fixes
cer-0's follow-up about the chart's top rows staying blank for
low-range data.
Tighten the look in the same step. Y-axis labels are now sparse (top,
~25 %, ~50 %, ~75 %, bottom) instead of one per row, in the style of
tokio-console / Granite, with an inclusive label range (top = vmax,
bottom = vmin) decoupled from the threshold formula so the existing
`_` baseline behaviour still appears. The bottom of the chart grows
an X-axis ruler with `^` tick markers and `0x...` start / middle /
end offsets (driven by a new `opts->blocksize` field). Two more
options, `value_scale` and `value_precision`, let callers format
ruler labels as fractional values; the `p==e` (entropy) command opts
in with `value_max = 1, value_precision = 2` so the ruler reads
0.00..1.00 by default, matching Shannon-entropy convention.
A new `opts->data_f` field lets callers feed double-precision data
directly into the renderer (and engages double-precision arithmetic
for the row thresholds), so entropy keeps full precision end-to-end
instead of losing ~1/255 of resolution to the `(ut8)(255 * fraction)`
quantisation step. This captures the precision win sketched in PR
#6355 without introducing a separate `rz_histogram_horizontal_f64()`
twin function. Ten unit tests in `test/unit/test_cons_histogram.c`
(seven new) cover sparse labels, fractional labels, the X-axis offset
ruler, the cer-0 regression, `opts->cols`, the legacy 0..255 ruler,
and the fp data path; all pass.
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This PR introduces the following changes to rizin shell:
- Use Meta-L to lowercase the following word
- Use Meta-U to uppercase the following word
- Use Meta-C to capitalize the following word
The behavior of these actions is the same as in zsh.
* Remove RIZIN command output for the old projects
* Fix cmeta.c
* Fix ik command
* Revert back pc*
* fix formatting cmd_descs_generate.py
* Fix rz_cons_pal_list_as_css
* Fill all info about colors for ec commands.
* Fix all tests
* Add ?** as alias for ?*~...
* Zero initialize the help desc copy.
Fixes a bug when detail_cb was called but it was just garbage.
* Implement ?***
* Add tests for interactive command search
* Add string buffer output mode for internal use and use it for setting help.
* Add ?**e for interactive search of config values.
* Fix sys.c unused variable.
* Add native/unsupported.c
* Clean rz_debug.h from comments and functions which does not exists
* Add fall-thru comment for haiku os case
* Fix warning: "MIN" redefined /boot/system/develop/headers/posix/sys/param.h:18: note: this is the location of the previous definition
- All `ht_*_new0()` are removed
- `freefn` field of HT options was renamed to `finiKV`
- `finiKV_user` fields was added to HT options
- Added `ht_*_new_opt_size` API
- `HtSP` and `HtUP` are created with `ValueFree` callback that allows to reduce extra LOC and prevent bugs
- `SetP` replaced with `SetS` (based on `HtSP`)
- `rz_th_ht_*_new0()` and `rz_th_ht_*_new_opt()` are replaced with `rz_th_ht_*_new(HtXX *)`
* Replace OpenBSD regex library with PCRE2.
PCRE2 has way better performance than the OpenBSD
library (something around 20 times faster).
The following flags are enabled for every pattern:
- PCRE2_UTF
- PCRE2_MATCH_INVALID_UTF
- PCRE2_NO_UTF_CHECK
All the others are optional.
Changes made:
- Adds PCRE2 as subproject.
- Changes the API away from POSIX to PCRE2.
- Edits many regex patterns because:
- ' ' is skipped in patterns, if the EXTENDED flag is set for matching. '\s' must be set now.
- '.' doesn't match newlines by default.
- Changes the API so matches and their groups are bundled into PVectors.
- Moves the regex component to rz_util.
* Fix cross build - add copy of PCRE2 dependecy
Meson currently doesn't support subprojects to be native and non-native at the same time.
See: https://github.com/mesonbuild/meson/issues/10947
Unfortunately, sdb depends on rz_util which in turn depends on PCRE2.
Excluding PCRE2 from the native build makes linking of rz_util not possible anymore.
Adding it, will make Meson complain that the dependencies cannot be mixed.
Hence, we compile a copy of PCRE2 for the native build if required.
* Add support for arrow keys on some terminals
Some terminals use the sequences \EO{A,B,C,D} for the arrow keys
(e.g. xterm, tmux, screen).
* Remove cursor move on Ctrl-l
^L clears the screen as expected, but the cursor is moved and it is
probably not intended.
* Improve cmd_help.yaml and fix a small bug
* Add support for 64bit random numbers
* Make a distinction between 32- and 64-bit PRNG
* Add documentation for new functions
* Change the RBTree test to use 32-bit random numbers