mirror of
https://github.com/neovim/neovim.git
synced 2026-06-15 08:13:45 +00:00
feat(extmark): virt_lines_overflow "wrap" and "auto"
Problem: Extmark has support for horizontal scrolling and truncating, but not wrapping. Solution: Extend virt_lines_overflow flags to support "wrap" and "auto" based on proposed changes in #18282.
This commit is contained in:
@@ -3332,6 +3332,9 @@ nvim_buf_set_extmark({buf}, {ns_id}, {line}, {col}, {opts})
|
||||
• "trunc": truncate virtual lines on the right (default).
|
||||
• "scroll": virtual lines can scroll horizontally with
|
||||
'nowrap', otherwise the same as "trunc".
|
||||
• "wrap": virtual lines can wrap onto extra lines.
|
||||
• "auto": virtual lines wrap with 'wrap' and scroll
|
||||
horizontally with 'nowrap'.
|
||||
• virt_text : *virtual-text* to link to this mark. A list of
|
||||
`[text, highlight]` tuples, each representing a text chunk
|
||||
with specified highlight. `highlight` element can either be
|
||||
|
||||
@@ -127,6 +127,9 @@ API
|
||||
• |nvim_get_option_info2()|
|
||||
• |nvim_get_option_value()|
|
||||
• |nvim_set_option_value()|
|
||||
• |nvim_buf_set_extmark()| `virt_lines_overflow` accepts "wrap" to enable
|
||||
wrapping onto extra rows and "auto" which enables horizontal scrolling when
|
||||
'nowrap' is set and wrapping when 'wrap' is set.
|
||||
|
||||
BUILD
|
||||
|
||||
|
||||
2
runtime/lua/vim/_meta/api.gen.lua
generated
2
runtime/lua/vim/_meta/api.gen.lua
generated
@@ -696,6 +696,8 @@ function vim.api.nvim_buf_line_count(buf) end
|
||||
--- - "trunc": truncate virtual lines on the right (default).
|
||||
--- - "scroll": virtual lines can scroll horizontally with 'nowrap',
|
||||
--- otherwise the same as "trunc".
|
||||
--- - "wrap": virtual lines can wrap onto extra lines.
|
||||
--- - "auto": virtual lines wrap with 'wrap' and scroll horizontally with 'nowrap'.
|
||||
--- - virt_text : [](virtual-text) to link to this mark.
|
||||
--- A list of `[text, highlight]` tuples, each representing a
|
||||
--- text chunk with specified highlight. `highlight` element
|
||||
|
||||
2
runtime/lua/vim/_meta/api_keysets.gen.lua
generated
2
runtime/lua/vim/_meta/api_keysets.gen.lua
generated
@@ -441,7 +441,7 @@ error('Cannot require a meta file')
|
||||
--- @field virt_lines? any[]
|
||||
--- @field virt_lines_above? boolean
|
||||
--- @field virt_lines_leftcol? boolean
|
||||
--- @field virt_lines_overflow? "trunc"|"scroll"
|
||||
--- @field virt_lines_overflow? "trunc"|"scroll"|"wrap"|"auto"
|
||||
--- @field virt_text? any[]
|
||||
--- @field virt_text_hide? boolean
|
||||
--- @field virt_text_pos? "eol"|"eol_right_align"|"overlay"|"right_align"|"inline"
|
||||
|
||||
@@ -495,6 +495,8 @@ ArrayOf(DictAs(get_extmark_item)) nvim_buf_get_extmarks(Buffer buf, Integer ns_i
|
||||
/// - "trunc": truncate virtual lines on the right (default).
|
||||
/// - "scroll": virtual lines can scroll horizontally with 'nowrap',
|
||||
/// otherwise the same as "trunc".
|
||||
/// - "wrap": virtual lines can wrap onto extra lines.
|
||||
/// - "auto": virtual lines wrap with 'wrap' and scroll horizontally with 'nowrap'.
|
||||
/// - virt_text : [](virtual-text) to link to this mark.
|
||||
/// A list of `[text, highlight]` tuples, each representing a
|
||||
/// text chunk with specified highlight. `highlight` element
|
||||
@@ -724,10 +726,15 @@ Integer nvim_buf_set_extmark(Buffer buf, Integer ns_id, Integer line, Integer co
|
||||
}
|
||||
|
||||
int virt_lines_flags = opts->virt_lines_leftcol ? kVLLeftcol : 0;
|
||||
VirtLineOverflow virt_lines_overflow = kVLOverflowTrunc;
|
||||
if (HAS_KEY(opts, set_extmark, virt_lines_overflow)) {
|
||||
String str = opts->virt_lines_overflow;
|
||||
if (strequal("scroll", str.data)) {
|
||||
virt_lines_flags |= kVLScroll;
|
||||
virt_lines_overflow = kVLOverflowScroll;
|
||||
} else if (strequal("wrap", str.data)) {
|
||||
virt_lines_overflow = kVLOverflowWrap;
|
||||
} else if (strequal("auto", str.data)) {
|
||||
virt_lines_overflow = kVLOverflowAuto;
|
||||
} else if (!strequal("trunc", str.data)) {
|
||||
VALIDATE_S(false, "virt_lines_overflow", str.data, {
|
||||
goto error;
|
||||
@@ -743,7 +750,8 @@ Integer nvim_buf_set_extmark(Buffer buf, Integer ns_id, Integer line, Integer co
|
||||
});
|
||||
int dummig;
|
||||
VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig, false);
|
||||
kv_push(virt_lines.data.virt_lines, ((struct virt_line){ jtem, virt_lines_flags }));
|
||||
kv_push(virt_lines.data.virt_lines,
|
||||
((struct virt_line){ jtem, virt_lines_flags, virt_lines_overflow }));
|
||||
if (ERROR_SET(err)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ typedef struct {
|
||||
Array virt_lines;
|
||||
Boolean virt_lines_above;
|
||||
Boolean virt_lines_leftcol;
|
||||
Enum("trunc", "scroll") virt_lines_overflow;
|
||||
Enum("trunc", "scroll", "wrap", "auto") virt_lines_overflow;
|
||||
Boolean strict;
|
||||
String sign_text;
|
||||
HLGroupID sign_hl_group;
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
#include "nvim/grid.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_group.h"
|
||||
#include "nvim/indent.h"
|
||||
#include "nvim/marktree.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/memory_defs.h"
|
||||
#include "nvim/move.h"
|
||||
@@ -1122,7 +1124,60 @@ bool decor_redraw_eol(win_T *wp, DecorState *state, int *eol_attr, int eol_col)
|
||||
|
||||
static const uint32_t lines_filter[kMTMetaCount] = {[kMTMetaLines] = kMTFilterSelect };
|
||||
|
||||
/// Counts the number of rows occupied by a virtual line. When skip_cells is non-NULL, sets it to
|
||||
/// the cell offset where target_row begins.
|
||||
///
|
||||
/// @param target_row Row relative to the virtual line that skip_cells is computed for.
|
||||
/// @param skip_cells Cell offset for the target_row. Pass NULL when only the row count is needed.
|
||||
///
|
||||
/// @return Number of rows occupied by the virtual line.
|
||||
int decor_virt_line_rows(win_T *wp, const struct virt_line *vl, int target_row, int *skip_cells)
|
||||
{
|
||||
VirtLineOverflow overflow = vl->overflow;
|
||||
bool wrap = (overflow == kVLOverflowWrap) || ((overflow == kVLOverflowAuto) && wp->w_p_wrap);
|
||||
int row_width = wp->w_view_width - ((vl->flags & kVLLeftcol) ? 0 : win_col_off(wp));
|
||||
if (skip_cells != NULL) {
|
||||
*skip_cells = 0;
|
||||
}
|
||||
if (!wrap || row_width <= 0) {
|
||||
return 1;
|
||||
}
|
||||
VirtText vt = vl->line;
|
||||
buf_T *buf = wp->w_buffer;
|
||||
int vcol = 0;
|
||||
int row_cells = 0;
|
||||
int row = 0;
|
||||
for (int i = 0; i < (int)kv_size(vt); i++) {
|
||||
const char *virt_str = kv_A(vt, i).text;
|
||||
if (virt_str == NULL) {
|
||||
continue;
|
||||
}
|
||||
while (*virt_str != NUL) {
|
||||
int bytes_to_next_char = utfc_ptr2len(virt_str);
|
||||
// Need to compute cell width due to TAB & double width cell chars
|
||||
int cells = (*virt_str == TAB)
|
||||
? tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array)
|
||||
: utf_ptr2cells(virt_str);
|
||||
virt_str += bytes_to_next_char;
|
||||
// Wrap before total row cell length would exceed the window size
|
||||
// to protect against double width cell chars being split at the boundary
|
||||
if (row_cells + cells > row_width) {
|
||||
row++;
|
||||
if (skip_cells != NULL && row == target_row) {
|
||||
*skip_cells = vcol;
|
||||
}
|
||||
row_cells = 0;
|
||||
}
|
||||
row_cells += cells;
|
||||
vcol += cells;
|
||||
}
|
||||
}
|
||||
|
||||
return row + 1;
|
||||
}
|
||||
|
||||
/// @param apply_folds Only count virtual lines that are not in folds.
|
||||
/// @return Number of rows occupied by the virtual lines.
|
||||
int decor_virt_lines(win_T *wp, int start_row, int end_row, int *num_below, VirtLines *lines,
|
||||
bool apply_folds)
|
||||
{
|
||||
@@ -1154,13 +1209,18 @@ int decor_virt_lines(win_T *wp, int start_row, int end_row, int *num_below, Virt
|
||||
if (draw_row >= start_row && draw_row < end_row
|
||||
&& (!apply_folds || !(hasFolding(wp, mrow + 1, NULL, NULL)
|
||||
|| decor_conceal_line(wp, mrow, false)))) {
|
||||
virt_lines += (int)kv_size(vt->data.virt_lines);
|
||||
// Iterates over each virtual line summing number of rows.
|
||||
// Rows belonging to previous line are accumulated in num_below.
|
||||
for (int i = 0; i < (int)kv_size(vt->data.virt_lines); i++) {
|
||||
int rows = decor_virt_line_rows(wp, &kv_A(vt->data.virt_lines, i), 0, NULL);
|
||||
virt_lines += rows;
|
||||
if (num_below && !above) {
|
||||
(*num_below) += rows;
|
||||
}
|
||||
}
|
||||
if (lines) {
|
||||
kv_splice(*lines, vt->data.virt_lines);
|
||||
}
|
||||
if (num_below && !above) {
|
||||
(*num_below) += (int)kv_size(vt->data.virt_lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
vt = vt->next;
|
||||
@@ -1262,16 +1322,27 @@ void decor_to_dict_legacy(Dict *dict, DecorInline decor, bool hl_name, Arena *ar
|
||||
if (virt_lines) {
|
||||
Array all_chunks = arena_array(arena, kv_size(virt_lines->data.virt_lines));
|
||||
int virt_lines_flags = 0;
|
||||
VirtLineOverflow virt_lines_overflow = kVLOverflowTrunc;
|
||||
for (size_t i = 0; i < kv_size(virt_lines->data.virt_lines); i++) {
|
||||
virt_lines_flags = kv_A(virt_lines->data.virt_lines, i).flags;
|
||||
virt_lines_overflow = kv_A(virt_lines->data.virt_lines, i).overflow;
|
||||
Array chunks = virt_text_to_array(kv_A(virt_lines->data.virt_lines, i).line, hl_name, arena);
|
||||
ADD(all_chunks, ARRAY_OBJ(chunks));
|
||||
}
|
||||
PUT_C(*dict, "virt_lines", ARRAY_OBJ(all_chunks));
|
||||
PUT_C(*dict, "virt_lines_above", BOOLEAN_OBJ(virt_lines->flags & kVTLinesAbove));
|
||||
PUT_C(*dict, "virt_lines_leftcol", BOOLEAN_OBJ(virt_lines_flags & kVLLeftcol));
|
||||
PUT_C(*dict, "virt_lines_overflow",
|
||||
CSTR_AS_OBJ(virt_lines_flags & kVLScroll ? "scroll" : "trunc"));
|
||||
|
||||
char *overflow = "trunc";
|
||||
if (virt_lines_overflow == kVLOverflowScroll) {
|
||||
overflow = "scroll";
|
||||
} else if (virt_lines_overflow == kVLOverflowWrap) {
|
||||
overflow = "wrap";
|
||||
} else if (virt_lines_overflow == kVLOverflowAuto) {
|
||||
overflow = "auto";
|
||||
}
|
||||
|
||||
PUT_C(*dict, "virt_lines_overflow", CSTR_AS_OBJ(overflow));
|
||||
priority = virt_lines->priority;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,16 @@ typedef enum {
|
||||
/// Flags for virtual lines
|
||||
enum {
|
||||
kVLLeftcol = 1, ///< Start at left window edge, ignoring number column, etc.
|
||||
kVLScroll = 2, ///< Can scroll horizontally with 'nowrap'
|
||||
// kVLWrap = 4,
|
||||
};
|
||||
|
||||
typedef kvec_t(struct virt_line { VirtText line; int flags; }) VirtLines;
|
||||
typedef enum {
|
||||
kVLOverflowTrunc, ///< Truncate with 'nowrap'
|
||||
kVLOverflowScroll, ///< Scroll horizontally with 'nowrap'
|
||||
kVLOverflowWrap, ///< Wrap onto extra rows
|
||||
kVLOverflowAuto, ///< Scroll with 'nowrap'; wrap with 'wrap'
|
||||
} VirtLineOverflow;
|
||||
|
||||
typedef kvec_t(struct virt_line { VirtText line; int flags; VirtLineOverflow overflow; }) VirtLines;
|
||||
|
||||
typedef uint16_t DecorPriority;
|
||||
typedef uint32_t DecorPriorityInternal;
|
||||
|
||||
@@ -1322,6 +1322,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
|
||||
}
|
||||
VirtLines virt_lines = KV_INITIAL_VALUE;
|
||||
wlv.n_virt_lines = decor_virt_lines(wp, lnum - 1, lnum, &wlv.n_virt_below, &virt_lines, true);
|
||||
// Preserving count of virt_lines for topline visibility
|
||||
int total_virt_rows = wlv.n_virt_lines;
|
||||
wlv.filler_lines += wlv.n_virt_lines;
|
||||
if (lnum == wp->w_topline) {
|
||||
wlv.filler_lines = wp->w_topfill;
|
||||
@@ -1674,8 +1676,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
|
||||
|
||||
const bool may_have_inline_virt
|
||||
= !has_foldtext && buf_meta_total(wp->w_buffer, kMTMetaInline) > 0;
|
||||
int virt_line_index = -1;
|
||||
bool has_virt_line = false;
|
||||
int virt_line_flags = 0;
|
||||
// Index into virt_lines and the starting row of that line (virt_line_start_row).
|
||||
// Both persist across iterations to avoid traversing previously visited rows.
|
||||
int virt_line_index = 0;
|
||||
int virt_line_start_row = 0;
|
||||
int virt_line_skip_cells = 0;
|
||||
|
||||
// Repeat for each cell in the displayed line.
|
||||
while (true) {
|
||||
@@ -1715,15 +1722,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
|
||||
}
|
||||
|
||||
if (wlv.filler_todo > 0) {
|
||||
int index = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines);
|
||||
if (index > 0) {
|
||||
virt_line_index = (int)kv_size(virt_lines) - index;
|
||||
assert(virt_line_index >= 0);
|
||||
virt_line_flags = kv_A(virt_lines, virt_line_index).flags;
|
||||
// nvim_buf_set_extmark: virt_lines_overflow
|
||||
int virt_rows_todo = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines);
|
||||
if (virt_rows_todo > 0) {
|
||||
int target_row = total_virt_rows - virt_rows_todo;
|
||||
// Count number of rows spanned by virtual line.
|
||||
// Find the virtual line containing the target row.
|
||||
// Set skip cells with the same row-counting function so offset calculation stays in sync
|
||||
for (; virt_line_index < (int)kv_size(virt_lines); virt_line_index++) {
|
||||
int line_rows = decor_virt_line_rows(wp, &kv_A(virt_lines, virt_line_index), 0, NULL);
|
||||
if (target_row < virt_line_start_row + line_rows) {
|
||||
has_virt_line = true;
|
||||
virt_line_flags = kv_A(virt_lines, virt_line_index).flags;
|
||||
decor_virt_line_rows(wp, &kv_A(virt_lines, virt_line_index),
|
||||
target_row - virt_line_start_row,
|
||||
&virt_line_skip_cells);
|
||||
break;
|
||||
}
|
||||
virt_line_start_row += line_rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (virt_line_index >= 0 && (virt_line_flags & kVLLeftcol)) {
|
||||
if (has_virt_line && (virt_line_flags & kVLLeftcol)) {
|
||||
// skip columns
|
||||
} else if (statuscol.draw) {
|
||||
// Draw 'statuscolumn' if it is set.
|
||||
@@ -1768,7 +1789,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
|
||||
break;
|
||||
}
|
||||
wlv.filler_todo--;
|
||||
virt_line_index = -1;
|
||||
has_virt_line = false;
|
||||
if (wlv.filler_todo == 0 && (wp->w_botfill || !draw_text)) {
|
||||
break;
|
||||
}
|
||||
@@ -3149,14 +3170,20 @@ end_check:
|
||||
}
|
||||
}
|
||||
|
||||
if (virt_line_index >= 0) {
|
||||
if (has_virt_line) {
|
||||
VirtLineOverflow overflow = kv_A(virt_lines, virt_line_index).overflow;
|
||||
bool virt_row_scroll = (overflow == kVLOverflowScroll)
|
||||
|| ((overflow == kVLOverflowAuto) && !wp->w_p_wrap);
|
||||
if (virt_row_scroll) {
|
||||
virt_line_skip_cells = wp->w_leftcol;
|
||||
}
|
||||
draw_virt_text_item(buf,
|
||||
virt_line_flags & kVLLeftcol ? 0 : win_col_offset,
|
||||
(virt_line_flags & kVLLeftcol) ? 0 : win_col_offset,
|
||||
kv_A(virt_lines, virt_line_index).line,
|
||||
kHlModeReplace,
|
||||
view_width,
|
||||
0,
|
||||
virt_line_flags & kVLScroll ? wp->w_leftcol : 0);
|
||||
virt_line_skip_cells);
|
||||
} else if (wlv.filler_todo <= 0) {
|
||||
draw_virt_text(wp, buf, win_col_offset, &draw_col, wlv.row);
|
||||
}
|
||||
@@ -3205,7 +3232,7 @@ end_check:
|
||||
statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
|
||||
}
|
||||
wlv.filler_todo--;
|
||||
virt_line_index = -1;
|
||||
has_virt_line = false;
|
||||
virt_line_flags = 0;
|
||||
// When the filler lines are actually below the last line of the
|
||||
// file, or we are not drawing text for this line, break here.
|
||||
|
||||
@@ -1738,6 +1738,50 @@ describe('API/extmarks', function()
|
||||
},
|
||||
}, get_extmark_by_id(ns, marks[3], { details = true }))
|
||||
|
||||
-- verify 'wrap' is returned through get_extmark_by_id to validate flag comparison
|
||||
set_extmark(ns, marks[4], 0, 0, {
|
||||
priority = 0,
|
||||
ui_watched = true,
|
||||
virt_lines = { { { '', 'Macro' }, { '' }, { '', '' } } },
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
eq({
|
||||
0,
|
||||
0,
|
||||
{
|
||||
ns_id = ns,
|
||||
right_gravity = true,
|
||||
ui_watched = true,
|
||||
priority = 0,
|
||||
virt_lines = { { { '', 'Macro' }, { '' }, { '', '' } } },
|
||||
virt_lines_above = false,
|
||||
virt_lines_leftcol = false,
|
||||
virt_lines_overflow = 'wrap',
|
||||
},
|
||||
}, get_extmark_by_id(ns, marks[4], { details = true }))
|
||||
|
||||
-- verify 'auto' is returned through get_extmark_by_id to validate flag comparison
|
||||
set_extmark(ns, marks[5], 0, 0, {
|
||||
priority = 0,
|
||||
ui_watched = true,
|
||||
virt_lines = { { { '', 'Macro' }, { '' }, { '', '' } } },
|
||||
virt_lines_overflow = 'auto',
|
||||
})
|
||||
eq({
|
||||
0,
|
||||
0,
|
||||
{
|
||||
ns_id = ns,
|
||||
right_gravity = true,
|
||||
ui_watched = true,
|
||||
priority = 0,
|
||||
virt_lines = { { { '', 'Macro' }, { '' }, { '', '' } } },
|
||||
virt_lines_above = false,
|
||||
virt_lines_leftcol = false,
|
||||
virt_lines_overflow = 'auto',
|
||||
},
|
||||
}, get_extmark_by_id(ns, marks[5], { details = true }))
|
||||
|
||||
set_extmark(ns, marks[4], 0, 0, { cursorline_hl_group = 'Statement' })
|
||||
eq({
|
||||
0,
|
||||
|
||||
@@ -6893,6 +6893,291 @@ if (h->n_buckets < new_n_buckets) { // expand
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap', function()
|
||||
command('set wrap signcolumn=yes')
|
||||
insert('line1\nline2\nline3\n')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{
|
||||
{
|
||||
string.rep(
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean non felis dapibus, semper sapien vitae, fringilla orci.',
|
||||
5
|
||||
),
|
||||
'Special',
|
||||
},
|
||||
},
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }{16:rem ipsum dolor sit amet, consectetur adipiscing}|
|
||||
{7: }{16: elit. Aenean non felis dapibus, semper sapien v}|
|
||||
{7: }{16:itae, fringilla orci.Lorem ipsum dolor sit amet,}|
|
||||
{7: }{16: consectetur adipiscing elit. Aenean non felis d}|
|
||||
{7: }{16:apibus, semper sapien vitae, fringilla orci.Lore}|
|
||||
{7: }{16:m ipsum dolor sit amet, consectetur adipiscing e}|
|
||||
{7: }{16:lit. Aenean non felis dapibus, semper sapien vit}|
|
||||
{7: }{16:ae, fringilla orci.} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
|
|
||||
]])
|
||||
feed('<C-e>')
|
||||
screen:expect([[
|
||||
{7: }{16: elit. Aenean non felis dapibus, semper sapien v}|
|
||||
{7: }{16:itae, fringilla orci.Lorem ipsum dolor sit amet,}|
|
||||
{7: }{16: consectetur adipiscing elit. Aenean non felis d}|
|
||||
{7: }{16:apibus, semper sapien vitae, fringilla orci.Lore}|
|
||||
{7: }{16:m ipsum dolor sit amet, consectetur adipiscing e}|
|
||||
{7: }{16:lit. Aenean non felis dapibus, semper sapien vit}|
|
||||
{7: }{16:ae, fringilla orci.} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
{1:~ }|
|
||||
|
|
||||
]])
|
||||
feed('<C-e>')
|
||||
screen:expect([[
|
||||
{7: }{16:itae, fringilla orci.Lorem ipsum dolor sit amet,}|
|
||||
{7: }{16: consectetur adipiscing elit. Aenean non felis d}|
|
||||
{7: }{16:apibus, semper sapien vitae, fringilla orci.Lore}|
|
||||
{7: }{16:m ipsum dolor sit amet, consectetur adipiscing e}|
|
||||
{7: }{16:lit. Aenean non felis dapibus, semper sapien vit}|
|
||||
{7: }{16:ae, fringilla orci.} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
{1:~ }|*2
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with 2 cell character', function()
|
||||
command('set wrap signcolumn=yes')
|
||||
insert('line1\nline2\nline3\n')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { string.rep('12345678古', 5), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }line1 |
|
||||
{7: }{16:12345678古12345678古12345678古12345678古12345678}|
|
||||
{7: }{16:古} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
{1:~ }|*5
|
||||
|
|
||||
]])
|
||||
feed('<C-e>')
|
||||
|
||||
screen:expect([[
|
||||
{7: }{16:12345678古12345678古12345678古12345678古12345678}|
|
||||
{7: }{16:古} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
{1:~ }|*6
|
||||
|
|
||||
]])
|
||||
|
||||
feed('<C-e>')
|
||||
screen:expect([[
|
||||
{7: }{16:古} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
{1:~ }|*7
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with tabs', function()
|
||||
command('set wrap signcolumn=yes')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { string.rep('1234\t\t\t5\t6\t78古', 10), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }^ |
|
||||
{7: }{16:1234 5 6 78古1234}|
|
||||
{7: }{16: 5 6 78古1234}|*8
|
||||
{7: }{16: 5 6 78古} |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with 2 cell character at the boundary', function()
|
||||
insert('x')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = { { { string.rep('a', 49) .. string.rep('古', 4), 'Special' } } },
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
screen:expect([[
|
||||
^x |
|
||||
{16:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }|
|
||||
{16:古古古古} |
|
||||
{1:~ }|*8
|
||||
|
|
||||
]])
|
||||
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||
screen:try_resize(13, 10)
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { 'AB', 'Special' } },
|
||||
{ { string.rep('古', 13), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
screen:expect([[
|
||||
^x |
|
||||
{16:AB} |
|
||||
{16:古古古古古古 }|*2
|
||||
{16:古} |
|
||||
{1:~ }|*4
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with nowrap', function()
|
||||
command('set nowrap signcolumn=yes')
|
||||
insert(string.rep('abcdefghij', 6) .. 'line1\nline2\nline3\n')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { string.rep('12345678古', 5), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
feed('ggzlzl')
|
||||
screen:expect([[
|
||||
{7: }^cdefghijabcdefghijabcdefghijabcdefghijabcdefghij|
|
||||
{7: }{16:12345678古12345678古12345678古12345678古12345678}|
|
||||
{7: }{16:古} |
|
||||
{7: }ne2 |
|
||||
{7: }ne3 |
|
||||
{7: } |
|
||||
{1:~ }|*5
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=auto with wrap', function()
|
||||
command('set wrap signcolumn=yes')
|
||||
insert('line1\nline2\nline3\n')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { string.rep('Thequickbrownfoxjumpsoverthelazydog. The quick brown fox jumps over the lazy dog', 20), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'auto',
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }{16:rown fox jumps over the lazy dogThequickbrownfox}|
|
||||
{7: }{16:jumpsoverthelazydog. The quick brown fox jumps o}|
|
||||
{7: }{16:ver the lazy dogThequickbrownfoxjumpsoverthelazy}|
|
||||
{7: }{16:dog. The quick brown fox jumps over the lazy dog}|
|
||||
{7: }{16:Thequickbrownfoxjumpsoverthelazydog. The quick b}|
|
||||
{7: }{16:rown fox jumps over the lazy dogThequickbrownfox}|
|
||||
{7: }{16:jumpsoverthelazydog. The quick brown fox jumps o}|
|
||||
{7: }{16:ver the lazy dog} |
|
||||
{7: }line2 |
|
||||
{7: }line3 |
|
||||
{7: }^ |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=auto and nowrap scrolls horizontally', function()
|
||||
command('set nowrap signcolumn=yes')
|
||||
insert('abcdefghijklmnopqrstuvwxyz')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { '12α口β̳γ̲=', 'Special' }, { '❤️345678', 'Special' } },
|
||||
{ { '123\t45\t678', 'NonText' } },
|
||||
},
|
||||
virt_lines_overflow = 'auto',
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }abcdefghijklmnopqrstuvwxy^z |
|
||||
{7: }{16:12α口β̳γ̲=❤️345678} |
|
||||
{7: }{1:123 45 678} |
|
||||
{1:~ }|*8
|
||||
|
|
||||
]])
|
||||
feed('zl')
|
||||
screen:expect([[
|
||||
{7: }bcdefghijklmnopqrstuvwxy^z |
|
||||
{7: }{16:2α口β̳γ̲=❤️345678} |
|
||||
{7: }{1:23 45 678} |
|
||||
{1:~ }|*8
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with virt_lines_above', function()
|
||||
command('set wrap signcolumn=yes')
|
||||
insert('line1\nline2\nline3\n')
|
||||
feed('2gg')
|
||||
api.nvim_buf_set_extmark(0, ns, 1, 0, {
|
||||
virt_lines = {
|
||||
{ { string.rep('Lorem ipsum dolor sit amet, consectetur. ', 4), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
virt_lines_above = true,
|
||||
})
|
||||
screen:expect([[
|
||||
{7: }line1 |
|
||||
{7: }{16:Lorem ipsum dolor sit amet, consectetur. Lorem i}|
|
||||
{7: }{16:psum dolor sit amet, consectetur. Lorem ipsum do}|
|
||||
{7: }{16:lor sit amet, consectetur. Lorem ipsum dolor sit}|
|
||||
{7: }{16: amet, consectetur. } |
|
||||
{7: }^line2 |
|
||||
{7: }line3 |
|
||||
{7: } |
|
||||
{1:~ }|*3
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('virt_lines_overflow=wrap with wrapped rows for statuscolumn', function()
|
||||
command('set wrap statuscolumn=[%{v:lnum}]')
|
||||
insert('line1\nline2\nline3\n')
|
||||
feed('2gg')
|
||||
api.nvim_buf_set_extmark(0, ns, 0, 0, {
|
||||
virt_lines = {
|
||||
{ { 'BELOW ' .. string.rep('Lorem ipsum dolor sit amet, consectetur. ', 4), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
})
|
||||
api.nvim_buf_set_extmark(0, ns, 1, 0, {
|
||||
virt_lines = {
|
||||
{ { 'ABOVE ' .. string.rep('Lorem ipsum dolor sit amet, consectetur. ', 4), 'Special' } },
|
||||
},
|
||||
virt_lines_overflow = 'wrap',
|
||||
virt_lines_above = true,
|
||||
})
|
||||
screen:expect([[
|
||||
{8:[1]}line1 |
|
||||
{8:[1]}{16:BELOW Lorem ipsum dolor sit amet, consectetur. }|
|
||||
{8:[1]}{16:Lorem ipsum dolor sit amet, consectetur. Lorem }|
|
||||
{8:[1]}{16:ipsum dolor sit amet, consectetur. Lorem ipsum }|
|
||||
{8:[1]}{16:dolor sit amet, consectetur. } |
|
||||
{8:[2]}{16:ABOVE Lorem ipsum dolor sit amet, consectetur. }|
|
||||
{8:[2]}{16:Lorem ipsum dolor sit amet, consectetur. Lorem }|
|
||||
{8:[2]}{16:ipsum dolor sit amet, consectetur. Lorem ipsum }|
|
||||
{8:[2]}{16:dolor sit amet, consectetur. } |
|
||||
{8:[2]}^line2 |
|
||||
{8:[3]}line3 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('does not show twice if end_row or end_col is specified #18622', function()
|
||||
screen:try_resize(50, 8)
|
||||
insert([[
|
||||
|
||||
Reference in New Issue
Block a user