Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add italics and dim modifier to set_color #3650

Merged
merged 5 commits into from
Dec 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions doc_src/set_color.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ The following options are available:
- `-b`, `--background` *COLOR* sets the background color.
- `-c`, `--print-colors` prints a list of the 16 named colors.
- `-o`, `--bold` sets bold mode.
- `-d`, `--dim` sets dim mode.
- `-i`, `--italics` sets italics mode.
- `-r`, `--reverse` sets reverse mode.
- `-u`, `--underline` sets underlined mode.

Using the *normal* keyword will reset foreground, background, and all formatting back to default.
Using the *normal* keyword will reset foreground, background, and all formatting back to default.

\subsection set_color-notes Notes

1. Using the *normal* keyword will reset both background and foreground colors to whatever is the default for the terminal.
2. Setting the background color only affects subsequently written characters. Fish provides no way to set the background color for the entire terminal window. Configuring the window background color (and other attributes such as its opacity) has to be done using whatever mechanisms the terminal provides.
3. Some terminals use the `--bold` escape sequence to switch to a brighter color set rather than increasing the weight of text.
3. Some terminals use the `--bold` escape sequence to switch to a brighter color set rather than increasing the weight of text.
4. `set_color` works by printing sequences of characters to *stdout*. If used in command substitution or a pipe, these characters will also be captured. This may or may not be desirable. Checking the exit code of `isatty stdout` before using `set_color` can be useful to decide not to colorize output in a script.

\subsection set_color-example Examples
Expand All @@ -50,3 +53,5 @@ If terminfo reports 256 color support for a terminal, support will always be ena
Many terminals support 24-bit (i.e., true-color) color escape sequences. This includes modern xterm, Gnome Terminal, Konsole, and iTerm2. Fish attempts to detect such terminals through various means in `config.fish` You can explicitly force that support via `set fish_term24bit 1`.

The `set_color` command uses the terminfo database to look up how to change terminal colors on whatever terminal is in use. Some systems have old and incomplete terminfo databases, and may lack color information for terminals that support it. Fish will assume that all terminals can use the [ANSI X3.64](https://en.wikipedia.org/wiki/ANSI_escape_code) escape sequences if the terminfo definition indicates a color below 16 is not supported.

Support for italics, dim, reverse, and other modes is not guaranteed in all terminal emulators. Fish attempts to determine if the terminal supports these modes even if the terminfo database may not be up-to-date.
35 changes: 32 additions & 3 deletions src/builtin_set_color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,14 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
{L"help", no_argument, 0, 'h'},
{L"bold", no_argument, 0, 'o'},
{L"underline", no_argument, 0, 'u'},
{L"italics", no_argument, 0, 'i'},
{L"dim", no_argument, 0, 'd'},
{L"reverse", no_argument, 0, 'r'},
{L"version", no_argument, 0, 'v'},
{L"print-colors", no_argument, 0, 'c'},
{0, 0, 0, 0}};

const wchar_t *short_options = L"b:hvocu";
const wchar_t *short_options = L"b:hvoidrcu";

int argc = builtin_count_args(argv);

Expand All @@ -71,7 +74,7 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
}

const wchar_t *bgcolor = NULL;
bool bold = false, underline = false;
bool bold = false, underline = false, italics = false, dim = false, reverse = false;
int errret;

// Parse options to obtain the requested operation and the modifiers.
Expand Down Expand Up @@ -99,6 +102,18 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
bold = true;
break;
}
case 'i': {
italics = true;
break;
}
case 'd': {
dim = true;
break;
}
case 'r': {
reverse = true;
break;
}
case 'u': {
underline = true;
break;
Expand Down Expand Up @@ -128,7 +143,7 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
fgcolors.push_back(fg);
}

if (fgcolors.empty() && bgcolor == NULL && !bold && !underline) {
if (fgcolors.empty() && bgcolor == NULL && !bold && !underline && !italics && !dim && !reverse) {
streams.err.append_format(_(L"%ls: Expected an argument\n"), argv[0]);
return STATUS_BUILTIN_ERROR;
}
Expand Down Expand Up @@ -171,6 +186,20 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
writembs(enter_underline_mode);
}

if (italics && enter_italics_mode) {
writembs(enter_italics_mode);
}

if (dim && enter_dim_mode) {
writembs(enter_dim_mode);
}

if (reverse && enter_reverse_mode) {
writembs(enter_reverse_mode);
} else if (reverse && enter_standout_mode) {
writembs(enter_standout_mode);
}

if (bgcolor != NULL && bg.is_normal()) {
write_color(rgb_color_t::black(), false /* not is_fg */);
writembs(tparm(exit_attribute_mode));
Expand Down
37 changes: 35 additions & 2 deletions src/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class rgb_color_t {
unsigned char type : 4;

// Flags
enum { flag_bold = 1 << 0, flag_underline = 1 << 1 };
unsigned char flags : 4;
enum { flag_bold = 1 << 0, flag_underline = 1 << 1, flag_italics = 1 << 2, flag_dim = 1 << 3, flag_reverse = 1 << 4 };
unsigned char flags : 5;

union {
unsigned char name_idx; // 0-10
Expand Down Expand Up @@ -117,6 +117,39 @@ class rgb_color_t {
flags &= ~flag_underline;
}

/// Returns whether the color is italics.
bool is_italics() const { return static_cast<bool>(flags & flag_italics); }

/// Set whether the color is italics.
void set_italics(bool x) {
if (x)
flags |= flag_italics;
else
flags &= ~flag_italics;
}

/// Returns whether the color is dim.
bool is_dim() const { return static_cast<bool>(flags & flag_dim); }

/// Set whether the color is dim.
void set_dim(bool x) {
if (x)
flags |= flag_dim;
else
flags &= ~flag_dim;
}

/// Returns whether the color is reverse.
bool is_reverse() const { return static_cast<bool>(flags & flag_reverse); }

/// Set whether the color is reverse.
void set_reverse(bool x) {
if (x)
flags |= flag_reverse;
else
flags &= ~flag_reverse;
}

/// Compare two colors for equality.
bool operator==(const rgb_color_t &other) const {
return type == other.type && !memcmp(&data, &other.data, sizeof data);
Expand Down
3 changes: 3 additions & 0 deletions src/highlight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background)
else {
if (result2.is_bold()) result.set_bold(true);
if (result2.is_underline()) result.set_underline(true);
if (result2.is_italics()) result.set_italics(true);
if (result2.is_dim()) result.set_dim(true);
if (result2.is_reverse()) result.set_reverse(true);
}
}

Expand Down
94 changes: 93 additions & 1 deletion src/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,15 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
static rgb_color_t last_color2 = rgb_color_t::normal();
static bool was_bold = false;
static bool was_underline = false;
static bool was_italics = false;
static bool was_dim = false;
static bool was_reverse = false;
bool bg_set = false, last_bg_set = false;
bool is_bold = false;
bool is_underline = false;
bool is_italics = false;
bool is_dim = false;
bool is_reverse = false;

// Test if we have at least basic support for setting fonts, colors and related bits - otherwise
// just give up...
Expand All @@ -189,10 +195,22 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
is_underline |= c.is_underline();
is_underline |= c2.is_underline();

is_italics |= c.is_italics();
is_italics |= c2.is_italics();

is_dim |= c.is_dim();
is_dim |= c2.is_dim();

is_reverse |= c.is_reverse();
is_reverse |= c2.is_reverse();

if (c.is_reset() || c2.is_reset()) {
c = c2 = normal;
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
// If we exit attibute mode, we must first set a color, or previously coloured text might
// lose it's color. Terminals are weird...
write_foreground_color(0);
Expand All @@ -207,6 +225,33 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
last_color2 = normal;
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
}

if (was_dim && !is_dim ) {
// Only way to exit dim mode is a reset of all attributes.
writembs(exit_attribute_mode);
last_color = normal;
last_color2 = normal;
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
}

if (was_reverse && !is_reverse ) {
// Only way to exit reverse mode is a reset of all attributes.
writembs(exit_attribute_mode);
last_color = normal;
last_color2 = normal;
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
}

if (!last_color2.is_normal() && !last_color2.is_reset()) {
Expand All @@ -231,6 +276,9 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
writembs(exit_attribute_mode);
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
// We don't know if exit_attribute_mode resets colors, so we set it to something known.
if (write_foreground_color(0)) {
last_color = rgb_color_t::black();
Expand All @@ -246,6 +294,9 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
last_color2 = rgb_color_t::normal();
was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
} else if (!c.is_special()) {
write_color(c, true /* foreground */);
}
Expand All @@ -264,14 +315,17 @@ void set_color(rgb_color_t c, rgb_color_t c2) {

was_bold = false;
was_underline = false;
was_italics = false;
was_dim = false;
was_reverse = false;
last_color2 = c2;
} else if (!c2.is_special()) {
write_color(c2, false /* not foreground */);
last_color2 = c2;
}
}

// Lastly, we set bold mode and underline mode correctly.
// Lastly, we set bold, underline, italics, dim, and reverse modes correctly.
if (is_bold && !was_bold && enter_bold_mode && strlen(enter_bold_mode) > 0 && !bg_set) {
writembs(tparm(enter_bold_mode));
was_bold = is_bold;
Expand All @@ -285,6 +339,32 @@ void set_color(rgb_color_t c, rgb_color_t c2) {
writembs(enter_underline_mode);
}
was_underline = is_underline;

if (was_italics && !is_italics && enter_italics_mode && strlen(enter_italics_mode) > 0) {
writembs(exit_italics_mode);
was_italics = is_italics;
}

if (!was_italics && is_italics && enter_italics_mode && strlen(enter_italics_mode) > 0) {
writembs(enter_italics_mode);
was_italics = is_italics;
}

if (is_dim && !was_dim && enter_dim_mode && strlen(enter_dim_mode) > 0) {
writembs(enter_dim_mode);
was_dim = is_dim;
}

if (is_reverse && !was_reverse) {
// Some terms do not have a reverse mode set, so standout mode is a fallback.
if (enter_reverse_mode && strlen(enter_reverse_mode) > 0) {
writembs(enter_reverse_mode);
was_reverse = is_reverse;
} else if (enter_standout_mode && strlen(enter_standout_mode) > 0) {
writembs(enter_standout_mode);
was_reverse = is_reverse;
}
}
}

/// Default output method, simply calls write() on stdout.
Expand Down Expand Up @@ -400,6 +480,9 @@ rgb_color_t best_color(const std::vector<rgb_color_t> &candidates, color_support
rgb_color_t parse_color(const wcstring &val, bool is_background) {
int is_bold = 0;
int is_underline = 0;
int is_italics = 0;
int is_dim = 0;
int is_reverse = 0;

std::vector<rgb_color_t> candidates;

Expand All @@ -420,6 +503,12 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) {
is_bold = true;
else if (next == L"--underline" || next == L"-u")
is_underline = true;
else if (next == L"--italics" || next == L"-i")
is_italics = true;
else if (next == L"--dim" || next == L"-d")
is_dim = true;
else if (next == L"--reverse" || next == L"-r")
is_reverse = true;
else
color_name = next;
}
Expand All @@ -437,6 +526,9 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) {

result.set_bold(is_bold);
result.set_underline(is_underline);
result.set_italics(is_italics);
result.set_dim(is_dim);
result.set_reverse(is_reverse);

#if 0
wcstring desc = result.description();
Expand Down