diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 781d759c82..8784a395f2 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -199,7 +199,7 @@ the editor. The following keys are deprecated: `hl_id`: Use `attr_id` instead. - `hl_lm`: Use `attr_id_lm` instead. + `id_lm`: Use `attr_id_lm` instead. ["option_set", name, value] ~ UI-related option changed, where `name` is one of: @@ -336,7 +336,7 @@ numerical highlight ids to the actual attributes. Highlights are always transmitted both for both the RGB format and as terminal 256-color codes, as the `rgb_attr` and `cterm_attr` parameters - respectively. The |ui-rgb| option has no effect effect anymore. + respectively. The |ui-rgb| option has no effect anymore. Most external UIs will only need to store and use the `rgb_attr` attributes. @@ -352,7 +352,7 @@ numerical highlight ids to the actual attributes. |ui-hlstate| extension explained below. ["hl_group_set", name, hl_id] ~ - The bulitin highlight group `name` was set to use the attributes `hl_id` + The built-in highlight group `name` was set to use the attributes `hl_id` defined by a previous `hl_attr_define` call. This event is not needed to render the grids which use attribute ids directly, but is useful for a UI who want to render its own elements with consistent @@ -434,7 +434,7 @@ numerical highlight ids to the actual attributes. +-------------------------+ < `cols` is always zero in this version of Nvim, and reserved for future - use. + use. Note when updating code from |ui-grid-old| events: ranges are end-exclusive, which is consistent with API conventions, but different @@ -640,7 +640,8 @@ tabs. the top line of a window moved since `win_viewport` was last emitted. It is intended to be used to implement smooth scrolling. For this purpose it only counts "virtual" or "displayed" lines, so folds - only count as one line. + only count as one line. When scrolling more than a full screen it is + an approximate value. All updates, such as `grid_line`, in a batch affects the new viewport, despite the fact that `win_viewport` is received after the updates. @@ -651,7 +652,7 @@ tabs. ["win_extmark", grid, win, ns_id, mark_id, row, col] ~ Updates the position of an extmark which is currently visible in a - window. Only emitted if the mark has the `ui_watched` attribute. + window. Only emitted if the mark has the `ui_watched` attribute. ============================================================================== Popupmenu Events *ui-popupmenu* @@ -723,7 +724,7 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|. to distinguish different command lines active at the same time. The first invoked command line has level 1, the next recursively-invoked prompt has level 2. A command line invoked from the |cmdline-window| - has a higher level than than the edited command line. + has a higher level than the edited command line. ["cmdline_pos", pos, level] ~ Change the cursor position in the cmdline. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 34fad4a632..8b2f09b88c 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1223,6 +1223,9 @@ struct window_S { bool w_viewport_invalid; linenr_T w_viewport_last_topline; // topline when the viewport was last updated + linenr_T w_viewport_last_botline; // botline when the viewport was last updated + linenr_T w_viewport_last_topfill; // topfill when the viewport was last updated + linenr_T w_viewport_last_skipcol; // skipcol when the viewport was last updated // w_cline_height is the number of physical lines taken by the buffer line // that the cursor is on. We use this to avoid extra calls to plines_win(). diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 71984e806d..237fc08631 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -771,7 +771,7 @@ void clearFolding(win_T *win) /// The changes in lines from top to bot (inclusive). void foldUpdate(win_T *wp, linenr_T top, linenr_T bot) { - if (disable_fold_update || State & MODE_INSERT) { + if (disable_fold_update || (State & MODE_INSERT && !foldmethodIsIndent(wp))) { return; } diff --git a/src/nvim/main.c b/src/nvim/main.c index 779b88af4e..650c10c855 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -629,6 +629,8 @@ int main(int argc, char **argv) } if (params.luaf != NULL) { + // Like "--cmd", "+", "-c" and "-S", don't truncate messages. + msg_scroll = true; bool lua_ok = nlua_exec_file(params.luaf); TIME_MSG("executing Lua -l script"); getout(lua_ok ? 0 : 1); diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 9b1d84c756..cf2fbabcdb 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1300,14 +1300,13 @@ retnomove: } first = false; - if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline) - && curwin->w_topline == curbuf->b_ml.ml_line_count) { - break; - } - if (curwin->w_topfill > 0) { curwin->w_topfill--; } else { + if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline) + && curwin->w_topline == curbuf->b_ml.ml_line_count) { + break; + } curwin->w_topline++; curwin->w_topfill = win_get_fill(curwin, curwin->w_topline); } @@ -1393,8 +1392,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) while (row > 0) { // Don't include filler lines in "count" - if (win_may_fill(win) - && !hasFoldingWin(win, lnum, NULL, NULL, true, NULL)) { + if (win_may_fill(win)) { if (lnum == win->w_topline) { row -= win->w_topfill; } else { diff --git a/src/nvim/move.c b/src/nvim/move.c index ef52fac008..5d8136107e 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -943,21 +943,20 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, bool visible_row = false; bool is_folded = false; - if (pos->lnum >= wp->w_topline && pos->lnum <= wp->w_botline) { - linenr_T lnum = pos->lnum; + linenr_T lnum = pos->lnum; + if (lnum >= wp->w_topline && lnum <= wp->w_botline) { is_folded = hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL); row = plines_m_win(wp, wp->w_topline, lnum - 1) + 1; // Add filler lines above this buffer line. - row += win_get_fill(wp, lnum); + row += lnum == wp->w_topline ? wp->w_topfill : win_get_fill(wp, lnum); visible_row = true; - } else if (!local || pos->lnum < wp->w_topline) { + } else if (!local || lnum < wp->w_topline) { row = 0; } else { row = wp->w_height_inner; } - bool existing_row = (pos->lnum > 0 - && pos->lnum <= wp->w_buffer->b_ml.ml_line_count); + bool existing_row = (lnum > 0 && lnum <= wp->w_buffer->b_ml.ml_line_count); if ((local || visible_row) && existing_row) { const colnr_T off = win_col_off(wp); @@ -965,6 +964,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, row += local ? 0 : wp->w_winrow + wp->w_winrow_off; coloff = (local ? 0 : wp->w_wincol + wp->w_wincol_off) + 1 + off; } else { + assert(lnum == pos->lnum); getvcol(wp, pos, &scol, &ccol, &ecol); // similar to what is done in validate_cursor_col() @@ -972,6 +972,10 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, col += off; int width = wp->w_width_inner - off + win_col_off2(wp); + if (lnum == wp->w_topline) { + col -= wp->w_skipcol; + } + // long line wrapping, adjust row if (wp->w_p_wrap && col >= (colnr_T)wp->w_width_inner && width > 0) { // use same formula as what is used in curs_columns() diff --git a/src/nvim/plines.c b/src/nvim/plines.c index a3e5640b18..50449671ce 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -38,8 +38,7 @@ /// @param winheight when true limit to window height int plines_win(win_T *wp, linenr_T lnum, bool winheight) { - // Check for filler lines above this buffer line. When folded the result - // is one line anyway. + // Check for filler lines above this buffer line. return plines_win_nofill(wp, lnum, winheight) + win_get_fill(wp, lnum); } @@ -133,8 +132,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum) /// used from the start of the line to the given column number. int plines_win_col(win_T *wp, linenr_T lnum, long column) { - // Check for filler lines above this buffer line. When folded the result - // is one line anyway. + // Check for filler lines above this buffer line. int lines = win_get_fill(wp, lnum); if (!wp->w_p_wrap) { @@ -194,16 +192,12 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const foldedp, const bool cache) { - bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL); - if (foldedp) { + bool folded = hasFoldingWin(wp, lnum, &lnum, nextp, cache, NULL); + if (foldedp != NULL) { *foldedp = folded; } - if (folded) { - return 1; - } else if (lnum == wp->w_topline) { - return plines_win_nofill(wp, lnum, true) + wp->w_topfill; - } - return plines_win(wp, lnum, true); + return ((folded ? 1 : plines_win_nofill(wp, lnum, true)) + + (lnum == wp->w_topline ? wp->w_topfill : win_get_fill(wp, lnum))); } int plines_m_win(win_T *wp, linenr_T first, linenr_T last) @@ -536,3 +530,68 @@ static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp) } return n; } + +/// Get the number of screen lines a range of text will take in window "wp". +/// +/// @param[in] start_lnum Starting line number, 1-based inclusive. +/// @param[in] start_vcol >= 0: Starting virtual column index on "start_lnum", +/// 0-based inclusive, rounded down to full screen lines. +/// < 0: Count a full "start_lnum", including filler lines above. +/// @param[in] end_lnum Ending line number, 1-based inclusive. +/// @param[in] end_vcol >= 0: Ending virtual column index on "end_lnum", +/// 0-based exclusive, rounded up to full screen lines. +/// < 0: Count a full "end_lnum", not including filler lines below. +/// @param[out] fill If not NULL, set to the number of filler lines in the range. +int64_t win_text_height(win_T *const wp, const linenr_T start_lnum, const int64_t start_vcol, + const linenr_T end_lnum, const int64_t end_vcol, int64_t *const fill) +{ + int width1 = 0; + int width2 = 0; + if (start_vcol >= 0 || end_vcol >= 0) { + width1 = wp->w_width_inner - win_col_off(wp); + width2 = width1 + win_col_off2(wp); + width1 = MAX(width1, 0); + width2 = MAX(width2, 0); + } + + int64_t height_sum_fill = 0; + int64_t height_cur_nofill = 0; + int64_t height_sum_nofill = 0; + linenr_T lnum = start_lnum; + + if (start_vcol >= 0) { + linenr_T lnum_next = lnum; + const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); + height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); + height_sum_nofill += height_cur_nofill; + const int64_t row_off = (start_vcol < width1 || width2 <= 0) + ? 0 + : 1 + (start_vcol - width1) / width2; + height_sum_nofill -= MIN(row_off, height_cur_nofill); + lnum = lnum_next + 1; + } + + while (lnum <= end_lnum) { + linenr_T lnum_next = lnum; + const bool folded = hasFoldingWin(wp, lnum, &lnum, &lnum_next, true, NULL); + height_sum_fill += win_get_fill(wp, lnum); + height_cur_nofill = folded ? 1 : plines_win_nofill(wp, lnum, false); + height_sum_nofill += height_cur_nofill; + lnum = lnum_next + 1; + } + + if (end_vcol >= 0) { + height_sum_nofill -= height_cur_nofill; + const int64_t row_off = end_vcol == 0 + ? 0 + : (end_vcol <= width1 || width2 <= 0) + ? 1 + : 1 + (end_vcol - width1 + width2 - 1) / width2; + height_sum_nofill += MIN(row_off, height_cur_nofill); + } + + if (fill != NULL) { + *fill = height_sum_fill; + } + return height_sum_fill + height_sum_nofill; +} diff --git a/src/nvim/window.c b/src/nvim/window.c index 26c533f2a3..ff2a01b827 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -990,29 +990,56 @@ void ui_ext_win_viewport(win_T *wp) // NOTE: The win_viewport command is delayed until the next flush when there are pending updates. // This ensures that the updates and the viewport are sent together. if ((wp == curwin || ui_has(kUIMultigrid)) && wp->w_viewport_invalid && wp->w_redr_type == 0) { - int botline = wp->w_botline; - int line_count = wp->w_buffer->b_ml.ml_line_count; - if (botline == line_count + 1 && wp->w_empty_rows == 0) { + const linenr_T line_count = wp->w_buffer->b_ml.ml_line_count; + // Avoid ml_get errors when producing "scroll_delta". + const linenr_T cur_topline = MIN(wp->w_topline, line_count); + const linenr_T cur_botline = MIN(wp->w_botline, line_count); + int64_t delta = 0; + linenr_T last_topline = wp->w_viewport_last_topline; + linenr_T last_botline = wp->w_viewport_last_botline; + int last_topfill = wp->w_viewport_last_topfill; + int64_t last_skipcol = wp->w_viewport_last_skipcol; + if (last_topline > line_count) { + delta -= last_topline - line_count; + last_topline = line_count; + last_topfill = 0; + last_skipcol = MAXCOL; + } + last_botline = MIN(last_botline, line_count); + if (cur_topline < last_topline + || (cur_topline == last_topline && wp->w_skipcol < last_skipcol)) { + if (last_topline > 0 && cur_botline < last_topline) { + // Scrolling too many lines: only give an approximate "scroll_delta". + delta -= win_text_height(wp, cur_topline, wp->w_skipcol, cur_botline, 0, NULL); + delta -= last_topline - cur_botline; + } else { + delta -= win_text_height(wp, cur_topline, wp->w_skipcol, last_topline, last_skipcol, NULL); + } + } else if (cur_topline > last_topline + || (cur_topline == last_topline && wp->w_skipcol > last_skipcol)) { + if (last_botline > 0 && cur_topline > last_botline) { + // Scrolling too many lines: only give an approximate "scroll_delta". + delta += win_text_height(wp, last_topline, last_skipcol, last_botline, 0, NULL); + delta += cur_topline - last_botline; + } else { + delta += win_text_height(wp, last_topline, last_skipcol, cur_topline, wp->w_skipcol, NULL); + } + } + delta += last_topfill; + delta -= wp->w_topfill; + linenr_T ev_botline = wp->w_botline; + if (ev_botline == line_count + 1 && wp->w_empty_rows == 0) { // TODO(bfredl): The might be more cases to consider, like how does this // interact with incomplete final line? Diff filler lines? - botline = wp->w_buffer->b_ml.ml_line_count; + ev_botline = line_count; } - int scroll_delta = 0; - if (wp->w_viewport_last_topline > line_count) { - scroll_delta -= wp->w_viewport_last_topline - line_count; - wp->w_viewport_last_topline = line_count; - } - if (wp->w_topline < wp->w_viewport_last_topline) { - scroll_delta -= plines_m_win(wp, wp->w_topline, wp->w_viewport_last_topline - 1); - } else if (wp->w_topline > wp->w_viewport_last_topline - && wp->w_topline <= line_count) { - scroll_delta += plines_m_win(wp, wp->w_viewport_last_topline, wp->w_topline - 1); - } - ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, - botline, wp->w_cursor.lnum - 1, wp->w_cursor.col, - line_count, scroll_delta); + ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, ev_botline, + wp->w_cursor.lnum - 1, wp->w_cursor.col, line_count, delta); wp->w_viewport_invalid = false; wp->w_viewport_last_topline = wp->w_topline; + wp->w_viewport_last_botline = wp->w_botline; + wp->w_viewport_last_topfill = wp->w_topfill; + wp->w_viewport_last_skipcol = wp->w_skipcol; } } diff --git a/test/functional/core/remote_spec.lua b/test/functional/core/remote_spec.lua index 15cc408437..a0ec748446 100644 --- a/test/functional/core/remote_spec.lua +++ b/test/functional/core/remote_spec.lua @@ -106,6 +106,7 @@ describe('Remote', function() eq({ '0', '' }, run_remote('--remote-expr', 'setline(1, "Yo")')) eq({ 'Yo', '' }, run_remote('--remote-expr', 'getline(1)')) expect('Yo') + eq({ ('k'):rep(1234), '' }, run_remote('--remote-expr', 'repeat("k", 1234)')) eq({ '1.25', '' }, run_remote('--remote-expr', '1.25')) eq({ 'no', '' }, run_remote('--remote-expr', '0z6E6F')) eq({ '\t', '' }, run_remote('--remote-expr', '"\t"')) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 2464e53a7a..245d0ace11 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -99,10 +99,11 @@ describe('startup', function() it('os.exit() sets Nvim exitcode', function() -- tricky: LeakSanitizer triggers on os.exit() and disrupts the return value, disable it exec_lua [[ - local asan_options = os.getenv 'ASAN_OPTIONS' - if asan_options ~= nil and asan_options ~= '' then - vim.loop.os_setenv('ASAN_OPTIONS', asan_options..':detect_leaks=0') + local asan_options = os.getenv('ASAN_OPTIONS') or '' + if asan_options ~= '' then + asan_options = asan_options .. ':' end + vim.loop.os_setenv('ASAN_OPTIONS', asan_options .. ':detect_leaks=0') ]] -- nvim -l foo.lua -arg1 -- a b c assert_l_out([[ @@ -141,6 +142,14 @@ describe('startup', function() eq(0, eval('v:shell_error')) end) + it('does not truncate long print() message', function() + assert_l_out(('k'):rep(1234), + nil, + nil, + '-', + "print(('k'):rep(1234))") + end) + it('sets _G.arg', function() -- nvim -l foo.lua assert_l_out([[ @@ -217,6 +226,15 @@ describe('startup', function() end) end) + it('--cmd/-c/+ do not truncate long Lua print() message with --headless', function() + local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', + '--cmd', 'lua print(("A"):rep(1234))', + '-c', 'lua print(("B"):rep(1234))', + '+lua print(("C"):rep(1234))', + '+q' }) + eq(('A'):rep(1234) .. '\r\n' .. ('B'):rep(1234) .. '\r\n' .. ('C'):rep(1234), out) + end) + it('pipe at both ends: has("ttyin")==0 has("ttyout")==0', function() -- system() puts a pipe at both ends. local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', diff --git a/test/functional/editor/fold_spec.lua b/test/functional/editor/fold_spec.lua index 3115c20410..568b2d0281 100644 --- a/test/functional/editor/fold_spec.lua +++ b/test/functional/editor/fold_spec.lua @@ -7,6 +7,7 @@ local expect = helpers.expect local command = helpers.command local funcs = helpers.funcs local eq = helpers.eq +local neq = helpers.neq describe('Folds', function() local tempfname = 'Xtest-fold.txt' @@ -417,4 +418,31 @@ a]], '13m7') eq(1, funcs.foldlevel(1)) eq(1, funcs.foldlevel(2)) end) + + it("doesn't open folds with indent method when inserting lower foldlevel line", function() + insert([[ + insert an unindented line under this line + keep the lines under this line folded + keep this line folded 1 + keep this line folded 2 + ]]) + command('set foldmethod=indent shiftwidth=2 noautoindent') + eq(1, funcs.foldlevel(1)) + eq(1, funcs.foldlevel(2)) + eq(2, funcs.foldlevel(3)) + eq(2, funcs.foldlevel(4)) + + feed('zo') -- open the outer fold + neq(-1, funcs.foldclosed(3)) -- make sure the inner fold is not open + + feed('gg0oa') -- insert unindented line + + eq(1, funcs.foldlevel(1)) --| insert an unindented line under this line + eq(0, funcs.foldlevel(2)) --|a + eq(1, funcs.foldlevel(3)) --| keep the lines under this line folded + eq(2, funcs.foldlevel(4)) --| keep this line folded 1 + eq(2, funcs.foldlevel(5)) --| keep this line folded 2 + + neq(-1, funcs.foldclosed(4)) -- make sure the inner fold is still not open + end) end) diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index a99b77f707..daa963195c 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -7,7 +7,6 @@ local insert = helpers.insert local funcs = helpers.funcs local meths = helpers.meths local exec = helpers.exec -local exec_lua = helpers.exec_lua local assert_alive = helpers.assert_alive @@ -43,6 +42,7 @@ describe("folded lines", function() [10] = {background = Screen.colors.LightGrey, underline = true}, [11] = {bold=true}, [12] = {background = Screen.colors.Grey90}, + [16] = {background = Screen.colors.LightGrey}, }) end) @@ -1892,21 +1892,19 @@ describe("folded lines", function() end end) - it('fold attached virtual lines are drawn correctly #21837', function() + it('fold attached virtual lines are drawn and scrolled correctly #21837', function() funcs.setline(1, 'line 1') funcs.setline(2, 'line 2') funcs.setline(3, 'line 3') funcs.setline(4, 'line 4') feed("zfj") - exec_lua([[ - local ns = vim.api.nvim_create_namespace("ns") - vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 1", ""}}} }) - vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"virt_line below line 2", ""}}} }) - vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 3", ""}}} }) - vim.api.nvim_buf_set_extmark(0, ns, 3, 0, { virt_lines = {{{"virt_line below line 4", ""}}} }) - ]]) + local ns = meths.create_namespace('ns') + meths.buf_set_extmark(0, ns, 0, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 1", ""}}} }) + meths.buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"virt_line below line 2", ""}}} }) + meths.buf_set_extmark(0, ns, 2, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 3", ""}}} }) + meths.buf_set_extmark(0, ns, 3, 0, { virt_lines = {{{"virt_line below line 4", ""}}} }) if multigrid then - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [2:---------------------------------------------]| [2:---------------------------------------------]| @@ -1926,7 +1924,9 @@ describe("folded lines", function() {1:~ }| ## grid 3 | - ]]) + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 5, curline = 0, curcol = 0, linecount = 4, sum_scroll_delta = 0}; + }} else screen:expect([[ {5:^+-- 2 lines: line 1·························}| @@ -1942,7 +1942,7 @@ describe("folded lines", function() feed('jzfj') if multigrid then - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [2:---------------------------------------------]| [2:---------------------------------------------]| @@ -1962,7 +1962,9 @@ describe("folded lines", function() {1:~ }| ## grid 3 | - ]]) + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 5, curline = 2, curcol = 0, linecount = 4, sum_scroll_delta = 0}; + }} else screen:expect([[ {5:+-- 2 lines: line 1·························}| @@ -1979,7 +1981,7 @@ describe("folded lines", function() feed('kzo') funcs.setline(5, 'line 5') if multigrid then - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [2:---------------------------------------------]| [2:---------------------------------------------]| @@ -1999,7 +2001,9 @@ describe("folded lines", function() {1:~ }| ## grid 3 | - ]]) + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = -1}; + }} else screen:expect([[ virt_line above line 1 | @@ -2012,6 +2016,398 @@ describe("folded lines", function() | ]]) end + + meths.input_mouse('left', 'press', '', multigrid and 2 or 0, 4, 0) + eq({ + column = 1, + line = 3, + screencol = 1, + screenrow = 5, + wincol = 1, + winid = 1000, + winrow = 5, + }, funcs.getmousepos()) + + meths.buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"more virt_line below line 2", ""}}} }) + feed('G') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + line 1 | + line 2 | + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 0}; + }} + else + screen:expect([[ + line 1 | + line 2 | + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + | + ]]) + end + + feed('') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + line 2 | + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 1, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 1}; + }} + else + screen:expect([[ + line 2 | + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2}; + }} + else + screen:expect([[ + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 3}; + }} + else + screen:expect([[ + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 4}; + }} + else + screen:expect([[ + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 4, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 5}; + }} + else + screen:expect([[ + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end + + feed('3') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2}; + }} + else + screen:expect([[ + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^line 5 | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end + + meths.input_mouse('left', 'press', '3', multigrid and 2 or 0, 3, 0) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^l{16:ine 5} | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + {11:-- VISUAL LINE --} | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2}; + }} + else + screen:expect([[ + virt_line below line 2 | + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^l{16:ine 5} | + {1:~ }| + {1:~ }| + {1:~ }| + {11:-- VISUAL LINE --} | + ]]) + end + + meths.input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 0) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^l{16:ine 5} | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + {11:-- VISUAL LINE --} | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 3}; + }} + else + screen:expect([[ + more virt_line below line 2 | + {5:+-- 2 lines: line 3·························}| + ^l{16:ine 5} | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {11:-- VISUAL LINE --} | + ]]) + end + + meths.input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 5) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + {5:+-- 2 lines: line 3·························}| + {16:line }^5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + {11:-- VISUAL LINE --} | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 5, linecount = 5, sum_scroll_delta = 4}; + }} + else + screen:expect([[ + {5:+-- 2 lines: line 3·························}| + {16:line }^5 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {11:-- VISUAL LINE --} | + ]]) + end end) end diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index 4c04bcb54e..d755bcb76a 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -3343,6 +3343,220 @@ describe('ext_multigrid', function() }} end) + it('scroll_delta is approximated reasonably when scrolling many lines #24234', function() + command('setlocal number nowrap') + command('edit test/functional/fixtures/bigfile.txt') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 1 }^0000;;Cc;0;BN;;;;;N;NULL;;;; | + {19: 2 }0001;;Cc;0;BN;;;;;N;START OF HEADING;;| + {19: 3 }0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; | + {19: 4 }0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; | + {19: 5 }0004;;Cc;0;BN;;;;;N;END OF TRANSMISSIO| + {19: 6 }0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; | + {19: 7 }0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; | + {19: 8 }0007;;Cc;0;BN;;;;;N;BELL;;;; | + {19: 9 }0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; | + {19: 10 }0009;;Cc;0;S;;;;;N;CHARACTER TABULATIO| + {19: 11 }000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; | + {19: 12 }000B;;Cc;0;S;;;;;N;LINE TABULATION;;;;| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0}; + }} + feed('G') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19:30581 }E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;| + {19:30582 }E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;| + {19:30583 }E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;| + {19:30584 }E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;| + {19:30585 }E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;| + {19:30586 }E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;| + {19:30587 }E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;| + {19:30588 }E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;| + {19:30589 }F0000;;Co;0;L;;;;;| + {19:30590 }FFFFD;;Co;0;L;;;;;N| + {19:30591 }100000;;Co;0;L;;;;| + {19:30592 }^10FFFD;;Co;0;L;;;;;| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 30580, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30580}; + }} + feed('gg') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 1 }^0000;;Cc;0;BN;;;;;N;NULL;;;; | + {19: 2 }0001;;Cc;0;BN;;;;;N;START OF HEADING;;| + {19: 3 }0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; | + {19: 4 }0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; | + {19: 5 }0004;;Cc;0;BN;;;;;N;END OF TRANSMISSIO| + {19: 6 }0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; | + {19: 7 }0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; | + {19: 8 }0007;;Cc;0;BN;;;;;N;BELL;;;; | + {19: 9 }0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; | + {19: 10 }0009;;Cc;0;S;;;;;N;CHARACTER TABULATIO| + {19: 11 }000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; | + {19: 12 }000B;;Cc;0;S;;;;;N;LINE TABULATION;;;;| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0}; + }} + command('setlocal wrap') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 1 }^0000;;Cc;0;BN;;;;;N;NULL;;;; | + {19: 2 }0001;;Cc;0;BN;;;;;N;START OF HEADING;;| + {19: };; | + {19: 3 }0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; | + {19: 4 }0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; | + {19: 5 }0004;;Cc;0;BN;;;;;N;END OF TRANSMISSIO| + {19: }N;;;; | + {19: 6 }0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; | + {19: 7 }0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; | + {19: 8 }0007;;Cc;0;BN;;;;;N;BELL;;;; | + {19: 9 }0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; | + {19: 10 }0009;;Cc;0;S;;;;;N;CHARACTER TABULA{1:@@@}| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0}; + }} + feed('G') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19:30587 }E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;| + {19: }; | + {19:30588 }E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;| + {19: }; | + {19:30589 }F0000;;Co;0;L;;;;;| + {19: }N;;;;; | + {19:30590 }FFFFD;;Co;0;L;;;;;N| + {19: };;;;; | + {19:30591 }100000;;Co;0;L;;;;| + {19: };N;;;;; | + {19:30592 }^10FFFD;;Co;0;L;;;;;| + {19: }N;;;;; | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 30586, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30588}; + }} + feed('gg') + screen:expect{grid=[[ + ## grid 1 + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {11:test/functional/fixtures/bigfile.txt }| + [3:-----------------------------------------------------]| + ## grid 2 + {19: 1 }^0000;;Cc;0;BN;;;;;N;NULL;;;; | + {19: 2 }0001;;Cc;0;BN;;;;;N;START OF HEADING;;| + {19: };; | + {19: 3 }0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; | + {19: 4 }0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; | + {19: 5 }0004;;Cc;0;BN;;;;;N;END OF TRANSMISSIO| + {19: }N;;;; | + {19: 6 }0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; | + {19: 7 }0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; | + {19: 8 }0007;;Cc;0;BN;;;;;N;BELL;;;; | + {19: 9 }0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; | + {19: 10 }0009;;Cc;0;S;;;;;N;CHARACTER TABULA{1:@@@}| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0}; + }} + end) + it('does not crash when dragging mouse across grid boundary', function() screen:try_resize(48, 8) screen:expect{grid=[[ diff --git a/test/functional/vimscript/screenpos_spec.lua b/test/functional/vimscript/screenpos_spec.lua index 75e5c02298..8b8276457d 100644 --- a/test/functional/vimscript/screenpos_spec.lua +++ b/test/functional/vimscript/screenpos_spec.lua @@ -1,12 +1,12 @@ local helpers = require('test.functional.helpers')(after_each) local clear, eq, meths = helpers.clear, helpers.eq, helpers.meths local command, funcs = helpers.command, helpers.funcs +local feed = helpers.feed before_each(clear) describe('screenpos() function', function() it('works in floating window with border', function() - local bufnr = meths.create_buf(false, true) local opts = { relative='editor', height=8, @@ -18,34 +18,56 @@ describe('screenpos() function', function() border='none', focusable=1 } - local float = meths.open_win(bufnr, false, opts) + local float = meths.open_win(meths.create_buf(false, true), false, opts) command('redraw') - local pos = funcs.screenpos(bufnr, 1, 1) - eq(7, pos.row) - eq(9, pos.col) + eq({row = 7, col = 9, endcol = 9, curscol = 9}, funcs.screenpos(float, 1, 1)) -- only left border opts.border = {'', '', '', '', '', '', '', '|'} meths.win_set_config(float, opts) command('redraw') - pos = funcs.screenpos(bufnr, 1, 1) - eq(7, pos.row) - eq(10, pos.col) + eq({row = 7, col = 10, endcol = 10, curscol = 10}, funcs.screenpos(float, 1, 1)) -- only top border opts.border = {'', '_', '', '', '', '', '', ''} meths.win_set_config(float, opts) command('redraw') - pos = funcs.screenpos(bufnr, 1, 1) - eq(8, pos.row) - eq(9, pos.col) + eq({row = 8, col = 9, endcol = 9, curscol = 9}, funcs.screenpos(float, 1, 1)) -- both left and top border opts.border = 'single' meths.win_set_config(float, opts) command('redraw') - pos = funcs.screenpos(bufnr, 1, 1) - eq(8, pos.row) - eq(10, pos.col) + eq({row = 8, col = 10, endcol = 10, curscol = 10}, funcs.screenpos(float, 1, 1)) + end) + + it('works for folded line with virt_lines attached to line above', function() + meths.buf_set_lines(0, 0, -1, true, {'aaa', 'bbb', 'ccc', 'ddd'}) + local ns = meths.create_namespace('') + meths.buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'abb'}}, {{'acc'}}, {{'add'}}} }) + command('2,3fold') + eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1)) + eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1)) + eq({row = 6, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1)) + + feed('') + eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1)) + eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1)) + eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1)) + + feed('') + eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1)) + eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1)) + eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1)) + + feed('') + eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1)) + eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1)) + eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1)) + + feed('') + eq({row = 1, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1)) + eq({row = 1, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1)) + eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1)) end) end) diff --git a/test/old/testdir/test_cursor_func.vim b/test/old/testdir/test_cursor_func.vim index 239eff5db5..f73bd4f2b9 100644 --- a/test/old/testdir/test_cursor_func.vim +++ b/test/old/testdir/test_cursor_func.vim @@ -125,7 +125,41 @@ func Test_screenpos() \ 'curscol': wincol + 7, \ 'endcol': wincol + 7}, winid->screenpos(line('$'), 8)) call assert_equal({'row': 0, 'col': 0, 'curscol': 0, 'endcol': 0}, - \ winid->screenpos(line('$'), 22)) + \ winid->screenpos(line('$'), 22)) + + 1split + normal G$ + redraw + " w_skipcol should be subtracted + call assert_equal({'row': winrow + 0, + \ 'col': wincol + 20 - 1, + \ 'curscol': wincol + 20 - 1, + \ 'endcol': wincol + 20 - 1}, + \ screenpos(win_getid(), line('.'), col('.'))) + + " w_leftcol should be subtracted + setlocal nowrap + normal 050zl$ + call assert_equal({'row': winrow + 0, + \ 'col': wincol + 10 - 1, + \ 'curscol': wincol + 10 - 1, + \ 'endcol': wincol + 10 - 1}, + \ screenpos(win_getid(), line('.'), col('.'))) + + " w_skipcol should only matter for the topline +" FIXME: This fails because pline_m_win() does not take w_skipcol into +" account. If it does, then other tests fail. +" wincmd + +" setlocal wrap smoothscroll +" call setline(line('$') + 1, 'last line') +" exe "normal \G$" +" redraw +" call assert_equal({'row': winrow + 1, +" \ 'col': wincol + 9 - 1, +" \ 'curscol': wincol + 9 - 1, +" \ 'endcol': wincol + 9 - 1}, +" \ screenpos(win_getid(), line('.'), col('.'))) + close close call assert_equal({}, screenpos(999, 1, 1)) @@ -170,6 +204,19 @@ func Test_screenpos_diff() windo diffthis wincmd w call assert_equal(#{col: 3, row: 7, endcol: 3, curscol: 3}, screenpos(0, 4, 1)) + call assert_equal(#{col: 3, row: 8, endcol: 3, curscol: 3}, screenpos(0, 5, 1)) + exe "normal! 3\" + call assert_equal(#{col: 3, row: 4, endcol: 3, curscol: 3}, screenpos(0, 4, 1)) + call assert_equal(#{col: 3, row: 5, endcol: 3, curscol: 3}, screenpos(0, 5, 1)) + exe "normal! \" + call assert_equal(#{col: 3, row: 3, endcol: 3, curscol: 3}, screenpos(0, 4, 1)) + call assert_equal(#{col: 3, row: 4, endcol: 3, curscol: 3}, screenpos(0, 5, 1)) + exe "normal! \" + call assert_equal(#{col: 3, row: 2, endcol: 3, curscol: 3}, screenpos(0, 4, 1)) + call assert_equal(#{col: 3, row: 3, endcol: 3, curscol: 3}, screenpos(0, 5, 1)) + exe "normal! \" + call assert_equal(#{col: 3, row: 1, endcol: 3, curscol: 3}, screenpos(0, 4, 1)) + call assert_equal(#{col: 3, row: 2, endcol: 3, curscol: 3}, screenpos(0, 5, 1)) windo diffoff bwipe!