diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in index aab92b398..71c74ccb7 100644 --- a/doc_src/index.hdr.in +++ b/doc_src/index.hdr.in @@ -1026,15 +1026,31 @@ The following variables are available to change the highlighting colors in fish: Additionally, the following variables are available to change the highlighting in the completion pager: +- `fish_pager_color_progress`, the color of the progress bar at the bottom left corner + +- `fish_pager_color_background`, the background color of a line + - `fish_pager_color_prefix`, the color of the prefix string, i.e. the string that is to be completed - `fish_pager_color_completion`, the color of the completion itself - `fish_pager_color_description`, the color of the completion description -- `fish_pager_color_progress`, the color of the progress bar at the bottom left corner +- `fish_pager_color_secondary_background`, `fish_pager_color_background` of every second unselected completion. Defaults to `fish_pager_color_background` -- `fish_pager_color_secondary`, the background color of the every second completion +- `fish_pager_color_secondary_ prefix`, `fish_pager_color_prefix` of every second unselected completion. Defaults to `fish_pager_color_prefix` + +- `fish_pager_color_secondary_completion`, `fish_pager_color_completion` of every second unselected completion. Defaults to `fish_pager_color_completion` + +- `fish_pager_color_secondary_description`, `fish_pager_color_description` of every second unselected completion. Defaults to `fish_pager_color_description` + +- `fish_pager_color_selected_background`, `fish_pager_color_background` of the selected completion. Defaults to `fish_color_search_match` + +- `fish_pager_color_selected_ prefix`, `fish_pager_color_prefix` of the selected completion. Defaults to `fish_pager_color_prefix` + +- `fish_pager_color_selected_completion`, `fish_pager_color_completion` of the selected completion. Defaults to `fish_pager_color_completion` + +- `fish_pager_color_selected_description`, `fish_pager_color_description` of the selected completion. Defaults to `fish_pager_color_description` Example: diff --git a/src/highlight.cpp b/src/highlight.cpp index 920f66b4c..cf20ba5d8 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -42,28 +42,69 @@ namespace g = grammar; /// Number of elements in the highlight_var array. #define VAR_COUNT (sizeof(highlight_var) / sizeof(wchar_t *)) static const wchar_t *const highlight_var[] = { - [highlight_spec_normal] = L"fish_color_normal", - [highlight_spec_error] = L"fish_color_error", - [highlight_spec_command] = L"fish_color_command", - [highlight_spec_statement_terminator] = L"fish_color_end", - [highlight_spec_param] = L"fish_color_param", - [highlight_spec_comment] = L"fish_color_comment", - [highlight_spec_match] = L"fish_color_match", - [highlight_spec_search_match] = L"fish_color_search_match", - [highlight_spec_operator] = L"fish_color_operator", - [highlight_spec_escape] = L"fish_color_escape", - [highlight_spec_quote] = L"fish_color_quote", - [highlight_spec_redirection] = L"fish_color_redirection", - [highlight_spec_autosuggestion] = L"fish_color_autosuggestion", - [highlight_spec_selection] = L"fish_color_selection", - [highlight_spec_pager_prefix] = L"fish_pager_color_prefix", - [highlight_spec_pager_completion] = L"fish_pager_color_completion", - [highlight_spec_pager_description] = L"fish_pager_color_description", - [highlight_spec_pager_progress] = L"fish_pager_color_progress", - [highlight_spec_pager_secondary] = L"fish_pager_color_secondary", + [highlight_spec_normal] = L"fish_color_normal", + [highlight_spec_error] = L"fish_color_error", + [highlight_spec_command] = L"fish_color_command", + [highlight_spec_statement_terminator] = L"fish_color_end", + [highlight_spec_param] = L"fish_color_param", + [highlight_spec_comment] = L"fish_color_comment", + [highlight_spec_match] = L"fish_color_match", + [highlight_spec_search_match] = L"fish_color_search_match", + [highlight_spec_operator] = L"fish_color_operator", + [highlight_spec_escape] = L"fish_color_escape", + [highlight_spec_quote] = L"fish_color_quote", + [highlight_spec_redirection] = L"fish_color_redirection", + [highlight_spec_autosuggestion] = L"fish_color_autosuggestion", + [highlight_spec_selection] = L"fish_color_selection", + [highlight_spec_pager_progress] = L"fish_pager_color_progress", + [highlight_spec_pager_background] = L"fish_pager_color_background", + [highlight_spec_pager_prefix] = L"fish_pager_color_prefix", + [highlight_spec_pager_completion] = L"fish_pager_color_completion", + [highlight_spec_pager_description] = L"fish_pager_color_description", + [highlight_spec_pager_secondary_background] = L"fish_pager_color_secondary_background", + [highlight_spec_pager_secondary_prefix] = L"fish_pager_color_secondary_prefix", + [highlight_spec_pager_secondary_completion] = L"fish_pager_color_secondary_completion", + [highlight_spec_pager_secondary_description] = L"fish_pager_color_secondary_description", + [highlight_spec_pager_selected_background] = L"fish_pager_color_selected_background", + [highlight_spec_pager_selected_prefix] = L"fish_pager_color_selected_prefix", + [highlight_spec_pager_selected_completion] = L"fish_pager_color_selected_completion", + [highlight_spec_pager_selected_description] = L"fish_pager_color_selected_description", }; static_assert(VAR_COUNT == HIGHLIGHT_SPEC_MAX, "Every color spec has a corresponding env var"); +// Table used to fetch fallback highlights in case the specified one +// wasn't set. +static const highlight_spec_t fallbacks[] = { + [highlight_spec_normal] = highlight_spec_normal, + [highlight_spec_error] = highlight_spec_normal, + [highlight_spec_command] = highlight_spec_normal, + [highlight_spec_statement_terminator] = highlight_spec_normal, + [highlight_spec_param] = highlight_spec_normal, + [highlight_spec_comment] = highlight_spec_normal, + [highlight_spec_match] = highlight_spec_normal, + [highlight_spec_search_match] = highlight_spec_normal, + [highlight_spec_operator] = highlight_spec_normal, + [highlight_spec_escape] = highlight_spec_normal, + [highlight_spec_quote] = highlight_spec_normal, + [highlight_spec_redirection] = highlight_spec_normal, + [highlight_spec_autosuggestion] = highlight_spec_normal, + [highlight_spec_selection] = highlight_spec_normal, + [highlight_spec_pager_progress] = highlight_spec_normal, + [highlight_spec_pager_background] = highlight_spec_normal, + [highlight_spec_pager_prefix] = highlight_spec_normal, + [highlight_spec_pager_completion] = highlight_spec_normal, + [highlight_spec_pager_description] = highlight_spec_normal, + [highlight_spec_pager_secondary_background] = highlight_spec_pager_background, + [highlight_spec_pager_secondary_prefix] = highlight_spec_pager_prefix, + [highlight_spec_pager_secondary_completion] = highlight_spec_pager_completion, + [highlight_spec_pager_secondary_description] = highlight_spec_pager_description, + [highlight_spec_pager_selected_background] = highlight_spec_search_match, + [highlight_spec_pager_selected_prefix] = highlight_spec_pager_prefix, + [highlight_spec_pager_selected_completion] = highlight_spec_pager_completion, + [highlight_spec_pager_selected_description] = highlight_spec_pager_description, +}; +static_assert(sizeof(fallbacks) / sizeof(fallbacks[0]) == HIGHLIGHT_SPEC_MAX, "No missing fallbacks"); + /// Determine if the filesystem containing the given fd is case insensitive for lookups regardless /// of whether it preserves the case when saving a pathname. /// @@ -270,6 +311,7 @@ rgb_color_t highlight_get_color(highlight_spec_t highlight, bool is_background) // debug( 1, L"%d -> %d -> %ls", highlight, idx, val ); + if (!var) var = vars.get(highlight_var[fallbacks[idx]]); if (!var) var = vars.get(highlight_var[0]); if (var) result = parse_color(*var, treat_as_background); diff --git a/src/highlight.h b/src/highlight.h index 248d71af6..57c1f947a 100644 --- a/src/highlight.h +++ b/src/highlight.h @@ -33,11 +33,20 @@ enum { highlight_spec_selection, // Pager support. + // NOTE: pager.cpp relies on these being in this order. + highlight_spec_pager_progress, + highlight_spec_pager_background, highlight_spec_pager_prefix, highlight_spec_pager_completion, highlight_spec_pager_description, - highlight_spec_pager_progress, - highlight_spec_pager_secondary, + highlight_spec_pager_secondary_background, + highlight_spec_pager_secondary_prefix, + highlight_spec_pager_secondary_completion, + highlight_spec_pager_secondary_description, + highlight_spec_pager_selected_background, + highlight_spec_pager_selected_prefix, + highlight_spec_pager_selected_completion, + highlight_spec_pager_selected_description, // Used to double check a data structure in highlight.cpp HIGHLIGHT_SPEC_MAX, diff --git a/src/pager.cpp b/src/pager.cpp index 52da3581b..548a67223 100644 --- a/src/pager.cpp +++ b/src/pager.cpp @@ -137,18 +137,24 @@ line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, s assert(comp_width <= width); } - int bg_color = secondary ? highlight_spec_pager_secondary : highlight_spec_normal; - if (selected) { - bg_color = highlight_spec_search_match; - } + int offset = selected + ? (highlight_spec_pager_selected_background - highlight_spec_pager_background) + : (secondary + ? (highlight_spec_pager_secondary_background - highlight_spec_pager_background) + : 0); + highlight_spec_t bg_color = highlight_spec_pager_background + offset; + highlight_spec_t prefix_fg = highlight_spec_pager_prefix + offset; + highlight_spec_t comp_fg = highlight_spec_pager_completion + offset; + highlight_spec_t desc_fg = highlight_spec_pager_description + offset; auto bg = highlight_make_background(bg_color); + auto prefix_col = prefix_fg | bg; + auto comp_col = comp_fg | bg; + auto desc_col = desc_fg | bg; // Print the completion part size_t comp_remaining = comp_width; for (size_t i = 0; i < c->comp.size(); i++) { const wcstring &comp = c->comp.at(i); - highlight_spec_t packed_color = - highlight_spec_pager_prefix | bg; if (i > 0) { comp_remaining -= print_max(PAGER_SPACER_STRING, bg, comp_remaining, @@ -156,33 +162,27 @@ line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, s } comp_remaining -= - print_max(prefix, packed_color, comp_remaining, !comp.empty(), &line_data); - - packed_color = highlight_spec_pager_completion | bg; + print_max(prefix, prefix_col, comp_remaining, !comp.empty(), &line_data); comp_remaining -= - print_max(comp, packed_color, comp_remaining, i + 1 < c->comp.size(), &line_data); + print_max(comp, comp_col, comp_remaining, i + 1 < c->comp.size(), &line_data); } size_t desc_remaining = width - comp_width + comp_remaining; if (c->desc_width > 0 && desc_remaining > 4) { - highlight_spec_t desc_color = - highlight_spec_pager_description | bg; - highlight_spec_t punct_color = - highlight_spec_pager_completion | bg; - // always have at least two spaces to separate completion and description - desc_remaining -= print_max(L" ", punct_color, 2, false, &line_data); + desc_remaining -= print_max(L" ", bg, 2, false, &line_data); // right-justify the description by adding spaces // the 2 here refers to the parenthesis below while (desc_remaining > c->desc_width + 2) { - desc_remaining -= print_max(L" ", punct_color, 1, false, &line_data); + desc_remaining -= print_max(L" ", bg, 1, false, &line_data); } assert(desc_remaining >= 2); - desc_remaining -= print_max(L"(", punct_color, 1, false, &line_data); - desc_remaining -= print_max(c->desc, desc_color, desc_remaining - 1, false, &line_data); - desc_remaining -= print_max(L")", punct_color, 1, false, &line_data); + auto paren_col = highlight_spec_pager_completion | bg; + desc_remaining -= print_max(L"(", paren_col, 1, false, &line_data); + desc_remaining -= print_max(c->desc, desc_col, desc_remaining - 1, false, &line_data); + desc_remaining -= print_max(L")", paren_col, 1, false, &line_data); } else { // No description, or it won't fit. Just add spaces. print_max(wcstring(desc_remaining, L' '), bg, desc_remaining, false, &line_data);