Added color.h, color.cpp. Got term256 colors working.

This commit is contained in:
ridiculousfish 2012-02-12 18:05:59 -08:00
parent d66700a0e4
commit 0a4c72e78b
11 changed files with 471 additions and 197 deletions

View file

@ -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 */,

View file

@ -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
View 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
View 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

View file

@ -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 );

View file

@ -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
{

View file

@ -10,6 +10,7 @@
#include "env.h"
#include "util.h"
#include "screen.h"
#include "color.h"
/**
Internal value representing highlighting of normal text

View file

@ -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;
}

View file

@ -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
View file

@ -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;

View file

@ -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