Browse Source

Upgrade to clap version 4

clap-4
JuanLeon Lahoz 3 months ago
parent
commit
bc6b1c1c7e
No known key found for this signature in database
GPG Key ID: C52130C6A1D5802
  1. 133
      Cargo.lock
  2. 2
      Cargo.toml
  3. 151
      src/app.rs
  4. 84
      src/main.rs
  5. 16
      src/read/dateparser.rs
  6. 2
      src/read/mod.rs

133
Cargo.lock generated

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "aho-corasick"
@ -26,12 +26,56 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
]
[[package]]
name = "assert_cmd"
version = "2.0.12"
@ -123,29 +167,31 @@ dependencies = [
[[package]]
name = "clap"
version = "3.2.25"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
dependencies = [
"atty",
"bitflags 1.3.2",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
"clap_builder",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
name = "clap_builder"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
dependencies = [
"os_str_bytes",
"anstream",
"anstyle",
"clap_lex",
"strsim 0.11.1",
]
[[package]]
name = "clap_lex"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@ -156,6 +202,12 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@ -226,7 +278,7 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"strsim 0.10.0",
"syn 1.0.107",
]
@ -491,14 +543,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "1.9.2"
name = "is_terminal_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
@ -625,10 +673,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "parking_lot"
@ -891,6 +939,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "1.0.107"
@ -941,12 +995,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
[[package]]
name = "textwrap"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "time"
version = "0.1.45"
@ -999,6 +1047,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wait-timeout"
version = "0.2.0"
@ -1105,6 +1159,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.45.0"
@ -1123,6 +1183,15 @@ dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.42.1"

2
Cargo.toml

@ -25,7 +25,6 @@ depends = ""
[dependencies]
clap = { version = "^3", features = ["cargo"] }
yansi = "^0"
atty = "^0"
derive_builder = "^0"
@ -34,6 +33,7 @@ chrono = "^0.4.28"
humantime = "^2"
simplelog = "^0"
log = "^0"
clap = { version = "^4", features = ["cargo"] }
[dev-dependencies]
float_eq = "^1"

151
src/app.rs

@ -1,4 +1,8 @@
use clap::{self, Arg, Command};
use clap::{
self,
builder::styling::{AnsiColor, Effects, Styles},
value_parser, Arg, ArgAction, Command,
};
fn add_input(cmd: Command) -> Command {
cmd.arg(
@ -15,7 +19,7 @@ fn add_input_as_option(cmd: Command) -> Command {
.long("input")
.default_value("-")
.long_help("If not present or a single dash, standard input will be used")
.takes_value(true),
.value_parser(value_parser!(String)),
)
}
@ -26,7 +30,7 @@ fn add_min_max(cmd: Command) -> Command {
.short('M')
.allow_hyphen_values(true)
.help("Filter out values bigger than this")
.takes_value(true),
.value_parser(value_parser!(f64)),
)
.arg(
Arg::new("min")
@ -34,7 +38,7 @@ fn add_min_max(cmd: Command) -> Command {
.short('m')
.allow_hyphen_values(true)
.help("Filter out values smaller than this")
.takes_value(true),
.value_parser(value_parser!(f64)),
)
}
@ -58,7 +62,7 @@ the named one will be used).
.short('R')
.help("Use a regex to capture input values")
.long_help(LONG_RE_ABOUT)
.takes_value(true),
.value_parser(value_parser!(String)),
)
}
@ -68,7 +72,7 @@ fn add_non_capturing_regex(cmd: Command) -> Command {
.long("regex")
.short('R')
.help("Filter out lines where regex is not present")
.takes_value(true),
.value_parser(value_parser!(String)),
)
}
@ -79,7 +83,7 @@ fn add_width(cmd: Command) -> Command {
.short('w')
.help("Use this many characters as terminal width")
.default_value("110")
.takes_value(true),
.value_parser(value_parser!(usize)),
)
}
@ -90,7 +94,7 @@ fn add_intervals(cmd: Command) -> Command {
.short('i')
.help("Use no more than this amount of buckets to classify data")
.default_value("20")
.takes_value(true),
.value_parser(value_parser!(usize)),
)
}
@ -101,7 +105,7 @@ fn add_precision(cmd: Command) -> Command {
.short('p')
.help("Show that number of decimals (if omitted, 'human' units will be used)")
.default_value("-1")
.takes_value(true),
.value_parser(value_parser!(i32)),
)
}
@ -110,11 +114,11 @@ fn add_log_scale(cmd: Command) -> Command {
Arg::new("log-scale")
.long("log-scale")
.help("Use a logarithmic scale in buckets")
.takes_value(false),
.action(ArgAction::SetTrue),
)
}
pub fn get_app() -> Command<'static> {
pub fn get_app() -> Command {
let mut hist = Command::new("hist")
.version(clap::crate_version!())
.about("Plot an histogram from input values");
@ -131,7 +135,7 @@ pub fn get_app() -> Command<'static> {
.short('H')
.help("Use that many `rows` for the plot")
.default_value("40")
.takes_value(true),
.value_parser(value_parser!(usize)),
);
plot = add_input(add_regex(add_width(add_min_max(add_precision(plot)))));
@ -143,30 +147,34 @@ pub fn get_app() -> Command<'static> {
Arg::new("match")
.help("Count matches for those strings")
.required(true)
.takes_value(true)
.multiple_occurrences(true),
.action(ArgAction::Append)
.num_args(1..),
);
let mut timehist =
Command::new("timehist")
.version(clap::crate_version!())
.about("Plot histogram with amount of matches over time")
.arg(
Arg::new("format")
.long("format")
.short('f')
.help("Use this string formatting")
.takes_value(true),
)
.arg(
Arg::new("duration")
.long("duration")
.help("Cap the time interval at that duration (example: '3h 5min')")
.takes_value(true),
)
.arg(Arg::new("early-stop").long("early-stop").help(
"If duration flag is used, assume monotonic times and stop as soon as possible",
));
let mut timehist = Command::new("timehist")
.version(clap::crate_version!())
.about("Plot histogram with amount of matches over time")
.arg(
Arg::new("format")
.long("format")
.short('f')
.help("Use this string formatting")
.value_parser(value_parser!(String)),
)
.arg(
Arg::new("duration")
.long("duration")
.help("Cap the time interval at that duration (example: '3h 5min')")
.value_parser(value_parser!(String)),
)
.arg(
Arg::new("early-stop")
.long("early-stop")
.help(
"If duration flag is used, assume monotonic times and stop as soon as possible",
)
.action(ArgAction::SetTrue),
);
timehist = add_input(add_width(add_non_capturing_regex(add_intervals(timehist))));
let mut splittimehist = Command::new("split-timehist")
@ -177,14 +185,14 @@ pub fn get_app() -> Command<'static> {
.long("format")
.short('f')
.help("Use this string formatting")
.takes_value(true),
.value_parser(value_parser!(String)),
);
splittimehist = add_input_as_option(add_width(add_intervals(splittimehist))).arg(
Arg::new("match")
.help("Count matches for those strings")
.required(true)
.takes_value(true)
.multiple_occurrences(true),
.action(ArgAction::Append)
.num_args(1..),
);
let mut common_terms = Command::new("common-terms")
@ -196,13 +204,20 @@ pub fn get_app() -> Command<'static> {
.short('l')
.help("Display that many lines, sorting by most frequent")
.default_value("10")
.takes_value(true),
.value_parser(value_parser!(i32)),
);
Command::new("lowcharts")
.author(clap::crate_authors!())
.version(clap::crate_version!())
.about(clap::crate_description!())
.styles(
Styles::styled()
.header(AnsiColor::Red.on_default() | Effects::BOLD)
.usage(AnsiColor::Red.on_default() | Effects::BOLD)
.literal(AnsiColor::Blue.on_default() | Effects::BOLD)
.placeholder(AnsiColor::Green.on_default()),
)
.max_term_width(100)
.subcommand_required(true)
.arg(
@ -210,16 +225,16 @@ pub fn get_app() -> Command<'static> {
.short('c')
.long("color")
.help("Use colors in the output")
.possible_values(["auto", "no", "yes"])
.value_parser(["auto", "no", "yes"])
.default_value("auto")
.takes_value(true),
.value_parser(value_parser!(String)),
)
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.help("Be more verbose")
.takes_value(false),
.action(ArgAction::SetTrue),
)
.subcommand(hist)
.subcommand(plot)
@ -238,14 +253,14 @@ mod tests {
fn hist_subcommand_arg_parsing() {
let arg_vec = vec!["lowcharts", "--verbose", "hist", "foo"];
let m = get_app().get_matches_from(arg_vec);
assert!(m.is_present("verbose"));
assert!(m.get_flag("verbose"));
let sub_m = m.subcommand_matches("hist").unwrap();
assert_eq!("foo", sub_m.value_of("input").unwrap());
assert!(sub_m.value_of("max").is_none());
assert!(sub_m.value_of("min").is_none());
assert!(sub_m.value_of("regex").is_none());
assert_eq!("110", sub_m.value_of("width").unwrap());
assert_eq!("20", sub_m.value_of("intervals").unwrap());
assert_eq!("foo", sub_m.get_one::<String>("input").unwrap());
assert!(sub_m.get_one::<f64>("max").is_none());
assert!(sub_m.get_one::<f64>("min").is_none());
assert!(sub_m.get_one::<String>("regex").is_none());
assert_eq!(&110usize, sub_m.get_one::<usize>("width").unwrap());
assert_eq!(&20usize, sub_m.get_one::<usize>("intervals").unwrap());
}
#[test]
@ -261,12 +276,12 @@ mod tests {
"11",
];
let m = get_app().get_matches_from(arg_vec);
assert!(!m.is_present("verbose"));
assert!(!m.get_flag("verbose"));
let sub_m = m.subcommand_matches("plot").unwrap();
assert_eq!("-", sub_m.value_of("input").unwrap());
assert_eq!("1.1", sub_m.value_of("max").unwrap());
assert_eq!("0.9", sub_m.value_of("min").unwrap());
assert_eq!("11", sub_m.value_of("height").unwrap());
assert_eq!("-", sub_m.get_one::<String>("input").unwrap());
assert_eq!(&1.1f64, sub_m.get_one::<f64>("max").unwrap());
assert_eq!(&0.9f64, sub_m.get_one::<f64>("min").unwrap());
assert_eq!(&11usize, sub_m.get_one::<usize>("height").unwrap());
}
#[test]
@ -274,18 +289,26 @@ mod tests {
let arg_vec = vec!["lowcharts", "matches", "A", "B", "C"];
let m = get_app().get_matches_from(arg_vec);
let sub_m = m.subcommand_matches("matches").unwrap();
assert_eq!("-", sub_m.value_of("input").unwrap());
assert_eq!("-", sub_m.get_one::<String>("input").unwrap());
assert_eq!(
vec!["A", "B", "C"],
sub_m.values_of("match").unwrap().collect::<Vec<&str>>()
sub_m
.get_many::<String>("match")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<&str>>()
);
let arg_vec = vec!["lowcharts", "matches", "A", "--input", "B", "C"];
let m = get_app().get_matches_from(arg_vec);
let sub_m = m.subcommand_matches("matches").unwrap();
assert_eq!("B", sub_m.value_of("input").unwrap());
assert_eq!("B", sub_m.get_one::<String>("input").unwrap());
assert_eq!(
vec!["A", "C"],
sub_m.values_of("match").unwrap().collect::<Vec<&str>>()
sub_m
.get_many::<String>("match")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<&str>>()
);
}
@ -294,8 +317,8 @@ mod tests {
let arg_vec = vec!["lowcharts", "timehist", "--regex", "foo", "some"];
let m = get_app().get_matches_from(arg_vec);
let sub_m = m.subcommand_matches("timehist").unwrap();
assert_eq!("some", sub_m.value_of("input").unwrap());
assert_eq!("foo", sub_m.value_of("regex").unwrap());
assert_eq!("some", sub_m.get_one::<String>("input").unwrap());
assert_eq!("foo", sub_m.get_one::<String>("regex").unwrap());
}
#[test]
@ -305,7 +328,11 @@ mod tests {
let sub_m = m.subcommand_matches("split-timehist").unwrap();
assert_eq!(
vec!["foo", "bar"],
sub_m.values_of("match").unwrap().collect::<Vec<&str>>()
sub_m
.get_many::<String>("match")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<&str>>()
);
}
@ -314,7 +341,7 @@ mod tests {
let arg_vec = vec!["lowcharts", "common-terms", "--regex", "foo", "some"];
let m = get_app().get_matches_from(arg_vec);
let sub_m = m.subcommand_matches("common-terms").unwrap();
assert_eq!("some", sub_m.value_of("input").unwrap());
assert_eq!("foo", sub_m.value_of("regex").unwrap());
assert_eq!("some", sub_m.get_one::<String>("input").unwrap());
assert_eq!("foo", sub_m.get_one::<String>("regex").unwrap());
}
}

84
src/main.rs

@ -76,17 +76,17 @@ fn parse_duration(duration: &str) -> Result<Duration, humantime::DurationError>
/// from an input source.
fn get_float_reader(matches: &ArgMatches) -> Result<read::DataReader, ()> {
let mut builder = read::DataReaderBuilder::default();
if matches.is_present("min") || matches.is_present("max") {
let min = matches.value_of_t("min").unwrap_or(f64::NEG_INFINITY);
let max = matches.value_of_t("max").unwrap_or(f64::INFINITY);
if matches.contains_id("min") || matches.contains_id("max") {
let min = *matches.get_one::<f64>("min").unwrap_or(&f64::NEG_INFINITY);
let max = *matches.get_one::<f64>("max").unwrap_or(&f64::INFINITY);
if min > max {
error!("Minimum should be smaller than maximum");
return Err(());
}
builder.range(min..max);
}
if let Some(string) = matches.value_of("regex") {
match Regex::new(string) {
if let Some(string) = matches.get_one::<String>("regex") {
match Regex::new(string.as_str()) {
Ok(re) => {
builder.regex(re);
}
@ -105,18 +105,18 @@ fn histogram(matches: &ArgMatches) -> i32 {
Ok(r) => r,
_ => return 2,
};
let mut vec = reader.read(matches.value_of("input").unwrap());
let mut vec = reader.read(matches.get_one::<String>("input").unwrap().as_str());
if !assert_data(&vec, 1) {
return 1;
}
let mut options = plot::HistogramOptions::default();
let precision_arg: i32 = matches.value_of_t("precision").unwrap();
let precision_arg: i32 = *matches.get_one::<i32>("precision").unwrap();
if precision_arg > 0 {
options.precision = Some(precision_arg as usize);
};
options.log_scale = matches.is_present("log-scale");
options.intervals = matches.value_of_t("intervals").unwrap();
let width = matches.value_of_t("width").unwrap();
options.log_scale = matches.get_flag("log-scale");
options.intervals = *matches.get_one::<usize>("intervals").unwrap();
let width = *matches.get_one::<usize>("width").unwrap();
let histogram = plot::Histogram::new(&mut vec, options);
print!("{histogram:width$}");
0
@ -128,11 +128,11 @@ fn plot(matches: &ArgMatches) -> i32 {
Ok(r) => r,
_ => return 2,
};
let vec = reader.read(matches.value_of("input").unwrap());
let vec = reader.read(matches.get_one::<String>("input").unwrap().as_str());
if !assert_data(&vec, 1) {
return 1;
}
let precision_arg: i32 = matches.value_of_t("precision").unwrap();
let precision_arg: i32 = *matches.get_one::<i32>("precision").unwrap();
let precision = if precision_arg < 0 {
None
} else {
@ -140,8 +140,8 @@ fn plot(matches: &ArgMatches) -> i32 {
};
let plot = plot::XyPlot::new(
&vec,
matches.value_of_t("width").unwrap(),
matches.value_of_t("height").unwrap(),
*matches.get_one::<usize>("width").unwrap(),
*matches.get_one::<usize>("height").unwrap(),
precision,
);
print!("{plot}");
@ -151,12 +151,16 @@ fn plot(matches: &ArgMatches) -> i32 {
/// Implements the matches cli-subcommand
fn matchbar(matches: &ArgMatches) -> i32 {
let reader = read::DataReader::default();
let width = matches.value_of_t("width").unwrap();
let width = *matches.get_one::<usize>("width").unwrap();
print!(
"{:width$}",
reader.read_matches(
matches.value_of("input").unwrap(),
matches.values_of("match").unwrap().collect()
matches.get_one::<String>("input").unwrap().as_str(),
matches
.get_many::<String>("match")
.unwrap()
.map(|s| s.as_str())
.collect()
),
width = width
);
@ -166,8 +170,8 @@ fn matchbar(matches: &ArgMatches) -> i32 {
/// Implements the common-terms cli-subcommand
fn common_terms(matches: &ArgMatches) -> i32 {
let mut builder = read::DataReaderBuilder::default();
if let Some(string) = matches.value_of("regex") {
match Regex::new(string) {
if let Some(string) = matches.get_one::<String>("regex") {
match Regex::new(string.as_str()) {
Ok(re) => {
builder.regex(re);
}
@ -180,15 +184,18 @@ fn common_terms(matches: &ArgMatches) -> i32 {
builder.regex(Regex::new("(.*)").unwrap());
};
let reader = builder.build().unwrap();
let width = matches.value_of_t("width").unwrap();
let lines = matches.value_of_t("lines").unwrap();
let width = *matches.get_one::<usize>("width").unwrap();
let lines = *matches.get_one::<i32>("lines").unwrap();
if lines < 1 {
error!("You should specify a potitive number of lines");
return 2;
};
print!(
"{:width$}",
reader.read_terms(matches.value_of("input").unwrap(), lines),
reader.read_terms(
matches.get_one::<String>("input").unwrap().as_str(),
lines as usize,
),
width = width
);
0
@ -197,8 +204,8 @@ fn common_terms(matches: &ArgMatches) -> i32 {
/// Implements the timehist cli-subcommand
fn timehist(matches: &ArgMatches) -> i32 {
let mut builder = read::TimeReaderBuilder::default();
if let Some(string) = matches.value_of("regex") {
match Regex::new(string) {
if let Some(string) = matches.get_one::<String>("regex") {
match Regex::new(string.as_str()) {
Ok(re) => {
builder.regex(re);
}
@ -208,12 +215,12 @@ fn timehist(matches: &ArgMatches) -> i32 {
}
};
}
if let Some(as_str) = matches.value_of("format") {
if let Some(as_str) = matches.get_one::<String>("format") {
builder.ts_format(as_str.to_string());
}
builder.early_stop(matches.is_present("early-stop"));
if let Some(duration) = matches.value_of("duration") {
match parse_duration(duration) {
builder.early_stop(matches.get_flag("early-stop"));
if let Some(duration) = matches.get_one::<String>("duration") {
match parse_duration(duration.as_str()) {
Ok(d) => builder.duration(d),
Err(err) => {
error!("Failed to parse duration {}: {}", duration, err);
@ -221,11 +228,12 @@ fn timehist(matches: &ArgMatches) -> i32 {
}
};
};
let width = matches.value_of_t("width").unwrap();
let width = *matches.get_one::<usize>("width").unwrap();
let reader = builder.build().unwrap();
let vec = reader.read(matches.value_of("input").unwrap());
let vec = reader.read(matches.get_one::<String>("input").unwrap().as_str());
if assert_data(&vec, 2) {
let timehist = plot::TimeHistogram::new(matches.value_of_t("intervals").unwrap(), &vec);
let timehist =
plot::TimeHistogram::new(*matches.get_one::<usize>("intervals").unwrap(), &vec);
print!("{timehist:width$}");
};
0
@ -234,7 +242,7 @@ fn timehist(matches: &ArgMatches) -> i32 {
/// Implements the timehist cli-subcommand
fn splittime(matches: &ArgMatches) -> i32 {
let mut builder = read::SplitTimeReaderBuilder::default();
let string_list: Vec<String> = match matches.values_of("match") {
let string_list: Vec<String> = match matches.get_many::<String>("match") {
Some(s) => s.map(|s| s.to_string()).collect(),
None => {
error!("At least a match is needed");
@ -245,16 +253,16 @@ fn splittime(matches: &ArgMatches) -> i32 {
error!("Only 5 different sub-groups are supported");
return 2;
}
if let Some(as_str) = matches.value_of("format") {
if let Some(as_str) = matches.get_one::<String>("format") {
builder.ts_format(as_str.to_string());
}
builder.matches(string_list.iter().map(|s| s.to_string()).collect());
let width = matches.value_of_t("width").unwrap();
let width = *matches.get_one::<usize>("width").unwrap();
let reader = builder.build().unwrap();
let vec = reader.read(matches.value_of("input").unwrap());
let vec = reader.read(matches.get_one::<String>("input").unwrap().as_str());
if assert_data(&vec, 2) {
let timehist = plot::SplitTimeHistogram::new(
matches.value_of_t("intervals").unwrap(),
*matches.get_one::<usize>("intervals").unwrap(),
string_list,
&vec,
);
@ -266,8 +274,8 @@ fn splittime(matches: &ArgMatches) -> i32 {
fn main() {
let matches = app::get_app().get_matches();
configure_output(
matches.value_of("color").unwrap(),
matches.is_present("verbose"),
matches.get_one::<String>("color").unwrap().as_str(),
matches.get_flag("verbose"),
);
std::process::exit(match matches.subcommand() {
Some(("hist", subcommand_matches)) => histogram(subcommand_matches),

16
src/read/dateparser.rs

@ -41,9 +41,21 @@ impl LogDateParser {
// the 1st digit and then try to parse as much text as possible with any
// of the "supported" formats (so that we do not lose precision digits
// or TZ info).
for (i, c) in log_line.chars().enumerate() {
for (i, c) in log_line.char_indices() {
if c.is_ascii_digit() {
for j in (i..(i + MAX_LEN).min(log_line.len() + 1)).rev() {
let mut end_positions: Vec<usize> = log_line[i..]
.char_indices()
.skip(1)
.map(|(off, _)| i + off)
.take(MAX_LEN)
.collect();
let max_end = log_line.len();
if end_positions.last().copied().unwrap_or(i) != max_end {
end_positions.push(max_end);
}
for j in end_positions.into_iter().rev() {
if let Some(parser) = Self::guess_parser(&log_line[i..j]) {
return Ok(Self {
range: i..j,

2
src/read/mod.rs

@ -1,5 +1,5 @@
pub use self::buckets::{DataReader, DataReaderBuilder};
pub use self::splittimes::{SplitTimeReader, SplitTimeReaderBuilder};
pub use self::splittimes::SplitTimeReaderBuilder;
pub use self::times::TimeReaderBuilder;
mod buckets;

Loading…
Cancel
Save