rang
rang copied to clipboard
Two features that would be nice to have
-
[x] 1 A switch to turn this on and off. Not sure how this could be done in with the relative statelessness of the library, but it would be nice to be able to provide my users with an option to disable colors (some people hate it) and not have to have two different code paths. In other words, something like
std::cout << rang::fg::red << "Error";
would be red or not according to some switch. -
[ ] 2 Storing the colors in a stream for later printing It would be nice if we could do something like:
std::ostream foo;
foo << rang::fg::red << "Error";
std::cout << foo.cstr() << std::endl;
And still have the text be red. I realize this would probably require significant changes and would probably be something more like:
rang::ostream foo;
foo << rang::fg::red << "Error";
std::cout << foo << std::endl;
But it would be a great feature!
Anyway, I'm definitely using this library already. Great work.
Thankyou for your kind words 😄 . About 1st - one thing we could try is having rang::colors::off
or something so when next time it prints, colors are not shown. or I'm open to ideas if you've any.
For 2nd - it was on my mind when I started but I somehow forgot along the way. I do have some exams coming this month but I'll work on it when I get some time. Meanwhile I'm open to accepting Pull Requests :octocat: for the same.
I think the 1st can be done simply via the non-tty-output mechanics: just setting the rang::coutbuf
to nullptr
should disable the coloring. It would still be sensitive to the "force color" thing of course but perhaps this is even a desired behavior?
(congratulations on the release by the way :smile: )
or maybe by using enum class control { autoColor = 0, forceColor = 1 };
with another added member offColor = 2
? or infact enum class control { offColor = 0, autoColor = 1, forceColor = 2 };
and then we could do -
template <typename T>
inline rang_implementation::enableControl<T> operator<<(
std::ostream &os, T const value)
{
....
} else if (value == rang::control::offColor) {
os.iword(rang_implementation::getIword()) = 0;
}
return os;
}
and at last modify this bit -
template <typename T>
inline rang_implementation::enableStd<T> operator<<(
std::ostream &os, T const value)
{
....
return (os.iword(rang_implementation::getIword())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
....
}
to accept 3 values instead of 0 and 1 which acted as bool. What's your thought about this @AxelStrem ?
@agauniyal That implementation for #1 is the path I started going down to implement this on my own. If I get something working well in the next few days I'll submit a pull request.
@zethon sure thing 👍
@agauniyal yeah, that looks like a proper way to do it. Can't find any reasons for that not to work:)
No ideas on #2 though
The second one looks like one of the feature request made up in #51 though.
@zethon the first request has landed in develop branch and for now it's stable so you can fork the repo if you need that option right now. I'm putting halt on further feature development till #56 is completed which is going to bring major changes in the lib. I'll take look at the 2nd request after it.
I was testing some scratch code and your 2nd request is also possible without changing much code. instead of direct writing to cout, you'll have to force rang to output colors(instead of autodetect itself) and write to a std::ostream
object. then there would be a function where you'll feed that object along with a number (0 = offColor, 1 = autoColor, 2 = forceColor) again and feed that function to std::cout
which will handle the stream again.
However there are 2 blocking task before this, one that I mentioned above and another being a terminfo parser that I'll be working on before I start out on this again. However I'm open to accepting PRs if someone wants to do this before me 😄 .
Will your suggested implementation work for concatenating streams? If other words, I would like to do something like:
std::ostream buffer1;
buffer1 << rang::fg::red << "This is red";
std::ostream buffer2;
buffer2 << rang::fg::yellow << "This is yellow";
std::cout << buffer1.cstr() << " " << buffer2.cstr();
Or even have buffer1
and buffer2
feed into a buffer3
and then call std::cout << buffer3.cstr();
What I was thinking of was along the lines of a function rang::someFunc(buffer, mode)
where you could pass a single buffer or two concatenated buffers and it would either strip out escape codes or autodetect or let them remain in the stream before printing to cout -
std::ostream buffer1;
buffer1 << rang::fg::red << "This is red";
std::ostream buffer2;
buffer2 << rang::fg::yellow << "This is yellow";
std::cout << rang::method(buffer1, autoDetect) << " " << rang::method(buffer2, force)
I'm open to suggestions and PRs if you've anything else in mind.
Regarding the "turn on/off colors", what about an environment variable RANG_COLORS that can be set to on/off to force to turn on or off colors? That way code can stay the same but the user can control whether to enable or disable colors if the automatic detection says otherwise?
I think it would be better to leave that choice to the user of this library. This way user can decide whether to use 'RANG_COLORS' or something other like 'COLORS' etc and call setControlMode()
after detecting the env variable themselves 😸
I am beginner but i can help. (I may need a mentor). If we make another class RangBuffer. it will contain all the enums and it will implement the output operator '<<'. I am on it