13 Commits
10 changed files with 421 additions and 125 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
name: CICD name: CICD
env: env:
MIN_SUPPORTED_RUST_VERSION: "1.56.0" MIN_SUPPORTED_RUST_VERSION: "1.56.1"
CICD_INTERMEDIATES_DIR: "_cicd-intermediates" CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
on: on:
Generated
+161 -36
View File
@@ -1,6 +1,6 @@
# 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 version = 4
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
@@ -20,6 +20,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.57" version = "1.0.57"
@@ -28,13 +34,14 @@ checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]] [[package]]
name = "assert_cmd" name = "assert_cmd"
version = "2.0.4" version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514"
dependencies = [ dependencies = [
"anstyle",
"bstr", "bstr",
"doc-comment", "libc",
"predicates", "predicates 3.1.4",
"predicates-core", "predicates-core",
"predicates-tree", "predicates-tree",
"wait-timeout", "wait-timeout",
@@ -65,37 +72,43 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.17" version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
dependencies = [ dependencies = [
"lazy_static",
"memchr", "memchr",
"regex-automata", "regex-automata",
"serde",
] ]
[[package]] [[package]]
name = "clap" name = "cc"
version = "3.1.18" version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "clap"
version = "3.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d646c7ade5eb07c4aa20e907a922750df0c448892513714fd3e4acbc7130829f"
dependencies = [ dependencies = [
"atty", "atty",
"bitflags", "bitflags",
"clap_lex", "clap_lex",
"indexmap", "indexmap",
"lazy_static", "once_cell",
"strsim", "strsim",
"termcolor", "termcolor",
"terminal_size", "terminal_size 0.1.17",
"textwrap", "textwrap",
] ]
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.2.0" 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 = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
@@ -126,18 +139,33 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "either" name = "either"
version = "1.6.1" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[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.9.0" version = "0.9.0"
@@ -173,7 +201,8 @@ dependencies = [
"clap", "clap",
"const_format", "const_format",
"libc", "libc",
"predicates", "predicates 2.1.1",
"terminal_size 0.2.1",
"thiserror", "thiserror",
] ]
@@ -187,6 +216,12 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "io-lifetimes"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.3" version = "0.10.3"
@@ -197,22 +232,22 @@ dependencies = [
] ]
[[package]] [[package]]
name = "lazy_static" name = "libc"
version = "1.4.0" version = "0.2.182"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]] [[package]]
name = "libc" name = "linux-raw-sys"
version = "0.2.126" version = "0.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]] [[package]]
name = "normalize-line-endings" name = "normalize-line-endings"
@@ -229,6 +264,12 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.0.1" version = "6.0.1"
@@ -250,10 +291,21 @@ dependencies = [
] ]
[[package]] [[package]]
name = "predicates-core" name = "predicates"
version = "1.0.3" version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe"
dependencies = [
"anstyle",
"difflib",
"predicates-core",
]
[[package]]
name = "predicates-core"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144"
[[package]] [[package]]
name = "predicates-tree" name = "predicates-tree"
@@ -296,9 +348,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.1.10" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
@@ -306,6 +358,26 @@ version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "rustix"
version = "0.35.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51cc38aa10f6bbb377ed28197aa052aa4e2b762c22be9d3153d01822587e787"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "serde"
version = "1.0.185"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@@ -342,6 +414,16 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "terminal_size"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8440c860cf79def6164e4a0a983bcc2305d82419177a0e0c71930d049e3ac5a1"
dependencies = [
"rustix",
"windows-sys",
]
[[package]] [[package]]
name = "termtree" name = "termtree"
version = "0.2.4" version = "0.2.4"
@@ -354,7 +436,7 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
dependencies = [ dependencies = [
"terminal_size", "terminal_size 0.1.17",
] ]
[[package]] [[package]]
@@ -428,3 +510,46 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+2 -1
View File
@@ -17,6 +17,7 @@ atty = "0.2"
const_format = "0.2" const_format = "0.2"
libc = "0.2" libc = "0.2"
thiserror = "1.0" thiserror = "1.0"
terminal_size = "0.2"
[dependencies.clap] [dependencies.clap]
version = "3" version = "3"
@@ -24,7 +25,7 @@ default-features = false
features = ["std", "suggestions", "color", "wrap_help", "cargo"] features = ["std", "suggestions", "color", "wrap_help", "cargo"]
[dev-dependencies] [dev-dependencies]
assert_cmd = "2.0" assert_cmd = "2.1"
predicates = "2.0" predicates = "2.0"
[profile.release] [profile.release]
+8
View File
@@ -44,6 +44,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/):
+3
View File
@@ -121,6 +121,9 @@ Source repository:
Print a given file: Print a given file:
: $ **hexyl small.png** : $ **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: Print the first 256 bytes of a given special file:
: $ **hexyl -n 256 /dev/urandom** : $ **hexyl -n 256 /dev/urandom**
+2
View File
@@ -16,6 +16,7 @@ fn main() {
let show_position_panel = true; let show_position_panel = true;
let use_squeezing = false; let use_squeezing = false;
let border_style = BorderStyle::Unicode; let border_style = BorderStyle::Unicode;
let columns = 2;
let mut printer = Printer::new( let mut printer = Printer::new(
&mut handle, &mut handle,
@@ -24,6 +25,7 @@ fn main() {
show_position_panel, show_position_panel,
border_style, border_style,
use_squeezing, use_squeezing,
columns,
); );
printer.print_all(&input[..]).unwrap(); printer.print_all(&input[..]).unwrap();
} }
+82 -1
View File
@@ -4,7 +4,7 @@ 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::*, SeekFrom};
use std::num::NonZeroI64; use std::num::{NonZeroI64, NonZeroU16};
use clap::{crate_name, crate_version, AppSettings, Arg, ColorChoice, Command}; use clap::{crate_name, crate_version, AppSettings, Arg, ColorChoice, Command};
@@ -16,6 +16,8 @@ use const_format::formatcp;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use terminal_size::terminal_size;
use hexyl::{BorderStyle, Input, Printer}; use hexyl::{BorderStyle, Input, Printer};
const DEFAULT_BLOCK_SIZE: i64 = 512; const DEFAULT_BLOCK_SIZE: i64 = 512;
@@ -149,6 +151,42 @@ 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("columns")
.short('w')
.long("columns")
.takes_value(true)
.value_name("N")
.help(
"Sets the number of hex data columns to be displayed. \
Cannot be used with other width-setting options.",
),
)
.arg(
Arg::new("terminal_width")
.short('t')
.long("terminal-width")
.takes_value(true)
.value_name("N")
.conflicts_with("columns")
.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 columns that can fit in the requested \
width but still leave some space to the right.\nCannot be used with other \
width-setting options.",
),
)
.arg(
Arg::new("auto_width")
.short('a')
.long("auto-width")
.conflicts_with_all(&["columns", "terminal_width"])
.help(
"Sets the number of hex data columns to be adjusted according to the \
detected terminal width.\nCannot be used with other width-setting options.",
),
); );
let matches = command.get_matches(); let matches = command.get_matches();
@@ -267,6 +305,48 @@ fn run() -> Result<(), AnyhowError> {
.transpose()? .transpose()?
.unwrap_or(0); .unwrap_or(0);
let columns = if let Some(columns) = matches
.value_of("columns")
.map(|s| {
s.parse::<NonZeroU16>().map(u16::from).context(anyhow!(
"failed to parse `--columns` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
columns
} else {
let terminal_width = if let Some(terminal_width) = matches
.value_of("terminal_width")
.map(|s| {
s.parse::<NonZeroU16>().map(u16::from).context(anyhow!(
"failed to parse `--columns` arg {:?} as unsigned nonzero integer",
s
))
})
.transpose()?
{
Some(terminal_width)
} else if matches.is_present("auto_width") {
Some(terminal_size().ok_or_else(|| anyhow!("not a TTY"))?.0 .0)
} else {
None
};
if let Some(terminal_width) = terminal_width {
let offset = if show_position_panel { 10 } else { 1 };
let col_width = if show_char_panel { 35 } else { 26 };
if (terminal_width - offset) / col_width < 1 {
1
} else {
(terminal_width - offset) / col_width
}
} else {
2
}
};
let stdout = io::stdout(); let stdout = io::stdout();
let mut stdout_lock = stdout.lock(); let mut stdout_lock = stdout.lock();
@@ -277,6 +357,7 @@ fn run() -> Result<(), AnyhowError> {
show_position_panel, show_position_panel,
border_style, border_style,
squeeze, squeeze,
columns,
); );
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))?;
+145 -69
View File
@@ -154,6 +154,8 @@ pub struct Printer<'a, Writer: Write> {
byte_char_panel: Vec<String>, byte_char_panel: Vec<String>,
squeezer: Squeezer, squeezer: Squeezer,
display_offset: u64, display_offset: u64,
/// The number of panels to draw.
columns: u16,
} }
impl<'a, Writer: Write> Printer<'a, Writer> { impl<'a, Writer: Write> Printer<'a, Writer> {
@@ -164,6 +166,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
show_position_panel: bool, show_position_panel: bool,
border_style: BorderStyle, border_style: BorderStyle,
use_squeeze: bool, use_squeeze: bool,
columns: u16,
) -> Printer<'a, Writer> { ) -> Printer<'a, Writer> {
Printer { Printer {
idx: 1, idx: 1,
@@ -175,7 +178,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
show_position_panel, show_position_panel,
border_style, border_style,
header_was_printed: false, header_was_printed: false,
byte_hex_panel: (0u8..=u8::max_value()) byte_hex_panel: (0u8..=u8::MAX)
.map(|i| { .map(|i| {
let byte_hex = format!("{:02x} ", i); let byte_hex = format!("{:02x} ", i);
if show_color { if show_color {
@@ -187,7 +190,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
.collect(), .collect(),
byte_char_panel: show_char_panel byte_char_panel: show_char_panel
.then(|| { .then(|| {
(0u8..=u8::max_value()) (0u8..=u8::MAX)
.map(|i| { .map(|i| {
let byte_char = format!("{}", Byte(i).as_char()); let byte_char = format!("{}", Byte(i).as_char());
if show_color { if show_color {
@@ -199,8 +202,9 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
.collect() .collect()
}) })
.unwrap_or_default(), .unwrap_or_default(),
squeezer: Squeezer::new(use_squeeze), squeezer: Squeezer::new(use_squeeze, 8 * columns as u64),
display_offset: 0, display_offset: 0,
columns,
} }
} }
@@ -223,10 +227,20 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
write!(self.writer, "{}", l).ok(); write!(self.writer, "{}", l).ok();
} }
write!(self.writer, "{h25}{c}{h25}", c = c, h25 = h25).ok(); for _ in 0..self.columns - 1 {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok();
}
if self.show_char_panel {
write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok();
} else {
write!(self.writer, "{h25}", h25 = h25).ok();
}
if self.show_char_panel { if self.show_char_panel {
writeln!(self.writer, "{c}{h8}{c}{h8}{r}", c = c, h8 = h8, r = r).ok(); for _ in 0..self.columns - 1 {
write!(self.writer, "{h8}{c}", h8 = h8, c = c).ok();
}
writeln!(self.writer, "{h8}{r}", h8 = h8, r = r).ok();
} else { } else {
writeln!(self.writer, "{r}", r = r).ok(); writeln!(self.writer, "{r}", r = r).ok();
} }
@@ -287,36 +301,30 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.byte_char_panel[b as usize] self.byte_char_panel[b as usize]
); );
if idx == 8 { if idx % 8 == 0 && idx % (u64::from(self.columns) * 8) != 0 {
let _ = write!(&mut self.buffer_line, "{}", self.border_style.inner_sep()); let _ = write!(&mut self.buffer_line, "{}", self.border_style.inner_sep());
} }
idx += 1; idx += 1;
} }
if len < 8 { if len < usize::from(8 * self.columns) {
let _ = writeln!( let _ = write!(&mut self.buffer_line, "{0:1$}", "", 8 - len % 8);
&mut self.buffer_line, for _ in 0..(usize::from(8 * self.columns) - (len + (8 - len % 8))) / 8 {
"{0:1$}{3}{0:2$}{4}", let _ = write!(
"", &mut self.buffer_line,
8 - len, "{2}{0:1$}",
8, "",
self.border_style.inner_sep(), 8,
self.border_style.outer_sep(), self.border_style.inner_sep()
); );
} else { }
let _ = writeln!(
&mut self.buffer_line,
"{0:1$}{2}",
"",
16 - len,
self.border_style.outer_sep()
);
} }
let _ = writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep());
} }
pub fn print_byte(&mut self, b: u8) -> io::Result<()> { pub fn print_byte(&mut self, b: u8) -> io::Result<()> {
if self.idx % 16 == 1 { if self.idx % (u64::from(self.columns) * 8) == 1 {
self.print_header(); self.print_header();
self.print_position_panel(); self.print_position_panel();
} }
@@ -326,14 +334,10 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.squeezer.process(b, self.idx); self.squeezer.process(b, self.idx);
match self.idx % 16 { if self.idx % (u64::from(self.columns) * 8) == 0 {
8 => { self.print_textline()?;
let _ = write!(&mut self.buffer_line, "{} ", self.border_style.inner_sep()); } else if self.idx % 8 == 0 {
} let _ = write!(&mut self.buffer_line, "{} ", self.border_style.inner_sep());
0 => {
self.print_textline()?;
}
_ => {}
} }
self.idx += 1; self.idx += 1;
@@ -347,16 +351,33 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
if len == 0 { if len == 0 {
if self.squeezer.active() { if self.squeezer.active() {
self.print_position_panel(); self.print_position_panel();
let _ = writeln!( write!(&mut self.buffer_line, "{0:1$}", "", 24)?;
for _ in 0..self.columns - 1 {
write!(
&mut self.buffer_line,
"{2}{0:1$}",
"",
25,
self.border_style.inner_sep()
)?;
}
write!(
&mut self.buffer_line, &mut self.buffer_line,
"{0:1$}{4}{0:2$}{5}{0:3$}{4}{0:3$}{5}", "{2}{0:1$}",
"", "",
24,
25,
8, 8,
self.border_style.inner_sep(), self.border_style.outer_sep()
self.border_style.outer_sep(), )?;
); for _ in 0..self.columns - 1 {
write!(
&mut self.buffer_line,
"{2}{0:1$}",
"",
8,
self.border_style.inner_sep()
)?;
}
writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
self.writer.write_all(&self.buffer_line)?; self.writer.write_all(&self.buffer_line)?;
} }
return Ok(()); return Ok(());
@@ -364,28 +385,22 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
let squeeze_action = self.squeezer.action(); let squeeze_action = self.squeezer.action();
// print empty space on last line
if squeeze_action != SqueezeAction::Delete { if squeeze_action != SqueezeAction::Delete {
if len < 8 { if len < usize::from(8 * self.columns) {
let _ = write!( write!(&mut self.buffer_line, "{0:1$}", "", 3 * (8 - len % 8))?;
&mut self.buffer_line, for _ in 0..(usize::from(8 * self.columns) - (len + (8 - len % 8))) / 8 {
"{0:1$}{3}{0:2$}{4}", write!(
"", &mut self.buffer_line,
3 * (8 - len), "{2}{0:1$}",
1 + 3 * 8, "",
self.border_style.inner_sep(), 1 + 3 * 8,
self.border_style.outer_sep(), self.border_style.inner_sep()
); )?;
} else { }
let _ = write!(
&mut self.buffer_line,
"{0:1$}{2}",
"",
3 * (16 - len),
self.border_style.outer_sep()
);
} }
write!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
} }
self.print_char_panel(); self.print_char_panel();
match squeeze_action { match squeeze_action {
@@ -397,17 +412,33 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
} else { } else {
String::from("*") String::from("*")
}; };
let _ = writeln!(
write!(
&mut self.buffer_line, &mut self.buffer_line,
"{5}{0}{1:2$}{5}{1:3$}{6}{1:3$}{5}{1:4$}{6}{1:4$}{5}", "{3}{0}{1:2$}{3}",
asterisk, asterisk,
"", "",
7, 7,
25, self.border_style.outer_sep()
8, )?;
self.border_style.outer_sep(),
self.border_style.inner_sep(), for i in 0..self.columns {
); write!(&mut self.buffer_line, "{0:1$}", "", 25)?;
if i != self.columns - 1 {
write!(&mut self.buffer_line, "{}", self.border_style.inner_sep())?;
} else {
write!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
}
}
for i in 0..self.columns {
write!(&mut self.buffer_line, "{0:1$}", "", 8)?;
if i != self.columns - 1 {
write!(&mut self.buffer_line, "{}", self.border_style.inner_sep())?;
} else {
writeln!(&mut self.buffer_line, "{}", self.border_style.outer_sep())?;
}
}
} }
SqueezeAction::Delete => self.buffer_line.clear(), SqueezeAction::Delete => self.buffer_line.clear(),
SqueezeAction::Ignore => (), SqueezeAction::Ignore => (),
@@ -484,7 +515,15 @@ mod tests {
fn assert_print_all_output<Reader: Read>(input: Reader, expected_string: String) { fn assert_print_all_output<Reader: Read>(input: Reader, expected_string: String) {
let mut output = vec![]; let mut output = vec![];
let mut printer = Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true); let mut printer = Printer::new(
&mut output,
false,
true,
true,
BorderStyle::Unicode,
true,
2,
);
printer.print_all(input).unwrap(); printer.print_all(input).unwrap();
@@ -528,8 +567,15 @@ mod tests {
.to_owned(); .to_owned();
let mut output = vec![]; let mut output = vec![];
let mut printer: Printer<Vec<u8>> = let mut printer: Printer<Vec<u8>> = Printer::new(
Printer::new(&mut output, false, true, true, BorderStyle::Unicode, true); &mut output,
false,
true,
true,
BorderStyle::Unicode,
true,
2,
);
printer.display_offset(0xdeadbeef); printer.display_offset(0xdeadbeef);
printer.print_all(input).unwrap(); printer.print_all(input).unwrap();
@@ -537,4 +583,34 @@ mod tests {
let actual_string: &str = str::from_utf8(&output).unwrap(); let actual_string: &str = str::from_utf8(&output).unwrap();
assert_eq!(actual_string, expected_string) assert_eq!(actual_string, expected_string)
} }
#[test]
fn multiple_columns() {
let input = io::Cursor::new(b"supercalifragilisticexpialidocioussupercalifragilisticexpialidocioussupercalifragilisticexpialidocious");
let expected_string = "\
┌────────┬─────────────────────────┬─────────────────────────┬─────────────────────────┬─────────────────────────┬────────┬────────┬────────┬────────┐
│00000000│ 73 75 70 65 72 63 61 6c ┊ 69 66 72 61 67 69 6c 69 ┊ 73 74 69 63 65 78 70 69 ┊ 61 6c 69 64 6f 63 69 6f │supercal┊ifragili┊sticexpi┊alidocio│
│00000020│ 75 73 73 75 70 65 72 63 ┊ 61 6c 69 66 72 61 67 69 ┊ 6c 69 73 74 69 63 65 78 ┊ 70 69 61 6c 69 64 6f 63 │ussuperc┊alifragi┊listicex┊pialidoc│
│00000040│ 69 6f 75 73 73 75 70 65 ┊ 72 63 61 6c 69 66 72 61 ┊ 67 69 6c 69 73 74 69 63 ┊ 65 78 70 69 61 6c 69 64 │ioussupe┊rcalifra┊gilistic┊expialid│
│00000060│ 6f 63 69 6f 75 73 ┊ ┊ ┊ │ocious ┊ ┊ ┊ │
└────────┴─────────────────────────┴─────────────────────────┴─────────────────────────┴─────────────────────────┴────────┴────────┴────────┴────────┘
"
.to_owned();
let mut output = vec![];
let mut printer: Printer<Vec<u8>> = Printer::new(
&mut output,
false,
true,
true,
BorderStyle::Unicode,
true,
4,
);
printer.print_all(input).unwrap();
let actual_string: &str = str::from_utf8(&output).unwrap();
assert_eq!(actual_string, expected_string)
}
} }
+16 -16
View File
@@ -22,6 +22,7 @@ enum SqueezeState {
pub struct Squeezer { pub struct Squeezer {
state: SqueezeState, state: SqueezeState,
byte: u8, byte: u8,
lsize: u64,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@@ -31,11 +32,8 @@ pub enum SqueezeAction {
Delete, Delete,
} }
/// line size
const LSIZE: u64 = 16;
impl Squeezer { impl Squeezer {
pub fn new(enabled: bool) -> Squeezer { pub fn new(enabled: bool, lsize: u64) -> Squeezer {
Squeezer { Squeezer {
state: if enabled { state: if enabled {
SqueezeState::Probe SqueezeState::Probe
@@ -43,6 +41,7 @@ impl Squeezer {
SqueezeState::Disabled SqueezeState::Disabled
}, },
byte: 0, byte: 0,
lsize,
} }
} }
@@ -53,7 +52,7 @@ impl Squeezer {
} }
let eq = b == self.byte; let eq = b == self.byte;
if i % LSIZE == 0 { if i % self.lsize == 0 {
if !eq { if !eq {
self.state = Probe; self.state = Probe;
} else { } else {
@@ -68,9 +67,9 @@ impl Squeezer {
}; };
} }
} else if !eq { } else if !eq {
if i % LSIZE == 1 { if i % self.lsize == 1 {
self.state = Probe; self.state = Probe;
} else if i % LSIZE != 1 { } else if i % self.lsize != 1 {
self.state = NoSqueeze; self.state = NoSqueeze;
} }
} }
@@ -111,13 +110,14 @@ impl Squeezer {
mod tests { mod tests {
use super::*; use super::*;
const LSIZE: u64 = 16;
const LSIZE_USIZE: usize = LSIZE as usize; const LSIZE_USIZE: usize = LSIZE as usize;
#[test] #[test]
fn three_same_lines() { fn three_same_lines() {
const LINES: usize = 3; const LINES: usize = 3;
let v = vec![0u8; LINES * LSIZE_USIZE]; let v = vec![0u8; LINES * LSIZE_USIZE];
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -144,7 +144,7 @@ mod tests {
fn incomplete_while_squeeze() { fn incomplete_while_squeeze() {
// fourth line only has 12 bytes and should be printed // fourth line only has 12 bytes and should be printed
let v = vec![0u8; 3 * LSIZE_USIZE + 12]; let v = vec![0u8; 3 * LSIZE_USIZE + 12];
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -175,7 +175,7 @@ mod tests {
v.extend(vec![1u8; 16]); v.extend(vec![1u8; 16]);
v.extend(vec![2u8; 16]); v.extend(vec![2u8; 16]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -206,7 +206,7 @@ mod tests {
let mut v = vec![0u8; (LINES - 1) * LSIZE_USIZE]; let mut v = vec![0u8; (LINES - 1) * LSIZE_USIZE];
v.extend(vec![1u8; 16]); v.extend(vec![1u8; 16]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -237,7 +237,7 @@ mod tests {
v.extend(vec![0u8; 8]); v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]); v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -270,7 +270,7 @@ mod tests {
v.extend(vec![0u8; 8]); v.extend(vec![0u8; 8]);
v.extend(vec![1u8; 8]); v.extend(vec![1u8; 8]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -309,7 +309,7 @@ mod tests {
v.extend(vec![20u8; 16]); // print v.extend(vec![20u8; 16]); // print
v.extend(vec![0u8; 12]); // print, only 12 bytes v.extend(vec![0u8; 12]); // print, only 12 bytes
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -351,7 +351,7 @@ mod tests {
v.extend(vec![20u8; 16]); v.extend(vec![20u8; 16]);
v.extend(vec![20u8; 16]); v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
@@ -383,7 +383,7 @@ mod tests {
v.extend(vec![20u8; 15]); v.extend(vec![20u8; 15]);
v.extend(vec![20u8; 16]); v.extend(vec![20u8; 16]);
let mut s = Squeezer::new(true); let mut s = Squeezer::new(true, LSIZE);
// just initialized // just initialized
assert_eq!(s.action(), SqueezeAction::Ignore); assert_eq!(s.action(), SqueezeAction::Ignore);
s.advance(); s.advance();
+1 -1
View File
@@ -1,7 +1,7 @@
use assert_cmd::Command; use assert_cmd::Command;
fn hexyl() -> Command { fn hexyl() -> Command {
let mut cmd = Command::cargo_bin("hexyl").unwrap(); let mut cmd = Command::new(assert_cmd::cargo_bin!("hexyl"));
cmd.current_dir("tests/examples"); cmd.current_dir("tests/examples");
cmd cmd
} }