From 1fdd770093c2f34ea0516aff5909ad0f216a572e Mon Sep 17 00:00:00 2001 From: Sharif Haason Date: Sun, 17 Jul 2022 15:20:00 -0400 Subject: [PATCH] Implement -a and -t for terminal width setting --- Cargo.lock | 129 ++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 1 + src/bin/hexyl.rs | 66 ++++++++++++++++++++++-- 3 files changed, 185 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 909a6f3..a203b1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,27 +75,33 @@ dependencies = [ ] [[package]] -name = "clap" -version = "3.1.18" +name = "cc" +version = "1.0.73" 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 = [ "atty", "bitflags", "clap_lex", "indexmap", - "lazy_static", + "once_cell", "strsim", "termcolor", - "terminal_size", + "terminal_size 0.1.17", "textwrap", ] [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -138,6 +144,27 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "float-cmp" version = "0.9.0" @@ -174,6 +201,7 @@ dependencies = [ "const_format", "libc", "predicates", + "terminal_size 0.2.1", "thiserror", ] @@ -187,6 +215,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "io-lifetimes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" + [[package]] name = "itertools" version = "0.10.3" @@ -208,6 +242,12 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "linux-raw-sys" +version = "0.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" + [[package]] name = "memchr" version = "2.5.0" @@ -229,6 +269,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + [[package]] name = "os_str_bytes" version = "6.0.1" @@ -306,6 +352,20 @@ version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" 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 = "strsim" version = "0.10.0" @@ -342,6 +402,16 @@ dependencies = [ "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]] name = "termtree" version = "0.2.4" @@ -354,7 +424,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" dependencies = [ - "terminal_size", + "terminal_size 0.1.17", ] [[package]] @@ -428,3 +498,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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" diff --git a/Cargo.toml b/Cargo.toml index 4991e32..4e10806 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ atty = "0.2" const_format = "0.2" libc = "0.2" thiserror = "1.0" +terminal_size = "0.2" [dependencies.clap] version = "3" diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index a25ae7f..99e7e28 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -4,7 +4,7 @@ extern crate clap; use std::convert::TryFrom; use std::fs::File; use std::io::{self, prelude::*, SeekFrom}; -use std::num::{NonZeroI64, NonZeroU8}; +use std::num::{NonZeroI64, NonZeroU16, NonZeroU8}; use clap::{crate_name, crate_version, AppSettings, Arg, ColorChoice, Command}; @@ -16,6 +16,8 @@ use const_format::formatcp; use thiserror::Error as ThisError; +use terminal_size::terminal_size; + use hexyl::{BorderStyle, Input, Printer}; const DEFAULT_BLOCK_SIZE: i64 = 512; @@ -160,6 +162,31 @@ fn run() -> Result<(), AnyhowError> { "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(); @@ -278,7 +305,7 @@ fn run() -> Result<(), AnyhowError> { .transpose()? .unwrap_or(0); - let columns = matches + let columns = if let Some(columns) = matches .value_of("columns") .map(|s| { s.parse::().map(u8::from).context(anyhow!( @@ -287,7 +314,40 @@ fn run() -> Result<(), AnyhowError> { )) }) .transpose()? - .unwrap_or(2); + { + columns + } else { + let terminal_width = if let Some(terminal_width) = matches + .value_of("terminal_width") + .map(|s| { + s.parse::().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().expect("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) + .try_into() + .expect("there is a maximum of 255 columns") + } + } else { + 2 + } + }; let stdout = io::stdout(); let mut stdout_lock = stdout.lock();