Merge floam/colorfix #3260

This commit is contained in:
Aaron Gyes 2016-09-11 03:14:08 -07:00 committed by GitHub
commit f7c6426b21
10 changed files with 225 additions and 244 deletions

View file

@ -2,36 +2,35 @@
\subsection set_color-synopsis Synopsis
\fish{synopsis}
set_color [OPTIONS] [COLOR]
set_color [OPTIONS] VALUE
\endfish
\subsection set_color-description Description
`set_color` changes the foreground and/or background color of the terminal. `COLOR` is one of `black`, `red`, `green`, `brown`, `yellow`, `blue`, `magenta`, `purple`, `cyan`, `brred`, `brgreen`, `brbrown`, `bryellow`, `brblue`, `brmagenta`, `brpurple`, `brcyan`, `white`. The `br`, bright, forms are most useful as background colors. The special color `normal` resets the background and foreground to whatever is normal for your terminal.
`set_color` is used to control the color and styling of text in the terminal. `VALUE` corresponds to a reserved color name such as *red* or a RGB color value given as 3 or 6 hexadecimal digits. The *br*-, as in 'bright', forms are full-brightness variants of the 8 standard-brightness colors on many terminals. *brblack* has higher brightness than *black* - towards gray. A special keyword *normal* resets text formatting to terminal defaults.
You can also specify an RGB value with three or six hex digits, such as A0FF33 or f2f. `fish` will choose the closest supported color. A three digit value is equivalent to specifying each digit twice; e.g., `#2BC` is the same as `#22BBCC`. Hex RGB values can be in lower or uppercase, optionally prefixed with the pound-sign character. Depending on the capabilities of your terminal the actual color may be approximated by the closest known matching color in the [ANSI X3.64](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) color palette.
Valid colors include:
- *black*, *red*, *green*, *yellow*, *blue*, *magenta*, *cyan*, *white*
- *brblack*, *brred*, *brgreen*, *bryellow*, *brblue*, *brmagenta*, *brcyan*, *brwhite*
An RGB value with three or six hex digits, such as A0FF33 or f2f can be used. `fish` will choose the closest supported color. A three digit value is equivalent to specifying each digit twice; e.g., `set_color 2BC` is the same as `set_color 22BBCC`. Hexadecimal RGB values can be in lower or uppercase. Depending on the capabilities of your terminal (and the level of support `set_color` has for it) the actual color may be approximated by a nearby matching reserved color name or `set_color` may not have an effect on color. A second color may be given as a desired fallback color. e.g. `set_color 124212` *brblue* will instruct set_color to use *brblue* if a terminal is not capable of the exact shade of grey desired. This is very useful when an 8 or 16 color terminal might otherwise not use a color.
The following options are available:
- `-b`, `--background` `COLOR` sets the background color.
- `-c`, `--print-colors` prints a list of all valid color names.
- `-o`, `--bold` sets bold or extra bright mode.
- `-b`, `--background` *COLOR* sets the background color.
- `-c`, `--print-colors` prints a list of the 16 named colors.
- `-o`, `--bold` sets bold mode.
- `-u`, `--underline` sets underlined mode.
Calling `set_color normal` will set the terminal background and foreground colors to the defaults for the terminal.
Using the *normal* keyword will reset foreground, background, and all formatting back to default.
Some terminals use the `--bold` escape sequence to switch to a brighter color set rather than bolding the characters. This only applies to the foreground color. You should probably use the `br` color name variants listed above for both the foreground and background "bright" colors rather than use this option. The only use for this option is on a black&white terminal (e.g., a DEC VT220) to select foreground black text that is bolder than the normal text.
\subsection set_color-notes Notes
Not all terminal emulators support all these features.
Note 1: Setting either color to "normal" will reset both background and foreground colors to whatever is the default for the terminal.
Note 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.
Note 3: `set_color` works by printing sequences of characters to its stdout. If you use it in a command substitution or pipe, these characters will also be captured (and can then later be printed to the terminal). To avoid printing these sequences (and hence not add color) if not connected to a terminal, use `isatty stdout`.
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.
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
@ -44,8 +43,10 @@ set_color normal; echo "Normal is nice" # Resets the background too
\subsection set_color-detection Terminal Capability Detection
Fish uses a heuristic to decide if your terminal supports the 256 color palette (as opposed to the more limited 16 color palette of older terminals). If you've done the equivalent of `set fish_term256 1` that will be true. If the $TERM value contains "256color" (e.g., "xterm-256color") that will be true. If your $TERM value is "xterm" and $TERM_PROGRAM is not set to "Apple_Terminal" that will be true. If your terminal supports the full 256 color palette (which is pretty much every color terminal emulator written in the past decade) you should ensure one of the aforementioned conditions is true.
Fish uses a heuristic to decide if a terminal supports the 256-color palette as opposed to the more limited 16 color palette of older terminals. Support can be forced on by setting `fish_term256` to *1*. If `$TERM` contains "256color" (e.g., *xterm-256color*), 256-color support is enabled. If `$TERM` contains *xterm*, 256 color support is enabled (except for MacOS: `$TERM_PROGRAM` and `$TERM_PROGRAM_VERSION` are used to detect Terminal.app from MacOS 10.6; support is disabled here it because it is known that it reports `xterm` and only supports 16 colors.
Many terminals support 24-bit (i.e., true-color) color escape sequences. This includes modern xterms, Gnome Terminal, KDE Konsole, and iTerm2. Fish currently does some limited attempts to detect whether a given `$TERM` supports 24-bit colors. You can explicitly enable that support via `set fish_term24bit 1`. If you do so fish will not map your RGB color values to the closest known matching color in the ANSI X3.64 color palette.
If terminfo reports 256 color support for a terminal, support will always be enabled. To debug color palette problems, `tput colors` may be useful to see the number of colors in terminfo for a terminal. Fish launched as `fish -d2` will include diagnostic messages that indicate the color support mode in use.
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 use the [ANSI X3.64](https://en.wikipedia.org/wiki/ANSI_escape_code) escape sequences if the terminfo definition says less than 256 colors are supported; otherwise it will use the terminfo definition.
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.

View file

@ -1,8 +1,6 @@
# Main file for fish command completions. This file contains various
# common helper functions for the command completions. All actual
# completions are located in the completions subdirectory.
#
#
# Set default field separators
#
@ -15,6 +13,8 @@ function __fish_default_command_not_found_handler
echo "fish: Unknown command '$argv'" >&2
end
set -g version $FISH_VERSION
if status --is-interactive
# The user has seemingly explicitly launched an old fish with too-new scripts installed.
if not contains "string" (builtin -n)

View file

@ -22,42 +22,54 @@ function __fish_config_interactive -d "Initializations that should be performed
set userdatadir $XDG_DATA_HOME
end
if not set -q fish_greeting
set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell' ))
if not set -q __fish_init_2_3_0
set -l line2 \n(printf (_ 'Type %shelp%s for instructions on how to use fish %s') (set_color green) (set_color normal))
else
set -l line2 ''
end
set -U fish_greeting $line1$line2
end
#
# If we are starting up for the first time, set various defaults
#
if not set -q __fish_init_1_50_0
if not set -q fish_greeting
set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell') )
set -l line2 (printf (_ 'Type %shelp%s for instructions on how to use fish') (set_color green) (set_color normal))
set -U fish_greeting $line1\n$line2
#
if not set -q __fish_init_2_39_8 # bump this to 2_4_0 when rolling release if anything changes after 9/10/2016
set -g colors_backup "$HOME/fish_previous_colors-(date).txt"
echo Backing up uvars to:\n (set_color --underline)$colors_backup(set_color normal)
set -U >>$colors_backup
for option in (set -Un | string match "fish*color_*")
set -eU $option
end
set -U __fish_init_1_50_0
echo \"Normalized\" colors on upgrade.
# Regular syntax highlighting colors
set -q fish_color_normal
or set -U fish_color_normal normal
set -q fish_color_command
or set -U fish_color_command brblue
or set -U fish_color_command --bold
set -q fish_color_param
or set -U fish_color_param cyan
set -q fish_color_redirection
or set -U fish_color_redirection normal
or set -U fish_color_redirection brblue
set -q fish_color_comment
or set -U fish_color_comment red
set -q fish_color_error
or set -U fish_color_error red --bold
or set -U fish_color_error brred
set -q fish_color_escape
or set -U fish_color_escape cyan
or set -U fish_color_escape bryellow
set -q fish_color_operator
or set -U fish_color_operator cyan
or set -U fish_color_operator bryellow
set -q fish_color_end
or set -U fish_color_end green
or set -U fish_color_end brmagenta
set -q fish_color_quote
or set -U fish_color_quote brown
or set -U fish_color_quote yellow
set -q fish_color_autosuggestion
or set -U fish_color_autosuggestion brgrey
or set -U fish_color_autosuggestion 555 brblack
set -q fish_color_user
or set -U fish_color_user green
or set -U fish_color_user brgreen
set -q fish_color_host
or set -U fish_color_host normal
@ -71,31 +83,34 @@ function __fish_config_interactive -d "Initializations that should be performed
# Background color for matching quotes and parenthesis
set -q fish_color_match
or set -U fish_color_match cyan
or set -U fish_color_match --background=blue
# Background color for search matches
set -q fish_color_search_match
or set -U fish_color_search_match --background=purple
or set -U fish_color_search_match bryellow --background=brgrey
# Background color for selections
set -q fish_color_selection
or set -U fish_color_selection --background=purple
or set -U fish_color_selection white --bold --background=brgrey
# Pager colors
set -q fish_pager_color_prefix
or set -U fish_pager_color_prefix cyan
set -q fish_pager_color_completion
or set -U fish_pager_color_completion normal
or set -U fish_pager_color_prefix white --bold --underline
#set -q fish_pager_color_completion
#or set -U fish_pager_color_completion
set -q fish_pager_color_description
or set -U fish_pager_color_description brgrey
or set -U fish_pager_color_description B3A06D yellow
set -q fish_pager_color_progress
or set -U fish_pager_color_progress cyan
or set -U fish_pager_color_progress brwhite --background=cyan
#
# Directory history colors
#
set -q fish_color_history_current
or set -U fish_color_history_current cyan
or set -U fish_color_history_current --bold
set -U __fish_init_2_39_8
end
#
@ -144,11 +159,13 @@ function __fish_config_interactive -d "Initializations that should be performed
# Completions for SysV startup scripts. These aren't bound to any
# specific command, so they can't be autoloaded.
#
complete -x -p "/etc/init.d/*" -a start --description 'Start service'
complete -x -p "/etc/init.d/*" -a stop --description 'Stop service'
complete -x -p "/etc/init.d/*" -a status --description 'Print service status'
complete -x -p "/etc/init.d/*" -a restart --description 'Stop and then start service'
complete -x -p "/etc/init.d/*" -a reload --description 'Reload service configuration'
if test -d /etc/init.d
complete -x -p "/etc/init.d/*" -a start --description 'Start service'
complete -x -p "/etc/init.d/*" -a stop --description 'Stop service'
complete -x -p "/etc/init.d/*" -a status --description 'Print service status'
complete -x -p "/etc/init.d/*" -a restart --description 'Stop and then start service'
complete -x -p "/etc/init.d/*" -a reload --description 'Reload service configuration'
end
# Make sure some key bindings are set
if not set -q fish_key_bindings
@ -208,15 +225,14 @@ function __fish_config_interactive -d "Initializations that should be performed
commandline -f repaint
end
# Notify vte-based terminals when $PWD changes (issue #906)
# Notify terminals when $PWD changes (issue #906)
if test "$VTE_VERSION" -ge 3405 -o "$TERM_PROGRAM" = "Apple_Terminal"
function __update_vte_cwd --on-variable PWD --description 'Notify VTE of change to $PWD'
function __update_cwd_osc --on-variable PWD --description 'Notify VTE of change to $PWD'
status --is-command-substitution
and return
printf '\033]7;file://%s%s\a' (hostname) (pwd | __fish_urlencode)
printf \e\]7\;file://\%s\%s\a (hostname) (pwd | __fish_urlencode)
end
__update_vte_cwd # Run once because we might have already inherited a PWD from an old tab
__update_cwd_osc # Run once because we might have already inherited a PWD from an old tab
end
### Command-not-found handlers
@ -269,69 +285,4 @@ function __fish_config_interactive -d "Initializations that should be performed
end
end
end
if test $TERM = "linux" # A linux in-kernel VT with 8 colors and 256/512 glyphs
# In a VT we have
# black (invisible)
# red
# green
# yellow
# blue
# magenta
# cyan
# white
# Pretty much just set at random
set -g fish_color_normal normal
set -g fish_color_command yellow
set -g fish_color_param cyan
set -g fish_color_redirection normal
set -g fish_color_comment red
set -g fish_color_error red
set -g fish_color_escape cyan
set -g fish_color_operator cyan
set -g fish_color_quote blue
set -g fish_color_autosuggestion yellow
set -g fish_color_valid_path
set -g fish_color_cwd green
set -g fish_color_cwd_root red
set -g fish_color_match cyan
set -g fish_color_history_current cyan
set -g fish_color_search_match cyan
set -g fish_color_selection blue
set -g fish_color_end yellow
set -g fish_color_host normal
set -g fish_color_status red
set -g fish_color_user green
set -g fish_pager_color_prefix cyan
set -g fish_pager_color_completion normal
set -g fish_pager_color_description yellow
set -g fish_pager_color_progress cyan
# Don't allow setting color other than what linux offers (see #2001)
functions -e set_color
function set_color
set -l term_colors black red green yellow blue magenta cyan white normal
for a in $argv
if not contains -- $a $term_colors
switch $a
# Also allow options
case "-*"
continue
case "*"
echo "Color not valid in TERM = linux: $a"
return 1
end
end
end
builtin set_color $argv
return $status
end
# Set fish_prompt to a VT-friendly version
# without color or unicode
function fish_prompt
fish_fallback_prompt
end
end
end

View file

@ -65,23 +65,27 @@ def escape_fish_cmd(text):
named_colors = {
'black' : '000000',
'red' : 'FF0000',
'green' : '00FF00',
'red' : '800000',
'green' : '008000',
'brown' : '725000',
'yellow' : 'FFFF00',
'blue' : '0000FF',
'magenta' : 'FF00FF',
'purple' : 'FF00FF',
'cyan' : '00FFFF',
'grey' : 'E5E5E5',
'yellow' : '808000',
'blue' : '000080',
'magenta' : '800080',
'purple' : '800080',
'cyan' : '008080',
'grey' : 'e5e5e5',
'brgrey' : '555555',
'brbrown' : 'FFFF55',
'bryellow' : 'FFFF55',
'brblue' : '5555FF',
'brmagenta' : 'FF55FF',
'brpurple' : 'FF55FF',
'brcyan' : '55FFFF',
'white' : 'FFFFFF'
'white' : 'c0c0c0',
'brblack' : '808080',
'brred' : 'ff0000',
'brgreen' : '00ff00',
'brbrown' : 'ffff00',
'bryellow' : 'ffff00',
'brblue' : '0000ff',
'brmagenta' : 'ff00ff',
'brpurple' : 'ff00ff',
'brcyan' : '00ffff',
'brwhite' : 'ffffff'
}
bindings_blacklist = set(["self-insert", "'begin;end'"])

View file

@ -179,7 +179,12 @@ int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
write_color(rgb_color_t::black(), true /* is_fg */);
writembs(tparm(exit_attribute_mode));
} else {
write_color(fg, true /* is_fg */);
if (!write_color(fg, true /* is_fg */)) {
// We need to do *something* or the lack of any output messes up
// when the cartesian product here would make "foo" disappear:
// $ echo (set_color foo)bar
set_color(rgb_color_t::reset(), rgb_color_t::none());
}
}
}

View file

@ -149,29 +149,32 @@ struct named_color_t {
const wchar_t *name;
unsigned char idx;
unsigned char rgb[3];
bool hidden;
};
static const named_color_t named_colors[] = {
{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"grey", 7, {0xE5, 0xE5, 0xE5}},
{L"brgrey", 8, {0x55, 0x55, 0x55}},
{L"brred", 9, {0xFF, 0x55, 0x55}},
{L"brgreen", 10, {0x55, 0xFF, 0x55}},
{L"brbrown", 11, {0xFF, 0xFF, 0x55}},
{L"bryellow", 11, {0xFF, 0xFF, 0x55}},
{L"brblue", 12, {0x55, 0x55, 0xFF}},
{L"brmagenta", 13, {0xFF, 0x55, 0xFF}},
{L"brpurple", 13, {0xFF, 0x55, 0xFF}},
{L"brcyan", 14, {0x55, 0xFF, 0xFF}},
{L"white", 15, {0xFF, 0xFF, 0xFF}},
{L"black", 0, {0, 0, 0}, false},
{L"red", 1, {0x80, 0, 0}, false},
{L"green", 2, {0, 0x80, 0}, false},
{L"brown", 3, {0x72, 0x50, 0}, true},
{L"yellow", 3, {0x80, 0x80, 0}, false},
{L"blue", 4, {0, 0, 0x80}, false},
{L"magenta", 5, {0x80, 0, 0x80}, false},
{L"purple", 5, {0x80, 0, 0x80}, true},
{L"cyan", 6, {0, 0x80, 0x80}, false},
{L"white", 7, {0xC0, 0xC0, 0xC0}, false},
{L"grey", 7, {0xe5, 0xe5, 0xe5}, true},
{L"brblack", 8, {0x80, 0x80, 0x80}, false},
{L"brgrey", 8, {0055, 0x55, 0x55}, true},
{L"brred", 9, {0xFF, 0x00, 0x00}, false},
{L"brgreen", 10, {0x00, 0xFF, 0x00}, false},
{L"brbrown", 11, {0xFF, 0xFF, 0x00}, true},
{L"bryellow", 11, {0xFF, 0xFF, 0x00}, false},
{L"brblue", 12, {0x00, 0, 0xFF}, false},
{L"brmagenta", 13, {0xFF, 0, 0xFF}, false},
{L"brpurple", 13, {0xFF, 0, 0xFF}, true},
{L"brcyan", 14, {0x00, 0xFF, 0xFF}, false},
{L"brwhite", 15, {0xFF, 0xFF, 0xFF}, false},
};
wcstring_list_t rgb_color_t::named_color_names(void) {
@ -179,7 +182,9 @@ wcstring_list_t rgb_color_t::named_color_names(void) {
wcstring_list_t result;
result.reserve(1 + count);
for (size_t i = 0; i < count; i++) {
result.push_back(named_colors[i].name);
if (named_colors[i].hidden == false) {
result.push_back(named_colors[i].name);
}
}
// "normal" isn't really a color and does not have a color palette index or
// RGB value. Therefore, it does not appear in the named_colors table.
@ -227,16 +232,24 @@ 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]) {
static unsigned char term16_color_for_rgb(const unsigned char rgb[3]) {
const uint32_t kColors[] = {
0x000000, // Black
0xFF0000, // Red
0x00FF00, // Green
0xFFFF00, // Yellow
0x0000FF, // Blue
0xFF00FF, // Magenta
0x00FFFF, // Cyan
0xFFFFFF, // White
0x800000, // Red
0x008000, // Green
0x808000, // Yellow
0x000080, // Blue
0x800080, // Magenta
0x008080, // Cyan
0xc0c0c0, // White
0x808080, // Bright Black
0xFF0000, // Bright Red
0x00FF00, // Bright Green
0xFFFF00, // Bright Yellow
0x0000FF, // Bright Blue
0xFF00FF, // Bright Magenta
0x00FFFF, // Bright Cyan
0xFFFFFF // Bright White
};
return convert_color(rgb, kColors, sizeof kColors / sizeof *kColors);
}
@ -284,9 +297,10 @@ color24_t rgb_color_t::to_color24() const {
}
unsigned char rgb_color_t::to_name_index() const {
// XXX this should look for the nearest color
assert(type == type_named || type == type_rgb);
if (type == type_named) return data.name_idx;
if (type == type_rgb) return term8_color_for_rgb(data.color.rgb);
if (type == type_rgb) return term16_color_for_rgb(data.color.rgb);
return (unsigned char)-1; // this is an error
}

View file

@ -37,15 +37,19 @@ static int (*out)(char c) = writeb_internal;
/// Whether term256 and term24bit are supported.
static color_support_t color_support = 0;
/// Set the function used for writing in move_cursor, writespace and set_color and all other output
/// functions in this library. By default, the write call is used to give completely unbuffered
/// output to stdout.
void output_set_writer(int (*writer)(char)) {
CHECK(writer, );
out = writer;
}
/// Return the current output writer.
int (*output_get_writer())(char) { return out; }
// Returns true if we think the term256 support is "native" as opposed to forced.
static bool term256_support_is_native(void) { return max_colors >= 256; }
/// Returns true if we think tparm can handle outputting a color index
static bool term_supports_color_natively(unsigned int c) { return max_colors >= c; }
color_support_t output_get_color_support(void) { return color_support; }
@ -59,15 +63,18 @@ unsigned char index_for_color(rgb_color_t c) {
}
static bool write_color_escape(char *todo, unsigned char idx, bool is_fg) {
bool result = false;
if (idx < 16 || term256_support_is_native()) {
if (term_supports_color_natively(idx)) {
// Use tparm to emit color escape.
writembs(tparm(todo, idx));
result = true;
return true;
} else {
// We are attempting to bypass the term here. Generate the ANSI escape sequence ourself.
char buff[128] = "";
snprintf(buff, sizeof buff, "\x1b[%d;5;%dm", is_fg ? 38 : 48, idx);
char buff[16] = "";
if (idx < 16) {
snprintf(buff, sizeof buff, "\x1b[%dm", ((idx > 7) ? 82 : 30) + idx + !is_fg * 10);
} else {
snprintf(buff, sizeof buff, "\x1b[%d;5;%dm", is_fg ? 38 : 48, idx);
}
int (*writer)(char) = output_get_writer();
if (writer) {
@ -76,9 +83,8 @@ static bool write_color_escape(char *todo, unsigned char idx, bool is_fg) {
}
}
result = true;
return true;
}
return result;
}
static bool write_foreground_color(unsigned char idx) {
@ -99,12 +105,13 @@ static bool write_background_color(unsigned char idx) {
return false;
}
void write_color(rgb_color_t color, bool is_fg) {
// Exported for builtin_set_color's usage only.
bool write_color(rgb_color_t color, bool is_fg) {
bool supports_term24bit = !!(output_get_color_support() & color_support_term24bit);
if (!supports_term24bit || !color.is_rgb()) {
// Indexed or non-24 bit color.
unsigned char idx = index_for_color(color);
(is_fg ? write_foreground_color : write_background_color)(idx);
return (is_fg ? write_foreground_color : write_background_color)(idx);
} else {
// 24 bit! No tparm here, just ANSI escape sequences.
// Foreground: ^[38;2;<r>;<g>;<b>m
@ -120,8 +127,30 @@ void write_color(rgb_color_t color, bool is_fg) {
}
}
}
return true;
}
/// Sets the fg and bg color. May be called as often as you like, since if the new color is the same
/// as the previous, nothing will be written. Negative values for set_color will also be ignored.
/// Since the terminfo string this function emits can potentially cause the screen to flicker, the
/// function takes care to write as little as possible.
///
/// Possible values for color are any form the FISH_COLOR_* enum and FISH_COLOR_RESET.
/// FISH_COLOR_RESET will perform an exit_attribute_mode, even if set_color thinks it is already in
/// FISH_COLOR_NORMAL mode.
///
/// In order to set the color to normal, three terminfo strings may have to be written.
///
/// - First a string to set the color, such as set_a_foreground. This is needed because otherwise
/// the previous strings colors might be removed as well.
///
/// - After that we write the exit_attribute_mode string to reset all color attributes.
///
/// - Lastly we may need to write set_a_background or set_a_foreground to set the other half of the
/// color pair to what it should be.
///
/// \param c Foreground color.
/// \param c2 Background color.
void set_color(rgb_color_t c, rgb_color_t c2) {
#if 0
wcstring tmp = c.description();
@ -260,11 +289,15 @@ static int writeb_internal(char c) { // cppcheck
return 0;
}
/// This is for writing process notification messages. Has to write to stdout, so clr_eol and such
/// functions will work correctly. Not an issue since this function is only used in interactive mode
/// anyway.
int writeb(tputs_arg_t b) {
out(b);
return 0;
}
/// Write a wide character using the output method specified using output_set_writer().
int writech(wint_t ch) {
char buff[MB_LEN_MAX + 1];
size_t len;
@ -294,6 +327,7 @@ int writech(wint_t ch) {
return 0;
}
/// Write a wide character string to FD 1.
void writestr(const wchar_t *str) {
CHECK(str, );
@ -329,6 +363,8 @@ void writestr(const wchar_t *str) {
if (buffer != static_buffer) delete[] buffer;
}
/// 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> &candidates, color_support_t support) {
if (candidates.empty()) {
return rgb_color_t::none();
@ -358,7 +394,8 @@ rgb_color_t best_color(const std::vector<rgb_color_t> &candidates, color_support
return result;
}
// This code should be refactored to enable sharing with builtin_set_color.
/// Return the internal color code representing the specified color.
/// XXX 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;
int is_underline = 0;
@ -408,6 +445,7 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) {
return result;
}
/// Write specified multibyte string.
void writembs_check(char *mbs, const char *mbs_name, const char *file, long line) {
if (mbs != NULL) {
tputs(mbs, 1, &writeb);

View file

@ -14,65 +14,33 @@
/// Constants for various colors as used by the set_color function.
enum {
FISH_COLOR_BLACK,
FISH_COLOR_RED,
FISH_COLOR_GREEN,
FISH_COLOR_YELLOW,
FISH_COLOR_BLUE,
FISH_COLOR_MAGENTA,
FISH_COLOR_CYAN,
FISH_COLOR_WHITE,
FISH_COLOR_NORMAL, // the default fg color of the terminal
FISH_COLOR_RESET
FISH_COLOR_BLACK, // 0
FISH_COLOR_RED, // 1
FISH_COLOR_GREEN, // 2
FISH_COLOR_YELLOW, // 3
FISH_COLOR_BLUE, // 4
FISH_COLOR_MAGENTA, // 5
FISH_COLOR_CYAN, // 6
FISH_COLOR_WHITE, // 7
FISH_COLOR_NORMAL, // 8 terminal default
FISH_COLOR_RESET // 9
};
/// Sets the fg and bg color. May be called as often as you like, since if the new color is the same
/// as the previous, nothing will be written. Negative values for set_color will also be ignored.
/// Since the terminfo string this function emits can potentially cause the screen to flicker, the
/// function takes care to write as little as possible.
///
/// Possible values for color are any form the FISH_COLOR_* enum and FISH_COLOR_RESET.
/// FISH_COLOR_RESET will perform an exit_attribute_mode, even if set_color thinks it is already in
/// FISH_COLOR_NORMAL mode.
///
/// In order to set the color to normal, three terminfo strings may have to be written.
///
/// - First a string to set the color, such as set_a_foreground. This is needed because otherwise
/// the previous strings colors might be removed as well.
///
/// - After that we write the exit_attribute_mode string to reset all color attributes.
///
/// - Lastly we may need to write set_a_background or set_a_foreground to set the other half of the
/// color pair to what it should be.
///
/// \param c Foreground color.
/// \param c2 Background color.
void set_color(rgb_color_t c, rgb_color_t c2);
/// Write specified multibyte string.
void writembs_check(char *mbs, const char *mbs_name, const char *file, long line);
#define writembs(mbs) writembs_check((mbs), #mbs, __FILE__, __LINE__)
/// Write a wide character using the output method specified using output_set_writer().
int writech(wint_t ch);
/// Write a wide character string to FD 1.
void writestr(const wchar_t *str);
/// Return the internal color code representing the specified color.
rgb_color_t parse_color(const wcstring &val, bool is_background);
/// This is for writing process notification messages. Has to write to stdout, so clr_eol and such
/// functions will work correctly. Not an issue since this function is only used in interactive mode
/// anyway.
int writeb(tputs_arg_t b);
/// Set the function used for writing in move_cursor, writespace and set_color and all other output
/// functions in this library. By default, the write call is used to give completely unbuffered
/// output to stdout.
void output_set_writer(int (*writer)(char));
/// Return the current output writer.
int (*output_get_writer())(char);
/// Sets what colors are supported.
@ -81,12 +49,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);
bool write_color(rgb_color_t color, bool is_fg);
unsigned char index_for_color(rgb_color_t c);
#endif

View file

@ -130,9 +130,10 @@ line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, s
{
written += print_max(L" ", packed_color, 1, false, &line_data);
}
print_max(L"(", packed_color, 1, false, &line_data);
// hack - this just works around the issue
print_max(L"(", highlight_spec_pager_completion | highlight_make_background(bg_color), 1, false, &line_data);
print_max(c->desc, packed_color, desc_width, false, &line_data);
print_max(L")", packed_color, 1, false, &line_data);
print_max(L")", highlight_spec_pager_completion | highlight_make_background(bg_color), 1, false, &line_data);
} else {
while (written < width) {
written += print_max(L" ", 0, 1, false, &line_data);

View file

@ -205,8 +205,8 @@ size_t escape_code_length(const wchar_t *code) {
bool found = false;
if (cur_term != NULL) {
// Detect these terminfo color escapes with parameter value 0..7, all of which don't move
// the cursor.
// Detect these terminfo color escapes with parameter value 0..16, all of which don't move
// the cursor.
char *const esc[] = {
set_a_foreground, set_a_background, set_foreground, set_background,
};
@ -232,12 +232,15 @@ size_t escape_code_length(const wchar_t *code) {
enter_superscript_mode, exit_superscript_mode, enter_blink_mode,
enter_italics_mode, exit_italics_mode, enter_reverse_mode,
enter_shadow_mode, exit_shadow_mode, enter_standout_mode,
exit_standout_mode, enter_secure_mode};
exit_standout_mode, enter_secure_mode, enter_dim_mode,
enter_blink_mode, enter_protected_mode, enter_alt_charset_mode,
exit_alt_charset_mode};
for (size_t p = 0; p < sizeof esc2 / sizeof *esc2 && !found; p++) {
if (!esc2[p]) continue;
// Test both padded and unpadded version, just to be safe. Most versions of tparm don't
// actually seem to do anything these days.
size_t len = maxi(try_sequence(tparm(esc2[p]), code), try_sequence(esc2[p], code));
if (len) {
resulting_length = len;
@ -601,9 +604,8 @@ static bool perform_any_impending_soft_wrap(screen_t *scr, int x, int y) {
/// Make sure we don't soft wrap.
static void invalidate_soft_wrap(screen_t *scr) { scr->soft_wrap_location = INVALID_LOCATION; }
// Various code for testing term behavior.
#if 0
/// Various code for testing term behavior.
static bool test_stuff(screen_t *scr)
{
data_buffer_t output;
@ -1186,18 +1188,18 @@ void s_reset(screen_t *s, screen_reset_mode_t mode) {
// omitted_newline_char in common.cpp.
int non_space_width = fish_wcwidth(omitted_newline_char);
if (screen_width >= non_space_width) {
bool has_256_colors = output_get_color_support() & color_support_term256;
if (has_256_colors) {
// Draw the string in term256 gray.
abandon_line_string.append(L"\x1b[38;5;245m");
} else {
// Draw in "bright black" (gray).
abandon_line_string.append(
L"\x1b[0m" // bright
L"\x1b[30;1m"); // black
if (enter_dim_mode) {
// Use dim if they have it, so the color will be based on their actual normal color and the background of the termianl.
abandon_line_string.append(str2wcstring(tparm(enter_dim_mode)));
}
else if (set_a_foreground && max_colors >= 8) {
// Draw the string in gray.
abandon_line_string.append(str2wcstring(tparm(set_a_foreground, 8)));
}
abandon_line_string.push_back(omitted_newline_char);
abandon_line_string.append(L"\x1b[0m"); // normal text ANSI escape sequence
if (exit_attribute_mode)
abandon_line_string.append(str2wcstring(tparm(exit_attribute_mode))); // normal text ANSI escape sequence
abandon_line_string.append(screen_width - non_space_width, L' ');
}
abandon_line_string.push_back(L'\r');