diff --git a/src/lib.rs b/src/lib.rs index ba28fa2c..a8597fb3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,6 +131,8 @@ pub struct Options { grps: Vec, parsing_style: ParsingStyle, long_only: bool, + usage_column: usize, + usage_width: usize, } impl Default for Options { @@ -146,6 +148,8 @@ impl Options { grps: Vec::new(), parsing_style: ParsingStyle::FloatingFrees, long_only: false, + usage_column: 24, + usage_width: 54, } } @@ -604,7 +608,7 @@ impl Options { /// Derive usage items from a set of options. fn usage_items<'a>(&'a self) -> Box + 'a> { - let desc_sep = format!("\n{}", repeat(" ").take(24).collect::()); + let desc_sep = format!("\n{}", repeat(" ").take(self.usage_column).collect::()); let any_short = self.grps.iter().any(|optref| !optref.short_name.is_empty()); @@ -664,15 +668,15 @@ impl Options { } let rowlen = row.width(); - if rowlen < 24 { - for _ in 0..24 - rowlen { + if rowlen < self.usage_column { + for _ in 0..self.usage_column - rowlen { row.push(' '); } } else { row.push_str(&desc_sep) } - let desc_rows = each_split_within(&desc, 54); + let desc_rows = each_split_within(&desc, self.usage_width); row.push_str(&desc_rows.join(&desc_sep)); row @@ -680,6 +684,28 @@ impl Options { Box::new(rows) } + + /// Get the display column of usage + pub fn usage_column(&self) -> usize { + self.usage_column.clone() + } + + /// Set the display column of usage + pub fn set_usage_column(&mut self, column: usize) -> &mut Options { + self.usage_column = column; + self + } + + /// Get the display width of usage + pub fn usage_width(&self) -> usize { + self.usage_width.clone() + } + + /// Set the display width of usage + pub fn set_usage_width(&mut self, width: usize) -> &mut Options { + self.usage_width = width; + self + } } fn validate_names(short_name: &str, long_name: &str) { diff --git a/src/tests/mod.rs b/src/tests/mod.rs index f1eb9410..73607845 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -921,6 +921,41 @@ Options: assert!(usage == expected) } +#[test] +fn test_usage_description_newline_handling_custom_width() { + let mut opts = Options::new(); + opts.set_usage_width(30); + opts.optflag( + "k", + "k\u{2013}w\u{2013}", + "The word kiwi is normally spelled with two i's", + ); + opts.optflag( + "a", + "apple", + "This description forces a new line.\n Here is a premature\n\ + newline", + ); + + let expected = "Usage: fruits + +Options: + -k, --k–w– The word kiwi is normally + spelled with two i's + -a, --apple This description forces a new + line. + Here is a premature + newline +"; + + let usage = opts.usage("Usage: fruits"); + + debug!("expected: <<{}>>", expected); + debug!("generated: <<{}>>", usage); + assert!(usage == expected) +} + + #[test] fn test_usage_description_newline_handling() { let mut opts = Options::new(); @@ -952,6 +987,41 @@ Options: assert!(usage == expected) } + +#[test] +fn test_usage_description_newline_handling_custom_column() { + let mut opts = Options::new(); + opts.set_usage_column(10); + opts.optflag( + "k", + "k\u{2013}w\u{2013}", + "The word kiwi is normally spelled with two i's", + ); + opts.optflag( + "a", + "apple", + "This description forces a new line.\n Here is a premature\n\ + newline", + ); + + let expected = "Usage: fruits + +Options: + -k, --k–w–\u{0020} + The word kiwi is normally spelled with two i's + -a, --apple\u{0020} + This description forces a new line. + Here is a premature + newline +"; + + let usage = opts.usage("Usage: fruits"); + + debug!("expected: <<{}>>", expected); + debug!("generated: <<{}>>", usage); + assert!(usage == expected) +} + #[test] fn test_usage_multiwidth() { let mut opts = Options::new();