Design question: A little C++ header for colorizing text in Linux -- Comments/Ideas

S

Slash

I often do a lot of text-mode programming in Linux and wanted to use
colors in text mode, and found the ncurses library needlessly complex
for small applications. So I wrote my own little header to handle
colors in C++. (The code follows.)

This allows me to write code like

cout << gotoxy(10, 11)
<< color(lightcyan, blue)
<< "some text whatever";

I'd like to know how I could implement this more efficiently or in a
better way. Here are some questions I have:

(1) What exactly is a manipulator and how do I write one? How could a
manipulator help here?

(2) All that color and gotoxy do is simply output the corresponding
ANSI escape sequence string. How could I best make a color pair map
into its corresponding ANSI escape string?

(3) Could I selectively output the characters for gotoxy and color
(they simply output the corresponding ANSI escape sequences) only when
it is used with cout and not an ofstream object?

(4) How could I make this more easy to use?

Thanks in advance :)

-----------------------------------------------------

Here's the code:

//---------------------------------------------
// color.h
//---------------------------------------------

#ifndef COLOR_H
#define COLOR_H

#include <iostream>
using namespace std;

enum ColorName
{
black,
red,
green,
brown,
blue,
magenta,
cyan,
lightgray,

darkgray,
lightred,
lightgreen,
yellow,
lightblue,
lightmagenta,
lightcyan,
white
};


struct color
{
color(ColorName f = white, ColorName b = black)
:
fore(f),
back(b)
{}


ColorName fore;
ColorName back;
};


inline ostream& operator<<(ostream& o, const color& c)
{
if(c.fore > lightgray) // bold color
o << "\033[1;3" << c.fore - lightgray - 1 << "m";
else
o << "\033[0;3" << c.fore << "m";

return o << "\033[4" << c.back << "m";
}


struct gotoxy
{
gotoxy(int x_, int y_)
:
x(x_),
y(y_)
{}

int x;
int y;

};


inline ostream& operator<<(ostream& o, const gotoxy& g)
{
return o << "\033[" << g.y << ";" << g.x << "f";
}

#endif
 
V

Victor Bazarov

Slash said:
I often do a lot of text-mode programming in Linux and wanted to use
colors in text mode, and found the ncurses library needlessly complex
for small applications. So I wrote my own little header to handle
colors in C++. (The code follows.)

This allows me to write code like

cout << gotoxy(10, 11)
<< color(lightcyan, blue)
<< "some text whatever";

I'd like to know how I could implement this more efficiently or in a
better way.

I think your implementation is good enough. What inefficiencies do
you see in it? What is not good about it, in your opinion?
Here are some questions I have:

(1) What exactly is a manipulator and how do I write one? How could a
manipulator help here?

You have successfully written two manipulators. Why are you asking
about how to write them?
(2) All that color and gotoxy do is simply output the corresponding
ANSI escape sequence string. How could I best make a color pair map
into its corresponding ANSI escape string?

What don't you like about the way you do it now? I can see only one
marginally acceptable improvement: a table of ANSI strings instead
of the calculation. Still, to prove that it's an improvement, one
would need to profile both versions.
(3) Could I selectively output the characters for gotoxy and color
(they simply output the corresponding ANSI escape sequences) only when
it is used with cout and not an ofstream object?

No, for all intents and purposes 'std::cout' _could_ be a file. It
is impossible to tell without being platform-specific, AFAIK.
(4) How could I make this more easy to use?

It's easy as it is. How much easier do you expect it to get?

Keep in mind, though, that your code is NOT going to work on systems
that do not have ANSI terminals (and those are quite a few).

Victor
 
R

Roger Leigh

I often do a lot of text-mode programming in Linux and wanted to use
colors in text mode, and found the ncurses library needlessly complex
for small applications. So I wrote my own little header to handle
colors in C++. (The code follows.)

This allows me to write code like

cout << gotoxy(10, 11)
<< color(lightcyan, blue)
<< "some text whatever";

I'd like to know how I could implement this more efficiently or in a
better way. Here are some questions I have:

You still need libncurses, or libslang, or terminfo. If you don't,
you can't cope with non-ANSI terminals or output redirection to
non-terminal destinations.

ncurses isn't /that/ difficult. Your existing API is quite good, and
should wrap ncurses with little difficulty. You could have a base
object representing a window, and do

window << color(blue, yellow) << message;

and have this wrap printw() et. al..
(1) What exactly is a manipulator and how do I write one? How could a
manipulator help here?

Do you mean in the sense of <iomanip>? These are used to control
formatting of numbers, field widths, alignment etc. I don't think you
need to use them in your header, but users of the header would use
them to format their output appropriately.

If you output to your own class (rather than a std::eek:stream) you could
use your own custom manipulators to set the colours, coordinates,
etc..
(2) All that color and gotoxy do is simply output the corresponding
ANSI escape sequence string. How could I best make a color pair map
into its corresponding ANSI escape string?

I'd use ncurses and a defined set of COLOR_PAIRs: use an enum for the
defined values (it looks like you are already doing this).
(4) How could I make this more easy to use?

Personally, I'd prefer to use an ncurses-based toolkit that provided a
higher-level abstraction of terminal I/O, providing widgets, input
focus, container-based widget alignment and sizing etc.. Essentially,
I mean an object-oriented toolkit after the likes of GTK+/Gtkmm or
Swing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top