forked from Alepha/Alepha
Progress towards a word-wrap stream helper.
This commit is contained in:
@ -6,6 +6,8 @@ static_assert( __cplusplus > 2020 );
|
|||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "evaluation_helpers.h"
|
#include "evaluation_helpers.h"
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ namespace Alepha::Cavorite ::detail:: word_wrap
|
|||||||
{
|
{
|
||||||
// Returns the number of chars in the line just written to.
|
// Returns the number of chars in the line just written to.
|
||||||
std::size_t
|
std::size_t
|
||||||
applyWordToLine( const std::size_t maximumWidth, const std::size_t nextLineOffset, const std::size_t currentLineWidth, std::string &&word, std::string &result )
|
applyWordToLine( const std::size_t maximumWidth, const std::size_t nextLineOffset, const std::size_t currentLineWidth, std::string &&word, std::ostream &result )
|
||||||
{
|
{
|
||||||
if( word.empty() ) return currentLineWidth;
|
if( word.empty() ) return currentLineWidth;
|
||||||
|
|
||||||
@ -23,25 +25,67 @@ namespace Alepha::Cavorite ::detail:: word_wrap
|
|||||||
{
|
{
|
||||||
if( currentLineWidth + word.size() > maximumWidth )
|
if( currentLineWidth + word.size() > maximumWidth )
|
||||||
{
|
{
|
||||||
result+= '\n';
|
result << "\n";
|
||||||
std::fill_n( back_inserter( result ), nextLineOffset, ' ' );
|
std::fill_n( std::ostream_iterator< char >( result ), nextLineOffset, ' ' );
|
||||||
return nextLineOffset;
|
return nextLineOffset;
|
||||||
}
|
}
|
||||||
else return currentLineWidth;
|
else return currentLineWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto rv= lineWidth + word.size();
|
const auto rv= lineWidth + word.size();
|
||||||
result+= std::move( word );
|
result << std::move( word );
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WordWrapStreambuf::writeChar( const char ch )
|
||||||
|
{
|
||||||
|
std::ostream outWrap{ underlying };
|
||||||
|
if( ch == '\n' )
|
||||||
|
{
|
||||||
|
const auto prev= currentLineLength;
|
||||||
|
const auto size= currentWord.size();
|
||||||
|
currentLineLength= applyWordToLine( maximumWidth, nextLineOffset, currentLineLength, std::move( currentWord ), outWrap );
|
||||||
|
currentWord.clear();
|
||||||
|
outWrap << '\n';
|
||||||
|
if( currentLineLength == prev + size )
|
||||||
|
{
|
||||||
|
std::fill_n( std::ostream_iterator< char >{ outWrap }, nextLineOffset, ' ' );
|
||||||
|
currentLineLength= nextLineOffset;
|
||||||
|
}
|
||||||
|
else currentLineLength= 0;
|
||||||
|
}
|
||||||
|
else if( ch == ' ' )
|
||||||
|
{
|
||||||
|
currentLineLength= applyWordToLine( maximumWidth, nextLineOffset, currentLineLength, std::move( currentWord ), outWrap );
|
||||||
|
currentWord.clear();
|
||||||
|
if( currentLineLength < maximumWidth )
|
||||||
|
{
|
||||||
|
outWrap << ' ';
|
||||||
|
++currentLineLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else currentWord+= ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WordWrapStreambuf::drain()
|
||||||
|
{
|
||||||
|
if( currentWord.empty() ) return;
|
||||||
|
std::ostream outWrap{ underlying };
|
||||||
|
applyWordToLine( maximumWidth, nextLineOffset, currentLineLength, std::move( currentWord ), outWrap );
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
exports::wordWrap( const std::string &text, const std::size_t width, const std::size_t nextLineOffset )
|
exports::wordWrap( const std::string &text, const std::size_t width, const std::size_t nextLineOffset )
|
||||||
{
|
{
|
||||||
|
#if NEVER
|
||||||
auto putWord= [width, nextLineOffset]( std::string &&word, std::string &line, const std::size_t lineLength )
|
auto putWord= [width, nextLineOffset]( std::string &&word, std::string &line, const std::size_t lineLength )
|
||||||
{
|
{
|
||||||
const auto rv= applyWordToLine( width, nextLineOffset, lineLength, std::move( word ), line );
|
std::ostringstream out;
|
||||||
|
const auto rv= applyWordToLine( width, nextLineOffset, lineLength, std::move( word ), out );
|
||||||
|
line+= std::move( out ).str();
|
||||||
return rv;
|
return rv;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,5 +122,20 @@ namespace Alepha::Cavorite ::detail:: word_wrap
|
|||||||
}
|
}
|
||||||
if( not word.empty() ) std::ignore= putWord( std::move( word ), result, lineLength );
|
if( not word.empty() ) std::ignore= putWord( std::move( word ), result, lineLength );
|
||||||
return result;
|
return result;
|
||||||
|
#else
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
WordWrapStreambuf buf;
|
||||||
|
buf.maximumWidth= width;
|
||||||
|
buf.nextLineOffset= nextLineOffset;
|
||||||
|
buf.underlying= static_cast< std::ostream & >( oss ).rdbuf();
|
||||||
|
static_cast< std::ostream & >( oss ).rdbuf( &buf );
|
||||||
|
|
||||||
|
oss << text;
|
||||||
|
buf.drain();
|
||||||
|
|
||||||
|
auto rv= std::move( oss ).str();
|
||||||
|
return rv;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
word_wrap.h
37
word_wrap.h
@ -5,13 +5,50 @@ static_assert( __cplusplus > 2020'00 );
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <streambuf>
|
||||||
|
|
||||||
namespace Alepha::inline Cavorite ::detail:: word_wrap
|
namespace Alepha::inline Cavorite ::detail:: word_wrap
|
||||||
{
|
{
|
||||||
inline namespace exports
|
inline namespace exports
|
||||||
{
|
{
|
||||||
std::string wordWrap( const std::string &text, std::size_t width, std::size_t nextLineOffset= 0 );
|
std::string wordWrap( const std::string &text, std::size_t width, std::size_t nextLineOffset= 0 );
|
||||||
|
|
||||||
|
class WordWrapStreambuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class exports::WordWrapStreambuf
|
||||||
|
: public std::streambuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::streambuf *underlying= nullptr;
|
||||||
|
|
||||||
|
std::size_t maximumWidth= 0;
|
||||||
|
std::size_t nextLineOffset= 0;
|
||||||
|
std::size_t currentLineLength= 0;
|
||||||
|
|
||||||
|
std::string currentWord;
|
||||||
|
|
||||||
|
void writeChar( const char ch );
|
||||||
|
|
||||||
|
void drain();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int
|
||||||
|
overflow( const int ch ) override
|
||||||
|
{
|
||||||
|
if( ch == EOF ) throw std::logic_error( "EOF!" );
|
||||||
|
writeChar( ch );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamsize
|
||||||
|
xsputn( const char *const data, const std::streamsize amt ) override
|
||||||
|
{
|
||||||
|
for( std::streamsize i= 0; i< amt; ++i ) overflow( data[ i ] );
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Alepha::Cavorite::inline exports::inline word_wrap
|
namespace Alepha::Cavorite::inline exports::inline word_wrap
|
||||||
|
|||||||
@ -91,19 +91,19 @@ static auto init= Alepha::Utility::enroll <=[]
|
|||||||
},
|
},
|
||||||
{ "wider terminal, complex text: Hamlet's \"To Be or Not To Be\"",
|
{ "wider terminal, complex text: Hamlet's \"To Be or Not To Be\"",
|
||||||
{
|
{
|
||||||
"To be, or not to be: "
|
"To be, or not to be: "
|
||||||
"that is the question: "
|
"that is the question: "
|
||||||
"Whether 'tis nobler in the mind to suffer "
|
"Whether 'tis nobler in the mind to suffer "
|
||||||
"The slings and arrows of outrageous fortune, "
|
"The slings and arrows of outrageous fortune, "
|
||||||
"Or to take arms against a sea of troubles, "
|
"Or to take arms against a sea of troubles, "
|
||||||
"And by opposing end them? "
|
"And by opposing end them? "
|
||||||
"To die: to sleep; "
|
"To die: to sleep; "
|
||||||
"No more; and by a sleep to say we end "
|
"No more; and by a sleep to say we end "
|
||||||
"The heart-ache and the thousand natural shocks "
|
"The heart-ache and the thousand natural shocks "
|
||||||
"That flesh is heir to, 'tis a consummation "
|
"That flesh is heir to, 'tis a consummation "
|
||||||
"Devoutly to be wish'd. To die, to sleep; "
|
"Devoutly to be wish'd. To die, to sleep; "
|
||||||
"To sleep: perchance to dream: ay, there's the rub;",
|
"To sleep: perchance to dream: ay, there's the rub;",
|
||||||
80, 0
|
80, 0
|
||||||
},
|
},
|
||||||
"To be, or not to be: that is the question: Whether 'tis nobler in the mind to \n"
|
"To be, or not to be: that is the question: Whether 'tis nobler in the mind to \n"
|
||||||
"suffer The slings and arrows of outrageous fortune, Or to take arms against a \n"
|
"suffer The slings and arrows of outrageous fortune, Or to take arms against a \n"
|
||||||
|
|||||||
Reference in New Issue
Block a user