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 <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
#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.
|
||||
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;
|
||||
|
||||
@ -23,25 +25,67 @@ namespace Alepha::Cavorite ::detail:: word_wrap
|
||||
{
|
||||
if( currentLineWidth + word.size() > maximumWidth )
|
||||
{
|
||||
result+= '\n';
|
||||
std::fill_n( back_inserter( result ), nextLineOffset, ' ' );
|
||||
result << "\n";
|
||||
std::fill_n( std::ostream_iterator< char >( result ), nextLineOffset, ' ' );
|
||||
return nextLineOffset;
|
||||
}
|
||||
else return currentLineWidth;
|
||||
};
|
||||
|
||||
const auto rv= lineWidth + word.size();
|
||||
result+= std::move( word );
|
||||
result << std::move( word );
|
||||
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
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
@ -78,5 +122,20 @@ namespace Alepha::Cavorite ::detail:: word_wrap
|
||||
}
|
||||
if( not word.empty() ) std::ignore= putWord( std::move( word ), result, lineLength );
|
||||
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 <string>
|
||||
#include <streambuf>
|
||||
|
||||
namespace Alepha::inline Cavorite ::detail:: word_wrap
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
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
|
||||
|
@ -91,19 +91,19 @@ static auto init= Alepha::Utility::enroll <=[]
|
||||
},
|
||||
{ "wider terminal, complex text: Hamlet's \"To Be or Not To Be\"",
|
||||
{
|
||||
"To be, or not to be: "
|
||||
"that is the question: "
|
||||
"Whether 'tis nobler in the mind to suffer "
|
||||
"The slings and arrows of outrageous fortune, "
|
||||
"Or to take arms against a sea of troubles, "
|
||||
"And by opposing end them? "
|
||||
"To die: to sleep; "
|
||||
"No more; and by a sleep to say we end "
|
||||
"The heart-ache and the thousand natural shocks "
|
||||
"That flesh is heir to, 'tis a consummation "
|
||||
"Devoutly to be wish'd. To die, to sleep; "
|
||||
"To sleep: perchance to dream: ay, there's the rub;",
|
||||
80, 0
|
||||
"To be, or not to be: "
|
||||
"that is the question: "
|
||||
"Whether 'tis nobler in the mind to suffer "
|
||||
"The slings and arrows of outrageous fortune, "
|
||||
"Or to take arms against a sea of troubles, "
|
||||
"And by opposing end them? "
|
||||
"To die: to sleep; "
|
||||
"No more; and by a sleep to say we end "
|
||||
"The heart-ache and the thousand natural shocks "
|
||||
"That flesh is heir to, 'tis a consummation "
|
||||
"Devoutly to be wish'd. To die, to sleep; "
|
||||
"To sleep: perchance to dream: ay, there's the rub;",
|
||||
80, 0
|
||||
},
|
||||
"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"
|
||||
|
Reference in New Issue
Block a user