aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt10
-rw-r--r--runtime/doc/vim_diff.txt1
-rw-r--r--src/nvim/api/ui.c5
-rw-r--r--src/nvim/highlight.c98
-rw-r--r--src/nvim/highlight.h8
-rw-r--r--src/nvim/highlight_defs.h2
-rw-r--r--src/nvim/option.c10
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/popupmnu.c18
-rw-r--r--src/nvim/screen.c13
-rw-r--r--src/nvim/ui_compositor.c42
-rw-r--r--test/functional/ui/options_spec.lua1
-rw-r--r--test/functional/ui/popupmenu_spec.lua217
-rw-r--r--test/functional/ui/screen.lua2
15 files changed, 417 insertions, 19 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index d0643bf5ed..315ca24835 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4486,6 +4486,16 @@ A jump table for the options with a short description can be found at |Q_op|.
Insert mode completion. When zero as much space as available is used.
|ins-completion-menu|.
+ *'pumblend'* *'pb'*
+'pumblend' 'pb' number (default 0)
+ global
+ Enables semi-transparency for the completion popupmenu. Valid values
+ are in the range from 0 for fully opaque popupmenu (disabled) to 100
+ for fully transparent background. Lower values 0-30 are typically most
+ useful.
+
+ UI-dependent. Supported by TUI with 'termguicolors' enabled.
+
*'pyxversion'* *'pyx'*
'pyxversion' 'pyx' number (default depends on the build)
global
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 33260ab53b..ae0bd2fdb2 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -189,6 +189,7 @@ Options:
for |hl-EndOfBuffer| marker
'inccommand' shows interactive results for |:substitute|-like commands
'listchars' local to window
+ 'pumblend' semi-transparent popupmenu
'scrollback'
'statusline' supports unlimited alignment sections
'tabline' %@Func@foo%X can call any function on mouse-click
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index a934f18dbf..91009c950f 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -357,10 +357,7 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg,
Integer cterm_fg, Integer cterm_bg)
{
if (!ui->ui_ext[kUITermColors]) {
- bool dark = (*p_bg == 'd');
- rgb_fg = rgb_fg != -1 ? rgb_fg : (dark ? 0xFFFFFF : 0x000000);
- rgb_bg = rgb_bg != -1 ? rgb_bg : (dark ? 0x000000 : 0xFFFFFF);
- rgb_sp = rgb_sp != -1 ? rgb_sp : 0xFF0000;
+ HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
}
Array args = ARRAY_DICT_INIT;
ADD(args, INTEGER_OBJ(rgb_fg));
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index 20cdbc7ec9..cbb28d9a09 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -23,11 +23,15 @@ static kvec_t(HlEntry) attr_entries = KV_INITIAL_VALUE;
static Map(HlEntry, int) *attr_entry_ids;
static Map(int, int) *combine_attr_entries;
+static Map(int, int) *blend_attr_entries;
+static Map(int, int) *blendthrough_attr_entries;
void highlight_init(void)
{
attr_entry_ids = map_new(HlEntry, int)();
combine_attr_entries = map_new(int, int)();
+ blend_attr_entries = map_new(int, int)();
+ blendthrough_attr_entries = map_new(int, int)();
// index 0 is no attribute, add dummy entry:
kv_push(attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlUnknown,
@@ -213,6 +217,8 @@ void clear_hl_tables(bool reinit)
kv_size(attr_entries) = 1;
map_clear(HlEntry, int)(attr_entry_ids);
map_clear(int, int)(combine_attr_entries);
+ map_clear(int, int)(blend_attr_entries);
+ map_clear(int, int)(blendthrough_attr_entries);
highlight_attr_set_all();
highlight_changed();
screen_invalidate_highlights();
@@ -220,15 +226,22 @@ void clear_hl_tables(bool reinit)
kv_destroy(attr_entries);
map_free(HlEntry, int)(attr_entry_ids);
map_free(int, int)(combine_attr_entries);
+ map_free(int, int)(blend_attr_entries);
+ map_free(int, int)(blendthrough_attr_entries);
}
}
+void hl_invalidate_blends(void)
+{
+ map_clear(int, int)(blend_attr_entries);
+ map_clear(int, int)(blendthrough_attr_entries);
+}
+
// Combine special attributes (e.g., for spelling) with other attributes
// (e.g., for syntax highlighting).
// "prim_attr" overrules "char_attr".
// This creates a new group when required.
-// Since we expect there to be few spelling mistakes we don't cache the
-// result.
+// Since we expect there to be a lot of spelling mistakes we cache the result.
// Return the resulting attributes.
int hl_combine_attr(int char_attr, int prim_attr)
{
@@ -283,6 +296,85 @@ int hl_combine_attr(int char_attr, int prim_attr)
return id;
}
+/// Get the used rgb colors for an attr group.
+///
+/// If colors are unset, use builtin default colors. Never returns -1
+/// Cterm colors are unchanged.
+static HlAttrs get_colors_force(int attr)
+{
+ HlAttrs attrs = syn_attr2entry(attr);
+ if (attrs.rgb_bg_color == -1) {
+ attrs.rgb_bg_color = normal_bg;
+ }
+ if (attrs.rgb_fg_color == -1) {
+ attrs.rgb_fg_color = normal_fg;
+ }
+ if (attrs.rgb_sp_color == -1) {
+ attrs.rgb_sp_color = normal_sp;
+ }
+ HL_SET_DEFAULT_COLORS(attrs.rgb_fg_color, attrs.rgb_bg_color,
+ attrs.rgb_sp_color);
+ return attrs;
+}
+
+/// Blend overlay attributes (for popupmenu) with other attributes
+///
+/// This creates a new group when required.
+/// This will be called on a per-cell basis when in use, so cache the result.
+/// @return the resulting attributes.
+int hl_blend_attrs(int back_attr, int front_attr, bool through)
+{
+ int combine_tag = (back_attr << 16) + front_attr;
+ 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) {
+ cattrs = battrs;
+ cattrs.rgb_fg_color = rgb_blend((int)p_pb, battrs.rgb_fg_color,
+ fattrs.rgb_bg_color);
+ cattrs.cterm_bg_color = fattrs.cterm_bg_color;
+ cattrs.cterm_fg_color = fattrs.cterm_bg_color;
+ } else {
+ cattrs = fattrs;
+ if (p_pb >= 50) {
+ cattrs.rgb_ae_attr |= battrs.rgb_ae_attr;
+ }
+ cattrs.rgb_fg_color = rgb_blend((int)p_pb/2, battrs.rgb_fg_color,
+ fattrs.rgb_fg_color);
+ }
+ cattrs.rgb_bg_color = rgb_blend((int)p_pb, battrs.rgb_bg_color,
+ fattrs.rgb_bg_color);
+
+ HlKind kind = through ? kHlBlendThrough : kHlBlend;
+ id = get_attr_entry((HlEntry){ .attr = cattrs, .kind = kind,
+ .id1 = back_attr, .id2 = front_attr });
+ if (id > 0) {
+ map_put(int, int)(map, combine_tag, id);
+ }
+ return id;
+}
+
+static int rgb_blend(int ratio, int rgb1, int rgb2)
+{
+ int a = ratio, b = 100-ratio;
+ int r1 = (rgb1 & 0xFF0000) >> 16;
+ int g1 = (rgb1 & 0x00FF00) >> 8;
+ int b1 = (rgb1 & 0x0000FF) >> 0;
+ int r2 = (rgb2 & 0xFF0000) >> 16;
+ int g2 = (rgb2 & 0x00FF00) >> 8;
+ int b2 = (rgb2 & 0x0000FF) >> 0;
+ int mr = (a * r1 + b * r2)/100;
+ int mg = (a * g1 + b * g2)/100;
+ int mb = (a * b1 + b * b2)/100;
+ return (mr << 16) + (mg << 8) + mb;
+}
+
/// Get highlight attributes for a attribute code
HlAttrs syn_attr2entry(int attr)
{
@@ -406,6 +498,8 @@ static void hl_inspect_impl(Array *arr, int attr)
break;
case kHlCombine:
+ case kHlBlend:
+ case kHlBlendThrough:
// attribute combination is associative, so flatten to an array
hl_inspect_impl(arr, e.id1);
hl_inspect_impl(arr, e.id2);
diff --git a/src/nvim/highlight.h b/src/nvim/highlight.h
index 6be0d6200b..a237ddbc34 100644
--- a/src/nvim/highlight.h
+++ b/src/nvim/highlight.h
@@ -10,4 +10,12 @@
# include "highlight.h.generated.h"
#endif
+# define HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp) \
+ do { \
+ bool dark_ = (*p_bg == 'd'); \
+ rgb_fg = rgb_fg != -1 ? rgb_fg : (dark_ ? 0xFFFFFF : 0x000000); \
+ rgb_bg = rgb_bg != -1 ? rgb_bg : (dark_ ? 0x000000 : 0xFFFFFF); \
+ rgb_sp = rgb_sp != -1 ? rgb_sp : 0xFF0000; \
+ } while (0);
+
#endif // NVIM_HIGHLIGHT_H
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 40025fcbbb..1da33bfea5 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -160,6 +160,8 @@ typedef enum {
kHlSyntax,
kHlTerminal,
kHlCombine,
+ kHlBlend,
+ kHlBlendThrough,
} HlKind;
typedef struct {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 3914e020b1..5517768194 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -50,6 +50,7 @@
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/hardcopy.h"
+#include "nvim/highlight.h"
#include "nvim/indent_c.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
@@ -65,6 +66,7 @@
#include "nvim/normal.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
+#include "nvim/popupmnu.h"
#include "nvim/regexp.h"
#include "nvim/screen.h"
#include "nvim/spell.h"
@@ -4338,6 +4340,14 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
if (p_uc && !old_value) {
ml_open_files();
}
+ } else if (pp == &p_pb) {
+ p_pb = MAX(MIN(p_pb, 100), 0);
+ if (old_value != 0) {
+ hl_invalidate_blends();
+ }
+ if (pum_drawn()) {
+ pum_recompose();
+ }
} else if (pp == &p_pyx) {
if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) {
errmsg = e_invarg;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index c80de4d46b..ccb0496495 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -375,6 +375,7 @@ EXTERN int p_confirm; // 'confirm'
EXTERN int p_cp; // 'compatible'
EXTERN char_u *p_cot; // 'completeopt'
EXTERN long p_ph; // 'pumheight'
+EXTERN long p_pb; // 'pumblend'
EXTERN char_u *p_cpo; // 'cpoptions'
EXTERN char_u *p_csprg; // 'cscopeprg'
EXTERN int p_csre; // 'cscoperelative'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 127c15dd5a..b8f128103c 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1806,6 +1806,14 @@ return {
defaults={if_true={vi=0}}
},
{
+ full_name='pumblend', abbreviation='pb',
+ type='number', scope={'global'},
+ vi_def=true,
+ redraw={'ui_option'},
+ varname='p_pb',
+ defaults={if_true={vi=0}}
+ },
+ {
full_name='pyxversion', abbreviation='pyx',
type='number', scope={'global'},
secure=true,
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 9b09006b5f..3c10b7ae0f 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -44,6 +44,7 @@ static int pum_col; // left column of pum
static bool pum_is_visible = false;
static bool pum_is_drawn = false;
static bool pum_external = false;
+static bool pum_invalid = false; // the screen was just cleared
static ScreenGrid pum_grid = SCREEN_GRID_INIT;
@@ -360,12 +361,14 @@ void pum_redraw(void)
grid_assign_handle(&pum_grid);
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_col-col_off,
pum_height, grid_width);
+ bool invalid_grid = moved || pum_invalid;
+ pum_invalid = false;
if (!pum_grid.chars
|| pum_grid.Rows != pum_height || pum_grid.Columns != grid_width) {
- grid_alloc(&pum_grid, pum_height, grid_width, !moved, false);
+ grid_alloc(&pum_grid, pum_height, grid_width, !invalid_grid, false);
ui_call_grid_resize(pum_grid.handle, pum_grid.Columns, pum_grid.Rows);
- } else if (moved) {
+ } else if (invalid_grid) {
grid_invalidate(&pum_grid);
}
@@ -806,6 +809,17 @@ bool pum_drawn(void)
return pum_visible() && !pum_external;
}
+/// Screen was cleared, need to redraw next time
+void pum_invalidate(void)
+{
+ pum_invalid = true;
+}
+
+void pum_recompose(void)
+{
+ ui_comp_compose_grid(&pum_grid);
+}
+
/// Gets the height of the menu.
///
/// @return the height of the popup menu, the number of entries visible.
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 014f63f400..00d7c05be4 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -154,7 +154,7 @@ static bool highlights_invalid = false;
static bool conceal_cursor_used = false;
-static bool floats_invalid = false;
+static bool redraw_popupmenu = false;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.c.generated.h"
@@ -466,13 +466,13 @@ void update_screen(int type)
end_search_hl();
// May need to redraw the popup menu.
- if (pum_drawn() && floats_invalid) {
+ if (pum_drawn() && redraw_popupmenu) {
pum_redraw();
}
send_grid_resize = false;
highlights_invalid = false;
- floats_invalid = 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). */
@@ -6185,7 +6185,6 @@ static void screenclear2(void)
default_grid.line_wraps[i] = false;
}
- floats_invalid = true;
ui_call_grid_clear(1); // clear the display
clear_cmdline = false;
mode_displayed = false;
@@ -6193,6 +6192,8 @@ static void screenclear2(void)
redraw_all_later(NOT_VALID);
redraw_cmdline = true;
redraw_tabline = true;
+ redraw_popupmenu = true;
+ pum_invalidate();
if (must_redraw == CLEAR) {
must_redraw = NOT_VALID; // no need to clear again
}
@@ -7196,6 +7197,10 @@ void screen_resize(int width, int height)
} else {
update_topline();
if (pum_drawn()) {
+ // TODO(bfredl): ins_compl_show_pum wants to redraw the screen first.
+ // For now make sure the nested update_screen(0) won't redraw the
+ // pum at the old position. Try to untangle this later.
+ redraw_popupmenu = false;
ins_compl_show_pum();
}
update_screen(NOT_VALID);
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 9e0c44f3c2..59ae9c34ec 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -15,6 +15,7 @@
#include "nvim/ascii.h"
#include "nvim/vim.h"
#include "nvim/ui.h"
+#include "nvim/highlight.h"
#include "nvim/memory.h"
#include "nvim/ui_compositor.h"
#include "nvim/ugrid.h"
@@ -169,11 +170,9 @@ void ui_comp_remove_grid(ScreenGrid *grid)
(void)kv_pop(layers);
grid->comp_index = 0;
- if (ui_comp_should_draw()) {
- // inefficent: only draw up to grid->comp_index
- compose_area(grid->comp_row, grid->comp_row+grid->Rows,
- grid->comp_col, grid->comp_col+grid->Columns);
- }
+ // recompose the area under the grid
+ // inefficent when being overlapped: only draw up to grid->comp_index
+ ui_comp_compose_grid(grid);
}
bool ui_comp_set_grid(handle_T handle)
@@ -229,6 +228,10 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
int col = (int)startcol;
ScreenGrid *grid = NULL;
+ schar_T *bg_line = &default_grid.chars[default_grid.line_offset[row]
+ +(size_t)startcol];
+ sattr_T *bg_attrs = &default_grid.attrs[default_grid.line_offset[row]
+ +(size_t)startcol];
while (col < endcol) {
int until = 0;
@@ -256,6 +259,16 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
memcpy(linebuf+(col-startcol), grid->chars+off, n * sizeof(*linebuf));
memcpy(attrbuf+(col-startcol), grid->attrs+off, n * sizeof(*attrbuf));
+ if (grid != &default_grid && p_pb) {
+ for (int i = col-(int)startcol; i < until-startcol; i++) {
+ bool thru = strequal((char *)linebuf[i], " ");
+ attrbuf[i] = (sattr_T)hl_blend_attrs(bg_attrs[i], attrbuf[i], thru);
+ if (thru) {
+ memcpy(linebuf[i], bg_line[i], sizeof(linebuf[i]));
+ }
+ }
+ }
+
// Tricky: if overlap caused a doublewidth char to get cut-off, must
// replace the visible half with a space.
if (linebuf[col-startcol][0] == NUL) {
@@ -272,6 +285,7 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
skip = 0;
}
}
+
col = until;
}
assert(endcol <= chk_width);
@@ -293,11 +307,25 @@ static void compose_area(Integer startrow, Integer endrow,
{
endrow = MIN(endrow, default_grid.Rows);
endcol = MIN(endcol, default_grid.Columns);
+ if (endcol <= startcol) {
+ return;
+ }
for (int r = (int)startrow; r < endrow; r++) {
compose_line(r, startcol, endcol, kLineFlagInvalid);
}
}
+/// compose the area under the grid.
+///
+/// This is needed when some option affecting composition is changed,
+/// such as 'pumblend' for popupmenu grid.
+void ui_comp_compose_grid(ScreenGrid *grid)
+{
+ if (ui_comp_should_draw()) {
+ compose_area(grid->comp_row, grid->comp_row+grid->Rows,
+ grid->comp_col, grid->comp_col+grid->Columns);
+ }
+}
static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
Integer startcol, Integer endcol,
@@ -316,8 +344,10 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
if (curgrid != &default_grid) {
flags = flags & ~kLineFlagWrap;
}
+ assert(row < default_grid.Rows);
assert(clearcol <= default_grid.Columns);
- if (flags & kLineFlagInvalid || kv_size(layers) > curgrid->comp_index+1) {
+ if (flags & kLineFlagInvalid
+ || kv_size(layers) > (p_pb ? 1 : curgrid->comp_index+1)) {
compose_line(row, startcol, clearcol, flags);
} else {
ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr,
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index 493079b576..966669fa95 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -18,6 +18,7 @@ describe('ui receives option updates', function()
guifontset='',
guifontwide='',
linespace=0,
+ pumblend=0,
showtabline=1,
termguicolors=false,
ext_cmdline=false,
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 6a10f60ad8..582f357972 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -999,9 +999,52 @@ describe('builtin popupmenu', function()
{1:~ }|
{2:-- INSERT --} |
]])
+
+ screen:try_resize(25,10)
+ screen:expect([[
+ some long prefix before |
+ the text^ |
+ {1:~ }{n: word }{1: }|
+ {1:~ }{n: choice }{1: }|
+ {1:~ }{s: text }{1: }|
+ {1:~ }{n: thing }{1: }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
+
+ screen:try_resize(12,5)
+ screen:expect([[
+ some long |
+ prefix |
+ bef{n: word } |
+ tex{n: }^ |
+ {2:-- }{s: text } |
+ ]])
+
+ -- can't draw the pum, but check we don't crash
+ screen:try_resize(12,2)
+ screen:expect([[
+ text^ |
+ {2:-- INSERT -} |
+ ]])
+
+ -- but state is preserved, pum reappears
+ screen:try_resize(20,8)
+ screen:expect([[
+ some long prefix |
+ before the text^ |
+ {1:~ }{n: word }|
+ {1:~ }{n: choice }|
+ {1:~ }{s: text }|
+ {1:~ }{n: thing }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]])
end)
- it('can be moved due to wrap or resize', function()
+ it('works with rightleft window', function()
command("set rl")
feed('isome rightleft ')
screen:expect([[
@@ -1230,4 +1273,176 @@ describe('builtin popupmenu', function()
]])
end)
+ it('works with pumblend', function()
+ screen:try_resize(60,14)
+ screen:set_default_attr_ids({
+ [1] = {background = Screen.colors.Yellow},
+ [2] = {bold = true, reverse = true},
+ [3] = {bold = true, foreground = Screen.colors.Brown},
+ [4] = {foreground = Screen.colors.Blue1},
+ [5] = {reverse = true},
+ [6] = {background = Screen.colors.Gray55, foreground = Screen.colors.Grey45, special = Screen.colors.Red},
+ [7] = {background = Screen.colors.Gray55, foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [8] = {background = tonumber('0x191919'), foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [9] = {background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8e5'), special = Screen.colors.Red},
+ [10] = {background = tonumber('0xffc1ff'), foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [11] = {foreground = tonumber('0xe5a8e5'), special = Screen.colors.Red, background = tonumber('0xffc1ff'), reverse = true, bold = true},
+ [12] = {foreground = Screen.colors.Grey45, special = Screen.colors.Red, background = Screen.colors.Gray55, reverse = true, bold = true},
+ [13] = {background = tonumber('0xffc1e5'), foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [14] = {background = tonumber('0xffc1e5'), foreground = tonumber('0xe5a8e5'), special = Screen.colors.Red},
+ [15] = {background = tonumber('0xffc1ff'), foreground = tonumber('0x080202'), special = Screen.colors.Red},
+ [16] = {special = Screen.colors.Red, background = tonumber('0xffc1ff'), bold = true, foreground = tonumber('0xf6ace9')},
+ [17] = {background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8ff'), special = Screen.colors.Red},
+ [18] = {special = Screen.colors.Red, background = tonumber('0xffc1ff'), reverse = true, foreground = tonumber('0xe5a8e5')},
+ [19] = {special = Screen.colors.Red, background = Screen.colors.Gray55, reverse = true, foreground = Screen.colors.Grey45},
+ [20] = {bold = true},
+ [21] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [22] = {background = Screen.colors.WebGray},
+ [23] = {background = Screen.colors.Grey0},
+ [24] = {background = Screen.colors.LightMagenta},
+ [25] = {background = Screen.colors.Gray75, foreground = Screen.colors.Grey25, special = Screen.colors.Red},
+ [26] = {background = Screen.colors.Gray75, foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [27] = {background = Screen.colors.Gray50, foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [28] = {background = tonumber('0xffddff'), foreground = tonumber('0x7f5d7f'), special = Screen.colors.Red},
+ [29] = {background = tonumber('0xffddff'), foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [30] = {foreground = tonumber('0x7f5d7f'), special = Screen.colors.Red, background = tonumber('0xffddff'), reverse = true, bold = true},
+ [31] = {foreground = Screen.colors.Grey0, special = Screen.colors.Red, background = tonumber('0xffddff'), reverse = true, bold = true},
+ [32] = {foreground = Screen.colors.Grey25, special = Screen.colors.Red, background = Screen.colors.Gray75, reverse = true, bold = true},
+ [33] = {background = tonumber('0xffdd7f'), foreground = Screen.colors.Grey0, special = Screen.colors.Red},
+ [34] = {background = tonumber('0xffdd7f'), foreground = tonumber('0x7f5d7f'), special = Screen.colors.Red},
+ [35] = {special = Screen.colors.Red, background = tonumber('0xffddff'), bold = true, foreground = tonumber('0x290a0a')},
+ [36] = {special = Screen.colors.Red, background = tonumber('0xffddff'), bold = true, foreground = tonumber('0xd27294')},
+ [37] = {background = tonumber('0xffddff'), foreground = tonumber('0x7f5dff'), special = Screen.colors.Red},
+ [38] = {special = Screen.colors.Red, background = tonumber('0xffddff'), reverse = true, foreground = tonumber('0x7f5d7f')},
+ [39] = {special = Screen.colors.Red, background = tonumber('0xffddff'), reverse = true, foreground = Screen.colors.Grey0},
+ [40] = {special = Screen.colors.Red, background = Screen.colors.Gray75, reverse = true, foreground = Screen.colors.Grey25},
+ [41] = {background = tonumber('0xffddff'), foreground = tonumber('0x00003f'), special = Screen.colors.Red},
+ })
+ command('syntax on')
+ command('set mouse=a')
+ command('set pumblend=10')
+ 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.]])
+ command('match Statement /el/')
+ command('2match Comment /ut/')
+ command('1')
+ command('split')
+ command('/ol')
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ ^incididunt ut labore et d{1:ol}ore magna aliqua. |
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi ut aliquip ex |
+ ea commodo consequat. Duis aute irure d{1:ol}or in |
+ {2:[No Name] [+] }|
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing {3:el}it, sed do eiusmod tempor |
+ incididunt {4:ut} labore et d{1:ol}ore magna aliqua. |
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi {4:ut} aliquip ex |
+ {5:[No Name] [+] }|
+ |
+ ]])
+
+ feed('Obla bla <c-x><c-n>')
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ bla bla incididunt^ |
+ incidid{6:u}{7:incididunt}{6:re et}{8: }d{1:ol}ore magna aliqua. |
+ Ut enim{9: }{10:ut}{9: minim veniam}{6:,} quis nostrud |
+ exercit{9:a}{10:labore}{9:llamco la}{6:b}oris nisi ut aliquip ex |
+ {2:[No Nam}{11:e}{10:et}{11:[+] }{12: }{2: }|
+ Lorem i{9:p}{10:dolor}{13:e}{14:l}{9:or sit a}{6:m}et, consectetur |
+ adipisi{9:c}{10:magn}{15:a}{16:l}{9:it, sed d}{6:o} eiusmod tempor |
+ bla bla{9: }{10:aliqua}{9:dunt }{6: } |
+ incidid{9:u}{10:Ut}{9: }{17:ut}{9: labore et}{6: }d{1:ol}ore magna aliqua. |
+ Ut enim{9: }{10:enim}{9:inim veniam}{6:,} quis nostrud |
+ {5:[No Nam}{18:e}{10:ad}{18:[+] }{19: }{5: }|
+ {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
+ ]])
+
+ command('set pumblend=0')
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ bla bla incididunt^ |
+ incidid{22: incididunt }{23: }d{1:ol}ore magna aliqua. |
+ Ut enim{24: ut }{22: } quis nostrud |
+ exercit{24: labore }{22: }oris nisi ut aliquip ex |
+ {2:[No Nam}{24: et }{22: }{2: }|
+ Lorem i{24: dolore }{22: }et, consectetur |
+ adipisi{24: magna }{22: } eiusmod tempor |
+ bla bla{24: aliqua }{22: } |
+ incidid{24: Ut }{22: }d{1:ol}ore magna aliqua. |
+ Ut enim{24: enim }{22: } quis nostrud |
+ {5:[No Nam}{24: ad }{22: }{5: }|
+ {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
+ ]])
+
+ command('set pumblend=50')
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ bla bla incididunt^ |
+ incidid{25:u}{26:incididunt}{25:re et}{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}{31:et}{30:[+] }{32: }{2: }|
+ Lorem i{28:p}{29:dolor}{33:e}{34:l}{28:or sit a}{25:m}et, consectetur |
+ adipisi{28:c}{29:magn}{35:a}{36:l}{28:it, sed d}{25:o} eiusmod tempor |
+ bla bla{28: }{29:aliqua}{28:dunt }{25: } |
+ incidid{28:u}{29:Ut}{28: }{37:ut}{28: labore et}{25: }d{1:ol}ore magna aliqua. |
+ Ut enim{28: }{29:enim}{28:inim veniam}{25:,} quis nostrud |
+ {5:[No Nam}{38:e}{39:ad}{38:[+] }{40: }{5: }|
+ {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
+ ]])
+
+ meths.input_mouse('wheel', 'down', '', 0, 9, 40)
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ bla bla incididunt^ |
+ incidid{25:u}{26:incididunt}{25:re et}{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}{31: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}{39:ad}{38:[+] }{40: }{5: }|
+ {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
+ ]])
+
+ feed('<c-e>')
+ screen:expect([[
+ Lorem ipsum d{1:ol}or sit amet, consectetur |
+ adipisicing elit, sed do eiusmod tempor |
+ bla bla ^ |
+ incididunt ut labore et d{1:ol}ore magna aliqua. |
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi ut aliquip ex |
+ {2:[No Name] [+] }|
+ incididunt {4:ut} labore et d{1:ol}ore magna aliqua. |
+ Ut enim ad minim veniam, quis nostrud |
+ exercitation ullamco laboris nisi {4:ut} aliquip ex |
+ ea commodo consequat. Duis a{4:ut}e irure d{1:ol}or in |
+ reprehenderit in v{1:ol}uptate v{3:el}it esse cillum |
+ {5:[No Name] [+] }|
+ {20:-- INSERT --} |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 69f4a44dd8..038bf48839 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -1303,6 +1303,8 @@ function Screen:_pprint_attrs(attrs)
if f == "foreground" or f == "background" or f == "special" then
if Screen.colornames[v] ~= nil then
desc = "Screen.colors."..Screen.colornames[v]
+ else
+ desc = string.format("tonumber('0x%06x')",v)
end
end
table.insert(items, f.." = "..desc)