mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-03 21:49:32 +01:00 
			
		
		
		
	New version of Clara that fixes operator= issue with ref member (#265)
This commit is contained in:
		
							
								
								
									
										85
									
								
								include/external/clara.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								include/external/clara.h
									
									
									
									
										vendored
									
									
								
							@@ -278,6 +278,10 @@ namespace Clara {
 | 
			
		||||
                functionObj->setFlag( config );
 | 
			
		||||
            }
 | 
			
		||||
            bool takesArg() const { return functionObj->takesArg(); }
 | 
			
		||||
 | 
			
		||||
            bool isSet() const {
 | 
			
		||||
                return functionObj != NULL;
 | 
			
		||||
            }
 | 
			
		||||
        private:
 | 
			
		||||
            IArgFunction<ConfigT>* functionObj;
 | 
			
		||||
        };
 | 
			
		||||
@@ -426,11 +430,16 @@ namespace Clara {
 | 
			
		||||
 | 
			
		||||
        Detail::BoundArgFunction<ConfigT> 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<std::string> 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<ConfigT>::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<typename C, typename M>
 | 
			
		||||
            void bind( M C::* field, std::string const& placeholder ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundDataMember<C,M>( field );
 | 
			
		||||
                m_arg.placeholder = placeholder;
 | 
			
		||||
                m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
 | 
			
		||||
                m_arg->placeholder = placeholder;
 | 
			
		||||
            }
 | 
			
		||||
            // Bind a boolean data member (no placeholder required)
 | 
			
		||||
            template<typename C>
 | 
			
		||||
            void bind( bool C::* field ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundDataMember<C,bool>( field );
 | 
			
		||||
                m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Bind a method taking a single, non-boolean argument (requires a placeholder string)
 | 
			
		||||
            template<typename C, typename M>
 | 
			
		||||
            void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
 | 
			
		||||
                m_arg.placeholder = placeholder;
 | 
			
		||||
            void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
 | 
			
		||||
                m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
 | 
			
		||||
                m_arg->placeholder = placeholder;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Bind a method taking a single, boolean argument (no placeholder string required)
 | 
			
		||||
            template<typename C>
 | 
			
		||||
            void bind( void (C::*_unaryMethod)( bool ) ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundUnaryMethod<C,bool>( _unaryMethod );
 | 
			
		||||
            void bind( void (C::* unaryMethod)( bool ) ) {
 | 
			
		||||
                m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Bind a method that takes no arguments (will be called if opt is present)
 | 
			
		||||
            template<typename C>
 | 
			
		||||
            void bind( void (C::*_nullaryMethod)() ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundNullaryMethod<C>( _nullaryMethod );
 | 
			
		||||
            void bind( void (C::* nullaryMethod)() ) {
 | 
			
		||||
                m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
 | 
			
		||||
            template<typename C>
 | 
			
		||||
            void bind( void (*_unaryFunction)( C& ) ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundUnaryFunction<C>( _unaryFunction );
 | 
			
		||||
            void bind( void (* unaryFunction)( C& ) ) {
 | 
			
		||||
                m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
 | 
			
		||||
            template<typename C, typename T>
 | 
			
		||||
            void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) {
 | 
			
		||||
                m_arg.boundField = new Detail::BoundBinaryFunction<C, T>( _binaryFunction );
 | 
			
		||||
                m_arg.placeholder = placeholder;
 | 
			
		||||
            void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
 | 
			
		||||
                m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( 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<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
 | 
			
		||||
            if( m_options.empty() && m_positionalArgs.empty() )
 | 
			
		||||
                throw std::logic_error( "No options or arguments specified" );
 | 
			
		||||
 | 
			
		||||
            validate();
 | 
			
		||||
            std::vector<Parser::Token> 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<Arg>::const_iterator  it = m_options.begin(),
 | 
			
		||||
                                                            itEnd = m_options.end();
 | 
			
		||||
                    it != itEnd; ++it )
 | 
			
		||||
                it->validate();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        Detail::BoundArgFunction<ConfigT> m_boundProcessName;
 | 
			
		||||
        std::vector<Arg> m_options;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user