mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
Merge pull request #8180 from bfredl/eol_text
support "virtual text" annotations (currently after EOL only)
This commit is contained in:
commit
8de87c7b1c
@ -967,6 +967,85 @@ void nvim_buf_clear_highlight(Buffer buffer,
|
||||
bufhl_clear_line_range(buf, (int)src_id, (int)line_start+1, (int)line_end);
|
||||
}
|
||||
|
||||
|
||||
/// Set the virtual text (annotation) for a buffer line.
|
||||
///
|
||||
/// By default (and currently the only option) the text will be placed after
|
||||
/// the buffer text. Virtual text will never cause reflow, rather virtual
|
||||
/// text will be truncated at the end of the screen line. The virtual text will
|
||||
/// begin after one cell to the right of the ordinary text, this will contain
|
||||
/// the |lcs-eol| char if set, otherwise just be a space.
|
||||
///
|
||||
/// @param buffer Buffer handle
|
||||
/// @param src_id Source group to use or 0 to use a new group,
|
||||
/// or -1 for a ungrouped annotation
|
||||
/// @param line Line to annotate with virtual text (zero-indexed)
|
||||
/// @param chunks A list of [text, hl_group] arrays, each representing a
|
||||
/// text chunk with specified highlight. `hl_group` element
|
||||
/// can be omitted for no highlight.
|
||||
/// @param opts Optional parameters. Currently not used.
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return The src_id that was used
|
||||
Integer nvim_buf_set_virtual_text(Buffer buffer,
|
||||
Integer src_id,
|
||||
Integer line,
|
||||
Array chunks,
|
||||
Dictionary opts,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(5)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (line < 0 || line >= MAXLNUM) {
|
||||
api_set_error(err, kErrorTypeValidation, "Line number outside range");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.size > 0) {
|
||||
api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
VirtText virt_text = KV_INITIAL_VALUE;
|
||||
for (size_t i = 0; i < chunks.size; i++) {
|
||||
if (chunks.items[i].type != kObjectTypeArray) {
|
||||
api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
|
||||
goto free_exit;
|
||||
}
|
||||
Array chunk = chunks.items[i].data.array;
|
||||
if (chunk.size == 0 || chunk.size > 2
|
||||
|| chunk.items[0].type != kObjectTypeString
|
||||
|| (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Chunk is not an array with one or two strings");
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
String str = chunk.items[0].data.string;
|
||||
char *text = xstrdup(str.size > 0 ? str.data : "");
|
||||
|
||||
int hl_id = 0;
|
||||
if (chunk.size == 2) {
|
||||
String hl = chunk.items[1].data.string;
|
||||
if (hl.size > 0) {
|
||||
hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
|
||||
}
|
||||
}
|
||||
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
|
||||
}
|
||||
|
||||
src_id = bufhl_add_virt_text(buf, (int)src_id, (linenr_T)line+1,
|
||||
virt_text);
|
||||
return src_id;
|
||||
|
||||
free_exit:
|
||||
kv_destroy(virt_text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if deleting lines made the cursor position invalid.
|
||||
// Changed the lines from "lo" to "hi" and added "extra" lines (negative if
|
||||
// deleted).
|
||||
|
@ -5375,6 +5375,45 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
|
||||
}
|
||||
}
|
||||
|
||||
int bufhl_add_virt_text(buf_T *buf,
|
||||
int src_id,
|
||||
linenr_T lnum,
|
||||
VirtText virt_text)
|
||||
{
|
||||
static int next_src_id = 1;
|
||||
if (src_id == 0) {
|
||||
src_id = next_src_id++;
|
||||
}
|
||||
|
||||
BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, true);
|
||||
|
||||
bufhl_clear_virttext(&lineinfo->virt_text);
|
||||
if (kv_size(virt_text) > 0) {
|
||||
lineinfo->virt_text_src = src_id;
|
||||
lineinfo->virt_text = virt_text;
|
||||
} else {
|
||||
lineinfo->virt_text_src = 0;
|
||||
// currently not needed, but allow a future caller with
|
||||
// 0 size and non-zero capacity
|
||||
kv_destroy(virt_text);
|
||||
}
|
||||
|
||||
if (0 < lnum && lnum <= buf->b_ml.ml_line_count) {
|
||||
changed_lines_buf(buf, lnum, lnum+1, 0);
|
||||
redraw_buf_later(buf, VALID);
|
||||
}
|
||||
return src_id;
|
||||
}
|
||||
|
||||
static void bufhl_clear_virttext(VirtText *text)
|
||||
{
|
||||
for (size_t i = 0; i < kv_size(*text); i++) {
|
||||
xfree(kv_A(*text, i).text);
|
||||
}
|
||||
kv_destroy(*text);
|
||||
*text = (VirtText)KV_INITIAL_VALUE;
|
||||
}
|
||||
|
||||
/// Clear bufhl highlights from a given source group and range of lines.
|
||||
///
|
||||
/// @param buf The buffer to remove highlights from
|
||||
@ -5430,6 +5469,7 @@ void bufhl_clear_line_range(buf_T *buf,
|
||||
static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id,
|
||||
linenr_T lnum)
|
||||
{
|
||||
BufhlLineStatus changed = kBLSUnchanged;
|
||||
size_t oldsize = kv_size(lineinfo->items);
|
||||
if (src_id < 0) {
|
||||
kv_size(lineinfo->items) = 0;
|
||||
@ -5445,14 +5485,25 @@ static BufhlLineStatus bufhl_clear_line(BufhlLine *lineinfo, int src_id,
|
||||
}
|
||||
kv_size(lineinfo->items) = newidx;
|
||||
}
|
||||
if (kv_size(lineinfo->items) != oldsize) {
|
||||
changed = kBLSChanged;
|
||||
}
|
||||
|
||||
if (kv_size(lineinfo->items) == 0) {
|
||||
if (kv_size(lineinfo->virt_text) != 0
|
||||
&& (src_id < 0 || src_id == lineinfo->virt_text_src)) {
|
||||
bufhl_clear_virttext(&lineinfo->virt_text);
|
||||
lineinfo->virt_text_src = 0;
|
||||
changed = kBLSChanged;
|
||||
}
|
||||
|
||||
if (kv_size(lineinfo->items) == 0 && kv_size(lineinfo->virt_text) == 0) {
|
||||
kv_destroy(lineinfo->items);
|
||||
return kBLSDeleted;
|
||||
}
|
||||
return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged;
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
/// Remove all highlights and free the highlight data
|
||||
void bufhl_clear_all(buf_T *buf)
|
||||
{
|
||||
@ -5527,8 +5578,8 @@ bool bufhl_start_line(buf_T *buf, linenr_T lnum, BufhlLineInfo *info)
|
||||
return false;
|
||||
}
|
||||
info->valid_to = -1;
|
||||
info->entries = lineinfo->items;
|
||||
return kv_size(info->entries) > 0;
|
||||
info->line = lineinfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// get highlighting at column col
|
||||
@ -5548,8 +5599,8 @@ int bufhl_get_attr(BufhlLineInfo *info, colnr_T col)
|
||||
}
|
||||
int attr = 0;
|
||||
info->valid_to = MAXCOL;
|
||||
for (size_t i = 0; i < kv_size(info->entries); i++) {
|
||||
BufhlItem entry = kv_A(info->entries, i);
|
||||
for (size_t i = 0; i < kv_size(info->line->items); i++) {
|
||||
BufhlItem entry = kv_A(info->line->items, i);
|
||||
if (entry.start <= col && col <= entry.stop) {
|
||||
int entry_attr = syn_id2attr(entry.hl_id);
|
||||
attr = hl_combine_attr(attr, entry_attr);
|
||||
|
@ -14,16 +14,23 @@ typedef struct {
|
||||
colnr_T stop; // last column to highlight
|
||||
} BufhlItem;
|
||||
|
||||
typedef kvec_t(BufhlItem) BufhlItemVec;
|
||||
typedef struct {
|
||||
char *text;
|
||||
int hl_id;
|
||||
} VirtTextChunk;
|
||||
|
||||
typedef kvec_t(VirtTextChunk) VirtText;
|
||||
|
||||
typedef struct {
|
||||
linenr_T line;
|
||||
BufhlItemVec items;
|
||||
kvec_t(BufhlItem) items;
|
||||
int virt_text_src;
|
||||
VirtText virt_text;
|
||||
} BufhlLine;
|
||||
#define BUFHLLINE_INIT(l) { l, KV_INITIAL_VALUE }
|
||||
#define BUFHLLINE_INIT(l) { l, KV_INITIAL_VALUE, 0, KV_INITIAL_VALUE }
|
||||
|
||||
typedef struct {
|
||||
BufhlItemVec entries;
|
||||
BufhlLine *line;
|
||||
int current;
|
||||
colnr_T valid_to;
|
||||
} BufhlLineInfo;
|
||||
|
@ -132,6 +132,15 @@ static schar_T *current_ScreenLine;
|
||||
StlClickDefinition *tab_page_click_defs = NULL;
|
||||
long tab_page_click_defs_size = 0;
|
||||
|
||||
// for line_putchar. Contains the state that needs to be remembered from
|
||||
// putting one character to the next.
|
||||
typedef struct {
|
||||
const char_u *p;
|
||||
int prev_c; // previous Arabic character
|
||||
int prev_c1; // first composing char for prev_c
|
||||
} LineState;
|
||||
#define LINE_STATE(p) { p, 0, 0 }
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "screen.c.generated.h"
|
||||
#endif
|
||||
@ -1731,6 +1740,56 @@ static int compute_foldcolumn(win_T *wp, int col)
|
||||
return fdc;
|
||||
}
|
||||
|
||||
/// Put a single char from an UTF-8 buffer into a line buffer.
|
||||
///
|
||||
/// Handles composing chars and arabic shaping state.
|
||||
static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl)
|
||||
{
|
||||
const char_u *p = s->p;
|
||||
int cells = utf_ptr2cells(p);
|
||||
int c_len = utfc_ptr2len(p);
|
||||
int u8c, u8cc[MAX_MCO];
|
||||
if (cells > maxcells) {
|
||||
return -1;
|
||||
}
|
||||
u8c = utfc_ptr2char(p, u8cc);
|
||||
if (*p < 0x80 && u8cc[0] == 0) {
|
||||
schar_from_ascii(dest[0], *p);
|
||||
s->prev_c = u8c;
|
||||
} else {
|
||||
if (p_arshape && !p_tbidi && arabic_char(u8c)) {
|
||||
// Do Arabic shaping.
|
||||
int pc, pc1, nc;
|
||||
int pcc[MAX_MCO];
|
||||
int firstbyte = *p;
|
||||
|
||||
// The idea of what is the previous and next
|
||||
// character depends on 'rightleft'.
|
||||
if (rl) {
|
||||
pc = s->prev_c;
|
||||
pc1 = s->prev_c1;
|
||||
nc = utf_ptr2char(p + c_len);
|
||||
s->prev_c1 = u8cc[0];
|
||||
} else {
|
||||
pc = utfc_ptr2char(p + c_len, pcc);
|
||||
nc = s->prev_c;
|
||||
pc1 = pcc[0];
|
||||
}
|
||||
s->prev_c = u8c;
|
||||
|
||||
u8c = arabic_shape(u8c, &firstbyte, &u8cc[0], pc, pc1, nc);
|
||||
} else {
|
||||
s->prev_c = u8c;
|
||||
}
|
||||
schar_from_cc(dest[0], u8c, u8cc);
|
||||
}
|
||||
if (cells > 1) {
|
||||
dest[1][0] = 0;
|
||||
}
|
||||
s->p += c_len;
|
||||
return cells;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display one folded line.
|
||||
*/
|
||||
@ -1863,13 +1922,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
|
||||
* Right-left text is put in columns 0 - number-col, normal text is put
|
||||
* in columns number-col - window-width.
|
||||
*/
|
||||
int cells;
|
||||
int u8c, u8cc[MAX_MCO];
|
||||
int idx;
|
||||
int c_len;
|
||||
char_u *p;
|
||||
int prev_c = 0; // previous Arabic character
|
||||
int prev_c1 = 0; // first composing char for prev_c
|
||||
|
||||
if (wp->w_p_rl) {
|
||||
idx = off;
|
||||
@ -1877,50 +1930,20 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
|
||||
idx = off + col;
|
||||
}
|
||||
|
||||
// Store multibyte characters in ScreenLines[] et al. correctly.
|
||||
for (p = text; *p != NUL; ) {
|
||||
cells = utf_ptr2cells(p);
|
||||
c_len = utfc_ptr2len(p);
|
||||
if (col + cells > wp->w_width - (wp->w_p_rl ? col : 0)) {
|
||||
LineState s = LINE_STATE(text);
|
||||
|
||||
while (*s.p != NUL) {
|
||||
// TODO(bfredl): cargo-culted from the old Vim code:
|
||||
// if(col + cells > wp->w_width - (wp->w_p_rl ? col : 0)) { break; }
|
||||
// This is obvious wrong. If Vim ever fixes this, solve for "cells" again
|
||||
// in the correct condition.
|
||||
int maxcells = wp->w_width - col - (wp->w_p_rl ? col : 0);
|
||||
int cells = line_putchar(&s, &ScreenLines[idx], maxcells, wp->w_p_rl);
|
||||
if (cells == -1) {
|
||||
break;
|
||||
}
|
||||
u8c = utfc_ptr2char(p, u8cc);
|
||||
if (*p < 0x80 && u8cc[0] == 0) {
|
||||
schar_from_ascii(ScreenLines[idx], *p);
|
||||
prev_c = u8c;
|
||||
} else {
|
||||
if (p_arshape && !p_tbidi && arabic_char(u8c)) {
|
||||
// Do Arabic shaping.
|
||||
int pc, pc1, nc;
|
||||
int pcc[MAX_MCO];
|
||||
int firstbyte = *p;
|
||||
|
||||
// The idea of what is the previous and next
|
||||
// character depends on 'rightleft'.
|
||||
if (wp->w_p_rl) {
|
||||
pc = prev_c;
|
||||
pc1 = prev_c1;
|
||||
nc = utf_ptr2char(p + c_len);
|
||||
prev_c1 = u8cc[0];
|
||||
} else {
|
||||
pc = utfc_ptr2char(p + c_len, pcc);
|
||||
nc = prev_c;
|
||||
pc1 = pcc[0];
|
||||
}
|
||||
prev_c = u8c;
|
||||
|
||||
u8c = arabic_shape(u8c, &firstbyte, &u8cc[0], pc, pc1, nc);
|
||||
} else {
|
||||
prev_c = u8c;
|
||||
}
|
||||
schar_from_cc(ScreenLines[idx], u8c, u8cc);
|
||||
}
|
||||
if (cells > 1) {
|
||||
ScreenLines[idx + 1][0] = 0;
|
||||
}
|
||||
col += cells;
|
||||
idx += cells;
|
||||
p += c_len;
|
||||
}
|
||||
|
||||
/* Fill the rest of the line with the fold filler */
|
||||
@ -2215,9 +2238,9 @@ win_line (
|
||||
int did_line_attr = 0;
|
||||
|
||||
bool search_attr_from_match = false; // if search_attr is from :match
|
||||
bool has_bufhl = false; // this buffer has highlight matches
|
||||
int bufhl_attr = 0; // attributes desired by bufhl
|
||||
BufhlLineInfo bufhl_info; // bufhl data for this line
|
||||
bool has_bufhl = false; // this buffer has highlight matches
|
||||
bool do_virttext = false; // draw virtual text for this line
|
||||
|
||||
/* draw_state: items that are drawn in sequence: */
|
||||
#define WL_START 0 /* nothing done yet */
|
||||
@ -2279,9 +2302,14 @@ win_line (
|
||||
}
|
||||
|
||||
if (bufhl_start_line(wp->w_buffer, lnum, &bufhl_info)) {
|
||||
if (kv_size(bufhl_info.line->items)) {
|
||||
has_bufhl = true;
|
||||
extra_check = true;
|
||||
}
|
||||
if (kv_size(bufhl_info.line->virt_text)) {
|
||||
do_virttext = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for columns to display for 'colorcolumn'.
|
||||
color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
|
||||
@ -3429,7 +3457,7 @@ win_line (
|
||||
}
|
||||
|
||||
if (has_bufhl && v > 0) {
|
||||
bufhl_attr = bufhl_get_attr(&bufhl_info, (colnr_T)v);
|
||||
int bufhl_attr = bufhl_get_attr(&bufhl_info, (colnr_T)v);
|
||||
if (bufhl_attr != 0) {
|
||||
if (!attr_pri) {
|
||||
char_attr = hl_combine_attr(char_attr, bufhl_attr);
|
||||
@ -3949,40 +3977,87 @@ win_line (
|
||||
&& (int)wp->w_virtcol <
|
||||
wp->w_width * (row - startrow + 1) + v
|
||||
&& lnum != wp->w_cursor.lnum)
|
||||
|| draw_color_col)
|
||||
&& !wp->w_p_rl
|
||||
) {
|
||||
|| draw_color_col || do_virttext)
|
||||
&& !wp->w_p_rl) {
|
||||
int rightmost_vcol = 0;
|
||||
int i;
|
||||
|
||||
if (wp->w_p_cuc)
|
||||
VirtText virt_text = do_virttext ? bufhl_info.line->virt_text
|
||||
: (VirtText)KV_INITIAL_VALUE;
|
||||
size_t virt_pos = 0;
|
||||
LineState s = LINE_STATE((char_u *)"");
|
||||
int virt_attr = 0;
|
||||
|
||||
// Make sure alignment is the same regardless
|
||||
// if listchars=eol:X is used or not.
|
||||
bool delay_virttext = lcs_eol <= 0;
|
||||
|
||||
if (wp->w_p_cuc) {
|
||||
rightmost_vcol = wp->w_virtcol;
|
||||
if (draw_color_col)
|
||||
/* determine rightmost colorcolumn to possibly draw */
|
||||
for (i = 0; color_cols[i] >= 0; ++i)
|
||||
if (rightmost_vcol < color_cols[i])
|
||||
}
|
||||
|
||||
if (draw_color_col) {
|
||||
// determine rightmost colorcolumn to possibly draw
|
||||
for (i = 0; color_cols[i] >= 0; i++) {
|
||||
if (rightmost_vcol < color_cols[i]) {
|
||||
rightmost_vcol = color_cols[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cuc_attr = win_hl_attr(wp, HLF_CUC);
|
||||
int mc_attr = win_hl_attr(wp, HLF_MC);
|
||||
|
||||
while (col < wp->w_width) {
|
||||
int cells = -1;
|
||||
if (do_virttext && !delay_virttext) {
|
||||
if (*s.p == NUL) {
|
||||
if (virt_pos < virt_text.size) {
|
||||
s.p = (char_u *)kv_A(virt_text, virt_pos).text;
|
||||
int hl_id = kv_A(virt_text, virt_pos).hl_id;
|
||||
virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
|
||||
virt_pos++;
|
||||
} else {
|
||||
do_virttext = false;
|
||||
}
|
||||
}
|
||||
if (*s.p != NUL) {
|
||||
cells = line_putchar(&s, &ScreenLines[off], wp->w_width - col,
|
||||
false);
|
||||
}
|
||||
}
|
||||
delay_virttext = false;
|
||||
|
||||
if (cells == -1) {
|
||||
schar_from_ascii(ScreenLines[off], ' ');
|
||||
col++;
|
||||
cells = 1;
|
||||
}
|
||||
col += cells;
|
||||
if (draw_color_col) {
|
||||
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
|
||||
}
|
||||
|
||||
int attr = 0;
|
||||
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
|
||||
ScreenAttrs[off++] = cuc_attr;
|
||||
attr = cuc_attr;
|
||||
} else if (draw_color_col && VCOL_HLC == *color_cols) {
|
||||
ScreenAttrs[off++] = mc_attr;
|
||||
} else {
|
||||
ScreenAttrs[off++] = wp->w_hl_attr_normal;
|
||||
attr = mc_attr;
|
||||
}
|
||||
|
||||
if (VCOL_HLC >= rightmost_vcol)
|
||||
if (do_virttext) {
|
||||
attr = hl_combine_attr(attr, virt_attr);
|
||||
}
|
||||
|
||||
ScreenAttrs[off] = attr;
|
||||
if (cells == 2) {
|
||||
ScreenAttrs[off+1] = attr;
|
||||
}
|
||||
off += cells;
|
||||
|
||||
if (VCOL_HLC >= rightmost_vcol && *s.p == NUL
|
||||
&& virt_pos >= virt_text.size) {
|
||||
break;
|
||||
}
|
||||
|
||||
++vcol;
|
||||
}
|
||||
|
@ -23,7 +23,10 @@ describe('Buffer highlighting', function()
|
||||
[7] = {bold = true},
|
||||
[8] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
|
||||
[9] = {foreground = Screen.colors.SlateBlue, underline = true},
|
||||
[10] = {foreground = Screen.colors.Red}
|
||||
[10] = {foreground = Screen.colors.Red},
|
||||
[11] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
|
||||
[12] = {foreground = Screen.colors.Blue1},
|
||||
[13] = {background = Screen.colors.LightGrey},
|
||||
})
|
||||
end)
|
||||
|
||||
@ -77,7 +80,7 @@ describe('Buffer highlighting', function()
|
||||
|
|
||||
]])
|
||||
|
||||
clear_hl(-1, 0 , -1)
|
||||
clear_hl(-1, 0, -1)
|
||||
screen:expect([[
|
||||
these are some lines |
|
||||
^ |
|
||||
@ -275,4 +278,140 @@ describe('Buffer highlighting', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('supports virtual text annotations', function()
|
||||
local set_virtual_text = curbufmeths.set_virtual_text
|
||||
insert([[
|
||||
1 + 2
|
||||
3 +
|
||||
x = 4]])
|
||||
feed('O<esc>20A5, <esc>gg')
|
||||
screen:expect([[
|
||||
^1 + 2 |
|
||||
3 + |
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, |
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
local id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {})
|
||||
set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {})
|
||||
local id2 = set_virtual_text(0, 2, {{"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}}, {})
|
||||
neq(id2, id1)
|
||||
|
||||
screen:expect([[
|
||||
^1 + 2 {3:=}{2: 3} |
|
||||
3 + {11:ERROR:} invalid syntax |
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
clear_hl(id1, 0, -1)
|
||||
screen:expect([[
|
||||
^1 + 2 |
|
||||
3 + |
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
-- Handles doublewidth chars, leaving a space if truncating
|
||||
-- in the middle of a char
|
||||
set_virtual_text(id1, 1, {{"暗x事zz速野谷質結育副住新覚丸活解終事", "Comment"}}, {})
|
||||
screen:expect([[
|
||||
^1 + 2 |
|
||||
3 + {12:暗x事zz速野谷質結育副住新覚丸活解終 }|
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
feed("2Gx")
|
||||
screen:expect([[
|
||||
1 + 2 |
|
||||
^ + {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
-- visual selection doesn't highlight virtual text
|
||||
feed("ggVG")
|
||||
screen:expect([[
|
||||
{13:1 + 2} |
|
||||
{13: +} {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
|
||||
{13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
|
||||
{13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s|
|
||||
^x{13: = 4} |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{7:-- VISUAL LINE --} |
|
||||
]])
|
||||
|
||||
feed("<esc>")
|
||||
screen:expect([[
|
||||
1 + 2 |
|
||||
+ {12:暗x事zz速野谷質結育副住新覚丸活解終事}|
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
^x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
feed("2Gdd")
|
||||
screen:expect([[
|
||||
1 + 2 |
|
||||
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
-- listchars=eol:- works, and doesn't shift virtual text
|
||||
command("set list")
|
||||
screen:expect([[
|
||||
1 + 2 |
|
||||
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5,{1:-} Lorem ipsum dolor s|
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
clear_hl(-1, 0, -1)
|
||||
screen:expect([[
|
||||
1 + 2 |
|
||||
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
|
||||
, 5, 5, 5, 5, 5, 5,{1:-} |
|
||||
x = 4 |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user