diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 212e686f96..53581179b6 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4513,6 +4513,13 @@ A jump table for the options with a short description can be found at |Q_op|. the range of 0 for fully opaque popupmenu (disabled) to 100 for fully transparent background. Values between 0-30 are typically most useful. + It is possible to override the level for individual highlights within + the popupmenu using |highlight-blend|. For instance, to enable + transparency but force the current selected element to be fully opaque: > + + :set pumblend=15 + :hi PmenuSel blend=0 +< UI-dependent. Works best with RGB colors. 'termguicolors' *'pyxversion'* *'pyx'* @@ -6693,6 +6700,15 @@ A jump table for the options with a short description can be found at |Q_op|. key is never used for the menu. This option is not used for ; on Win32. + *'winblend'* *'winbl'* +'winblend' 'winbl' number (default 0) + local to window + Enables pseudo-transparency for a floating window. Valid values are in + the range of 0 for fully opaque window (disabled) to 100 for fully + transparent background. Values between 0-30 are typically most useful. + + UI-dependent. Works best with RGB colors. 'termguicolors' + *'window'* *'wi'* 'window' 'wi' number (default screen height - 1) global diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index b60a952def..1373aff891 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -4879,6 +4879,11 @@ guisp={color-name} *highlight-guisp* All values are hexadecimal, range from "00" to "ff". Examples: > :highlight Comment guifg=#11f0c3 guibg=#ff00ff < +blend={integer} *highlight-blend* + Override the blend level for a highlight group within the popupmenu + or floating windows. Only takes effect if 'pumblend' or 'winblend' + is set for the menu or window. See the help at the respective option. + *highlight-groups* *highlight-default* These are the builtin highlighting groups. Note that the highlighting depends on the value of 'background'. You can see the current settings with the diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 2e8ca384b4..72eb68b650 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -30,6 +30,7 @@ #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/popupmnu.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" @@ -2239,16 +2240,33 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, } /// NB: if your UI doesn't use hlstate, this will not return hlstate first time -Array nvim__inspect_cell(Integer row, Integer col, Error *err) +Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err) { Array ret = ARRAY_DICT_INIT; - if (row < 0 || row >= default_grid.Rows - || col < 0 || col >= default_grid.Columns) { + + // TODO(bfredl): if grid == 0 we should read from the compositor's buffer. + // The only problem is that it does not yet exist. + ScreenGrid *g = &default_grid; + if (grid == pum_grid.handle) { + g = &pum_grid; + } else if (grid > 1) { + win_T *wp = get_win_by_grid_handle((handle_T)grid); + if (wp != NULL && wp->w_grid.chars != NULL) { + g = &wp->w_grid; + } else { + api_set_error(err, kErrorTypeValidation, + "No grid with the given handle"); + return ret; + } + } + + if (row < 0 || row >= g->Rows + || col < 0 || col >= g->Columns) { return ret; } - size_t off = default_grid.line_offset[(size_t)row] + (size_t)col; - ADD(ret, STRING_OBJ(cstr_to_string((char *)default_grid.chars[off]))); - int attr = default_grid.attrs[off]; + size_t off = g->line_offset[(size_t)row] + (size_t)col; + ADD(ret, STRING_OBJ(cstr_to_string((char *)g->chars[off]))); + int attr = g->attrs[off]; ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err))); // will not work first time if (!highlight_use_hlstate()) { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 4b0e680c25..ad10f6baa2 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -252,6 +252,8 @@ typedef struct { # define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars' char_u *wo_lcs; # define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars' + long wo_winbl; +# define w_p_winbl w_onebuf_opt.wo_winbl // 'winblend' LastSet wo_scriptID[WV_COUNT]; // SIDs for window-local options # define w_p_scriptID w_onebuf_opt.wo_scriptID diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 68b2640aa5..0b5fafd7c0 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -756,9 +756,11 @@ EXTERN bool KeyTyped; // true if user typed current char EXTERN int KeyStuffed; // TRUE if current char from stuffbuf EXTERN int maptick INIT(= 0); // tick for each non-mapped char -EXTERN int must_redraw INIT(= 0); /* type of redraw necessary */ -EXTERN int skip_redraw INIT(= FALSE); /* skip redraw once */ -EXTERN int do_redraw INIT(= FALSE); /* extra redraw once */ +EXTERN int must_redraw INIT(= 0); // type of redraw necessary +EXTERN bool skip_redraw INIT(= false); // skip redraw once +EXTERN bool do_redraw INIT(= false); // extra redraw once +EXTERN bool must_redraw_pum INIT(= false); // redraw pum. NB: must_redraw + // should also be set. EXTERN int need_highlight_changed INIT(= true); diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h index 38fc513baa..e4021c033b 100644 --- a/src/nvim/grid_defs.h +++ b/src/nvim/grid_defs.h @@ -54,6 +54,9 @@ typedef struct { int row_offset; int col_offset; + // whether the compositor should blend the grid with the background grid + bool blending; + // state owned by the compositor. int comp_row; int comp_col; @@ -61,7 +64,7 @@ typedef struct { bool comp_disabled; } ScreenGrid; -#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, 0, 0, false, 0, 0, 0, \ - 0, 0, false } +#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, 0, 0, false, 0, 0, \ + false, 0, 0, 0, false } #endif // NVIM_GRID_DEFS_H diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 3ba02be32d..15c3d0eb7b 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -7,6 +7,7 @@ #include "nvim/highlight.h" #include "nvim/highlight_defs.h" #include "nvim/map.h" +#include "nvim/popupmnu.h" #include "nvim/screen.h" #include "nvim/syntax.h" #include "nvim/ui.h" @@ -145,6 +146,16 @@ int hl_get_ui_attr(int idx, int final_id, bool optional) attrs = syn_attr2entry(syn_attr); available = true; } + + if (HLF_PNI <= idx && idx <= HLF_PST) { + if (attrs.hl_blend == -1 && p_pb > 0) { + attrs.hl_blend = (int)p_pb; + } + if (pum_drawn()) { + must_redraw_pum = true; + } + } + if (optional && !available) { return 0; } @@ -159,20 +170,35 @@ void update_window_hl(win_T *wp, bool invalid) } wp->w_hl_needs_update = false; + // If a floating window is blending it always have a named + // wp->w_hl_attr_normal group. HL_ATTR(HLF_NFLOAT) is always named. + bool has_blend = wp->w_floating && wp->w_p_winbl != 0; + // determine window specific background set in 'winhighlight' bool float_win = wp->w_floating && !wp->w_float_config.external; if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) { wp->w_hl_attr_normal = hl_get_ui_attr(HLF_INACTIVE, - wp->w_hl_ids[HLF_INACTIVE], true); + wp->w_hl_ids[HLF_INACTIVE], + !has_blend); } else if (float_win && wp->w_hl_ids[HLF_NFLOAT] > 0) { wp->w_hl_attr_normal = hl_get_ui_attr(HLF_NFLOAT, - wp->w_hl_ids[HLF_NFLOAT], true); + // 'cursorline' + wp->w_hl_ids[HLF_NFLOAT], !has_blend); } else if (wp->w_hl_id_normal > 0) { - wp->w_hl_attr_normal = hl_get_ui_attr(-1, wp->w_hl_id_normal, true); + wp->w_hl_attr_normal = hl_get_ui_attr(-1, wp->w_hl_id_normal, !has_blend); } else { wp->w_hl_attr_normal = float_win ? HL_ATTR(HLF_NFLOAT) : 0; } + // if blend= attribute is not set, 'winblend' value overrides it. + if (wp->w_floating && wp->w_p_winbl > 0) { + HlEntry entry = kv_A(attr_entries, wp->w_hl_attr_normal); + if (entry.attr.hl_blend == -1) { + entry.attr.hl_blend = (int)wp->w_p_winbl; + wp->w_hl_attr_normal = get_attr_entry(entry); + } + } + if (wp != curwin) { wp->w_hl_attr_normal = hl_combine_attr(HL_ATTR(HLF_INACTIVE), wp->w_hl_attr_normal); @@ -240,6 +266,8 @@ void hl_invalidate_blends(void) { map_clear(int, int)(blend_attr_entries); map_clear(int, int)(blendthrough_attr_entries); + highlight_changed(); + update_window_hl(curwin, true); } // Combine special attributes (e.g., for spelling) with other attributes @@ -292,6 +320,10 @@ int hl_combine_attr(int char_attr, int prim_attr) new_en.rgb_sp_color = spell_aep.rgb_sp_color; } + if (spell_aep.hl_blend >= 0) { + new_en.hl_blend = spell_aep.hl_blend; + } + id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine, .id1 = char_attr, .id2 = prim_attr }); if (id > 0) { @@ -336,50 +368,59 @@ static HlAttrs get_colors_force(int attr) /// This is called per-cell, so cache the result. /// /// @return the resulting attributes. -int hl_blend_attrs(int back_attr, int front_attr, bool through) +int hl_blend_attrs(int back_attr, int front_attr, bool *through) { + HlAttrs fattrs = get_colors_force(front_attr); + int ratio = fattrs.hl_blend; + if (ratio <= 0) { + *through = false; + return front_attr; + } + int combine_tag = (back_attr << 16) + front_attr; - Map(int, int) *map = through ? blendthrough_attr_entries : blend_attr_entries; + Map(int, int) *map = (*through + ? blendthrough_attr_entries + : blend_attr_entries); int id = map_get(int, int)(map, combine_tag); if (id > 0) { return id; } HlAttrs battrs = get_colors_force(back_attr); - HlAttrs fattrs = get_colors_force(front_attr); HlAttrs cattrs; - if (through) { + + if (*through) { cattrs = battrs; - cattrs.rgb_fg_color = rgb_blend((int)p_pb, battrs.rgb_fg_color, + cattrs.rgb_fg_color = rgb_blend(ratio, battrs.rgb_fg_color, fattrs.rgb_bg_color); if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) { - cattrs.rgb_sp_color = rgb_blend((int)p_pb, battrs.rgb_sp_color, + cattrs.rgb_sp_color = rgb_blend(ratio, battrs.rgb_sp_color, fattrs.rgb_bg_color); } else { cattrs.rgb_sp_color = -1; } cattrs.cterm_bg_color = fattrs.cterm_bg_color; - cattrs.cterm_fg_color = cterm_blend((int)p_pb, battrs.cterm_fg_color, + cattrs.cterm_fg_color = cterm_blend(ratio, battrs.cterm_fg_color, fattrs.cterm_bg_color); } else { cattrs = fattrs; - if (p_pb >= 50) { + if (ratio >= 50) { cattrs.rgb_ae_attr |= battrs.rgb_ae_attr; } - cattrs.rgb_fg_color = rgb_blend((int)p_pb/2, battrs.rgb_fg_color, + cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color, fattrs.rgb_fg_color); if (cattrs.rgb_ae_attr & (HL_UNDERLINE|HL_UNDERCURL)) { - cattrs.rgb_sp_color = rgb_blend((int)p_pb/2, battrs.rgb_bg_color, + cattrs.rgb_sp_color = rgb_blend(ratio/2, battrs.rgb_bg_color, fattrs.rgb_sp_color); } else { cattrs.rgb_sp_color = -1; } } - cattrs.rgb_bg_color = rgb_blend((int)p_pb, battrs.rgb_bg_color, + cattrs.rgb_bg_color = rgb_blend(ratio, battrs.rgb_bg_color, fattrs.rgb_bg_color); - HlKind kind = through ? kHlBlendThrough : kHlBlend; + HlKind kind = *through ? kHlBlendThrough : kHlBlend; id = get_attr_entry((HlEntry){ .attr = cattrs, .kind = kind, .id1 = back_attr, .id2 = front_attr }); if (id > 0) { diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h index 746d2c2dfc..60f571ff0f 100644 --- a/src/nvim/highlight_defs.h +++ b/src/nvim/highlight_defs.h @@ -25,6 +25,7 @@ typedef struct attr_entry { int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color; int cterm_fg_color, cterm_bg_color; + int hl_blend; } HlAttrs; #define HLATTRS_INIT (HlAttrs) { \ diff --git a/src/nvim/option.c b/src/nvim/option.c index 8dadf926b9..25b498e3e6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -74,6 +74,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/ui.h" +#include "nvim/ui_compositor.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/os/os.h" @@ -4391,11 +4392,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, } } else if (pp == &p_pb) { p_pb = MAX(MIN(p_pb, 100), 0); - if (old_value != 0) { - hl_invalidate_blends(); - } + hl_invalidate_blends(); + pum_grid.blending = (p_pb > 0); if (pum_drawn()) { - pum_recompose(); + pum_redraw(); } } else if (pp == &p_pyx) { if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) { @@ -4418,6 +4418,11 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, } } else if (pp == &curwin->w_p_nuw) { curwin->w_nrwidth_line_count = 0; + } else if (pp == &curwin->w_p_winbl && value != old_value) { + // 'floatblend' + curwin->w_p_winbl = MAX(MIN(curwin->w_p_winbl, 100), 0); + curwin->w_hl_needs_update = true; + curwin->w_grid.blending = curwin->w_p_winbl > 0; } @@ -5713,6 +5718,7 @@ static char_u *get_varp(vimoption_T *p) case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); case PV_FCS: return (char_u *)&(curwin->w_p_fcs); case PV_LCS: return (char_u *)&(curwin->w_p_lcs); + case PV_WINBL: return (char_u *)&(curwin->w_p_winbl); default: IEMSG(_("E356: get_varp ERROR")); } // always return a valid pointer to avoid a crash! @@ -5792,6 +5798,7 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_winhl = vim_strsave(from->wo_winhl); to->wo_fcs = vim_strsave(from->wo_fcs); to->wo_lcs = vim_strsave(from->wo_lcs); + to->wo_winbl = from->wo_winbl; check_winopt(to); // don't want NULL pointers } @@ -5854,7 +5861,8 @@ void didset_window_options(win_T *wp) briopt_check(wp); set_chars_option(wp, &wp->w_p_fcs); set_chars_option(wp, &wp->w_p_lcs); - parse_winhl_opt(wp); + parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl + wp->w_grid.blending = wp->w_p_winbl > 0; } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 8df5039037..35fe3b5b00 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -816,6 +816,7 @@ enum { , WV_WINHL , WV_FCS , WV_LCS + , WV_WINBL , WV_COUNT // must be the last one }; diff --git a/src/nvim/options.lua b/src/nvim/options.lua index e892e59ba6..cfdac36990 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -2761,6 +2761,13 @@ return { varname='p_wak', defaults={if_true={vi="menu"}} }, + { + full_name='winblend', abbreviation='winbl', + type='number', scope={'window'}, + vi_def=true, + redraw={'current_window'}, + defaults={if_true={vi=0}} + }, { full_name='winhighlight', abbreviation='winhl', type='string', scope={'window'}, diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index df751b0ca2..ef4330003f 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -376,6 +376,7 @@ void pum_redraw(void) pum_height, grid_width, false, true); bool invalid_grid = moved || pum_invalid; pum_invalid = false; + must_redraw_pum = false; if (!pum_grid.chars || pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) { @@ -790,6 +791,7 @@ void pum_undisplay(bool immediate) { pum_is_visible = false; pum_array = NULL; + must_redraw_pum = false; if (immediate) { pum_check_clear(); diff --git a/src/nvim/screen.c b/src/nvim/screen.c index f349304468..d91b832e5a 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -482,13 +482,13 @@ void update_screen(int type) } end_search_hl(); + // May need to redraw the popup menu. - if (pum_drawn() && redraw_popupmenu) { + if (pum_drawn() && must_redraw_pum) { pum_redraw(); } send_grid_resize = false; - redraw_popupmenu = false; /* Reset b_mod_set flags. Going through all windows is probably faster * than going through all buffers (there could be many buffers). */ diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 38d0e33948..8d846df8b6 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -75,6 +75,8 @@ struct hl_group { uint8_t *sg_rgb_fg_name; ///< RGB foreground color name uint8_t *sg_rgb_bg_name; ///< RGB background color name uint8_t *sg_rgb_sp_name; ///< RGB special color name + + int sg_blend; ///< blend level (0-100 inclusive), -1 if unset }; /// \addtogroup SG_SET @@ -6879,6 +6881,12 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) { // Ignored for now + } else if (strcmp(key, "BLEND") == 0) { + if (strcmp(arg, "NONE") != 0) { + HL_TABLE()[idx].sg_blend = strtol(arg, NULL, 10); + } else { + HL_TABLE()[idx].sg_blend = -1; + } } else { emsgf(_("E423: Illegal argument: %s"), key_start); error = true; @@ -6993,6 +7001,7 @@ static void highlight_clear(int idx) XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_fg_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name); XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name); + HL_TABLE()[idx].sg_blend = -1; // Clear the script ID only when there is no link, since that is not // cleared. if (HL_TABLE()[idx].sg_link == 0) { @@ -7029,6 +7038,9 @@ static void highlight_list_one(const int id) didh = highlight_list_arg(id, didh, LIST_STRING, 0, sgp->sg_rgb_sp_name, "guisp"); + didh = highlight_list_arg(id, didh, LIST_INT, + sgp->sg_blend+1, NULL, "blend"); + if (sgp->sg_link && !got_int) { (void)syn_list_header(didh, 9999, id); didh = true; @@ -7252,6 +7264,7 @@ static void set_hl_attr(int idx) at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1; at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1; at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1; + at_en.hl_blend = sgp->sg_blend; sgp->sg_attr = hl_get_syn_attr(idx+1, at_en); @@ -7377,6 +7390,7 @@ static int syn_add_group(char_u *name) hlgp->sg_rgb_bg = -1; hlgp->sg_rgb_fg = -1; hlgp->sg_rgb_sp = -1; + hlgp->sg_blend = -1; hlgp->sg_name_u = vim_strsave_up(name); return highlight_ga.ga_len; /* ID is index plus one */ diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index f6573e7488..0c3e771eb8 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -330,10 +330,10 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, memcpy(attrbuf+(col-startcol), grid->attrs+off, n * sizeof(*attrbuf)); // 'pumblend' - if (grid == &pum_grid && p_pb) { + if (grid->blending) { for (int i = col-(int)startcol; i < until-startcol; i++) { bool thru = strequal((char *)linebuf[i], " "); // negative space - attrbuf[i] = (sattr_T)hl_blend_attrs(bg_attrs[i], attrbuf[i], thru); + attrbuf[i] = (sattr_T)hl_blend_attrs(bg_attrs[i], attrbuf[i], &thru); if (thru) { memcpy(linebuf[i], bg_line[i], sizeof(linebuf[i])); } @@ -419,7 +419,7 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, assert(clearcol <= default_grid.Columns); if (flags & kLineFlagInvalid || kv_size(layers) > curgrid->comp_index+1 - || (p_pb && curgrid == &pum_grid)) { + || curgrid->blending) { compose_line(row, startcol, clearcol, flags); } else { ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr, diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index a567fbb941..3c7418167c 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -3764,6 +3764,196 @@ describe('floating windows', function() end end) end) + + it("'winblend' option", function() + screen:try_resize(50,9) + screen:set_default_attr_ids({ + [1] = {background = Screen.colors.LightMagenta}, + [2] = {foreground = Screen.colors.Grey0, background = tonumber('0xffcfff')}, + [3] = {foreground = tonumber('0xb282b2'), background = tonumber('0xffcfff')}, + [4] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta}, + [5] = {foreground = tonumber('0x990000'), background = tonumber('0xfff1ff')}, + [6] = {foreground = tonumber('0x332533'), background = tonumber('0xfff1ff')}, + }) + insert([[ + Lorem ipsum dolor sit amet, consectetur + adipisicing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa + qui officia deserunt mollit anim id est + laborum.]]) + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf, 0, -1, true, {"test", "", "popup text"}) + local win = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=2, col=5}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + | + ## grid 2 + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + ## grid 4 + {1:test }| + {1: }| + {1:popup text }| + ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}} + else + screen:expect([[ + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea co{1:test }. Duis aute irure dolor in | + repre{1: }uptate velit esse cillum | + dolor{1:popup text }la pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + | + ]]) + end + + meths.win_set_option(win, "winblend", 30) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + | + ## grid 2 + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + ## grid 4 + {1:test }| + {1: }| + {1:popup text }| + ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true} + else + screen:expect([[ + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea co{2:test}{3:o consequat}. Duis aute irure dolor in | + repre{3:henderit in vol}uptate velit esse cillum | + dolor{2:popup}{3:fugi}{2:text}{3:ul}la pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + | + ]]) + end + + command('hi SpecialRegion guifg=Red blend=0') + meths.buf_add_highlight(buf, -1, "SpecialRegion", 2, 0, -1) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + | + ## grid 2 + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + ## grid 4 + {1:test }| + {1: }| + {4:popup text}{1: }| + ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}} + else + screen:expect([[ + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea co{2:test}{3:o consequat}. Duis aute irure dolor in | + repre{3:henderit in vol}uptate velit esse cillum | + dolor{4:popup text}{3:ul}la pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + | + ]]) + end + + command('hi SpecialRegion guifg=Red blend=80') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + [2:--------------------------------------------------]| + | + ## grid 2 + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + ## grid 4 + {1:test }| + {1: }| + {4:popup text}{1: }| + ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true} + else + screen:expect([[ + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea co{2:test}{3:o consequat}. Duis aute irure dolor in | + repre{3:henderit in vol}uptate velit esse cillum | + dolor{5:popup}{6:fugi}{5:text}{3:ul}la pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + | + ]]) + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index b457ebebab..466e078277 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -1662,6 +1662,26 @@ describe('builtin popupmenu', function() {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} | ]]) + -- can disable blending for indiviual attribute. For instance current + -- selected item. (also tests that `hi Pmenu*` take immediate effect) + command('hi PMenuSel blend=0') + screen:expect([[ + Lorem ipsum d{1:ol}or sit amet, consectetur | + adipisicing elit, sed do eiusmod tempor | + bla bla incididunt^ | + incidid{22: incididunt }{27: }d{1:ol}ore magna aliqua. | + Ut enim{28: }{29:ut}{28: minim veniam}{25:,} quis nostrud | + exercit{28:a}{29:labore}{28:llamco la}{25:b}oris nisi ut aliquip ex | + {2:[No Nam}{30:e}{43:et}{30:[+] }{32: }{2: }| + incidid{28:u}{29:dol}{41:or}{29:e}{28:labore et}{25: }d{1:ol}ore magna aliqua. | + Ut enim{28: }{29:magna}{28:nim veniam}{25:,} quis nostrud | + exercit{28:a}{29:aliqua}{28:llamco la}{25:b}oris nisi {4:ut} aliquip ex | + ea comm{28:o}{29:Ut}{28: consequat. D}{25:u}is a{4:ut}e irure d{1:ol}or in | + reprehe{28:n}{29:enim}{28:t in v}{34:ol}{28:upt}{25:a}te v{3:el}it esse cillum | + {5:[No Nam}{38:e}{44:ad}{38:[+] }{40: }{5: }| + {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} | + ]]) + feed('') screen:expect([[ Lorem ipsum d{1:ol}or sit amet, consectetur |