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