Embed Clara v1.1.1

This commit is contained in:
Phil Nash 2018-01-22 15:08:28 +00:00
parent b0f4f16ee0
commit 31e6499e64
2 changed files with 112 additions and 100 deletions

View File

@ -1,5 +1,11 @@
// v1.0-develop.2 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
// See https://github.com/philsquared/Clara //
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.1
#ifndef CATCH_CLARA_HPP_INCLUDED #ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED #define CATCH_CLARA_HPP_INCLUDED
@ -370,7 +376,7 @@ namespace detail {
template<typename ClassT, typename ReturnT, typename ArgT> template<typename ClassT, typename ReturnT, typename ArgT>
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
static const bool isValid = true; static const bool isValid = true;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;; using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
using ReturnType = ReturnT; using ReturnType = ReturnT;
}; };
@ -535,7 +541,7 @@ namespace detail {
return *this; return *this;
} }
~ResultValueBase() { ~ResultValueBase() override {
if( m_type == Ok ) if( m_type == Ok )
m_value.~T(); m_value.~T();
} }
@ -573,7 +579,7 @@ namespace detail {
auto errorMessage() const -> std::string { return m_errorMessage; } auto errorMessage() const -> std::string { return m_errorMessage; }
protected: protected:
virtual void enforceOk() const { void enforceOk() const override {
// !TBD: If no exceptions, std::terminate here or something // !TBD: If no exceptions, std::terminate here or something
switch( m_type ) { switch( m_type ) {
case ResultBase::LogicError: case ResultBase::LogicError:
@ -653,46 +659,30 @@ namespace detail {
return ParserResult::ok( ParseResultType::Matched ); return ParserResult::ok( ParseResultType::Matched );
} }
struct BoundRefBase { struct NonCopyable {
BoundRefBase() = default; NonCopyable() = default;
BoundRefBase( BoundRefBase const & ) = delete; NonCopyable( NonCopyable const & ) = delete;
BoundRefBase( BoundRefBase && ) = delete; NonCopyable( NonCopyable && ) = delete;
BoundRefBase &operator=( BoundRefBase const & ) = delete; NonCopyable &operator=( NonCopyable const & ) = delete;
BoundRefBase &operator=( BoundRefBase && ) = delete; NonCopyable &operator=( NonCopyable && ) = delete;
};
virtual ~BoundRefBase() = default; struct BoundRef : NonCopyable {
virtual ~BoundRef() = default;
virtual auto isFlag() const -> bool = 0;
virtual auto isContainer() const -> bool { return false; } virtual auto isContainer() const -> bool { return false; }
};
struct BoundValueRefBase : BoundRef {
virtual auto setValue( std::string const &arg ) -> ParserResult = 0; virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
};
struct BoundFlagRefBase : BoundRef {
virtual auto setFlag( bool flag ) -> ParserResult = 0; virtual auto setFlag( bool flag ) -> ParserResult = 0;
}; };
struct BoundValueRefBase : BoundRefBase {
auto isFlag() const -> bool override { return false; }
auto setFlag( bool ) -> ParserResult override {
return ParserResult::logicError( "Flags can only be set on boolean fields" );
}
};
struct BoundFlagRefBase : BoundRefBase {
auto isFlag() const -> bool override { return true; }
auto setValue( std::string const &arg ) -> ParserResult override {
bool flag;
auto result = convertInto( arg, flag );
if( result )
setFlag( flag );
return result;
}
};
template<typename T> template<typename T>
struct BoundRef : BoundValueRefBase { struct BoundValueRef : BoundValueRefBase {
T &m_ref; T &m_ref;
explicit BoundRef( T &ref ) : m_ref( ref ) {} explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
auto setValue( std::string const &arg ) -> ParserResult override { auto setValue( std::string const &arg ) -> ParserResult override {
return convertInto( arg, m_ref ); return convertInto( arg, m_ref );
@ -700,10 +690,10 @@ namespace detail {
}; };
template<typename T> template<typename T>
struct BoundRef<std::vector<T>> : BoundValueRefBase { struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref; std::vector<T> &m_ref;
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {} explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
auto isContainer() const -> bool override { return true; } auto isContainer() const -> bool override { return true; }
@ -748,12 +738,12 @@ namespace detail {
template<typename ArgType, typename L> template<typename ArgType, typename L>
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
ArgType temp; ArgType temp{};
auto result = convertInto( arg, temp ); auto result = convertInto( arg, temp );
return !result return !result
? result ? result
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
}; }
template<typename L> template<typename L>
@ -803,6 +793,9 @@ namespace detail {
public: public:
template<typename T> template<typename T>
auto operator|( T const &other ) const -> Parser; auto operator|( T const &other ) const -> Parser;
template<typename T>
auto operator+( T const &other ) const -> Parser;
}; };
// Common code and state for Args and Opts // Common code and state for Args and Opts
@ -810,16 +803,16 @@ namespace detail {
class ParserRefImpl : public ComposableParserImpl<DerivedT> { class ParserRefImpl : public ComposableParserImpl<DerivedT> {
protected: protected:
Optionality m_optionality = Optionality::Optional; Optionality m_optionality = Optionality::Optional;
std::shared_ptr<BoundRefBase> m_ref; std::shared_ptr<BoundRef> m_ref;
std::string m_hint; std::string m_hint;
std::string m_description; std::string m_description;
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {} explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
public: public:
template<typename T> template<typename T>
ParserRefImpl( T &ref, std::string const &hint ) ParserRefImpl( T &ref, std::string const &hint )
: m_ref( std::make_shared<BoundRef<T>>( ref ) ), : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint ) m_hint( hint )
{} {}
@ -860,10 +853,10 @@ namespace detail {
class ExeName : public ComposableParserImpl<ExeName> { class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<std::string> m_name; std::shared_ptr<std::string> m_name;
std::shared_ptr<BoundRefBase> m_ref; std::shared_ptr<BoundValueRefBase> m_ref;
template<typename LambdaT> template<typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> { static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>( lambda) ; return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
} }
@ -871,7 +864,7 @@ namespace detail {
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
explicit ExeName( std::string &ref ) : ExeName() { explicit ExeName( std::string &ref ) : ExeName() {
m_ref = std::make_shared<BoundRef<std::string>>( ref ); m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
} }
template<typename LambdaT> template<typename LambdaT>
@ -914,7 +907,10 @@ namespace detail {
if( token.type != TokenType::Argument ) if( token.type != TokenType::Argument )
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
auto result = m_ref->setValue( remainingTokens->token ); assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
auto result = valueRef->setValue( remainingTokens->token );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
else else
@ -987,20 +983,22 @@ namespace detail {
if( remainingTokens && remainingTokens->type == TokenType::Option ) { if( remainingTokens && remainingTokens->type == TokenType::Option ) {
auto const &token = *remainingTokens; auto const &token = *remainingTokens;
if( isMatch(token.token ) ) { if( isMatch(token.token ) ) {
if( m_ref->isFlag() ) { if( auto flagRef = dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) ) {
auto result = m_ref->setFlag( true ); auto result = flagRef->setFlag( true );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll ) if( result.value() == ParseResultType::ShortCircuitAll )
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
} else { } else {
assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
++remainingTokens; ++remainingTokens;
if( !remainingTokens ) if( !remainingTokens )
return InternalParseResult::runtimeError( "Expected argument following " + token.token ); return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto const &argToken = *remainingTokens; auto const &argToken = *remainingTokens;
if( argToken.type != TokenType::Argument ) if( argToken.type != TokenType::Argument )
return InternalParseResult::runtimeError( "Expected argument following " + token.token ); return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto result = m_ref->setValue( argToken.token ); auto result = valueRef->setValue( argToken.token );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll ) if( result.value() == ParseResultType::ShortCircuitAll )
@ -1077,6 +1075,12 @@ namespace detail {
return Parser( *this ) |= other; return Parser( *this ) |= other;
} }
// Forward deprecated interface with '+' instead of '|'
template<typename T>
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
template<typename T>
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols; std::vector<HelpColumns> cols;
for (auto const &o : m_options) { for (auto const &o : m_options) {
@ -1116,6 +1120,8 @@ namespace detail {
for( auto const &cols : rows ) for( auto const &cols : rows )
optWidth = (std::max)(optWidth, cols.left.size() + 2); optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth/2);
for( auto const &cols : rows ) { for( auto const &cols : rows ) {
auto row = auto row =
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +

106
third_party/clara.hpp vendored
View File

@ -1,5 +1,11 @@
// v1.0-develop.2 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
// See https://github.com/philsquared/Clara //
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.1
#ifndef CLARA_HPP_INCLUDED #ifndef CLARA_HPP_INCLUDED
#define CLARA_HPP_INCLUDED #define CLARA_HPP_INCLUDED
@ -370,7 +376,7 @@ namespace detail {
template<typename ClassT, typename ReturnT, typename ArgT> template<typename ClassT, typename ReturnT, typename ArgT>
struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> { struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
static const bool isValid = true; static const bool isValid = true;
using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;; using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
using ReturnType = ReturnT; using ReturnType = ReturnT;
}; };
@ -535,7 +541,7 @@ namespace detail {
return *this; return *this;
} }
~ResultValueBase() { ~ResultValueBase() override {
if( m_type == Ok ) if( m_type == Ok )
m_value.~T(); m_value.~T();
} }
@ -573,7 +579,7 @@ namespace detail {
auto errorMessage() const -> std::string { return m_errorMessage; } auto errorMessage() const -> std::string { return m_errorMessage; }
protected: protected:
virtual void enforceOk() const { void enforceOk() const override {
// !TBD: If no exceptions, std::terminate here or something // !TBD: If no exceptions, std::terminate here or something
switch( m_type ) { switch( m_type ) {
case ResultBase::LogicError: case ResultBase::LogicError:
@ -653,46 +659,30 @@ namespace detail {
return ParserResult::ok( ParseResultType::Matched ); return ParserResult::ok( ParseResultType::Matched );
} }
struct BoundRefBase { struct NonCopyable {
BoundRefBase() = default; NonCopyable() = default;
BoundRefBase( BoundRefBase const & ) = delete; NonCopyable( NonCopyable const & ) = delete;
BoundRefBase( BoundRefBase && ) = delete; NonCopyable( NonCopyable && ) = delete;
BoundRefBase &operator=( BoundRefBase const & ) = delete; NonCopyable &operator=( NonCopyable const & ) = delete;
BoundRefBase &operator=( BoundRefBase && ) = delete; NonCopyable &operator=( NonCopyable && ) = delete;
};
virtual ~BoundRefBase() = default; struct BoundRef : NonCopyable {
virtual ~BoundRef() = default;
virtual auto isFlag() const -> bool = 0;
virtual auto isContainer() const -> bool { return false; } virtual auto isContainer() const -> bool { return false; }
};
struct BoundValueRefBase : BoundRef {
virtual auto setValue( std::string const &arg ) -> ParserResult = 0; virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
};
struct BoundFlagRefBase : BoundRef {
virtual auto setFlag( bool flag ) -> ParserResult = 0; virtual auto setFlag( bool flag ) -> ParserResult = 0;
}; };
struct BoundValueRefBase : BoundRefBase {
auto isFlag() const -> bool override { return false; }
auto setFlag( bool ) -> ParserResult override {
return ParserResult::logicError( "Flags can only be set on boolean fields" );
}
};
struct BoundFlagRefBase : BoundRefBase {
auto isFlag() const -> bool override { return true; }
auto setValue( std::string const &arg ) -> ParserResult override {
bool flag;
auto result = convertInto( arg, flag );
if( result )
setFlag( flag );
return result;
}
};
template<typename T> template<typename T>
struct BoundRef : BoundValueRefBase { struct BoundValueRef : BoundValueRefBase {
T &m_ref; T &m_ref;
explicit BoundRef( T &ref ) : m_ref( ref ) {} explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
auto setValue( std::string const &arg ) -> ParserResult override { auto setValue( std::string const &arg ) -> ParserResult override {
return convertInto( arg, m_ref ); return convertInto( arg, m_ref );
@ -700,10 +690,10 @@ namespace detail {
}; };
template<typename T> template<typename T>
struct BoundRef<std::vector<T>> : BoundValueRefBase { struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
std::vector<T> &m_ref; std::vector<T> &m_ref;
explicit BoundRef( std::vector<T> &ref ) : m_ref( ref ) {} explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
auto isContainer() const -> bool override { return true; } auto isContainer() const -> bool override { return true; }
@ -748,12 +738,12 @@ namespace detail {
template<typename ArgType, typename L> template<typename ArgType, typename L>
inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
ArgType temp; ArgType temp{};
auto result = convertInto( arg, temp ); auto result = convertInto( arg, temp );
return !result return !result
? result ? result
: LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp ); : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
}; }
template<typename L> template<typename L>
@ -803,6 +793,9 @@ namespace detail {
public: public:
template<typename T> template<typename T>
auto operator|( T const &other ) const -> Parser; auto operator|( T const &other ) const -> Parser;
template<typename T>
auto operator+( T const &other ) const -> Parser;
}; };
// Common code and state for Args and Opts // Common code and state for Args and Opts
@ -810,16 +803,16 @@ namespace detail {
class ParserRefImpl : public ComposableParserImpl<DerivedT> { class ParserRefImpl : public ComposableParserImpl<DerivedT> {
protected: protected:
Optionality m_optionality = Optionality::Optional; Optionality m_optionality = Optionality::Optional;
std::shared_ptr<BoundRefBase> m_ref; std::shared_ptr<BoundRef> m_ref;
std::string m_hint; std::string m_hint;
std::string m_description; std::string m_description;
explicit ParserRefImpl( std::shared_ptr<BoundRefBase> const &ref ) : m_ref( ref ) {} explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
public: public:
template<typename T> template<typename T>
ParserRefImpl( T &ref, std::string const &hint ) ParserRefImpl( T &ref, std::string const &hint )
: m_ref( std::make_shared<BoundRef<T>>( ref ) ), : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
m_hint( hint ) m_hint( hint )
{} {}
@ -860,10 +853,10 @@ namespace detail {
class ExeName : public ComposableParserImpl<ExeName> { class ExeName : public ComposableParserImpl<ExeName> {
std::shared_ptr<std::string> m_name; std::shared_ptr<std::string> m_name;
std::shared_ptr<BoundRefBase> m_ref; std::shared_ptr<BoundValueRefBase> m_ref;
template<typename LambdaT> template<typename LambdaT>
static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundRefBase> { static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
return std::make_shared<BoundLambda<LambdaT>>( lambda) ; return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
} }
@ -871,7 +864,7 @@ namespace detail {
ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {} ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
explicit ExeName( std::string &ref ) : ExeName() { explicit ExeName( std::string &ref ) : ExeName() {
m_ref = std::make_shared<BoundRef<std::string>>( ref ); m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
} }
template<typename LambdaT> template<typename LambdaT>
@ -914,7 +907,10 @@ namespace detail {
if( token.type != TokenType::Argument ) if( token.type != TokenType::Argument )
return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
auto result = m_ref->setValue( remainingTokens->token ); assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
auto result = valueRef->setValue( remainingTokens->token );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
else else
@ -987,20 +983,22 @@ namespace detail {
if( remainingTokens && remainingTokens->type == TokenType::Option ) { if( remainingTokens && remainingTokens->type == TokenType::Option ) {
auto const &token = *remainingTokens; auto const &token = *remainingTokens;
if( isMatch(token.token ) ) { if( isMatch(token.token ) ) {
if( m_ref->isFlag() ) { if( auto flagRef = dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) ) {
auto result = m_ref->setFlag( true ); auto result = flagRef->setFlag( true );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll ) if( result.value() == ParseResultType::ShortCircuitAll )
return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
} else { } else {
assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
++remainingTokens; ++remainingTokens;
if( !remainingTokens ) if( !remainingTokens )
return InternalParseResult::runtimeError( "Expected argument following " + token.token ); return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto const &argToken = *remainingTokens; auto const &argToken = *remainingTokens;
if( argToken.type != TokenType::Argument ) if( argToken.type != TokenType::Argument )
return InternalParseResult::runtimeError( "Expected argument following " + token.token ); return InternalParseResult::runtimeError( "Expected argument following " + token.token );
auto result = m_ref->setValue( argToken.token ); auto result = valueRef->setValue( argToken.token );
if( !result ) if( !result )
return InternalParseResult( result ); return InternalParseResult( result );
if( result.value() == ParseResultType::ShortCircuitAll ) if( result.value() == ParseResultType::ShortCircuitAll )
@ -1077,6 +1075,12 @@ namespace detail {
return Parser( *this ) |= other; return Parser( *this ) |= other;
} }
// Forward deprecated interface with '+' instead of '|'
template<typename T>
auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
template<typename T>
auto operator+( T const &other ) const -> Parser { return operator|( other ); }
auto getHelpColumns() const -> std::vector<HelpColumns> { auto getHelpColumns() const -> std::vector<HelpColumns> {
std::vector<HelpColumns> cols; std::vector<HelpColumns> cols;
for (auto const &o : m_options) { for (auto const &o : m_options) {
@ -1116,6 +1120,8 @@ namespace detail {
for( auto const &cols : rows ) for( auto const &cols : rows )
optWidth = (std::max)(optWidth, cols.left.size() + 2); optWidth = (std::max)(optWidth, cols.left.size() + 2);
optWidth = (std::min)(optWidth, consoleWidth/2);
for( auto const &cols : rows ) { for( auto const &cols : rows ) {
auto row = auto row =
TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +