#[macro_use]
extern crate clap;
use std::convert::TryFrom;
use std::fs::File;
use std::io::{self, prelude::*, BufWriter, SeekFrom};
use std::num::{NonZeroI64, NonZeroU64, NonZeroU8};
use clap::builder::ArgPredicate;
use clap::{crate_name, crate_version, Arg, ArgAction, ColorChoice, Command};
use anyhow::{anyhow, Context, Result};
use const_format::formatcp;
use thiserror::Error as ThisError;
use terminal_size::terminal_size;
use hexyl::{Base, BorderStyle, Input, PrinterBuilder};
const DEFAULT_BLOCK_SIZE: i64 = 512;
fn run() -> Result<()> {
let command = Command::new(crate_name!())
.color(ColorChoice::Auto)
.max_term_width(90)
.version(crate_version!())
.about(crate_description!())
.arg(
Arg::new("FILE")
.help("The file to display. If no FILE argument is given, read from STDIN."),
)
.arg(
Arg::new("length")
.short('n')
.long("length")
.num_args(1)
.value_name("N")
.help(
"Only read N bytes from the input. The N argument can also include a \
unit with a decimal prefix (kB, MB, ..) or binary prefix (kiB, MiB, ..), \
or can be specified using a hex number. \
The short option '-l' can be used as an alias.\n\
Examples: --length=64, --length=4KiB, --length=0xff",
),
)
.arg(
Arg::new("bytes")
.short('c')
.long("bytes")
.num_args(1)
.value_name("N")
.conflicts_with("length")
.help("An alias for -n/--length"),
)
.arg(
Arg::new("count")
.short('l')
.num_args(1)
.value_name("N")
.conflicts_with_all(["length", "bytes"])
.hide(true)
.help("Yet another alias for -n/--length"),
)
.arg(
Arg::new("skip")
.short('s')
.long("skip")
.num_args(1)
.value_name("N")
.help(
"Skip the first N bytes of the input. The N argument can also include \
a unit (see `--length` for details)\n\
A negative value is valid and will seek from the end of the file.",
),
)
.arg(
Arg::new("block_size")
.long("block-size")
.num_args(1)
.value_name("SIZE")
.help(formatcp!(
"Sets the size of the `block` unit to SIZE (default is {}).\n\
Examples: --block-size=1024, --block-size=4kB",
DEFAULT_BLOCK_SIZE
)),
)
.arg(
Arg::new("nosqueezing")
.short('v')
.long("no-squeezing")
.action(ArgAction::SetFalse)
.help(
"Displays all input data. Otherwise any number of groups of output \
lines which would be identical to the preceding group of lines, are \
replaced with a line comprised of a single asterisk.",
),
)
.arg(
Arg::new("color")
.long("color")
.num_args(1)
.value_name("WHEN")
.value_parser(["always", "auto", "never"])
.default_value_if("plain", ArgPredicate::IsPresent, Some("never"))
.default_value("always")
.help(
"When to use colors. The auto-mode only displays colors if the output \
goes to an interactive terminal",
),
)
.arg(
Arg::new("border")
.long("border")
.num_args(1)
.value_name("STYLE")
.value_parser(["unicode", "ascii", "none"])
.default_value_if("plain", ArgPredicate::IsPresent, Some("none"))
.default_value("unicode")
.help(
"Whether to draw a border with Unicode characters, ASCII characters, \
or none at all",
),
)
.arg(Arg::new("plain").short('p').long("plain").action(ArgAction::SetTrue).help(
"Display output with --no-characters, --no-position, --border=none, and --color=never.",
))
.arg(
Arg::new("no_chars")
.short('C')
.long("no-characters")
.action(ArgAction::SetFalse)
.help("Whether to display the character panel on the right."),
)
.arg(
Arg::new("no_position")
.short('P')
.long("no-position")
.action(ArgAction::SetFalse)
.help("Whether to display the position panel on the left."),
)
.arg(
Arg::new("display_offset")
.short('o')
.long("display-offset")
.num_args(1)
.value_name("N")
.help(
"Add N bytes to the displayed file position. The N argument can also \
include a unit (see `--length` for details)\n\
A negative value is valid and calculates an offset relative to the \
end of the file.",
),
)
.arg(
Arg::new("panels")
.long("panels")
.num_args(1)
.value_name("N")
.help(
"Sets the number of hex data panels to be displayed. \
`--panels=auto` will display the maximum number of hex data panels \
based on the current terminal width. By default, hexyl will show \
two panels, unless the terminal is not wide enough for that.",
),
)
.arg(
Arg::new("group_size")
.short('g')
.long("group-size")
.alias("groupsize")
.num_args(1)
.