Pull out a colored text output interface out of the Console class.
parent
c260aca3f1
commit
b2737e2bed
@ -0,0 +1,190 @@
|
||||
/*
|
||||
https://github.com/peterix/dfhack
|
||||
Copyright (c) 2011 Petr Mrázek <peterix@gmail.com>
|
||||
|
||||
A thread-safe logging console with a line editor for windows.
|
||||
|
||||
Based on linenoise win32 port,
|
||||
copyright 2010, Jon Griffiths <jon_p_griffiths at yahoo dot com>.
|
||||
All rights reserved.
|
||||
Based on linenoise, copyright 2010, Salvatore Sanfilippo <antirez at gmail dot com>.
|
||||
The original linenoise can be found at: http://github.com/antirez/linenoise
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Redis nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <istream>
|
||||
#include <string>
|
||||
|
||||
#include "ColorText.h"
|
||||
#include "MiscUtils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
using namespace DFHack;
|
||||
|
||||
#include "tinythread.h"
|
||||
using namespace tthread;
|
||||
|
||||
void color_ostream::flush_buffer(bool flush)
|
||||
{
|
||||
auto buffer = buf();
|
||||
auto str = buffer->str();
|
||||
|
||||
if (!str.empty()) {
|
||||
add_text(cur_color, buffer->str());
|
||||
buffer->str(std::string());
|
||||
}
|
||||
|
||||
if (flush)
|
||||
flush_proxy();
|
||||
}
|
||||
|
||||
void color_ostream::begin_batch()
|
||||
{
|
||||
flush_buffer(false);
|
||||
}
|
||||
|
||||
void color_ostream::end_batch()
|
||||
{
|
||||
flush_proxy();
|
||||
}
|
||||
|
||||
color_ostream::color_ostream() : ostream(new buffer(this)), cur_color(COLOR_RESET)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
color_ostream::~color_ostream()
|
||||
{
|
||||
delete buf();
|
||||
}
|
||||
|
||||
void color_ostream::print(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprint(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void color_ostream::vprint(const char *format, va_list args)
|
||||
{
|
||||
std::string str = stl_vsprintf(format, args);
|
||||
|
||||
if (!str.empty()) {
|
||||
flush_buffer(false);
|
||||
add_text(cur_color, str);
|
||||
if (str[str.size()-1] == '\n')
|
||||
flush_proxy();
|
||||
}
|
||||
}
|
||||
|
||||
void color_ostream::printerr(const char * format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprinterr(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void color_ostream::vprinterr(const char *format, va_list args)
|
||||
{
|
||||
color_value save = cur_color;
|
||||
|
||||
fprintf(stderr, format, args);
|
||||
|
||||
color(COLOR_LIGHTRED);
|
||||
vprint(format, args);
|
||||
color(save);
|
||||
}
|
||||
|
||||
void color_ostream::color(color_value c)
|
||||
{
|
||||
if (c == cur_color)
|
||||
return;
|
||||
|
||||
flush_buffer(false);
|
||||
cur_color = c;
|
||||
}
|
||||
|
||||
void color_ostream::reset_color(void)
|
||||
{
|
||||
color(COLOR_RESET);
|
||||
}
|
||||
|
||||
void buffered_color_ostream::add_text(color_value color, const std::string &text)
|
||||
{
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
if (buffer.empty())
|
||||
{
|
||||
buffer.push_back(fragment_type(color, text));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &back = buffer.back();
|
||||
|
||||
if (back.first != color || std::max(back.second.size(), text.size()) > 128)
|
||||
buffer.push_back(fragment_type(color, text));
|
||||
else
|
||||
buffer.back().second += text;
|
||||
}
|
||||
}
|
||||
|
||||
void color_ostream_proxy::flush_proxy()
|
||||
{
|
||||
if (!buffer.empty())
|
||||
{
|
||||
target->begin_batch();
|
||||
|
||||
for (auto it = buffer.begin(); it != buffer.end(); ++it)
|
||||
target->add_text(it->first, it->second);
|
||||
|
||||
buffer.clear();
|
||||
|
||||
target->end_batch();
|
||||
}
|
||||
}
|
||||
|
||||
color_ostream_proxy::color_ostream_proxy(color_ostream &target)
|
||||
: target(&target)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
color_ostream_proxy::~color_ostream_proxy()
|
||||
{
|
||||
*this << std::flush;
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
https://github.com/peterix/dfhack
|
||||
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Pragma.h"
|
||||
#include "Export.h"
|
||||
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace DFHack
|
||||
{
|
||||
class DFHACK_EXPORT color_ostream : public std::ostream
|
||||
{
|
||||
public:
|
||||
enum color_value
|
||||
{
|
||||
COLOR_RESET = -1,
|
||||
COLOR_BLACK = 0,
|
||||
COLOR_BLUE,
|
||||
COLOR_GREEN,
|
||||
COLOR_CYAN,
|
||||
COLOR_RED,
|
||||
COLOR_MAGENTA,
|
||||
COLOR_BROWN,
|
||||
COLOR_GREY,
|
||||
COLOR_DARKGREY,
|
||||
COLOR_LIGHTBLUE,
|
||||
COLOR_LIGHTGREEN,
|
||||
COLOR_LIGHTCYAN,
|
||||
COLOR_LIGHTRED,
|
||||
COLOR_LIGHTMAGENTA,
|
||||
COLOR_YELLOW,
|
||||
COLOR_WHITE,
|
||||
COLOR_MAX = COLOR_WHITE
|
||||
};
|
||||
|
||||
private:
|
||||
color_value cur_color;
|
||||
|
||||
class buffer : public std::stringbuf
|
||||
{
|
||||
public:
|
||||
color_ostream *owner;
|
||||
|
||||
buffer(color_ostream *owner) : owner(owner) {}
|
||||
virtual ~buffer() { }
|
||||
|
||||
protected:
|
||||
virtual int sync() {
|
||||
owner->flush_buffer(true);
|
||||
}
|
||||
};
|
||||
|
||||
buffer *buf() { return (buffer*)rdbuf(); }
|
||||
|
||||
void flush_buffer(bool flush);
|
||||
|
||||
protected:
|
||||
// These must be strictly balanced, because
|
||||
// they might grab and hold mutexes.
|
||||
virtual void begin_batch();
|
||||
virtual void end_batch();
|
||||
|
||||
virtual void add_text(color_value color, const std::string &text) = 0;
|
||||
|
||||
virtual void flush_proxy() {};
|
||||
|
||||
friend class color_ostream_proxy;
|
||||
public:
|
||||
color_ostream();
|
||||
virtual ~color_ostream();
|
||||
|
||||
/// Print a formatted string, like printf
|
||||
void print(const char *format, ...);
|
||||
void vprint(const char *format, va_list args);
|
||||
|
||||
/// Print a formatted string, like printf, in red
|
||||
void printerr(const char *format, ...);
|
||||
void vprinterr(const char *format, va_list args);
|
||||
|
||||
/// Set color (ANSI color number)
|
||||
void color(color_value c);
|
||||
/// Reset color to default
|
||||
void reset_color(void);
|
||||
|
||||
virtual bool is_console() { return false; }
|
||||
};
|
||||
|
||||
class DFHACK_EXPORT buffered_color_ostream : public color_ostream
|
||||
{
|
||||
protected:
|
||||
virtual void add_text(color_value color, const std::string &text);
|
||||
|
||||
public:
|
||||
typedef std::pair<color_value,std::string> fragment_type;
|
||||
|
||||
buffered_color_ostream() {}
|
||||
~buffered_color_ostream() {}
|
||||
|
||||
const std::list<fragment_type> &fragments() { return buffer; }
|
||||
|
||||
protected:
|
||||
std::list<fragment_type> buffer;
|
||||
};
|
||||
|
||||
class DFHACK_EXPORT color_ostream_proxy : public buffered_color_ostream
|
||||
{
|
||||
protected:
|
||||
color_ostream *target;
|
||||
|
||||
virtual void flush_proxy();
|
||||
|
||||
public:
|
||||
color_ostream_proxy(color_ostream &target);
|
||||
~color_ostream_proxy();
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue