From ae63a3e400970a895d03ec1ef359ba86217c854b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 23 Aug 2013 18:31:13 +0200 Subject: [PATCH 1/3] Make getopts count (and thus align/paginate) in terms of codepoints not bytes. --- src/libextra/getopts.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 000520fe41e..f5efa940530 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -501,6 +501,7 @@ pub enum FailType { pub mod groups { use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req}; use getopts::{Short, Yes}; + use std::str; /** one group of options, e.g., both -h and --help, along with * their shared description and properties @@ -691,7 +692,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { // FIXME: #5516 // here we just need to indent the start of the description - let rowlen = row.len(); + let rowlen = str::count_chars(row, 0, row.len()); if rowlen < 24 { do (24 - rowlen).times { row.push_char(' ') @@ -798,7 +799,7 @@ enum LengthLimit { cont }; - ss.iter().enumerate().advance(|x| machine(x)); + ss.char_offset_iter().advance(|x| machine(x)); // Let the automaton 'run out' by supplying trailing whitespace while cont && match state { B | C => true, A => false } { From cc477dfa74b78511f96cae5b8b39c3ea391d3779 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sat, 24 Aug 2013 12:09:18 +0200 Subject: [PATCH 2/3] Added note that there is still more to do on 5516. Also added regression test for the byte vs codepoint issues that the previous commit fixes. --- src/libextra/getopts.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index f5efa940530..87aab3fbae2 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -690,7 +690,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { } } - // FIXME: #5516 + // FIXME: #5516 should be graphemes not codepoints // here we just need to indent the start of the description let rowlen = str::count_chars(row, 0, row.len()); if rowlen < 24 { @@ -708,14 +708,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { desc_normalized_whitespace.push_char(' '); } - // FIXME: #5516 + // FIXME: #5516 should be graphemes not codepoints let mut desc_rows = ~[]; do each_split_within(desc_normalized_whitespace, 54) |substr| { desc_rows.push(substr.to_owned()); true }; - // FIXME: #5516 + // FIXME: #5516 should be graphemes not codepoints // wrapped description row.push_str(desc_rows.connect(desc_sep)); @@ -1581,4 +1581,31 @@ fn test_groups_usage_description_wrapping() { debug!("generated: <<%s>>", usage); assert!(usage == expected) } + + #[test] + fn test_groups_usage_description_multibyte_handling() { + let optgroups = ~[ + groups::optflag("k", "k\u2013w\u2013", + "The word kiwi is normally spelled with two i's"), + groups::optflag("a", "apple", + "This \u201Cdescription\u201D has some characters that could \ +confuse the line wrapping; an apple costs 0.51€ in some parts of Europe."), + ]; + + let expected = +~"Usage: fruits + +Options: + -k --k–w– The word kiwi is normally spelled with two i's + -a --apple This “description” has some characters that could + confuse the line wrapping; an apple costs 0.51€ in + some parts of Europe. +"; + + let usage = groups::usage("Usage: fruits", optgroups); + + debug!("expected: <<%s>>", expected); + debug!("generated: <<%s>>", usage); + assert!(usage == expected) + } } From ca0e7b12aa3ec542a75769cc3453464813b20490 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Sun, 25 Aug 2013 11:19:35 +0200 Subject: [PATCH 3/3] char_len is more succinct than count_chars. --- src/libextra/getopts.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs index 87aab3fbae2..a21d9dc605f 100644 --- a/src/libextra/getopts.rs +++ b/src/libextra/getopts.rs @@ -501,7 +501,6 @@ pub enum FailType { pub mod groups { use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req}; use getopts::{Short, Yes}; - use std::str; /** one group of options, e.g., both -h and --help, along with * their shared description and properties @@ -692,7 +691,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { // FIXME: #5516 should be graphemes not codepoints // here we just need to indent the start of the description - let rowlen = str::count_chars(row, 0, row.len()); + let rowlen = row.char_len(); if rowlen < 24 { do (24 - rowlen).times { row.push_char(' ')