diff --git a/README.md b/README.md index 28439d09..1f7c9e68 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.0 build 32 (master branch)* +*v1.0 build 33 (master branch)* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/external/clara.h b/include/external/clara.h index 4b83d1d6..549bade5 100644 --- a/include/external/clara.h +++ b/include/external/clara.h @@ -278,6 +278,10 @@ namespace Clara { functionObj->setFlag( config ); } bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } private: IArgFunction* functionObj; }; @@ -426,11 +430,16 @@ namespace Clara { Detail::BoundArgFunction boundField; std::string description; + std::string detail; std::string placeholder; // Only value if boundField takes an arg bool takesArg() const { return !placeholder.empty(); } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } }; struct OptionArgProperties { std::vector shortNames; @@ -442,7 +451,6 @@ namespace Clara { bool hasLongName( std::string const& _longName ) const { return _longName == longName; } - }; struct PositionalArgProperties { PositionalArgProperties() : position( -1 ) {} @@ -462,9 +470,6 @@ namespace Clara { using CommonArgProperties::placeholder; // !TBD - bool isAnyPositional() const { - return position == -1 && shortNames.empty() && longName.empty(); - } std::string dbgName() const { if( !longName.empty() ) return "--" + longName; @@ -526,73 +531,72 @@ namespace Clara { class ArgBuilder { public: - ArgBuilder( Arg& arg ) : m_arg( arg ) {} + ArgBuilder( Arg* arg ) : m_arg( arg ) {} // Bind a non-boolean data member (requires placeholder string) template void bind( M C::* field, std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundDataMember( field ); - m_arg.placeholder = placeholder; + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; } // Bind a boolean data member (no placeholder required) template void bind( bool C::* field ) { - m_arg.boundField = new Detail::BoundDataMember( field ); + m_arg->boundField = new Detail::BoundDataMember( field ); } // Bind a method taking a single, non-boolean argument (requires a placeholder string) template - void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); - m_arg.placeholder = placeholder; + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; } // Bind a method taking a single, boolean argument (no placeholder string required) template - void bind( void (C::*_unaryMethod)( bool ) ) { - m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); } // Bind a method that takes no arguments (will be called if opt is present) template - void bind( void (C::*_nullaryMethod)() ) { - m_arg.boundField = new Detail::BoundNullaryMethod( _nullaryMethod ); + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); } // Bind a free function taking a single argument - the object to operate on (no placeholder string required) template - void bind( void (*_unaryFunction)( C& ) ) { - m_arg.boundField = new Detail::BoundUnaryFunction( _unaryFunction ); + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); } // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) template - void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundBinaryFunction( _binaryFunction ); - m_arg.placeholder = placeholder; + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; } ArgBuilder& describe( std::string const& description ) { - m_arg.description = description; + m_arg->description = description; return *this; } - ArgBuilder& detail( std::string const& ) { -// m_arg.description = description; -// !TBD + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; return *this; } protected: - Arg& m_arg; + Arg* m_arg; }; class OptBuilder : public ArgBuilder { public: - OptBuilder( Arg& arg ) : ArgBuilder( arg ) {} + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { - addOptName( ArgBuilder::m_arg, optName ); + addOptName( *ArgBuilder::m_arg, optName ); return *this; } }; @@ -624,7 +628,7 @@ namespace Clara { OptBuilder operator[]( std::string const& optName ) { m_options.push_back( Arg() ); addOptName( m_options.back(), optName ); - OptBuilder builder( m_options.back() ); + OptBuilder builder( &m_options.back() ); return builder; } @@ -633,7 +637,7 @@ namespace Clara { if( position > m_highestSpecifiedArgPosition ) m_highestSpecifiedArgPosition = position; setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( m_positionalArgs[position] ); + ArgBuilder builder( &m_positionalArgs[position] ); return builder; } @@ -642,7 +646,7 @@ namespace Clara { if( m_floatingArg.get() ) throw std::logic_error( "Only one unpositional argument can be added" ); m_floatingArg = ArgAutoPtr( new Arg() ); - ArgBuilder builder( *m_floatingArg ); + ArgBuilder builder( m_floatingArg.get() ); return builder; } @@ -665,9 +669,8 @@ namespace Clara { Detail::Text usage( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); - // !TBD handle longer usage strings Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth -3 ) ); + .setWidth( width - maxWidth - 3 ) ); for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { std::string usageCol = i < usage.size() ? usage[i] : ""; @@ -712,6 +715,7 @@ namespace Clara { } void usage( std::ostream& os, std::string const& procName ) const { + validate(); os << "usage:\n " << procName << " "; argSynopsis( os ); if( !m_options.empty() ) { @@ -726,7 +730,7 @@ namespace Clara { return oss.str(); } - ConfigT parseInto( int argc, char const * const * argv ) const { + ConfigT parse( int argc, char const * const * argv ) const { ConfigT config; parseInto( argc, argv, config ); return config; @@ -745,9 +749,7 @@ namespace Clara { } std::vector populate( std::vector const& tokens, ConfigT& config ) const { - if( m_options.empty() && m_positionalArgs.empty() ) - throw std::logic_error( "No options or arguments specified" ); - + validate(); std::vector unusedTokens = populateOptions( tokens, config ); unusedTokens = populateFixedArgs( unusedTokens, config ); unusedTokens = populateFloatingArgs( unusedTokens, config ); @@ -831,6 +833,17 @@ namespace Clara { return unusedTokens; } + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + private: Detail::BoundArgFunction m_boundProcessName; std::vector m_options; diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index c9bdeb84..ef1d2371 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -13,7 +13,7 @@ namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 32, "master" ); + Version libraryVersion( 1, 0, 33, "master" ); } #endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED diff --git a/single_include/catch.hpp b/single_include/catch.hpp index ae880edf..052a761f 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.0 build 32 (master branch) - * Generated: 2014-03-17 18:37:08.497437 + * CATCH v1.0 build 33 (master branch) + * Generated: 2014-03-24 18:11:50.426554 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -3290,6 +3290,10 @@ namespace Clara { functionObj->setFlag( config ); } bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } private: IArgFunction* functionObj; }; @@ -3437,11 +3441,16 @@ namespace Clara { Detail::BoundArgFunction boundField; std::string description; + std::string detail; std::string placeholder; // Only value if boundField takes an arg bool takesArg() const { return !placeholder.empty(); } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } }; struct OptionArgProperties { std::vector shortNames; @@ -3453,7 +3462,6 @@ namespace Clara { bool hasLongName( std::string const& _longName ) const { return _longName == longName; } - }; struct PositionalArgProperties { PositionalArgProperties() : position( -1 ) {} @@ -3473,9 +3481,6 @@ namespace Clara { using CommonArgProperties::placeholder; // !TBD - bool isAnyPositional() const { - return position == -1 && shortNames.empty() && longName.empty(); - } std::string dbgName() const { if( !longName.empty() ) return "--" + longName; @@ -3536,73 +3541,72 @@ namespace Clara { class ArgBuilder { public: - ArgBuilder( Arg& arg ) : m_arg( arg ) {} + ArgBuilder( Arg* arg ) : m_arg( arg ) {} // Bind a non-boolean data member (requires placeholder string) template void bind( M C::* field, std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundDataMember( field ); - m_arg.placeholder = placeholder; + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; } // Bind a boolean data member (no placeholder required) template void bind( bool C::* field ) { - m_arg.boundField = new Detail::BoundDataMember( field ); + m_arg->boundField = new Detail::BoundDataMember( field ); } // Bind a method taking a single, non-boolean argument (requires a placeholder string) template - void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); - m_arg.placeholder = placeholder; + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; } // Bind a method taking a single, boolean argument (no placeholder string required) template - void bind( void (C::*_unaryMethod)( bool ) ) { - m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); } // Bind a method that takes no arguments (will be called if opt is present) template - void bind( void (C::*_nullaryMethod)() ) { - m_arg.boundField = new Detail::BoundNullaryMethod( _nullaryMethod ); + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); } // Bind a free function taking a single argument - the object to operate on (no placeholder string required) template - void bind( void (*_unaryFunction)( C& ) ) { - m_arg.boundField = new Detail::BoundUnaryFunction( _unaryFunction ); + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); } // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) template - void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg.boundField = new Detail::BoundBinaryFunction( _binaryFunction ); - m_arg.placeholder = placeholder; + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; } ArgBuilder& describe( std::string const& description ) { - m_arg.description = description; + m_arg->description = description; return *this; } - ArgBuilder& detail( std::string const& ) { -// m_arg.description = description; -// !TBD + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; return *this; } protected: - Arg& m_arg; + Arg* m_arg; }; class OptBuilder : public ArgBuilder { public: - OptBuilder( Arg& arg ) : ArgBuilder( arg ) {} + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { - addOptName( ArgBuilder::m_arg, optName ); + addOptName( *ArgBuilder::m_arg, optName ); return *this; } }; @@ -3633,7 +3637,7 @@ namespace Clara { OptBuilder operator[]( std::string const& optName ) { m_options.push_back( Arg() ); addOptName( m_options.back(), optName ); - OptBuilder builder( m_options.back() ); + OptBuilder builder( &m_options.back() ); return builder; } @@ -3642,7 +3646,7 @@ namespace Clara { if( position > m_highestSpecifiedArgPosition ) m_highestSpecifiedArgPosition = position; setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( m_positionalArgs[position] ); + ArgBuilder builder( &m_positionalArgs[position] ); return builder; } @@ -3651,7 +3655,7 @@ namespace Clara { if( m_floatingArg.get() ) throw std::logic_error( "Only one unpositional argument can be added" ); m_floatingArg = ArgAutoPtr( new Arg() ); - ArgBuilder builder( *m_floatingArg ); + ArgBuilder builder( m_floatingArg.get() ); return builder; } @@ -3674,9 +3678,8 @@ namespace Clara { Detail::Text usage( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); - // !TBD handle longer usage strings Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth -3 ) ); + .setWidth( width - maxWidth - 3 ) ); for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { std::string usageCol = i < usage.size() ? usage[i] : ""; @@ -3721,6 +3724,7 @@ namespace Clara { } void usage( std::ostream& os, std::string const& procName ) const { + validate(); os << "usage:\n " << procName << " "; argSynopsis( os ); if( !m_options.empty() ) { @@ -3735,7 +3739,7 @@ namespace Clara { return oss.str(); } - ConfigT parseInto( int argc, char const * const * argv ) const { + ConfigT parse( int argc, char const * const * argv ) const { ConfigT config; parseInto( argc, argv, config ); return config; @@ -3754,9 +3758,7 @@ namespace Clara { } std::vector populate( std::vector const& tokens, ConfigT& config ) const { - if( m_options.empty() && m_positionalArgs.empty() ) - throw std::logic_error( "No options or arguments specified" ); - + validate(); std::vector unusedTokens = populateOptions( tokens, config ); unusedTokens = populateFixedArgs( unusedTokens, config ); unusedTokens = populateFloatingArgs( unusedTokens, config ); @@ -3840,6 +3842,17 @@ namespace Clara { return unusedTokens; } + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + private: Detail::BoundArgFunction m_boundProcessName; std::vector m_options; @@ -6585,7 +6598,7 @@ namespace Catch { namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 1, 0, 32, "master" ); + Version libraryVersion( 1, 0, 33, "master" ); } // #included from: catch_message.hpp