diff --git a/examples/actions.cpp b/examples/actions.cpp index c1183f6..afbabc2 100644 --- a/examples/actions.cpp +++ b/examples/actions.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/align.cpp b/examples/align.cpp index fb795bf..ae98304 100644 --- a/examples/align.cpp +++ b/examples/align.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/alternatives.cpp b/examples/alternatives.cpp index 900a657..342ece2 100644 --- a/examples/alternatives.cpp +++ b/examples/alternatives.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/annotate.cpp b/examples/annotate.cpp index 4660243..d30f034 100644 --- a/examples/annotate.cpp +++ b/examples/annotate.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/argv0.cpp b/examples/argv0.cpp index 58200ca..bd30456 100644 --- a/examples/argv0.cpp +++ b/examples/argv0.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/commands.cpp b/examples/commands.cpp index e15e5dd..18abd6d 100644 --- a/examples/commands.cpp +++ b/examples/commands.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/complex_nesting.cpp b/examples/complex_nesting.cpp index f731484..f988a11 100644 --- a/examples/complex_nesting.cpp +++ b/examples/complex_nesting.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/convert.cpp b/examples/convert.cpp index c26bd8e..c3c93f0 100644 --- a/examples/convert.cpp +++ b/examples/convert.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/counter.cpp b/examples/counter.cpp index eefb589..7d5f2d4 100644 --- a/examples/counter.cpp +++ b/examples/counter.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/doc_filter.cpp b/examples/doc_filter.cpp index 822fa9d..c6662fa 100644 --- a/examples/doc_filter.cpp +++ b/examples/doc_filter.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/documentation.cpp b/examples/documentation.cpp index 579fcf1..9aa195f 100644 --- a/examples/documentation.cpp +++ b/examples/documentation.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/finder.cpp b/examples/finder.cpp index c5d0866..002060e 100644 --- a/examples/finder.cpp +++ b/examples/finder.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/float_vector.cpp b/examples/float_vector.cpp index d2787ef..6b11ade 100644 --- a/examples/float_vector.cpp +++ b/examples/float_vector.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/groups.cpp b/examples/groups.cpp index 939f1bd..ca6a386 100644 --- a/examples/groups.cpp +++ b/examples/groups.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/joinable_flags.cpp b/examples/joinable_flags.cpp index 5cae296..f6c11a4 100644 --- a/examples/joinable_flags.cpp +++ b/examples/joinable_flags.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/model.cpp b/examples/model.cpp index ed8c081..4174b84 100644 --- a/examples/model.cpp +++ b/examples/model.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/naval_fate.cpp b/examples/naval_fate.cpp index 651fad8..d200f59 100644 --- a/examples/naval_fate.cpp +++ b/examples/naval_fate.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * * * This command line interface example was taken from http://docopt.org/. diff --git a/examples/nested_alternatives.cpp b/examples/nested_alternatives.cpp index 3306885..6ae1f6e 100644 --- a/examples/nested_alternatives.cpp +++ b/examples/nested_alternatives.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/numbers.cpp b/examples/numbers.cpp index fcc2624..f89044f 100644 --- a/examples/numbers.cpp +++ b/examples/numbers.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/options.cpp b/examples/options.cpp index 268cc9b..23f8ca6 100644 --- a/examples/options.cpp +++ b/examples/options.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/options_values.cpp b/examples/options_values.cpp index f91eb6d..4988c62 100644 --- a/examples/options_values.cpp +++ b/examples/options_values.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/parsing.cpp b/examples/parsing.cpp index eb1e8ee..e56f8c1 100644 --- a/examples/parsing.cpp +++ b/examples/parsing.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/positional_values.cpp b/examples/positional_values.cpp index b5410cf..a49ee27 100644 --- a/examples/positional_values.cpp +++ b/examples/positional_values.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/repeatable.cpp b/examples/repeatable.cpp index b358ddc..7e63571 100644 --- a/examples/repeatable.cpp +++ b/examples/repeatable.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/required_flags.cpp b/examples/required_flags.cpp index 72b66fa..b6b9eaa 100644 --- a/examples/required_flags.cpp +++ b/examples/required_flags.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/sanity.cpp b/examples/sanity.cpp index b29c94e..bf215a7 100644 --- a/examples/sanity.cpp +++ b/examples/sanity.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/send.cpp b/examples/send.cpp index edc18c7..4143ce2 100644 --- a/examples/send.cpp +++ b/examples/send.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/simplify.cpp b/examples/simplify.cpp index 2e22695..a1c142c 100644 --- a/examples/simplify.cpp +++ b/examples/simplify.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/switches.cpp b/examples/switches.cpp index b8ebc43..7840197 100644 --- a/examples/switches.cpp +++ b/examples/switches.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/tagnames.cpp b/examples/tagnames.cpp index 25d4bf2..a787832 100644 --- a/examples/tagnames.cpp +++ b/examples/tagnames.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/text_formatting.cpp b/examples/text_formatting.cpp index 445ba87..736da23 100644 --- a/examples/text_formatting.cpp +++ b/examples/text_formatting.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/timing.cpp b/examples/timing.cpp index 66a9dd0..15f05d1 100644 --- a/examples/timing.cpp +++ b/examples/timing.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/examples/transform.cpp b/examples/transform.cpp index 43102b5..e49eb2a 100644 --- a/examples/transform.cpp +++ b/examples/transform.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/include/clipp.h b/include/clipp.h index 625aeb3..6fcf0cc 100644 --- a/include/clipp.h +++ b/include/clipp.h @@ -1,11 +1,11 @@ /***************************************************************************** * ___ _ _ ___ ___ * | _|| | | | | _ \ _ \ CLIPP - command line interfaces for modern C++ - * | |_ | |_ | | | _/ _/ version 1.2.1 + * | |_ | |_ | | | _/ _/ version 1.2.2 * |___||___||_| |_| |_| https://github.com/muellan/clipp * * Licensed under the MIT License . - * Copyright (c) 2017-18 André Müller + * Copyright (c) 2017-2018 André Müller * * --------------------------------------------------------------------------- * Permission is hereby granted, free of charge, to any person obtaining a @@ -2829,12 +2829,12 @@ class group : return int(stack_.size()); } - bool is_first_in_group() const noexcept { + bool is_first_in_parent() const noexcept { if(stack_.empty()) return false; return (stack_.back().cur == stack_.back().parent->begin()); } - bool is_last_in_group() const noexcept { + bool is_last_in_parent() const noexcept { if(stack_.empty()) return false; return (stack_.back().cur+1 == stack_.back().end); } @@ -2868,6 +2868,14 @@ class group : return std::any_of(stack_.begin() + minlevel, stack_.end(), [](const context& c) { return c.parent->repeatable(); }); } + + /** @brief inside a particular group */ + bool is_inside(const group* g) const noexcept { + if(!g) return false; + return std::any_of(stack_.begin(), stack_.end(), + [g](const context& c) { return c.parent == g; }); + } + /** @brief inside group with joinable flags */ bool joinable() const noexcept { if(stack_.empty()) return false; @@ -2882,16 +2890,47 @@ class group : /** @brief innermost repeat group */ const group* - repeat_group() const noexcept { + innermost_repeat_group() const noexcept { auto i = std::find_if(stack_.rbegin(), stack_.rend(), [](const context& c) { return c.parent->repeatable(); }); + return i != stack_.rend() ? i->parent : nullptr; + } + /** @brief innermost exclusive (alternatives) group */ + const group* + innermost_exclusive_group() const noexcept { + auto i = std::find_if(stack_.rbegin(), stack_.rend(), + [](const context& c) { return c.parent->exclusive(); }); + return i != stack_.rend() ? i->parent : nullptr; + } + + /** @brief innermost blocking group */ + const group* + innermost_blocking_group() const noexcept { + auto i = std::find_if(stack_.rbegin(), stack_.rend(), + [](const context& c) { return c.parent->blocking(); }); return i != stack_.rend() ? i->parent : nullptr; } + /** @brief returns the outermost group that will be left on next ++*/ + const group* + outermost_blocking_group_fully_explored() const noexcept { + if(stack_.empty()) return nullptr; + + const group* g = nullptr; + for(auto i = stack_.rbegin(); i != stack_.rend(); ++i) { + if(i->cur+1 == i->end) { + if(i->parent->blocking()) g = i->parent; + } else { + return g; + } + } + return g; + } + /** @brief outermost join group */ const group* - join_group() const noexcept { + outermost_join_group() const noexcept { auto i = std::find_if(stack_.begin(), stack_.end(), [](const context& c) { return c.parent->joinable(); }); return i != stack_.end() ? i->parent : nullptr; @@ -2904,7 +2943,7 @@ class group : /** @brief common flag prefix of all flags in current group */ arg_string common_flag_prefix() const noexcept { if(stack_.empty()) return ""; - auto g = join_group(); + auto g = outermost_join_group(); return g ? g->common_flag_prefix() : arg_string(""); } @@ -2963,29 +3002,17 @@ class group : return *this; } - /** @brief skips to next alternative in innermost group - */ - depth_first_traverser& - next_alternative() { - if(stack_.empty()) return *this; - - //find first exclusive group (from the top of the stack!) - auto i = std::find_if(stack_.rbegin(), stack_.rend(), - [](const context& c) { return c.parent->exclusive(); }); - if(i == stack_.rend()) return *this; - - stack_.erase(i.base(), stack_.end()); - next_sibling(); - return *this; - } - /** * @brief */ depth_first_traverser& - back_to_parent() { - if(stack_.empty()) return *this; - stack_.pop_back(); + back_to_ancestor(const group* g) { + if(!g) return *this; + while(!stack_.empty()) { + const auto& top = stack_.back().cur; + if(top->is_group() && &(top->as_group()) == g) return *this; + stack_.pop_back(); + } return *this; } @@ -4044,7 +4071,7 @@ class scoped_dfs_traverser explicit scoped_dfs_traverser(const group& g): pos_{g}, lastMatch_{}, posAfterLastMatch_{}, scopes_{}, - curMatched_{false}, ignoreBlocks_{false}, + ignoreBlocks_{false}, repeatGroupStarted_{false}, repeatGroupContinues_{false} {} @@ -4052,8 +4079,19 @@ class scoped_dfs_traverser const dfs_traverser& last_match() const noexcept { return lastMatch_; } const group& parent() const noexcept { return pos_.parent(); } - const group* repeat_group() const noexcept { return pos_.repeat_group(); } - const group* join_group() const noexcept { return pos_.join_group(); } + + const group* innermost_repeat_group() const noexcept { + return pos_.innermost_repeat_group(); + } + const group* outermost_join_group() const noexcept { + return pos_.outermost_join_group(); + } + const group* innermost_blocking_group() const noexcept { + return pos_.innermost_blocking_group(); + } + const group* innermost_exclusive_group() const noexcept { + return pos_.innermost_exclusive_group(); + } const pattern* operator ->() const noexcept { return pos_.operator->(); } const pattern& operator *() const noexcept { return *pos_; } @@ -4067,8 +4105,13 @@ class scoped_dfs_traverser void ignore_blocking(bool yes) { ignoreBlocks_ = yes; } - void invalidate() { pos_.invalidate(); curMatched_ = false; } - bool matched() const noexcept { return curMatched_; } + void invalidate() { + pos_.invalidate(); + } + + bool matched() const noexcept { + return (pos_ == lastMatch_); + } bool start_of_repeat_group() const noexcept { return repeatGroupStarted_; } @@ -4076,12 +4119,10 @@ class scoped_dfs_traverser scoped_dfs_traverser& next_sibling() { pos_.next_sibling(); return *this; } - scoped_dfs_traverser& - next_alternative() { pos_.next_alternative(); return *this; } - scoped_dfs_traverser& next_after_siblings() { pos_.next_after_siblings(); return *this; } + //----------------------------------------------------- scoped_dfs_traverser& operator ++ () @@ -4094,20 +4135,20 @@ class scoped_dfs_traverser } //current pattern can block if it didn't match already - if(!ignoreBlocks_ && !matched()) { + if(ignoreBlocks_ || matched()) { + ++pos_; + } + else if(!pos_->is_group()) { //current group can block if we didn't have any match in it - if(pos_.is_last_in_group() && pos_.parent().blocking() - && (!posAfterLastMatch_ || &(posAfterLastMatch_.parent()) != &(pos_.parent()))) - { - //ascend to parent's level - ++pos_; - //skip all siblings of parent group - pos_.next_after_siblings(); + const group* g = pos_.outermost_blocking_group_fully_explored(); + //no match in 'g' before -> skip to after its siblings + if(g && !lastMatch_.is_inside(g)) { + pos_.back_to_ancestor(g).next_after_siblings(); if(!pos_) return_to_outermost_scope(); } - else if(pos_->blocking() && !pos_->is_group()) { - if(pos_.parent().exclusive()) { //is_alternative(pos_.level())) { - pos_.next_alternative(); + else if(pos_->blocking()) { + if(pos_.parent().exclusive()) { + pos_.next_sibling(); } else { //no match => skip siblings of blocking param pos_.next_after_siblings(); @@ -4132,8 +4173,9 @@ class scoped_dfs_traverser lastMatch_ = match.base(); - if(!match->blocking() && match.base().parent().blocking()) { - match.pos_.back_to_parent(); + // if there is a blocking ancestor -> go back to it + if(!match->blocking()) { + match.pos_.back_to_ancestor(match.innermost_blocking_group()); } //if match is not in current position & current position is blocking @@ -4151,22 +4193,17 @@ class scoped_dfs_traverser if(is_last_in_current_scope(match.pos_)) { //if current param is not repeatable -> back to previous scope if(!match->repeatable() && !match->is_group()) { - curMatched_ = false; pos_ = std::move(match.pos_); if(!scopes_.empty()) pos_.undo(scopes_.top()); } else { //stay at match position - curMatched_ = true; pos_ = std::move(match.pos_); } } else { //not last in current group //if current param is not repeatable, go directly to next if(!match->repeatable() && !match->is_group()) { - curMatched_ = false; ++match.pos_; - } else { - curMatched_ = true; } if(match.pos_.level() > pos_.level()) { @@ -4193,7 +4230,7 @@ class scoped_dfs_traverser private: //----------------------------------------------------- - bool is_last_in_current_scope(const dfs_traverser& pos) + bool is_last_in_current_scope(const dfs_traverser& pos) const { if(scopes_.empty()) return pos.is_last_in_path(); //check if we would leave the current scope on ++ @@ -4205,11 +4242,11 @@ class scoped_dfs_traverser //----------------------------------------------------- void check_repeat_group_start(const scoped_dfs_traverser& newMatch) { - const auto newrg = newMatch.repeat_group(); + const auto newrg = newMatch.innermost_repeat_group(); if(!newrg) { repeatGroupStarted_ = false; } - else if(lastMatch_.repeat_group() != newrg) { + else if(lastMatch_.innermost_repeat_group() != newrg) { repeatGroupStarted_ = true; } else if(!repeatGroupContinues_ || !newMatch.repeatGroupContinues_) { @@ -4228,12 +4265,12 @@ class scoped_dfs_traverser } //----------------------------------------------------- - bool repeat_group_continues() + bool repeat_group_continues() const { if(!repeatGroupContinues_) return false; - const auto curRepGroup = pos_.repeat_group(); + const auto curRepGroup = pos_.innermost_repeat_group(); if(!curRepGroup) return false; - if(curRepGroup != lastMatch_.repeat_group()) return false; + if(curRepGroup != lastMatch_.innermost_repeat_group()) return false; if(!posAfterLastMatch_) return false; return true; } @@ -4291,7 +4328,6 @@ class scoped_dfs_traverser dfs_traverser lastMatch_; dfs_traverser posAfterLastMatch_; std::stack scopes_; - bool curMatched_ = false; bool ignoreBlocks_ = false; bool repeatGroupStarted_ = false; bool repeatGroupContinues_ = false; @@ -4495,7 +4531,7 @@ class parser bool bad_repeat() const noexcept { if(!param()) return false; return repeat_ > 0 && !param()->repeatable() - && !match_.repeat_group(); + && !match_.innermost_repeat_group(); } bool any_error() const noexcept { @@ -4946,13 +4982,13 @@ class parser ++npos; //need to add potential misses if: //either new repeat group was started - const auto newRepGroup = match.repeat_group(); + const auto newRepGroup = match.innermost_repeat_group(); if(newRepGroup) { if(pos_.start_of_repeat_group()) { for_each_potential_miss(std::move(npos), [&,this](const dfs_traverser& pos) { //only add candidates within repeat group - if(newRepGroup == pos.repeat_group()) { + if(newRepGroup == pos.innermost_repeat_group()) { missCand_.emplace_back(pos, index_, true); } }); @@ -5008,6 +5044,8 @@ class parser //--------------------------------------------------------------- std::size_t occurrences_of(const parameter* p) const { + if(!p) return 0; + auto i = std::find_if(args_.rbegin(), args_.rend(), [p](const arg_mapping& a){ return a.param() == p; }); @@ -6123,7 +6161,7 @@ class usage_lines do { if(buf.tellp() > initPos) cur.linestart = false; - if(!cur.linestart && !cur.pos.is_first_in_group()) { + if(!cur.linestart && !cur.pos.is_first_in_parent()) { buf << cur.separators.top(); } if(cur.pos->is_group()) { @@ -6244,7 +6282,7 @@ class usage_lines const auto& parent = cur.pos.parent(); const bool startsOptionalSequence = - parent.size() > 1 && p.blocking() && cur.pos.is_first_in_group(); + parent.size() > 1 && p.blocking() && cur.pos.is_first_in_parent(); const bool outermost = ommitOutermostSurrounders_ && cur.outermost == &parent; @@ -6961,7 +6999,7 @@ void print(OStream& os, const group& g, int level) { auto indent = doc_string(4*level, ' '); os << indent; - if(g.blocking()) os << '!'; + if(g.blocking()) os << '~'; if(g.joinable()) os << 'J'; os << (g.exclusive() ? "(|\n" : "(\n"); for(const auto& p : g) { diff --git a/test/actions_test.cpp b/test/actions_test.cpp index cfda527..be8dfdd 100644 --- a/test/actions_test.cpp +++ b/test/actions_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * * Tests: "missing" detection for required parameters * 'if_missing' error handler should be called: diff --git a/test/alternative_groups_test.cpp b/test/alternative_groups_test.cpp index 6c02f63..0e6cabb 100644 --- a/test/alternative_groups_test.cpp +++ b/test/alternative_groups_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/alternative_options_test.cpp b/test/alternative_options_test.cpp index e247d7f..1de1c62 100644 --- a/test/alternative_options_test.cpp +++ b/test/alternative_options_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/alternative_required_test.cpp b/test/alternative_required_test.cpp index 21c7894..470d6f3 100644 --- a/test/alternative_required_test.cpp +++ b/test/alternative_required_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test1.cpp b/test/blocking_test01.cpp similarity index 98% rename from test/blocking_test1.cpp rename to test/blocking_test01.cpp index 8723a9d..3b00456 100644 --- a/test/blocking_test1.cpp +++ b/test/blocking_test01.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test2.cpp b/test/blocking_test02.cpp similarity index 95% rename from test/blocking_test2.cpp rename to test/blocking_test02.cpp index 9a1e6e3..209d563 100644 --- a/test/blocking_test2.cpp +++ b/test/blocking_test02.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ @@ -40,21 +40,23 @@ void test(int lineNo, auto cli = ( ( command("a"), option("-x").set(m.a) - ) | + ).doc("group (~a,-x)") + | ( command("b"), option("-x").set(m.b), ( command("u").set(m.i,1) | command("v").set(m.i,2) | command("w").set(m.i,3) - ), + ).doc("group (u|v|w)"), option("-e").set(m.e) - ) | + ).doc("group (~b,-x,(~u|~v|~w),-e)") + | ( command("c"), option("-x").set(m.c), command("d").set(m.d), required("-i").set(m.e) & value("i", m.i), option("-f").set(m.f) - ) + ).doc("group (~c,-x,d,(~-i,~i),-f)") ); run_wrapped_variants({ __FILE__, lineNo }, args, cli, diff --git a/test/blocking_test3.cpp b/test/blocking_test03.cpp similarity index 98% rename from test/blocking_test3.cpp rename to test/blocking_test03.cpp index bcec1ba..6c1cb48 100644 --- a/test/blocking_test3.cpp +++ b/test/blocking_test03.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test4.cpp b/test/blocking_test04.cpp similarity index 98% rename from test/blocking_test4.cpp rename to test/blocking_test04.cpp index b05328d..79e92a9 100644 --- a/test/blocking_test4.cpp +++ b/test/blocking_test04.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test5.cpp b/test/blocking_test05.cpp similarity index 99% rename from test/blocking_test5.cpp rename to test/blocking_test05.cpp index 153ad92..bd7174b 100644 --- a/test/blocking_test5.cpp +++ b/test/blocking_test05.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test6.cpp b/test/blocking_test06.cpp similarity index 63% rename from test/blocking_test6.cpp rename to test/blocking_test06.cpp index e523c5e..0e6f596 100644 --- a/test/blocking_test6.cpp +++ b/test/blocking_test06.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ @@ -36,24 +36,98 @@ void test(int lineNo, active m; - auto cli = ( + auto cli1 = ( ( option("a").set(m.a), option("b").set(m.b), option("c").set(m.c) - ) & ( + ).doc("group abc") + & ( option("d").set(m.d), option("e").set(m.e), option("f").set(m.f) - ) + ).doc("group def") ); - run_wrapped_variants({ __FILE__, lineNo }, args, cli, + run_wrapped_variants({ __FILE__, lineNo }, args, cli1, [&]{ m = active{}; }, [&]{ return m == matches; }); + + + auto cli2 = ( + ( + option("x"), + ( + option("a").set(m.a), + option("b").set(m.b), + option("c").set(m.c) + ).doc("group abc") + ).doc("group x(abc)") + & ( + option("d").set(m.d), + option("e").set(m.e), + option("f").set(m.f) + ).doc("group def") + ); + + run_wrapped_variants({ __FILE__, lineNo }, args, cli2, + [&]{ m = active{}; }, + [&]{ return m == matches; }); + + + auto cli3 = ( + ( + ( option("a").set(m.a), + option("b").set(m.b) + ).doc("group ab") + , + option("c").set(m.c) + ).doc("group (ab)c") + & ( + ( option("d").set(m.d), + option("e").set(m.e) + ).doc("group de") + , + option("f").set(m.f) + ).doc("group (de)f") + ); + + run_wrapped_variants({ __FILE__, lineNo }, args, cli3, + [&]{ m = active{}; }, + [&]{ return m == matches; }); + + + auto cli4 = ( + ( + ( + ( option("a").set(m.a), + option("b").set(m.b) + ).doc("group ab") + , + option("c").set(m.c) + ).doc("group (ab)c"), + option("x") + ).doc("group ((ab)c)x") + & ( + ( + ( option("d").set(m.d), + option("e").set(m.e) + ).doc("group de") + , + option("f").set(m.f) + ).doc("group (de)f"), + option("y") + ).doc("group ((de)f)y") + ); + + run_wrapped_variants({ __FILE__, lineNo }, args, cli4, + [&]{ m = active{}; }, + [&]{ return m == matches; }); + } + //------------------------------------------------------------------- int main() { diff --git a/test/blocking_test7.cpp b/test/blocking_test07.cpp similarity index 98% rename from test/blocking_test7.cpp rename to test/blocking_test07.cpp index 7596d31..343fff5 100644 --- a/test/blocking_test7.cpp +++ b/test/blocking_test07.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test8.cpp b/test/blocking_test08.cpp similarity index 98% rename from test/blocking_test8.cpp rename to test/blocking_test08.cpp index 019d5bc..83beae7 100644 --- a/test/blocking_test8.cpp +++ b/test/blocking_test08.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test9.cpp b/test/blocking_test09.cpp similarity index 98% rename from test/blocking_test9.cpp rename to test/blocking_test09.cpp index 68c72ab..62dc904 100644 --- a/test/blocking_test9.cpp +++ b/test/blocking_test09.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/blocking_test10.cpp b/test/blocking_test10.cpp new file mode 100644 index 0000000..d1624ee --- /dev/null +++ b/test/blocking_test10.cpp @@ -0,0 +1,83 @@ +/***************************************************************************** + * + * CLIPP - command line interfaces for modern C++ + * + * released under MIT license + * + * (c) 2017-2018 André Müller; foss@andremueller-online.de + * + *****************************************************************************/ + +#include "testing.h" + + +//------------------------------------------------------------------- +struct active { + active() = default; + explicit + active(bool n_, std::initializer_list nums_, + bool s_, const std::string& str_) + : + str{str_}, nums{nums_}, n{n_}, s{s_} + {} + + std::string str; + std::vector nums; + bool n = false, s = false; + + friend bool operator == (const active& x, const active& y) noexcept { + return x.n == y.n && x.s == y.s && x.str == y.str && + std::equal(x.nums.begin(), x.nums.end(), y.nums.begin()); + } +}; + + +//------------------------------------------------------------------- +void test(int lineNo, + const std::initializer_list args, + const active& matches) +{ + using namespace clipp; + + active m; + + auto cli = ( + option("-n", "--num").set(m.n) & integers("nums", m.nums), + option("-s", "--str").set(m.s) & value("str", m.str) + ); + + run_wrapped_variants({ __FILE__, lineNo }, args, cli, + [&]{ m = active{}; }, + [&]{ return m == matches; }); +} + + +//------------------------------------------------------------------- +int main() +{ + try { + test(__LINE__, {""}, active{}); + + + test(__LINE__, {"-n"}, active{true, {}, false, ""}); + test(__LINE__, {"-n", "1"}, active{true, {1}, false, ""}); + test(__LINE__, {"-n", "1", "5"}, active{true, {1,5}, false, ""}); + test(__LINE__, {"-n", "1", "-3", "4"}, active{true, {1,-3,4}, false, ""}); + + test(__LINE__, {"-s"}, active{false, {}, true, ""}); + test(__LINE__, {"-s", "xyz"}, active{false, {}, true, "xyz"}); + + test(__LINE__, {"-n", "1", "ab"}, active{true, {1}, false, ""}); + test(__LINE__, {"-n", "1", "2", "ab"}, active{true, {1,2}, false, ""}); + test(__LINE__, {"-n", "1", "-3", "ab"}, active{true, {1,-3}, false, ""}); + + test(__LINE__, {"-n", "1", "-s", "ab"}, active{true, {1}, true, "ab"}); + test(__LINE__, {"-n", "1", "2", "-s", "ab"}, active{true, {1,2}, true, "ab"}); + test(__LINE__, {"-n", "1", "-3", "-s", "ab"}, active{true, {1,-3}, true, "ab"}); + + } + catch(std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} diff --git a/test/documentation_test.cpp b/test/documentation_test.cpp index 3b11a44..9885475 100644 --- a/test/documentation_test.cpp +++ b/test/documentation_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/empty_args.cpp b/test/empty_args.cpp index 90c865a..86915a4 100644 --- a/test/empty_args.cpp +++ b/test/empty_args.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017-2018 André Müller; foss@andremueller-online.de + * (c) 2017-2018-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/flag_param_factories_test.cpp b/test/flag_param_factories_test.cpp index 2810919..b89c183 100644 --- a/test/flag_param_factories_test.cpp +++ b/test/flag_param_factories_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test1.cpp b/test/joined_flags_test1.cpp index f127615..15af3ed 100644 --- a/test/joined_flags_test1.cpp +++ b/test/joined_flags_test1.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test2.cpp b/test/joined_flags_test2.cpp index c09ee00..dd78490 100644 --- a/test/joined_flags_test2.cpp +++ b/test/joined_flags_test2.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test3.cpp b/test/joined_flags_test3.cpp index 211983e..7719620 100644 --- a/test/joined_flags_test3.cpp +++ b/test/joined_flags_test3.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test4.cpp b/test/joined_flags_test4.cpp index 6bca0d8..db75ccb 100644 --- a/test/joined_flags_test4.cpp +++ b/test/joined_flags_test4.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test5.cpp b/test/joined_flags_test5.cpp index 03a7e26..49d1851 100644 --- a/test/joined_flags_test5.cpp +++ b/test/joined_flags_test5.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_flags_test6.cpp b/test/joined_flags_test6.cpp index 979f708..9d59e08 100644 --- a/test/joined_flags_test6.cpp +++ b/test/joined_flags_test6.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_params_test1.cpp b/test/joined_params_test1.cpp index 0a83302..6a00873 100644 --- a/test/joined_params_test1.cpp +++ b/test/joined_params_test1.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_params_test2.cpp b/test/joined_params_test2.cpp index c07a2b8..f083b06 100644 --- a/test/joined_params_test2.cpp +++ b/test/joined_params_test2.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/joined_sequence_test.cpp b/test/joined_sequence_test.cpp index a40c3a1..474e289 100644 --- a/test/joined_sequence_test.cpp +++ b/test/joined_sequence_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/mixed_params_test.cpp b/test/mixed_params_test.cpp index 9a4c9b3..789b47a 100644 --- a/test/mixed_params_test.cpp +++ b/test/mixed_params_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/nesting_test.cpp b/test/nesting_test.cpp index 49e3ff7..54e5eca 100644 --- a/test/nesting_test.cpp +++ b/test/nesting_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/options_test.cpp b/test/options_test.cpp index dffd949..9df0adc 100644 --- a/test/options_test.cpp +++ b/test/options_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/prefix_free_test.cpp b/test/prefix_free_test.cpp index 237868d..90774f8 100644 --- a/test/prefix_free_test.cpp +++ b/test/prefix_free_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/repeatability_test.cpp b/test/repeatability_test.cpp index 359e401..3f9400d 100644 --- a/test/repeatability_test.cpp +++ b/test/repeatability_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/repeatable_alternatives_test.cpp b/test/repeatable_alternatives_test.cpp index d79a37f..ef8eff6 100644 --- a/test/repeatable_alternatives_test.cpp +++ b/test/repeatable_alternatives_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/required_params_test1.cpp b/test/required_params_test1.cpp index 32c7427..10faf56 100644 --- a/test/required_params_test1.cpp +++ b/test/required_params_test1.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/required_params_test2.cpp b/test/required_params_test2.cpp index 91698fe..41a5bca 100644 --- a/test/required_params_test2.cpp +++ b/test/required_params_test2.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/usage_lines_test.cpp b/test/usage_lines_test.cpp index bee57ff..3475035 100644 --- a/test/usage_lines_test.cpp +++ b/test/usage_lines_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/values_conversion_test.cpp b/test/values_conversion_test.cpp index c821cd9..15560b7 100644 --- a/test/values_conversion_test.cpp +++ b/test/values_conversion_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/values_filter_test.cpp b/test/values_filter_test.cpp index c5ab257..161747d 100644 --- a/test/values_filter_test.cpp +++ b/test/values_filter_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ diff --git a/test/values_sequencing_test.cpp b/test/values_sequencing_test.cpp index 44a2407..e955da4 100644 --- a/test/values_sequencing_test.cpp +++ b/test/values_sequencing_test.cpp @@ -4,7 +4,7 @@ * * released under MIT license * - * (c) 2017 André Müller; foss@andremueller-online.de + * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/