mirror of
https://github.com/neovim/neovim
synced 2025-07-17 17:51:48 +00:00
decorations: add additional styling of virt_text overlays
This commit is contained in:
@ -1430,6 +1430,18 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
|
|||||||
/// - "eol": right after eol character (default)
|
/// - "eol": right after eol character (default)
|
||||||
/// - "overlay": display over the specified column, without
|
/// - "overlay": display over the specified column, without
|
||||||
/// shifting the underlying text.
|
/// shifting the underlying text.
|
||||||
|
/// - virt_text_hide : hide the virtual text when the background
|
||||||
|
/// text is selected or hidden due to
|
||||||
|
/// horizontal scroll 'nowrap'
|
||||||
|
/// - hl_mode : control how highlights are combined with the
|
||||||
|
/// highlights of the text. Currently only affects
|
||||||
|
/// virt_text highlights, but might affect `hl_group`
|
||||||
|
/// in later versions.
|
||||||
|
/// - "replace": only show the virt_text color. This is the
|
||||||
|
/// default
|
||||||
|
/// - "combine": combine with background text color
|
||||||
|
/// - "blend": blend with background text color.
|
||||||
|
///
|
||||||
/// - ephemeral : for use with |nvim_set_decoration_provider|
|
/// - ephemeral : for use with |nvim_set_decoration_provider|
|
||||||
/// callbacks. The mark will only be used for the current
|
/// callbacks. The mark will only be used for the current
|
||||||
/// redraw cycle, and not be permantently stored in the
|
/// redraw cycle, and not be permantently stored in the
|
||||||
@ -1477,11 +1489,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
bool ephemeral = false;
|
bool ephemeral = false;
|
||||||
|
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
int line2 = -1, hl_id = 0;
|
int line2 = -1;
|
||||||
DecorPriority priority = DECOR_PRIORITY_BASE;
|
Decoration decor = DECORATION_INIT;
|
||||||
colnr_T col2 = -1;
|
colnr_T col2 = -1;
|
||||||
VirtText virt_text = KV_INITIAL_VALUE;
|
|
||||||
VirtTextPos virt_text_pos = kVTEndOfLine;
|
|
||||||
bool right_gravity = true;
|
bool right_gravity = true;
|
||||||
bool end_right_gravity = false;
|
bool end_right_gravity = false;
|
||||||
bool end_gravity_set = false;
|
bool end_gravity_set = false;
|
||||||
@ -1528,12 +1539,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case kObjectTypeString:
|
case kObjectTypeString:
|
||||||
hl_group = v->data.string;
|
hl_group = v->data.string;
|
||||||
hl_id = syn_check_group(
|
decor.hl_id = syn_check_group(
|
||||||
(char_u *)(hl_group.data),
|
(char_u *)(hl_group.data),
|
||||||
(int)hl_group.size);
|
(int)hl_group.size);
|
||||||
break;
|
break;
|
||||||
case kObjectTypeInteger:
|
case kObjectTypeInteger:
|
||||||
hl_id = (int)v->data.integer;
|
decor.hl_id = (int)v->data.integer;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
api_set_error(err, kErrorTypeValidation,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
@ -1546,7 +1557,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
"virt_text is not an Array");
|
"virt_text is not an Array");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
virt_text = parse_virt_text(v->data.array, err);
|
decor.virt_text = parse_virt_text(v->data.array, err);
|
||||||
if (ERROR_SET(err)) {
|
if (ERROR_SET(err)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1558,9 +1569,33 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
}
|
}
|
||||||
String str = v->data.string;
|
String str = v->data.string;
|
||||||
if (strequal("eol", str.data)) {
|
if (strequal("eol", str.data)) {
|
||||||
virt_text_pos = kVTEndOfLine;
|
decor.virt_text_pos = kVTEndOfLine;
|
||||||
} else if (strequal("overlay", str.data)) {
|
} else if (strequal("overlay", str.data)) {
|
||||||
virt_text_pos = kVTOverlay;
|
decor.virt_text_pos = kVTOverlay;
|
||||||
|
} else {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"virt_text_pos: invalid value");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (strequal("virt_text_hide", k.data)) {
|
||||||
|
decor.virt_text_hide = api_object_to_bool(*v,
|
||||||
|
"virt_text_hide", false, err);
|
||||||
|
if (ERROR_SET(err)) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (strequal("hl_mode", k.data)) {
|
||||||
|
if (v->type != kObjectTypeString) {
|
||||||
|
api_set_error(err, kErrorTypeValidation,
|
||||||
|
"hl_mode is not a String");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
String str = v->data.string;
|
||||||
|
if (strequal("replace", str.data)) {
|
||||||
|
decor.hl_mode = kHlModeReplace;
|
||||||
|
} else if (strequal("combine", str.data)) {
|
||||||
|
decor.hl_mode = kHlModeCombine;
|
||||||
|
} else if (strequal("blend", str.data)) {
|
||||||
|
decor.hl_mode = kHlModeBlend;
|
||||||
} else {
|
} else {
|
||||||
api_set_error(err, kErrorTypeValidation,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
"virt_text_pos: invalid value");
|
"virt_text_pos: invalid value");
|
||||||
@ -1583,7 +1618,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
"priority is not a valid value");
|
"priority is not a valid value");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
priority = (DecorPriority)v->data.integer;
|
decor.priority = (DecorPriority)v->data.integer;
|
||||||
} else if (strequal("right_gravity", k.data)) {
|
} else if (strequal("right_gravity", k.data)) {
|
||||||
if (v->type != kObjectTypeBoolean) {
|
if (v->type != kObjectTypeBoolean) {
|
||||||
api_set_error(err, kErrorTypeValidation,
|
api_set_error(err, kErrorTypeValidation,
|
||||||
@ -1631,23 +1666,23 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
col2 = 0;
|
col2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoration *decor = NULL, tmp = { 0 };
|
Decoration *d = NULL;
|
||||||
|
|
||||||
if (kv_size(virt_text) || priority != DECOR_PRIORITY_BASE) {
|
if (ephemeral) {
|
||||||
|
d = &decor;
|
||||||
|
} else if (kv_size(decor.virt_text)
|
||||||
|
|| decor.priority != DECOR_PRIORITY_BASE) {
|
||||||
// TODO(bfredl): this is a bit sketchy. eventually we should
|
// TODO(bfredl): this is a bit sketchy. eventually we should
|
||||||
// have predefined decorations for both marks/ephemerals
|
// have predefined decorations for both marks/ephemerals
|
||||||
decor = ephemeral ? &tmp : xcalloc(1, sizeof(*decor));
|
d = xcalloc(1, sizeof(*d));
|
||||||
decor->hl_id = hl_id;
|
*d = decor;
|
||||||
decor->virt_text = virt_text;
|
} else if (decor.hl_id) {
|
||||||
decor->priority = priority;
|
d = decor_hl(decor.hl_id);
|
||||||
decor->virt_text_pos = virt_text_pos;
|
|
||||||
} else if (hl_id) {
|
|
||||||
decor = decor_hl(hl_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bfredl): synergize these two branches even more
|
// TODO(bfredl): synergize these two branches even more
|
||||||
if (ephemeral && decor_state.buf == buf) {
|
if (ephemeral && decor_state.buf == buf) {
|
||||||
decor_add_ephemeral((int)line, (int)col, line2, col2, decor, 0);
|
decor_add_ephemeral((int)line, (int)col, line2, col2, &decor, 0);
|
||||||
} else {
|
} else {
|
||||||
if (ephemeral) {
|
if (ephemeral) {
|
||||||
api_set_error(err, kErrorTypeException, "not yet implemented");
|
api_set_error(err, kErrorTypeException, "not yet implemented");
|
||||||
@ -1655,14 +1690,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
|
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
|
||||||
line2, col2, decor, right_gravity,
|
line2, col2, d, right_gravity,
|
||||||
end_right_gravity, kExtmarkNoUndo);
|
end_right_gravity, kExtmarkNoUndo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Integer)id;
|
return (Integer)id;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
clear_virttext(&virt_text);
|
clear_virttext(&decor.virt_text);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ static void decor_add(DecorState *state, int start_row, int start_col,
|
|||||||
HlRange range = { start_row, start_col, end_row, end_col,
|
HlRange range = { start_row, start_col, end_row, end_col,
|
||||||
attr_id, MAX(priority, decor->priority),
|
attr_id, MAX(priority, decor->priority),
|
||||||
kv_size(decor->virt_text) ? &decor->virt_text : NULL,
|
kv_size(decor->virt_text) ? &decor->virt_text : NULL,
|
||||||
decor->virt_text_pos,
|
decor->virt_text_pos, decor->virt_text_hide, decor->hl_mode,
|
||||||
kv_size(decor->virt_text) && owned, -1 };
|
kv_size(decor->virt_text) && owned, -1 };
|
||||||
|
|
||||||
kv_pushp(state->active);
|
kv_pushp(state->active);
|
||||||
@ -245,7 +245,8 @@ static void decor_add(DecorState *state, int start_row, int start_col,
|
|||||||
kv_A(state->active, index) = range;
|
kv_A(state->active, index) = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decor_redraw_col(buf_T *buf, int col, int virt_col, DecorState *state)
|
int decor_redraw_col(buf_T *buf, int col, int virt_col, bool hidden,
|
||||||
|
DecorState *state)
|
||||||
{
|
{
|
||||||
if (col <= state->col_until) {
|
if (col <= state->col_until) {
|
||||||
return state->current;
|
return state->current;
|
||||||
@ -324,7 +325,7 @@ next_mark:
|
|||||||
}
|
}
|
||||||
if ((item.start_row == state->row && item.start_col <= col)
|
if ((item.start_row == state->row && item.start_col <= col)
|
||||||
&& item.virt_text && item.virt_col == -1) {
|
&& item.virt_text && item.virt_col == -1) {
|
||||||
item.virt_col = virt_col;
|
item.virt_col = (item.virt_text_hide && hidden) ? -2 : virt_col;
|
||||||
}
|
}
|
||||||
if (keep) {
|
if (keep) {
|
||||||
kv_A(state->active, j++) = item;
|
kv_A(state->active, j++) = item;
|
||||||
@ -345,7 +346,7 @@ void decor_redraw_end(DecorState *state)
|
|||||||
|
|
||||||
VirtText *decor_redraw_virt_text(buf_T *buf, DecorState *state)
|
VirtText *decor_redraw_virt_text(buf_T *buf, DecorState *state)
|
||||||
{
|
{
|
||||||
decor_redraw_col(buf, MAXCOL, MAXCOL, state);
|
decor_redraw_col(buf, MAXCOL, MAXCOL, false, state);
|
||||||
for (size_t i = 0; i < kv_size(state->active); i++) {
|
for (size_t i = 0; i < kv_size(state->active); i++) {
|
||||||
HlRange item = kv_A(state->active, i);
|
HlRange item = kv_A(state->active, i);
|
||||||
if (item.start_row == state->row && item.virt_text
|
if (item.start_row == state->row && item.virt_text
|
||||||
|
@ -23,15 +23,26 @@ typedef enum {
|
|||||||
kVTOverlay,
|
kVTOverlay,
|
||||||
} VirtTextPos;
|
} VirtTextPos;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
kHlModeUnknown,
|
||||||
|
kHlModeReplace,
|
||||||
|
kHlModeCombine,
|
||||||
|
kHlModeBlend,
|
||||||
|
} HlMode;
|
||||||
|
|
||||||
struct Decoration
|
struct Decoration
|
||||||
{
|
{
|
||||||
int hl_id; // highlight group
|
int hl_id; // highlight group
|
||||||
VirtText virt_text;
|
VirtText virt_text;
|
||||||
VirtTextPos virt_text_pos;
|
VirtTextPos virt_text_pos;
|
||||||
|
bool virt_text_hide;
|
||||||
|
HlMode hl_mode;
|
||||||
// TODO(bfredl): style, signs, etc
|
// TODO(bfredl): style, signs, etc
|
||||||
DecorPriority priority;
|
DecorPriority priority;
|
||||||
bool shared; // shared decoration, don't free
|
bool shared; // shared decoration, don't free
|
||||||
};
|
};
|
||||||
|
#define DECORATION_INIT { 0, KV_INITIAL_VALUE, kVTEndOfLine, false, \
|
||||||
|
kHlModeUnknown, DECOR_PRIORITY_BASE, false }
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int start_row;
|
int start_row;
|
||||||
@ -39,9 +50,13 @@ typedef struct {
|
|||||||
int end_row;
|
int end_row;
|
||||||
int end_col;
|
int end_col;
|
||||||
int attr_id;
|
int attr_id;
|
||||||
|
// TODO(bfredl): embed decoration instead, perhaps using an arena
|
||||||
|
// for ephemerals?
|
||||||
DecorPriority priority;
|
DecorPriority priority;
|
||||||
VirtText *virt_text;
|
VirtText *virt_text;
|
||||||
VirtTextPos virt_text_pos;
|
VirtTextPos virt_text_pos;
|
||||||
|
bool virt_text_hide;
|
||||||
|
HlMode hl_mode;
|
||||||
bool virt_text_owned;
|
bool virt_text_owned;
|
||||||
int virt_col;
|
int virt_col;
|
||||||
} HlRange;
|
} HlRange;
|
||||||
|
@ -2096,6 +2096,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
|
|
||||||
char_u buf_fold[FOLD_TEXT_LEN + 1]; // Hold value returned by get_foldtext
|
char_u buf_fold[FOLD_TEXT_LEN + 1]; // Hold value returned by get_foldtext
|
||||||
|
|
||||||
|
bool area_active = false;
|
||||||
|
|
||||||
/* draw_state: items that are drawn in sequence: */
|
/* draw_state: items that are drawn in sequence: */
|
||||||
#define WL_START 0 /* nothing done yet */
|
#define WL_START 0 /* nothing done yet */
|
||||||
# define WL_CMDLINE WL_START + 1 /* cmdline window column */
|
# define WL_CMDLINE WL_START + 1 /* cmdline window column */
|
||||||
@ -2850,6 +2852,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
if (draw_state == WL_LINE - 1 && n_extra == 0) {
|
if (draw_state == WL_LINE - 1 && n_extra == 0) {
|
||||||
sign_idx = 0;
|
sign_idx = 0;
|
||||||
draw_state = WL_LINE;
|
draw_state = WL_LINE;
|
||||||
|
|
||||||
|
if (has_decor && row == startrow + filler_lines) {
|
||||||
|
// hide virt_text on text hidden by 'nowrap'
|
||||||
|
decor_redraw_col(wp->w_buffer, vcol, off, true, &decor_state);
|
||||||
|
}
|
||||||
|
|
||||||
if (saved_n_extra) {
|
if (saved_n_extra) {
|
||||||
/* Continue item from end of wrapped line. */
|
/* Continue item from end of wrapped line. */
|
||||||
n_extra = saved_n_extra;
|
n_extra = saved_n_extra;
|
||||||
@ -2934,10 +2942,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
&& vcol_prev < vcol // not at margin
|
&& vcol_prev < vcol // not at margin
|
||||||
&& vcol < tocol)) {
|
&& vcol < tocol)) {
|
||||||
area_attr = attr; // start highlighting
|
area_attr = attr; // start highlighting
|
||||||
|
if (area_highlighting) {
|
||||||
|
area_active = true;
|
||||||
|
}
|
||||||
} else if (area_attr != 0 && (vcol == tocol
|
} else if (area_attr != 0 && (vcol == tocol
|
||||||
|| (noinvcur
|
|| (noinvcur
|
||||||
&& (colnr_T)vcol == wp->w_virtcol))) {
|
&& (colnr_T)vcol == wp->w_virtcol))) {
|
||||||
area_attr = 0; // stop highlighting
|
area_attr = 0; // stop highlighting
|
||||||
|
area_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!n_extra) {
|
if (!n_extra) {
|
||||||
@ -3397,9 +3409,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
char_attr = hl_combine_attr(spell_attr, char_attr);
|
char_attr = hl_combine_attr(spell_attr, char_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wp->w_buffer->terminal) {
|
||||||
|
char_attr = hl_combine_attr(term_attrs[vcol], char_attr);
|
||||||
|
}
|
||||||
|
|
||||||
if (has_decor && v > 0) {
|
if (has_decor && v > 0) {
|
||||||
|
bool selected = (area_active || (area_highlighting && noinvcur
|
||||||
|
&& (colnr_T)vcol == wp->w_virtcol));
|
||||||
int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, off,
|
int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, off,
|
||||||
&decor_state);
|
selected, &decor_state);
|
||||||
if (extmark_attr != 0) {
|
if (extmark_attr != 0) {
|
||||||
if (!attr_pri) {
|
if (!attr_pri) {
|
||||||
char_attr = hl_combine_attr(char_attr, extmark_attr);
|
char_attr = hl_combine_attr(char_attr, extmark_attr);
|
||||||
@ -3409,10 +3427,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wp->w_buffer->terminal) {
|
|
||||||
char_attr = hl_combine_attr(term_attrs[vcol], char_attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Found last space before word: check for line break.
|
// Found last space before word: check for line break.
|
||||||
if (wp->w_p_lbr && c0 == c && vim_isbreak(c)
|
if (wp->w_p_lbr && c0 == c && vim_isbreak(c)
|
||||||
&& !vim_isbreak((int)(*ptr))) {
|
&& !vim_isbreak((int)(*ptr))) {
|
||||||
@ -4355,10 +4369,22 @@ void draw_virt_text(buf_T *buf, int *end_col, int max_col)
|
|||||||
virt_pos++;
|
virt_pos++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int cells = line_putchar(&s, &linebuf_char[col], 2, false);
|
int attr;
|
||||||
linebuf_attr[col++] = virt_attr;
|
bool through = false;
|
||||||
|
if (item->hl_mode == kHlModeCombine) {
|
||||||
|
attr = hl_combine_attr(linebuf_attr[col], virt_attr);
|
||||||
|
} else if (item->hl_mode == kHlModeBlend) {
|
||||||
|
through = (*s.p == ' ');
|
||||||
|
attr = hl_blend_attrs(linebuf_attr[col], virt_attr, &through);
|
||||||
|
} else {
|
||||||
|
attr = virt_attr;
|
||||||
|
}
|
||||||
|
schar_T dummy[2];
|
||||||
|
int cells = line_putchar(&s, through ? dummy : &linebuf_char[col],
|
||||||
|
max_col-col, false);
|
||||||
|
linebuf_attr[col++] = attr;
|
||||||
if (cells > 1) {
|
if (cells > 1) {
|
||||||
linebuf_attr[col++] = virt_attr;
|
linebuf_attr[col++] = attr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*end_col = MAX(*end_col, col);
|
*end_col = MAX(*end_col, col);
|
||||||
|
@ -8,6 +8,7 @@ local exec_lua = helpers.exec_lua
|
|||||||
local exec = helpers.exec
|
local exec = helpers.exec
|
||||||
local expect_events = helpers.expect_events
|
local expect_events = helpers.expect_events
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
|
local command = helpers.command
|
||||||
|
|
||||||
describe('decorations providers', function()
|
describe('decorations providers', function()
|
||||||
local screen
|
local screen
|
||||||
@ -314,11 +315,30 @@ describe('extmark decorations', function()
|
|||||||
[2] = {foreground = Screen.colors.Brown};
|
[2] = {foreground = Screen.colors.Brown};
|
||||||
[3] = {bold = true, foreground = Screen.colors.SeaGreen};
|
[3] = {bold = true, foreground = Screen.colors.SeaGreen};
|
||||||
[4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
|
[4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
|
||||||
|
[5] = {foreground = Screen.colors.Brown, bold = true};
|
||||||
|
[6] = {foreground = Screen.colors.DarkCyan};
|
||||||
|
[7] = {foreground = Screen.colors.Grey0, background = tonumber('0xff4c4c')};
|
||||||
|
[8] = {foreground = tonumber('0x180606'), background = tonumber('0xff4c4c')};
|
||||||
|
[9] = {foreground = tonumber('0xe40c0c'), background = tonumber('0xff4c4c'), bold = true};
|
||||||
|
[10] = {foreground = tonumber('0xb20000'), background = tonumber('0xff4c4c')};
|
||||||
|
[11] = {blend = 30, background = Screen.colors.Red1};
|
||||||
|
[12] = {foreground = Screen.colors.Brown, blend = 30, background = Screen.colors.Red1, bold = true};
|
||||||
|
[13] = {foreground = Screen.colors.Fuchsia};
|
||||||
|
[14] = {background = Screen.colors.Red1, foreground = Screen.colors.Black};
|
||||||
|
[15] = {background = Screen.colors.Red1, foreground = tonumber('0xb20000')};
|
||||||
|
[16] = {blend = 30, background = Screen.colors.Red1, foreground = Screen.colors.Magenta1};
|
||||||
|
[17] = {bold = true, foreground = Screen.colors.Brown, background = Screen.colors.LightGrey};
|
||||||
|
[18] = {background = Screen.colors.LightGrey};
|
||||||
|
[19] = {foreground = Screen.colors.Cyan4, background = Screen.colors.LightGrey};
|
||||||
|
[20] = {foreground = tonumber('0x180606'), background = tonumber('0xf13f3f')};
|
||||||
|
[21] = {foreground = Screen.colors.Gray0, background = tonumber('0xf13f3f')};
|
||||||
|
[22] = {foreground = tonumber('0xb20000'), background = tonumber('0xf13f3f')};
|
||||||
|
[23] = {foreground = Screen.colors.Magenta1, background = Screen.colors.LightGrey};
|
||||||
|
[24] = {bold = true};
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('can have virtual text of overlay style', function()
|
local example_text = [[
|
||||||
insert [[
|
|
||||||
for _,item in ipairs(items) do
|
for _,item in ipairs(items) do
|
||||||
local text, hl_id_cell, count = unpack(item)
|
local text, hl_id_cell, count = unpack(item)
|
||||||
if hl_id_cell ~= nil then
|
if hl_id_cell ~= nil then
|
||||||
@ -331,69 +351,164 @@ for _,item in ipairs(items) do
|
|||||||
colpos = colpos+1
|
colpos = colpos+1
|
||||||
end
|
end
|
||||||
end]]
|
end]]
|
||||||
feed 'gg'
|
|
||||||
|
|
||||||
local ns = meths.create_namespace 'test'
|
it('can have virtual text of overlay position', function()
|
||||||
for i = 1,9 do
|
insert(example_text)
|
||||||
meths.buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
|
feed 'gg'
|
||||||
if i == 3 or (i >= 6 and i <= 9) then
|
|
||||||
meths.buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
|
local ns = meths.create_namespace 'test'
|
||||||
|
for i = 1,9 do
|
||||||
|
meths.buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
|
||||||
|
if i == 3 or (i >= 6 and i <= 9) then
|
||||||
|
meths.buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
meths.buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
||||||
meths.buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
|
||||||
|
|
||||||
-- can "float" beyond end of line
|
-- can "float" beyond end of line
|
||||||
meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
||||||
-- bound check: right edge of window
|
-- bound check: right edge of window
|
||||||
meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork ' }, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork ' }, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
||||||
|
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
^for _,item in ipairs(items) do |
|
^for _,item in ipairs(items) do |
|
||||||
{2:|} local text, hl_id_cell, count = unpack(item) |
|
{2:|} local text, hl_id_cell, count = unpack(item) |
|
||||||
{2:|} if hl_id_cell ~= nil tbork bork bork {4:bork bork}|
|
{2:|} if hl_id_cell ~= nil tbork bork bork {4:bork bork}|
|
||||||
{2:|} {1:|} hl_id = hl_id_cell |
|
{2:|} {1:|} hl_id = hl_id_cell |
|
||||||
{2:|} end |
|
{2:|} end |
|
||||||
{2:|} for _ = 1, (count or 1) {4:loopy} |
|
{2:|} for _ = 1, (count or 1) {4:loopy} |
|
||||||
{2:|} {1:|} local cell = line[colpos] |
|
{2:|} {1:|} local cell = line[colpos] |
|
||||||
{2:|} {1:|} cell.text = text |
|
{2:|} {1:|} cell.text = text |
|
||||||
{2:|} {1:|} cell.hl_id = hl_id |
|
{2:|} {1:|} cell.hl_id = hl_id |
|
||||||
{2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
|
{2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
|
||||||
end |
|
end |
|
||||||
end |
|
end |
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
|
|
||||||
|
|
||||||
-- handles broken lines
|
-- handles broken lines
|
||||||
screen:try_resize(22, 25)
|
screen:try_resize(22, 25)
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
^for _,item in ipairs(i|
|
^for _,item in ipairs(i|
|
||||||
tems) do |
|
tems) do |
|
||||||
{2:|} local text, hl_id_|
|
{2:|} local text, hl_id_|
|
||||||
cell, count = unpack(i|
|
cell, count = unpack(i|
|
||||||
tem) |
|
tem) |
|
||||||
{2:|} if hl_id_cell ~= n|
|
{2:|} if hl_id_cell ~= n|
|
||||||
il tbork bork bork {4:bor}|
|
il tbork bork bork {4:bor}|
|
||||||
{2:|} {1:|} hl_id = hl_id_|
|
{2:|} {1:|} hl_id = hl_id_|
|
||||||
cell |
|
cell |
|
||||||
{2:|} end |
|
{2:|} end |
|
||||||
{2:|} for _ = 1, (count |
|
{2:|} for _ = 1, (count |
|
||||||
or 1) {4:loopy} |
|
or 1) {4:loopy} |
|
||||||
{2:|} {1:|} local cell = l|
|
{2:|} {1:|} local cell = l|
|
||||||
ine[colpos] |
|
ine[colpos] |
|
||||||
{2:|} {1:|} cell.text = te|
|
{2:|} {1:|} cell.text = te|
|
||||||
xt |
|
xt |
|
||||||
{2:|} {1:|} cell.hl_id = h|
|
{2:|} {1:|} cell.hl_id = h|
|
||||||
l_id |
|
l_id |
|
||||||
{2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
|
{2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
|
||||||
s+1 |
|
s+1 |
|
||||||
end |
|
end |
|
||||||
end |
|
end |
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
{1:~ }|
|
{1:~ }|
|
||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can have virtual text of overlay position and styling', function()
|
||||||
|
insert(example_text)
|
||||||
|
feed 'gg'
|
||||||
|
local ns = meths.create_namespace 'test'
|
||||||
|
|
||||||
|
command 'set ft=lua'
|
||||||
|
command 'syntax on'
|
||||||
|
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{5:^for} _,item {5:in} {6:ipairs}(items) {5:do} |
|
||||||
|
{5:local} text, hl_id_cell, count = unpack(item) |
|
||||||
|
{5:if} hl_id_cell ~= {13:nil} {5:then} |
|
||||||
|
hl_id = hl_id_cell |
|
||||||
|
{5:end} |
|
||||||
|
{5:for} _ = {13:1}, (count {5:or} {13:1}) {5:do} |
|
||||||
|
{5:local} cell = line[colpos] |
|
||||||
|
cell.text = text |
|
||||||
|
cell.hl_id = hl_id |
|
||||||
|
colpos = colpos+{13:1} |
|
||||||
|
{5:end} |
|
||||||
|
{5:end} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
command 'hi Blendy guibg=Red blend=30'
|
||||||
|
meths.buf_set_extmark(0, ns, 1, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend'})
|
||||||
|
meths.buf_set_extmark(0, ns, 2, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine'})
|
||||||
|
meths.buf_set_extmark(0, ns, 3, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace'})
|
||||||
|
|
||||||
|
meths.buf_set_extmark(0, ns, 4, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend', virt_text_hide=true})
|
||||||
|
meths.buf_set_extmark(0, ns, 5, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine', virt_text_hide=true})
|
||||||
|
meths.buf_set_extmark(0, ns, 6, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace', virt_text_hide=true})
|
||||||
|
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{5:^for} _,item {5:in} {6:ipairs}(items) {5:do} |
|
||||||
|
{5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count = unpack(item) |
|
||||||
|
{5:i}{12:c}{11:ombining color} {13:nil} {5:then} |
|
||||||
|
{11:replacing color}d_cell |
|
||||||
|
{5:e}{8:bl}{14:endy}{15:i}{14:text}{15:o}{14:-}{15:o}{14:h}{7:ere} |
|
||||||
|
{5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
|
||||||
|
{11:replacing color} line[colpos] |
|
||||||
|
cell.text = text |
|
||||||
|
cell.hl_id = hl_id |
|
||||||
|
colpos = colpos+{13:1} |
|
||||||
|
{5:end} |
|
||||||
|
{5:end} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
|
||||||
|
feed 'V5G'
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} |
|
||||||
|
{18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count = unpack(item)} |
|
||||||
|
{18: }{17:i}{12:c}{11:ombining color}{18: }{23:nil}{18: }{17:then} |
|
||||||
|
{18: }{11:replacing color}{18:d_cell} |
|
||||||
|
{18: }{5:^e}{17:nd} |
|
||||||
|
{5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
|
||||||
|
{11:replacing color} line[colpos] |
|
||||||
|
cell.text = text |
|
||||||
|
cell.hl_id = hl_id |
|
||||||
|
colpos = colpos+{13:1} |
|
||||||
|
{5:end} |
|
||||||
|
{5:end} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{24:-- VISUAL LINE --} |
|
||||||
|
]]}
|
||||||
|
|
||||||
|
feed 'jj'
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} |
|
||||||
|
{18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count = unpack(item)} |
|
||||||
|
{18: }{17:i}{12:c}{11:ombining color}{18: }{23:nil}{18: }{17:then} |
|
||||||
|
{18: }{11:replacing color}{18:d_cell} |
|
||||||
|
{18: }{17:end} |
|
||||||
|
{18: }{17:for}{18: _ = }{23:1}{18:, (count }{17:or}{18: }{23:1}{18:) }{17:do} |
|
||||||
|
{18: }^ {18: }{17:local}{18: cell = line[colpos]} |
|
||||||
|
cell.text = text |
|
||||||
|
cell.hl_id = hl_id |
|
||||||
|
colpos = colpos+{13:1} |
|
||||||
|
{5:end} |
|
||||||
|
{5:end} |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{24:-- VISUAL LINE --} |
|
||||||
|
]]}
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
Reference in New Issue
Block a user