From 0dc49d1b5785209c6d8e6b03f02f103b3305fbc4 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 11 Feb 2014 06:32:56 +0000 Subject: [PATCH] Extracted stand-alone micro-library, tbc_text_format.h, from catch_text.h. - use this version in clara.h so clara can stand alone. --- include/internal/catch_clara.h | 3 + include/internal/catch_impl.hpp | 1 - include/internal/catch_text.h | 57 ++----- include/internal/catch_text.hpp | 95 ----------- include/internal/clara.h | 23 ++- include/internal/tbc_text_format.h | 153 ++++++++++++++++++ .../CatchSelfTest.xcodeproj/project.pbxproj | 2 + 7 files changed, 187 insertions(+), 147 deletions(-) delete mode 100644 include/internal/catch_text.hpp create mode 100644 include/internal/tbc_text_format.h diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index a30c0fd2..d9ecbed1 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -9,6 +9,9 @@ #ifndef TWOBLUECUBES_CATCH_CLARA_H_INCLUDED #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + + // Declare Clara inside the Catch namespace #define CLICHE_CLARA_OUTER_NAMESPACE Catch #include "clara.h" diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 01522355..e19c159f 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -28,7 +28,6 @@ #include "catch_tags.hpp" #include "catch_test_spec.hpp" #include "catch_version.hpp" -#include "catch_text.hpp" #include "catch_message.hpp" #include "catch_legacy_reporter_adapter.hpp" #include "catch_timer.hpp" diff --git a/include/internal/catch_text.h b/include/internal/catch_text.h index e713f7b7..4657f744 100644 --- a/include/internal/catch_text.h +++ b/include/internal/catch_text.h @@ -1,6 +1,6 @@ /* - * Created by Phil on 18/4/2013. - * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * Created by Phil on 10/2/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. * * 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) @@ -10,52 +10,15 @@ #include "catch_config.hpp" -#include -#include +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +#include "tbc_text_format.h" +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace Catch { - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( CATCH_CONFIG_CONSOLE_WIDTH-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ); - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ); - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const; - - friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ); - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Catch + using Tbc::Text; + using Tbc::TextAttributes; +} #endif // TWOBLUECUBES_CATCH_TEXT_H_INCLUDED diff --git a/include/internal/catch_text.hpp b/include/internal/catch_text.hpp deleted file mode 100644 index f1f884dd..00000000 --- a/include/internal/catch_text.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Created by Phil on 20/4/2013. - * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. - * - * 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) - */ -#ifndef TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED - -#include -#include - -namespace Catch { - - Text::Text( std::string const& _str, TextAttributes const& _attr ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - std::string Text::toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED diff --git a/include/internal/clara.h b/include/internal/clara.h index 5a207139..b2ffc586 100644 --- a/include/internal/clara.h +++ b/include/internal/clara.h @@ -18,7 +18,13 @@ #endif #ifndef TWOBLUECUBES_CLARA_H_ALREADY_INCLUDED -#include "catch_text.h" // This will get moved out too +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Clara +#include "tbc_text_format.h" +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +#include +#include +#include // Use optional outer namespace #ifdef CLICHE_CLARA_OUTER_NAMESPACE @@ -27,6 +33,15 @@ namespace CLICHE_CLARA_OUTER_NAMESPACE { namespace Clara { namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace ::Clara::Tbc; + template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; @@ -416,18 +431,18 @@ namespace Clara { m_boundProcessName = Detail::makeBoundField( f ); } - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const { + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; std::size_t maxWidth = 0; for( it = itBegin; it != itEnd; ++it ) maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { - Catch::Text usage( it->commands(), Catch::TextAttributes() + Detail::Text usage( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); // !TBD handle longer usage strings - Catch::Text desc( it->description, Catch::TextAttributes() + Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth -3 ) ); for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { diff --git a/include/internal/tbc_text_format.h b/include/internal/tbc_text_format.h new file mode 100644 index 00000000..a63d6a14 --- /dev/null +++ b/include/internal/tbc_text_format.h @@ -0,0 +1,153 @@ +/* + * Created by Phil on 18/4/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * 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) + */ +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED diff --git a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 20d58a9f..4c3d6af2 100644 --- a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -78,6 +78,7 @@ 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = ""; }; 26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = ""; }; 268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = ""; }; + 268F47B118A944DB00D8C14F /* tbc_text_format.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/internal/tbc_text_format.h; sourceTree = ""; }; 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = ""; }; 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = ""; }; 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = ""; }; @@ -202,6 +203,7 @@ isa = PBXGroup; children = ( 26C5F3EC17514B970056FB3C /* clara.h */, + 268F47B118A944DB00D8C14F /* tbc_text_format.h */, ); name = External; sourceTree = "";