mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-03 21:49:32 +01:00 
			
		
		
		
	Refactored string wrapper
- to be much more flexible (writes to vector) - fixed a couple of bugs
This commit is contained in:
		@@ -161,7 +161,7 @@ namespace Catch {
 | 
			
		||||
                displayedSpecificOption = true;
 | 
			
		||||
                std::cout   << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
 | 
			
		||||
                            << opt.optionSummary() << "\n\n"
 | 
			
		||||
                            << wrapLongStrings( opt.optionDescription(), 80, 2 ) << "\n" << std::endl;
 | 
			
		||||
                            << LineWrapper().setIndent( 2 ).wrap( opt.optionDescription() ).toString() << "\n" << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,11 +9,39 @@
 | 
			
		||||
#define TWOBLUECUBES_CATCH_LINE_WRAP_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    
 | 
			
		||||
    void wrapLongStrings( std::ostream& stream, const std::string& str, std::size_t columns, std::size_t indent = 0 );
 | 
			
		||||
    std::string wrapLongStrings( const std::string& str, std::size_t columns, std::size_t indent = 0 );
 | 
			
		||||
    class LineWrapper {
 | 
			
		||||
    public:
 | 
			
		||||
        LineWrapper( std::size_t _indent, std::size_t _right );
 | 
			
		||||
        LineWrapper( std::size_t _right );
 | 
			
		||||
        LineWrapper();
 | 
			
		||||
 | 
			
		||||
        LineWrapper& setIndent( std::size_t _indent );
 | 
			
		||||
        LineWrapper& setRight( std::size_t _right );
 | 
			
		||||
 | 
			
		||||
        LineWrapper& wrap( std::string const& _str );
 | 
			
		||||
        
 | 
			
		||||
        std::ostream& intoStream( std::ostream& stream ) const;
 | 
			
		||||
        std::string toString() const;
 | 
			
		||||
 | 
			
		||||
        typedef std::vector<std::string>::const_iterator const_iterator;
 | 
			
		||||
 | 
			
		||||
        const_iterator begin() const { return lines.begin(); }
 | 
			
		||||
        const_iterator end() const { return lines.end(); }
 | 
			
		||||
        
 | 
			
		||||
    private:
 | 
			
		||||
        void wrapInternal( std::string const& _str );
 | 
			
		||||
        void addLine( const std::string& _line );
 | 
			
		||||
 | 
			
		||||
        std::string indent;
 | 
			
		||||
        std::size_t right;
 | 
			
		||||
        std::size_t nextTab;
 | 
			
		||||
        std::size_t tab;
 | 
			
		||||
        std::vector<std::string> lines;
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,62 +12,93 @@
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    
 | 
			
		||||
    namespace {
 | 
			
		||||
        inline void addIndent( std::ostream& os, std::size_t indent ) {
 | 
			
		||||
            while( indent-- > 0 )
 | 
			
		||||
                os << ' ';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) {
 | 
			
		||||
            std::size_t width = columns-indent;
 | 
			
		||||
            std::size_t tab = 0;
 | 
			
		||||
            std::size_t wrapPoint = width;
 | 
			
		||||
            for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) {
 | 
			
		||||
                if( pos == width ) {
 | 
			
		||||
                    addIndent( os, indent );
 | 
			
		||||
                    if( paragraph[wrapPoint] == ' ' ) {
 | 
			
		||||
                        os << paragraph.substr( 0, wrapPoint ) << "\n";
 | 
			
		||||
                        while( paragraph[++wrapPoint] == ' ' );
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        os << paragraph.substr( 0, --wrapPoint ) << "-\n";
 | 
			
		||||
                    }
 | 
			
		||||
                    return recursivelyWrapLine( os, paragraph.substr( wrapPoint ), columns, indent+tab );
 | 
			
		||||
                }
 | 
			
		||||
                if( paragraph[pos] == '\t' ) {
 | 
			
		||||
                    tab = pos;
 | 
			
		||||
                    paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 );
 | 
			
		||||
                    pos--;
 | 
			
		||||
                }
 | 
			
		||||
                else if( paragraph[pos] == ' ' ) {
 | 
			
		||||
                    wrapPoint = pos;
 | 
			
		||||
                }
 | 
			
		||||
    LineWrapper::LineWrapper( std::size_t _indent, std::size_t _right )
 | 
			
		||||
    :   indent( _indent, ' ' ),
 | 
			
		||||
        right( _right ),
 | 
			
		||||
        nextTab( 0 ),
 | 
			
		||||
        tab( 0 )
 | 
			
		||||
    {}
 | 
			
		||||
    LineWrapper::LineWrapper( std::size_t _right )
 | 
			
		||||
    :   right( _right ),
 | 
			
		||||
        nextTab( 0 ),
 | 
			
		||||
        tab( 0 )
 | 
			
		||||
    {}
 | 
			
		||||
    LineWrapper::LineWrapper()
 | 
			
		||||
    :   right( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
 | 
			
		||||
        nextTab( 0 ),
 | 
			
		||||
        tab( 0 )
 | 
			
		||||
    {}
 | 
			
		||||
    
 | 
			
		||||
    LineWrapper& LineWrapper::setIndent( std::size_t _indent ) {
 | 
			
		||||
        indent = std::string( _indent, ' ' );
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    LineWrapper& LineWrapper::setRight( std::size_t _right ) {
 | 
			
		||||
        right = _right;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    LineWrapper& LineWrapper::wrap( std::string const& _str ) {
 | 
			
		||||
        nextTab = tab = 0;
 | 
			
		||||
        wrapInternal( _str );
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    void LineWrapper::wrapInternal( std::string const& _str ) {
 | 
			
		||||
        std::size_t width = right - indent.size();
 | 
			
		||||
        std::size_t wrapPoint = width-tab;
 | 
			
		||||
        for( std::size_t pos = 0; pos < _str.size(); ++pos ) {
 | 
			
		||||
            if( _str[pos] == '\n' )
 | 
			
		||||
            {
 | 
			
		||||
                addLine( _str.substr( 0, pos ) );
 | 
			
		||||
                nextTab = tab = 0;
 | 
			
		||||
                return wrapInternal( _str.substr( pos+1 ) );
 | 
			
		||||
            }                
 | 
			
		||||
            if( pos == width-tab ) {
 | 
			
		||||
                if( _str[wrapPoint] == ' ' ) {
 | 
			
		||||
                    addLine( _str.substr( 0, wrapPoint ) );
 | 
			
		||||
                    while( _str[++wrapPoint] == ' ' );
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    addLine( _str.substr( 0, --wrapPoint ) + '-' );
 | 
			
		||||
                }
 | 
			
		||||
                return wrapInternal( _str.substr( wrapPoint ) );
 | 
			
		||||
            }
 | 
			
		||||
            if( _str[pos] == '\t' ) {
 | 
			
		||||
                nextTab = pos;
 | 
			
		||||
                std::string withoutTab = _str.substr( 0, nextTab ) + _str.substr( nextTab+1 );
 | 
			
		||||
                return wrapInternal( withoutTab );
 | 
			
		||||
            }
 | 
			
		||||
            else if( _str[pos] == ' ' ) {
 | 
			
		||||
                wrapPoint = pos;
 | 
			
		||||
            }
 | 
			
		||||
            addIndent( os, indent );
 | 
			
		||||
            os << paragraph;
 | 
			
		||||
        }
 | 
			
		||||
        addLine( _str );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void wrapLongStrings( std::ostream& stream, const std::string& str, std::size_t columns, std::size_t indent ) {
 | 
			
		||||
        std::string::size_type pos = 0;
 | 
			
		||||
        std::string::size_type newline = str.find_first_of( '\n' );
 | 
			
		||||
        while( newline != std::string::npos ) {
 | 
			
		||||
            std::string paragraph = str.substr( pos, newline-pos );
 | 
			
		||||
            recursivelyWrapLine( stream, paragraph, columns, indent );
 | 
			
		||||
            stream << "\n";
 | 
			
		||||
            pos = newline+1;
 | 
			
		||||
            newline = str.find_first_of( '\n', pos );
 | 
			
		||||
    std::ostream& LineWrapper::intoStream( std::ostream& stream ) const {
 | 
			
		||||
        for( const_iterator it = begin(), itEnd = end();
 | 
			
		||||
            it != itEnd; ++it ) {
 | 
			
		||||
            if( it != begin() )
 | 
			
		||||
                stream << "\n";
 | 
			
		||||
            stream << *it;
 | 
			
		||||
        }
 | 
			
		||||
        if( pos != str.size() )
 | 
			
		||||
            recursivelyWrapLine( stream, str.substr( pos, str.size()-pos ), columns, indent );
 | 
			
		||||
        return stream;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string wrapLongStrings( const std::string& str, std::size_t columns, std::size_t indent ) {
 | 
			
		||||
    std::string LineWrapper::toString() const {
 | 
			
		||||
        std::ostringstream oss;
 | 
			
		||||
        wrapLongStrings( oss, str, columns, indent );
 | 
			
		||||
        intoStream( oss );
 | 
			
		||||
        return oss.str();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void LineWrapper::addLine( const std::string& _line ) {
 | 
			
		||||
        if( tab > 0 )
 | 
			
		||||
            lines.push_back( indent + std::string( tab, ' ' ) + _line );
 | 
			
		||||
        else
 | 
			
		||||
            lines.push_back( indent + _line );
 | 
			
		||||
        if( nextTab > 0 )
 | 
			
		||||
            tab = nextTab;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
} // end namespace Catch
 | 
			
		||||
 | 
			
		||||
#endif // TWOBLUECUBES_CATCH_LINE_WRAP_HPP_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -211,7 +211,7 @@ namespace Catch {
 | 
			
		||||
                if( result.hasExpandedExpression() ) {
 | 
			
		||||
                    stream << "with expansion:\n";
 | 
			
		||||
                    TextColour colourGuard( TextColour::ReconstructedExpression );
 | 
			
		||||
                    stream << wrapLongStrings( result.getExpandedExpression() ) << "\n";
 | 
			
		||||
                    stream << LineWrapper().setIndent(2).wrap( result.getExpandedExpression() ).toString() << "\n";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            void printMessage() const {
 | 
			
		||||
@@ -220,7 +220,8 @@ namespace Catch {
 | 
			
		||||
                for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
 | 
			
		||||
                        it != itEnd;
 | 
			
		||||
                        ++it ) {                    
 | 
			
		||||
                    stream << wrapLongStrings( it->message ) << "\n";
 | 
			
		||||
                    LineWrapper().setIndent(2).wrap( it->message ).intoStream( stream );
 | 
			
		||||
                    stream << "\n";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            void printSourceInfo() const {
 | 
			
		||||
@@ -228,10 +229,6 @@ namespace Catch {
 | 
			
		||||
                stream << result.getSourceInfo() << ": ";
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            static std::string wrapLongStrings( std::string const& _string ){
 | 
			
		||||
                return Catch::wrapLongStrings( _string, CATCH_CONFIG_CONSOLE_WIDTH-1, 2 );
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            std::ostream& stream;
 | 
			
		||||
            AssertionStats const& stats;
 | 
			
		||||
            AssertionResult const& result;
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -426,34 +426,63 @@ TEST_CASE( "selftest/tags", "" ) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
 | 
			
		||||
    // guide:                 123456789012345678
 | 
			
		||||
    std::string testString = "one two three four";
 | 
			
		||||
 | 
			
		||||
    SECTION( "No wrapping", "" ) {
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 80, 0 ) == testString );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 18, 0 ) == testString );
 | 
			
		||||
    }
 | 
			
		||||
    SECTION( "Wrapped once", "" ) {
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 17, 0 ) == "one two three\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 16, 0 ) == "one two three\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 15, 0 ) == "one two three\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 14, 0 ) == "one two three\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 13, 0 ) == "one two\nthree four" );
 | 
			
		||||
    }
 | 
			
		||||
    SECTION( "Wrapped twice", "" ) {
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 9, 0 ) == "one two\nthree\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 8, 0 ) == "one two\nthree\nfour" );
 | 
			
		||||
    }
 | 
			
		||||
    SECTION( "Wrapped three times", "" ) {
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 7, 0 ) == "one\ntwo\nthree\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 5, 0 ) == "one\ntwo\nthree\nfour" );
 | 
			
		||||
    }
 | 
			
		||||
    SECTION( "Short wrap", "" ) {
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( "abcdef", 4, 0 ) == "abc-\ndef" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( "abcdefg", 4, 0 ) == "abc-\ndefg" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( "abcdefgh", 4, 0 ) == "abc-\ndef-\ngh" );
 | 
			
		||||
    SECTION( "plain string", "" ) {
 | 
			
		||||
        // guide:                 123456789012345678
 | 
			
		||||
        std::string testString = "one two three four";
 | 
			
		||||
        
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 4, 0 ) == "one\ntwo\nthr-\nee\nfour" );
 | 
			
		||||
        CHECK( Catch::wrapLongStrings( testString, 3, 0 ) == "one\ntwo\nth-\nree\nfo-\nur" );
 | 
			
		||||
        SECTION( "No wrapping", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 80 ).wrap( testString ).toString() == testString );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 18 ).wrap( testString ).toString() == testString );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Wrapped once", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 17 ).wrap( testString ).toString() == "one two three\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 16 ).wrap( testString ).toString() == "one two three\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 15 ).wrap( testString ).toString() == "one two three\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 14 ).wrap( testString ).toString() == "one two three\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 13 ).wrap( testString ).toString() == "one two\nthree four" );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Wrapped twice", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Wrapped three times", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 7 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 5 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Short wrap", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 4 ).wrap( "abcdef" ).toString() == "abc-\ndef" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 4 ).wrap( "abcdefg" ).toString() == "abc-\ndefg" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 4  ).wrap("abcdefgh" ).toString() == "abc-\ndef-\ngh" );
 | 
			
		||||
 | 
			
		||||
            CHECK( Catch::LineWrapper( 4 ).wrap( testString ).toString() == "one\ntwo\nthr-\nee\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 3 ).wrap( testString ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SECTION( "With newlines", "" ) {
 | 
			
		||||
        
 | 
			
		||||
        // guide:                 1234567890123456789
 | 
			
		||||
        std::string testString = "one two\nthree four";
 | 
			
		||||
        
 | 
			
		||||
        SECTION( "No wrapping" , "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 80 ).wrap( testString ).toString() == testString );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 18 ).wrap( testString ).toString() == testString );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 10 ).wrap( testString ).toString() == testString );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Trailing newline" , "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 10 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
 | 
			
		||||
            CHECK( Catch::LineWrapper(  6 ).wrap( "abcdef" ).toString() == "abcdef" );
 | 
			
		||||
            CHECK( Catch::LineWrapper(  6 ).wrap( "abcdef\n" ).toString() == "abcdef\n" );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Wrapped once", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 9 ).wrap( testString ).toString() == "one two\nthree\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 8 ).wrap( testString ).toString() == "one two\nthree\nfour" );
 | 
			
		||||
            CHECK( Catch::LineWrapper( 7 ).wrap( testString ).toString() == "one two\nthree\nfour" );
 | 
			
		||||
        }
 | 
			
		||||
        SECTION( "Wrapped twice", "" ) {
 | 
			
		||||
            CHECK( Catch::LineWrapper( 6 ).wrap( testString ).toString() == "one\ntwo\nthree\nfour" );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user