mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Added color.h, color.cpp. Got term256 colors working.
This commit is contained in:
parent
d66700a0e4
commit
0a4c72e78b
11 changed files with 471 additions and 197 deletions
|
@ -105,6 +105,8 @@
|
|||
D0A0856513B3ACEE0099B651 /* xdgmimeint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimeint.cpp; sourceTree = "<group>"; };
|
||||
D0A0856613B3ACEE0099B651 /* xdgmimemagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimemagic.cpp; sourceTree = "<group>"; };
|
||||
D0A0856713B3ACEE0099B651 /* xdgmimeparent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xdgmimeparent.cpp; sourceTree = "<group>"; };
|
||||
D0B6B0FE14E88BA400AD6C10 /* color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cpp; sourceTree = "<group>"; };
|
||||
D0B6B0FF14E88BA400AD6C10 /* color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color.h; sourceTree = "<group>"; };
|
||||
D0C6FCC914CFA4B0004CE8AD /* autoload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = autoload.cpp; sourceTree = "<group>"; };
|
||||
D0C6FCCB14CFA4B7004CE8AD /* autoload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = autoload.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -122,6 +124,8 @@
|
|||
D0A0853313B3ACEE0099B651 /* builtin_set.cpp */,
|
||||
D0A0853413B3ACEE0099B651 /* builtin_ulimit.cpp */,
|
||||
D0A0853513B3ACEE0099B651 /* builtin.cpp */,
|
||||
D0B6B0FF14E88BA400AD6C10 /* color.h */,
|
||||
D0B6B0FE14E88BA400AD6C10 /* color.cpp */,
|
||||
D0A0850413B3ACEE0099B651 /* common.h */,
|
||||
D0A0853613B3ACEE0099B651 /* common.cpp */,
|
||||
D0A0850513B3ACEE0099B651 /* complete.h */,
|
||||
|
|
45
Makefile.in
45
Makefile.in
|
@ -96,7 +96,7 @@ FISH_OBJS := function.o builtin.o complete.o env.o exec.o expand.o \
|
|||
tokenizer.o wildcard.o wgetopt.o wutil.o input.o output.o intern.o \
|
||||
env_universal.o env_universal_common.o input_common.o event.o \
|
||||
signal.o io.o parse_util.o common.o screen.o path.o autoload.o \
|
||||
parser_keywords.o iothread.o builtin_scripts.o
|
||||
parser_keywords.o iothread.o builtin_scripts.o color.o
|
||||
|
||||
FISH_INDENT_OBJS := fish_indent.o print_help.o common.o \
|
||||
parser_keywords.o wutil.o tokenizer.o
|
||||
|
@ -115,7 +115,7 @@ BUILTIN_FILES := builtin_set.cpp builtin_commandline.cpp \
|
|||
|
||||
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
|
||||
input_common.o env_universal.o env_universal_common.o common.o \
|
||||
print_help.o iothread.o
|
||||
print_help.o iothread.o color.o
|
||||
|
||||
|
||||
#
|
||||
|
@ -922,8 +922,8 @@ autoload.o: builtin_scripts.h exec.h proc.h io.h
|
|||
builtin.o: config.h signal.h fallback.h util.h wutil.h builtin.h io.h
|
||||
builtin.o: common.h function.h event.h complete.h proc.h parser.h reader.h
|
||||
builtin.o: env.h wgetopt.h sanity.h tokenizer.h wildcard.h input_common.h
|
||||
builtin.o: input.h intern.h exec.h highlight.h parse_util.h autoload.h lru.h
|
||||
builtin.o: parser_keywords.h expand.h path.h builtin_set.cpp
|
||||
builtin.o: input.h intern.h exec.h highlight.h screen.h color.h parse_util.h
|
||||
builtin.o: autoload.h lru.h parser_keywords.h expand.h path.h builtin_set.cpp
|
||||
builtin.o: builtin_commandline.cpp builtin_complete.cpp builtin_ulimit.cpp
|
||||
builtin.o: builtin_jobs.cpp
|
||||
builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h builtin.h
|
||||
|
@ -941,6 +941,7 @@ builtin_set.o: common.h env.h expand.h wgetopt.h proc.h parser.h event.h
|
|||
builtin_set.o: function.h
|
||||
builtin_ulimit.o: config.h fallback.h signal.h util.h builtin.h io.h common.h
|
||||
builtin_ulimit.o: wgetopt.h
|
||||
color.o: color.h config.h common.h util.h
|
||||
common.o: config.h fallback.h signal.h util.h wutil.h common.h expand.h
|
||||
common.o: proc.h io.h wildcard.h parser.h event.h function.h complete.h
|
||||
common.o: util.cpp fallback.cpp
|
||||
|
@ -968,16 +969,16 @@ expand.o: tokenizer.h complete.h parse_util.h autoload.h lru.h
|
|||
fallback.o: config.h fallback.h signal.h util.h
|
||||
fish.o: config.h signal.h fallback.h util.h common.h reader.h io.h builtin.h
|
||||
fish.o: function.h event.h complete.h wutil.h env.h sanity.h proc.h parser.h
|
||||
fish.o: expand.h intern.h exec.h output.h history.h path.h
|
||||
fish.o: expand.h intern.h exec.h output.h screen.h color.h history.h path.h
|
||||
fish_indent.o: config.h fallback.h signal.h util.h common.h wutil.h
|
||||
fish_indent.o: tokenizer.h print_help.h parser_keywords.h
|
||||
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
|
||||
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
|
||||
fish_pager.o: print_help.h
|
||||
fish_pager.o: output.h screen.h color.h input_common.h env_universal.h
|
||||
fish_pager.o: env_universal_common.h print_help.h
|
||||
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
|
||||
fish_tests.o: reader.h builtin.h function.h event.h autoload.h lru.h
|
||||
fish_tests.o: complete.h wutil.h env.h expand.h parser.h tokenizer.h output.h
|
||||
fish_tests.o: exec.h path.h history.h
|
||||
fish_tests.o: screen.h color.h exec.h path.h history.h
|
||||
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
fishd.o: env_universal_common.h path.h print_help.h
|
||||
function.o: config.h signal.h wutil.h fallback.h util.h function.h common.h
|
||||
|
@ -985,14 +986,15 @@ function.o: event.h proc.h io.h parser.h intern.h reader.h parse_util.h
|
|||
function.o: autoload.h lru.h parser_keywords.h env.h expand.h
|
||||
function.o: builtin_scripts.h
|
||||
highlight.o: config.h signal.h fallback.h util.h wutil.h highlight.h env.h
|
||||
highlight.o: common.h tokenizer.h proc.h io.h parser.h event.h function.h
|
||||
highlight.o: parse_util.h autoload.h lru.h parser_keywords.h builtin.h
|
||||
highlight.o: expand.h sanity.h complete.h output.h wildcard.h path.h
|
||||
highlight.o: common.h screen.h color.h tokenizer.h proc.h io.h parser.h
|
||||
highlight.o: event.h function.h parse_util.h autoload.h lru.h
|
||||
highlight.o: parser_keywords.h builtin.h expand.h sanity.h complete.h
|
||||
highlight.o: output.h wildcard.h path.h
|
||||
history.o: config.h fallback.h signal.h util.h sanity.h wutil.h history.h
|
||||
history.o: common.h intern.h path.h autoload.h lru.h
|
||||
input.o: config.h signal.h fallback.h util.h wutil.h reader.h io.h proc.h
|
||||
input.o: common.h sanity.h input_common.h input.h parser.h event.h function.h
|
||||
input.o: env.h expand.h output.h intern.h
|
||||
input.o: config.h signal.h fallback.h util.h wutil.h reader.h io.h common.h
|
||||
input.o: proc.h sanity.h input_common.h input.h parser.h event.h function.h
|
||||
input.o: env.h expand.h output.h screen.h color.h intern.h
|
||||
input_common.o: config.h fallback.h signal.h util.h common.h wutil.h
|
||||
input_common.o: input_common.h env_universal.h env_universal_common.h
|
||||
input_common.o: iothread.h
|
||||
|
@ -1004,7 +1006,7 @@ kill.o: config.h signal.h fallback.h util.h wutil.h kill.h proc.h io.h
|
|||
kill.o: common.h sanity.h env.h exec.h path.h
|
||||
mimedb.o: config.h xdgmime.h fallback.h signal.h util.h print_help.h
|
||||
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
|
||||
output.o: output.h highlight.h env.h
|
||||
output.o: output.h screen.h color.h highlight.h env.h
|
||||
parse_util.o: config.h fallback.h signal.h util.h wutil.h common.h
|
||||
parse_util.o: tokenizer.h parse_util.h autoload.h lru.h expand.h intern.h
|
||||
parse_util.o: exec.h proc.h io.h env.h wildcard.h
|
||||
|
@ -1019,16 +1021,17 @@ path.o: config.h fallback.h signal.h util.h common.h env.h wutil.h path.h
|
|||
path.o: expand.h
|
||||
print_help.o: print_help.h
|
||||
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
|
||||
proc.o: reader.h sanity.h env.h parser.h event.h function.h output.h
|
||||
proc.o: reader.h sanity.h env.h parser.h event.h function.h output.h screen.h
|
||||
proc.o: color.h
|
||||
reader.o: config.h signal.h fallback.h util.h wutil.h highlight.h env.h
|
||||
reader.o: common.h reader.h io.h proc.h parser.h event.h function.h
|
||||
reader.o: complete.h history.h sanity.h exec.h expand.h tokenizer.h kill.h
|
||||
reader.o: input_common.h input.h output.h screen.h iothread.h intern.h
|
||||
reader.o: parse_util.h autoload.h lru.h
|
||||
reader.o: common.h screen.h color.h reader.h io.h proc.h parser.h event.h
|
||||
reader.o: function.h complete.h history.h sanity.h exec.h expand.h
|
||||
reader.o: tokenizer.h kill.h input_common.h input.h output.h iothread.h
|
||||
reader.o: intern.h parse_util.h autoload.h lru.h
|
||||
sanity.o: config.h signal.h fallback.h util.h common.h sanity.h proc.h io.h
|
||||
sanity.o: history.h reader.h kill.h wutil.h
|
||||
screen.o: config.h fallback.h signal.h common.h util.h wutil.h output.h
|
||||
screen.o: highlight.h env.h screen.h
|
||||
screen.o: screen.h color.h highlight.h env.h
|
||||
set_color.o: config.h fallback.h signal.h print_help.h
|
||||
signal.o: config.h signal.h common.h util.h fallback.h wutil.h event.h
|
||||
signal.o: reader.h io.h proc.h
|
||||
|
|
254
color.cpp
Normal file
254
color.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
/** \file color.cpp Color class implementation
|
||||
*/
|
||||
|
||||
#include "color.h"
|
||||
|
||||
|
||||
bool rgb_color_t::try_parse_special(const wcstring &special) {
|
||||
bzero(&data, sizeof data);
|
||||
const wchar_t *name = special.c_str();
|
||||
if (! wcscasecmp(name, L"normal")) {
|
||||
this->type = type_normal;
|
||||
} else if (! wcscasecmp(name, L"reset")) {
|
||||
this->type = type_reset;
|
||||
} else if (! wcscasecmp(name, L"ignore")) {
|
||||
this->type = type_ignore;
|
||||
} else {
|
||||
this->type = type_none;
|
||||
}
|
||||
return this->type != type_none;
|
||||
}
|
||||
|
||||
static int parse_hex_digit(wchar_t x) {
|
||||
switch (x) {
|
||||
case L'0': return 0x0;
|
||||
case L'1': return 0x1;
|
||||
case L'2': return 0x2;
|
||||
case L'3': return 0x3;
|
||||
case L'4': return 0x4;
|
||||
case L'5': return 0x5;
|
||||
case L'6': return 0x6;
|
||||
case L'7': return 0x7;
|
||||
case L'8': return 0x8;
|
||||
case L'9': return 0x9;
|
||||
case L'a':case L'A': return 0xA;
|
||||
case L'b':case L'B': return 0xB;
|
||||
case L'c':case L'C': return 0xC;
|
||||
case L'd':case L'D': return 0xD;
|
||||
case L'e':case L'E': return 0xE;
|
||||
case L'f':case L'F': return 0xF;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char convert_color(const unsigned char rgb[3], const uint32_t *colors, size_t color_count) {
|
||||
long r = rgb[0], g = rgb[1], b = rgb[2];
|
||||
unsigned long best_distance = (unsigned long)(-1);
|
||||
unsigned char best_index = (unsigned char)(-1);
|
||||
for (unsigned char idx = 0; idx < color_count; idx++) {
|
||||
uint32_t color = colors[idx];
|
||||
long test_r = (color >> 16) & 0xFF, test_g = (color >> 8) & 0xFF, test_b = (color >> 0) & 0xFF;
|
||||
unsigned long distance = 0;
|
||||
distance += (r - test_r) * (r - test_r);
|
||||
distance += (g - test_g) * (g - test_g);
|
||||
distance += (b - test_b) * (b - test_b);
|
||||
if (distance <= best_distance) {
|
||||
best_index = idx;
|
||||
best_distance = distance;
|
||||
}
|
||||
}
|
||||
return best_index;
|
||||
|
||||
}
|
||||
|
||||
bool rgb_color_t::try_parse_rgb(const wcstring &name) {
|
||||
bzero(&data, sizeof data);
|
||||
/* We support the following style of rgb formats (case insensitive):
|
||||
#FA3
|
||||
#F3A035
|
||||
FA3
|
||||
F3A035
|
||||
*/
|
||||
|
||||
size_t digit_idx = 0, len = name.size();
|
||||
|
||||
/* Skip any leading # */
|
||||
if (len > 0 && name.at(0) == L'#')
|
||||
digit_idx++;
|
||||
|
||||
bool success = false;
|
||||
size_t i;
|
||||
if (len - digit_idx == 3) {
|
||||
// type FA3
|
||||
for (i=0; i < 3; i++) {
|
||||
int val = parse_hex_digit(name.at(digit_idx++));
|
||||
if (val < 0) break;
|
||||
data.rgb[i] = val*16+val;
|
||||
}
|
||||
success = (i == 3);
|
||||
} else if (len - digit_idx == 6) {
|
||||
// type F3A035
|
||||
for (i=0; i < 3; i++) {
|
||||
int hi = parse_hex_digit(name.at(digit_idx++));
|
||||
int lo = parse_hex_digit(name.at(digit_idx++));
|
||||
if (lo < 0 || hi < 0) break;
|
||||
data.rgb[i] = hi*16+lo;
|
||||
}
|
||||
success = (i == 3);
|
||||
}
|
||||
if (success) {
|
||||
this->type = type_rgb;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
struct named_color_t {
|
||||
const wchar_t * name;
|
||||
unsigned char idx;
|
||||
unsigned char rgb[3];
|
||||
};
|
||||
|
||||
static const named_color_t named_colors[11] = {
|
||||
{L"black", 0, {0, 0, 0}},
|
||||
{L"red", 1, {0xFF, 0, 0}},
|
||||
{L"green", 2, {0, 0xFF, 0}},
|
||||
{L"brown", 3, {0x72, 0x50, 0}},
|
||||
{L"yellow", 3, {0xFF, 0xFF, 0}},
|
||||
{L"blue", 4, {0, 0, 0xFF}},
|
||||
{L"magenta", 5, {0xFF, 0, 0xFF}},
|
||||
{L"purple", 5, {0xFF, 0, 0xFF}},
|
||||
{L"cyan", 6, {0, 0xFF, 0xFF}},
|
||||
{L"white", 7, {0xFF, 0xFF, 0xFF}},
|
||||
{L"normal", 8, {0xFF, 0xFF, 0XFF}}
|
||||
};
|
||||
|
||||
bool rgb_color_t::try_parse_named(const wcstring &str) {
|
||||
bzero(&data, sizeof data);
|
||||
size_t max = sizeof named_colors / sizeof *named_colors;
|
||||
for (size_t idx=0; idx < max; idx++) {
|
||||
if (0 == wcscasecmp(str.c_str(), named_colors[idx].name)) {
|
||||
data.name_idx = named_colors[idx].idx;
|
||||
this->type = type_named;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
rgb_color_t::rgb_color_t(unsigned char t, unsigned char i) : type(t), data(), flags() {
|
||||
data.name_idx = i;
|
||||
}
|
||||
|
||||
rgb_color_t rgb_color_t::normal() { return rgb_color_t(type_normal); }
|
||||
rgb_color_t rgb_color_t::reset() { return rgb_color_t(type_reset); }
|
||||
rgb_color_t rgb_color_t::ignore() { return rgb_color_t(type_ignore); }
|
||||
rgb_color_t rgb_color_t::none() { return rgb_color_t(type_none); }
|
||||
rgb_color_t rgb_color_t::white() { return rgb_color_t(type_named, 7); }
|
||||
rgb_color_t rgb_color_t::black() { return rgb_color_t(type_named, 0); }
|
||||
|
||||
static unsigned char term8_color_for_rgb(const unsigned char rgb[3]) {
|
||||
const uint32_t kColors[] = {
|
||||
0x000000, //Black
|
||||
0xFF0000, //Red
|
||||
0x00FF00, //Green
|
||||
0x725000, //Brown
|
||||
0xFFFF00, //Yellow
|
||||
0x0000FF, //Blue
|
||||
0xFF00FF, //Magenta
|
||||
0xFF00FF, //Purple
|
||||
0x00FFFF, //Cyan
|
||||
0xFFFFFF, //White
|
||||
};
|
||||
return convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
|
||||
}
|
||||
|
||||
static unsigned char term256_color_for_rgb(const unsigned char rgb[3]) {
|
||||
const uint32_t kColors[240] = {
|
||||
0x000000, 0x00005f, 0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
|
||||
0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, 0x008787, 0x0087af,
|
||||
0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, 0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
|
||||
0x00d700, 0x00d75f, 0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
|
||||
0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
|
||||
0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, 0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
|
||||
0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
|
||||
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
|
||||
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, 0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
|
||||
0x870000, 0x87005f, 0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
|
||||
0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, 0x878787, 0x8787af,
|
||||
0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, 0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
|
||||
0x87d700, 0x87d75f, 0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
|
||||
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
|
||||
0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, 0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
|
||||
0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
|
||||
0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
|
||||
0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, 0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
|
||||
0xd70000, 0xd7005f, 0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
|
||||
0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, 0xd78787, 0xd787af,
|
||||
0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, 0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
|
||||
0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
|
||||
0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, 0xff0087, 0xff00af,
|
||||
0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, 0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
|
||||
0xff8700, 0xff875f, 0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
|
||||
0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
|
||||
0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, 0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
|
||||
0x080808, 0x121212, 0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
|
||||
0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
|
||||
0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, 0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
|
||||
};
|
||||
return 16 + convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
|
||||
}
|
||||
|
||||
unsigned char rgb_color_t::to_term256_index() const {
|
||||
assert(type == type_rgb);
|
||||
return term256_color_for_rgb(data.rgb);
|
||||
}
|
||||
|
||||
unsigned char rgb_color_t::to_name_index() const {
|
||||
if (type == type_named) {
|
||||
return data.name_idx;
|
||||
} else if (type == type_rgb) {
|
||||
return term8_color_for_rgb(data.rgb);
|
||||
} else {
|
||||
throw "Bad type for to_name_index";
|
||||
}
|
||||
}
|
||||
|
||||
rgb_color_t::rgb_color_t(const wcstring &str) {
|
||||
bool success = false;
|
||||
if (! success) success = try_parse_special(str);
|
||||
if (! success) success = try_parse_named(str);
|
||||
if (! success) success = try_parse_rgb(str);
|
||||
if (! success) {
|
||||
bzero(this->data.rgb, sizeof this->data.rgb);
|
||||
this->type = type_none;
|
||||
}
|
||||
if (! success) success = try_parse_special(str);
|
||||
if (this->try_parse_special(str)) {
|
||||
/* Nothing */
|
||||
} else if (this->try_parse_named(str)) {
|
||||
|
||||
} else if (this->try_parse_rgb(str)) {
|
||||
this->type = type_rgb;
|
||||
} else {
|
||||
bzero(this->data.rgb, sizeof this->data.rgb);
|
||||
this->type = type_none;
|
||||
}
|
||||
}
|
||||
|
||||
wcstring rgb_color_t::description() const {
|
||||
switch (type) {
|
||||
case type_none:
|
||||
return L"none";
|
||||
case type_named:
|
||||
return format_string(L"named(%d)", (int)data.name_idx);
|
||||
case type_rgb:
|
||||
return format_string(L"rgb(0x%02x%02x%02x)", data.rgb[0], data.rgb[1], data.rgb[2]);
|
||||
case type_reset:
|
||||
return L"reset";
|
||||
case type_ignore:
|
||||
return L"ignore";
|
||||
default:
|
||||
abort();
|
||||
return L"";
|
||||
}
|
||||
}
|
120
color.h
Normal file
120
color.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/** \file color.h Color class.
|
||||
*/
|
||||
#ifndef FISH_COLOR_H
|
||||
#define FISH_COLOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/* A type that represents a color */
|
||||
class rgb_color_t {
|
||||
enum {
|
||||
type_none,
|
||||
type_named,
|
||||
type_rgb,
|
||||
type_normal,
|
||||
type_reset,
|
||||
type_ignore
|
||||
};
|
||||
unsigned char type;
|
||||
union {
|
||||
unsigned char name_idx; //0-10
|
||||
unsigned char rgb[3];
|
||||
} data;
|
||||
unsigned flags;
|
||||
|
||||
/** Try parsing a special color name like "normal" */
|
||||
bool try_parse_special(const wcstring &str);
|
||||
|
||||
/** Try parsing an rgb color like "#F0A030" */
|
||||
bool try_parse_rgb(const wcstring &str);
|
||||
|
||||
/** Try parsing an explicit color name like "magenta" */
|
||||
bool try_parse_named(const wcstring &str);
|
||||
|
||||
/** Private constructor */
|
||||
explicit rgb_color_t(unsigned char t, unsigned char i=0);
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor of type none */
|
||||
explicit rgb_color_t() : type(type_none), data(), flags() {}
|
||||
|
||||
/** Parse a color from a string */
|
||||
explicit rgb_color_t(const wcstring &str);
|
||||
|
||||
/** Returns white */
|
||||
static rgb_color_t white();
|
||||
|
||||
/** Returns black */
|
||||
static rgb_color_t black();
|
||||
|
||||
/** Returns the reset special color */
|
||||
static rgb_color_t reset();
|
||||
|
||||
/** Returns the normal special color */
|
||||
static rgb_color_t normal();
|
||||
|
||||
/** Returns the ignore special color */
|
||||
static rgb_color_t ignore();
|
||||
|
||||
/** Returns the none special color */
|
||||
static rgb_color_t none();
|
||||
|
||||
/** Returns whether the color is the ignore special color */
|
||||
bool is_ignore(void) const { return type == type_ignore; }
|
||||
|
||||
/** Returns whether the color is the normal special color */
|
||||
bool is_normal(void) const { return type == type_normal; }
|
||||
|
||||
/** Returns whether the color is the reset special color */
|
||||
bool is_reset(void) const { return type == type_reset; }
|
||||
|
||||
/** Returns whether the color is the none special color */
|
||||
bool is_none(void) const { return type == type_none; }
|
||||
|
||||
/** Returns whether the color is a named color (like "magenta") */
|
||||
bool is_named(void) const { return type == type_named; }
|
||||
|
||||
/** Returns whether the color is specified via RGB components */
|
||||
bool is_rgb(void) const { return type == type_rgb; }
|
||||
|
||||
/** Returns whether the color is special, that is, not rgb or named */
|
||||
bool is_special(void) const { return type != type_named && type != type_rgb; }
|
||||
|
||||
/** Returns a description of the color */
|
||||
wcstring description() const;
|
||||
|
||||
/** Returns the name index for the given color. Requires that the color be named or RGB. */
|
||||
unsigned char to_name_index() const;
|
||||
|
||||
/** Returns the term256 index for the given color. Requires that the color be named or RGB. */
|
||||
unsigned char to_term256_index() const;
|
||||
|
||||
/** Returns whether the color is bold */
|
||||
bool is_bold() const { return flags & 1; }
|
||||
|
||||
/** Set whether the color is bold */
|
||||
void set_bold(bool x) { if (x) flags |= 1; else flags &= ~1; }
|
||||
|
||||
/** Returns whether the color is underlined */
|
||||
bool is_underline() const { return flags & 2; }
|
||||
|
||||
/** Set whether the color is underlined */
|
||||
void set_underline(bool x) { if (x) flags |= 2; else flags &= ~2; }
|
||||
|
||||
/** Compare two colors for equality */
|
||||
bool operator==(const rgb_color_t &other) const {
|
||||
return type == other.type && ! memcmp(&data, &other.data, sizeof data);
|
||||
}
|
||||
|
||||
/** Compare two colors for inequality */
|
||||
bool operator!=(const rgb_color_t &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -670,12 +670,28 @@ static void test_path()
|
|||
wcstring path = L"//foo//////bar/";
|
||||
wcstring canon = path;
|
||||
path_make_canonical(canon);
|
||||
if( canon != L"/foo/bar" ) )
|
||||
if( canon != L"/foo/bar" )
|
||||
{
|
||||
err( L"Bug in canonical PATH code" );
|
||||
}
|
||||
}
|
||||
|
||||
/** Testing colors */
|
||||
static void test_colors()
|
||||
{
|
||||
say(L"Testing colors");
|
||||
assert(rgb_color_t(L"#FF00A0").is_rgb());
|
||||
assert(rgb_color_t(L"FF00A0").is_rgb());
|
||||
assert(rgb_color_t(L"#F30").is_rgb());
|
||||
assert(rgb_color_t(L"F30").is_rgb());
|
||||
assert(rgb_color_t(L"f30").is_rgb());
|
||||
assert(rgb_color_t(L"#FF30a5").is_rgb());
|
||||
assert(rgb_color_t(L"3f30").is_none());
|
||||
assert(rgb_color_t(L"##f30").is_none());
|
||||
assert(rgb_color_t(L"magenta").is_named());
|
||||
assert(rgb_color_t(L"MaGeNTa").is_named());
|
||||
assert(rgb_color_t(L"mooganta").is_none());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -808,6 +824,7 @@ int main( int argc, char **argv )
|
|||
test_lru();
|
||||
test_expand();
|
||||
test_path();
|
||||
test_colors();
|
||||
test_history();
|
||||
|
||||
say( L"Encountered %d errors in low-level tests", err_count );
|
||||
|
|
|
@ -201,7 +201,7 @@ rgb_color_t highlight_get_rgb_color( int highlight, bool is_background )
|
|||
const wcstring val2 = val2_wstr.missing() ? L"" : val2_wstr.c_str();
|
||||
|
||||
rgb_color_t result2 = parse_color( val2, is_background );
|
||||
if( result == rgb_color_t::normal() )
|
||||
if( result.is_normal() )
|
||||
result = result2;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "env.h"
|
||||
#include "util.h"
|
||||
#include "screen.h"
|
||||
#include "color.h"
|
||||
|
||||
/**
|
||||
Internal value representing highlighting of normal text
|
||||
|
|
67
output.cpp
67
output.cpp
|
@ -55,6 +55,7 @@
|
|||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "highlight.h"
|
||||
#include "env.h"
|
||||
|
||||
/**
|
||||
Number of color names in the col array
|
||||
|
@ -126,8 +127,30 @@ int (*output_get_writer())(char)
|
|||
return out;
|
||||
}
|
||||
|
||||
bool allow_term256(void)
|
||||
{
|
||||
//consider using t_Co
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
const wchar_t *t = output_get_term();
|
||||
return t && wcsstr(t, L"256color");
|
||||
}
|
||||
|
||||
static unsigned char index_for_color(rgb_color_t c) {
|
||||
if (c.is_named() || ! allow_term256()) {
|
||||
return c.to_name_index();
|
||||
} else {
|
||||
return c.to_term256_index();
|
||||
}
|
||||
}
|
||||
|
||||
void set_color(rgb_color_t c, rgb_color_t c2)
|
||||
{
|
||||
|
||||
#if 0
|
||||
wcstring tmp = c.description();
|
||||
wcstring tmp2 = c2.description();
|
||||
printf("set_color %ls : %ls\n", tmp.c_str(), tmp2.c_str());
|
||||
#endif
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
|
||||
const rgb_color_t normal = rgb_color_t::normal();
|
||||
|
@ -198,9 +221,9 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
was_underline=0;
|
||||
}
|
||||
|
||||
if( last_color2 != rgb_color_t::normal() &&
|
||||
last_color2 != rgb_color_t::reset() &&
|
||||
last_color2 != rgb_color_t::ignore() )
|
||||
if( ! last_color2.is_normal() &&
|
||||
! last_color2.is_reset() &&
|
||||
! last_color2.is_ignore() )
|
||||
{
|
||||
/*
|
||||
Background was set
|
||||
|
@ -208,15 +231,14 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
last_bg_set=1;
|
||||
}
|
||||
|
||||
if( c2 != rgb_color_t::normal() &&
|
||||
c2 != rgb_color_t::ignore() )
|
||||
if( ! c2.is_normal() &&
|
||||
! c2.is_ignore())
|
||||
{
|
||||
/*
|
||||
Background is set
|
||||
*/
|
||||
bg_set=1;
|
||||
// PCA color fix
|
||||
//c = (c2==FISH_COLOR_WHITE)?FISH_COLOR_BLACK:FISH_COLOR_WHITE;
|
||||
c = (c2==rgb_color_t::white())?rgb_color_t::black():rgb_color_t::white();
|
||||
}
|
||||
|
||||
if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0))
|
||||
|
@ -253,7 +275,7 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
|
||||
if( last_color != c )
|
||||
{
|
||||
if( c==rgb_color_t::normal() )
|
||||
if( c.is_normal() )
|
||||
{
|
||||
if( fg )
|
||||
{
|
||||
|
@ -265,11 +287,11 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
was_bold=0;
|
||||
was_underline=0;
|
||||
}
|
||||
else if( c.is_named() )
|
||||
else if( ! c.is_special() )
|
||||
{
|
||||
if( fg )
|
||||
{
|
||||
writembs( tparm( fg, c.name_index() ) );
|
||||
writembs( tparm(fg, index_for_color(c)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +300,7 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
|
||||
if( last_color2 != c2 )
|
||||
{
|
||||
if( c2 == rgb_color_t::normal() )
|
||||
if( c2.is_normal() )
|
||||
{
|
||||
if( bg )
|
||||
{
|
||||
|
@ -286,12 +308,9 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
}
|
||||
|
||||
writembs( exit_attribute_mode );
|
||||
if( ( last_color != rgb_color_t::normal() ) && fg )
|
||||
if( ! last_color.is_normal() && fg )
|
||||
{
|
||||
if( fg )
|
||||
{
|
||||
writembs( tparm( fg, last_color.name_index() ) );
|
||||
}
|
||||
writembs( tparm( fg, index_for_color(last_color) ));
|
||||
}
|
||||
|
||||
|
||||
|
@ -299,11 +318,11 @@ void set_color(rgb_color_t c, rgb_color_t c2)
|
|||
was_underline=0;
|
||||
last_color2 = c2;
|
||||
}
|
||||
else if ( c2.is_named() && c2 != normal)
|
||||
else if ( ! c2.is_special() )
|
||||
{
|
||||
if( bg )
|
||||
{
|
||||
writembs( tparm( bg, c2.name_index() ) );
|
||||
writembs( tparm( bg, index_for_color(c2) ));
|
||||
}
|
||||
last_color2 = c2;
|
||||
}
|
||||
|
@ -794,7 +813,6 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
|
|||
if (string_prefixes_string(prefix, next)) {
|
||||
color_name = wcstring(next, prefix.size());
|
||||
}
|
||||
|
||||
} else {
|
||||
if (next == L"--bold" || next == L"-o")
|
||||
is_bold = true;
|
||||
|
@ -805,9 +823,18 @@ rgb_color_t parse_color( const wcstring &val, bool is_background ) {
|
|||
}
|
||||
|
||||
if (! color_name.empty()) {
|
||||
rgb_color_t::parse(color_name, result);
|
||||
result = rgb_color_t(color_name);
|
||||
if (result.is_none()) {
|
||||
result = rgb_color_t::normal();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
wcstring desc = result.description();
|
||||
printf("Parsed %ls from %ls (%s)\n", desc.c_str(), val.c_str(), is_background ? "background" : "foreground");
|
||||
#endif
|
||||
if (result.is_none())
|
||||
result = rgb_color_t::normal();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
1
output.h
1
output.h
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <wchar.h>
|
||||
#include "screen.h"
|
||||
#include "color.h"
|
||||
|
||||
/**
|
||||
Constants for various colors as used by the set_color function.
|
||||
|
|
154
screen.h
154
screen.h
|
@ -14,160 +14,6 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
/* A type that represents a color */
|
||||
class rgb_color_t {
|
||||
enum {
|
||||
type_none,
|
||||
type_named,
|
||||
type_rgb,
|
||||
type_reset,
|
||||
type_ignore
|
||||
};
|
||||
unsigned char type;
|
||||
union {
|
||||
unsigned char name_idx; //0-10
|
||||
unsigned char rgb[3];
|
||||
} data;
|
||||
unsigned flags;
|
||||
|
||||
/* Try parsing an explicit color name like "magenta" */
|
||||
bool try_parse_named(const wcstring &str) {
|
||||
bzero(&data, sizeof data);
|
||||
const struct {const wchar_t * name; unsigned char idx;} names[] = {
|
||||
{L"black", 0},
|
||||
{L"red", 1},
|
||||
{L"green", 2},
|
||||
{L"brown", 3},
|
||||
{L"yellow", 3},
|
||||
{L"blue", 4},
|
||||
{L"magenta", 5},
|
||||
{L"purple", 5},
|
||||
{L"cyan", 6},
|
||||
{L"white", 7},
|
||||
{L"normal", 8}
|
||||
};
|
||||
size_t max = sizeof names / sizeof *names;
|
||||
for (size_t idx=0; idx < max; idx++) {
|
||||
if (0 == wcscasecmp(str.c_str(), names[idx].name)) {
|
||||
data.name_idx = names[idx].idx;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int parse_hex_digit(wchar_t x) {
|
||||
switch (x) {
|
||||
case L'0': return 0x0;
|
||||
case L'1': return 0x1;
|
||||
case L'2': return 0x2;
|
||||
case L'3': return 0x3;
|
||||
case L'4': return 0x4;
|
||||
case L'5': return 0x5;
|
||||
case L'6': return 0x6;
|
||||
case L'7': return 0x7;
|
||||
case L'8': return 0x8;
|
||||
case L'9': return 0x9;
|
||||
case L'a':case L'A': return 0xA;
|
||||
case L'b':case L'B': return 0xB;
|
||||
case L'c':case L'C': return 0xC;
|
||||
case L'd':case L'D': return 0xD;
|
||||
case L'e':case L'E': return 0xE;
|
||||
case L'f':case L'F': return 0xF;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool try_parse_rgb(const wcstring &name) {
|
||||
bzero(&data, sizeof data);
|
||||
/* We support the following style of rgb formats (case insensitive):
|
||||
#FA3
|
||||
#F3A035
|
||||
*/
|
||||
size_t i;
|
||||
if (name.size() == 4 && name.at(0) == L'#') {
|
||||
// type #FA3
|
||||
for (i=0; i < 3; i++) {
|
||||
int val = parse_hex_digit(name.at(i));
|
||||
if (val < 0) break;
|
||||
data.rgb[i] = val*16+val;
|
||||
}
|
||||
return i == 3;
|
||||
} else if (name.size() == 7 && name.at(0) == L'#') {
|
||||
// type #F3A035
|
||||
for (i=0; i < 6;) {
|
||||
int hi = parse_hex_digit(name.at(i++));
|
||||
int lo = parse_hex_digit(name.at(i++));
|
||||
if (lo < 0 || hi < 0) break;
|
||||
data.rgb[i] = hi*16+lo;
|
||||
}
|
||||
return i == 6;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static rgb_color_t named_color(unsigned char which)
|
||||
{
|
||||
rgb_color_t result(type_named);
|
||||
result.data.name_idx = which;
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit rgb_color_t(unsigned char t = type_none) : type(t), data(), flags() {}
|
||||
|
||||
static rgb_color_t normal() { return named_color(8); }
|
||||
static rgb_color_t white() { return named_color(7); }
|
||||
static rgb_color_t black() { return named_color(0); }
|
||||
static rgb_color_t reset() { return rgb_color_t(type_reset); }
|
||||
static rgb_color_t ignore() { return rgb_color_t(type_ignore); }
|
||||
|
||||
rgb_color_t(unsigned char r, unsigned char g, unsigned char b)
|
||||
{
|
||||
type = type_rgb;
|
||||
data.rgb[0] = r;
|
||||
data.rgb[1] = g;
|
||||
data.rgb[2] = b;
|
||||
}
|
||||
|
||||
static bool parse(const wcstring &str, rgb_color_t &color) {
|
||||
if (color.try_parse_named(str)) {
|
||||
color.type = type_named;
|
||||
} else if (color.try_parse_rgb(str)) {
|
||||
color.type = type_rgb;
|
||||
} else {
|
||||
bzero(color.data.rgb, sizeof color.data.rgb);
|
||||
color.type = type_none;
|
||||
}
|
||||
return color.type != type_none;
|
||||
}
|
||||
|
||||
unsigned char name_index() const {
|
||||
assert(type == type_named);
|
||||
return data.name_idx;
|
||||
}
|
||||
|
||||
bool is_bold() const { return flags & 1; }
|
||||
void set_bold(bool x) { if (x) flags |= 1; else flags &= ~1; }
|
||||
bool is_underline() const { return flags & 2; }
|
||||
void set_underline(bool x) { if (x) flags |= 2; else flags &= ~2; }
|
||||
|
||||
bool is_reset(void) const { return type == type_reset; }
|
||||
bool is_ignore(void) const { return type == type_ignore; }
|
||||
bool is_named(void) const { return type == type_named; }
|
||||
|
||||
bool operator==(const rgb_color_t &other) const {
|
||||
return type == other.type && ! memcmp(&data, &other.data, sizeof data);
|
||||
}
|
||||
|
||||
bool operator!=(const rgb_color_t &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct line_entry_t
|
||||
{
|
||||
wchar_t text;
|
||||
|
|
|
@ -104,6 +104,7 @@ function __fish_config_interactive -d "Initializations that should be performed
|
|||
set_default fish_color_escape cyan
|
||||
set_default fish_color_operator cyan
|
||||
set_default fish_color_quote brown
|
||||
set_default fish_color_autosuggestion 555
|
||||
set_default fish_color_valid_path --underline
|
||||
|
||||
set_default fish_color_cwd green
|
||||
|
|
Loading…
Reference in a new issue