209 Commits
Author SHA1 Message Date
David Peter 5981fc8725 Bump MSRV to 1.66 2023-07-26 08:54:15 +02:00
David Peter f4515b0f14 Update CHANGELOG 2023-07-26 08:51:26 +02:00
David Peter e3d406dd95 Update dependencies 2023-07-26 08:47:03 +02:00
David Peter b6b7e2c79a Merge pull request #197 from sharifhsn/stdin-fix
Correctly handle discontinuous input i.e. stdin
2023-07-23 13:07:31 +02:00
Sharif Haason dfad7b3faf Refactor to avoid code duplication 2023-06-20 10:55:07 -04:00
Sharif Haason ef9b530d6a Finish comment 2023-06-20 10:46:48 -04:00
Sharif Haason a3268b8791 Correctly handle discontinuous input i.e. stdin 2023-06-20 10:45:13 -04:00
David Peter 2a534483c8 Update README.md 2023-05-25 15:27:04 +02:00
David Peter e6ba196bcb Merge pull request #193 from v0idx/master
Add color reference table to README.md
2023-05-25 15:26:11 +02:00
David Peter d0bd971382 Merge pull request #192 from LemmingAvalanche/master
Bump version in readme (0.13.0)
2023-05-25 15:24:41 +02:00
v0idx 8eed3cadbb Add color reference table to README.md 2023-05-22 02:33:41 +01:00
Kristoffer Haugsbakk 38a9662ea5 Bump version in readme (0.13.0) 2023-05-18 17:31:31 +02:00
David Peter e10136d203 Updates for 0.13 2023-05-10 22:19:07 +02:00
David Peter 5f0373184f Add --characters, change meaning of -C
This changes the meaning of `-C` to "show the character panel". The long
version `--no-characters` can still be used to hide the character panel.

closes #187
2023-05-10 22:09:19 +02:00
David Peter 57d18482ba Add Copy and Clone for Endianness 2023-04-26 14:53:37 +02:00
David Peter 816779e968 Merge pull request #189 from RinHizakura/master
Support both little and big endian dump
2023-04-25 09:20:23 +02:00
David Peter 9be018fbb9 Add -e alias for --endianness=little 2023-04-25 09:12:26 +02:00
David Peter cba717b783 Minor doc comment adjustment 2023-04-25 08:51:31 +02:00
David Peter 580f865c4a Rename function 2023-04-25 08:50:55 +02:00
David Peter 20450310c9 Help text adjustments, do not require group-size to be present 2023-04-25 08:48:39 +02:00
RinHizakura b251575d94 Change design for endianness command line option 2023-04-24 23:44:49 +08:00
RinHizakura 58b038af27 Change le to non-abbreviated name little endian 2023-04-24 23:13:28 +08:00
RinHizakura d703cdfd78 Fix comment error and grammarly 2023-04-24 23:10:25 +08:00
RinHizakura 43f8b92502 Fix test for endianness 2023-04-24 22:59:23 +08:00
RinHizakura a966896d3f Fix integration test module name 2023-04-24 22:59:23 +08:00
RinHizakura 08b903270f Change endianness from boolean type to enum 2023-04-24 22:59:19 +08:00
David Peter dd601e4792 Run cargo fmt 2023-04-21 21:28:52 +02:00
RinHizakura 564cf64b1b Support both little and big endian dump 2023-04-21 21:26:43 +02:00
David Peter c24280620a Merge pull request #191 from sharkdp/ci-sync
CI update
2023-04-21 21:25:27 +02:00
David Peter bfa2726e05 CI update 2023-04-21 21:02:49 +02:00
David Peter d6af232691 Merge pull request #188 from sharkdp/ci-update
CI: macos 12
2023-02-26 19:53:56 +01:00
David Peter cc6987e270 CI: macos 12 2023-02-26 13:44:08 +01:00
David Peter ee56a3396d Bump version 2022-12-07 23:48:29 +01:00
David Peter 4833c2afe4 Merge pull request #183 from sharifhsn/owo
Use `owo-colors` instead of `anstyle`
2022-12-07 23:42:54 +01:00
sharifandDavid Peter dfd7bdef49 Update src/bin/hexyl.rs
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2022-12-07 17:33:35 -05:00
sharif fd4aee2b85 Merge branch 'master' into owo 2022-12-07 16:51:30 -05:00
Sharif Haason cf8e7ec079 Revert default color option to always 2022-12-07 16:48:20 -05:00
Sharif Haason faa9866d11 Change group_bytes to satisfy merge conflict 2022-12-07 16:44:11 -05:00
David Peter 1df35eeb63 Renme --group-bytes to --group-size
For `xxd`-compatibility reasons

see #121
2022-12-07 21:50:12 +01:00
David Peter 437a15f3d6 One panel by default is terminal is not wide enough
closes #182
2022-12-07 21:35:34 +01:00
David Peter 70fa092df1 Do not fail if output is not a TTY for --panels=auto
closes #184
2022-12-07 21:33:20 +01:00
Sharif Haason b2f0e75ed2 Satisfy clippy 2022-12-06 13:22:34 -05:00
Sharif Haason 4fc0c1f1b0 Replace anstyle with owo-colors 2022-12-06 11:27:16 -05:00
Sharif Haason 4ce6e9d799 Remove now unnecessary byte_char_panel_g 2022-12-06 11:26:19 -05:00
Sharif Haason 5bd76fd11b Replace is-terminal with supports-color and make auto default for color 2022-12-06 11:24:53 -05:00
David Peter c7e2235293 Update CHANGELOG 2022-12-05 10:01:03 +01:00
David Peter 421bd73ec1 Revert "Replace libc with rustix"
This reverts commit 571312dd6e.
2022-12-05 09:52:27 +01:00
David Peter e888021a48 Update version in README, man page 2022-12-05 09:48:10 +01:00
David Peter 7d38f70918 Show 0x00-bytes as '⋄' instead of '0', closes #166 2022-12-05 09:45:38 +01:00
David Peter c6af2edda8 Bump version 2022-12-05 09:32:07 +01:00
David Peter a7fadfaaf2 Update dependencies 2022-12-05 09:31:43 +01:00
David Peter 8577a17b14 Ignore EPIPE silently
fixes a regression introduced in a6aeabfde4

closes #181
2022-12-05 09:30:13 +01:00
David Peter 2d8b600c48 Update CHANGELOG 2022-12-05 09:11:47 +01:00
David Peter f8601e5bc9 Merge pull request #180 from sharifhsn/altdeps
Replace outdated dependencies
2022-12-05 09:03:40 +01:00
David Peter 9770b89cf4 Merge pull request #178 from sharifhsn/base
[feature] Implement alternate bases
2022-12-05 09:03:03 +01:00
Sharif Haason 571312dd6e Replace libc with rustix 2022-12-04 21:48:10 -05:00
Sharif Haason fcd09fffac Relax anstyle version 2022-12-04 21:43:03 -05:00
Sharif Haason 188e753675 Replace atty with is-terminal 2022-12-04 21:42:44 -05:00
Sharif Haason 030235afb7 Improve help text for --base 2022-12-04 21:36:42 -05:00
Sharif Haason 7847e8cd33 Remove debug statement 2022-11-27 19:45:33 -05:00
Sharif Haason 32f4ce9987 cargo fmt 2022-11-27 17:52:29 -05:00
Sharif Haason 2a4b17a162 Add tests for alternate base 2022-11-27 17:32:18 -05:00
Sharif Haason 5e3c49f933 cargo fmt 2022-11-27 17:19:48 -05:00
Sharif Haason fc794b290c Account for new panel arguments 2022-11-27 17:19:33 -05:00
Sharif Haason e6000a56f4 Parse -b argument 2022-11-27 17:18:38 -05:00
Sharif Haason 2861cd51ac Adjust panel calculation to account for base and group 2022-11-27 17:17:52 -05:00
Sharif Haason a8cffbb6df Move group_bytes so it can be used for panels 2022-11-27 17:17:25 -05:00
Sharif Haason 7bb6343d2a Add --base/-b argument 2022-11-27 17:16:48 -05:00
Sharif Haason 7de17c4f35 Adjust spaces on empty lines 2022-11-27 17:15:26 -05:00
Sharif Haason ec61c2a789 Print header only if non-empty 2022-11-27 17:14:30 -05:00
Sharif Haason 7f7b88a914 Adjust tests 2022-11-27 17:13:36 -05:00
Sharif Haason 85fa75ba67 Differentiate format on base 2022-11-27 17:11:55 -05:00
Sharif Haason d5d645fc48 Add Base to Printer 2022-11-27 17:11:21 -05:00
David Peter 8d3aa65134 Merge pull request #176 from sharifhsn/anstyle
Change `ansi_term` to `anstyle`
2022-11-27 21:02:26 +01:00
Sharif Haason 252b4e84c3 Merge branch 'master' into anstyle 2022-11-27 10:03:53 -05:00
Sharif Haason 3dc118d0ad cargo update 2022-11-27 09:47:38 -05:00
Mikhail Katychev b1ff8b6ce4 added squeeze tests 2022-11-26 20:18:21 +01:00
David Peter fe65792b96 Add CHANGELOG entry 2022-11-26 13:07:06 +01:00
David Peter 31c0bcfeae Improve error messages 2022-11-26 13:07:06 +01:00
RinHizakura c0f94ad6aa Refine the support of byte grouping 2022-11-26 13:07:06 +01:00
RinHizakura 55fed5e3c0 Fix for clap4 2022-11-26 13:07:06 +01:00
RinHizakura aeee0a1033 Add new integration tests for group bytes feature 2022-11-26 13:07:06 +01:00
RinHizakura 179c8f40a2 Support byte grouping 2022-11-26 13:07:06 +01:00
Sharif Haason fb2500d7d6 Include Cargo.lock 2022-11-19 11:40:03 -05:00
Sharif Haason ad9ecda952 Remove once_cell dependency 2022-11-19 11:04:59 -05:00
Sharif Haason c43effefd6 cargo fmt 2022-11-19 11:04:13 -05:00
Sharif Haason 0b6454ed9d Use Vec of enums for color instead of HashMap 2022-11-19 10:50:31 -05:00
Sharif Haason 557ae66ed5 Update Cargo.lock 2022-11-18 16:15:49 -05:00
Sharif Haason df1afdc73f Merge branch 'anstyle' of https://github.com/sharifhsn/hexyl into anstyle 2022-11-18 16:15:12 -05:00
Sharif Haason 9106b899b2 Bump MSRV 2022-11-18 19:22:24 +01:00
Sharif Haason df1c36e5a7 Satisfy clippy 2022-11-18 19:22:24 +01:00
Sharif Haason ac610f7bad Add get_one and fix ordering 2022-11-18 19:22:24 +01:00
Sharif Haason 767740865f Update predicate for default_value_if 2022-11-18 19:22:24 +01:00
Sharif Haason 1fb324f411 Use ArgAction for flags 2022-11-18 19:22:24 +01:00
Sharif Haason 3d0bc3d0eb Replace 'value_of with get_one::<String>` 2022-11-18 19:22:24 +01:00
Sharif Haason 8a52261a50 Replace possible_values with value_parser 2022-11-18 19:22:24 +01:00
Sharif Haason ccc4fb9ba9 Replace takes_value with num_args 2022-11-18 19:22:24 +01:00
Sharif Haason 0baa22f152 DeriveDisplayOrder now default 2022-11-18 19:22:24 +01:00
Sharif Haason 165ced9307 Update to clap 4.0 2022-11-18 19:22:24 +01:00
Sharif Haason 3888a20dfe Bump MSRV 2022-11-18 11:06:18 -05:00
Sharif Haason 75b37fa125 Use compatible lockfile 2022-11-18 11:01:39 -05:00
Sharif Haason 794e1935e3 Prerender color strings for better performance 2022-11-18 10:39:54 -05:00
Sharif Haason c49aa079b4 Add color only when needed 2022-11-18 08:19:13 -05:00
Sharif Haason 675ef6d4a8 Remove calls to ansi_term 2022-11-17 22:33:49 -05:00
Sharif Haason eade38c94a Explicitly paint with style formatting 2022-11-17 22:33:03 -05:00
Sharif Haason 98ceec18cd Replace colors with ANSI styles 2022-11-17 22:15:53 -05:00
Sharif Haason a49f295acc Replace deprecated ansi_term with anstyle 2022-11-17 22:12:00 -05:00
Sharif Haason 0caab15255 Document the main loop 2022-11-13 22:15:41 +01:00
Sharif Haason 828fb210ce Use repeat byte when discovering squeeze 2022-11-13 22:15:41 +01:00
Sharif Haason 1e43783616 Clean up flags for ergonomics 2022-11-13 22:15:41 +01:00
Sharif Haason 6b7cfefec6 Use repeated byte optimization on nonzero bytes 2022-11-13 22:15:41 +01:00
Sharif Haason 5f82942f98 Add second check if read fails unexpectedly 2022-11-13 22:15:41 +01:00
Sharif Haason f6a1c4e8e3 Add unit tests for new implementation of squeeze 2022-11-13 22:15:41 +01:00
Sharif Haason b4fb1b079c Print last line only when squeezed 2022-11-13 22:15:41 +01:00
Sharif Haason f9f59d653d Print asterisk when no position panel 2022-11-13 22:15:41 +01:00
Sharif Haason c82695f0a9 Fix incomplete line ending when squeezed 2022-11-13 22:15:41 +01:00
Sharif Haason 9d938b11ed Remove unnecessary ending case (covered by next) 2022-11-13 22:15:41 +01:00
Sharif Haason d5982c0eb0 Optimize line check when squeezing zero bytes 2022-11-13 22:15:41 +01:00
Sharif Haason 1502419ad4 Document byte_hex_panel_g 2022-11-13 22:15:41 +01:00
Sharif Haason f5be845d70 Satisfy clippy 2022-11-13 22:15:41 +01:00
Sharif Haason 664025477b Alter when position panel is called 2022-11-13 22:15:41 +01:00
Sharif Haason 074bc791c2 Fix incomplete line ending 2022-11-13 22:15:41 +01:00
Sharif Haason 77a4ad25f1 Remove unnecessary import 2022-11-13 22:15:41 +01:00
Sharif Haason ca31d466ba Keep newline consistent 2022-11-13 22:15:41 +01:00
Sharif Haason 945e7a3472 Remove unnecessary squeezer module 2022-11-13 22:15:41 +01:00
Sharif Haason 75d612ff11 Alter newline usage 2022-11-13 22:15:41 +01:00
Sharif Haason 15e8abfc9a Complete architectural rewrite (intentionally fails) 2022-11-13 22:15:41 +01:00
Sharif Haason b36d74ed9d Track squeeze_byte correctly 2022-11-13 22:15:41 +01:00
Sharif Haason 094bf63f02 Eliminate unnecessary call to active 2022-11-13 22:15:41 +01:00
Sharif Haason e0e870de27 Store squeezed byte instead of pushing to vector 2022-11-13 22:15:41 +01:00
Sharif Haason 966421c522 Undo inlining to satisfy MSRV 2022-11-13 22:15:41 +01:00
Sharif Haason 166c2cc46b Inline StdoutLock variable 2022-11-13 22:15:41 +01:00
Sharif Haason 74a5e4bc84 Print first line always 2022-11-13 22:15:41 +01:00
Sharif Haason 363ea0a586 Undo perf regression on squeezer 2022-11-13 22:15:41 +01:00
Sharif Haason 1c4c7ed9a5 Satisfy clippy 2022-11-13 22:15:41 +01:00
Sharif Haason b5c224c119 Fix for no position panel 2022-11-13 22:15:41 +01:00
Sharif Haason d6e34d9dd2 Fix issues with hello_world_elf64 2022-11-13 22:15:41 +01:00
Sharif Haason 1cb346bd13 Fixes --no-characters causes output artifacts when squeezing lines #171 2022-11-13 22:15:41 +01:00
Sharif Haason daa40900bd Fix char panel showing even if disabled 2022-11-13 22:15:41 +01:00
Sharif Haason d98c6edb55 Fix overflow when printing without char panel 2022-11-13 22:15:41 +01:00
Sharif Haason 73bfc68cd0 cargo fmt 2022-11-13 22:15:41 +01:00
Sharif Haason 5d3f36d066 Remove write! formatting from hot loop 2022-11-13 22:15:41 +01:00
Sharif Haason d214bc63f1 Precalculate position formatting in Printer state 2022-11-13 22:15:41 +01:00
Sharif Haason a6aeabfde4 Refactor code to replace manual buffering with BufReader and BufWriter 2022-11-13 22:15:41 +01:00
Sharif Haason 9602667991 Rename with_panels to num_panels 2022-10-04 18:09:47 +02:00
Sharif Haason 9ccf18f4c0 Update CHANGELOG.md with PrinterBuilder 2022-10-04 18:09:47 +02:00
Sharif Haason aa921ca184 Rename with_squeeze to enable_squeezing 2022-10-04 18:09:47 +02:00
Sharif Haason 4823523b7d Remove superfluous with_writer function 2022-10-04 18:09:47 +02:00
Sharif Haason 4569c8f871 Self-document simple.rs example with builder API 2022-10-04 18:09:47 +02:00
Sharif Haason 80163764c3 Implement builder pattern 2022-10-04 18:09:47 +02:00
Sharif Haason 9bc81820e7 Update CHANGELOG 2022-09-11 21:45:06 +02:00
Sharif Haason 273ef0c045 Remove short options for panels and terminal-width 2022-09-11 21:45:06 +02:00
Sharif Haason ac1a67e90c Fix abbreviation clash 2022-09-11 21:45:06 +02:00
Sharif Haason 12324d615a Rename --columns to --panels 2022-09-11 21:45:06 +02:00
Sharif Haason 6b062ba127 Fix typo 2022-09-11 21:45:06 +02:00
Sharif Haason 8c7c3a073c Use --columns=auto instead of --auto-width 2022-09-11 21:45:06 +02:00
Sharif Haason 0565901fad Return a proper error if terminal size fails 2022-09-11 21:45:06 +02:00
Sharif Haason 41b3241718 Change columns type to u16 2022-09-11 21:45:06 +02:00
Sharif Haason 975a406d20 Remove debugging line 2022-09-11 21:45:06 +02:00
Sharif Haason aa43c20f39 Bump MSRV 2022-09-11 21:45:06 +02:00
Sharif Haason 1fdd770093 Implement -a and -t for terminal width setting 2022-09-11 21:45:06 +02:00
Sharif Haason a3fde45c18 Added test for multiple columns 2022-09-11 21:45:06 +02:00
Sharif Haason 85659a9cd6 Prevent overflow when columns >= 32 2022-09-11 21:45:06 +02:00
sharifandDavid Peter 2a4a22c9cb Update src/squeezer.rs
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2022-09-11 21:45:06 +02:00
Sharif Haason b820bdfeca cargo fmt 2022-09-11 21:45:06 +02:00
Sharif Haason b9348ffb1d Adds --columns for Print using custom width #13 2022-09-11 21:45:06 +02:00
Giovanni Tirloni 55cf7b034c Add Fedora install instructions 2022-06-23 21:56:49 +02:00
Vadym-Valdis Yudaiev c622c8217f doc: Add example usage with terminal pager 2022-05-24 18:57:21 +02:00
David Peter 49484fa0f0 Bump MSRV 2022-05-22 22:26:59 +02:00
David Peter 3661b06b60 Update CHANGELOG 2022-05-22 22:24:47 +02:00
David Peter f5814d4442 Update version 2022-05-22 22:23:25 +02:00
David Peter 49ebf4771f Update to clap 3 2022-05-22 22:21:49 +02:00
David Peter 4904a7e26f Relax constraints 2022-05-22 21:53:26 +02:00
David Peter becc1b80f1 Update dependencies 2022-05-22 21:52:44 +02:00
David Peter 1fb5263c3b Fix clippy suggestions 2022-05-22 21:48:40 +02:00
David Peter 0ae89168ad Update CHANGELOG 2022-05-22 21:39:42 +02:00
Mikhail Katychev 6873867658 table -> panel 2022-05-22 21:34:26 +02:00
Mikhail Katychev f15e049bf5 added proposed table suffix to no_chars and no_position 2022-05-22 21:34:26 +02:00
Mikhail Katychev 1d04cdf119 bump min version 2022-05-22 21:34:26 +02:00
Mikhail Katychev 5d92f07e21 cargo clippy warning 2022-05-22 21:34:26 +02:00
Mikhail Katychev a4ed50e1f0 clippy feedback 2022-05-22 21:34:26 +02:00
Mikhail Katychev f7f7447994 added --plain functionality 2022-05-22 21:34:26 +02:00
cuishuang e4f0e8a092 fix some typos
Signed-off-by: cuishuang <imcusg@gmail.com>
2022-05-18 20:10:29 +02:00
Shun Sakai a23645ddfd Add man page 2022-03-27 10:22:14 +02:00
Shun Sakai 7da04c6bff Change -l to conflict with -n and -c 2022-03-25 22:00:40 +01:00
Shun Sakai c497c1fac9 Fix Clippy warnings 2022-03-25 22:00:40 +01:00
Shun Sakai 653cf02954 Add rustfmt and clippy to the CI 2022-03-25 22:00:40 +01:00
David Peter 18cdbe02c5 Fix Debian package description 2021-11-14 09:36:35 +01:00
merkrafter d1ae68585f Make code compatible with rust 1.46 2021-11-14 09:26:21 +01:00
merkrafter 7a225fe732 Apply clippy suggestions 2021-11-14 09:26:21 +01:00
merkrafter 1b33e516d9 Move hex number processing into own function 2021-11-14 09:26:21 +01:00
merkrafter 55d02c933a Move sign (+/-) processing into own function 2021-11-14 09:26:21 +01:00
merkrafter b8ed8d5df9 Raise minimum Rust version for executable to 1.46 2021-11-14 09:26:21 +01:00
merkrafter 641c32e395 Mention new feature in CHANGELOG 2021-11-14 09:26:21 +01:00
merkrafter 51b28ed0b0 Allow hex numbers for --block-size 2021-11-14 09:26:21 +01:00
merkrafter 825100c6d6 Deny 'block' as unit for --block-size 2021-11-14 09:26:21 +01:00
merkrafter 1b1fc4b053 Allow units for --block-size 2021-11-14 09:26:21 +01:00
merkrafter c3dd4e871e Use extraction function for length arg parsing 2021-11-14 09:26:21 +01:00
merkrafter 923bceffaa Add function to extract num and unit from string
Having this as an own function allows special handling of the
'block' unit in --block-size argument.
2021-11-14 09:26:21 +01:00
merkrafter 2942d2419f Introduce enum for byte size units 2021-11-14 09:26:21 +01:00
merkrafter 37d4180f9a Refactor default block size into constant 2021-11-14 09:26:21 +01:00
Mark Umnus 99435cd215 Mention ability to specify length in hex 2021-10-20 22:52:01 +02:00
Issac Lin 27f039d72a README: Add scoop instruction (on Windows) 2021-09-20 08:41:25 +02:00
a1346054 e72422ecfb Trim trailing whitespace 2021-08-28 09:56:56 +02:00
a1346054 3c56ed2b0e Fix typos 2021-08-28 09:56:56 +02:00
a1346054 a09ea8ee27 Use HTTPS links 2021-08-28 09:56:56 +02:00
David Peter d6bdfe9897 Update package links 2021-08-25 22:17:21 +02:00
HRXN 7c9f7e1bd0 README.md does not mention availability of binary builds for Windows
Could not check this, but release page lists Windows binaries, apparently.
2021-07-12 07:15:41 +02:00
David Peter b1d2a47590 Remove old ci/ directory 2021-07-11 22:03:19 +02:00
15 changed files with 2414 additions and 1227 deletions

No files matched your search

+120 -101
View File
@@ -1,8 +1,8 @@
name: CICD name: CICD
env: env:
MIN_SUPPORTED_RUST_VERSION: "1.40.0"
CICD_INTERMEDIATES_DIR: "_cicd-intermediates" CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
MSRV_FEATURES: ""
on: on:
workflow_dispatch: workflow_dispatch:
@@ -14,70 +14,102 @@ on:
- '*' - '*'
jobs: jobs:
crate_metadata:
name: Extract crate metadata
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Extract crate information
id: crate_metadata
run: |
cargo metadata --no-deps --format-version 1 | jq -r '"name=" + .packages[0].name' | tee -a $GITHUB_OUTPUT
cargo metadata --no-deps --format-version 1 | jq -r '"version=" + .packages[0].version' | tee -a $GITHUB_OUTPUT
cargo metadata --no-deps --format-version 1 | jq -r '"maintainer=" + .packages[0].authors[0]' | tee -a $GITHUB_OUTPUT
cargo metadata --no-deps --format-version 1 | jq -r '"homepage=" + .packages[0].homepage' | tee -a $GITHUB_OUTPUT
cargo metadata --no-deps --format-version 1 | jq -r '"msrv=" + .packages[0].rust_version' | tee -a $GITHUB_OUTPUT
outputs:
name: ${{ steps.crate_metadata.outputs.name }}
version: ${{ steps.crate_metadata.outputs.version }}
maintainer: ${{ steps.crate_metadata.outputs.maintainer }}
homepage: ${{ steps.crate_metadata.outputs.homepage }}
msrv: ${{ steps.crate_metadata.outputs.msrv }}
ensure_cargo_fmt:
name: Ensure 'cargo fmt' has been run
runs-on: ubuntu-20.04
steps:
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- uses: actions/checkout@v3
- run: cargo fmt -- --check
min_version: min_version:
name: Minimum supported rust version name: Minimum supported rust version
runs-on: ubuntu-18.04 runs-on: ubuntu-20.04
needs: crate_metadata
steps: steps:
- name: Checkout source code - name: Checkout source code
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }}) - name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
uses: actions-rs/toolchain@v1 uses: dtolnay/rust-toolchain@master
with: with:
toolchain: ${{ env.MIN_SUPPORTED_RUST_VERSION }} toolchain: ${{ needs.crate_metadata.outputs.msrv }}
default: true components: clippy
profile: minimal # minimal component installation (ie, no documentation) - name: Run clippy (on minimum supported rust version to prevent warnings we can't fix)
run: cargo clippy --locked --all-targets ${{ env.MSRV_FEATURES }}
- name: Run tests - name: Run tests
uses: actions-rs/cargo@v1 run: cargo test --locked ${{ env.MSRV_FEATURES }}
with:
command: test
build: build:
name: ${{ matrix.job.os }} (${{ matrix.job.target }}) name: ${{ matrix.job.target }} (${{ matrix.job.os }})
runs-on: ${{ matrix.job.os }} runs-on: ${{ matrix.job.os }}
needs: crate_metadata
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
job: job:
- { os: ubuntu-18.04, target: arm-unknown-linux-gnueabihf , use-cross: true } - { target: aarch64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
- { os: ubuntu-18.04, target: aarch64-unknown-linux-gnu , use-cross: true } - { target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true }
- { os: ubuntu-18.04, target: i686-unknown-linux-gnu , use-cross: true } - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true }
- { os: ubuntu-18.04, target: i686-unknown-linux-musl , use-cross: true } - { target: i686-pc-windows-msvc , os: windows-2019 }
- { os: ubuntu-18.04, target: x86_64-unknown-linux-gnu } - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
- { os: ubuntu-18.04, target: x86_64-unknown-linux-musl , use-cross: true } - { target: i686-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
- { os: macos-10.15 , target: x86_64-apple-darwin } - { target: x86_64-apple-darwin , os: macos-12 }
# - { os: windows-2019, target: i686-pc-windows-gnu } ## disabled; error: linker `i686-w64-mingw32-gcc` not found - { target: x86_64-pc-windows-gnu , os: windows-2019 }
- { os: windows-2019, target: i686-pc-windows-msvc } - { target: x86_64-pc-windows-msvc , os: windows-2019 }
- { os: windows-2019, target: x86_64-pc-windows-gnu } - { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
- { os: windows-2019, target: x86_64-pc-windows-msvc } - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
env:
BUILD_CMD: cargo
steps: steps:
- name: Checkout source code - name: Checkout source code
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Install prerequisites - name: Install prerequisites
shell: bash shell: bash
run: | run: |
case ${{ matrix.job.target }} in case ${{ matrix.job.target }} in
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; arm-unknown-linux-*) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;; aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
esac esac
- name: Extract crate information
shell: bash
run: |
echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
echo "PROJECT_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
echo "PROJECT_MAINTAINER=$(sed -n 's/^authors = \["\(.*\)"\]/\1/p' Cargo.toml)" >> $GITHUB_ENV
echo "PROJECT_HOMEPAGE=$(sed -n 's/^homepage = "\(.*\)"/\1/p' Cargo.toml)" >> $GITHUB_ENV
- name: Install Rust toolchain - name: Install Rust toolchain
uses: actions-rs/toolchain@v1 uses: dtolnay/rust-toolchain@stable
with: with:
toolchain: stable targets: ${{ matrix.job.target }}
target: ${{ matrix.job.target }}
override: true - name: Install cross
profile: minimal # minimal component installation (ie, no documentation) if: matrix.job.use-cross
uses: taiki-e/install-action@v2
with:
tool: cross
- name: Overwrite build command env variable
if: matrix.job.use-cross
shell: bash
run: echo "BUILD_CMD=cross" >> $GITHUB_ENV
- name: Show version information (Rust, cargo, GCC) - name: Show version information (Rust, cargo, GCC)
shell: bash shell: bash
@@ -90,21 +122,16 @@ jobs:
rustc -V rustc -V
- name: Build - name: Build
uses: actions-rs/cargo@v1 shell: bash
with: run: $BUILD_CMD build --locked --release --target=${{ matrix.job.target }}
use-cross: ${{ matrix.job.use-cross }}
command: build
args: --release --target=${{ matrix.job.target }}
- name: Run example - name: Run example
uses: actions-rs/cargo@v1 if: ${{ !matrix.job.use-cross }}
with: shell: bash
use-cross: ${{ matrix.job.use-cross }} run: $BUILD_CMD run --release --target=${{ matrix.job.target }} --example=simple
command: run
args: --release --target=${{ matrix.job.target }} --example=simple
- name: Strip debug information from executable - name: Set binary name & path
id: strip id: bin
shell: bash shell: bash
run: | run: |
# Figure out suffix of binary # Figure out suffix of binary
@@ -113,31 +140,13 @@ jobs:
*-pc-windows-*) EXE_suffix=".exe" ;; *-pc-windows-*) EXE_suffix=".exe" ;;
esac; esac;
# Figure out what strip tool to use if any
STRIP="strip"
case ${{ matrix.job.target }} in
arm-unknown-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;;
aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;;
*-pc-windows-msvc) STRIP="" ;;
esac;
# Setup paths # Setup paths
BIN_DIR="${{ env.CICD_INTERMEDIATES_DIR }}/stripped-release-bin/" BIN_NAME="${{ needs.crate_metadata.outputs.name }}${EXE_suffix}"
mkdir -p "${BIN_DIR}" BIN_PATH="target/${{ matrix.job.target }}/release/${BIN_NAME}"
BIN_NAME="${{ env.PROJECT_NAME }}${EXE_suffix}"
BIN_PATH="${BIN_DIR}/${BIN_NAME}"
# Copy the release build binary to the result location # Let subsequent steps know where to find the binary
cp "target/${{ matrix.job.target }}/release/${BIN_NAME}" "${BIN_DIR}" echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT
# Also strip if possible
if [ -n "${STRIP}" ]; then
"${STRIP}" "${BIN_PATH}"
fi
# Let subsequent steps know where to find the (stripped) bin
echo ::set-output name=BIN_PATH::${BIN_PATH}
echo ::set-output name=BIN_NAME::${BIN_NAME}
- name: Set testing options - name: Set testing options
id: test-options id: test-options
@@ -145,35 +154,41 @@ jobs:
run: | run: |
# test only library unit tests and binary for arm-type targets # test only library unit tests and binary for arm-type targets
unset CARGO_TEST_OPTIONS unset CARGO_TEST_OPTIONS
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${PROJECT_NAME}" ;; esac; unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-* | aarch64-*) CARGO_TEST_OPTIONS="--lib --bin ${{ needs.crate_metadata.outputs.name }}" ;; esac;
echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS} echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT
- name: Run tests - name: Run tests
uses: actions-rs/cargo@v1 shell: bash
with: run: $BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
use-cross: ${{ matrix.job.use-cross }}
command: test - name: Setup Pandoc
args: --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}} uses: r-lib/actions/setup-pandoc@v2
- name: Generate man page
run: pandoc -s -f markdown -t man -o "doc/${{ needs.crate_metadata.outputs.name }}.1" "doc/${{ needs.crate_metadata.outputs.name }}.1.md"
- name: Create tarball - name: Create tarball
id: package id: package
shell: bash shell: bash
run: | run: |
PKG_suffix=".tar.gz" ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac; PKG_suffix=".tar.gz" ; case ${{ matrix.job.target }} in *-pc-windows-*) PKG_suffix=".zip" ;; esac;
PKG_BASENAME=${PROJECT_NAME}-v${PROJECT_VERSION}-${{ matrix.job.target }} PKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-v${{ needs.crate_metadata.outputs.version }}-${{ matrix.job.target }}
PKG_NAME=${PKG_BASENAME}${PKG_suffix} PKG_NAME=${PKG_BASENAME}${PKG_suffix}
echo ::set-output name=PKG_NAME::${PKG_NAME} echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package" PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package"
ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/" ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/"
mkdir -p "${ARCHIVE_DIR}" mkdir -p "${ARCHIVE_DIR}"
# Binary # Binary
cp "${{ steps.strip.outputs.BIN_PATH }}" "$ARCHIVE_DIR" cp "${{ steps.bin.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
# README, LICENSE and CHANGELOG files # README, LICENSE and CHANGELOG files
cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$ARCHIVE_DIR" cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "CHANGELOG.md" "$ARCHIVE_DIR"
# Man page
cp "doc/${{ needs.crate_metadata.outputs.name }}.1" "$ARCHIVE_DIR"
# base compressed package # base compressed package
pushd "${PKG_STAGING}/" >/dev/null pushd "${PKG_STAGING}/" >/dev/null
case ${{ matrix.job.target }} in case ${{ matrix.job.target }} in
@@ -183,7 +198,7 @@ jobs:
popd >/dev/null popd >/dev/null
# Let subsequent steps know where to find the compressed package # Let subsequent steps know where to find the compressed package
echo ::set-output name=PKG_PATH::"${PKG_STAGING}/${PKG_NAME}" echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT
- name: Create Debian package - name: Create Debian package
id: debian-package id: debian-package
@@ -195,10 +210,10 @@ jobs:
DPKG_DIR="${DPKG_STAGING}/dpkg" DPKG_DIR="${DPKG_STAGING}/dpkg"
mkdir -p "${DPKG_DIR}" mkdir -p "${DPKG_DIR}"
DPKG_BASENAME=${PROJECT_NAME} DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}
DPKG_CONFLICTS=${PROJECT_NAME}-musl DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}-musl
case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${PROJECT_NAME}-musl ; DPKG_CONFLICTS=${PROJECT_NAME} ;; esac; case ${{ matrix.job.target }} in *-musl) DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl ; DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }} ;; esac;
DPKG_VERSION=${PROJECT_VERSION} DPKG_VERSION=${{ needs.crate_metadata.outputs.version }}
unset DPKG_ARCH unset DPKG_ARCH
case ${{ matrix.job.target }} in case ${{ matrix.job.target }} in
@@ -210,10 +225,14 @@ jobs:
esac; esac;
DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb" DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb"
echo ::set-output name=DPKG_NAME::${DPKG_NAME} echo "DPKG_NAME=${DPKG_NAME}" >> $GITHUB_OUTPUT
# Binary # Binary
install -Dm755 "${{ steps.strip.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.strip.outputs.BIN_NAME }}" install -Dm755 "${{ steps.bin.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.bin.outputs.BIN_NAME }}"
# Man page
install -Dm644 'doc/${{ needs.crate_metadata.outputs.name }}.1' "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1"
gzip -n --best "${DPKG_DIR}/usr/share/man/man1/${{ needs.crate_metadata.outputs.name }}.1"
# README and LICENSE # README and LICENSE
install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md" install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md"
@@ -224,12 +243,12 @@ jobs:
cat > "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright" <<EOF cat > "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/copyright" <<EOF
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ${{ env.PROJECT_NAME }} Upstream-Name: ${{ needs.crate_metadata.outputs.name }}
Source: ${{ env.PROJECT_HOMEPAGE }} Source: ${{ needs.crate_metadata.outputs.homepage }}
Files: * Files: *
Copyright: ${{ env.PROJECT_MAINTAINER }} Copyright: ${{ needs.crate_metadata.outputs.maintainer }}
Copyright: $COPYRIGHT_YEARS ${{ env.PROJECT_MAINTAINER }} Copyright: $COPYRIGHT_YEARS ${{ needs.crate_metadata.outputs.maintainer }}
License: Apache-2.0 or MIT License: Apache-2.0 or MIT
License: Apache-2.0 License: Apache-2.0
@@ -270,16 +289,16 @@ jobs:
Version: ${DPKG_VERSION} Version: ${DPKG_VERSION}
Section: utils Section: utils
Priority: optional Priority: optional
Maintainer: ${{ env.PROJECT_MAINTAINER }} Maintainer: ${{ needs.crate_metadata.outputs.maintainer }}
Homepage: ${{ env.PROJECT_HOMEPAGE }} Homepage: ${{ needs.crate_metadata.outputs.homepage }}
Architecture: ${DPKG_ARCH} Architecture: ${DPKG_ARCH}
Provides: ${{ env.PROJECT_NAME }} Provides: ${{ needs.crate_metadata.outputs.name }}
Conflicts: ${DPKG_CONFLICTS} Conflicts: ${DPKG_CONFLICTS}
Description: command-line tool to generate, analyze, convert and manipulate colors Description: A command-line benchmarking tool
EOF EOF
DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}" DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}"
echo ::set-output name=DPKG_PATH::${DPKG_PATH} echo "DPKG_PATH=${DPKG_PATH}" >> $GITHUB_OUTPUT
# build dpkg # build dpkg
fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}" fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}"
@@ -302,7 +321,7 @@ jobs:
shell: bash shell: bash
run: | run: |
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/v[0-9].* ]]; then IS_RELEASE='true' ; fi
echo ::set-output name=IS_RELEASE::${IS_RELEASE} echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT
- name: Publish archives and packages - name: Publish archives and packages
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
+3
View File
@@ -1,2 +1,5 @@
/target /target
**/*.rs.bk **/*.rs.bk
# Generated files
hexyl.1
+80 -10
View File
@@ -1,20 +1,82 @@
# unreleased # v0.13.1
## Changes
## Features
## Bugfixes ## Bugfixes
- Correctly handle discontinuous input (stdin), see #196 and #197 (@sharifhsn)
# v0.13.0
## Features
- Support both little and big Endian dumps using `--endianness={little,big}`, see #189 and #104 (@RinHizakura)
## Changes
- **Breaking**: Changed the meaning of the short flag `-C` to be consistent with `hexdump -C`. Previously, this would *hide* the character panel, but now `-C` *shows* the character panel, in case it has been previously (e.g. in an `alias`) disabled with `--no-characters`, see #187 (@sharkdp)
## `hexyl` as a library
- New `endianness` method for `PrinterBuilder`
# v0.12.0
## Features
- Only show one panel by default if the terminal width is not wide enough for two panels, see #182 (@sharkdp)
- Respect the `NO_COLOR` environment variable, see #179 (@sharifhsn)
## Bugfixes
- Do not fail with an error if `--panels=auto` is used and the output is piped, see #184 (@sharkdp)
## Changes
- Breaking: For `xxd`-compatibility reasons, `--group_bytes` has been renamed to `--group-size` (with an `--groupsize` alias), see #121 (@sharkdp)
## `hexyl` as a library
- Breaking: `num_group_bytes` has been renamed to `group_size`.
# v0.11.0
## Features
- Significantly improved performance, see #173 and #176 (@sharifhsn)
- Added variable panels through the `--panels` and `--terminal-width` flags, see [#13](https://github.com/sharkdp/hexyl/issues/13) and [#164](https://github.com/sharkdp/hexyl/pull/164) (@sharifhsn)
- Added new `--group-bytes`/`-g` option, see #104 and #170 (@RinHizakura)
- Added new `--base B` option (where `B` can be `binary`, `octal`, `decimal` or `hexadecimal`), see #147 and #178 (@sharifhsn)
- Show actual zero bytes as `⋄` in the character panel (previously: `0`), in order not to confuse them with ASCII
`0` bytes if colors are deactivated. Closes #166 (@sharkdp)
## `hexyl` as a library
- Breaking change: `Printer::new` is deprecated as a part of the public API. Alternatively, you can now construct a `Printer` using the `PrinterBuilder` builder API, see [#168](https://github.com/sharkdp/hexyl/pull/168). (@sharifhsn)
## Other ## Other
- More tests for the squeezing feature, see #177 (@mkatychev)
## Packaging ## Thank you
Special thanks go to @sharifhsn, not just for the new features,
bugfixes and performance improvements. But also for many internal
improvements of the code base and other maintenance tasks.
# v0.10.0
## Features
- Added new `--plain`, `--no-characters`, and `--no-position` flags, see #154 (@mkatychev)
- Allow hex numbers and units for `--block-size` argument, see #111 and #144 (@merkrafter)
## Other
- Added a man page, see #151 (@sorairolake)
- Mention ability to specify length in hex, see #143 (@merkrafter)
- `--length` and `--bytes` are now marked as conflicting command-line options, see #152 (@sorairolake)
# v0.9.0 # v0.9.0
@@ -43,6 +105,7 @@
- `hexyl` is now available on snapstore, see #116 (@purveshpatel511) - `hexyl` is now available on snapstore, see #116 (@purveshpatel511)
# v0.8.0 # v0.8.0
## Features ## Features
@@ -69,17 +132,19 @@
- `hexyl` is now available on Void Linux, see #91 (@notramo) - `hexyl` is now available on Void Linux, see #91 (@notramo)
# v0.7.0 # v0.7.0
## Bugfixes ## Bugfixes
- hexyl can now be closed with `Ctrl-C` when reading input from STDIN, see #84 - hexyl can now be closed with `Ctrl-C` when reading input from STDIN, see #84
## Changes ## Changes
- Breaking change (library): [`Printer::print_all`](https://docs.rs/hexyl/latest/hexyl/struct.Printer.html#method.print_all) does not take a second argument anymore. - Breaking change (library): [`Printer::print_all`](https://docs.rs/hexyl/latest/hexyl/struct.Printer.html#method.print_all) does not take a second argument anymore.
- Added an example on how to use `hexyl` as a library: https://github.com/sharkdp/hexyl/blob/v0.7.0/examples/simple.rs - Added an example on how to use `hexyl` as a library: https://github.com/sharkdp/hexyl/blob/v0.7.0/examples/simple.rs
# v0.6.0 # v0.6.0
## Features ## Features
@@ -97,6 +162,7 @@
- Performance improvements, see #73 and #66 - Performance improvements, see #73 and #66
# v0.5.1 # v0.5.1
## Bugfixes ## Bugfixes
@@ -105,11 +171,12 @@
- Some colors are printed even if they're disabled, see #64 (@awidegreen) - Some colors are printed even if they're disabled, see #64 (@awidegreen)
- Fixed build failure on OpenBSD 6.5, see #61 - Fixed build failure on OpenBSD 6.5, see #61
# v0.5.0 # v0.5.0
## Features ## Features
- Added support for squeezing where reoccuring lines are squashed together and visualized with an asterisk. A new `-v`/`--no-squeezing` option can be used to disable the feature. For details, see #59 (@awidegreen) - Added support for squeezing where reoccurring lines are squashed together and visualized with an asterisk. A new `-v`/`--no-squeezing` option can be used to disable the feature. For details, see #59 (@awidegreen)
- Added a new `--border` option with support for various styles (Unicode, ASCII, None), see #54 (@dmke) - Added a new `--border` option with support for various styles (Unicode, ASCII, None), see #54 (@dmke)
- The `--length`/`-n` argument can be passed as a hexadecimal number (`hexyl -n 0xff /dev/urandom`), see #45 (@Qyriad) - The `--length`/`-n` argument can be passed as a hexadecimal number (`hexyl -n 0xff /dev/urandom`), see #45 (@Qyriad)
- Added `--bytes`/`-c` as an alias for `--length`/`-n`, see #48 (@selfup) - Added `--bytes`/`-c` as an alias for `--length`/`-n`, see #48 (@selfup)
@@ -136,16 +203,19 @@
- Proper Ctrl-C handling, see #35 - Proper Ctrl-C handling, see #35
- Proper handling of broken pipes (`hexyl … | head`) - Proper handling of broken pipes (`hexyl … | head`)
# v0.3.1 # v0.3.1
- Various (huge) performance improvements, see #23 and #24 (@kballard) - Various (huge) performance improvements, see #23 and #24 (@kballard)
- Replaced 24-bit truecolor ANSI codes by 8-bit codes to support - Replaced 24-bit truecolor ANSI codes by 8-bit codes to support
more terminal emulators, fixes #9 more terminal emulators, fixes #9
# v0.3.0 # v0.3.0
Windows support Windows support
# v0.2.0 # v0.2.0
Initial release Initial release
+1 -1
View File
@@ -8,7 +8,7 @@ Thank you for considering to contribute to `hexyl`!
If your contribution changes the behavior of `hexyl` (as opposed to a typo-fix If your contribution changes the behavior of `hexyl` (as opposed to a typo-fix
in the documentation), please update the [`CHANGELOG.md`](CHANGELOG.md) file in the documentation), please update the [`CHANGELOG.md`](CHANGELOG.md) file
and describe your changes. This makes the release proess much easier and and describe your changes. This makes the release process much easier and
therefore helps to get your changes into a new `hexyl` release faster. therefore helps to get your changes into a new `hexyl` release faster.
The top of the `CHANGELOG` contains a *"unreleased"* section with a few The top of the `CHANGELOG` contains a *"unreleased"* section with a few
Generated
+399 -134
View File
@@ -1,101 +1,182 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]] [[package]]
name = "ansi_term" name = "anstream"
version = "0.11.0" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
dependencies = [ dependencies = [
"winapi", "anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
] ]
[[package]] [[package]]
name = "ansi_term" name = "anstyle"
version = "0.12.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
[[package]]
name = "anstyle-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [ dependencies = [
"winapi", "utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
dependencies = [
"anstyle",
"windows-sys",
] ]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.42" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
[[package]] [[package]]
name = "assert_cmd" name = "assert_cmd"
version = "1.0.7" version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f" checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
dependencies = [ dependencies = [
"anstyle",
"bstr", "bstr",
"doc-comment", "doc-comment",
"predicates", "predicates 3.0.3",
"predicates-core", "predicates-core",
"predicates-tree", "predicates-tree",
"wait-timeout", "wait-timeout",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.16" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
dependencies = [ dependencies = [
"lazy_static",
"memchr", "memchr",
"regex-automata", "regex-automata",
"serde",
] ]
[[package]] [[package]]
name = "clap" name = "cc"
version = "2.33.3" version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "clap"
version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
dependencies = [ dependencies = [
"ansi_term 0.11.0", "clap_builder",
"atty",
"bitflags",
"strsim",
"term_size",
"textwrap",
"unicode-width",
] ]
[[package]]
name = "clap_builder"
version = "4.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"once_cell",
"strsim",
"terminal_size",
]
[[package]]
name = "clap_lex"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "const_format"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]] [[package]]
name = "difflib" name = "difflib"
version = "0.4.0" version = "0.4.0"
@@ -110,68 +191,123 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "either" name = "either"
version = "1.6.1" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "float-cmp" name = "float-cmp"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [ dependencies = [
"num-traits", "num-traits",
] ]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hexyl" name = "hexyl"
version = "0.9.0" version = "0.13.1"
dependencies = [ dependencies = [
"ansi_term 0.12.1",
"anyhow", "anyhow",
"assert_cmd", "assert_cmd",
"atty",
"clap", "clap",
"const_format",
"libc", "libc",
"predicates", "owo-colors",
"predicates 2.1.5",
"pretty_assertions",
"supports-color",
"terminal_size",
"thiserror", "thiserror",
] ]
[[package]] [[package]]
name = "itertools" name = "io-lifetimes"
version = "0.10.1" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi",
"rustix 0.38.4",
"windows-sys",
]
[[package]]
name = "is_ci"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [ dependencies = [
"either", "either",
] ]
[[package]] [[package]]
name = "lazy_static" name = "libc"
version = "1.4.0" version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]] [[package]]
name = "libc" name = "linux-raw-sys"
version = "0.2.98" version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "linux-raw-sys"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "normalize-line-endings" name = "normalize-line-endings"
@@ -181,18 +317,30 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.14" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "predicates" name = "once_cell"
version = "2.0.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6e46ca79eb4e21e2ec14430340c71250ab69332abf85521c95d3a8bc336aa76" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "owo-colors"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "predicates"
version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
dependencies = [ dependencies = [
"difflib", "difflib",
"float-cmp", "float-cmp",
@@ -203,44 +351,78 @@ dependencies = [
] ]
[[package]] [[package]]
name = "predicates-core" name = "predicates"
version = "1.0.2" version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
dependencies = [
"anstyle",
"difflib",
"itertools",
"predicates-core",
]
[[package]]
name = "predicates-core"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
[[package]] [[package]]
name = "predicates-tree" name = "predicates-tree"
version = "1.0.2" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2" checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
dependencies = [ dependencies = [
"predicates-core", "predicates-core",
"treeline", "termtree",
]
[[package]]
name = "pretty_assertions"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
"diff",
"yansi",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.27" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [ dependencies = [
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.9" version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.4" version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@@ -248,68 +430,101 @@ dependencies = [
] ]
[[package]] [[package]]
name = "regex-automata" name = "regex-syntax"
version = "0.1.10" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]] [[package]]
name = "regex-syntax" name = "rustix"
version = "0.6.25" version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys",
]
[[package]]
name = "rustix"
version = "0.38.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
dependencies = [
"bitflags 2.3.3",
"errno",
"libc",
"linux-raw-sys 0.4.3",
"windows-sys",
]
[[package]]
name = "serde"
version = "1.0.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "supports-color"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354"
dependencies = [
"is-terminal",
"is_ci",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.73" version = "2.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
name = "term_size" name = "terminal_size"
version = "0.3.2" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
dependencies = [ dependencies = [
"libc", "rustix 0.37.23",
"winapi", "windows-sys",
] ]
[[package]] [[package]]
name = "textwrap" name = "termtree"
version = "0.11.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
dependencies = [
"term_size",
"unicode-width",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.26" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.26" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -317,22 +532,22 @@ dependencies = [
] ]
[[package]] [[package]]
name = "treeline" name = "unicode-ident"
version = "0.1.0" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "wait-timeout" name = "wait-timeout"
@@ -344,23 +559,73 @@ dependencies = [
] ]
[[package]] [[package]]
name = "winapi" name = "windows-sys"
version = "0.3.9" version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [ dependencies = [
"winapi-i686-pc-windows-gnu", "windows-targets",
"winapi-x86_64-pc-windows-gnu",
] ]
[[package]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "windows-targets"
version = "0.4.0" version = "0.48.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "windows_aarch64_gnullvm"
version = "0.4.0" version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+13 -9
View File
@@ -7,24 +7,28 @@ license = "MIT/Apache-2.0"
name = "hexyl" name = "hexyl"
readme = "README.md" readme = "README.md"
repository = "https://github.com/sharkdp/hexyl" repository = "https://github.com/sharkdp/hexyl"
version = "0.9.0" version = "0.13.1"
edition = "2018" edition = "2021"
rust-version = "1.66"
[dependencies] [dependencies]
ansi_term = "0.12" anyhow = "1.0"
anyhow = "1.0.31" const_format = "0.2"
atty = "0.2"
libc = "0.2" libc = "0.2"
thiserror = "1.0.19" owo-colors = "3"
supports-color = "2"
thiserror = "1.0"
terminal_size = "0.2"
[dependencies.clap] [dependencies.clap]
version = "2" version = "4"
default-features = false default-features = false
features = ["suggestions", "color", "wrap_help"] features = ["std", "suggestions", "color", "wrap_help", "cargo", "help", "usage", "error-context"]
[dev-dependencies] [dev-dependencies]
assert_cmd = "1.0" assert_cmd = "2.0"
predicates = "2.0" predicates = "2.0"
pretty_assertions = "1.3.0"
[profile.release] [profile.release]
lto = true lto = true
+53 -10
View File
@@ -17,13 +17,27 @@ of bytes (NULL bytes, printable ASCII characters, ASCII whitespace characters, o
![](https://i.imgur.com/f8nm8g6.png) ![](https://i.imgur.com/f8nm8g6.png)
## Color Reference
|Type of Byte|Color|ANSI Code |
|---|---|---|
|NULL|![#555753](https://placehold.co/10x10/555753/555753.png) Bright Black|90|
|OFFSET|![#555753](https://placehold.co/10x10/555753/555753.png) Bright Black|90|
|ASCII Printable|![#06989a](https://placehold.co/10x10/06989a/06989a.png) Cyan|36|
|ASCII Whitespace|![#4e9a06](https://placehold.co/10x10/4e9a06/4e9a06.png) Green|32|
|ASCII Other|![#4e9a06](https://placehold.co/10x10/4e9a06/4e9a06.png) Green|32|
|Non-ASCII|![#c4a000](https://placehold.co/10x10/c4a000/c4a000.png) Yellow|33|
*Colors taken from the Ubuntu terminal color scheme, they could look different in your terminal*
## Installation ## Installation
### On Ubuntu ### On Ubuntu
*... and other Debian-based Linux distributions.* *... and other Debian-based Linux distributions.*
If you run Ubuntu 19.10 (Eoan Ermine) or newer, you can install the [officially maintained package](https://packages.ubuntu.com/eoan/hexyl): If you run Ubuntu 19.10 (Eoan Ermine) or newer, you can install the [officially maintained package](https://packages.ubuntu.com/search?keywords=hexyl):
```bash ```bash
sudo apt install hexyl sudo apt install hexyl
``` ```
@@ -31,12 +45,12 @@ If you use an older version of Ubuntu, you can download
the latest `.deb` package from the release page and install it via: the latest `.deb` package from the release page and install it via:
``` bash ``` bash
sudo dpkg -i hexyl_0.9.0_amd64.deb # adapt version number and architecture sudo dpkg -i hexyl_0.13.1_amd64.deb # adapt version number and architecture
``` ```
### On Debian ### On Debian
If you run Debian Buster or newer, you can install the [officially maintained Debian package](https://packages.debian.org/buster/hexyl): If you run Debian Buster or newer, you can install the [officially maintained Debian package](https://packages.debian.org/search?searchon=names&keywords=hexyl):
```bash ```bash
sudo apt-get install hexyl sudo apt-get install hexyl
``` ```
@@ -44,6 +58,14 @@ sudo apt-get install hexyl
If you run an older version of Debian, see above for instructions on how to If you run an older version of Debian, see above for instructions on how to
manually install `hexyl`. manually install `hexyl`.
### On Fedora
If you run Fedora 35 or newer, you can install the [officially maintained Fedora package](https://packages.fedoraproject.org/pkgs/rust-hexyl/hexyl):
```bash
sudo dnf install hexyl
```
### On Arch Linux ### On Arch Linux
You can install `hexyl` from [the official package repository](https://www.archlinux.org/packages/community/x86_64/hexyl/): You can install `hexyl` from [the official package repository](https://www.archlinux.org/packages/community/x86_64/hexyl/):
@@ -53,6 +75,7 @@ pacman -S hexyl
``` ```
### On Void Linux ### On Void Linux
``` ```
xbps-install hexyl xbps-install hexyl
``` ```
@@ -91,7 +114,7 @@ pkg install hexyl
``` ```
pkg install hexyl pkg install hexyl
``` ```
or or
``` ```
apt install hexyl apt install hexyl
``` ```
@@ -116,30 +139,50 @@ Check out the [release page](https://github.com/sharkdp/hexyl/releases) for bina
### On Windows ### On Windows
For now, you will have to install from source via `cargo` (see below). Make sure that you Check out the [release page](https://github.com/sharkdp/hexyl/releases) for binary builds.
use a terminal that supports ANSI escape sequences (like ConHost v2 since Windows 10 1703 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). or Windows Terminal since Windows 10 1903).
### Via cargo ### Via cargo
If you have Rust 1.40 or higher, you can install `hexyl` from source via `cargo`: If you have Rust 1.56 or higher, you can install `hexyl` from source via `cargo`:
``` ```
cargo install hexyl cargo install hexyl
``` ```
Alternatively, you can install `hexyl` directly from the repository by using:
```
git clone https://github.com/sharkdp/hexyl
cargo install --path ./hexyl
```
Note: To convert the man page, you will need [Pandoc](https://pandoc.org/).
You can convert from Markdown by using (in the project root):
```
pandoc -s -f markdown -t man -o ./doc/hexyl.1 ./doc/hexyl.1.md
```
### Via snap package ### Via snap package
``` ```
sudo snap install hexyl sudo snap install hexyl
``` ```
[Get it from the Snap Store](https://snapcraft.io/hexyl) [Get it from the Snap Store](https://snapcraft.io/hexyl)
### Via [Scoop](https://scoop.sh)
```
scoop install hexyl
```
## License ## License
Licensed under either of Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
at your option. at your option.
-1
View File
@@ -1 +0,0 @@
*.bash linguist-vendored
-103
View File
@@ -1,103 +0,0 @@
#!/usr/bin/env bash
# Building and packaging for release
set -ex
build() {
cargo build --target "$TARGET" --release --verbose
}
pack() {
local tempdir
local out_dir
local package_name
tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp)
out_dir=$(pwd)
package_name="$PROJECT_NAME-$TRAVIS_TAG-$TARGET"
# create a "staging" directory
mkdir "$tempdir/$package_name"
# copying the main binary
cp "target/$TARGET/release/$PROJECT_NAME" "$tempdir/$package_name/"
strip "$tempdir/$package_name/$PROJECT_NAME"
# readme and license
cp README.md "$tempdir/$package_name"
cp LICENSE-MIT "$tempdir/$package_name"
cp LICENSE-APACHE "$tempdir/$package_name"
# archiving
pushd "$tempdir"
tar czf "$out_dir/$package_name.tar.gz" "$package_name"/*
popd
rm -r "$tempdir"
}
make_deb() {
local tempdir
local architecture
local version
local dpkgname
local conflictname
case $TARGET in
x86_64*)
architecture=amd64
;;
i686*)
architecture=i386
;;
*)
echo "ERROR: unknown target" >&2
return 1
;;
esac
version=${TRAVIS_TAG#v}
if [[ $TARGET = *musl* ]]; then
dpkgname=$PROJECT_NAME-musl
conflictname=$PROJECT_NAME
else
dpkgname=$PROJECT_NAME
conflictname=$PROJECT_NAME-musl
fi
tempdir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp)
# copy the main binary
install -Dm755 "target/$TARGET/release/$PROJECT_NAME" "$tempdir/usr/bin/$PROJECT_NAME"
strip "$tempdir/usr/bin/$PROJECT_NAME"
# readme and license
install -Dm644 README.md "$tempdir/usr/share/doc/$PROJECT_NAME/README.md"
install -Dm644 LICENSE-MIT "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-MIT"
install -Dm644 LICENSE-APACHE "$tempdir/usr/share/doc/$PROJECT_NAME/LICENSE-APACHE"
# Control file
mkdir "$tempdir/DEBIAN"
cat > "$tempdir/DEBIAN/control" <<EOF
Package: $dpkgname
Version: $version
Section: utils
Priority: optional
Maintainer: David Peter <mail@david-peter.de>
Architecture: $architecture
Provides: $PROJECT_NAME
Conflicts: $conflictname
Description: A command-line hex viewer.
EOF
fakeroot dpkg-deb --build "$tempdir" "${dpkgname}_${version}_${architecture}.deb"
}
main() {
build
pack
if [[ $TARGET = *linux* ]]; then
make_deb
fi
}
main
+148
View File
@@ -0,0 +1,148 @@
% HEXYL(1) hexyl 0.12.0 | General Commands Manual
%
% 2022-12-05
<!--
This man page is written in Pandoc's Markdown.
See: https://pandoc.org/MANUAL.html#pandocs-markdown
-->
# NAME
hexyl - a command-line hex viewer
# SYNOPSIS
**hexyl** [_OPTIONS_] [_FILE_]
# DESCRIPTION
**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).
# POSITIONAL ARGUMENTS
_FILE_
: The file to display.
If no _FILE_ argument is given, read from STDIN.
# OPTIONS
**-n**, **\--length** _N_
: Only read _N_ bytes from the input.
The _N_ argument can also include a unit with a decimal prefix (kB, MB, ..)
or binary prefix (kiB, MiB, ..), or can be specified using a hex number.
Examples:
:
Read the first 64 bytes:
: $ **hexyl \--length=64**
Read the first 4 kibibytes:
: $ **hexyl \--length=4KiB**
Read the first 255 bytes (specified using a hex number):
: $ **hexyl \--length=0xff**
**-c**, **\--bytes** _N_
: An alias for **-n**/**\--length**.
**-l** _N_
: Yet another alias for **-n**/**\--length**.
**-s**, **\--skip** _N_
: Skip the first _N_ bytes of the input.
The _N_ argument can also include a unit (see **\--length** for details).
A negative value is valid and will seek from the end of the file.
**\--block-size** _SIZE_
: Sets the size of the block unit to _SIZE_ (default is 512).
Examples:
:
Sets the block size to 1024 bytes:
: $ **hexyl \--block-size=1024 \--length=5block**
Sets the block size to 4 kilobytes:
: $ **hexyl \--block-size=4kB \--length=2block**
**-v**, **\--no-squeezing**
: Displays all input data.
Otherwise any number of groups of output lines which would be identical to
the preceding group of lines, are replaced with a line comprised of a
single asterisk.
**\--color** _WHEN_
: When to use colors.
The auto-mode only displays colors if the output goes to an interactive
terminal.
Possible values:
: - **always** (default)
- **auto**
- **never**
**\--border** _STYLE_
: Whether to draw a border with Unicode characters, ASCII characters, or none
at all.
Possible values:
: - **unicode** (default)
- **ascii**
- **none**
**-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.
**-h**, **\--help**
: Prints help information.
**-V**, **\--version**
: Prints version information.
# NOTES
Source repository:
: <https://github.com/sharkdp/hexyl>
# EXAMPLES
Print a given file:
: $ **hexyl small.png**
Print and view a given file in the terminal pager:
: $ **hexyl big.png | less -r**
Print the first 256 bytes of a given special file:
: $ **hexyl -n 256 /dev/urandom**
# AUTHORS
**hexyl** was written by David Peter <mail@david-peter.de>.
# REPORTING BUGS
Bugs can be reported on GitHub at:
: <https://github.com/sharkdp/hexyl/issues>
# COPYRIGHT
**hexyl** is dual-licensed under:
: - Apache License 2.0 (<https://www.apache.org/licenses/LICENSE-2.0>)
- MIT License (<https://opensource.org/licenses/MIT>)
# SEE ALSO
**hexdump**(1), **xxd**(1)
+10 -6
View File
@@ -1,6 +1,6 @@
use std::io; use std::io;
use hexyl::{BorderStyle, Printer}; use hexyl::{BorderStyle, PrinterBuilder};
fn main() { fn main() {
let input = vec![ let input = vec![
@@ -11,10 +11,14 @@ fn main() {
let stdout = io::stdout(); let stdout = io::stdout();
let mut handle = stdout.lock(); let mut handle = stdout.lock();
let show_color = true; let mut printer = PrinterBuilder::new(&mut handle)
let use_squeezing = false; .show_color(true)
let border_style = BorderStyle::Unicode; .show_char_panel(true)
.show_position_panel(true)
let mut printer = Printer::new(&mut handle, show_color, border_style, use_squeezing); .with_border_style(BorderStyle::Unicode)
.enable_squeezing(false)
.num_panels(2)
.group_size(1)
.build();
printer.print_all(&input[..]).unwrap(); printer.print_all(&input[..]).unwrap();
} }
+525 -163
View File
@@ -3,66 +3,71 @@ extern crate clap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io::{self, prelude::*, SeekFrom}; use std::io::{self, prelude::*, BufWriter, SeekFrom};
use std::num::{NonZeroI64, NonZeroU64, NonZeroU8};
use clap::{App, AppSettings, Arg}; use clap::builder::ArgPredicate;
use clap::{crate_name, crate_version, Arg, ArgAction, ColorChoice, Command};
use atty::Stream; use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Context, Error as AnyhowError}; use const_format::formatcp;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use hexyl::{BorderStyle, Input, Printer}; use terminal_size::terminal_size;
fn run() -> Result<(), AnyhowError> { use hexyl::{Base, BorderStyle, Endianness, Input, PrinterBuilder};
let app = App::new(crate_name!())
.setting(AppSettings::ColorAuto) const DEFAULT_BLOCK_SIZE: i64 = 512;
.setting(AppSettings::ColoredHelp)
.setting(AppSettings::DeriveDisplayOrder) fn run() -> Result<()> {
.setting(AppSettings::UnifiedHelpMessage) let command = Command::new(crate_name!())
.color(ColorChoice::Auto)
.max_term_width(90) .max_term_width(90)
.version(crate_version!()) .version(crate_version!())
.about(crate_description!()) .about(crate_description!())
.arg( .arg(
Arg::with_name("FILE") Arg::new("FILE")
.help("The file to display. If no FILE argument is given, read from STDIN."), .help("The file to display. If no FILE argument is given, read from STDIN."),
) )
.arg( .arg(
Arg::with_name("length") Arg::new("length")
.short("n") .short('n')
.long("length") .long("length")
.takes_value(true) .num_args(1)
.value_name("N") .value_name("N")
.help( .help(
"Only read N bytes from the input. The N argument can also include a \ "Only read N bytes from the input. The N argument can also include a \
unit with a decimal prefix (kB, MB, ..) or binary prefix (kiB, MiB, ..). \ unit with a decimal prefix (kB, MB, ..) or binary prefix (kiB, MiB, ..), \
or can be specified using a hex number. \
The short option '-l' can be used as an alias.\n\ The short option '-l' can be used as an alias.\n\
Examples: --length=64, --length=4KiB", Examples: --length=64, --length=4KiB, --length=0xff",
), ),
) )
.arg( .arg(
Arg::with_name("bytes") Arg::new("bytes")
.short("c") .short('c')
.long("bytes") .long("bytes")
.takes_value(true) .num_args(1)
.value_name("N") .value_name("N")
.conflicts_with("length") .conflicts_with("length")
.help("An alias for -n/--length"), .help("An alias for -n/--length"),
) )
.arg( .arg(
Arg::with_name("count") Arg::new("count")
.short("l") .short('l')
.takes_value(true) .num_args(1)
.value_name("N") .value_name("N")
.hidden(true) .conflicts_with_all(["length", "bytes"])
.hide(true)
.help("Yet another alias for -n/--length"), .help("Yet another alias for -n/--length"),
) )
.arg( .arg(
Arg::with_name("skip") Arg::new("skip")
.short("s") .short('s')
.long("skip") .long("skip")
.takes_value(true) .num_args(1)
.value_name("N") .value_name("N")
.help( .help(
"Skip the first N bytes of the input. The N argument can also include \ "Skip the first N bytes of the input. The N argument can also include \
@@ -71,19 +76,21 @@ fn run() -> Result<(), AnyhowError> {
), ),
) )
.arg( .arg(
Arg::with_name("block_size") Arg::new("block_size")
.long("block-size") .long("block-size")
.takes_value(true) .num_args(1)
.value_name("SIZE") .value_name("SIZE")
.help( .help(formatcp!(
"Sets the size of the `block` unit to SIZE.\n\ "Sets the size of the `block` unit to SIZE (default is {}).\n\
Examples: --block-size=1024, --block-size=4kB", Examples: --block-size=1024, --block-size=4kB",
), DEFAULT_BLOCK_SIZE
)),
) )
.arg( .arg(
Arg::with_name("nosqueezing") Arg::new("nosqueezing")
.short("v") .short('v')
.long("no-squeezing") .long("no-squeezing")
.action(ArgAction::SetFalse)
.help( .help(
"Displays all input data. Otherwise any number of groups of output \ "Displays all input data. Otherwise any number of groups of output \
lines which would be identical to the preceding group of lines, are \ lines which would be identical to the preceding group of lines, are \
@@ -91,11 +98,12 @@ fn run() -> Result<(), AnyhowError> {
), ),
) )
.arg( .arg(
Arg::with_name("color") Arg::new("color")
.long("color") .long("color")
.takes_value(true) .num_args(1)
.value_name("WHEN") .value_name("WHEN")
.possible_values(&["always", "auto", "never"]) .value_parser(["always", "auto", "never"])
.default_value_if("plain", ArgPredicate::IsPresent, Some("never"))
.default_value("always") .default_value("always")
.help( .help(
"When to use colors. The auto-mode only displays colors if the output \ "When to use colors. The auto-mode only displays colors if the output \
@@ -103,22 +111,47 @@ fn run() -> Result<(), AnyhowError> {
), ),
) )
.arg( .arg(
Arg::with_name("border") Arg::new("border")
.long("border") .long("border")
.takes_value(true) .num_args(1)
.value_name("STYLE") .value_name("STYLE")
.possible_values(&["unicode", "ascii", "none"]) .value_parser(["unicode", "ascii", "none"])
.default_value_if("plain", ArgPredicate::IsPresent, Some("none"))
.default_value("unicode") .default_value("unicode")
.help( .help(
"Whether to draw a border with Unicode characters, ASCII characters, \ "Whether to draw a border with Unicode characters, ASCII characters, \
or none at all", or none at all",
), ),
) )
.arg(Arg::new("plain").short('p').long("plain").action(ArgAction::SetTrue).help(
"Display output with --no-characters, --no-position, --border=none, and --color=never.",
))
.arg( .arg(
Arg::with_name("display_offset") Arg::new("no_chars")
.short("o") .long("no-characters")
.action(ArgAction::SetFalse)
.help("Do not show the character panel on the right."),
)
.arg(
Arg::new("chars")
.short('C')
.long("characters")
.overrides_with("no_chars")
.action(ArgAction::SetTrue)
.help("Show the character panel on the right. This is the default, unless --no-characters has been specified."),
)
.arg(
Arg::new("no_position")
.short('P')
.long("no-position")
.action(ArgAction::SetFalse)
.help("Whether to display the position panel on the left."),
)
.arg(
Arg::new("display_offset")
.short('o')
.long("display-offset") .long("display-offset")
.takes_value(true) .num_args(1)
.value_name("N") .value_name("N")
.help( .help(
"Add N bytes to the displayed file position. The N argument can also \ "Add N bytes to the displayed file position. The N argument can also \
@@ -126,29 +159,119 @@ fn run() -> Result<(), AnyhowError> {
A negative value is valid and calculates an offset relative to the \ A negative value is valid and calculates an offset relative to the \
end of the file.", end of the file.",
), ),
)
.arg(
Arg::new("panels")
.long("panels")
.num_args(1)
.value_name("N")
.help(
"Sets the number of hex data panels to be displayed. \
`--panels=auto` will display the maximum number of hex data panels \
based on the current terminal width. By default, hexyl will show \
two panels, unless the terminal is not wide enough for that.",
),
)
.arg(
Arg::new("group_size")
.short('g')
.long("group-size")
.alias("groupsize")
.num_args(1)
.value_name("N")
.help(
"Number of bytes/octets that should be grouped together. \
Possible group sizes are 1, 2, 4, 8. The default is 1. You \
can use the '--endianness' option to control the ordering of \
the bytes within a group. '--groupsize' can be used as an \
alias (xxd-compatibility).",
),
)
.arg(
Arg::new("endianness")
.long("endianness")
.num_args(1)
.value_name("FORMAT")
.value_parser(["big", "little"])
.default_value("big")
.help(
"Whether to print out groups in little-endian or big-endian \
format. This option only has an effect if the '--group-size' \
is larger than 1. '-e' can be used as an alias for \
'--endianness=little'.",
),
)
.arg(
Arg::new("little_endian_format")
.short('e')
.action(ArgAction::SetTrue)
.overrides_with("endianness")
.hide(true)
.help("An alias for '--endianness=little'."),
)
.arg(
Arg::new("base")
.short('b')
.long("base")
.num_args(1)
.value_name("B")
.help(
"Sets the base used for the bytes. The possible options are \
binary, octal, decimal, and hexadecimal. The default base \
is hexadecimal."
)
)
.arg(
Arg::new("terminal_width")
.long("terminal-width")
.num_args(1)
.value_name("N")
.conflicts_with("panels")
.help(
"Sets the number of terminal columns to be displayed.\nSince the terminal \
width may not be an evenly divisible by the width per hex data column, this \
will use the greatest number of hex data panels that can fit in the requested \
width but still leave some space to the right.\nCannot be used with other \
width-setting options.",
),
); );
let matches = app.get_matches_safe()?; let matches = command.get_matches();
let stdin = io::stdin(); let stdin = io::stdin();
let mut reader = match matches.value_of("FILE") { let mut reader = match matches.get_one::<String>("FILE") {
Some(filename) => Input::File(File::open(filename)?), Some(filename) => Input::File(File::open(filename)?),
None => Input::Stdin(stdin.lock()), None => Input::Stdin(stdin.lock()),
}; };
let block_size = matches let block_size = matches
.value_of("block_size") .get_one::<String>("block_size")
.map(|bs| { .map(|bs| {
bs.parse::<i64>().map_err(|e| anyhow!(e)).and_then(|x| { if let Some(hex_number) = try_parse_as_hex_number(bs) {
PositiveI64::new(x).ok_or_else(|| anyhow!("block size argument must be positive")) return hex_number.map_err(|e| anyhow!(e)).and_then(|x| {
}) PositiveI64::new(x)
.ok_or_else(|| anyhow!("block size argument must be positive"))
});
}
let (num, unit) = extract_num_and_unit_from(bs)?;
if let Unit::Block { custom_size: _ } = unit {
return Err(anyhow!(
"can not use 'block(s)' as a unit to specify block size"
));
};
num.checked_mul(unit.get_multiplier())
.ok_or_else(|| anyhow!(ByteOffsetParseError::UnitMultiplicationOverflow))
.and_then(|x| {
PositiveI64::new(x)
.ok_or_else(|| anyhow!("block size argument must be positive"))
})
}) })
.transpose()? .transpose()?
.unwrap_or_else(|| PositiveI64::new(512).unwrap()); .unwrap_or_else(|| PositiveI64::new(DEFAULT_BLOCK_SIZE).unwrap());
let skip_arg = matches let skip_arg = matches
.value_of("skip") .get_one::<String>("skip")
.map(|s| { .map(|s| {
parse_byte_offset(s, block_size).context(anyhow!( parse_byte_offset(s, block_size).context(anyhow!(
"failed to parse `--skip` arg {:?} as byte count", "failed to parse `--skip` arg {:?} as byte count",
@@ -177,16 +300,16 @@ fn run() -> Result<(), AnyhowError> {
0 0
}; };
let parse_byte_count = |s| -> Result<u64, AnyhowError> { let parse_byte_count = |s| -> Result<u64> {
Ok(parse_byte_offset(s, block_size)? Ok(parse_byte_offset(s, block_size)?
.assume_forward_offset_from_start()? .assume_forward_offset_from_start()?
.into()) .into())
}; };
let mut reader = if let Some(length) = matches let mut reader = if let Some(length) = matches
.value_of("length") .get_one::<String>("length")
.or_else(|| matches.value_of("bytes")) .or_else(|| matches.get_one::<String>("bytes"))
.or_else(|| matches.value_of("count")) .or_else(|| matches.get_one::<String>("count"))
.map(|s| { .map(|s| {
parse_byte_count(s).context(anyhow!( parse_byte_count(s).context(anyhow!(
"failed to parse `--length` arg {:?} as byte count", "failed to parse `--length` arg {:?} as byte count",
@@ -200,22 +323,30 @@ fn run() -> Result<(), AnyhowError> {
reader.into_inner() reader.into_inner()
}; };
let show_color = match matches.value_of("color") { let show_color = match matches.get_one::<String>("color").map(String::as_ref) {
Some("never") => false, Some("never") => false,
Some("auto") => atty::is(Stream::Stdout), Some("always") => true,
_ => true, _ => supports_color::on(supports_color::Stream::Stdout)
.map(|level| level.has_basic)
.unwrap_or(false),
}; };
let border_style = match matches.value_of("border") { let border_style = match matches.get_one::<String>("border").map(String::as_ref) {
Some("unicode") => BorderStyle::Unicode, Some("unicode") => BorderStyle::Unicode,
Some("ascii") => BorderStyle::Ascii, Some("ascii") => BorderStyle::Ascii,
_ => BorderStyle::None, _ => BorderStyle::None,
}; };
let squeeze = !matches.is_present("nosqueezing"); let &squeeze = matches.get_one::<bool>("nosqueezing").unwrap_or(&true);
let show_char_panel = *matches.get_one::<bool>("no_chars").unwrap_or(&true)
&& !matches.get_one::<bool>("plain").unwrap_or(&false);
let show_position_panel = *matches.get_one::<bool>("no_position").unwrap_or(&true)
&& !matches.get_one::<bool>("plain").unwrap_or(&false);
let display_offset: u64 = matches let display_offset: u64 = matches
.value_of("display_offset") .get_one::<String>("display_offset")
.map(|s| { .map(|s| {
parse_byte_count(s).context(anyhow!( parse_byte_count(s).context(anyhow!(
"failed to parse `--display-offset` arg {:?} as byte count", "failed to parse `--display-offset` arg {:?} as byte count",
@@ -223,13 +354,132 @@ fn run() -> Result<(), AnyhowError> {
)) ))
}) })
.transpose()? .transpose()?
.unwrap_or(0) .unwrap_or(0);
.into();
let max_panels_fn = |terminal_width: u64, base_digits: u64, group_size: u64| {
let offset = if show_position_panel { 10 } else { 1 };
let col_width = if show_char_panel {
((8 / group_size) * (base_digits * group_size + 1)) + 2 + 8
} else {
((8 / group_size) * (base_digits * group_size + 1)) + 2
};
if (terminal_width - offset) / col_width < 1 {
1
} else {
(terminal_width - offset) / col_width
}
};
let base = if let Some(base) = matches.get_one::<String>("base")
.map(|s| {
if let Ok(base_num) = s.parse::<u8>() {
match base_num {
2 => Ok(Base::Binary),
8 => Ok(Base::Octal),
10 => Ok(Base::Decimal),
16 => Ok(Base::Hexadecimal),
_ => Err(anyhow!("The number provided is not a valid base. Valid bases are 2, 8, 10, and 16.")),
}
} else {
match s.as_str() {
"b" | "bin" | "binary" => Ok(Base::Binary),
"o" | "oct" | "octal" => Ok(Base::Octal),
"d" | "dec" | "decimal" => Ok(Base::Decimal),
"x" | "hex" | "hexadecimal" => Ok(Base::Hexadecimal),
_ => Err(anyhow!("The base provided is not valid. Valid bases are \"b\", \"o\", \"d\", and \"x\"."))
}
}
}).transpose()? {
base
} else {
Base::Hexadecimal
};
let base_digits = match base {
Base::Binary => 8,
Base::Octal => 3,
Base::Decimal => 3,
Base::Hexadecimal => 2,
};
let group_size = if let Some(group_size) = matches
.get_one::<String>("group_size")
.map(|s| {
s.parse::<NonZeroU8>().map(u8::from).context(anyhow!(
"Failed to parse `--group-size`/`-g` argument {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
if (group_size <= 8) && ((group_size & (group_size - 1)) == 0) {
group_size
} else {
return Err(anyhow!(
"Possible sizes for the `--group-size`/`-g` option are 1, 2, 4 or 8. "
));
}
} else {
1
};
let terminal_width = terminal_size().map(|s| s.0 .0 as u64).unwrap_or(80);
let panels = if matches.get_one::<String>("panels").map(String::as_ref) == Some("auto") {
max_panels_fn(terminal_width, base_digits, group_size.into())
} else if let Some(panels) = matches
.get_one::<String>("panels")
.map(|s| {
s.parse::<NonZeroU64>().map(u64::from).context(anyhow!(
"failed to parse `--panels` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
panels
} else if let Some(terminal_width) = matches
.get_one::<String>("terminal_width")
.map(|s| {
s.parse::<NonZeroU64>().map(u64::from).context(anyhow!(
"failed to parse `--terminal-width` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
max_panels_fn(terminal_width, base_digits, group_size.into())
} else {
std::cmp::min(
2,
max_panels_fn(terminal_width, base_digits, group_size.into()),
)
};
let little_endian_format = *matches.get_one::<bool>("little_endian_format").unwrap();
let endianness = matches.get_one::<String>("endianness");
let endianness = match (
endianness.map(|s| s.as_ref()).unwrap(),
little_endian_format,
) {
(_, true) | ("little", _) => Endianness::Little,
("big", _) => Endianness::Big,
_ => unreachable!(),
};
let stdout = io::stdout(); let stdout = io::stdout();
let mut stdout_lock = stdout.lock(); let mut stdout_lock = BufWriter::new(stdout.lock());
let mut printer = Printer::new(&mut stdout_lock, show_color, border_style, squeeze); let mut printer = PrinterBuilder::new(&mut stdout_lock)
.show_color(show_color)
.show_char_panel(show_char_panel)
.show_position_panel(show_position_panel)
.with_border_style(border_style)
.enable_squeezing(squeeze)
.num_panels(panels)
.group_size(group_size)
.with_base(base)
.endianness(endianness)
.build();
printer.display_offset(skip_offset + display_offset); printer.display_offset(skip_offset + display_offset);
printer.print_all(&mut reader).map_err(|e| anyhow!(e))?; printer.print_all(&mut reader).map_err(|e| anyhow!(e))?;
@@ -237,31 +487,15 @@ fn run() -> Result<(), AnyhowError> {
} }
fn main() { fn main() {
// Enable ANSI support for Windows
#[cfg(windows)]
let _ = ansi_term::enable_ansi_support();
let result = run(); let result = run();
if let Err(err) = result { if let Err(err) = result {
if let Some(clap_err) = err.downcast_ref::<clap::Error>() { if let Some(io_error) = err.downcast_ref::<io::Error>() {
match clap_err.kind { if io_error.kind() == ::std::io::ErrorKind::BrokenPipe {
// The exit code should not indicate an error for --help / --version std::process::exit(0);
clap::ErrorKind::HelpDisplayed => {
eprint!("{}", clap_err); // Clap errors already have newlines
std::process::exit(0)
}
clap::ErrorKind::VersionDisplayed => {
// Version output in clap 2.33.1 (dep as of now) doesn't have a newline
// and the fix is not included even in the latest stable release
println!("");
std::process::exit(0)
}
_ => (),
} }
} else {
eprintln!("Error: {:?}", err);
} }
eprintln!("Error: {err:?}");
std::process::exit(1); std::process::exit(1);
} }
} }
@@ -283,9 +517,9 @@ impl NonNegativeI64 {
} }
} }
impl Into<u64> for NonNegativeI64 { impl From<NonNegativeI64> for u64 {
fn into(self) -> u64 { fn from(x: NonNegativeI64) -> u64 {
u64::try_from(self.0) u64::try_from(x.0)
.expect("invariant broken: NonNegativeI64 should contain a non-negative i64 value") .expect("invariant broken: NonNegativeI64 should contain a non-negative i64 value")
} }
} }
@@ -307,13 +541,50 @@ impl PositiveI64 {
} }
} }
impl Into<u64> for PositiveI64 { impl From<PositiveI64> for u64 {
fn into(self) -> u64 { fn from(x: PositiveI64) -> u64 {
u64::try_from(self.0) u64::try_from(x.0)
.expect("invariant broken: PositiveI64 should contain a positive i64 value") .expect("invariant broken: PositiveI64 should contain a positive i64 value")
} }
} }
#[derive(Debug, PartialEq)]
enum Unit {
Byte,
Kilobyte,
Megabyte,
Gigabyte,
Terabyte,
Kibibyte,
Mebibyte,
Gibibyte,
Tebibyte,
/// a customizable amount of bytes
Block {
custom_size: Option<NonZeroI64>,
},
}
impl Unit {
const fn get_multiplier(self) -> i64 {
match self {
Self::Byte => 1,
Self::Kilobyte => 1000,
Self::Megabyte => 1_000_000,
Self::Gigabyte => 1_000_000_000,
Self::Terabyte => 1_000_000_000_000,
Self::Kibibyte => 1 << 10,
Self::Mebibyte => 1 << 20,
Self::Gibibyte => 1 << 30,
Self::Tebibyte => 1 << 40,
Self::Block {
custom_size: Some(size),
} => size.get(),
Self::Block { custom_size: None } => DEFAULT_BLOCK_SIZE,
}
}
}
const HEX_PREFIX: &str = "0x"; const HEX_PREFIX: &str = "0x";
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
@@ -368,33 +639,14 @@ enum ByteOffsetParseError {
InvalidUnit(String), InvalidUnit(String),
#[error("failed to parse integer part")] #[error("failed to parse integer part")]
ParseNum(#[source] std::num::ParseIntError), ParseNum(#[source] std::num::ParseIntError),
#[error("count multipled by the unit overflowed a signed 64-bit integer; are you sure it should be that big?")] #[error("count multiplied by the unit overflowed a signed 64-bit integer; are you sure it should be that big?")]
UnitMultiplicationOverflow, UnitMultiplicationOverflow,
} }
fn parse_byte_offset(n: &str, block_size: PositiveI64) -> Result<ByteOffset, ByteOffsetParseError> { fn parse_byte_offset(n: &str, block_size: PositiveI64) -> Result<ByteOffset, ByteOffsetParseError> {
use ByteOffsetParseError::*; use ByteOffsetParseError::*;
let (n, kind) = { let (n, kind) = process_sign_of(n)?;
let mut chars = n.chars();
let next_char = chars.next();
let check_empty_after_sign = || {
if chars.clone().next().is_none() {
Err(EmptyAfterSign)
} else {
Ok(chars.as_str())
}
};
match next_char {
Some('+') => (
check_empty_after_sign()?,
ByteOffsetKind::ForwardFromLastOffset,
),
Some('-') => (check_empty_after_sign()?, ByteOffsetKind::BackwardFromEnd),
None => return Err(Empty),
_ => (n, ByteOffsetKind::ForwardFromBeginning),
}
};
let into_byte_offset = |value| { let into_byte_offset = |value| {
Ok(ByteOffset { Ok(ByteOffset {
@@ -403,9 +655,103 @@ fn parse_byte_offset(n: &str, block_size: PositiveI64) -> Result<ByteOffset, Byt
}) })
}; };
if n.starts_with(HEX_PREFIX) { if let Some(hex_number) = try_parse_as_hex_number(n) {
let n = &n[HEX_PREFIX.len()..]; return hex_number.map(into_byte_offset)?;
let mut chars = n.chars(); }
let (num, mut unit) = extract_num_and_unit_from(n)?;
if let Unit::Block { custom_size: None } = unit {
unit = Unit::Block {
custom_size: Some(
NonZeroI64::new(block_size.into_inner()).expect("PositiveI64 was zero"),
),
};
}
num.checked_mul(unit.get_multiplier())
.ok_or(UnitMultiplicationOverflow)
.and_then(into_byte_offset)
}
/// Takes a string containing a base-10 number and an optional unit, and returns them with their proper types.
/// The unit must directly follow the number (e.g. no whitespace is allowed between them).
/// When no unit is given, [Unit::Byte] is assumed.
/// When the unit is [Unit::Block], it is returned without custom size.
/// No normalization is performed, that is "1024" is extracted to (1024, Byte), not (1, Kibibyte).
fn extract_num_and_unit_from(n: &str) -> Result<(i64, Unit), ByteOffsetParseError> {
use ByteOffsetParseError::*;
if n.is_empty() {
return Err(Empty);
}
match n.chars().position(|c| !c.is_ascii_digit()) {
Some(unit_begin_idx) => {
let (n, raw_unit) = n.split_at(unit_begin_idx);
let unit = match raw_unit.to_lowercase().as_str() {
"" => Unit::Byte, // no "b" => Byte to allow hex nums with units
"kb" => Unit::Kilobyte,
"mb" => Unit::Megabyte,
"gb" => Unit::Gigabyte,
"tb" => Unit::Terabyte,
"kib" => Unit::Kibibyte,
"mib" => Unit::Mebibyte,
"gib" => Unit::Gibibyte,
"tib" => Unit::Tebibyte,
"block" | "blocks" => Unit::Block { custom_size: None },
_ => {
return if n.is_empty() {
Err(InvalidNumAndUnit(raw_unit.to_string()))
} else {
Err(InvalidUnit(raw_unit.to_string()))
}
}
};
let num = n.parse::<i64>().map_err(|e| {
if n.is_empty() {
EmptyWithUnit(raw_unit.to_owned())
} else {
ParseNum(e)
}
})?;
Ok((num, unit))
}
None => {
// no unit part
let num = n.parse::<i64>().map_err(ParseNum)?;
Ok((num, Unit::Byte))
}
}
}
/// Extracts a [ByteOffsetKind] based on the sign at the beginning of the given string.
/// Returns the input string without the sign (or an equal string if there wasn't any sign).
fn process_sign_of(n: &str) -> Result<(&str, ByteOffsetKind), ByteOffsetParseError> {
use ByteOffsetParseError::*;
let mut chars = n.chars();
let next_char = chars.next();
let check_empty_after_sign = || {
if chars.clone().next().is_none() {
Err(EmptyAfterSign)
} else {
Ok(chars.as_str())
}
};
match next_char {
Some('+') => Ok((
check_empty_after_sign()?,
ByteOffsetKind::ForwardFromLastOffset,
)),
Some('-') => Ok((check_empty_after_sign()?, ByteOffsetKind::BackwardFromEnd)),
None => Err(Empty),
_ => Ok((n, ByteOffsetKind::ForwardFromBeginning)),
}
}
/// If `n` starts with a hex prefix, its remaining part is returned as some number (if possible),
/// otherwise None is returned.
fn try_parse_as_hex_number(n: &str) -> Option<Result<i64, ByteOffsetParseError>> {
use ByteOffsetParseError::*;
n.strip_prefix(HEX_PREFIX).map(|num| {
let mut chars = num.chars();
match chars.next() { match chars.next() {
Some(c @ '+') | Some(c @ '-') => { Some(c @ '+') | Some(c @ '-') => {
return if chars.next().is_none() { return if chars.next().is_none() {
@@ -416,54 +762,70 @@ fn parse_byte_offset(n: &str, block_size: PositiveI64) -> Result<ByteOffset, Byt
} }
_ => (), _ => (),
} }
return i64::from_str_radix(n, 16) i64::from_str_radix(num, 16).map_err(ParseNum)
.map(into_byte_offset) })
.map_err(ParseNum)?; }
}
let (num, unit) = match n.chars().position(|c| !c.is_ascii_digit()) { #[test]
Some(unit_begin_idx) => { fn unit_multipliers() {
let (n, raw_unit) = n.split_at(unit_begin_idx); use Unit::*;
let raw_unit_lower = raw_unit.to_lowercase(); assert_eq!(Kilobyte.get_multiplier(), 1000 * Byte.get_multiplier());
let multiplier = [ assert_eq!(Megabyte.get_multiplier(), 1000 * Kilobyte.get_multiplier());
("b", 1), assert_eq!(Gigabyte.get_multiplier(), 1000 * Megabyte.get_multiplier());
("kb", 1000i64.pow(1)), assert_eq!(Terabyte.get_multiplier(), 1000 * Gigabyte.get_multiplier());
("mb", 1000i64.pow(2)),
("gb", 1000i64.pow(3)),
("tb", 1000i64.pow(4)),
("kib", 1024i64.pow(1)),
("mib", 1024i64.pow(2)),
("gib", 1024i64.pow(3)),
("tib", 1024i64.pow(4)),
("block", block_size.into_inner()),
]
.iter()
.cloned()
.find_map(|(unit, multiplier)| {
if unit == raw_unit_lower {
Some(multiplier)
} else {
None
}
})
.ok_or_else(|| InvalidUnit(raw_unit.to_owned()));
(n, multiplier.map(|m| (Some(raw_unit), m)))
}
None => (n, Ok((None, 1))),
};
match (num.parse::<i64>(), unit) { assert_eq!(Kibibyte.get_multiplier(), 1024 * Byte.get_multiplier());
(Ok(num), Ok((_raw_unit, unit_multiplier))) => num assert_eq!(Mebibyte.get_multiplier(), 1024 * Kibibyte.get_multiplier());
.checked_mul(unit_multiplier) assert_eq!(Gibibyte.get_multiplier(), 1024 * Mebibyte.get_multiplier());
.ok_or_else(|| UnitMultiplicationOverflow) assert_eq!(Tebibyte.get_multiplier(), 1024 * Gibibyte.get_multiplier());
.and_then(into_byte_offset), }
(Ok(_), Err(e)) => Err(e),
(Err(e), Ok((raw_unit, _unit_multiplier))) => match raw_unit { #[test]
Some(raw_unit) if num.is_empty() => Err(EmptyWithUnit(raw_unit.to_owned())), fn test_process_sign() {
_ => Err(ParseNum(e)), use ByteOffsetKind::*;
}, use ByteOffsetParseError::*;
(Err(_), Err(_)) => Err(InvalidNumAndUnit(n.to_owned())), assert_eq!(process_sign_of("123"), Ok(("123", ForwardFromBeginning)));
} assert_eq!(process_sign_of("+123"), Ok(("123", ForwardFromLastOffset)));
assert_eq!(process_sign_of("-123"), Ok(("123", BackwardFromEnd)));
assert_eq!(process_sign_of("-"), Err(EmptyAfterSign));
assert_eq!(process_sign_of("+"), Err(EmptyAfterSign));
assert_eq!(process_sign_of(""), Err(Empty));
}
#[test]
fn test_parse_as_hex() {
assert_eq!(try_parse_as_hex_number("73"), None);
assert_eq!(try_parse_as_hex_number("0x1337"), Some(Ok(0x1337)));
assert!(matches!(try_parse_as_hex_number("0xnope"), Some(Err(_))));
assert!(matches!(try_parse_as_hex_number("0x-1"), Some(Err(_))));
}
#[test]
fn extract_num_and_unit() {
use ByteOffsetParseError::*;
use Unit::*;
// byte is default unit
assert_eq!(extract_num_and_unit_from("4"), Ok((4, Byte)));
// blocks are returned without customization
assert_eq!(
extract_num_and_unit_from("2blocks"),
Ok((2, Block { custom_size: None }))
);
// no normalization is performed
assert_eq!(extract_num_and_unit_from("1024kb"), Ok((1024, Kilobyte)));
// unit without number results in error
assert_eq!(
extract_num_and_unit_from("gib"),
Err(EmptyWithUnit("gib".to_string()))
);
// empty string results in error
assert_eq!(extract_num_and_unit_from(""), Err(Empty));
// an invalid unit results in an error
assert_eq!(
extract_num_and_unit_from("25litres"),
Err(InvalidUnit("litres".to_string()))
);
} }
#[test] #[test]
@@ -472,7 +834,7 @@ fn test_parse_byte_offset() {
macro_rules! success { macro_rules! success {
($input: expr, $expected_kind: ident $expected_value: expr) => { ($input: expr, $expected_kind: ident $expected_value: expr) => {
success!($input, $expected_kind $expected_value; block_size: 512) success!($input, $expected_kind $expected_value; block_size: DEFAULT_BLOCK_SIZE)
}; };
($input: expr, $expected_kind: ident $expected_value: expr; block_size: $block_size: expr) => { ($input: expr, $expected_kind: ident $expected_value: expr; block_size: $block_size: expr) => {
assert_eq!( assert_eq!(
@@ -490,7 +852,7 @@ fn test_parse_byte_offset() {
macro_rules! error { macro_rules! error {
($input: expr, $expected_err: expr) => { ($input: expr, $expected_err: expr) => {
assert_eq!( assert_eq!(
parse_byte_offset($input, PositiveI64::new(512).unwrap()), parse_byte_offset($input, PositiveI64::new(DEFAULT_BLOCK_SIZE).unwrap()),
Err($expected_err), Err($expected_err),
); );
}; };
+642 -259
View File
File diff suppressed because it is too large. Load diff
-425
View File
@@ -1,425 +0,0 @@
#[derive(Debug, PartialEq)]
enum SqueezeState {
/// not enabled
Disabled,
/// Will be set from all states if equal condition can't be hold up.
/// Set if previous byte is not equal the current processed byte.
NoSqueeze,
/// Valid for a whole line to identify if it is candidate for squeezing
Probe,
/// Squeeze line parsing is active, but EOL is not reached yet
SqueezeActive,
/// Squeeze line, EOL is reached, will influence the action
Squeeze,
/// same as Squeeze, however this is only for the first line after
/// the squeeze candidate has been set.
SqueezeFirstLine,
/// same as SqueezeActive, however this is only for the first line after
/// the squeeze candidate has been set.
SqueezeActiveFirstLine,
}
pub struct Squeezer {
state: SqueezeState,
byte: u8,
}
#[derive(Debug, PartialEq)]
pub enum SqueezeAction {
Ignore,
Print,
Delete,
}
/// line size
const LSIZE: u64 = 16;
impl Squeezer {
pub fn new(enabled: bool) -> Squeezer {
Squeezer {
state: if enabled {
SqueezeState::Probe
} else {
SqueezeState::Disabled
},
byte: 0,
}
}
pub fn process(&mut self, b: u8, i: u64) {
use self::SqueezeState::*;
if self.state == Disabled {
return;
}
let eq = b == self.byte;
if i % LSIZE == 0 {
if !eq {
self.state = Probe;
} else {
self.state = match self.state {
NoSqueeze => Probe,
Probe => SqueezeActiveFirstLine,
SqueezeActiveFirstLine => SqueezeFirstLine,
SqueezeFirstLine => SqueezeActive,
SqueezeActive => Squeeze,
Squeeze => SqueezeActive,
Disabled => Disabled,
};
}
} else if !eq {
if i % LSIZE == 1 {
self.state = Probe;
} else if i % LSIZE != 1 {
self.state = NoSqueeze;
}
}
self.byte = b;
}
pub fn active(&self) -> bool {
use self::SqueezeState::*;
match self.state {
Squeeze | SqueezeActive | SqueezeFirstLine | SqueezeActiveFirstLine => true,
_ => false,
}
}
pub fn action(&self) -> SqueezeAction {
match self.state {
SqueezeState::SqueezeFirstLine => SqueezeAction::Print,
SqueezeState::Squeeze => SqueezeAction::Delete,
_ => SqueezeAction::Ignore,
}
}
pub fn advance(&mut self) {
match self.state {
SqueezeState::SqueezeFirstLine => {
self.state = SqueezeState::SqueezeActive;
}
SqueezeState::Squeeze => {
self.state = SqueezeState::SqueezeActive;
}
_ => {}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const LSIZE_USIZE: usize = LSIZE as usize;
#[test]
fn three_same_lines() {
const LINES: usize = 3;
let v = vec![0u8; LINES * LSIZE_USIZE];
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Print, // print squeeze symbol
SqueezeAction::Delete, // delete reoccurring line
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
s.advance();
assert_eq!(action, exp[line]);
line += 1;
}
}
#[test]
fn incomplete_while_squeeze() {
// fourth line only has 12 bytes and should be printed
let v = vec![0u8; 3 * LSIZE_USIZE + 12];
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Print, // print squeeze symbol
SqueezeAction::Delete, // delete reoccurring line
SqueezeAction::Ignore, // last line only 12 bytes, print it
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
assert_eq!(s.action(), exp[line]);
s.advance();
line += 1;
}
}
#[test]
/// all three lines are different, print all
fn three_different_lines() {
let mut v: Vec<u8> = vec![];
v.extend(vec![0u8; 16]);
v.extend(vec![1u8; 16]);
v.extend(vec![2u8; 16]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Ignore, // different
SqueezeAction::Ignore, // different
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
assert_eq!(action, exp[line]);
s.advance();
line += 1;
}
}
#[test]
/// first two lines same, hence squeeze symbol, third line diff, hence
/// print
fn one_squeeze_no_delete() {
const LINES: usize = 3;
let mut v = vec![0u8; (LINES - 1) * LSIZE_USIZE];
v.extend(vec![1u8; 16]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Print, // print squeeze symbol
SqueezeAction::Ignore, // different lines, print again
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
s.advance();
assert_eq!(action, exp[line]);
line += 1;
}
}
#[test]
/// First line all eq, 2nd half eq with first line, then change
fn second_line_different() {
const LINES: usize = 2;
let mut v = vec![0u8; (LINES - 1) * LSIZE_USIZE];
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Ignore, // print squeeze symbol
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
s.advance();
assert_eq!(action, exp[line]);
line += 1;
}
}
#[test]
/// all three lines never become squeeze candidate (diff within line)
fn never_squeeze_candidate() {
let mut v = vec![];
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // first line, print as is
SqueezeAction::Ignore, // print squeeze symbol
SqueezeAction::Ignore, // print squeeze symbol
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
s.advance();
assert_eq!(action, exp[line]);
line += 1;
}
}
#[test]
fn mix_everything() {
let mut v = vec![];
v.extend(vec![10u8; 16]); // print
v.extend(vec![20u8; 16]); // print
v.extend(vec![0u8; 16]); // print
v.extend(vec![0u8; 16]); // *
v.extend(vec![10u8; 16]); // print
v.extend(vec![20u8; 16]); // print
v.extend(vec![0u8; 16]); // print
v.extend(vec![0u8; 16]); // *
v.extend(vec![0u8; 16]); // delete
v.extend(vec![0u8; 16]); // delete*
v.extend(vec![20u8; 16]); // print
v.extend(vec![0u8; 12]); // print, only 12 bytes
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore,
SqueezeAction::Ignore,
SqueezeAction::Ignore,
SqueezeAction::Print,
SqueezeAction::Ignore,
SqueezeAction::Ignore,
SqueezeAction::Ignore,
SqueezeAction::Print,
SqueezeAction::Delete,
SqueezeAction::Delete,
SqueezeAction::Ignore,
SqueezeAction::Ignore,
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
let action = s.action();
s.advance();
assert_eq!(action, exp[line]);
line += 1;
}
}
#[test]
fn last_char_diff() {
// see issue #62
let mut v = vec![];
v.extend(vec![20u8; 16]);
v.extend(vec![20u8; 15]);
v.push(61);
v.extend(vec![20u8; 16]);
v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // print as is
SqueezeAction::Ignore, // print as is
SqueezeAction::Ignore, // print as is
SqueezeAction::Print, // print '*' char
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
assert_eq!(s.action(), exp[line]);
s.advance();
line += 1;
}
}
#[test]
fn first_char_diff() {
// see issue #62
let mut v = vec![];
v.extend(vec![20u8; 16]);
v.push(61);
v.extend(vec![20u8; 15]);
v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true);
// just initialized
assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance();
let exp = vec![
SqueezeAction::Ignore, // print as is
SqueezeAction::Ignore, // print as is
SqueezeAction::Ignore, // print as is
];
let mut line = 0;
let mut idx = 1;
for z in v.chunks(LSIZE_USIZE) {
for i in z {
s.process(*i, idx);
idx += 1;
}
assert_eq!(s.action(), exp[line]);
s.advance();
line += 1;
}
}
}
+420 -5
View File
@@ -5,6 +5,26 @@ fn hexyl() -> Command {
cmd.current_dir("tests/examples"); cmd.current_dir("tests/examples");
cmd cmd
} }
trait PrettyAssert<S>
where
S: AsRef<str>,
{
fn pretty_stdout(self, other: S);
}
// https://github.com/assert-rs/assert_cmd/issues/121#issuecomment-849937376
//
impl<S> PrettyAssert<S> for assert_cmd::assert::Assert
where
S: AsRef<str>,
{
fn pretty_stdout(self, other: S) {
println!("{}", other.as_ref().len());
let self_str = String::from_utf8(self.get_output().stdout.clone()).unwrap();
println!("{}", self_str.len());
pretty_assertions::assert_eq!(self_str, other.as_ref());
}
}
mod basic { mod basic {
use super::hexyl; use super::hexyl;
@@ -51,7 +71,7 @@ mod basic {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│ │ No content to print │ │ │ │\n\ │ │ No content │ │ │ │\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }
@@ -70,8 +90,8 @@ mod length {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│00000000│ 7f 45 4c 46 02 01 01 00 ┊ 00 00 00 00 00 00 00 00 │•ELF•••0┊00000000│\n\ │00000000│ 7f 45 4c 46 02 01 01 00 ┊ 00 00 00 00 00 00 00 00 │•ELF•••⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│\n\
│00000010│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•0>0•000┊0•@00000│\n\ │00000010│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•⋄>⋄•⋄⋄⋄┊⋄•@⋄⋄⋄⋄⋄│\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }
@@ -85,6 +105,30 @@ mod length {
.assert() .assert()
.failure(); .failure();
} }
#[test]
fn fail_if_length_and_count_options_are_used_simultaneously() {
hexyl()
.arg("hello_world_elf64")
.arg("--length=32")
.arg("-l=10")
.assert()
.failure();
}
}
mod bytes {
use super::hexyl;
#[test]
fn fail_if_bytes_and_count_options_are_used_simultaneously() {
hexyl()
.arg("hello_world_elf64")
.arg("--bytes=32")
.arg("-l=10")
.assert()
.failure();
}
} }
mod skip { mod skip {
@@ -116,7 +160,7 @@ mod skip {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│ │ No content to print │ │ │ │\n\ │ │ No content │ │ │ │\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }
@@ -179,7 +223,7 @@ mod display_offset {
.success() .success()
.stdout( .stdout(
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│00000030│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•0>0•000┊0•@00000│\n\ │00000030│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │•⋄>⋄•⋄⋄⋄┊⋄•@⋄⋄⋄⋄⋄│\n\
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
); );
} }
@@ -203,3 +247,374 @@ mod blocksize {
.failure(); .failure();
} }
} }
mod display_settings {
use super::hexyl;
#[test]
fn plain() {
hexyl()
.arg("ascii")
.arg("--plain")
.assert()
.success()
.stdout(" 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 0a \n");
}
#[test]
fn no_chars() {
hexyl()
.arg("ascii")
.arg("--no-characters")
.arg("--color=never")
.assert()
.success()
.stdout(
"┌────────┬─────────────────────────┬─────────────────────────┐\n\
│00000000│ 30 31 32 33 34 35 36 37 ┊ 38 39 61 62 63 64 65 0a │\n\
└────────┴─────────────────────────┴─────────────────────────┘\n",
);
}
#[test]
fn no_position() {
hexyl()
.arg("ascii")
.arg("--no-position")
.arg("--color=never")
.assert()
.success()
.stdout(
"┌─────────────────────────┬─────────────────────────┬────────┬────────┐\n\
│ 30 31 32 33 34 35 36 37 ┊ 38 39 61 62 63 64 65 0a │01234567┊89abcde_│\n\
└─────────────────────────┴─────────────────────────┴────────┴────────┘\n",
);
}
}
mod group_and_endianness {
use super::hexyl;
use super::PrettyAssert;
#[test]
fn group_2_bytes_be() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=2")
.assert()
.success()
.stdout(
"┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\
│00000000│ 3031 3233 3435 3637 ┊ 3839 6162 6364 650a │01234567┊89abcde_│\n\
└────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_2_bytes_le() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=2")
.arg("--endianness=little")
.assert()
.success()
.stdout(
"┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\
│00000000│ 3130 3332 3534 3736 ┊ 3938 6261 6463 0a65 │01234567┊89abcde_│\n\
└────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_4_bytes_be() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=4")
.assert()
.success()
.stdout(
"┌────────┬───────────────────┬───────────────────┬────────┬────────┐\n\
│00000000│ 30313233 34353637 ┊ 38396162 6364650a │01234567┊89abcde_│\n\
└────────┴───────────────────┴───────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_4_bytes_le() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=4")
.arg("--endianness=little")
.assert()
.success()
.stdout(
"┌────────┬───────────────────┬───────────────────┬────────┬────────┐\n\
│00000000│ 33323130 37363534 ┊ 62613938 0a656463 │01234567┊89abcde_│\n\
└────────┴───────────────────┴───────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_8_bytes_be() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=8")
.assert()
.success()
.stdout(
"┌────────┬──────────────────┬──────────────────┬────────┬────────┐\n\
│00000000│ 3031323334353637 ┊ 383961626364650a │01234567┊89abcde_│\n\
└────────┴──────────────────┴──────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_8_bytes_le() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--group-size=8")
.arg("--endianness=little")
.assert()
.success()
.stdout(
"┌────────┬──────────────────┬──────────────────┬────────┬────────┐\n\
│00000000│ 3736353433323130 ┊ 0a65646362613938 │01234567┊89abcde_│\n\
└────────┴──────────────────┴──────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_size_plain() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--plain")
.arg("--group-size=2")
.assert()
.success()
.stdout(" 3031 3233 3435 3637 3839 6162 6364 650a \n");
}
#[test]
fn group_size_fill_space() {
hexyl()
.arg("--color=never")
.arg("--group-size=2")
.write_stdin("abc")
.assert()
.success()
.stdout(
"┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\
│00000000│ 6162 63 ┊ │abc ┊ │\n\
└────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n",
);
}
#[test]
fn group_size_invalid() {
hexyl()
.arg("ascii")
.arg("--color=never")
.arg("--plain")
.arg("--group-size=3")
.assert()
.failure();
}
#[test]
fn squeeze_no_chars() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4096")
.arg("--no-characters")
.assert()
.success()
.pretty_stdout(
"\
┌────────┬─────────────────────────┬─────────────────────────┐
│00000400│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │
│* │ ┊ │
│00001000│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 │
│00001010│ 04 00 00 00 cd 80 b8 01 ┊ 00 00 00 cd 80 00 00 00 │
│00001020│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │
│* │ ┊ │
│00001400│ ┊ │
└────────┴─────────────────────────┴─────────────────────────┘
",
);
}
#[test]
fn squeeze_no_chars_one_panel() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4096")
.arg("--no-characters")
.arg("--panels=1")
.assert()
.success()
.pretty_stdout(
"\
┌────────┬─────────────────────────┐
│00000400│ 00 00 00 00 00 00 00 00 │
│* │ │
│00001000│ ba 0e 00 00 00 b9 00 20 │
│00001008│ 40 00 bb 01 00 00 00 b8 │
│00001010│ 04 00 00 00 cd 80 b8 01 │
│00001018│ 00 00 00 cd 80 00 00 00 │
│00001020│ 00 00 00 00 00 00 00 00 │
│* │ │
│00001400│ │
└────────┴─────────────────────────┘
",
);
}
#[test]
fn squeeze_no_position() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4096")
.arg("--no-position")
.assert()
.success()
.pretty_stdout(
"\
┌─────────────────────────┬─────────────────────────┬────────┬────────┐
│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│* ┊ │ ┊ │
│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 │ו⋄⋄⋄×⋄ ┊@⋄ו⋄⋄⋄×│
│ 04 00 00 00 cd 80 b8 01 ┊ 00 00 00 cd 80 00 00 00 │•⋄⋄⋄××ו┊⋄⋄⋄××⋄⋄⋄│
│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│* ┊ │ ┊ │
│* ┊ │ ┊ │
└─────────────────────────┴─────────────────────────┴────────┴────────┘
",
);
}
#[test]
fn squeeze_no_position_one_panel() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4096")
.arg("--no-position")
.arg("--panels=1")
.assert()
.success()
.pretty_stdout(
"\
┌─────────────────────────┬────────┐
│ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄│
│* │ │
│ ba 0e 00 00 00 b9 00 20 │ו⋄⋄⋄×⋄ │
│ 40 00 bb 01 00 00 00 b8 │@⋄ו⋄⋄⋄×│
│ 04 00 00 00 cd 80 b8 01 │•⋄⋄⋄××ו│
│ 00 00 00 cd 80 00 00 00 │⋄⋄⋄××⋄⋄⋄│
│ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄│
│* │ │
│* │ │
└─────────────────────────┴────────┘
",
);
}
#[test]
fn squeeze_odd_panels_remainder_bytes() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4092") // 4 byte remainder
.arg("--panels=3")
.assert()
.success()
.pretty_stdout(
"\
┌────────┬─────────────────────────┬─────────────────────────┬─────────────────────────┬────────┬────────┬────────┐
│00000400│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│* │ ┊ ┊ │ ┊ ┊ │
│00001000│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 ┊ 04 00 00 00 cd 80 b8 01 │ו⋄⋄⋄×⋄ ┊@⋄ו⋄⋄⋄×┊•⋄⋄⋄××ו│
│00001018│ 00 00 00 cd 80 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄××⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│00001030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│* │ ┊ ┊ │ ┊ ┊ │
│000013f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 ┊ │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴─────────────────────────┴────────┴────────┴────────┘
",
);
}
#[test]
fn squeeze_plain() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4096")
.arg("--plain")
.assert()
.success()
.pretty_stdout(
" \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
ba 0e 00 00 00 b9 00 20 40 00 bb 01 00 00 00 b8
04 00 00 00 cd 80 b8 01 00 00 00 cd 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
*
",
);
}
#[test]
fn squeeze_plain_remainder() {
hexyl()
.arg("hello_world_elf64")
.arg("--color=never")
.arg("--skip=1024")
.arg("--length=4092") // 4 byte remainder
.arg("--plain")
.assert()
.success()
.pretty_stdout(
" \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
ba 0e 00 00 00 b9 00 20 40 00 bb 01 00 00 00 b8
04 00 00 00 cd 80 b8 01 00 00 00 cd 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
00 00 00 00 00 00 00 00 00 00 00 00
",
);
}
}
mod base {
use super::hexyl;
use super::PrettyAssert;
#[test]
fn base2() {
hexyl()
.arg("ascii")
.arg("--plain")
.arg("--base=binary")
.assert()
.success()
.pretty_stdout(
" 00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111 \n \
00111000 00111001 01100001 01100010 01100011 01100100 01100101 00001010 \n",
);
}
}