From 511637a1735a6ed0402bb3332ff94c875c1c64a6 Mon Sep 17 00:00:00 2001 From: Francis Murillo Date: Sun, 29 Sep 2019 22:02:49 +0800 Subject: [PATCH 1/5] Initial commit --- Cargo.toml | 1 + seq/Cargo.toml | 12 ++++++++++++ seq/build.rs | 19 +++++++++++++++++++ seq/src/main.rs | 38 ++++++++++++++++++++++++++++++++++++++ seq/src/seq.yml | 21 +++++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 seq/Cargo.toml create mode 100644 seq/build.rs create mode 100644 seq/src/main.rs create mode 100644 seq/src/seq.yml diff --git a/Cargo.toml b/Cargo.toml index f313aafb..272913cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "logname", "nice", "pwd", + "seq", "sleep", "true", "whoami", diff --git a/seq/Cargo.toml b/seq/Cargo.toml new file mode 100644 index 00000000..ba02193c --- /dev/null +++ b/seq/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "seq" +version = "0.1.0" +authors = ["GrayJack ", "FrancisMurillo "] +build = "build.rs" +edition = "2018" + +[dependencies] +clap = { version = "^2.33.0", features = ["yaml", "wrap_help"] } + +[build-dependencies] +clap = { version = "^2.33.0", features = ["yaml"] } diff --git a/seq/build.rs b/seq/build.rs new file mode 100644 index 00000000..b7694944 --- /dev/null +++ b/seq/build.rs @@ -0,0 +1,19 @@ +use std::env; + +use clap::{ App, Shell, load_yaml }; + +fn main() { + let yaml = load_yaml!("src/seq.yml"); + let mut app = App::from_yaml(yaml); + + let out_dir = match env::var("OUT_DIR") { + Ok(dir) => dir, + _ => return + }; + + app.gen_completions("seq", Shell::Zsh, out_dir.clone()); + app.gen_completions("seq", Shell::Fish, out_dir.clone()); + app.gen_completions("seq", Shell::Bash, out_dir.clone()); + app.gen_completions("seq", Shell::PowerShell, out_dir.clone()); + app.gen_completions("seq", Shell::Elvish, out_dir); +} diff --git a/seq/src/main.rs b/seq/src/main.rs new file mode 100644 index 00000000..bdb47245 --- /dev/null +++ b/seq/src/main.rs @@ -0,0 +1,38 @@ +use std::process; + +use clap::{load_yaml, App}; +use sugars::sleep; + +fn main() { + let yaml = load_yaml!("seq.yml"); + let matches = App::from_yaml(yaml).get_matches(); + + let numbers = match matches.values_of("NUMBER") { + Some(values) => values, + None => { + eprintln!("sleep: Missing operand.\nTry 'sleep --help' for more information."); + process::exit(1); + } + }; + + let total: u64 = numbers.filter_map(|s| s.parse::().ok()).sum(); + + let suffix = if matches.is_present("suffix") { + matches.value_of("suffix").unwrap() + } else { + "s" + }; + + match suffix { + "s" | "sec" => sleep!(total sec), + "m" | "min" => sleep!(total min), + "h" | "hour" => { + let total = 60 * total; + sleep!(total min) + } + _ => { + eprintln!("sleep: Invalid suffix value. It must be 'sec', 'min', 'hour', 's', 'm' or 'h'.\nFor more information, try 'sleep --help'."); + process::exit(1); + } + } +} diff --git a/seq/src/seq.yml b/seq/src/seq.yml new file mode 100644 index 00000000..7d360224 --- /dev/null +++ b/seq/src/seq.yml @@ -0,0 +1,21 @@ +name: seq +version: "0.0.0" +author: + - Eric Shimizu Karbstein + - Francis Murillo +about: "Suspends execution for a NUMBER of SUFFIX time.\nSUFFIX can be 'sec' or 's' for seconds, 'min' or 'm' for minutes, 'hour' or 'h' for hours." +args: + - LAST: + help: Number to set the sleep. If more than one, will sleep the sum of the numbers. + required: true + - FIRST: + help: Number to set the sleep. If more than one, will sleep the sum of the numbers. + required: false + - INCREMENT: + help: Number to set the sleep. If more than one, will sleep the sum of the numbers. + required: false + - suffix: + help: A optional parameter to set the time measurement to be used. The default is seconds. + long: suffix + short: s + value_name: SUFFIX From 2ac4e17564efcd01c4eda768e45bd13b8c7686cb Mon Sep 17 00:00:00 2001 From: Francis Murillo Date: Tue, 1 Oct 2019 04:36:46 +0800 Subject: [PATCH 2/5] Working clap --- seq/src/main.rs | 60 +++++++++++++++++++++++++------------------------ seq/src/seq.yml | 56 ++++++++++++++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 45 deletions(-) diff --git a/seq/src/main.rs b/seq/src/main.rs index bdb47245..a76aeeab 100644 --- a/seq/src/main.rs +++ b/seq/src/main.rs @@ -1,38 +1,40 @@ use std::process; use clap::{load_yaml, App}; -use sugars::sleep; fn main() { let yaml = load_yaml!("seq.yml"); let matches = App::from_yaml(yaml).get_matches(); - let numbers = match matches.values_of("NUMBER") { - Some(values) => values, - None => { - eprintln!("sleep: Missing operand.\nTry 'sleep --help' for more information."); - process::exit(1); - } - }; - - let total: u64 = numbers.filter_map(|s| s.parse::().ok()).sum(); - - let suffix = if matches.is_present("suffix") { - matches.value_of("suffix").unwrap() - } else { - "s" - }; - - match suffix { - "s" | "sec" => sleep!(total sec), - "m" | "min" => sleep!(total min), - "h" | "hour" => { - let total = 60 * total; - sleep!(total min) - } - _ => { - eprintln!("sleep: Invalid suffix value. It must be 'sec', 'min', 'hour', 's', 'm' or 'h'.\nFor more information, try 'sleep --help'."); - process::exit(1); - } - } + + std::dbg!(matches); + + // let numbers = match matches.values_of("NUMBER") { + // Some(values) => values, + // None => { + // eprintln!("sleep: Missing operand.\nTry 'sleep --help' for more information."); + // process::exit(1); + // } + // }; + + // let total: u64 = numbers.filter_map(|s| s.parse::().ok()).sum(); + + // let suffix = if matches.is_present("suffix") { + // matches.value_of("suffix").unwrap() + // } else { + // "s" + // }; + + // match suffix { + // "s" | "sec" => sleep!(total sec), + // "m" | "min" => sleep!(total min), + // "h" | "hour" => { + // let total = 60 * total; + // sleep!(total min) + // } + // _ => { + // eprintln!("sleep: Invalid suffix value. It must be 'sec', 'min', 'hour', 's', 'm' or 'h'.\nFor more information, try 'sleep --help'."); + // process::exit(1); + // } + // } } diff --git a/seq/src/seq.yml b/seq/src/seq.yml index 7d360224..f8d49046 100644 --- a/seq/src/seq.yml +++ b/seq/src/seq.yml @@ -1,21 +1,45 @@ name: seq version: "0.0.0" -author: - - Eric Shimizu Karbstein - - Francis Murillo -about: "Suspends execution for a NUMBER of SUFFIX time.\nSUFFIX can be 'sec' or 's' for seconds, 'min' or 'm' for minutes, 'hour' or 'h' for hours." +author: Francis Murillo +about: "Print a sequence of numbers" +long_about: > + Print numbers from FIRST to LAST, in steps of INCREMENT. +usage: > + + [OPTIONS] + + [OPTIONS] + + [OPTIONS] args: - - LAST: - help: Number to set the sleep. If more than one, will sleep the sum of the numbers. - required: true - FIRST: - help: Number to set the sleep. If more than one, will sleep the sum of the numbers. - required: false + help: > + The initial number to start the sequence. + long_help: > + The initial number to start the sequence. + + + This must not be NaN. If omitted, defaults to 1. - INCREMENT: - help: Number to set the sleep. If more than one, will sleep the sum of the numbers. - required: false - - suffix: - help: A optional parameter to set the time measurement to be used. The default is seconds. - long: suffix - short: s - value_name: SUFFIX + help: > + The step/increment added after each preceeding number in the + sequence. + long_help: > + The step/increment added after each preceeding number in the + sequence. + + + If FIRST is greater than LAST, this should be a positive + number; if less than, this should be a negative number. This + must not be 0 or NaN. If omitted, defaults to 1 even if FIRST + is greater than LAST. + - LAST: + help: > + The limit of the sequence. + long_help: > + The limit of the sequence. + + + If the next number in a sequence exceeds above or falls below + LAST whether STEP is positive or negative respectively, the + sequence ends. This must not be NaN. From d6ba949ed54370c330966d8bc7c7a5a1b7ad88ed Mon Sep 17 00:00:00 2001 From: Francis Murillo Date: Tue, 1 Oct 2019 21:29:50 +0800 Subject: [PATCH 3/5] seq: Initial prototype function --- seq/Cargo.toml | 2 +- seq/build.rs | 2 +- seq/src/main.rs | 133 +++++++++++++++++++++++++++++++++++------------- seq/src/seq.yml | 20 ++++---- 4 files changed, 110 insertions(+), 47 deletions(-) diff --git a/seq/Cargo.toml b/seq/Cargo.toml index ba02193c..119fe5ad 100644 --- a/seq/Cargo.toml +++ b/seq/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "seq" version = "0.1.0" -authors = ["GrayJack ", "FrancisMurillo "] +authors = ["GrayJack " , "FrancisMurillo "] build = "build.rs" edition = "2018" diff --git a/seq/build.rs b/seq/build.rs index b7694944..6639d05d 100644 --- a/seq/build.rs +++ b/seq/build.rs @@ -1,6 +1,6 @@ use std::env; -use clap::{ App, Shell, load_yaml }; +use clap::{load_yaml, App, Shell}; fn main() { let yaml = load_yaml!("src/seq.yml"); diff --git a/seq/src/main.rs b/seq/src/main.rs index a76aeeab..9d096e42 100644 --- a/seq/src/main.rs +++ b/seq/src/main.rs @@ -1,40 +1,105 @@ use std::process; -use clap::{load_yaml, App}; +use clap::{load_yaml, App, AppSettings}; + +#[derive(Copy, Clone, Debug)] +pub struct Seq { + current: f64, + stop: f64, + step: f64, +} + +impl Iterator for Seq { + type Item = f64; + + fn next(&mut self) -> Option { + if (self.step.is_sign_positive() && self.current <= self.stop) + || (self.step.is_sign_negative() && self.current >= self.stop) + { + let result = self.current; + + self.current += self.step; + + Some(result) + } else { + None + } + } +} + +fn parse_number(text: &str) -> Result { + text.parse::().map_err(|_| ()) +} + +fn check_nan(value: f64) -> Result { + if value.is_nan() { + Err(()) + } else { + Ok(value) + } +} + +fn check_zero(value: f64) -> Result { + if value == 0.0 { + Err(()) + } else { + Ok(value) + } +} + +fn argument_error(field: &str) -> impl Fn(()) -> f64 + '_ { + move |_| { + eprintln!( + "seq: Invalid {}.\nTry 'seq --help' for more information.", + field + ); + process::exit(1); + } +} + +const DEFAULT_FIRST: &str = "1"; +const DEFAULT_INCREMENT: &str = "1"; fn main() { let yaml = load_yaml!("seq.yml"); - let matches = App::from_yaml(yaml).get_matches(); - - - std::dbg!(matches); - - // let numbers = match matches.values_of("NUMBER") { - // Some(values) => values, - // None => { - // eprintln!("sleep: Missing operand.\nTry 'sleep --help' for more information."); - // process::exit(1); - // } - // }; - - // let total: u64 = numbers.filter_map(|s| s.parse::().ok()).sum(); - - // let suffix = if matches.is_present("suffix") { - // matches.value_of("suffix").unwrap() - // } else { - // "s" - // }; - - // match suffix { - // "s" | "sec" => sleep!(total sec), - // "m" | "min" => sleep!(total min), - // "h" | "hour" => { - // let total = 60 * total; - // sleep!(total min) - // } - // _ => { - // eprintln!("sleep: Invalid suffix value. It must be 'sec', 'min', 'hour', 's', 'm' or 'h'.\nFor more information, try 'sleep --help'."); - // process::exit(1); - // } - // } + let matches = App::from_yaml(yaml) + .setting(AppSettings::AllowNegativeNumbers) + .get_matches(); + + let (raw_first, raw_increment, raw_last) = match ( + matches.value_of("FIRST"), + matches.value_of("SECOND"), + matches.value_of("THIRD"), + ) { + (Some(last), None, None) => (DEFAULT_FIRST, DEFAULT_INCREMENT, last), + (Some(first), Some(last), None) => (first, DEFAULT_INCREMENT, last), + (Some(first), Some(increment), Some(last)) => (first, increment, last), + _ => { + eprintln!("seq: Missing operands.\nTry 'seq --help' for more information."); + process::exit(1); + } + }; + + let first = parse_number(raw_first) + .and_then(check_nan) + .unwrap_or_else(argument_error("FIRST")); + + let last = parse_number(raw_last) + .and_then(check_nan) + .unwrap_or_else(argument_error("LAST")); + + let increment = parse_number(raw_increment) + .and_then(check_nan) + .and_then(check_zero) + .unwrap_or_else(argument_error("INCREMENT")); + + let iter = Seq { + current: first, + stop: last, + step: increment, + }; + + for index in iter { + println!("{}", index); + } } diff --git a/seq/src/seq.yml b/seq/src/seq.yml index f8d49046..7c8e5e36 100644 --- a/seq/src/seq.yml +++ b/seq/src/seq.yml @@ -2,8 +2,7 @@ name: seq version: "0.0.0" author: Francis Murillo about: "Print a sequence of numbers" -long_about: > - Print numbers from FIRST to LAST, in steps of INCREMENT. +long_about: "Print numbers from FIRST to LAST, in steps of INCREMENT." usage: > [OPTIONS] @@ -13,17 +12,15 @@ usage: > [OPTIONS] args: - FIRST: - help: > - The initial number to start the sequence. + help: "The initial number to start the sequence." long_help: > The initial number to start the sequence. This must not be NaN. If omitted, defaults to 1. - - INCREMENT: - help: > - The step/increment added after each preceeding number in the - sequence. + required: true + - SECOND: + help: "The step/increment added after each preceeding number in the sequence." long_help: > The step/increment added after each preceeding number in the sequence. @@ -33,9 +30,9 @@ args: number; if less than, this should be a negative number. This must not be 0 or NaN. If omitted, defaults to 1 even if FIRST is greater than LAST. - - LAST: - help: > - The limit of the sequence. + required: false + - THIRD: + help: "The limit of the sequence." long_help: > The limit of the sequence. @@ -43,3 +40,4 @@ args: If the next number in a sequence exceeds above or falls below LAST whether STEP is positive or negative respectively, the sequence ends. This must not be NaN. + required: false From 286cb33f189662e154c2327f1734d45d480222fb Mon Sep 17 00:00:00 2001 From: Francis Murillo Date: Sat, 5 Oct 2019 11:08:58 +0800 Subject: [PATCH 4/5] seq: Add custom Number type for precision safety --- seq/Cargo.toml | 1 + seq/src/main.rs | 149 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 115 insertions(+), 35 deletions(-) diff --git a/seq/Cargo.toml b/seq/Cargo.toml index 119fe5ad..931ad93f 100644 --- a/seq/Cargo.toml +++ b/seq/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] clap = { version = "^2.33.0", features = ["yaml", "wrap_help"] } +rust_decimal = "^1.0.3" [build-dependencies] clap = { version = "^2.33.0", features = ["yaml"] } diff --git a/seq/src/main.rs b/seq/src/main.rs index 9d096e42..4f9840c4 100644 --- a/seq/src/main.rs +++ b/seq/src/main.rs @@ -1,52 +1,131 @@ -use std::process; +#![allow(clippy::suspicious_arithmetic_impl)] +use std::{ + cmp::Ordering, + fmt, + ops::{Add, AddAssign}, + process, + str::FromStr +}; use clap::{load_yaml, App, AppSettings}; - -#[derive(Copy, Clone, Debug)] -pub struct Seq { - current: f64, - stop: f64, - step: f64, +use rust_decimal::Decimal; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Number { + NegInf, + PosInf, + NaN, + Num(Decimal) } -impl Iterator for Seq { - type Item = f64; - - fn next(&mut self) -> Option { - if (self.step.is_sign_positive() && self.current <= self.stop) - || (self.step.is_sign_negative() && self.current >= self.stop) - { - let result = self.current; +use std::cmp::Ordering::*; +use Number::*; + +impl Add for Number { + type Output = Self; + + fn add(self, other: Self) -> Self { + match (self, other) { + (NaN, _) | (_, NaN) => NaN, + (Num(left), Num(right)) => match left.checked_add(right) { + Some(next_dec) => Num(next_dec), + None => { + if left.is_sign_positive() && right.is_sign_positive() { + PosInf + } else if left.is_sign_negative() && right.is_sign_negative() { + NegInf + } else { + NaN + } + }, + }, + (PosInf, PosInf) | (PosInf, Num(_)) | (Num(_), PosInf) => PosInf, + (NegInf, NegInf) | (NegInf, Num(_)) | (Num(_), NegInf) => NegInf, + (PosInf, NegInf) | (NegInf, PosInf) => NaN + } + } +} - self.current += self.step; +impl AddAssign for Number { + fn add_assign(&mut self, other: Self) { *self = *self + other; } +} - Some(result) - } else { - None +impl PartialOrd for Number { + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Num(left_dec), Num(right_dec)) => Some(left_dec.cmp(right_dec)), + (PosInf, PosInf) | (NegInf, NegInf) | (NaN, NaN) => Some(Equal), + (NaN, _) | (_, NaN) => None, + (NegInf, PosInf) | (Num(_), PosInf) | (NegInf, Num(_)) => Some(Less), + (PosInf, NegInf) | (PosInf, Num(_)) | (Num(_), NegInf) => Some(Greater) } } } -fn parse_number(text: &str) -> Result { - text.parse::().map_err(|_| ()) +impl From for Number { + fn from(number: f64) -> Self { + match number { + value if value.is_infinite() => { + if value.is_sign_positive() { + PosInf + } else { + NegInf + } + }, + value if value.is_finite() => Num(Decimal::from_str(&value.to_string()).unwrap()), + _ => NaN + } + } } -fn check_nan(value: f64) -> Result { - if value.is_nan() { - Err(()) - } else { - Ok(value) +impl fmt::Display for Number { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self { + PosInf => write!(f, "inf"), + NegInf => write!(f, "-inf"), + NaN => write!(f, "nan"), + Num(value) => write!(f, "{}", value) + } } } -fn check_zero(value: f64) -> Result { - if value == 0.0 { - Err(()) - } else { - Ok(value) +#[derive(Clone, Debug)] +pub struct Seq { + current: Number, + step: Number, + stop: Number +} + +impl Iterator for Seq { + type Item = Number; + + fn next(&mut self) -> Option { + match self.step { + step @ PosInf | step @ NegInf => Some(step + self.current), + Num(step_dec) => { + if (step_dec.is_sign_positive() && self.current <= self.stop) + || (step_dec.is_sign_negative() && self.current >= self.stop) + { + let result = self.current; + + self.current += self.step; + + Some(result) + } else { + None + } + }, + NaN => Some(NaN) + } } } +fn parse_number(text: &str) -> Result { text.parse::().map_err(|_| ()) } + +fn check_nan(value: f64) -> Result { if value.is_nan() { Err(()) } else { Ok(value) } } + +fn check_zero(value: f64) -> Result { if value == 0.0 { Err(()) } else { Ok(value) } } + fn argument_error(field: &str) -> impl Fn(()) -> f64 + '_ { move |_| { eprintln!( @@ -69,7 +148,7 @@ fn main() { let (raw_first, raw_increment, raw_last) = match ( matches.value_of("FIRST"), matches.value_of("SECOND"), - matches.value_of("THIRD"), + matches.value_of("THIRD") ) { (Some(last), None, None) => (DEFAULT_FIRST, DEFAULT_INCREMENT, last), (Some(first), Some(last), None) => (first, DEFAULT_INCREMENT, last), @@ -94,9 +173,9 @@ fn main() { .unwrap_or_else(argument_error("INCREMENT")); let iter = Seq { - current: first, - stop: last, - step: increment, + current: Number::from(first), + stop: Number::from(last), + step: Number::from(increment) }; for index in iter { From 6d84a8ae05b11c520cdb396675e2e2b3d261d499 Mon Sep 17 00:00:00 2001 From: Francis Murillo Date: Sat, 5 Oct 2019 12:28:48 +0800 Subject: [PATCH 5/5] seq: Add separator option --- seq/src/main.rs | 26 +++++++++++++++++--------- seq/src/seq.yml | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/seq/src/main.rs b/seq/src/main.rs index 4f9840c4..f0abe31a 100644 --- a/seq/src/main.rs +++ b/seq/src/main.rs @@ -26,7 +26,6 @@ impl Add for Number { fn add(self, other: Self) -> Self { match (self, other) { - (NaN, _) | (_, NaN) => NaN, (Num(left), Num(right)) => match left.checked_add(right) { Some(next_dec) => Num(next_dec), None => { @@ -39,9 +38,9 @@ impl Add for Number { } }, }, + (NaN, _) | (_, NaN) | (PosInf, NegInf) | (NegInf, PosInf) => NaN, (PosInf, PosInf) | (PosInf, Num(_)) | (Num(_), PosInf) => PosInf, - (NegInf, NegInf) | (NegInf, Num(_)) | (Num(_), NegInf) => NegInf, - (PosInf, NegInf) | (NegInf, PosInf) => NaN + (NegInf, NegInf) | (NegInf, Num(_)) | (Num(_), NegInf) => NegInf } } } @@ -54,8 +53,9 @@ impl PartialOrd for Number { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { (Num(left_dec), Num(right_dec)) => Some(left_dec.cmp(right_dec)), - (PosInf, PosInf) | (NegInf, NegInf) | (NaN, NaN) => Some(Equal), + (NaN, NaN) => Some(Equal), (NaN, _) | (_, NaN) => None, + (PosInf, PosInf) | (NegInf, NegInf) => Some(Equal), (NegInf, PosInf) | (Num(_), PosInf) | (NegInf, Num(_)) => Some(Less), (PosInf, NegInf) | (PosInf, Num(_)) | (Num(_), NegInf) => Some(Greater) } @@ -138,6 +138,7 @@ fn argument_error(field: &str) -> impl Fn(()) -> f64 + '_ { const DEFAULT_FIRST: &str = "1"; const DEFAULT_INCREMENT: &str = "1"; +const DEFAULT_SEPARATOR: &str = "\n"; fn main() { let yaml = load_yaml!("seq.yml"); @@ -159,6 +160,8 @@ fn main() { } }; + let separator = matches.value_of("SEPARATOR").unwrap_or(DEFAULT_SEPARATOR); + let first = parse_number(raw_first) .and_then(check_nan) .unwrap_or_else(argument_error("FIRST")); @@ -172,13 +175,18 @@ fn main() { .and_then(check_zero) .unwrap_or_else(argument_error("INCREMENT")); - let iter = Seq { + let mut iter = (Seq { current: Number::from(first), stop: Number::from(last), step: Number::from(increment) - }; - - for index in iter { - println!("{}", index); + }) + .peekable(); + + while let Some(index) = iter.next() { + if *&iter.peek().is_some() { + print!("{}{}", index, separator); + } else { + println!("{}", index); + } } } diff --git a/seq/src/seq.yml b/seq/src/seq.yml index 7c8e5e36..1a5d3ef6 100644 --- a/seq/src/seq.yml +++ b/seq/src/seq.yml @@ -11,6 +11,22 @@ usage: > [OPTIONS] args: + - FORMAT: + short: "f" + long: "format" + help: "Use printf style floating-point FORMAT" + takes_value: true + - SEPARATOR: + short: "s" + long: "separator" + help: "Use STRING to separate numbers" + default_value: "\n" + takes_value: true + - WIDTH: + short: "w" + long: "equal-width" + help: "Equalize width by padding with leading zeroes" + takes_value: false - FIRST: help: "The initial number to start the sequence." long_help: >