mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-26 10:43:47 +08:00
Make set_color take multiple colors, and choose the best supported one
As suggested in #1323
This commit is contained in:
parent
43d23ee56e
commit
e83441395e
|
@ -132,37 +132,31 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* Remaining argument is foreground color */
|
||||
const wchar_t *fgcolor = NULL;
|
||||
if (woptind < argc)
|
||||
/* Remaining arguments are foreground color */
|
||||
std::vector<rgb_color_t> fgcolors;
|
||||
for (; woptind < argc; woptind++)
|
||||
{
|
||||
if (woptind + 1 == argc)
|
||||
rgb_color_t fg = rgb_color_t(argv[woptind]);
|
||||
if (fg.is_none() || fg.is_ignore())
|
||||
{
|
||||
fgcolor = argv[woptind];
|
||||
}
|
||||
else
|
||||
{
|
||||
append_format(stderr_buffer,
|
||||
_(L"%ls: Too many arguments\n"),
|
||||
argv[0]);
|
||||
append_format(stderr_buffer, _(L"%ls: Unknown color '%ls'\n"), argv[0], argv[woptind]);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
fgcolors.push_back(fg);
|
||||
}
|
||||
|
||||
if (fgcolor == NULL && bgcolor == NULL && !bold && !underline)
|
||||
if (fgcolors.empty() && bgcolor == NULL && !bold && !underline)
|
||||
{
|
||||
append_format(stderr_buffer,
|
||||
_(L"%ls: Expected an argument\n"),
|
||||
argv[0]);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
const rgb_color_t fg = rgb_color_t(fgcolor ? fgcolor : L"");
|
||||
if (fgcolor && (fg.is_none() || fg.is_ignore()))
|
||||
{
|
||||
append_format(stderr_buffer, _(L"%ls: Unknown color '%ls'\n"), argv[0], fgcolor);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
// #1323: We may have multiple foreground colors. Choose the best one.
|
||||
// If we had no foreground coor, we'll get none(); if we have at least one we expect not-none
|
||||
const rgb_color_t fg = best_color(fgcolors, output_get_color_support());
|
||||
assert(fgcolors.empty() || !(fg.is_none() || fg.is_ignore()));
|
||||
|
||||
const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L"");
|
||||
if (bgcolor && (bg.is_none() || bg.is_ignore()))
|
||||
|
@ -187,7 +181,6 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv)
|
|||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Save old output function so we can restore it */
|
||||
int (* const saved_writer_func)(char) = output_get_writer();
|
||||
|
||||
|
@ -216,7 +209,7 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv)
|
|||
}
|
||||
}
|
||||
|
||||
if (fgcolor != NULL)
|
||||
if (! fg.is_none())
|
||||
{
|
||||
if (fg.is_normal() || fg.is_reset())
|
||||
{
|
||||
|
|
65
output.cpp
65
output.cpp
|
@ -488,6 +488,45 @@ void writestr(const wchar_t *str)
|
|||
delete[] buffer;
|
||||
}
|
||||
|
||||
rgb_color_t best_color(const std::vector<rgb_color_t> &candidates, color_support_t support)
|
||||
{
|
||||
if (candidates.empty())
|
||||
{
|
||||
return rgb_color_t::none();
|
||||
}
|
||||
|
||||
rgb_color_t first_rgb = rgb_color_t::none(), first_named = rgb_color_t::none();
|
||||
for (size_t i=0; i < candidates.size(); i++)
|
||||
{
|
||||
const rgb_color_t &color = candidates.at(i);
|
||||
if (first_rgb.is_none() && color.is_rgb())
|
||||
{
|
||||
first_rgb = color;
|
||||
}
|
||||
if (first_named.is_none() && color.is_named())
|
||||
{
|
||||
first_named = color;
|
||||
}
|
||||
}
|
||||
// If we have both RGB and named colors, then prefer rgb if term256 is supported
|
||||
rgb_color_t result = rgb_color_t::none();
|
||||
bool has_term256 = !! (support & color_support_term256);
|
||||
if ((!first_rgb.is_none() && has_term256) || first_named.is_none())
|
||||
{
|
||||
result = first_rgb;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = first_named;
|
||||
}
|
||||
if (result.is_none())
|
||||
{
|
||||
result = candidates.at(0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This code should be refactored to enable sharing with builtin_set_color */
|
||||
rgb_color_t parse_color(const wcstring &val, bool is_background)
|
||||
{
|
||||
int is_bold=0;
|
||||
|
@ -530,30 +569,8 @@ rgb_color_t parse_color(const wcstring &val, bool is_background)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the best candidate
|
||||
rgb_color_t first_rgb = rgb_color_t::none(), first_named = rgb_color_t::none();
|
||||
for (size_t i=0; i < candidates.size(); i++)
|
||||
{
|
||||
const rgb_color_t &color = candidates.at(i);
|
||||
if (color.is_rgb() && first_rgb.is_none())
|
||||
first_rgb = color;
|
||||
if (color.is_named() && first_named.is_none())
|
||||
first_named = color;
|
||||
}
|
||||
|
||||
// If we have both RGB and named colors, then prefer rgb if term256 is supported
|
||||
rgb_color_t result;
|
||||
bool has_term256 = !! (output_get_color_support() & color_support_term256);
|
||||
if ((!first_rgb.is_none() && has_term256) || first_named.is_none())
|
||||
{
|
||||
result = first_rgb;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = first_named;
|
||||
}
|
||||
|
||||
rgb_color_t result = best_color(candidates, output_get_color_support());
|
||||
|
||||
if (result.is_none())
|
||||
result = rgb_color_t::normal();
|
||||
|
||||
|
|
3
output.h
3
output.h
|
@ -132,6 +132,9 @@ typedef unsigned int color_support_t;
|
|||
color_support_t output_get_color_support();
|
||||
void output_set_color_support(color_support_t support);
|
||||
|
||||
/** Given a list of rgb_color_t, pick the "best" one, as determined by the color support. Returns rgb_color_t::none() if empty */
|
||||
rgb_color_t best_color(const std::vector<rgb_color_t> &colors, color_support_t support);
|
||||
|
||||
/* Exported for builtin_set_color's usage only */
|
||||
void write_color(rgb_color_t color, bool is_fg);
|
||||
unsigned char index_for_color(rgb_color_t c);
|
||||
|
|
Loading…
Reference in New Issue
Block a user