set_color: Honor modifiers (bold, background..) with --print-colors

Fixes 
This commit is contained in:
Fabian Homborg 2020-09-16 21:14:28 +02:00
parent 304649acc6
commit 58245b6fe7
2 changed files with 118 additions and 33 deletions

@ -33,15 +33,53 @@
class parser_t;
static void print_colors(io_streams_t &streams) {
outputter_t outp;
static void print_modifiers(outputter_t &outp, bool bold, bool underline, bool italics, bool dim, bool reverse, rgb_color_t bg) {
if (bold && enter_bold_mode) {
// These casts are needed to work with different curses implementations.
writembs_nofail(outp, tparm(const_cast<char *>(enter_bold_mode)));
}
if (underline && enter_underline_mode) {
writembs_nofail(outp, enter_underline_mode);
}
if (italics && enter_italics_mode) {
writembs_nofail(outp, enter_italics_mode);
}
if (dim && enter_dim_mode) {
writembs_nofail(outp, enter_dim_mode);
}
if (reverse && enter_reverse_mode) {
writembs_nofail(outp, enter_reverse_mode);
} else if (reverse && enter_standout_mode) {
writembs_nofail(outp, enter_standout_mode);
}
if (!bg.is_none() && bg.is_normal()) {
writembs_nofail(outp, tparm(const_cast<char *>(exit_attribute_mode)));
}
}
static void print_colors(io_streams_t &streams, bool bold, bool underline, bool italics, bool dim, bool reverse, rgb_color_t bg) {
outputter_t outp;
for (const auto &color_name : rgb_color_t::named_color_names()) {
if (!streams.out_is_redirected && isatty(STDOUT_FILENO)) {
print_modifiers(outp, bold, underline, italics, dim, reverse, bg);
rgb_color_t color = rgb_color_t(color_name);
outp.set_color(color, rgb_color_t::none());
if (!bg.is_none()) {
outp.write_color(bg, false /* not is_fg */);
}
}
outp.writestr(color_name);
if (!bg.is_none()) {
// If we have a background, stop it after the color
// or it goes to the end of the line and looks ugly.
writembs_nofail(outp, tparm(const_cast<char *>(exit_attribute_mode)));
}
outp.writech(L'\n');
} // conveniently, 'normal' is always the last color so we don't need to reset here
@ -96,7 +134,7 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
}
const wchar_t *bgcolor = nullptr;
bool bold = false, underline = false, italics = false, dim = false, reverse = false;
bool bold = false, underline = false, italics = false, dim = false, reverse = false, print = false;
// Parse options to obtain the requested operation and the modifiers.
int opt;
@ -132,8 +170,8 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
break;
}
case 'c': {
print_colors(streams);
return STATUS_CMD_OK;
print = true;
break;
}
case ':': {
// We don't error here because "-b" is the only option that requires an argument,
@ -149,6 +187,17 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
}
}
const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L"");
if (bgcolor && bg.is_none()) {
streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], bgcolor);
return STATUS_INVALID_ARGS;
}
if (print) {
print_colors(streams, bold, underline, italics, dim, reverse, bg);
return STATUS_CMD_OK;
}
// Remaining arguments are foreground color.
std::vector<rgb_color_t> fgcolors;
for (; w.woptind < argc; w.woptind++) {
@ -165,12 +214,6 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
const rgb_color_t fg = best_color(fgcolors, output_get_color_support());
assert(fgcolors.empty() || !fg.is_none());
const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L"");
if (bgcolor && bg.is_none()) {
streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], bgcolor);
return STATUS_INVALID_ARGS;
}
// Test if we have at least basic support for setting fonts, colors and related bits - otherwise
// just give up...
if (cur_term == nullptr || !exit_attribute_mode) {
@ -178,28 +221,7 @@ maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t
}
outputter_t outp;
if (bold && enter_bold_mode) {
// These casts are needed to work with different curses implementations.
writembs_nofail(outp, tparm(const_cast<char *>(enter_bold_mode)));
}
if (underline && enter_underline_mode) {
writembs_nofail(outp, enter_underline_mode);
}
if (italics && enter_italics_mode) {
writembs_nofail(outp, enter_italics_mode);
}
if (dim && enter_dim_mode) {
writembs_nofail(outp, enter_dim_mode);
}
if (reverse && enter_reverse_mode) {
writembs_nofail(outp, enter_reverse_mode);
} else if (reverse && enter_standout_mode) {
writembs_nofail(outp, enter_standout_mode);
}
print_modifiers(outp, bold, underline, italics, dim, reverse, bg);
if (bgcolor != nullptr && bg.is_normal()) {
writembs_nofail(outp, tparm(const_cast<char *>(exit_attribute_mode)));

@ -0,0 +1,63 @@
#!/usr/bin/env python3
from pexpect_helper import SpawnedProc
import subprocess
import sys
import time
import os
env = os.environ.copy()
env["TERM"] = "xterm"
sp = SpawnedProc(env=env)
send, sendline, sleep, expect_prompt, expect_re, expect_str = (
sp.send,
sp.sendline,
sp.sleep,
sp.expect_prompt,
sp.expect_re,
sp.expect_str,
)
expect_prompt()
# See that --print-colors prints the colors colored.
# Note that we don't check *all* of them, just a few.
sendline("set_color --print-colors")
expect_str("black")
expect_str("blue")
expect_str("brblack")
expect_str("brblue")
expect_str("brcyan")
expect_str("brgreen")
expect_str("brmagenta")
expect_str("brred")
expect_str("brwhite")
expect_str("bryellow")
expect_str("cyan")
expect_str("green")
expect_str("magenta")
expect_str("\x1b[31mred")
expect_str("\x1b[37mwhite")
expect_str("\x1b[33myellow")
expect_str("normal")
expect_prompt()
sendline ("set_color --background blue --print-colors")
expect_str("black")
expect_str("blue")
expect_str("brblack")
expect_str("brblue")
expect_str("brcyan")
expect_str("brgreen")
expect_str("brmagenta")
expect_str("brred")
expect_str("brwhite")
expect_str("bryellow")
expect_str("cyan")
expect_str("green")
expect_str("magenta")
expect_str("\x1b[31m\x1b[44mred")
expect_str("white")
expect_str("yellow")
expect_str("normal")
expect_prompt()