Commit 387e51dc1623cfbec81ec121b622c5cfd40518e2
Merge branch 'master' into default_values
Conflicts: src/cxxopts.hpp
Showing
4 changed files
with
248 additions
and
42 deletions
CMakeLists.txt
| @@ -23,5 +23,20 @@ project(cxxopts) | @@ -23,5 +23,20 @@ project(cxxopts) | ||
| 23 | 23 | ||
| 24 | set(VERSION "0.0.1") | 24 | set(VERSION "0.0.1") |
| 25 | 25 | ||
| 26 | +set(CXXOPTS_LINKER_LIBRARIES "") | ||
| 27 | + | ||
| 28 | +set(CXXOPTS_USE_UNICODE_HELP FALSE CACHE BOOL "Use ICU Unicode library") | ||
| 29 | + | ||
| 30 | +if(CXXOPTS_USE_UNICODE_HELP) | ||
| 31 | + | ||
| 32 | + find_package(PkgConfig) | ||
| 33 | + | ||
| 34 | + pkg_check_modules(ICU REQUIRED icu-uc) | ||
| 35 | + | ||
| 36 | + set(CXXOPTS_LINKER_LIBRARIES "${ICU_LIBRARIES}") | ||
| 37 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCXXOPTS_USE_UNICODE") | ||
| 38 | + | ||
| 39 | +endif() | ||
| 40 | + | ||
| 26 | add_subdirectory(src) | 41 | add_subdirectory(src) |
| 27 | 42 |
src/CMakeLists.txt
| @@ -21,5 +21,6 @@ | @@ -21,5 +21,6 @@ | ||
| 21 | add_executable(example example.cpp) | 21 | add_executable(example example.cpp) |
| 22 | 22 | ||
| 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") | 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") |
| 24 | +target_link_libraries(example ${CXXOPTS_LINKER_LIBRARIES}) | ||
| 24 | 25 | ||
| 25 | install(FILES cxxopts.hpp DESTINATION include) | 26 | install(FILES cxxopts.hpp DESTINATION include) |
src/cxxopts.hpp
| @@ -34,6 +34,184 @@ THE SOFTWARE. | @@ -34,6 +34,184 @@ THE SOFTWARE. | ||
| 34 | #include <string> | 34 | #include <string> |
| 35 | #include <vector> | 35 | #include <vector> |
| 36 | 36 | ||
| 37 | +#ifdef CXXOPTS_USE_UNICODE | ||
| 38 | +#include <unicode/unistr.h> | ||
| 39 | + | ||
| 40 | +namespace cxxopts | ||
| 41 | +{ | ||
| 42 | + typedef icu::UnicodeString String; | ||
| 43 | + | ||
| 44 | + inline | ||
| 45 | + String | ||
| 46 | + toLocalString(std::string s) | ||
| 47 | + { | ||
| 48 | + return icu::UnicodeString::fromUTF8(s); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + class UnicodeStringIterator : public | ||
| 52 | + std::iterator<std::forward_iterator_tag, int32_t> | ||
| 53 | + { | ||
| 54 | + public: | ||
| 55 | + | ||
| 56 | + UnicodeStringIterator(const icu::UnicodeString* s, int32_t pos) | ||
| 57 | + : s(s) | ||
| 58 | + , i(pos) | ||
| 59 | + { | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + value_type | ||
| 63 | + operator*() const | ||
| 64 | + { | ||
| 65 | + return s->char32At(i); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + bool | ||
| 69 | + operator==(const UnicodeStringIterator& rhs) const | ||
| 70 | + { | ||
| 71 | + return s == rhs.s && i == rhs.i; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + bool | ||
| 75 | + operator!=(const UnicodeStringIterator& rhs) const | ||
| 76 | + { | ||
| 77 | + return !(*this == rhs); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + UnicodeStringIterator& | ||
| 81 | + operator++() | ||
| 82 | + { | ||
| 83 | + ++i; | ||
| 84 | + return *this; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + UnicodeStringIterator | ||
| 88 | + operator+(int32_t v) | ||
| 89 | + { | ||
| 90 | + return UnicodeStringIterator(s, i + v); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + private: | ||
| 94 | + const icu::UnicodeString* s; | ||
| 95 | + int32_t i; | ||
| 96 | + }; | ||
| 97 | + | ||
| 98 | + inline | ||
| 99 | + String& | ||
| 100 | + stringAppend(String&s, String a) | ||
| 101 | + { | ||
| 102 | + return s.append(std::move(a)); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + inline | ||
| 106 | + String& | ||
| 107 | + stringAppend(String& s, int n, UChar32 c) | ||
| 108 | + { | ||
| 109 | + for (int i = 0; i != n; ++i) | ||
| 110 | + { | ||
| 111 | + s.append(c); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + return s; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + template <typename Iterator> | ||
| 118 | + String& | ||
| 119 | + stringAppend(String& s, Iterator begin, Iterator end) | ||
| 120 | + { | ||
| 121 | + while (begin != end) | ||
| 122 | + { | ||
| 123 | + s.append(*begin); | ||
| 124 | + ++begin; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + return s; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + inline | ||
| 131 | + size_t | ||
| 132 | + stringLength(const String& s) | ||
| 133 | + { | ||
| 134 | + return s.length(); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + inline | ||
| 138 | + std::string | ||
| 139 | + toUTF8String(const String& s) | ||
| 140 | + { | ||
| 141 | + std::string result; | ||
| 142 | + s.toUTF8String(result); | ||
| 143 | + | ||
| 144 | + return result; | ||
| 145 | + } | ||
| 146 | +} | ||
| 147 | + | ||
| 148 | +namespace std | ||
| 149 | +{ | ||
| 150 | + cxxopts::UnicodeStringIterator | ||
| 151 | + begin(const icu::UnicodeString& s) | ||
| 152 | + { | ||
| 153 | + return cxxopts::UnicodeStringIterator(&s, 0); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + cxxopts::UnicodeStringIterator | ||
| 157 | + end(const icu::UnicodeString& s) | ||
| 158 | + { | ||
| 159 | + return cxxopts::UnicodeStringIterator(&s, s.length()); | ||
| 160 | + } | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +#else | ||
| 164 | + | ||
| 165 | +namespace cxxopts | ||
| 166 | +{ | ||
| 167 | + typedef std::string String; | ||
| 168 | + | ||
| 169 | + template <typename T> | ||
| 170 | + T | ||
| 171 | + toLocalString(T&& t) | ||
| 172 | + { | ||
| 173 | + return t; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + inline | ||
| 177 | + size_t | ||
| 178 | + stringLength(const String& s) | ||
| 179 | + { | ||
| 180 | + return s.length(); | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + inline | ||
| 184 | + String& | ||
| 185 | + stringAppend(String&s, String a) | ||
| 186 | + { | ||
| 187 | + return s.append(std::move(a)); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + inline | ||
| 191 | + String& | ||
| 192 | + stringAppend(String& s, int n, char c) | ||
| 193 | + { | ||
| 194 | + return s.append(n, c); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + template <typename Iterator> | ||
| 198 | + String& | ||
| 199 | + stringAppend(String& s, Iterator begin, Iterator end) | ||
| 200 | + { | ||
| 201 | + return s.append(begin, end); | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + template <typename T> | ||
| 205 | + std::string | ||
| 206 | + toUTF8String(T&& t) | ||
| 207 | + { | ||
| 208 | + return std::forward<T>(t); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +#endif | ||
| 214 | + | ||
| 37 | namespace cxxopts | 215 | namespace cxxopts |
| 38 | { | 216 | { |
| 39 | class Value : public std::enable_shared_from_this<Value> | 217 | class Value : public std::enable_shared_from_this<Value> |
| @@ -354,7 +532,7 @@ namespace cxxopts | @@ -354,7 +532,7 @@ namespace cxxopts | ||
| 354 | public: | 532 | public: |
| 355 | OptionDetails | 533 | OptionDetails |
| 356 | ( | 534 | ( |
| 357 | - const std::string& description, | 535 | + const String& description, |
| 358 | std::shared_ptr<const Value> value | 536 | std::shared_ptr<const Value> value |
| 359 | ) | 537 | ) |
| 360 | : m_desc(description) | 538 | : m_desc(description) |
| @@ -363,7 +541,7 @@ namespace cxxopts | @@ -363,7 +541,7 @@ namespace cxxopts | ||
| 363 | { | 541 | { |
| 364 | } | 542 | } |
| 365 | 543 | ||
| 366 | - const std::string& | 544 | + const String& |
| 367 | description() const | 545 | description() const |
| 368 | { | 546 | { |
| 369 | return m_desc; | 547 | return m_desc; |
| @@ -407,7 +585,7 @@ namespace cxxopts | @@ -407,7 +585,7 @@ namespace cxxopts | ||
| 407 | } | 585 | } |
| 408 | 586 | ||
| 409 | private: | 587 | private: |
| 410 | - std::string m_desc; | 588 | + String m_desc; |
| 411 | std::shared_ptr<const Value> m_value; | 589 | std::shared_ptr<const Value> m_value; |
| 412 | int m_count; | 590 | int m_count; |
| 413 | }; | 591 | }; |
| @@ -416,7 +594,7 @@ namespace cxxopts | @@ -416,7 +594,7 @@ namespace cxxopts | ||
| 416 | { | 594 | { |
| 417 | std::string s; | 595 | std::string s; |
| 418 | std::string l; | 596 | std::string l; |
| 419 | - std::string desc; | 597 | + String desc; |
| 420 | bool has_arg; | 598 | bool has_arg; |
| 421 | bool has_default; | 599 | bool has_default; |
| 422 | std::string default_value; | 600 | std::string default_value; |
| @@ -435,7 +613,7 @@ namespace cxxopts | @@ -435,7 +613,7 @@ namespace cxxopts | ||
| 435 | 613 | ||
| 436 | Options(std::string program, std::string help_string = "") | 614 | Options(std::string program, std::string help_string = "") |
| 437 | : m_program(std::move(program)) | 615 | : m_program(std::move(program)) |
| 438 | - , m_help_string(std::move(help_string)) | 616 | + , m_help_string(toLocalString(std::move(help_string))) |
| 439 | { | 617 | { |
| 440 | } | 618 | } |
| 441 | 619 | ||
| @@ -454,7 +632,7 @@ namespace cxxopts | @@ -454,7 +632,7 @@ namespace cxxopts | ||
| 454 | const std::string& group, | 632 | const std::string& group, |
| 455 | const std::string& s, | 633 | const std::string& s, |
| 456 | const std::string& l, | 634 | const std::string& l, |
| 457 | - const std::string& desc, | 635 | + std::string desc, |
| 458 | std::shared_ptr<const Value> value | 636 | std::shared_ptr<const Value> value |
| 459 | ); | 637 | ); |
| 460 | 638 | ||
| @@ -531,11 +709,11 @@ namespace cxxopts | @@ -531,11 +709,11 @@ namespace cxxopts | ||
| 531 | ); | 709 | ); |
| 532 | 710 | ||
| 533 | inline | 711 | inline |
| 534 | - std::string | 712 | + String |
| 535 | help_one_group(const std::string& group) const; | 713 | help_one_group(const std::string& group) const; |
| 536 | 714 | ||
| 537 | std::string m_program; | 715 | std::string m_program; |
| 538 | - std::string m_help_string; | 716 | + String m_help_string; |
| 539 | 717 | ||
| 540 | std::map<std::string, std::shared_ptr<OptionDetails>> m_options; | 718 | std::map<std::string, std::shared_ptr<OptionDetails>> m_options; |
| 541 | std::string m_positional; | 719 | std::string m_positional; |
| @@ -580,12 +758,12 @@ namespace cxxopts | @@ -580,12 +758,12 @@ namespace cxxopts | ||
| 580 | constexpr int OPTION_DESC_GAP = 2; | 758 | constexpr int OPTION_DESC_GAP = 2; |
| 581 | 759 | ||
| 582 | std::basic_regex<char> option_matcher | 760 | std::basic_regex<char> option_matcher |
| 583 | - ("--([[:alpha:]][-_[:alpha:]]+)(=(.*))?|-([a-zA-Z]+)"); | 761 | + ("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([a-zA-Z]+)"); |
| 584 | 762 | ||
| 585 | std::basic_regex<char> option_specifier | 763 | std::basic_regex<char> option_specifier |
| 586 | - ("(([a-zA-Z]),)?([a-zA-Z][-_a-zA-Z]+)"); | 764 | + ("(([a-zA-Z]),)?([a-zA-Z0-9][-_a-zA-Z0-9]+)"); |
| 587 | 765 | ||
| 588 | - std::string | 766 | + String |
| 589 | format_option | 767 | format_option |
| 590 | ( | 768 | ( |
| 591 | const HelpOptionDetails& o | 769 | const HelpOptionDetails& o |
| @@ -594,11 +772,11 @@ namespace cxxopts | @@ -594,11 +772,11 @@ namespace cxxopts | ||
| 594 | auto& s = o.s; | 772 | auto& s = o.s; |
| 595 | auto& l = o.l; | 773 | auto& l = o.l; |
| 596 | 774 | ||
| 597 | - std::string result = " "; | 775 | + String result = " "; |
| 598 | 776 | ||
| 599 | if (s.size() > 0) | 777 | if (s.size() > 0) |
| 600 | { | 778 | { |
| 601 | - result += "-" + s + ","; | 779 | + result += "-" + toLocalString(s) + ","; |
| 602 | } | 780 | } |
| 603 | else | 781 | else |
| 604 | { | 782 | { |
| @@ -607,7 +785,7 @@ namespace cxxopts | @@ -607,7 +785,7 @@ namespace cxxopts | ||
| 607 | 785 | ||
| 608 | if (l.size() > 0) | 786 | if (l.size() > 0) |
| 609 | { | 787 | { |
| 610 | - result += " --" + l; | 788 | + result += " --" + toLocalString(l); |
| 611 | } | 789 | } |
| 612 | 790 | ||
| 613 | if (o.has_arg) | 791 | if (o.has_arg) |
| @@ -623,23 +801,23 @@ namespace cxxopts | @@ -623,23 +801,23 @@ namespace cxxopts | ||
| 623 | return result; | 801 | return result; |
| 624 | } | 802 | } |
| 625 | 803 | ||
| 626 | - std::string | 804 | + String |
| 627 | format_description | 805 | format_description |
| 628 | ( | 806 | ( |
| 629 | - const std::string& text, | 807 | + const String& text, |
| 630 | int start, | 808 | int start, |
| 631 | int width | 809 | int width |
| 632 | ) | 810 | ) |
| 633 | { | 811 | { |
| 634 | - std::string result; | 812 | + String result; |
| 635 | 813 | ||
| 636 | - auto current = text.begin(); | 814 | + auto current = std::begin(text); |
| 637 | auto startLine = current; | 815 | auto startLine = current; |
| 638 | auto lastSpace = current; | 816 | auto lastSpace = current; |
| 639 | 817 | ||
| 640 | int size = 0; | 818 | int size = 0; |
| 641 | 819 | ||
| 642 | - while (current != text.end()) | 820 | + while (current != std::end(text)) |
| 643 | { | 821 | { |
| 644 | if (*current == ' ') | 822 | if (*current == ' ') |
| 645 | { | 823 | { |
| @@ -650,17 +828,17 @@ namespace cxxopts | @@ -650,17 +828,17 @@ namespace cxxopts | ||
| 650 | { | 828 | { |
| 651 | if (lastSpace == startLine) | 829 | if (lastSpace == startLine) |
| 652 | { | 830 | { |
| 653 | - result.append(startLine, current + 1); | ||
| 654 | - result.append("\n"); | ||
| 655 | - result.append(start, ' '); | 831 | + stringAppend(result, startLine, current + 1); |
| 832 | + stringAppend(result, "\n"); | ||
| 833 | + stringAppend(result, start, ' '); | ||
| 656 | startLine = current + 1; | 834 | startLine = current + 1; |
| 657 | lastSpace = startLine; | 835 | lastSpace = startLine; |
| 658 | } | 836 | } |
| 659 | else | 837 | else |
| 660 | { | 838 | { |
| 661 | - result.append(startLine, lastSpace); | ||
| 662 | - result.append("\n"); | ||
| 663 | - result.append(start, ' '); | 839 | + stringAppend(result, startLine, lastSpace); |
| 840 | + stringAppend(result, "\n"); | ||
| 841 | + stringAppend(result, start, ' '); | ||
| 664 | startLine = lastSpace + 1; | 842 | startLine = lastSpace + 1; |
| 665 | } | 843 | } |
| 666 | size = 0; | 844 | size = 0; |
| @@ -674,7 +852,7 @@ namespace cxxopts | @@ -674,7 +852,7 @@ namespace cxxopts | ||
| 674 | } | 852 | } |
| 675 | 853 | ||
| 676 | //append whatever is left | 854 | //append whatever is left |
| 677 | - result.append(startLine, current); | 855 | + stringAppend(result, startLine, current); |
| 678 | 856 | ||
| 679 | return result; | 857 | return result; |
| 680 | } | 858 | } |
| @@ -921,11 +1099,12 @@ Options::add_option | @@ -921,11 +1099,12 @@ Options::add_option | ||
| 921 | const std::string& group, | 1099 | const std::string& group, |
| 922 | const std::string& s, | 1100 | const std::string& s, |
| 923 | const std::string& l, | 1101 | const std::string& l, |
| 924 | - const std::string& desc, | 1102 | + std::string desc, |
| 925 | std::shared_ptr<const Value> value | 1103 | std::shared_ptr<const Value> value |
| 926 | ) | 1104 | ) |
| 927 | { | 1105 | { |
| 928 | - auto option = std::make_shared<OptionDetails>(desc, value); | 1106 | + auto stringDesc = toLocalString(std::move(desc)); |
| 1107 | + auto option = std::make_shared<OptionDetails>(stringDesc, value); | ||
| 929 | 1108 | ||
| 930 | if (s.size() > 0) | 1109 | if (s.size() > 0) |
| 931 | { | 1110 | { |
| @@ -939,7 +1118,8 @@ Options::add_option | @@ -939,7 +1118,8 @@ Options::add_option | ||
| 939 | 1118 | ||
| 940 | //add the help details | 1119 | //add the help details |
| 941 | auto& options = m_help[group]; | 1120 | auto& options = m_help[group]; |
| 942 | - options.options.emplace_back(HelpOptionDetails{s, l, desc, | 1121 | + |
| 1122 | + options.options.emplace_back(HelpOptionDetails{s, l, stringDesc, | ||
| 943 | value->has_arg(), value->has_default(), value->get_default_value()}); | 1123 | value->has_arg(), value->has_default(), value->get_default_value()}); |
| 944 | } | 1124 | } |
| 945 | 1125 | ||
| @@ -958,10 +1138,10 @@ Options::add_one_option | @@ -958,10 +1138,10 @@ Options::add_one_option | ||
| 958 | } | 1138 | } |
| 959 | } | 1139 | } |
| 960 | 1140 | ||
| 961 | -std::string | 1141 | +String |
| 962 | Options::help_one_group(const std::string& g) const | 1142 | Options::help_one_group(const std::string& g) const |
| 963 | { | 1143 | { |
| 964 | - typedef std::vector<std::pair<std::string, std::string>> OptionHelp; | 1144 | + typedef std::vector<std::pair<String, String>> OptionHelp; |
| 965 | 1145 | ||
| 966 | auto group = m_help.find(g); | 1146 | auto group = m_help.find(g); |
| 967 | if (group == m_help.end()) | 1147 | if (group == m_help.end()) |
| @@ -973,18 +1153,19 @@ Options::help_one_group(const std::string& g) const | @@ -973,18 +1153,19 @@ Options::help_one_group(const std::string& g) const | ||
| 973 | 1153 | ||
| 974 | size_t longest = 0; | 1154 | size_t longest = 0; |
| 975 | 1155 | ||
| 976 | - std::string result; | 1156 | + String result; |
| 977 | 1157 | ||
| 978 | if (!g.empty()) | 1158 | if (!g.empty()) |
| 979 | { | 1159 | { |
| 980 | - result += " " + g + " options:\n\n"; | 1160 | + result += toLocalString(" " + g + " options:\n\n"); |
| 981 | } | 1161 | } |
| 982 | 1162 | ||
| 983 | for (const auto& o : group->second.options) | 1163 | for (const auto& o : group->second.options) |
| 984 | { | 1164 | { |
| 985 | auto s = format_option(o); | 1165 | auto s = format_option(o); |
| 986 | longest = std::max(longest, s.size()); | 1166 | longest = std::max(longest, s.size()); |
| 987 | - format.push_back(std::make_pair(s, std::string())); | 1167 | + longest = std::max(longest, stringLength(s)); |
| 1168 | + format.push_back(std::make_pair(s, String())); | ||
| 988 | } | 1169 | } |
| 989 | 1170 | ||
| 990 | longest = std::min(longest, static_cast<size_t>(OPTION_LONGEST)); | 1171 | longest = std::min(longest, static_cast<size_t>(OPTION_LONGEST)); |
| @@ -998,15 +1179,16 @@ Options::help_one_group(const std::string& g) const | @@ -998,15 +1179,16 @@ Options::help_one_group(const std::string& g) const | ||
| 998 | auto d = format_description(o.desc, longest + OPTION_DESC_GAP, allowed); | 1179 | auto d = format_description(o.desc, longest + OPTION_DESC_GAP, allowed); |
| 999 | 1180 | ||
| 1000 | result += fiter->first; | 1181 | result += fiter->first; |
| 1001 | - if (fiter->first.size() > longest) | 1182 | + if (stringLength(fiter->first) > longest) |
| 1002 | { | 1183 | { |
| 1003 | result += "\n"; | 1184 | result += "\n"; |
| 1004 | - result += std::string(longest + OPTION_DESC_GAP, ' '); | 1185 | + result += toLocalString(std::string(longest + OPTION_DESC_GAP, ' ')); |
| 1005 | } | 1186 | } |
| 1006 | else | 1187 | else |
| 1007 | { | 1188 | { |
| 1008 | - result += std::string(longest + OPTION_DESC_GAP - fiter->first.size(), | ||
| 1009 | - ' '); | 1189 | + result += toLocalString(std::string(longest + OPTION_DESC_GAP - |
| 1190 | + stringLength(fiter->first), | ||
| 1191 | + ' ')); | ||
| 1010 | } | 1192 | } |
| 1011 | result += d; | 1193 | result += d; |
| 1012 | result += "\n"; | 1194 | result += "\n"; |
| @@ -1020,15 +1202,19 @@ Options::help_one_group(const std::string& g) const | @@ -1020,15 +1202,19 @@ Options::help_one_group(const std::string& g) const | ||
| 1020 | std::string | 1202 | std::string |
| 1021 | Options::help(const std::vector<std::string>& groups) const | 1203 | Options::help(const std::vector<std::string>& groups) const |
| 1022 | { | 1204 | { |
| 1023 | - std::string result = "Usage:\n " + m_program + " [OPTION...]" | 1205 | + String result = "Usage:\n " + toLocalString(m_program) + " [OPTION...]" |
| 1024 | + m_help_string + "\n\n"; | 1206 | + m_help_string + "\n\n"; |
| 1025 | 1207 | ||
| 1026 | - for (const auto& g : groups) | 1208 | + for (std::size_t i = 0; i < groups.size(); ++i) |
| 1027 | { | 1209 | { |
| 1028 | - result += help_one_group(g); | 1210 | + result += help_one_group(groups[i]); |
| 1211 | + if (i < groups.size() - 1) | ||
| 1212 | + { | ||
| 1213 | + result += "\n"; | ||
| 1214 | + } | ||
| 1029 | } | 1215 | } |
| 1030 | 1216 | ||
| 1031 | - return result; | 1217 | + return toUTF8String(result); |
| 1032 | } | 1218 | } |
| 1033 | 1219 | ||
| 1034 | } | 1220 | } |
src/example.cpp
| @@ -48,6 +48,10 @@ int main(int argc, char* argv[]) | @@ -48,6 +48,10 @@ int main(int argc, char* argv[]) | ||
| 48 | ("help", "Print help") | 48 | ("help", "Print help") |
| 49 | ("int", "An integer", cxxopts::value<int>()) | 49 | ("int", "An integer", cxxopts::value<int>()) |
| 50 | ("option_that_is_too_long_for_the_help", "A very long option") | 50 | ("option_that_is_too_long_for_the_help", "A very long option") |
| 51 | + #ifdef CXXOPTS_USE_UNICODE | ||
| 52 | + ("unicode", u8"A help option with non-ascii: à. Here the size of the" | ||
| 53 | + " string should be correct") | ||
| 54 | + #endif | ||
| 51 | ; | 55 | ; |
| 52 | 56 | ||
| 53 | options.add_options("Group") | 57 | options.add_options("Group") |