mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
decorations: allow virt_text overlay at any column
This commit is contained in:
parent
d623400cad
commit
4781333a7a
@ -1425,6 +1425,11 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
|
||||
/// - hl_group : name of the highlight group used to highlight
|
||||
/// this mark.
|
||||
/// - virt_text : virtual text to link to this mark.
|
||||
/// - virt_text_pos : positioning of virtual text. Possible
|
||||
/// values:
|
||||
/// - "eol": right after eol character (default)
|
||||
/// - "overlay": display over the specified column, without
|
||||
/// shifting the underlying text.
|
||||
/// - ephemeral : for use with |nvim_set_decoration_provider|
|
||||
/// callbacks. The mark will only be used for the current
|
||||
/// redraw cycle, and not be permantently stored in the
|
||||
@ -1474,8 +1479,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
uint64_t id = 0;
|
||||
int line2 = -1, hl_id = 0;
|
||||
DecorPriority priority = DECOR_PRIORITY_BASE;
|
||||
colnr_T col2 = 0;
|
||||
colnr_T col2 = -1;
|
||||
VirtText virt_text = KV_INITIAL_VALUE;
|
||||
VirtTextPos virt_text_pos = kVTEndOfLine;
|
||||
bool right_gravity = true;
|
||||
bool end_right_gravity = false;
|
||||
bool end_gravity_set = false;
|
||||
@ -1544,6 +1550,22 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
if (ERROR_SET(err)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (strequal("virt_text_pos", k.data)) {
|
||||
if (v->type != kObjectTypeString) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"virt_text_pos is not a String");
|
||||
goto error;
|
||||
}
|
||||
String str = v->data.string;
|
||||
if (strequal("eol", str.data)) {
|
||||
virt_text_pos = kVTEndOfLine;
|
||||
} else if (strequal("overlay", str.data)) {
|
||||
virt_text_pos = kVTOverlay;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"virt_text_pos: invalid value");
|
||||
goto error;
|
||||
}
|
||||
} else if (strequal("ephemeral", k.data)) {
|
||||
ephemeral = api_object_to_bool(*v, "ephemeral", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
@ -1585,7 +1607,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
|
||||
// Only error out if they try to set end_right_gravity without
|
||||
// setting end_col or end_line
|
||||
if (line2 == -1 && col2 == 0 && end_gravity_set) {
|
||||
if (line2 == -1 && col2 == -1 && end_gravity_set) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"cannot set end_right_gravity "
|
||||
"without setting end_line or end_col");
|
||||
@ -1609,30 +1631,28 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
|
||||
col2 = 0;
|
||||
}
|
||||
|
||||
Decoration *decor = NULL, tmp = { 0 };
|
||||
|
||||
if (kv_size(virt_text) || priority != DECOR_PRIORITY_BASE) {
|
||||
// TODO(bfredl): this is a bit sketchy. eventually we should
|
||||
// have predefined decorations for both marks/ephemerals
|
||||
decor = ephemeral ? &tmp : xcalloc(1, sizeof(*decor));
|
||||
decor->hl_id = hl_id;
|
||||
decor->virt_text = virt_text;
|
||||
decor->priority = priority;
|
||||
decor->virt_text_pos = virt_text_pos;
|
||||
} else if (hl_id) {
|
||||
decor = decor_hl(hl_id);
|
||||
}
|
||||
|
||||
// TODO(bfredl): synergize these two branches even more
|
||||
if (ephemeral && decor_state.buf == buf) {
|
||||
int attr_id = hl_id > 0 ? syn_id2attr(hl_id) : 0;
|
||||
VirtText *vt_allocated = NULL;
|
||||
if (kv_size(virt_text)) {
|
||||
vt_allocated = xmalloc(sizeof *vt_allocated);
|
||||
*vt_allocated = virt_text;
|
||||
}
|
||||
decor_add_ephemeral(attr_id, (int)line, (colnr_T)col,
|
||||
(int)line2, (colnr_T)col2, priority, vt_allocated);
|
||||
decor_add_ephemeral((int)line, (int)col, line2, col2, decor, 0);
|
||||
} else {
|
||||
if (ephemeral) {
|
||||
api_set_error(err, kErrorTypeException, "not yet implemented");
|
||||
goto error;
|
||||
}
|
||||
Decoration *decor = NULL;
|
||||
if (kv_size(virt_text)) {
|
||||
decor = xcalloc(1, sizeof(*decor));
|
||||
decor->hl_id = hl_id;
|
||||
decor->virt_text = virt_text;
|
||||
} else if (hl_id) {
|
||||
decor = decor_hl(hl_id);
|
||||
decor->priority = priority;
|
||||
}
|
||||
|
||||
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
|
||||
line2, col2, decor, right_gravity,
|
||||
|
@ -188,20 +188,21 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
|
||||
goto next_mark;
|
||||
}
|
||||
|
||||
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
|
||||
VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
|
||||
HlRange range;
|
||||
if (mark.id&MARKTREE_END_FLAG) {
|
||||
range = (HlRange){ altpos.row, altpos.col, mark.row, mark.col,
|
||||
attr_id, decor->priority, vt, false };
|
||||
decor_add(state, altpos.row, altpos.col, mark.row, mark.col,
|
||||
decor, false, 0);
|
||||
} else {
|
||||
range = (HlRange){ mark.row, mark.col, altpos.row,
|
||||
altpos.col, attr_id, decor->priority, vt, false };
|
||||
if (altpos.row == -1) {
|
||||
altpos.row = mark.row;
|
||||
altpos.col = mark.col;
|
||||
}
|
||||
decor_add(state, mark.row, mark.col, altpos.row, altpos.col,
|
||||
decor, false, 0);
|
||||
}
|
||||
hlrange_activate(range, state);
|
||||
|
||||
next_mark:
|
||||
if (marktree_itr_node_done(state->itr)) {
|
||||
marktree_itr_next(buf->b_marktree, state->itr);
|
||||
break;
|
||||
}
|
||||
marktree_itr_next(buf->b_marktree, state->itr);
|
||||
@ -220,41 +221,39 @@ bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
|
||||
return true; // TODO(bfredl): be more precise
|
||||
}
|
||||
|
||||
static void hlrange_activate(HlRange range, DecorState *state)
|
||||
static void decor_add(DecorState *state, int start_row, int start_col,
|
||||
int end_row, int end_col, Decoration *decor, bool owned,
|
||||
DecorPriority priority)
|
||||
{
|
||||
// Get size before preparing the push, to have the number of elements
|
||||
size_t s = kv_size(state->active);
|
||||
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
|
||||
|
||||
HlRange range = { start_row, start_col, end_row, end_col,
|
||||
attr_id, MAX(priority, decor->priority),
|
||||
kv_size(decor->virt_text) ? &decor->virt_text : NULL,
|
||||
decor->virt_text_pos,
|
||||
kv_size(decor->virt_text) && owned, -1 };
|
||||
|
||||
kv_pushp(state->active);
|
||||
|
||||
size_t dest_index = 0;
|
||||
|
||||
// Determine insertion dest_index
|
||||
while (dest_index < s) {
|
||||
HlRange item = kv_A(state->active, dest_index);
|
||||
if (item.priority > range.priority) {
|
||||
size_t index;
|
||||
for (index = kv_size(state->active)-1; index > 0; index--) {
|
||||
HlRange item = kv_A(state->active, index-1);
|
||||
if (item.priority <= range.priority) {
|
||||
break;
|
||||
}
|
||||
|
||||
dest_index++;
|
||||
}
|
||||
|
||||
// Splice
|
||||
for (size_t index = s; index > dest_index; index--) {
|
||||
kv_A(state->active, index) = kv_A(state->active, index-1);
|
||||
}
|
||||
|
||||
// Insert
|
||||
kv_A(state->active, dest_index) = range;
|
||||
kv_A(state->active, index) = range;
|
||||
}
|
||||
|
||||
int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||
int decor_redraw_col(buf_T *buf, int col, int virt_col, DecorState *state)
|
||||
{
|
||||
if (col <= state->col_until) {
|
||||
return state->current;
|
||||
}
|
||||
state->col_until = MAXCOL;
|
||||
while (true) {
|
||||
// TODO(bfredl): check duplicate entry in "intersection"
|
||||
// branch
|
||||
mtmark_t mark = marktree_itr_current(state->itr);
|
||||
if (mark.row < 0 || mark.row > state->row) {
|
||||
break;
|
||||
@ -278,6 +277,11 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||
}
|
||||
Decoration *decor = item->decor;
|
||||
|
||||
if (endpos.row == -1) {
|
||||
endpos.row = mark.row;
|
||||
endpos.col = mark.col;
|
||||
}
|
||||
|
||||
if (endpos.row < mark.row
|
||||
|| (endpos.row == mark.row && endpos.col <= mark.col)) {
|
||||
if (!kv_size(decor->virt_text)) {
|
||||
@ -285,12 +289,8 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
|
||||
}
|
||||
}
|
||||
|
||||
int attr_id = decor->hl_id > 0 ? syn_id2attr(decor->hl_id) : 0;
|
||||
VirtText *vt = kv_size(decor->virt_text) ? &decor->virt_text : NULL;
|
||||
hlrange_activate((HlRange){ mark.row, mark.col,
|
||||
endpos.row, endpos.col,
|
||||
attr_id, decor->priority,
|
||||
vt, false }, state);
|
||||
decor_add(state, mark.row, mark.col, endpos.row, endpos.col,
|
||||
decor, false, 0);
|
||||
|
||||
next_mark:
|
||||
marktree_itr_next(buf->b_marktree, state->itr);
|
||||
@ -310,7 +310,7 @@ next_mark:
|
||||
if (item.start_row < state->row
|
||||
|| (item.start_row == state->row && item.start_col <= col)) {
|
||||
active = true;
|
||||
if (item.end_row == state->row) {
|
||||
if (item.end_row == state->row && item.end_col > col) {
|
||||
state->col_until = MIN(state->col_until, item.end_col-1);
|
||||
}
|
||||
} else {
|
||||
@ -322,8 +322,12 @@ next_mark:
|
||||
if (active && item.attr_id > 0) {
|
||||
attr = hl_combine_attr(attr, item.attr_id);
|
||||
}
|
||||
if ((item.start_row == state->row && item.start_col <= col)
|
||||
&& item.virt_text && item.virt_col == -1) {
|
||||
item.virt_col = virt_col;
|
||||
}
|
||||
if (keep) {
|
||||
kv_A(state->active, j++) = kv_A(state->active, i);
|
||||
kv_A(state->active, j++) = item;
|
||||
} else if (item.virt_text_owned) {
|
||||
clear_virttext(item.virt_text);
|
||||
xfree(item.virt_text);
|
||||
@ -341,21 +345,20 @@ void decor_redraw_end(DecorState *state)
|
||||
|
||||
VirtText *decor_redraw_virt_text(buf_T *buf, DecorState *state)
|
||||
{
|
||||
decor_redraw_col(buf, MAXCOL, state);
|
||||
decor_redraw_col(buf, MAXCOL, MAXCOL, state);
|
||||
for (size_t i = 0; i < kv_size(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
|
||||
&& item.virt_text_pos == kVTEndOfLine) {
|
||||
return item.virt_text;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void decor_add_ephemeral(int attr_id, int start_row, int start_col,
|
||||
int end_row, int end_col, DecorPriority priority,
|
||||
VirtText *virt_text)
|
||||
void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
|
||||
Decoration *decor, DecorPriority priority)
|
||||
{
|
||||
hlrange_activate(((HlRange){ start_row, start_col, end_row, end_col, attr_id,
|
||||
priority, virt_text, virt_text != NULL }),
|
||||
&decor_state);
|
||||
decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true,
|
||||
priority);
|
||||
}
|
||||
|
@ -18,10 +18,16 @@ typedef kvec_t(VirtTextChunk) VirtText;
|
||||
typedef uint16_t DecorPriority;
|
||||
#define DECOR_PRIORITY_BASE 0x1000
|
||||
|
||||
typedef enum {
|
||||
kVTEndOfLine,
|
||||
kVTOverlay,
|
||||
} VirtTextPos;
|
||||
|
||||
struct Decoration
|
||||
{
|
||||
int hl_id; // highlight group
|
||||
VirtText virt_text;
|
||||
VirtTextPos virt_text_pos;
|
||||
// TODO(bfredl): style, signs, etc
|
||||
DecorPriority priority;
|
||||
bool shared; // shared decoration, don't free
|
||||
@ -35,7 +41,9 @@ typedef struct {
|
||||
int attr_id;
|
||||
DecorPriority priority;
|
||||
VirtText *virt_text;
|
||||
VirtTextPos virt_text_pos;
|
||||
bool virt_text_owned;
|
||||
int virt_col;
|
||||
} HlRange;
|
||||
|
||||
typedef struct {
|
||||
|
@ -143,7 +143,7 @@ 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;
|
||||
const char *p;
|
||||
int prev_c; // previous Arabic character
|
||||
int prev_c1; // first composing char for prev_c
|
||||
} LineState;
|
||||
@ -1857,7 +1857,7 @@ static int compute_foldcolumn(win_T *wp, int col)
|
||||
/// 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;
|
||||
const char_u *p = (char_u *)s->p;
|
||||
int cells = utf_ptr2cells(p);
|
||||
int c_len = utfc_ptr2len(p);
|
||||
int u8c, u8cc[MAX_MCO];
|
||||
@ -2870,6 +2870,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
&& vcol >= (long)wp->w_virtcol)
|
||||
|| (number_only && draw_state > WL_NR))
|
||||
&& filler_todo <= 0) {
|
||||
draw_virt_text(buf, &col, grid->Columns);
|
||||
grid_put_linebuf(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp,
|
||||
wp->w_hl_attr_normal, false);
|
||||
// Pretend we have finished updating the window. Except when
|
||||
@ -3397,7 +3398,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
}
|
||||
|
||||
if (has_decor && v > 0) {
|
||||
int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1,
|
||||
int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, off,
|
||||
&decor_state);
|
||||
if (extmark_attr != 0) {
|
||||
if (!attr_pri) {
|
||||
@ -3919,7 +3920,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
int i;
|
||||
|
||||
size_t virt_pos = 0;
|
||||
LineState s = LINE_STATE((char_u *)"");
|
||||
LineState s = LINE_STATE("");
|
||||
int virt_attr = 0;
|
||||
|
||||
// Make sure alignment is the same regardless
|
||||
@ -3963,7 +3964,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
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;
|
||||
s.p = 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++;
|
||||
@ -4029,6 +4030,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
col += n;
|
||||
}
|
||||
}
|
||||
|
||||
draw_virt_text(buf, &col, grid->Columns);
|
||||
grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
|
||||
wp->w_hl_attr_normal, false);
|
||||
row++;
|
||||
@ -4247,7 +4250,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
&& (grid->Columns == Columns // Window spans the width of the screen,
|
||||
|| ui_has(kUIMultigrid)) // or has dedicated grid.
|
||||
&& !wp->w_p_rl; // Not right-to-left.
|
||||
grid_put_linebuf(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl,
|
||||
|
||||
int draw_col = col - boguscols;
|
||||
draw_virt_text(buf, &draw_col, grid->Columns);
|
||||
grid_put_linebuf(grid, row, 0, draw_col, grid->Columns, wp->w_p_rl,
|
||||
wp, wp->w_hl_attr_normal, wrap);
|
||||
if (wrap) {
|
||||
ScreenGrid *current_grid = grid;
|
||||
@ -4323,6 +4329,43 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|
||||
return row;
|
||||
}
|
||||
|
||||
void draw_virt_text(buf_T *buf, int *end_col, int max_col)
|
||||
{
|
||||
DecorState *state = &decor_state;
|
||||
for (size_t i = 0; i < kv_size(state->active); i++) {
|
||||
HlRange *item = &kv_A(state->active, i);
|
||||
if (item->start_row == state->row && item->virt_text
|
||||
&& item->virt_text_pos == kVTOverlay
|
||||
&& item->virt_col >= 0) {
|
||||
VirtText vt = *item->virt_text;
|
||||
LineState s = LINE_STATE("");
|
||||
int virt_attr = 0;
|
||||
int col = item->virt_col;
|
||||
size_t virt_pos = 0;
|
||||
item->virt_col = -2; // deactivate
|
||||
|
||||
while (col < max_col) {
|
||||
if (!*s.p) {
|
||||
if (virt_pos == kv_size(vt)) {
|
||||
break;
|
||||
}
|
||||
s.p = kv_A(vt, virt_pos).text;
|
||||
int hl_id = kv_A(vt, virt_pos).hl_id;
|
||||
virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
|
||||
virt_pos++;
|
||||
continue;
|
||||
}
|
||||
int cells = line_putchar(&s, &linebuf_char[col], 2, false);
|
||||
linebuf_attr[col++] = virt_attr;
|
||||
if (cells > 1) {
|
||||
linebuf_attr[col++] = virt_attr;
|
||||
}
|
||||
}
|
||||
*end_col = MAX(*end_col, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine if dedicated window grid should be used or the default_grid
|
||||
///
|
||||
/// If UI did not request multigrid support, draw all windows on the
|
||||
|
@ -302,3 +302,98 @@ describe('decorations providers', function()
|
||||
]]}
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('extmark decorations', function()
|
||||
local screen
|
||||
before_each( function()
|
||||
clear()
|
||||
screen = Screen.new(50, 15)
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids {
|
||||
[1] = {bold=true, foreground=Screen.colors.Blue};
|
||||
[2] = {foreground = Screen.colors.Brown};
|
||||
[3] = {bold = true, foreground = Screen.colors.SeaGreen};
|
||||
[4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
|
||||
}
|
||||
end)
|
||||
|
||||
it('can have virtual text of overlay style', function()
|
||||
insert [[
|
||||
for _,item in ipairs(items) do
|
||||
local text, hl_id_cell, count = unpack(item)
|
||||
if hl_id_cell ~= nil then
|
||||
hl_id = hl_id_cell
|
||||
end
|
||||
for _ = 1, (count or 1) do
|
||||
local cell = line[colpos]
|
||||
cell.text = text
|
||||
cell.hl_id = hl_id
|
||||
colpos = colpos+1
|
||||
end
|
||||
end]]
|
||||
feed 'gg'
|
||||
|
||||
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
|
||||
meths.buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
||||
|
||||
-- can "float" beyond end of line
|
||||
meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
|
||||
-- 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'})
|
||||
|
||||
screen:expect{grid=[[
|
||||
^for _,item in ipairs(items) do |
|
||||
{2:|} local text, hl_id_cell, count = unpack(item) |
|
||||
{2:|} if hl_id_cell ~= nil tbork bork bork {4:bork bork}|
|
||||
{2:|} {1:|} hl_id = hl_id_cell |
|
||||
{2:|} end |
|
||||
{2:|} for _ = 1, (count or 1) {4:loopy} |
|
||||
{2:|} {1:|} local cell = line[colpos] |
|
||||
{2:|} {1:|} cell.text = text |
|
||||
{2:|} {1:|} cell.hl_id = hl_id |
|
||||
{2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
|
||||
end |
|
||||
end |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
|
||||
|
||||
-- handles broken lines
|
||||
screen:try_resize(22, 25)
|
||||
screen:expect{grid=[[
|
||||
^for _,item in ipairs(i|
|
||||
tems) do |
|
||||
{2:|} local text, hl_id_|
|
||||
cell, count = unpack(i|
|
||||
tem) |
|
||||
{2:|} if hl_id_cell ~= n|
|
||||
il tbork bork bork {4:bor}|
|
||||
{2:|} {1:|} hl_id = hl_id_|
|
||||
cell |
|
||||
{2:|} end |
|
||||
{2:|} for _ = 1, (count |
|
||||
or 1) {4:loopy} |
|
||||
{2:|} {1:|} local cell = l|
|
||||
ine[colpos] |
|
||||
{2:|} {1:|} cell.text = te|
|
||||
xt |
|
||||
{2:|} {1:|} cell.hl_id = h|
|
||||
l_id |
|
||||
{2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
|
||||
s+1 |
|
||||
end |
|
||||
end |
|
||||
{1:~ }|
|
||||
{1:~ }|
|
||||
|
|
||||
]]}
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user