26 Commits
Author SHA1 Message Date
sharkdp 7e46a5d788 Bump version 2019-01-14 10:51:32 +01:00
sharkdp 19030470f9 Add proper Ctrl-C handling 2019-01-14 10:40:04 +01:00
sharkdp b27ab61608 Fix behavior on broken pipe 2019-01-14 10:17:14 +01:00
sharkdp 39a83021dc Use 16 colors instead of 256 2019-01-14 09:53:33 +01:00
sharkdp f6f41e76aa Use --color=always/auto/never instead of --no-color 2019-01-14 09:14:47 +01:00
Bennett Hardwick 74861353fa Add --no-color flag to disable ANSI sequences 2019-01-14 09:14:47 +01:00
Arnav Borborah 78d8cc516f Change exit code for help and version messages to 0 2019-01-13 18:35:15 +01:00
arnavb11 faebee7b8c Move duplicate code out of conditional 2019-01-13 18:03:07 +01:00
arnavb11 92c974d066 Handle clap errors and other errors separately 2019-01-13 18:03:07 +01:00
arnavb11 866feb2966 Refactor error handling into a if-let 2019-01-13 18:03:07 +01:00
arnavb11 952fff0ee4 Use instead of for consistency 2019-01-13 18:03:07 +01:00
Lily Ballard 1619cd5afe Bump the buffer size to 256 bytes
On my machine this produces an 11% speedup (benchmarked reading a 1.3MB
file from disk). Higher buffer sizes don't seem to make a difference.
2019-01-13 17:35:51 +01:00
Lily Ballard 20694bb628 Write lines into an in-memory buffer before printing to stdout
Running them through an in-memory buffer first produces a 25% speedup
(when tested against a 1.3MB file).
2019-01-13 17:35:51 +01:00
sharkdp 98311282e5 Fix #25 2019-01-10 09:03:39 +01:00
Lily Ballard afb6669477 Replace all uses of format!()
Previously we were allocating 2 strings per byte, plus another for the
offset. Instead we can just write all this directly to stdout.

Also replace the calculation of the ANSI escape code for every single
byte. This produces a significant speedup.
2019-01-10 09:00:44 +01:00
sharkdp 0dad8bf481 Bump version 2019-01-10 08:36:45 +01:00
sharkdp 612a227a81 Update dependencies 2019-01-10 08:34:28 +01:00
sharkdp 351fcf0aea Add note about Windows
closes #22
2019-01-10 08:32:46 +01:00
sharkdp 3c3d91cd51 Use 8-bit colors instead of 24-bit truecolor 2019-01-10 08:32:27 +01:00
Lily Ballard 7b7a0ff32d Get rid of the use of str.repeat()
This allocates a string. Instead we can (ab)use format specifiers to do
the repetitions for us.
2019-01-10 07:56:42 +01:00
Sebastian Thiel 2e403a2d11 Make clear we didn't accidentally forget to handle Results 2019-01-09 23:41:29 +01:00
Tobias Kortkamp 155b14e865 Add FreeBSD install instructions to README.md
I've just packaged hexyl for FreeBSD. It should be available in a couple of days from the `latest` package repository.

https://svnweb.freebsd.org/changeset/ports/489825
2019-01-09 23:07:50 +01:00
sharkdp 8429b87594 Re-enable Windows build 2019-01-09 20:20:37 +01:00
Thomas Schneider 1cddf395a8 Update README.md
changed yaourt to 
could be pakku, pikaur, aurman or something 
But yaourt is out of date, insecure and not recommended anymore
2019-01-09 19:55:14 +01:00
Yasuaki Uechi 2a1ae1d295 Add macOS installation guide 2019-01-07 10:09:37 +01:00
sharkdp 57e1c67bfb Disable Windows build 2018-12-30 13:27:21 +01:00
5 changed files with 217 additions and 80 deletions

No files matched your search

+1 -1
View File
@@ -72,7 +72,7 @@ deploy:
# deploy only if we push a tag
tags: true
# deploy only on stable channel that has TARGET env variable sets
condition: $TRAVIS_RUST_VERSION = stable && $TARGET != ""
condition: $TRAVIS_RUST_VERSION = stable && $TARGET != "x86_64-pc-windows-msvc"
notifications:
email:
Generated
+53 -10
View File
@@ -11,7 +11,7 @@ name = "atty"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -21,6 +21,16 @@ name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.32.0"
@@ -36,12 +46,23 @@ dependencies = [
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ctrlc"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hexyl"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -55,12 +76,24 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.45"
version = "0.2.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nix"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.49"
version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -68,7 +101,7 @@ name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -82,7 +115,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -91,8 +124,8 @@ name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -115,6 +148,11 @@ name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.8"
@@ -148,10 +186,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
"checksum redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f22c50afdcf3f0a31ebb6b47697f6a7c5e5a24967e842858118bce0615f0afad"
"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd"
"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17"
"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
@@ -159,6 +201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+3 -1
View File
@@ -7,10 +7,12 @@ license = "MIT/Apache-2.0"
name = "hexyl"
readme = "README.md"
repository = "https://github.com/sharkdp/hexyl"
version = "0.3.0"
version = "0.4.0"
[dependencies]
ansi_term = "0.11"
atty = "0.2"
ctrlc = "3.1"
[dependencies.clap]
version = "2"
+19 -3
View File
@@ -22,8 +22,8 @@ of bytes (NULL bytes, printable ASCII characters, ASCII whitespace characters, o
### On Debian-based systems
``` bash
wget "https://github.com/sharkdp/hexyl/releases/download/v0.3.0/hexyl_0.3.0_amd64.deb"
sudo dpkg -i hexyl_0.3.0_amd64.deb
wget "https://github.com/sharkdp/hexyl/releases/download/v0.4.0/hexyl_0.4.0_amd64.deb"
sudo dpkg -i hexyl_0.4.0_amd64.deb
```
### On Arch Linux
@@ -31,14 +31,30 @@ sudo dpkg -i hexyl_0.3.0_amd64.deb
You can install `hexyl` from [this AUR package](https://aur.archlinux.org/packages/hexyl/):
```
yaourt -S hexyl
yay -S hexyl
```
### On macOS
```
brew install hexyl
```
### On FreeBSD
```
pkg install hexyl
```
### On other distributions
Check out the [release page](https://github.com/sharkdp/hexyl/releases) for binary builds.
### On Windows
For now, you will have to install from source via `cargo` (see below). Make sure that
you use a terminal that supports ANSI escape sequences (like PowerShell on Windows 10).
### Via cargo
If you have Rust 1.29 or higher, you can install `hexyl` from source via `cargo`:
+141 -65
View File
@@ -1,23 +1,29 @@
#[macro_use]
extern crate clap;
extern crate ansi_term;
extern crate atty;
extern crate ctrlc;
use std::fs::File;
use std::io::{self, prelude::*, StdoutLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use clap::{App, AppSettings, Arg};
use ansi_term::Colour;
use ansi_term::Colour::RGB;
use ansi_term::Color;
use ansi_term::Color::Fixed;
const BUFFER_SIZE: usize = 64;
use atty::Stream;
const COLOR_NULL: Colour = RGB(117, 113, 94); // grey
const COLOR_OFFSET: Colour = RGB(117, 113, 94); // grey
const COLOR_ASCII_PRINTABLE: Colour = RGB(102, 217, 239); // cyan
const COLOR_ASCII_WHITESPACE: Colour = RGB(166, 226, 46); // green
const COLOR_ASCII_OTHER: Colour = RGB(249, 38, 114); // magenta
const COLOR_NONASCII: Colour = RGB(253, 151, 31); // orange
const BUFFER_SIZE: usize = 256;
const COLOR_NULL: Color = Fixed(242); // grey
const COLOR_OFFSET: Color = Fixed(242); // grey
const COLOR_ASCII_PRINTABLE: Color = Color::Cyan;
const COLOR_ASCII_WHITESPACE: Color = Color::Green;
const COLOR_ASCII_OTHER: Color = Color::Purple;
const COLOR_NONASCII: Color = Color::Yellow;
enum ByteCategory {
Null,
@@ -48,7 +54,7 @@ impl Byte {
}
}
fn color(self) -> &'static Colour {
fn color(self) -> &'static Color {
use ByteCategory::*;
match self.category() {
@@ -76,58 +82,85 @@ impl Byte {
struct Printer<'a> {
idx: usize,
line: Vec<u8>,
/// The raw bytes used as input for the current line.
raw_line: Vec<u8>,
/// The buffered line built with each byte, ready to print to stdout.
buffer_line: Vec<u8>,
stdout: StdoutLock<'a>,
show_color: bool,
byte_hex_table: Vec<String>,
byte_char_table: Vec<String>,
}
impl<'a> Printer<'a> {
fn new(stdout: StdoutLock) -> Printer {
fn new(stdout: StdoutLock, show_color: bool) -> Printer {
Printer {
idx: 1,
line: vec![],
raw_line: vec![],
buffer_line: vec![],
stdout,
show_color,
byte_hex_table: (0u8..=u8::max_value())
.map(|i| {
let byte_hex = format!("{:02x} ", i);
if show_color {
Byte(i).color().paint(byte_hex).to_string()
} else {
byte_hex
}
})
.collect(),
byte_char_table: (0u8..=u8::max_value())
.map(|i| {
let byte_char = format!("{}", Byte(i).as_char());
if show_color {
Byte(i).color().paint(byte_char).to_string()
} else {
byte_char
}
})
.collect(),
}
}
fn header(&mut self) {
writeln!(
self.stdout,
"┌{}┬{}┬{}┬{}┬{}┐",
"─".repeat(8),
"─".repeat(3 * 8 + 1),
"─".repeat(3 * 8 + 1),
"─".repeat(8),
"─".repeat(8)
);
"┌{0:─<8}┬{0:─<25}┬{0:─<25}┬{0:─<8}┬{0:─<8}┐",
""
)
.ok();
}
fn footer(&mut self) {
writeln!(
self.stdout,
"└{}┴{}┴{}┴{}┴{}┘",
"─".repeat(8),
"─".repeat(3 * 8 + 1),
"─".repeat(3 * 8 + 1),
"─".repeat(8),
"─".repeat(8)
);
"└{0:─<8}┴{0:─<25}┴{0:─<25}┴{0:─<8}┴{0:─<8}┘",
""
)
.ok();
}
fn print_byte(&mut self, b: u8) -> io::Result<()> {
if self.idx % 16 == 1 {
let offset_str = format!("{:08x}", self.idx - 1);
write!(self.stdout, "│{}│ ", COLOR_OFFSET.paint(offset_str))?;
let style = COLOR_OFFSET.normal();
let byte_index = format!("{:08x}", self.idx - 1);
let formatted_string = if self.show_color {
format!("{}", style.paint(byte_index))
} else {
byte_index
};
let _ = write!(&mut self.buffer_line, "│{}│ ", formatted_string);
}
let byte_str = format!("{:02x} ", b);
write!(self.stdout, "{}", Byte(b).color().paint(byte_str))?;
self.line.push(b);
write!(&mut self.buffer_line, "{}", self.byte_hex_table[b as usize])?;
self.raw_line.push(b);
match self.idx % 16 {
8 => write!(self.stdout, "┊ ")?,
0 => {
self.print_textline()?;
8 => {
let _ = write!(&mut self.buffer_line, "┊ ");
}
0 => self.print_textline()?,
_ => {}
}
@@ -137,53 +170,54 @@ impl<'a> Printer<'a> {
}
fn print_textline(&mut self) -> io::Result<()> {
let len = self.line.len();
let len = self.raw_line.len();
if len == 0 {
return Ok(());
}
if len < 8 {
write!(
self.stdout,
"{}┊{}│",
" ".repeat(3 * (8 - len)),
" ".repeat(1 + 3 * 8)
)?;
let _ = write!(
&mut self.buffer_line,
"{0:1$}┊{0:2$}│",
"",
3 * (8 - len),
1 + 3 * 8
);
} else {
write!(self.stdout, "{}│", " ".repeat(3 * (16 - len)))?;
let _ = write!(&mut self.buffer_line, "{0:1$}│", "", 3 * (16 - len));
}
let mut idx = 1;
for b in self.line.iter().map(|b| Byte(*b)) {
let chr = format!("{}", b.as_char());
write!(self.stdout, "{}", b.color().paint(chr)).ok();
for &b in self.raw_line.iter() {
let _ = write!(
&mut self.buffer_line,
"{}",
self.byte_char_table[b as usize]
);
if idx == 8 {
write!(self.stdout, "┊");
let _ = write!(&mut self.buffer_line, "┊");
}
idx += 1;
}
if len < 8 {
writeln!(
self.stdout,
"{}┊{}│ ",
" ".repeat(8 - len),
" ".repeat(8)
)?;
let _ = writeln!(&mut self.buffer_line, "{0:1$}┊{0:2$}│ ", "", 8 - len, 8);
} else {
writeln!(self.stdout, "{}│", " ".repeat(16 - len))?;
let _ = writeln!(&mut self.buffer_line, "{0:1$}│", "", 16 - len);
}
self.stdout.write_all(&self.buffer_line)?;
self.line.clear();
self.raw_line.clear();
self.buffer_line.clear();
Ok(())
}
}
fn run() -> io::Result<()> {
fn run() -> Result<(), Box<::std::error::Error>> {
let app = App::new(crate_name!())
.setting(AppSettings::ColorAuto)
.setting(AppSettings::ColoredHelp)
@@ -198,10 +232,22 @@ fn run() -> io::Result<()> {
.long("length")
.takes_value(true)
.value_name("N")
.help("read only N bytes from the input"),
.help("Read only N bytes from the input"),
)
.arg(
Arg::with_name("color")
.long("color")
.takes_value(true)
.value_name("when")
.possible_values(&["always", "auto", "never"])
.default_value("always")
.help(
"When to use colors. The auto-mode only displays colors if the output \
goes to an interactive terminal",
),
);
let matches = app.get_matches();
let matches = app.get_matches_safe()?;
let stdin = io::stdin();
@@ -217,23 +263,43 @@ fn run() -> io::Result<()> {
reader = Box::new(reader.take(length));
}
let show_color = match matches.value_of("color") {
Some("never") => false,
Some("auto") => atty::is(Stream::Stdout),
_ => true,
};
// Set up Ctrl-C handler
let cancelled = Arc::new(AtomicBool::new(false));
let c = cancelled.clone();
ctrlc::set_handler(move || {
c.store(true, Ordering::SeqCst);
})
.expect("Error setting Ctrl-C handler");
let stdout = io::stdout();
let mut printer = Printer::new(stdout.lock());
let mut printer = Printer::new(stdout.lock(), show_color);
printer.header();
let mut buffer = [0; BUFFER_SIZE];
loop {
'mainloop: loop {
let size = reader.read(&mut buffer)?;
if size == 0 {
break;
}
if cancelled.load(Ordering::SeqCst) {
eprintln!("hexyl has been cancelled.");
std::process::exit(130); // Set exit code to 128 + SIGINT
}
for b in &buffer[..size] {
let res = printer.print_byte(*b);
if res.is_err() {
// Broken pipe
break;
break 'mainloop;
}
}
}
@@ -251,11 +317,21 @@ fn main() {
let _ = ansi_term::enable_ansi_support();
let result = run();
match result {
Err(err) => {
if let Err(err) = result {
if let Some(clap_err) = err.downcast_ref::<clap::Error>() {
eprint!("{}", clap_err); // Clap errors already have newlines
match clap_err.kind {
// The exit code should not indicate an error for --help / --version
clap::ErrorKind::HelpDisplayed | clap::ErrorKind::VersionDisplayed => {
std::process::exit(0)
}
_ => (),
}
} else {
eprintln!("Error: {}", err);
std::process::exit(1);
}
Ok(()) => {}
std::process::exit(1);
}
}