Merge pull request #9571 from bfredl/pum_transparent

UI: implement 'pumblend' option for semi-transparent popupmenu
This commit is contained in:
Björn Linse 2019-02-07 17:52:58 +01:00 committed by GitHub
commit fa2580f953
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 417 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -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

View File

@ -160,6 +160,8 @@ typedef enum {
kHlSyntax,
kHlTerminal,
kHlCombine,
kHlBlend,
kHlBlendThrough,
} HlKind;
typedef struct {

View File

@ -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;

View File

@ -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'

View File

@ -1805,6 +1805,14 @@ return {
varname='p_ph',
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'},

View File

@ -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.

View File

@ -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);

View File

@ -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,

View File

@ -18,6 +18,7 @@ describe('ui receives option updates', function()
guifontset='',
guifontwide='',
linespace=0,
pumblend=0,
showtabline=1,
termguicolors=false,
ext_cmdline=false,

View File

@ -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)

View File

@ -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)