Sign in to follow this  

Custom cout formatting using /tags

This topic is 2043 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

In my game engine I output stuff for debugging purposes to the windows console using std::cout.
I wanted to use colors so I can more easily oversee what is going on, as well as some "macros" using /tags.
Let me show an example of what I am talking about:

[CODE]
myCout << "/warn Entity: "<< EntityName << "is doing /fgRed badstuff \n";
[/CODE]

would output:

[color=#8b4513]Warning: [/color]Entity: obj1 is doing [color=#ff0000]badstuff[/color]


The way I have this is that I parse a stringstream.str() and send that string to my function that will format it and output it, but it currently looks like:

[CODE]
mysstream << "/warn Entity: "<< EntityName << "is doing /fgRed badstuff \n";
myCout(mysstream.str());
[/CODE]

Obviously, I don't want to do this for every output, I want to use my output function just like std::cout, having the functionality of the same << operators, but does my formatting also.

How could I achieve this?
Your help is much appreciated!

Share this post


Link to post
Share on other sites
In the end you have to parse your string somewhere if you want to work with tags like this. Another way would be that your format your streams like the C++ streams with flags that can be passed to the stream instead of stringbased tags. (Google "C++ stream formatting" for this), which might mean that you have to create your own stream implentation and maybe a custom "device" or widget to display your messages.

Another simple way would be to define different macros which encapsulate your stream. But the problem with changing colors inside the message remains.
[CODE]
#define Info std::cout << "INFO: "
#define Warn std::cout << "WARNING: "
...
Info << "some information message\n";
Warn << "Warning stuff and a float: " << 1.0f << "\n";
[/CODE]

Share this post


Link to post
Share on other sites
I'd do something like this:

[code]
#include <iostream>
#include <windows.h>

using namespace std;

struct color {
unsigned char c;
color(unsigned char _c=0) : c(_c) {}
};
const color black(0);
const color blue(1);
const color green(2);
const color aqua(3);
const color red(4);
const color purple(5);
const color yellow(6);
const color white(7);
const color gray(8);
const color lightblue(9);
const color lightgreen(10);
const color lightaqua(11);
const color lightred(12);
const color lightpurple(13);
const color lightyellow(14);
const color brightwhite(15);

// Overload stream operator with color
std::ostream& operator<<(std::ostream& str, const color& c);

HANDLE handle; ///< Output handle

int main() {
if(AllocConsole());
handle=GetStdHandle(STD_OUTPUT_HANDLE);

cout << lightgreen << "Hello world!" << white << endl;
}

void setColor(unsigned char color) {
if(handle) SetConsoleTextAttribute(handle, color);
}

std::ostream& operator<<(std::ostream& str, const color& c) {
setColor(c.c);
return str;
}
[/code]

Share this post


Link to post
Share on other sites
Thanks for your replies doeme and mrjones!

The reason I would like it string based, that in that way I could also parse text from files that will be formatted and colored the way I want.

The reason I don't want to use hardcoded macros is because I would like my engine to be able to handle per-project custom tags, such that a file can be parsed that describes a list of custom tags and their corresponding custom strings (defined by the user without knowledge or access to engine code) that they resolve into and will be placed in a std::map<string, string>
example : "/goblin" = "/fgCyan GoblinName: /fgDarkGreen /bgWhite"

Any ideas?
Or is this impossible with a one liner? (like a cout statement?) Edited by chondee

Share this post


Link to post
Share on other sites
I guess it comes down to this:

Do I have to sacrifice one of the following:
[color=#ff0000][b]1. [/b][/color][color=#000000]String based color tags and macros[/color]
[b][color=#ff0000]2. [/color][/b]<<Operator for string conversion of variables

for this to be possible in a one line statement?

Edit:
If yes, than for THAT I could actually use a macro that aggregates the stringstream statement and the myFormattingCout(stringstream.str())

If it is however possible without a macro I would rather take that, so please let me know if you think it is. Edited by chondee

Share this post


Link to post
Share on other sites
Anything is possible. Maybe something like this would work for you? Example is without formatting and without colors output.

[code]
std::ostream& operator<<(std::ostream& str, const char* c);

int main() {
if(AllocConsole());
handle=GetStdHandle(STD_OUTPUT_HANDLE);

cout << "/fgCyan" << endl;
}

void setColor(unsigned char color) {
if(handle) SetConsoleTextAttribute(handle, color);
}

std::ostream& operator<<(std::ostream& str, const char* c) {
setColor(lightblue.c);

// Do formatting and output text in your own colors
str.write(c, strlen(c));
return str;
}
[/code]

Share this post


Link to post
Share on other sites

This topic is 2043 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this