diff --git a/Cargo.lock b/Cargo.lock index 2c5c07832..bb60331ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,6 +183,18 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.4", + "stable_deref_trait", +] + [[package]] name = "async-channel" version = "1.6.1" @@ -1967,6 +1979,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.4" @@ -2108,6 +2138,15 @@ dependencies = [ "regex 1.4.3", ] +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.9.1" @@ -2126,6 +2165,18 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.4", + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.3.2" @@ -3107,6 +3158,15 @@ dependencies = [ "serial_test", ] +[[package]] +name = "nu-ansi-term" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd69a141e8fdfa5ac882d8b816db2b9ad138ef7e3baa7cb753a9b3789aa8c7e" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "nu-ansi-term" version = "0.30.1" @@ -3158,7 +3218,7 @@ dependencies = [ "lazy_static 1.4.0", "log 0.4.14", "meval", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-command", "nu-data", "nu-engine", @@ -3166,6 +3226,7 @@ dependencies = [ "nu-json", "nu-parser", "nu-plugin", + "nu-pretty-hex", "nu-protocol", "nu-source", "nu-stream", @@ -3177,7 +3238,6 @@ dependencies = [ "num-traits 0.2.14", "parking_lot 0.11.1", "pin-utils", - "pretty-hex", "ptree", "query_interface", "quick-xml 0.21.0", @@ -3258,13 +3318,14 @@ dependencies = [ "md5 0.7.0", "meval", "minus", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-data", "nu-engine", "nu-errors", "nu-json", "nu-parser", "nu-plugin", + "nu-pretty-hex", "nu-protocol", "nu-source", "nu-stream", @@ -3276,7 +3337,6 @@ dependencies = [ "num-traits 0.2.14", "parking_lot 0.11.1", "pin-utils", - "pretty-hex", "ptree", "query_interface", "quick-xml 0.21.0", @@ -3331,7 +3391,7 @@ dependencies = [ "getset", "indexmap", "log 0.4.14", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-errors", "nu-protocol", "nu-source", @@ -3375,7 +3435,7 @@ dependencies = [ "indexmap", "itertools", "log 0.4.14", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-data", "nu-errors", "nu-parser", @@ -3410,7 +3470,7 @@ dependencies = [ "derive-new", "getset", "glob", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-source", "num-bigint 0.3.2", "num-traits 0.2.14", @@ -3473,6 +3533,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "nu-pretty-hex" +version = "0.30.1" +dependencies = [ + "heapless", + "nu-ansi-term 0.29.0", + "rand 0.8.3", +] + [[package]] name = "nu-protocol" version = "0.30.1" @@ -3521,7 +3590,7 @@ dependencies = [ name = "nu-table" version = "0.30.1" dependencies = [ - "nu-ansi-term", + "nu-ansi-term 0.30.1", "regex 1.4.3", "unicode-width", ] @@ -3564,12 +3633,12 @@ dependencies = [ "crossterm 0.19.0", "image 0.22.5", "neso", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-errors", "nu-plugin", + "nu-pretty-hex", "nu-protocol", "nu-source", - "pretty-hex", "rawkey", ] @@ -3755,7 +3824,7 @@ name = "nu_plugin_textview" version = "0.30.1" dependencies = [ "bat", - "nu-ansi-term", + "nu-ansi-term 0.30.1", "nu-data", "nu-errors", "nu-plugin", @@ -4384,12 +4453,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "pretty-hex" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" - [[package]] name = "pretty_env_logger" version = "0.4.0" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index ed37b0dc3..ffaf3a921 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -25,6 +25,7 @@ nu-table = { version = "0.30.1", path = "../nu-table" } nu-test-support = { version = "0.30.1", path = "../nu-test-support" } nu-value-ext = { version = "0.30.1", path = "../nu-value-ext" } nu-ansi-term = { version = "0.30.1", path = "../nu-ansi-term" } +nu-pretty-hex = { version = "0.30.1", path = "../nu-pretty-hex" } Inflector = "0.11" arboard = { version = "1.1.0", optional = true } @@ -67,7 +68,6 @@ num-format = { version = "0.4.0", features = ["with-num-bigint"] } num-traits = "0.2.14" parking_lot = "0.11.1" pin-utils = "0.1.0" -pretty-hex = "0.2.1" ptree = { version = "0.3.1", optional = true } query_interface = "0.3.5" quick-xml = "0.21.0" diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 7a81875c5..af7e401bc 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -24,6 +24,7 @@ nu-table = { version = "0.30.1", path = "../nu-table" } nu-test-support = { version = "0.30.1", path = "../nu-test-support" } nu-value-ext = { version = "0.30.1", path = "../nu-value-ext" } nu-ansi-term = { version = "0.30.1", path = "../nu-ansi-term" } +nu-pretty-hex = { version = "0.30.1", path = "../nu-pretty-hex" } Inflector = "0.11" arboard = { version = "1.1.0", optional = true } @@ -65,7 +66,6 @@ num-format = { version = "0.4.0", features = ["with-num-bigint"] } num-traits = "0.2.14" parking_lot = "0.11.1" pin-utils = "0.1.0" -pretty-hex = "0.2.1" ptree = { version = "0.3.1", optional = true } query_interface = "0.3.5" quick-xml = "0.21.0" diff --git a/crates/nu-command/src/commands.rs b/crates/nu-command/src/commands.rs index d4860b60d..b0a7492a6 100644 --- a/crates/nu-command/src/commands.rs +++ b/crates/nu-command/src/commands.rs @@ -172,6 +172,7 @@ pub(crate) use echo::Echo; pub(crate) use empty::Command as Empty; pub(crate) use if_::If; pub(crate) use into::Into; +pub(crate) use into::IntoBinary; pub(crate) use into::IntoInt; pub(crate) use nu::NuPlugin; pub(crate) use update::Command as Update; diff --git a/crates/nu-command/src/commands/autoview/command.rs b/crates/nu-command/src/commands/autoview/command.rs index 95b24b2f7..76dbb3cb0 100644 --- a/crates/nu-command/src/commands/autoview/command.rs +++ b/crates/nu-command/src/commands/autoview/command.rs @@ -165,7 +165,7 @@ pub fn autoview(context: CommandArgs) -> Result { let result = binary.run_with_actions(command_args)?; let _ = result.collect::>(); } else { - use pretty_hex::*; + use nu_pretty_hex::*; out!("{:?}", b.hex_dump()); } } diff --git a/crates/nu-command/src/commands/default_context.rs b/crates/nu-command/src/commands/default_context.rs index 4a63a6131..d40cb0778 100644 --- a/crates/nu-command/src/commands/default_context.rs +++ b/crates/nu-command/src/commands/default_context.rs @@ -122,6 +122,7 @@ pub fn create_default_context(interactive: bool) -> Result, +} + +impl WholeStreamCommand for SubCommand { + fn name(&self) -> &str { + "into binary" + } + + fn signature(&self) -> Signature { + Signature::build("into binary").rest( + SyntaxShape::ColumnPath, + "column paths to convert to binary (for table input)", + ) + } + + fn usage(&self) -> &str { + "Convert value to a binary primitive" + } + + fn run_with_actions(&self, args: CommandArgs) -> Result { + into_binary(args) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "convert string to a nushell binary primitive", + example: + "echo 'This is a string that is exactly 52 characters long.' | into binary", + result: Some(vec![UntaggedValue::binary( + "This is a string that is exactly 52 characters long." + .to_string() + .as_bytes() + .to_vec(), + ) + .into()]), + }, + Example { + description: "convert a number to a nushell binary primitive", + example: "echo 1 | into binary", + result: Some(vec![ + UntaggedValue::binary(BigInt::from(1).to_bytes_le().1).into() + ]), + }, + Example { + description: "convert a boolean to a nushell binary primitive", + example: "echo $true | into binary", + result: Some(vec![ + UntaggedValue::binary(BigInt::from(1).to_bytes_le().1).into() + ]), + }, + Example { + description: "convert a filesize to a nushell binary primitive", + example: "ls | where name == LICENSE | get size | into binary", + result: None, + }, + Example { + description: "convert a filepath to a nushell binary primitive", + example: "ls | where name == LICENSE | get name | path expand | into binary", + result: None, + }, + Example { + description: "convert a decimal to a nushell binary primitive", + example: "echo 1.234 | into binary", + result: Some(vec![ + UntaggedValue::binary(BigInt::from(1).to_bytes_le().1).into() + ]), + }, + ] + } +} + +fn into_binary(args: CommandArgs) -> Result { + let (Arguments { rest: column_paths }, input) = args.process()?; + + Ok(input + .map(move |v| { + if column_paths.is_empty() { + ReturnSuccess::value(action(&v, v.tag())?) + } else { + let mut ret = v; + for path in &column_paths { + ret = ret.swap_data_by_column_path( + path, + Box::new(move |old| action(old, old.tag())), + )?; + } + + ReturnSuccess::value(ret) + } + }) + .to_action_stream()) +} + +pub fn action(input: &Value, tag: impl Into) -> Result { + let tag = tag.into(); + match &input.value { + UntaggedValue::Primitive(prim) => Ok(UntaggedValue::binary(match prim { + Primitive::Binary(b) => b.to_vec(), + // TODO: Several places here we use Little Endian. We should probably + // query the host to determine if it's Big Endian or Little Endian + Primitive::Int(n_ref) => n_ref.to_bytes_le().1, + Primitive::Decimal(dec) => match dec.to_bigint() { + Some(n) => n.to_bytes_le().1, + None => { + return Err(ShellError::unimplemented( + "failed to convert decimal to int", + )); + } + }, + Primitive::Filesize(a_filesize) => match a_filesize.to_bigint() { + Some(n) => n.to_bytes_le().1, + None => { + return Err(ShellError::unimplemented( + "failed to convert filesize to bigint", + )); + } + }, + Primitive::String(a_string) => a_string.as_bytes().to_vec(), + Primitive::Boolean(a_bool) => match a_bool { + false => BigInt::from(0).to_bytes_le().1, + true => BigInt::from(1).to_bytes_le().1, + }, + Primitive::Date(a_date) => a_date.format("%c").to_string().as_bytes().to_vec(), + Primitive::FilePath(a_filepath) => a_filepath + .as_path() + .display() + .to_string() + .as_bytes() + .to_vec(), + _ => { + return Err(ShellError::unimplemented( + "'into int' for non-numeric primitives", + )) + } + }) + .into_value(&tag)), + UntaggedValue::Row(_) => Err(ShellError::labeled_error( + "specify column name to use, with 'into int COLUMN'", + "found table", + tag, + )), + _ => Err(ShellError::unimplemented("'into int' for unsupported type")), + } +} + +#[cfg(test)] +mod tests { + use super::ShellError; + use super::SubCommand; + + #[test] + fn examples_work_as_expected() -> Result<(), ShellError> { + use crate::examples::test as test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/commands/into/mod.rs b/crates/nu-command/src/commands/into/mod.rs index 9e53deb25..b4a88211b 100644 --- a/crates/nu-command/src/commands/into/mod.rs +++ b/crates/nu-command/src/commands/into/mod.rs @@ -1,5 +1,7 @@ +mod binary; mod command; mod int; +pub use binary::SubCommand as IntoBinary; pub use command::Command as Into; pub use int::SubCommand as IntoInt; diff --git a/crates/nu-command/src/commands/to_html.rs b/crates/nu-command/src/commands/to_html.rs index b790a2958..38cca5a96 100644 --- a/crates/nu-command/src/commands/to_html.rs +++ b/crates/nu-command/src/commands/to_html.rs @@ -435,7 +435,7 @@ fn html_value(value: &Value) -> String { output_string.push_str("\">"); } _ => { - let output = pretty_hex::pretty_hex(&b); + let output = nu_pretty_hex::pretty_hex(&b); output_string.push_str("
");
                             output_string.push_str(&output);
@@ -444,7 +444,7 @@ fn html_value(value: &Value) -> String {
                     }
                 }
                 _ => {
-                    let output = pretty_hex::pretty_hex(&b);
+                    let output = nu_pretty_hex::pretty_hex(&b);
 
                     output_string.push_str("
");
                     output_string.push_str(&output);
diff --git a/crates/nu-pretty-hex/Cargo.lock b/crates/nu-pretty-hex/Cargo.lock
new file mode 100644
index 000000000..1bfc1820e
--- /dev/null
+++ b/crates/nu-pretty-hex/Cargo.lock
@@ -0,0 +1,201 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "as-slice"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
+dependencies = [
+ "generic-array 0.12.4",
+ "generic-array 0.13.3",
+ "generic-array 0.14.4",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hash32"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "heapless"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422"
+dependencies = [
+ "as-slice",
+ "generic-array 0.14.4",
+ "hash32",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bd69a141e8fdfa5ac882d8b816db2b9ad138ef7e3baa7cb753a9b3789aa8c7e"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "nu-pretty-hex"
+version = "0.2.1"
+dependencies = [
+ "heapless",
+ "nu-ansi-term",
+ "rand",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "typenum"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/crates/nu-pretty-hex/Cargo.toml b/crates/nu-pretty-hex/Cargo.toml
new file mode 100644
index 000000000..74570a213
--- /dev/null
+++ b/crates/nu-pretty-hex/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+authors = [
+    "Andrei Volnin ",
+    "The Nu Project Contributors"
+    ]
+description = "Pretty hex dump of bytes slice in the common style."
+edition = "2018"
+license = "MIT"
+name = "nu-pretty-hex"
+version = "0.30.1"
+
+[lib]
+doctest = false
+name = "nu_pretty_hex"
+path = "src/lib.rs"
+
+[[bin]]
+name = "nu_pretty_hex"
+path = "src/main.rs"
+
+[dependencies]
+nu-ansi-term = "0.29.0"
+rand = "0.8.3"
+
+[dev-dependencies]
+heapless = "0.6.1"
+
+# [features]
+# default = ["alloc"]
+# alloc = []
diff --git a/crates/nu-pretty-hex/LICENSE b/crates/nu-pretty-hex/LICENSE
new file mode 100644
index 000000000..f70169fa2
--- /dev/null
+++ b/crates/nu-pretty-hex/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Andrei Volnin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/crates/nu-pretty-hex/README.md b/crates/nu-pretty-hex/README.md
new file mode 100644
index 000000000..7c640cc28
--- /dev/null
+++ b/crates/nu-pretty-hex/README.md
@@ -0,0 +1,81 @@
+# nu-pretty-hex
+
+An update of prett-hex to make it prettier
+
+[![crates.io](https://img.shields.io/crates/v/pretty-hex.svg)](https://crates.io/crates/pretty-hex)
+[![docs.rs](https://docs.rs/pretty-hex/badge.svg)](https://docs.rs/pretty-hex)
+
+A Rust library providing pretty hex dump.
+
+A `simple_hex()` way renders one-line hex dump, a `pretty_hex()` way renders
+columned multi-line hex dump with addressing and ASCII representation.
+A `config_hex()` way renders hex dump in specified format.
+
+## Inspiration
+
+[Hexed](https://github.com/adolfohw/hexed) \
+[Hexyl](https://github.com/sharkdp/hexyl) \
+[Pretty-hex](https://github.com/wolandr/pretty-hex)
+
+## Example of `simple_hex()`
+
+```rust
+use pretty_hex::*;
+
+let v = vec![222, 173, 190, 239, 202, 254, 32, 24];
+assert_eq!(simple_hex(&v), format!("{}", v.hex_dump()));
+
+println!("{}", v.hex_dump());
+
+```
+
+Output:
+
+```text
+de ad be ef  ca fe 20 18
+```
+
+## Example of `pretty_hex()`
+
+```rust
+use pretty_hex::*;
+
+let v: &[u8] = &random::<[u8;30]>();
+assert_eq!(pretty_hex(&v), format!("{:?}", v.hex_dump()));
+
+println!("{:?}", v.hex_dump());
+```
+
+Output:
+
+```text
+Length: 30 (0x1e) bytes
+0000:   6b 4e 1a c3  af 03 d2 1e  7e 73 ba c8  bd 84 0f 83   kN......~s......
+0010:   89 d5 cf 90  23 67 4b 48  db b1 bc 35  bf ee         ....#gKH...5..
+```
+
+## Example of `config_hex()`
+
+```rust
+use pretty_hex::*;
+
+let cfg = HexConfig {title: false, width: 8, group: 0, ..HexConfig::default() };
+
+let v = &include_bytes!("data");
+assert_eq!(config_hex(&v, cfg), format!("{:?}", v.hex_conf(cfg)));
+
+println!("{:?}", v.hex_conf(cfg));
+```
+
+Output:
+
+```text
+0000:   6b 4e 1a c3 af 03 d2 1e   kN......
+0008:   7e 73 ba c8 bd 84 0f 83   ~s......
+0010:   89 d5 cf 90 23 67 4b 48   ....#gKH
+0018:   db b1 bc 35 bf ee         ...5..
+```
+
+---
+
+Inspired by [haskell's pretty-hex](https://hackage.haskell.org/package/pretty-hex-1.0).
diff --git a/crates/nu-pretty-hex/src/lib.rs b/crates/nu-pretty-hex/src/lib.rs
new file mode 100644
index 000000000..d34542a7e
--- /dev/null
+++ b/crates/nu-pretty-hex/src/lib.rs
@@ -0,0 +1,66 @@
+// #![no_std]
+
+//! A Rust library providing pretty hex dump.
+//!
+//! A `simple_hex()` way renders one-line hex dump, and a `pretty_hex()` way renders
+//! columned multi-line hex dump with addressing and ASCII representation.
+//! A `config_hex()` way renders hex dump in specified format.
+//!
+//! ## Example of `simple_hex()`
+//! ```
+//! use pretty_hex::*;
+//!
+//! let v = vec![222, 173, 190, 239, 202, 254, 32, 24];
+//! # #[cfg(feature = "alloc")]
+//! assert_eq!(simple_hex(&v), format!("{}", v.hex_dump()));
+//!
+//! println!("{}", v.hex_dump());
+//! ```
+//! Output:
+//!
+//! ```text
+//! de ad be ef  ca fe 20 18
+//! ```
+//! ## Example of `pretty_hex()`
+//! ```
+//! use pretty_hex::*;
+//!
+//! let v = &include_bytes!("../tests/data");
+//! # #[cfg(feature = "alloc")]
+//! assert_eq!(pretty_hex(&v), format!("{:?}", v.hex_dump()));
+//!
+//! println!("{:?}", v.hex_dump());
+//! ```
+//! Output:
+//!
+//! ```text
+//! Length: 30 (0x1e) bytes
+//! 0000:   6b 4e 1a c3  af 03 d2 1e  7e 73 ba c8  bd 84 0f 83   kN......~s......
+//! 0010:   89 d5 cf 90  23 67 4b 48  db b1 bc 35  bf ee         ....#gKH...5..
+//! ```
+//! ## Example of `config_hex()`
+//! ```
+//! use pretty_hex::*;
+//!
+//! let cfg = HexConfig {title: false, width: 8, group: 0, ..HexConfig::default() };
+//!
+//! let v = &include_bytes!("../tests/data");
+//! # #[cfg(feature = "alloc")]
+//! assert_eq!(config_hex(&v, cfg), format!("{:?}", v.hex_conf(cfg)));
+//!
+//! println!("{:?}", v.hex_conf(cfg));
+//! ```
+//! Output:
+//!
+//! ```text
+//! 0000:   6b 4e 1a c3 af 03 d2 1e   kN......
+//! 0008:   7e 73 ba c8 bd 84 0f 83   ~s......
+//! 0010:   89 d5 cf 90 23 67 4b 48   ....#gKH
+//! 0018:   db b1 bc 35 bf ee         ...5..
+//! ```
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+mod pretty_hex;
+pub use pretty_hex::*;
diff --git a/crates/nu-pretty-hex/src/main.rs b/crates/nu-pretty-hex/src/main.rs
new file mode 100644
index 000000000..4156cb5c2
--- /dev/null
+++ b/crates/nu-pretty-hex/src/main.rs
@@ -0,0 +1,50 @@
+use nu_pretty_hex::*;
+
+fn main() {
+    let config = HexConfig {
+        title: true,
+        ascii: true,
+        width: 16,
+        group: 4,
+        chunk: 1,
+        skip: Some(10),
+        // length: Some(5),
+        // length: None,
+        length: Some(50),
+    };
+
+    let my_string = "Darren Schroeder 😉";
+    println!("ConfigHex\n{}\n", config_hex(&my_string, config));
+    println!("SimpleHex\n{}\n", simple_hex(&my_string));
+    println!("PrettyHex\n{}\n", pretty_hex(&my_string));
+    println!("ConfigHex\n{}\n", config_hex(&my_string, config));
+
+    // let mut my_str = String::new();
+    // for x in 0..256 {
+    //     my_str.push(x as u8);
+    // }
+    let mut v: Vec = vec![];
+    for x in 0..=127 {
+        v.push(x);
+    }
+    let my_str = String::from_utf8_lossy(&v[..]);
+
+    println!("First128\n{}\n", pretty_hex(&my_str.as_bytes()));
+    println!(
+        "First128-Param\n{}\n",
+        config_hex(&my_str.as_bytes(), config)
+    );
+
+    let mut r_str = String::new();
+    for _ in 0..=127 {
+        r_str.push(rand::random::() as char);
+    }
+
+    println!("Random127\n{}\n", pretty_hex(&r_str));
+}
+
+//chunk 0 44617272656e20536368726f65646572   Darren Schroeder
+//chunk 1 44 61 72 72  65 6e 20 53  63 68 72 6f  65 64 65 72   Darren Schroeder
+//chunk 2 461 7272 656e 2053  6368 726f 6564 6572   Darren Schroeder
+//chunk 3 46172 72656e 205363 68726f  656465 72   Darren Schroeder
+//chunk 4 44617272 656e2053 6368726f 65646572   Darren Schroeder
diff --git a/crates/nu-pretty-hex/src/pretty_hex.rs b/crates/nu-pretty-hex/src/pretty_hex.rs
new file mode 100644
index 000000000..32e4cea10
--- /dev/null
+++ b/crates/nu-pretty-hex/src/pretty_hex.rs
@@ -0,0 +1,305 @@
+use core::primitive::str;
+use core::{default::Default, fmt};
+use nu_ansi_term::{Color, Style};
+
+/// Returns a one-line hexdump of `source` grouped in default format without header
+/// and ASCII column.
+pub fn simple_hex>(source: &T) -> String {
+    let mut writer = String::new();
+    hex_write(&mut writer, source, HexConfig::simple(), None).unwrap_or(());
+    writer
+}
+
+/// Dump `source` as hex octets in default format without header and ASCII column to the `writer`.
+pub fn simple_hex_write(writer: &mut W, source: &T) -> fmt::Result
+where
+    T: AsRef<[u8]>,
+    W: fmt::Write,
+{
+    hex_write(writer, source, HexConfig::simple(), None)
+}
+
+/// Return a multi-line hexdump in default format complete with addressing, hex digits,
+/// and ASCII representation.
+pub fn pretty_hex>(source: &T) -> String {
+    let mut writer = String::new();
+    hex_write(&mut writer, source, HexConfig::default(), Some(true)).unwrap_or(());
+    writer
+}
+
+/// Write multi-line hexdump in default format complete with addressing, hex digits,
+/// and ASCII representation to the writer.
+pub fn pretty_hex_write(writer: &mut W, source: &T) -> fmt::Result
+where
+    T: AsRef<[u8]>,
+    W: fmt::Write,
+{
+    hex_write(writer, source, HexConfig::default(), Some(true))
+}
+
+/// Return a hexdump of `source` in specified format.
+pub fn config_hex>(source: &T, cfg: HexConfig) -> String {
+    let mut writer = String::new();
+    hex_write(&mut writer, source, cfg, Some(true)).unwrap_or(());
+    writer
+}
+
+/// Configuration parameters for hexdump.
+#[derive(Clone, Copy, Debug)]
+pub struct HexConfig {
+    /// Write first line header with data length.
+    pub title: bool,
+    /// Append ASCII representation column.
+    pub ascii: bool,
+    /// Source bytes per row. 0 for single row without address prefix.
+    pub width: usize,
+    /// Chunks count per group. 0 for single group (column).
+    pub group: usize,
+    /// Source bytes per chunk (word). 0 for single word.
+    pub chunk: usize,
+    /// Bytes from 0 to skip
+    pub skip: Option,
+    /// Length to return
+    pub length: Option,
+}
+
+/// Default configuration with `title`, `ascii`, 16 source bytes `width` grouped to 4 separate
+/// hex bytes. Using in `pretty_hex`, `pretty_hex_write` and `fmt::Debug` implementation.
+impl Default for HexConfig {
+    fn default() -> HexConfig {
+        HexConfig {
+            title: true,
+            ascii: true,
+            width: 16,
+            group: 4,
+            chunk: 1,
+            skip: None,
+            length: None,
+        }
+    }
+}
+
+impl HexConfig {
+    /// Returns configuration for `simple_hex`, `simple_hex_write` and `fmt::Display` implementation.
+    pub fn simple() -> Self {
+        HexConfig::default().to_simple()
+    }
+
+    fn delimiter(&self, i: usize) -> &'static str {
+        if i > 0 && self.chunk > 0 && i % self.chunk == 0 {
+            if self.group > 0 && i % (self.group * self.chunk) == 0 {
+                "  "
+            } else {
+                " "
+            }
+        } else {
+            ""
+        }
+    }
+
+    fn to_simple(self) -> Self {
+        HexConfig {
+            title: false,
+            ascii: false,
+            width: 0,
+            ..self
+        }
+    }
+}
+
+fn categorize_byte(byte: &u8) -> (Style, Option) {
+    // This section is here so later we can configure these items
+    let null_char_style = Style::default().fg(Color::Fixed(242));
+    let null_char = Some('0');
+    let ascii_printable_style = Style::default().fg(Color::Cyan).bold();
+    let ascii_printable = None;
+    let ascii_space_style = Style::default().fg(Color::Green).bold();
+    let ascii_space = Some(' ');
+    let ascii_white_space_style = Style::default().fg(Color::Green).bold();
+    let ascii_white_space = Some('_');
+    let ascii_other_style = Style::default().fg(Color::Purple).bold();
+    let ascii_other = Some('•');
+    let non_ascii_style = Style::default().fg(Color::Yellow).bold();
+    let non_ascii = Some('×'); // or Some('.')
+
+    if byte == &0 {
+        (null_char_style, null_char)
+    } else if byte.is_ascii_graphic() {
+        (ascii_printable_style, ascii_printable)
+    } else if byte.is_ascii_whitespace() {
+        // 0x20 == 32 decimal - replace with a real space
+        if byte == &32 {
+            (ascii_space_style, ascii_space)
+        } else {
+            (ascii_white_space_style, ascii_white_space)
+        }
+    } else if byte.is_ascii() {
+        (ascii_other_style, ascii_other)
+    } else {
+        (non_ascii_style, non_ascii)
+    }
+}
+
+/// Write hex dump in specified format.
+pub fn hex_write(
+    writer: &mut W,
+    source: &T,
+    cfg: HexConfig,
+    with_color: Option,
+) -> fmt::Result
+where
+    T: AsRef<[u8]>,
+    W: fmt::Write,
+{
+    let use_color = with_color.unwrap_or(false);
+
+    if source.as_ref().is_empty() {
+        return Ok(());
+    }
+
+    let amount = match cfg.length {
+        Some(len) => len,
+        None => source.as_ref().len(),
+    };
+
+    let skip = cfg.skip.unwrap_or(0);
+
+    let source_part_vec: Vec = source
+        .as_ref()
+        .iter()
+        .skip(skip)
+        .take(amount)
+        .map(|x| *x as u8)
+        .collect();
+
+    let source_part = String::from_utf8_lossy(&source_part_vec[..]);
+
+    if cfg.title {
+        if use_color {
+            writeln!(
+                writer,
+                "Length: {0} (0x{0:x}) bytes | {1}printable {2}whitespace {3}ascii_other {4}non_ascii{5}",
+                source_part.as_bytes().as_ref().len(),
+                Style::default().fg(Color::Cyan).bold().prefix(),
+                Style::default().fg(Color::Green).bold().prefix(),
+                Style::default().fg(Color::Purple).bold().prefix(),
+                Style::default().fg(Color::Yellow).bold().prefix(),
+                Style::default().fg(Color::Yellow).suffix()
+            )?;
+        } else {
+            writeln!(
+                writer,
+                "Length: {0} (0x{0:x}) bytes",
+                source_part.as_bytes().as_ref().len(),
+            )?;
+        }
+    }
+
+    let lines = source_part.as_bytes().as_ref().chunks(if cfg.width > 0 {
+        cfg.width
+    } else {
+        source_part.as_bytes().as_ref().len()
+    });
+
+    let lines_len = lines.len();
+
+    for (i, row) in lines.enumerate() {
+        if cfg.width > 0 {
+            let style = Style::default().fg(Color::Cyan);
+            if use_color {
+                write!(
+                    writer,
+                    "{}{:08x}{}:   ",
+                    style.prefix(),
+                    i * cfg.width + skip,
+                    style.suffix()
+                )?;
+            } else {
+                write!(writer, "{:08x}:   ", i * cfg.width + skip,)?;
+            }
+        }
+        for (i, x) in row.as_ref().iter().enumerate() {
+            if use_color {
+                let (style, _char) = categorize_byte(x);
+                write!(
+                    writer,
+                    "{}{}{:02x}{}",
+                    cfg.delimiter(i),
+                    style.prefix(),
+                    x,
+                    style.suffix()
+                )?;
+            } else {
+                write!(writer, "{}{:02x}", cfg.delimiter(i), x,)?;
+            }
+        }
+        if cfg.ascii {
+            for j in row.len()..cfg.width {
+                write!(writer, "{}  ", cfg.delimiter(j))?;
+            }
+            write!(writer, "   ")?;
+            for x in row {
+                let (style, a_char) = categorize_byte(x);
+                let replacement_char = match a_char {
+                    Some(c) => c,
+                    None => *x as char,
+                };
+                if use_color {
+                    write!(
+                        writer,
+                        "{}{}{}",
+                        style.prefix(),
+                        replacement_char,
+                        style.suffix()
+                    )?;
+                } else {
+                    write!(writer, "{}", replacement_char,)?;
+                }
+            }
+        }
+        if i + 1 < lines_len {
+            writeln!(writer)?;
+        }
+    }
+    Ok(())
+}
+
+/// Reference wrapper for use in arguments formatting.
+pub struct Hex<'a, T: 'a>(&'a T, HexConfig);
+
+impl<'a, T: 'a + AsRef<[u8]>> fmt::Display for Hex<'a, T> {
+    /// Formats the value by `simple_hex_write` using the given formatter.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        hex_write(f, self.0, self.1.to_simple(), None)
+    }
+}
+
+impl<'a, T: 'a + AsRef<[u8]>> fmt::Debug for Hex<'a, T> {
+    /// Formats the value by `pretty_hex_write` using the given formatter.
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        hex_write(f, self.0, self.1, None)
+    }
+}
+
+/// Allows generates hex dumps to a formatter.
+pub trait PrettyHex: Sized {
+    /// Wrap self reference for use in `std::fmt::Display` and `std::fmt::Debug`
+    /// formatting as hex dumps.
+    fn hex_dump(&self) -> Hex;
+
+    /// Wrap self reference for use in `std::fmt::Display` and `std::fmt::Debug`
+    /// formatting as hex dumps in specified format.
+    fn hex_conf(&self, cfg: HexConfig) -> Hex;
+}
+
+impl PrettyHex for T
+where
+    T: AsRef<[u8]>,
+{
+    fn hex_dump(&self) -> Hex {
+        Hex(self, HexConfig::default())
+    }
+    fn hex_conf(&self, cfg: HexConfig) -> Hex {
+        Hex(self, cfg)
+    }
+}
diff --git a/crates/nu-pretty-hex/tests/256.txt b/crates/nu-pretty-hex/tests/256.txt
new file mode 100644
index 000000000..0e08e874f
--- /dev/null
+++ b/crates/nu-pretty-hex/tests/256.txt
@@ -0,0 +1,17 @@
+Length: 256 (0x100) bytes
+0000:   00 01 02 03  04 05 06 07  08 09 0a 0b  0c 0d 0e 0f   ................
+0010:   10 11 12 13  14 15 16 17  18 19 1a 1b  1c 1d 1e 1f   ................
+0020:   20 21 22 23  24 25 26 27  28 29 2a 2b  2c 2d 2e 2f    !"#$%&'()*+,-./
+0030:   30 31 32 33  34 35 36 37  38 39 3a 3b  3c 3d 3e 3f   0123456789:;<=>?
+0040:   40 41 42 43  44 45 46 47  48 49 4a 4b  4c 4d 4e 4f   @ABCDEFGHIJKLMNO
+0050:   50 51 52 53  54 55 56 57  58 59 5a 5b  5c 5d 5e 5f   PQRSTUVWXYZ[\]^_
+0060:   60 61 62 63  64 65 66 67  68 69 6a 6b  6c 6d 6e 6f   `abcdefghijklmno
+0070:   70 71 72 73  74 75 76 77  78 79 7a 7b  7c 7d 7e 7f   pqrstuvwxyz{|}~.
+0080:   80 81 82 83  84 85 86 87  88 89 8a 8b  8c 8d 8e 8f   ................
+0090:   90 91 92 93  94 95 96 97  98 99 9a 9b  9c 9d 9e 9f   ................
+00a0:   a0 a1 a2 a3  a4 a5 a6 a7  a8 a9 aa ab  ac ad ae af   ................
+00b0:   b0 b1 b2 b3  b4 b5 b6 b7  b8 b9 ba bb  bc bd be bf   ................
+00c0:   c0 c1 c2 c3  c4 c5 c6 c7  c8 c9 ca cb  cc cd ce cf   ................
+00d0:   d0 d1 d2 d3  d4 d5 d6 d7  d8 d9 da db  dc dd de df   ................
+00e0:   e0 e1 e2 e3  e4 e5 e6 e7  e8 e9 ea eb  ec ed ee ef   ................
+00f0:   f0 f1 f2 f3  f4 f5 f6 f7  f8 f9 fa fb  fc fd fe ff   ................
\ No newline at end of file
diff --git a/crates/nu-pretty-hex/tests/data b/crates/nu-pretty-hex/tests/data
new file mode 100644
index 000000000..998d80f71
--- /dev/null
+++ b/crates/nu-pretty-hex/tests/data
@@ -0,0 +1 @@
+kNï~sȽϐ#gKH۱5
\ No newline at end of file
diff --git a/crates/nu-pretty-hex/tests/tests.rs b/crates/nu-pretty-hex/tests/tests.rs
new file mode 100644
index 000000000..fe1ed8ac6
--- /dev/null
+++ b/crates/nu-pretty-hex/tests/tests.rs
@@ -0,0 +1,175 @@
+// #![no_std]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+extern crate nu_pretty_hex;
+
+#[cfg(feature = "alloc")]
+use alloc::{format, string::String, vec, vec::Vec};
+use nu_pretty_hex::*;
+
+#[cfg(feature = "alloc")]
+#[test]
+fn test_simple() {
+    let bytes: Vec = (0..16).collect();
+    let expected = "00 01 02 03  04 05 06 07  08 09 0a 0b  0c 0d 0e 0f";
+    assert_eq!(expected, simple_hex(&bytes));
+    assert_eq!(expected, format!("{}", bytes.hex_dump()));
+    assert_eq!(simple_hex(&bytes), config_hex(&bytes, HexConfig::simple()));
+
+    let mut have = String::new();
+    simple_hex_write(&mut have, &bytes).unwrap();
+    assert_eq!(expected, have);
+
+    let str = "string";
+    let string: String = String::from("string");
+    let slice: &[u8] = &[0x73, 0x74, 0x72, 0x69, 0x6e, 0x67];
+    assert_eq!(simple_hex(&str), "73 74 72 69  6e 67");
+    assert_eq!(simple_hex(&str), simple_hex(&string));
+    assert_eq!(simple_hex(&str), simple_hex(&slice));
+
+    assert!(simple_hex(&vec![]).is_empty());
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn test_pretty() {
+    let bytes: Vec = (0..256).map(|x| x as u8).collect();
+    let want = include_str!("256.txt");
+
+    let mut hex = String::new();
+    pretty_hex_write(&mut hex, &bytes).unwrap();
+    assert_eq!(want, hex);
+    assert_eq!(want, format!("{:?}", bytes.hex_dump()));
+    assert_eq!(want, pretty_hex(&bytes));
+    assert_eq!(want, config_hex(&bytes, HexConfig::default()));
+
+    assert_eq!("Length: 0 (0x0) bytes\n", pretty_hex(&vec![]));
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn test_config() {
+    let cfg = HexConfig {
+        title: false,
+        ascii: false,
+        width: 0,
+        group: 0,
+        chunk: 0,
+    };
+    assert!(config_hex(&vec![], cfg).is_empty());
+    assert_eq!("2425262728", config_hex(&"$%&'(", cfg));
+
+    let v = include_bytes!("data");
+    let cfg = HexConfig {
+        title: false,
+        group: 8,
+        ..HexConfig::default()
+    };
+    let hex = "0000:   6b 4e 1a c3 af 03 d2 1e  7e 73 ba c8 bd 84 0f 83   kN......~s......\n\
+         0010:   89 d5 cf 90 23 67 4b 48  db b1 bc 35 bf ee         ....#gKH...5..";
+    assert_eq!(hex, config_hex(&v, cfg));
+    assert_eq!(hex, format!("{:?}", v.hex_conf(cfg)));
+    let mut str = String::new();
+    hex_write(&mut str, v, cfg).unwrap();
+    assert_eq!(hex, str);
+
+    assert_eq!(
+        config_hex(
+            &v,
+            HexConfig {
+                ascii: false,
+                ..cfg
+            }
+        ),
+        "0000:   6b 4e 1a c3 af 03 d2 1e  7e 73 ba c8 bd 84 0f 83\n\
+         0010:   89 d5 cf 90 23 67 4b 48  db b1 bc 35 bf ee"
+    );
+
+    assert_eq!(
+        config_hex(
+            &v,
+            HexConfig {
+                ascii: false,
+                group: 4,
+                chunk: 2,
+                ..cfg
+            }
+        ),
+        "0000:   6b4e 1ac3 af03 d21e  7e73 bac8 bd84 0f83\n\
+         0010:   89d5 cf90 2367 4b48  dbb1 bc35 bfee"
+    );
+
+    let v: Vec = (0..21).collect();
+    let want = r##"Length: 21 (0x15) bytes
+0000:   00 01 02 03  04 05 06 07  08 09 0a 0b  0c 0d 0e 0f   ................
+0010:   10 11 12 13  14                                      ....."##;
+    assert_eq!(want, pretty_hex(&v));
+
+    let v: Vec = (0..13).collect();
+    assert_eq!(
+        config_hex(
+            &v,
+            HexConfig {
+                title: false,
+                ascii: true,
+                width: 11,
+                group: 2,
+                chunk: 3
+            }
+        ),
+        "0000:   000102 030405  060708 090a   ...........\n\
+         000b:   0b0c                         .."
+    );
+
+    let v: Vec = (0..19).collect();
+    assert_eq!(
+        config_hex(
+            &v,
+            HexConfig {
+                title: false,
+                ascii: true,
+                width: 16,
+                group: 3,
+                chunk: 3
+            }
+        ),
+        "0000:   000102 030405 060708  090a0b 0c0d0e 0f   ................\n\
+         0010:   101112                                   ..."
+    );
+
+    let cfg = HexConfig {
+        title: false,
+        group: 0,
+        ..HexConfig::default()
+    };
+    assert_eq!(
+        format!("{:?}", v.hex_conf(cfg)),
+        "0000:   00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f   ................\n\
+         0010:   10 11 12                                          ..."
+    );
+    assert_eq!(
+        format!("{}", v.hex_conf(cfg)),
+        "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12"
+    );
+}
+
+// This test case checks that hex_write works even without the alloc crate.
+// Decorators to this function like simple_hex_write or PrettyHex::hex_dump()
+// will be tested when the alloc feature is selected because it feels quite
+// cumbersome to set up these tests without the comodity from `alloc`.
+#[test]
+fn test_hex_write_with_simple_config() {
+    let config = HexConfig::simple();
+    let bytes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+    let expected =
+        core::str::from_utf8(b"00 01 02 03  04 05 06 07  08 09 0a 0b  0c 0d 0e 0f").unwrap();
+    // let expected =
+    //     "\u{1b}[38;5;242m00\u{1b}[0m \u{1b}[1;35m01\u{1b}[0m \u{1b}[1;35m02\u{1b}[0m \u{1b}[1;";
+    let mut buffer = heapless::Vec::::new();
+
+    hex_write(&mut buffer, &bytes, config, None).unwrap();
+
+    let have = core::str::from_utf8(&buffer).unwrap();
+    assert_eq!(expected, have);
+}
diff --git a/crates/nu_plugin_binaryview/Cargo.toml b/crates/nu_plugin_binaryview/Cargo.toml
index 59e09c304..c736a2df7 100644
--- a/crates/nu_plugin_binaryview/Cargo.toml
+++ b/crates/nu_plugin_binaryview/Cargo.toml
@@ -18,7 +18,7 @@ nu-plugin = { path = "../nu-plugin", version = "0.30.1" }
 nu-protocol = { path = "../nu-protocol", version = "0.30.1" }
 nu-source = { path = "../nu-source", version = "0.30.1" }
 nu-ansi-term = { version = "0.30.1", path = "../nu-ansi-term" }
-pretty-hex = "0.2.1"
+nu-pretty-hex = { version = "0.30.1", path = "../nu-pretty-hex" }
 rawkey = "0.1.3"
 
 [build-dependencies]
diff --git a/crates/nu_plugin_binaryview/src/binaryview.rs b/crates/nu_plugin_binaryview/src/binaryview.rs
index c8eee06d0..2b6567454 100644
--- a/crates/nu_plugin_binaryview/src/binaryview.rs
+++ b/crates/nu_plugin_binaryview/src/binaryview.rs
@@ -1,7 +1,7 @@
 use crossterm::{style::Attribute, ExecutableCommand};
-use nu_protocol::outln;
+use nu_pretty_hex::*;
+use nu_protocol::{outln, Value};
 use nu_source::AnchorLocation;
-use pretty_hex::*;
 
 #[derive(Default)]
 pub struct BinaryView;
@@ -16,6 +16,8 @@ pub fn view_binary(
     b: &[u8],
     source: Option<&AnchorLocation>,
     lores_mode: bool,
+    skip: Option<&Value>,
+    length: Option<&Value>,
 ) -> Result<(), Box> {
     if b.len() > 3 {
         if let (0x4e, 0x45, 0x53) = (b[0], b[1], b[2]) {
@@ -23,7 +25,8 @@ pub fn view_binary(
             return Ok(());
         }
     }
-    view_contents(b, source, lores_mode)?;
+
+    view_contents(b, source, lores_mode, skip, length)?;
     Ok(())
 }
 
@@ -207,7 +210,29 @@ pub fn view_contents(
     buffer: &[u8],
     _source: Option<&AnchorLocation>,
     lores_mode: bool,
+    skip: Option<&Value>,
+    length: Option<&Value>,
 ) -> Result<(), Box> {
+    let skip_bytes = match skip {
+        Some(s) => Some(s.as_usize().unwrap_or(0)),
+        None => None,
+    };
+
+    let num_bytes = match length {
+        Some(b) => Some(b.as_usize().unwrap_or(0)),
+        None => None,
+    };
+
+    let config = HexConfig {
+        title: true,
+        ascii: true,
+        width: 16,
+        group: 4,
+        chunk: 1,
+        skip: skip_bytes,
+        length: num_bytes,
+    };
+
     let mut raw_image_buffer = load_from_png_buffer(buffer);
 
     if raw_image_buffer.is_err() {
@@ -216,7 +241,7 @@ pub fn view_contents(
 
     if raw_image_buffer.is_err() {
         //Not yet supported
-        outln!("{:?}", buffer.hex_dump());
+        outln!("{}", config_hex(&buffer, config));
         return Ok(());
     }
     let raw_image_buffer = raw_image_buffer?;
@@ -270,7 +295,8 @@ pub fn view_contents(
         }
         _ => {
             //Not yet supported
-            outln!("{:?}", buffer.hex_dump());
+            // outln!("{:?}", buffer.hex_dump());
+            outln!("{}", config_hex(&buffer, config));
             return Ok(());
         }
     }
diff --git a/crates/nu_plugin_binaryview/src/nu/mod.rs b/crates/nu_plugin_binaryview/src/nu/mod.rs
index 091cc0c25..b491b26d0 100644
--- a/crates/nu_plugin_binaryview/src/nu/mod.rs
+++ b/crates/nu_plugin_binaryview/src/nu/mod.rs
@@ -1,6 +1,6 @@
 use nu_errors::ShellError;
 use nu_plugin::Plugin;
-use nu_protocol::{CallInfo, Primitive, Signature, UntaggedValue, Value};
+use nu_protocol::{CallInfo, Primitive, Signature, SyntaxShape, UntaggedValue, Value};
 
 use crate::binaryview::view_binary;
 use crate::BinaryView;
@@ -9,14 +9,29 @@ impl Plugin for BinaryView {
     fn config(&mut self) -> Result {
         Ok(Signature::build("binaryview")
             .desc("Autoview of binary data.")
-            .switch("lores", "use low resolution output mode", Some('l')))
+            .switch("lores", "use low resolution output mode", Some('l'))
+            .named(
+                "skip",
+                SyntaxShape::Int,
+                "skip x number of bytes",
+                Some('s'),
+            )
+            .named(
+                "bytes",
+                SyntaxShape::Int,
+                "show y number of bytes",
+                Some('b'),
+            ))
     }
 
     fn sink(&mut self, call_info: CallInfo, input: Vec) {
         for v in input {
             let value_anchor = v.anchor();
             if let UntaggedValue::Primitive(Primitive::Binary(b)) = &v.value {
-                let _ = view_binary(&b, value_anchor.as_ref(), call_info.args.has("lores"));
+                let low_res = call_info.args.has("lores");
+                let skip = call_info.args.get("skip");
+                let length = call_info.args.get("bytes");
+                let _ = view_binary(&b, value_anchor.as_ref(), low_res, skip, length);
             }
         }
     }