pretty printing -- copmlete for xo::ast::GeneralizedExpression
This commit is contained in:
parent
7ddb79fadd
commit
c2dcc84c2e
14 changed files with 572 additions and 292 deletions
|
|
@ -16,6 +16,16 @@ namespace xo {
|
|||
**/
|
||||
template <typename CharT, typename Traits = std::char_traits<CharT>>
|
||||
class log_streambuf : public std::streambuf {
|
||||
public:
|
||||
struct rewind_state {
|
||||
explicit rewind_state(std::size_t solpos, std::size_t color_esc, std::uint32_t p)
|
||||
: solpos{solpos}, color_escape_chars{color_esc}, pos{p} {}
|
||||
|
||||
std::size_t solpos = 0;
|
||||
std::size_t color_escape_chars = 0;
|
||||
std::uint32_t pos = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
log_streambuf(std::uint32_t buf_z, bool debug_flag = false) : debug_flag_{debug_flag} {
|
||||
this->buf_v_.resize(buf_z);
|
||||
|
|
@ -27,8 +37,15 @@ namespace xo {
|
|||
char const * hi() const { return this->lo() + this->capacity(); }
|
||||
std::uint32_t pos() const { return this->pptr() - this->pbase(); }
|
||||
|
||||
/** number of characters since start of line (last \n or \r) **/
|
||||
std::uint32_t lpos() const { return pos() - solpos_; }
|
||||
/** number of visible characters since start of line (last \n or \r) **/
|
||||
std::uint32_t lpos() const {
|
||||
assert(pos() >= solpos_ + color_escape_chars_);
|
||||
return pos() - solpos_ - color_escape_chars_;
|
||||
}
|
||||
|
||||
rewind_state checkpoint() const {
|
||||
return rewind_state(solpos_, color_escape_chars_, pos());
|
||||
}
|
||||
|
||||
bool debug_flag() const { return debug_flag_; }
|
||||
|
||||
|
|
@ -40,12 +57,24 @@ namespace xo {
|
|||
this->setp(p_lo, p_hi);
|
||||
|
||||
this->solpos_ = 0;
|
||||
this->color_escape_chars_ = 0;
|
||||
this->color_escape_start_ = nullptr;
|
||||
} /*reset_stream*/
|
||||
|
||||
void rewind_to(std::uint32_t p) {
|
||||
void rewind_to(rewind_state s) {
|
||||
if (debug_flag_) {
|
||||
std::cout << "rewind_to: pos " << pos() << "->" << s.pos
|
||||
<< " solpos " << solpos_ << "->" << s.solpos
|
||||
<< " color_esc " << color_escape_chars_ << "->" << s.color_escape_chars
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
/* .setp(): using for side effect: sets .pptr to .pbase */
|
||||
this->setp(this->pbase(), this->epptr());
|
||||
this->pbump(p);
|
||||
this->pbump(s.pos);
|
||||
|
||||
this->solpos_ = s.solpos;
|
||||
this->color_escape_chars_ = s.color_escape_chars;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -65,7 +94,7 @@ namespace xo {
|
|||
|
||||
this->setp(p_base, p_hi);
|
||||
this->pbump(old_n);
|
||||
} /*expand*/
|
||||
}
|
||||
|
||||
virtual std::streamsize
|
||||
xsputn(char const * s, std::streamsize n) override {
|
||||
|
|
@ -94,7 +123,7 @@ namespace xo {
|
|||
ncopied = n;
|
||||
}
|
||||
|
||||
if (debug_flag_) {
|
||||
if (false /*debug_flag_*/) {
|
||||
std::cout << "xsputn: copying ncopied=" << ncopied << " (/n=" << n << ") bytes into range [lo,hi)"
|
||||
<< ", lo=" << (void*)this->pptr()
|
||||
<< ", hi=" << (void*)(this->pptr() + n)
|
||||
|
|
@ -103,11 +132,39 @@ namespace xo {
|
|||
|
||||
std::memcpy(this->pptr(), s, ncopied);
|
||||
|
||||
/* scan range [pptr, pptr+n] backwards, to account for newline (if any) */
|
||||
for (char const * p_lo = this->pptr(), * p_hi = p_lo + n - 1, * p = p_hi; p >= p_lo; --p) {
|
||||
/* scan range [pptr, pptr+n] for:
|
||||
* 1. completed color escape sequences \033..m
|
||||
* - account for chars in these sequences, since non-printing
|
||||
* 2. newlines (and carriage returns)
|
||||
* - remember position of last {newline or carriage return)
|
||||
*/
|
||||
for (char const * p_lo = this->pptr(), * p_hi = p_lo + n, * p = p_lo; p < p_hi; ++p) {
|
||||
if (*p == '\n' || *p == '\r') {
|
||||
this->solpos_ = (p+1 - this->pbase());
|
||||
break;
|
||||
/* reset, since these chars relevant as correction to solpos */
|
||||
this->color_escape_chars_ = 0;
|
||||
/* -> incomplete color escape, broken by newline */
|
||||
this->color_escape_start_ = nullptr;
|
||||
} else if (*p == '\033') {
|
||||
if (debug_flag_) {
|
||||
std::cout << "xsputn: \\033 at p-p_lo=" << (p - p_lo) << std::endl;
|
||||
}
|
||||
this->color_escape_start_ = p;
|
||||
} else if (this->color_escape_start_ != nullptr) {
|
||||
if (*p == 'm') {
|
||||
/* escape seq non-printing including both endpoints */
|
||||
std::int64_t esc_chars = (p+1 - color_escape_start_);
|
||||
this->color_escape_chars_ += esc_chars;
|
||||
|
||||
if (debug_flag_) {
|
||||
std::cout << "xsputn: m at p-p_lo" << (p - p_lo) << " +" << esc_chars
|
||||
<< " -> color_escape_chars=" << color_escape_chars_ << std::endl;
|
||||
}
|
||||
this->color_escape_start_ = nullptr;
|
||||
} else if (!isdigit(*p) && (*p != '[') && (*p != ';')) {
|
||||
/* not color escape after all */
|
||||
this->color_escape_start_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,32 +174,32 @@ namespace xo {
|
|||
} /*xsputn*/
|
||||
|
||||
virtual int_type
|
||||
overflow(int_type new_ch) override
|
||||
{
|
||||
char * old_pptr = this->pptr();
|
||||
std::streamsize old_n = old_pptr - this->pbase();
|
||||
overflow(int_type new_ch) override {
|
||||
char * old_pptr = this->pptr();
|
||||
std::streamsize old_n = old_pptr - this->pbase();
|
||||
|
||||
assert(old_n <= static_cast<std::streamsize>(this->buf_v_.size()));
|
||||
assert(old_n <= static_cast<std::streamsize>(this->buf_v_.size()));
|
||||
|
||||
if (debug_flag_) {
|
||||
std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl;
|
||||
}
|
||||
if (debug_flag_) {
|
||||
std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl;
|
||||
}
|
||||
|
||||
this->expand_to(2 * buf_v_.size());
|
||||
this->expand_to(2 * buf_v_.size());
|
||||
|
||||
this->buf_v_[old_n] = new_ch;
|
||||
this->pbump(1);
|
||||
this->buf_v_[old_n] = new_ch;
|
||||
this->pbump(1);
|
||||
|
||||
if ((new_ch == static_cast<int_type>('\n')) || (new_ch == static_cast<int_type>('\r')))
|
||||
this->solpos_ = this->pos();
|
||||
if ((new_ch == static_cast<int_type>('\n')) || (new_ch == static_cast<int_type>('\r'))) {
|
||||
this->solpos_ = this->pos();
|
||||
}
|
||||
|
||||
if (new_ch == Traits::eof()) {
|
||||
/* reminder: returning eof sets badbit on ostream */
|
||||
return Traits::not_eof(new_ch);
|
||||
} else {
|
||||
return new_ch;
|
||||
}
|
||||
} /*overflow*/
|
||||
if (new_ch == Traits::eof()) {
|
||||
/* reminder: returning eof sets badbit on ostream */
|
||||
return Traits::not_eof(new_ch);
|
||||
} else {
|
||||
return new_ch;
|
||||
}
|
||||
} /*overflow*/
|
||||
|
||||
/* off. offset, relative to starting point dir.
|
||||
* dir.
|
||||
|
|
@ -154,6 +211,9 @@ namespace xo {
|
|||
std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode which) override {
|
||||
//std::cout << "seekoff: off=" << off << ", dir=" << dir << ", which=" << which << std::endl;
|
||||
if (debug_flag_) {
|
||||
std::cout << "seekoff(off,dir,which)" << std::endl;
|
||||
}
|
||||
|
||||
// Only output stream is supported
|
||||
if (which != std::ios_base::out)
|
||||
|
|
@ -179,6 +239,13 @@ namespace xo {
|
|||
* Use to drive @ref lpos
|
||||
**/
|
||||
std::size_t solpos_ = 0;
|
||||
/** number of non-printing chars after @ref solpos_, from
|
||||
* completed color escape sequences.
|
||||
* (ansi color escapes = text between '\033' and 'm')
|
||||
**/
|
||||
std::size_t color_escape_chars_ = 0;
|
||||
/** non-null: start of incomplete color escape sequence **/
|
||||
char const * color_escape_start_ = nullptr;
|
||||
/** buffered output stored here **/
|
||||
std::vector<char> buf_v_;
|
||||
/** true to debug log_streambuf itself **/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue