diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-09-22 11:09:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-22 11:09:33 +0200 |
commit | 7fc5f6605fb3de361c970a1d22a42a905a072a0c (patch) | |
tree | ffe2148ab3193f2c122ed43e9655e3179b17c1e5 | |
parent | 8d13b08a03c31cdb269b7d09c166e0b447f2a303 (diff) | |
parent | 02f8ca59a80cd3570593c717ff6ceadc33239b89 (diff) | |
download | rneovim-7fc5f6605fb3de361c970a1d22a42a905a072a0c.tar.gz rneovim-7fc5f6605fb3de361c970a1d22a42a905a072a0c.tar.bz2 rneovim-7fc5f6605fb3de361c970a1d22a42a905a072a0c.zip |
Merge pull request #20249 from bfredl/cmdmessage
fix(redraw): avoid unnecessary redraws and glitches with floats+messages
-rw-r--r-- | runtime/lua/man.lua | 6 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 1 | ||||
-rw-r--r-- | src/nvim/decoration.c | 5 | ||||
-rw-r--r-- | src/nvim/drawline.c | 1 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 68 | ||||
-rw-r--r-- | src/nvim/grid.c | 11 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 2 | ||||
-rw-r--r-- | src/nvim/message.c | 4 | ||||
-rw-r--r-- | src/nvim/screen.c | 2 | ||||
-rw-r--r-- | src/nvim/sign.c | 6 | ||||
-rw-r--r-- | src/nvim/ui.c | 2 | ||||
-rw-r--r-- | src/nvim/ui_compositor.c | 4 | ||||
-rw-r--r-- | src/nvim/window.c | 38 | ||||
-rw-r--r-- | test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua | 4 | ||||
-rw-r--r-- | test/functional/helpers.lua | 15 | ||||
-rw-r--r-- | test/functional/ui/cmdline_spec.lua | 175 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 360 | ||||
-rw-r--r-- | test/functional/ui/syntax_conceal_spec.lua | 7 |
18 files changed, 587 insertions, 124 deletions
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index f0306f4871..88535321ac 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -21,13 +21,15 @@ local function man_system(cmd, silent) local done = false local exit_code - local handle = vim.loop.spawn(cmd[1], { + local handle + handle = vim.loop.spawn(cmd[1], { args = vim.list_slice(cmd, 2), stdio = { nil, stdout, stderr }, }, function(code) exit_code = code stdout:close() stderr:close() + handle:close() done = true end) @@ -52,7 +54,7 @@ local function man_system(cmd, silent) if not done then if handle then - vim.loop.shutdown(handle) + handle:close() stdout:close() stderr:close() end diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index dafbae5813..644f892f3c 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1445,7 +1445,6 @@ win_found: } aucmd_win_used = false; - last_status(false); // may need to remove last status line if (!valid_tabpage_win(curtab)) { // no valid window in current tabpage diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 778f9293fb..5a1708a57c 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -75,12 +75,11 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor) } if (decor && decor_virt_pos(*decor)) { - redraw_buf_line_later(buf, row1 + 1); + redraw_buf_line_later(buf, row1 + 1, false); } if (decor && kv_size(decor->virt_lines)) { - redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, - row1 + 1 + (decor->virt_lines_above?0:1))); + redraw_buf_line_later(buf, row1 + 1 + (decor->virt_lines_above?0:1), true); } } diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 25ea2e1000..5c3fa3d3b0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2638,6 +2638,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // When the window is too narrow draw all "@" lines. if (draw_state != WL_LINE && filler_todo <= 0) { win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, row); row = endrow; } diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 957e8ae4da..c95f3f3550 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -389,6 +389,10 @@ int update_screen(int type) diff_redraw(true); } + // TODO(bfredl): completely get rid of using update_screen(UPD_XX_VALID) + // to redraw curwin + int curwin_type = MIN(type, UPD_NOT_VALID); + if (must_redraw) { if (type < must_redraw) { // use maximal type type = must_redraw; @@ -445,9 +449,11 @@ int update_screen(int type) } if (msg_use_msgsep()) { msg_grid.throttled = false; + bool was_invalidated = false; + // UPD_CLEAR is already handled if (type == UPD_NOT_VALID && !ui_has(kUIMultigrid) && msg_scrolled) { - ui_comp_set_screen_valid(false); + was_invalidated = ui_comp_set_screen_valid(false); for (int i = valid; i < Rows - p_ch; i++) { grid_clear_line(&default_grid, default_grid.line_offset[i], Columns, false); @@ -457,6 +463,8 @@ int update_screen(int type) continue; } if (W_ENDROW(wp) > valid) { + // TODO(bfredl): too pessimistic. type could be UPD_NOT_VALID + // only because windows that are above the separator. wp->w_redr_type = MAX(wp->w_redr_type, UPD_NOT_VALID); } if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) { @@ -469,9 +477,16 @@ int update_screen(int type) } msg_grid_set_pos(Rows - (int)p_ch, false); msg_grid_invalid = false; + if (was_invalidated) { + // screen was only invalid for the msgarea part. + // @TODO(bfredl): using the same "valid" flag + // for both messages and floats moving is bit of a mess. + ui_comp_set_screen_valid(true); + } } else if (type != UPD_CLEAR) { if (msg_scrolled > Rows - 5) { // redrawing is faster type = UPD_NOT_VALID; + curwin_type = UPD_NOT_VALID; } else { check_for_delay(false); grid_ins_lines(&default_grid, 0, msg_scrolled, Rows, 0, Columns); @@ -506,7 +521,7 @@ int update_screen(int type) need_wait_return = false; } - win_ui_flush(); + win_ui_flush(true); msg_ext_check_clear(); // reset cmdline_row now (may have been changed temporarily) @@ -553,6 +568,8 @@ int update_screen(int type) // Force redraw when width of 'number' or 'relativenumber' column // changes. + // TODO(bfredl): special casing curwin here is SÅ JÄVLA BULL. + // Either this should be done for all windows or not at all. if (curwin->w_redr_type < UPD_NOT_VALID && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu) ? number_width(curwin) : 0)) { @@ -560,22 +577,25 @@ int update_screen(int type) } // Only start redrawing if there is really something to do. - if (type == UPD_INVERTED) { + // TODO(bfredl): more curwin special casing to get rid of. + // Change update_screen(UPD_INVERTED) to a wrapper function + // perhaps? + if (curwin_type == UPD_INVERTED) { update_curswant(); } - if (curwin->w_redr_type < type - && !((type == UPD_VALID + if (curwin->w_redr_type < curwin_type + && !((curwin_type == UPD_VALID && curwin->w_lines[0].wl_valid && curwin->w_topfill == curwin->w_old_topfill && curwin->w_botfill == curwin->w_old_botfill && curwin->w_topline == curwin->w_lines[0].wl_lnum) - || (type == UPD_INVERTED + || (curwin_type == UPD_INVERTED && VIsual_active && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum && curwin->w_old_visual_mode == VIsual_mode && (curwin->w_valid & VALID_VIRTCOL) && curwin->w_old_curswant == curwin->w_curswant))) { - curwin->w_redr_type = type; + curwin->w_redr_type = curwin_type; } // Redraw the tab pages line if needed. @@ -998,6 +1018,9 @@ win_update_start: bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit bool top_to_mod = false; // redraw above mod_top + int bot_scroll_start = 999; // first line that needs to be redrawn due to + // scrolling. only used for EOB + int row; // current window row to display linenr_T lnum; // current buffer lnum to display int idx; // current index in w_lines[] @@ -1022,7 +1045,9 @@ win_update_start: type = wp->w_redr_type; if (type >= UPD_NOT_VALID) { + // TODO(bfredl): should only be implied for CLEAR, not NOT_VALID! wp->w_redr_status = true; + wp->w_lines_valid = 0; } @@ -1173,6 +1198,7 @@ win_update_start: mod_bot = MAXLNUM; } } + wp->w_redraw_top = 0; // reset for next time wp->w_redraw_bot = 0; @@ -1243,6 +1269,7 @@ win_update_start: // If not the last window, delete the lines at the bottom. // win_ins_lines may fail when the terminal can't do it. win_scroll_lines(wp, 0, i); + bot_scroll_start = 0; if (wp->w_lines_valid != 0) { // Need to update rows that are new, stop at the // first one that scrolled down. @@ -1303,6 +1330,7 @@ win_update_start: if (row > 0) { win_scroll_lines(wp, 0, -row); bot_start = wp->w_grid.rows - row; + bot_scroll_start = bot_start; } if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0) { // Skip the lines (below the deleted lines) that are still @@ -1680,6 +1708,7 @@ win_update_start: // need to redraw until the end of the window. // Inserting/deleting lines has no use. bot_start = 0; + bot_scroll_start = 0; } else { // Able to count old number of rows: Count new window // rows, and may insert/delete lines @@ -1710,6 +1739,7 @@ win_update_start: } else { win_scroll_lines(wp, row, xtra_rows); bot_start = wp->w_grid.rows + xtra_rows; + bot_scroll_start = bot_start; } } else if (xtra_rows > 0) { // May scroll text down. If there is not enough @@ -1719,6 +1749,7 @@ win_update_start: mod_bot = MAXLNUM; } else { win_scroll_lines(wp, row + old_rows, xtra_rows); + bot_scroll_start = 0; if (top_end > row + old_rows) { // Scrolled the part at the top that requires // updating down. @@ -1908,6 +1939,7 @@ win_update_start: wp->w_botline = lnum; } else { win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, srow); wp->w_botline = lnum; } } else { @@ -1928,8 +1960,18 @@ win_update_start: // Make sure the rest of the screen is blank. // write the "eob" character from 'fillchars' to rows that aren't part // of the file. - win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.rows, + // TODO(bfredl): just keep track of the valid EOB area from last redraw? + int lastline = bot_scroll_start; + if (mid_end >= row) { + lastline = MIN(lastline, mid_start); + } + if (mod_bot > buf->b_ml.ml_line_count + 1) { + lastline = 0; + } + + win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, MAX(lastline, row), wp->w_grid.rows, HLF_EOB); + set_empty_rows(wp, row); } kvi_destroy(line_providers); @@ -2041,12 +2083,14 @@ void redraw_buf_later(buf_T *buf, int type) } } -void redraw_buf_line_later(buf_T *buf, linenr_T line) +void redraw_buf_line_later(buf_T *buf, linenr_T line, bool force) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_buffer == buf - && line >= wp->w_topline && line < wp->w_botline) { - redrawWinline(wp, line); + if (wp->w_buffer == buf) { + redrawWinline(wp, MIN(line, buf->b_ml.ml_line_count)); + if (force && line > buf->b_ml.ml_line_count) { + wp->w_redraw_bot = line; + } } } } diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 63bb945f73..2b73ff895d 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -175,7 +175,7 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr) { assert(put_dirty_row == row); size_t off = grid->line_offset[row] + (size_t)col; - if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) { + if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar) || rdb_flags & RDB_NODELTA) { schar_copy(grid->chars[off], schar); grid->attrs[off] = attr; @@ -280,7 +280,8 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, need_redraw = schar_cmp(grid->chars[off], buf) || (mbyte_cells == 2 && grid->chars[off + 1][0] != 0) || grid->attrs[off] != attr - || exmode_active; + || exmode_active + || rdb_flags & RDB_NODELTA; if (need_redraw) { // When at the end of the text and overwriting a two-cell @@ -412,8 +413,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int size_t lineoff = grid->line_offset[row]; for (col = start_col; col < end_col; col++) { size_t off = lineoff + (size_t)col; - if (schar_cmp(grid->chars[off], sc) - || grid->attrs[off] != attr) { + if (schar_cmp(grid->chars[off], sc) || grid->attrs[off] != attr || rdb_flags & RDB_NODELTA) { schar_copy(grid->chars[off], sc); grid->attrs[off] = attr; if (dirty_first == INT_MAX) { @@ -605,7 +605,8 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle while (col < clear_width) { if (grid->chars[off_to][0] != ' ' || grid->chars[off_to][1] != NUL - || grid->attrs[off_to] != bg_attr) { + || grid->attrs[off_to] != bg_attr + || rdb_flags & RDB_NODELTA) { grid->chars[off_to][0] = ' '; grid->chars[off_to][1] = NUL; grid->attrs[off_to] = bg_attr; diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 09f8c688d8..6063414a02 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1658,7 +1658,7 @@ void ex_luado(exarg_T *const eap) } lua_pop(lstate, 1); check_cursor(); - update_screen(UPD_NOT_VALID); + redraw_curbuf_later(UPD_NOT_VALID); } /// Run lua file diff --git a/src/nvim/message.c b/src/nvim/message.c index c93e825a5d..0b9cbfe474 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2053,7 +2053,7 @@ void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr) overflow = true; } } else { - overflow = msg_scrolled != 0; + overflow = msg_scrolled > (p_ch == 0 ? 1 : 0); } if (overflow && !msg_scrolled_ign && strcmp(str, "\r") != 0) { @@ -2334,7 +2334,7 @@ bool message_filtered(char *msg) /// including horizontal separator int msg_scrollsize(void) { - return msg_scrolled + (int)p_ch + 1; + return msg_scrolled + (int)p_ch + ((p_ch > 0 || msg_scrolled > 1) ? 1 : 0); } bool msg_use_msgsep(void) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index cdfb1e9ee1..1af93f061c 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -155,8 +155,6 @@ void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endr } else { grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.cols, c1, c2, attr); } - - set_empty_rows(wp, row); } /// Compute the width of the foldcolumn. Based on 'foldcolumn' and how much diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 5ce9ee4546..6f13dd2f06 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -557,7 +557,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char *group) sign_group_unref((char *)sign->se_group->sg_name); } xfree(sign); - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); // Check whether only one sign needs to be deleted // If deleting a sign with a specific identifier in a particular // group or deleting any sign at a particular line number, delete @@ -1062,7 +1062,7 @@ static int sign_place(int *sign_id, const char *sign_group, const char *sign_nam lnum = buf_change_sign_type(buf, *sign_id, (char *)sign_group, sp->sn_typenr, prio); } if (lnum > 0) { - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); // When displaying signs in the 'number' column, if the width of the // number column is less than 2, then force recomputing the width. @@ -1093,7 +1093,7 @@ static int sign_unplace(int sign_id, char *sign_group, buf_T *buf, linenr_T atln if (lnum == 0) { return FAIL; } - redraw_buf_line_later(buf, lnum); + redraw_buf_line_later(buf, lnum, false); } // When all the signs in a buffer are removed, force recomputing the diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 09eedcf059..2c9510bf34 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -510,7 +510,7 @@ void ui_flush(void) return; } cmdline_ui_flush(); - win_ui_flush(); + win_ui_flush(false); msg_ext_ui_flush(); msg_scroll_flush(); diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 9f9a32036c..f23615180e 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -590,12 +590,14 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol /// The screen is invalid and will soon be cleared /// /// Don't redraw floats until screen is cleared -void ui_comp_set_screen_valid(bool valid) +bool ui_comp_set_screen_valid(bool valid) { + bool old_val = valid_screen; valid_screen = valid; if (!valid) { msg_sep_row = -1; } + return old_val; } static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled, diff --git a/src/nvim/window.c b/src/nvim/window.c index 2ccbdc10ea..cc20a5fcec 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -871,8 +871,9 @@ int win_fdccol_count(win_T *wp) } } -void ui_ext_win_position(win_T *wp) +void ui_ext_win_position(win_T *wp, bool validate) { + wp->w_pos_changed = false; if (!wp->w_floating) { ui_call_win_pos(wp->w_grid_alloc.handle, wp->handle, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_height); @@ -910,6 +911,11 @@ void ui_ext_win_position(win_T *wp) grid->handle, row, col, c.focusable, wp->w_grid_alloc.zindex); } else { + bool valid = (wp->w_redr_type == 0); + if (!valid && !validate) { + wp->w_pos_changed = true; + return; + } // TODO(bfredl): ideally, compositor should work like any multigrid UI // and use standard win_pos events. bool east = c.anchor & kFloatAnchorEast; @@ -923,7 +929,6 @@ void ui_ext_win_position(win_T *wp) comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0); wp->w_winrow = comp_row; wp->w_wincol = comp_col; - bool valid = (wp->w_redr_type == 0); ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col, wp->w_height_outer, wp->w_width_outer, valid, false); ui_check_cursor_grid(wp->w_grid_alloc.handle); @@ -2849,12 +2854,12 @@ int win_close(win_T *win, bool free_buf, bool force) check_cursor(); } - // If last window has a status line now and we don't want one, - // remove the status line. Do this before win_equal(), because - // it may change the height of a window. - last_status(false); - if (!was_floating) { + // If last window has a status line now and we don't want one, + // remove the status line. Do this before win_equal(), because + // it may change the height of a window. + last_status(false); + if (!curwin->w_floating && p_ea && (*p_ead == 'b' || *p_ead == dir)) { // If the frame of the closed window contains the new current window, // only resize that frame. Otherwise resize all windows. @@ -2898,7 +2903,10 @@ int win_close(win_T *win, bool free_buf, bool force) } curwin->w_pos_changed = true; - redraw_all_later(UPD_NOT_VALID); + if (!was_floating) { + // TODO(bfredl): how about no? + redraw_all_later(UPD_NOT_VALID); + } return OK; } @@ -5413,7 +5421,7 @@ void win_setheight_win(int height, win_T *win) if (win->w_floating) { win->w_float_config.height = height; win_config_float(win, win->w_float_config); - redraw_later(win, UPD_NOT_VALID); + redraw_later(win, UPD_VALID); } else { frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height); @@ -6059,6 +6067,9 @@ void win_new_height(win_T *wp, int height) wp->w_height = height; wp->w_pos_changed = true; win_set_inner_size(wp, true); + if (wp->w_status_height) { + wp->w_redr_status = true; + } } void scroll_to_fraction(win_T *wp, int prev_height) @@ -6196,7 +6207,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor) if (!exiting && valid_cursor) { scroll_to_fraction(wp, prev_height); } - redraw_later(wp, UPD_NOT_VALID); // UPD_SOME_VALID?? + redraw_later(wp, UPD_SOME_VALID); } if (width != wp->w_width_inner) { @@ -6608,7 +6619,6 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global) wp->w_hsep_height = 0; comp_col(); } - redraw_all_later(UPD_SOME_VALID); } else { // For a column or row frame, recursively call this function for all child frames FOR_ALL_FRAMES(fp, fr->fr_child) { @@ -7336,16 +7346,16 @@ void get_framelayout(const frame_T *fr, list_T *l, bool outer) } } -void win_ui_flush(void) +void win_ui_flush(bool validate) { FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_pos_changed && wp->w_grid_alloc.chars != NULL) { if (tp == curtab) { - ui_ext_win_position(wp); + ui_ext_win_position(wp, validate); } else { ui_call_win_hide(wp->w_grid_alloc.handle); + wp->w_pos_changed = false; } - wp->w_pos_changed = false; } if (tp == curtab) { ui_ext_win_viewport(wp); diff --git a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua index a312572c5b..45226ce24b 100644 --- a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua +++ b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua @@ -1,3 +1,5 @@ return function (val, res) - vim.loop.new_async(function() _G[res] = require'leftpad'(val) end):send() + local handle + handle = vim.loop.new_async(function() _G[res] = require'leftpad'(val) handle:close() end) + handle:send() end diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index d672037a1e..eff54b6d4a 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -380,10 +380,23 @@ local function remove_args(args, args_rm) return new_args end +function module.check_close(old_session) + local start_time = luv.now() + old_session:close() + luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()). + local end_time = luv.now() + local delta = end_time - start_time + if delta > 500 then + print("nvim took " .. delta .. " milliseconds to exit after last test\n".. + "This indicates a likely problem with the test even if it passed!\n") + io.stdout:flush() + end +end + --- @param io_extra used for stdin_fd, see :help ui-option function module.spawn(argv, merge, env, keep, io_extra) if session and not keep then - session:close() + module.check_close(session) end local child_stream = ChildProcessStream.spawn( diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 40dee4186b..92eb853686 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -934,6 +934,15 @@ describe('cmdheight=0', function() before_each(function() clear() screen = Screen.new(25, 5) + screen:set_default_attr_ids { + [1] = {bold = true, foreground = Screen.colors.Blue}; + [2] = {bold = true, reverse = true}; + [3] = {bold = true}; + [4] = {foreground = Screen.colors.White, background = Screen.colors.Red}; + [5] = {foreground = Screen.colors.SeaGreen4, bold = true}; + [6] = {reverse = true}; + [7] = {background = Screen.colors.Yellow}; + } screen:attach() end) @@ -941,9 +950,9 @@ describe('cmdheight=0', function() command("set cmdheight=1 noruler laststatus=2") screen:expect{grid=[[ ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| | ]]} end) @@ -952,10 +961,10 @@ describe('cmdheight=0', function() command("set cmdheight=0 noruler laststatus=2") screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| ]]} end) @@ -963,10 +972,10 @@ describe('cmdheight=0', function() command("set cmdheight=0 ruler laststatus=0") screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]]} end) @@ -975,10 +984,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} feed('<Esc>') eq(0, eval('&cmdheight')) @@ -989,10 +998,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} feed('<Esc>') eq(0, eval('&cmdheight')) @@ -1003,10 +1012,10 @@ describe('cmdheight=0', function() feed('i') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - -- INSERT -- | + {1:~ }| + {1:~ }| + {1:~ }| + {3:-- INSERT --} | ]]} feed('<Esc>') eq(1, eval('&cmdheight')) @@ -1017,19 +1026,19 @@ describe('cmdheight=0', function() feed(':') screen:expect{grid=[[ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| :^ | ]]} eq(0, eval('&cmdheight')) feed('<cr>') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} eq(0, eval('&cmdheight')) end) @@ -1039,8 +1048,8 @@ describe('cmdheight=0', function() feed(':call input("foo >")<cr>') screen:expect{grid=[[ | - ~ | - | + {1:~ }| + {2: }| :call input("foo >") | foo >^ | ]]} @@ -1048,10 +1057,10 @@ describe('cmdheight=0', function() feed('<cr>') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], showmode={}} eq(0, eval('&cmdheight')) end) @@ -1060,35 +1069,35 @@ describe('cmdheight=0', function() command("set cmdheight=0 noruler laststatus=3 winbar=foo") feed(':split<CR>') screen:expect{grid=[[ - | + {2: }| :split | - E36: Not enough room | - Press ENTER or type comma| - nd to continue^ | + {4:E36: Not enough room} | + {5:Press ENTER or type comma}| + {5:nd to continue}^ | ]]} feed('<CR>') screen:expect{grid=[[ - foo | + {3:foo }| ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| ]]} feed(':') screen:expect{grid=[[ - foo | + {3:foo }| | - ~ | - ~ | + {1:~ }| + {1:~ }| :^ | ]]} feed('<Esc>') screen:expect{grid=[[ - foo | + {3:foo }| ^ | - ~ | - ~ | - [No Name] | + {1:~ }| + {1:~ }| + {2:[No Name] }| ]], showmode={}} eq(0, eval('&cmdheight')) @@ -1100,18 +1109,18 @@ describe('cmdheight=0', function() feed('qq') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]]} feed('q') screen:expect{grid=[[ ^ | - ~ | - ~ | - ~ | - ~ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| ]], unchanged=true} end) @@ -1120,28 +1129,28 @@ describe('cmdheight=0', function() feed('ifoo<ESC>') screen:expect{grid=[[ fo^o | - ~ | - ~ | - ~ | - [No Name] [+] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] [+] }| ]]} feed(':%s/foo/bar/gc<CR>') screen:expect{grid=[[ - foo | - ~ | - ~ | - ~ | - replace wi...q/l/^E/^Y)?^ | + {6:foo} | + {1:~ }| + {1:~ }| + {1:~ }| + {5:replace wi...q/l/^E/^Y)?}^ | ]]} feed('y') screen:expect{grid=[[ ^bar | - ~ | - ~ | - ~ | - [No Name] [+] | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] [+] }| ]]} assert_alive() @@ -1152,4 +1161,26 @@ describe('cmdheight=0', function() feed('<C-w>+') eq(0, eval('&cmdheight')) end) + + it("with non-silent mappings with cmdline", function() + command("set cmdheight=0") + command("map <f3> :nohlsearch<cr>") + feed('iaabbaa<esc>/aa<cr>') + screen:expect{grid=[[ + {7:^aa}bb{7:aa} | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + + feed('<f3>') + screen:expect{grid=[[ + ^aabbaa | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + end) end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 5967b630f6..a5a664cb3d 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -8147,6 +8147,366 @@ describe('float window', function() ]]} end end) + + it('it can be resized with messages and cmdheight=0 #20106', function() + screen:try_resize(40,9) + command 'set cmdheight=0' + local buf = meths.create_buf(false,true) + local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=9, col=0, style='minimal', border="single", noautocmd=true}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + ]]} + end + + exec_lua([[ + local win = ... + vim.api.nvim_win_set_height(win, 2) + vim.api.nvim_echo({ { "" } }, false, {}) + ]], win) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + ]]} + + end + + meths.win_close(win, true) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ]]} + end + end) + + it('it can be resized with messages and cmdheight=1', function() + screen:try_resize(40,9) + local buf = meths.create_buf(false,true) + local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=8, col=0, style='minimal', border="single", noautocmd=true}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + | + ]]} + end + + exec_lua([[ + -- echo prompt is blocking, so schedule + local win = ... + vim.schedule(function() + vim.api.nvim_win_set_height(win, 2) + vim.api.nvim_echo({ { "\n" } }, false, {}) + end) + ]], win) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + {8:Press ENTER or type command to continue}^ | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + | + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {4: }| + | + {8:Press ENTER or type command to continue}^ | + ]]} + end + + feed('<cr>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└────────────────────────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {5:┌──────────────────────────────────────┐}| + {5:│}{1: }{5:│}| + {5:│}{1: }{5:│}| + {5:└──────────────────────────────────────┘}| + | + ]]} + end + + meths.win_close(win, true) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index f790597140..e8798ddd93 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -947,7 +947,7 @@ describe('Screen', function() {0:~ }| | ]]} - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}, {3, 0, {{' ', 0, 53}}}}, grid_lines) end) it('K_EVENT should not cause extra redraws with concealcursor #13196', function() @@ -994,10 +994,11 @@ describe('Screen', function() {0:~ }| | ]]} - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}}, grid_lines) + grid_lines = {} poke_eventloop() -- causes K_EVENT key screen:expect_unchanged() - eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + eq({}, grid_lines) -- no redraw was done end) -- Copy of Test_cursor_column_in_concealed_line_after_window_scroll in |