diff options
36 files changed, 454 insertions, 297 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97e1ed8742..3653f04d5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ jobs: unixish: name: ${{ matrix.os }} ${{ matrix.flavor }} (cc=${{ matrix.cc }}) strategy: + fail-fast: false matrix: include: - flavor: asan @@ -90,6 +91,7 @@ jobs: DEPS_PREFIX: "C:/projects/nvim-deps/usr" strategy: + fail-fast: false matrix: config: [ MINGW_64-gcov, MINGW_32, MSVC_64, MSVC_32 ] name: windows (${{ matrix.config }}) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6905f8dd35..7587f62e59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -105,8 +105,35 @@ jobs: path: build/release/nvim-macos.tar.gz retention-days: 1 + windows: + runs-on: windows-2016 + env: + DEPS_BUILD_DIR: "C:/projects/nvim-deps" + DEPS_PREFIX: "C:/projects/nvim-deps/usr" + strategy: + matrix: + include: + - config: MSVC_64 + archive: nvim-win64 + - config: MSVC_32 + archive: nvim-win32 + name: windows (${{ matrix.config }}) + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: powershell ci\build.ps1 -NoTests + env: + CONFIGURATION: ${{ matrix.config }} + - run: move build\Neovim.zip build\${{ matrix.archive }}.zip + - uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.archive }} + path: build/${{ matrix.archive }}.zip + retention-days: 1 + publish: - needs: [linux, appimage, macOS] + needs: [linux, appimage, macOS, windows] runs-on: ubuntu-20.04 steps: - uses: actions/download-artifact@v2 @@ -143,6 +170,8 @@ jobs: nvim-linux64.tar.gz:./nvim-linux64/nvim-linux64.tar.gz nvim.appimage:./appimage/nvim.appimage nvim.appimage.zsync:./appimage/nvim.appimage.zsync + nvim-win32.zip:./nvim-win32/nvim-win32.zip + nvim-win64.zip:./nvim-win64/nvim-win64.zip body: | ${{ env.SUBJECT }} ``` @@ -5,7 +5,6 @@ [Twitter](https://twitter.com/Neovim) [](https://github.com/neovim/neovim/actions?query=workflow%3A%22CI%22) -[](https://ci.appveyor.com/project/neovim/neovim/branch/master) [](https://codecov.io/gh/neovim/neovim) [](https://scan.coverity.com/projects/2227) [](https://neovim.io/doc/reports/clang) diff --git a/contrib/flake.nix b/contrib/flake.nix index a75e584075..86e4b37cfa 100644 --- a/contrib/flake.nix +++ b/contrib/flake.nix @@ -44,7 +44,7 @@ pythonEnv = legacyPkgs.python3; luacheck = legacyPkgs.luaPackages.luacheck; in - neovim-debug.overrideAttrs(oa: { + (neovim-debug.override({doCheck = true;})).overrideAttrs(oa: { cmakeFlags = oa.cmakeFlags ++ [ "-DLUACHECK_PRG=${luacheck}/bin/luacheck" "-DMIN_LOG_LEVEL=0" diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 67e2815715..8e93b188e9 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -118,7 +118,7 @@ FAQ *lsp-faq* < *vim.lsp.callbacks* - Q: What happened to `vim.lsp.callbacks`? - A: After better defining the interface of |lsp-hander|s, we thought it best + A: After better defining the interface of |lsp-handler|s, we thought it best to remove the generic usage of `callbacks` and transform to `handlers`. Due to this, `vim.lsp.callbacks` was renamed to |vim.lsp.handlers|. @@ -257,7 +257,7 @@ For |lsp-notification|, each |lsp-handler| has this signature: > *lsp-handler-configuration* -To configure the behavior of a builtin |lsp-handler|, the conenvience method +To configure the behavior of a builtin |lsp-handler|, the convenient method |vim.lsp.with()| is provided for users. To configure the behavior of |vim.lsp.diagnostic.on_publish_diagnostics()|, diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index e5c6b9b1b7..0a8584927e 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -213,11 +213,9 @@ the editor. ["mouse_on"] ["mouse_off"] - |'mouse'| was enabled/disabled in the current editor mode. Useful for - a terminal UI, or other situations where Nvim mouse would conflict - with other usages of the mouse. UIs may ignore this and always send - mouse input, because 'mouse' decides the behavior of |nvim_input()| - implicitly. + 'mouse' was enabled/disabled in the current editor mode. Useful for + a terminal UI, or embedding into an application where Nvim mouse would + conflict with other usages of the mouse. Other UI:s may ignore this event. ["busy_start"] ["busy_stop"] diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 359573beb1..fd23a6a547 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -63,8 +63,44 @@ local function progress_callback(_, _, params, client_id) vim.api.nvim_command("doautocmd <nomodeline> User LspProgressUpdate") end +--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress M['$/progress'] = progress_callback +--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create +M['window/workDoneProgress/create'] = function(_, _, params, client_id) + local client = vim.lsp.get_client_by_id(client_id) + local token = params.token -- string or number + if not client then + err_message("LSP[", client_id, "] client has shut down after sending the message") + end + client.messages.progress[token] = {} + return vim.NIL +end + +--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest +M['window/showMessageRequest'] = function(_, _, params) + + local actions = params.actions + print(params.message) + local option_strings = {params.message, "\nRequest Actions:"} + for i, action in ipairs(actions) do + local title = action.title:gsub('\r\n', '\\r\\n') + title = title:gsub('\n', '\\n') + table.insert(option_strings, string.format("%d. %s", i, title)) + end + + -- window/showMessageRequest can return either MessageActionItem[] or null. + local choice = vim.fn.inputlist(option_strings) + if choice < 1 or choice > #actions then + return vim.NIL + else + local action_chosen = actions[choice] + return { + title = action_chosen; + } + end +end + --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction M['textDocument/codeAction'] = function(_, _, actions) if actions == nil or vim.tbl_isempty(actions) then diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index b785d2f586..b2d3d0641c 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -730,7 +730,15 @@ function protocol.make_client_capabilities() experimental = nil; window = { workDoneProgress = true; - } + showMessage = { + messageActionItem = { + additionalPropertiesSupport = false; + }; + }; + showDocument = { + support = false; + }; + }; } end diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 962ef9b245..876e53e3cd 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -7803,7 +7803,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) // Otherwise remove the mode message. if (reg_recording != 0 || restart_edit != NUL) { showmode(); - } else if (p_smd && (got_int || !skip_showmode())) { + } else if (p_smd) { MSG(""); } // Exit Insert mode @@ -8329,9 +8329,6 @@ static void ins_mouse(int c) pos_T tpos; win_T *old_curwin = curwin; - if (!mouse_has(MOUSE_INSERT)) - return; - undisplay_dollar(); tpos = curwin->w_cursor; if (do_mouse(NULL, c, BACKWARD, 1, 0)) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7916e3a66a..f60504de5e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -76,9 +76,6 @@ static char_u * const namespace_char = (char_u *)"abglstvw"; /// Variable used for g: static ScopeDictDictItem globvars_var; -/// g: value -#define globvarht globvardict.dv_hashtab - /* * Old Vim variables such as "v:version" are also available without the "v:". * Also in functions. We need a special hashtable for them. diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index a7d97c904b..ae389a6727 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3713,9 +3713,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, redraw_later(curwin, SOME_VALID); curwin->w_p_fen = save_p_fen; - if (msg_row == Rows - 1) { - msg_didout = false; // avoid a scroll-up - } + if (msg_row == Rows - 1) + msg_didout = FALSE; /* avoid a scroll-up */ msg_starthere(); i = msg_scroll; msg_scroll = 0; /* truncate msg when @@ -3734,8 +3733,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, typed = plain_vgetc(); no_mapping--; - // clear the question - msg_didout = false; // don't scroll up + /* clear the question */ + msg_didout = FALSE; /* don't scroll up */ msg_col = 0; gotocmdline(TRUE); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 3fc02e0693..003c78b241 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4769,10 +4769,8 @@ static void ex_abclear(exarg_T *eap) static void ex_autocmd(exarg_T *eap) { - /* - * Disallow auto commands from .exrc and .vimrc in current - * directory for security reasons. - */ + // Disallow autocommands from .exrc and .vimrc in current + // directory for security reasons. if (secure) { secure = 2; eap->errmsg = e_curdir; @@ -8071,8 +8069,8 @@ static void ex_redraw(exarg_T *eap) RedrawingDisabled = r; p_lz = p; - // Reset msg_didout, so that a message that's there is overwritten. - msg_didout = false; + /* Reset msg_didout, so that a message that's there is overwritten. */ + msg_didout = FALSE; msg_col = 0; /* No need to wait after an intentional redraw. */ diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0bc52f1e97..0f50d5153d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1884,9 +1884,6 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); // Ignore mouse case K_MIDDLEMOUSE: - if (!mouse_has(MOUSE_COMMAND)) { - return command_line_not_changed(s); // Ignore mouse - } cmdline_paste(eval_has_provider("clipboard") ? '*' : 0, true, true); redrawcmd(); return command_line_changed(s); @@ -1910,10 +1907,6 @@ static int command_line_handle_key(CommandLineState *s) s->ignore_drag_release = false; } - if (!mouse_has(MOUSE_COMMAND)) { - return command_line_not_changed(s); // Ignore mouse - } - ccline.cmdspos = cmd_startcol(); for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen; ccline.cmdpos++) { @@ -2746,8 +2739,8 @@ redraw: no_mapping--; - // make following messages go to the next line - msg_didout = false; + /* make following messages go to the next line */ + msg_didout = FALSE; msg_col = 0; if (msg_row < Rows - 1) { msg_row++; diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index d831ffc050..14dac9a126 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -526,8 +526,12 @@ static int makeopens(FILE *fd, char_u *dirnow) } } - // Close all windows but one. + // Close all windows and tabs but one. PUTLINE_FAIL("silent only"); + if ((ssop_flags & SSOP_TABPAGES) + && put_line(fd, "silent tabonly") == FAIL) { + return FAIL; + } // // Now a :cd command to the session directory or the current directory @@ -606,13 +610,26 @@ static int makeopens(FILE *fd, char_u *dirnow) // tab_firstwin = firstwin; // First window in tab page "tabnr". tab_topframe = topframe; + if ((ssop_flags & SSOP_TABPAGES)) { + // Similar to ses_win_rec() below, populate the tab pages first so + // later local options won't be copied to the new tabs. + FOR_ALL_TABS(tp) { + if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL) { + return FAIL; + } + } + + if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL) { + return FAIL; + } + } for (tabnr = 1;; tabnr++) { tabpage_T *tp = find_tabpage(tabnr); if (tp == NULL) { break; // done all tab pages } - int need_tabnew = false; + bool need_tabnext = false; int cnr = 1; if ((ssop_flags & SSOP_TABPAGES)) { @@ -624,7 +641,7 @@ static int makeopens(FILE *fd, char_u *dirnow) tab_topframe = tp->tp_topframe; } if (tabnr > 1) { - need_tabnew = true; + need_tabnext = true; } } @@ -639,11 +656,15 @@ static int makeopens(FILE *fd, char_u *dirnow) && !bt_help(wp->w_buffer) && !bt_nofile(wp->w_buffer) ) { - if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0 + if (need_tabnext && put_line(fd, "tabnext") == FAIL) { + return FAIL; + } + need_tabnext = false; + + if (fputs("edit ", fd) < 0 || ses_fname(fd, wp->w_buffer, &ssop_flags, true) == FAIL) { return FAIL; } - need_tabnew = false; if (!wp->w_arg_idx_invalid) { edited_win = wp; } @@ -652,7 +673,7 @@ static int makeopens(FILE *fd, char_u *dirnow) } // If no file got edited create an empty tab page. - if (need_tabnew && put_line(fd, "tabnew") == FAIL) { + if (need_tabnext && put_line(fd, "tabnext") == FAIL) { return FAIL; } @@ -775,6 +796,7 @@ static int makeopens(FILE *fd, char_u *dirnow) // if (fprintf(fd, "%s", "if exists('s:wipebuf') " + "&& len(win_findbuf(s:wipebuf)) == 0" "&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'\n" " silent exe 'bwipe ' . s:wipebuf\n" "endif\n" diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index eddbdef739..2e2993ed26 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2490,10 +2490,8 @@ int inchar( } // Always flush the output characters when getting input characters - // from the user and not just peeking. - if (wait_time == -1L || wait_time > 10L) { - ui_flush(); - } + // from the user. + ui_flush(); // Fill up to a third of the buffer, because each character may be // tripled below. diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 6b962dc1f6..31b905e858 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -139,9 +139,8 @@ EXTERN int mod_mask INIT(= 0x0); // current key modifiers EXTERN int cmdline_row; EXTERN int redraw_cmdline INIT(= false); // cmdline must be redrawn -EXTERN bool redraw_mode INIT(= false); // mode must be redrawn EXTERN int clear_cmdline INIT(= false); // cmdline must be cleared -EXTERN bool mode_displayed INIT(= false); // mode is being displayed +EXTERN int mode_displayed INIT(= false); // mode is being displayed EXTERN int cmdline_star INIT(= false); // cmdline is crypted EXTERN int redrawing_cmdline INIT(= false); // cmdline is being redrawn EXTERN int cmdline_was_last_drawn INIT(= false); // cmdline was last drawn @@ -200,7 +199,7 @@ EXTERN int keep_msg_attr INIT(= 0); // highlight attr for keep_msg EXTERN int keep_msg_more INIT(= false); // keep_msg was set by msgmore() EXTERN int need_fileinfo INIT(= false); // do fileinfo() after redraw EXTERN int msg_scroll INIT(= false); // msg_start() will scroll -EXTERN bool msg_didout INIT(= false); // msg_outstr() was used in line +EXTERN int msg_didout INIT(= false); // msg_outstr() was used in line EXTERN int msg_didany INIT(= false); // msg_outstr() was used at all EXTERN int msg_nowait INIT(= false); // don't wait for this msg EXTERN int emsg_off INIT(= 0); // don't display errors for now, @@ -216,6 +215,8 @@ EXTERN bool emsg_severe INIT(= false); // use message of next of several EXTERN int did_endif INIT(= false); // just had ":endif" EXTERN dict_T vimvardict; // Dictionary with v: variables EXTERN dict_T globvardict; // Dictionary with g: variables +/// g: value +#define globvarht globvardict.dv_hashtab EXTERN int did_emsg; // set by emsg() when the message // is displayed or thrown EXTERN bool called_vim_beep; // set if vim_beep() is called diff --git a/src/nvim/main.c b/src/nvim/main.c index e068b2361c..8bf745966e 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -2006,7 +2006,7 @@ static void version(void) info_message = TRUE; // use mch_msg(), not mch_errmsg() list_version(); msg_putchar('\n'); - msg_didout = false; + msg_didout = FALSE; } /// Prints help message for "nvim -h" or "nvim --help". diff --git a/src/nvim/message.c b/src/nvim/message.c index 530b930fed..f94529c687 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1128,11 +1128,11 @@ void wait_return(int redraw) if (p_more) { if (c == 'b' || c == 'k' || c == 'u' || c == 'g' || c == K_UP || c == K_PAGEUP) { - if (msg_scrolled > Rows) { - // scroll back to show older messages + if (msg_scrolled > Rows) + /* scroll back to show older messages */ do_more_prompt(c); - } else { - msg_didout = false; + else { + msg_didout = FALSE; c = K_IGNORE; msg_col = cmdmsg_rl ? Columns - 1 : @@ -1157,15 +1157,7 @@ void wait_return(int redraw) || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE || c == K_RIGHTDRAG || c == K_RIGHTRELEASE || c == K_MOUSELEFT || c == K_MOUSERIGHT - || c == K_MOUSEDOWN || c == K_MOUSEUP - || (!mouse_has(MOUSE_RETURN) - && mouse_row < msg_row - && (c == K_LEFTMOUSE - || c == K_MIDDLEMOUSE - || c == K_RIGHTMOUSE - || c == K_X1MOUSE - || c == K_X2MOUSE)) - ); + || c == K_MOUSEDOWN || c == K_MOUSEUP); os_breakcheck(); /* * Avoid that the mouse-up event causes visual mode to start. @@ -2097,17 +2089,15 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, store_sb_text((char_u **)&sb_str, (char_u *)s, attr, &sb_col, true); } - if (*s == '\n') { // go to next line - msg_didout = false; // remember that line is empty - if (cmdmsg_rl) { + if (*s == '\n') { /* go to next line */ + msg_didout = FALSE; /* remember that line is empty */ + if (cmdmsg_rl) msg_col = Columns - 1; - } else { + else msg_col = 0; - } - if (++msg_row >= Rows) { // safety check + if (++msg_row >= Rows) /* safety check */ msg_row = Rows - 1; - } - } else if (*s == '\r') { // go to column 0 + } else if (*s == '\r') { /* go to column 0 */ msg_col = 0; } else if (*s == '\b') { /* go to previous char */ if (msg_col) @@ -2880,10 +2870,10 @@ void repeat_message(void) ui_cursor_goto(msg_row, msg_col); /* put cursor back */ } else if (State == HITRETURN || State == SETWSIZE) { if (msg_row == Rows - 1) { - // Avoid drawing the "hit-enter" prompt below the previous one, - // overwrite it. Esp. useful when regaining focus and a - // FocusGained autocmd exists but didn't draw anything. - msg_didout = false; + /* Avoid drawing the "hit-enter" prompt below the previous one, + * overwrite it. Esp. useful when regaining focus and a + * FocusGained autocmd exists but didn't draw anything. */ + msg_didout = FALSE; msg_col = 0; msg_clr_eos(); } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index f05dade73f..ff471ea978 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -526,53 +526,9 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp) void setmouse(void) { ui_cursor_shape(); - - // Be quick when mouse is off. - if (*p_mouse == NUL) { - return; - } - - int checkfor = MOUSE_NORMAL; // assume normal mode - if (VIsual_active) { - checkfor = MOUSE_VISUAL; - } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) { - checkfor = MOUSE_RETURN; - } else if (State & INSERT) { - checkfor = MOUSE_INSERT; - } else if (State & CMDLINE) { - checkfor = MOUSE_COMMAND; - } else if (State == CONFIRM || State == EXTERNCMD) { - checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd" - } - - if (mouse_has(checkfor)) { - ui_call_mouse_on(); - } else { - ui_call_mouse_off(); - } + ui_check_mouse(); } -/* - * Return true if - * - "c" is in 'mouse', or - * - 'a' is in 'mouse' and "c" is in MOUSE_A, or - * - the current buffer is a help file and 'h' is in 'mouse' and we are in a - * normal editing mode (not at hit-return message). - */ -int mouse_has(int c) -{ - for (char_u *p = p_mouse; *p; ++p) - switch (*p) { - case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) - return true; - break; - case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) - return true; - break; - default: if (c == *p) return true; break; - } - return false; -} // Set orig_topline. Used when jumping to another window, so that a double // click still works. diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f93d772068..4e955667dc 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2375,10 +2375,10 @@ do_mouse ( * Also paste at the cursor if the current mode isn't in 'mouse' (only * happens for the GUI). */ - if ((State & INSERT) || !mouse_has(MOUSE_NORMAL)) { - if (regname == '.') + if ((State & INSERT)) { + if (regname == '.') { insert_reg(regname, true); - else { + } else { if (regname == 0 && eval_has_provider("clipboard")) { regname = '*'; } @@ -2558,8 +2558,9 @@ do_mouse ( * on a status line */ if (VIsual_active) jump_flags |= MOUSE_MAY_STOP_VIS; - } else if (mouse_has(MOUSE_VISUAL)) + } else { jump_flags |= MOUSE_MAY_VIS; + } } else if (which_button == MOUSE_RIGHT) { if (is_click && VIsual_active) { /* @@ -2575,8 +2576,7 @@ do_mouse ( } } jump_flags |= MOUSE_FOCUS; - if (mouse_has(MOUSE_VISUAL)) - jump_flags |= MOUSE_MAY_VIS; + jump_flags |= MOUSE_MAY_VIS; } } @@ -2790,8 +2790,7 @@ do_mouse ( /* Handle double clicks, unless on status line */ else if (in_status_line) { } else if (in_sep_line) { - } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)) - && mouse_has(MOUSE_VISUAL)) { + } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))) { if (is_click || !VIsual_active) { if (VIsual_active) { orig_cursor = VIsual; diff --git a/src/nvim/option.c b/src/nvim/option.c index d60c8bc01c..d43dd9ba15 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3210,11 +3210,7 @@ ambw_end: } if (varp == &p_mouse) { - if (*p_mouse == NUL) { - ui_call_mouse_off(); - } else { - setmouse(); // in case 'mouse' changed - } + setmouse(); // in case 'mouse' changed } if (curwin->w_curswant != MAXCOL @@ -4984,11 +4980,7 @@ void ui_refresh_options(void) ui_call_option_set(name, value); } if (p_mouse != NULL) { - if (*p_mouse == NUL) { - ui_call_mouse_off(); - } else { - setmouse(); - } + setmouse(); } } diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 64a09dc2b4..df2bfbce34 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -2313,6 +2313,7 @@ return { deny_duplicates=true, vi_def=true, secure=true, + expand=true, varname='p_shadafile', defaults={if_true={vi=""}} }, diff --git a/src/nvim/screen.c b/src/nvim/screen.c index dc028f0ed7..a7fd2bfcc6 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -620,7 +620,7 @@ int update_screen(int type) /* Clear or redraw the command line. Done last, because scrolling may * mess up the command line. */ - if (clear_cmdline || redraw_cmdline || redraw_mode) { + if (clear_cmdline || redraw_cmdline) { showmode(); } @@ -2013,7 +2013,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, // end-of-line int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used - bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines >= 0; + bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; // saved "extra" items for when draw_state becomes WL_LINE (again) int saved_n_extra = 0; @@ -6559,28 +6559,12 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col, return; } -// Return true when postponing displaying the mode message: when not redrawing -// or inside a mapping. -bool skip_showmode(void) -{ - // Call char_avail() only when we are going to show something, because it - // takes a bit of time. redrawing() may also call char_avail_avail(). - if (global_busy - || msg_silent != 0 - || !redrawing() - || (char_avail() && !KeyTyped)) { - redraw_mode = true; // show mode later - return true; - } - return false; -} // Show the current mode and ruler. // // If clear_cmdline is TRUE, clear the rest of the cmdline. // If clear_cmdline is FALSE there may be a message there that needs to be // cleared only if a mode is shown. -// If redraw_mode is true show or clear the mode. // Return the length of the message (0 if no message). int showmode(void) { @@ -6606,8 +6590,12 @@ int showmode(void) || restart_edit || VIsual_active)); if (do_mode || reg_recording != 0) { - if (skip_showmode()) { - return 0; // show mode later + // Don't show mode right now, when not redrawing or inside a mapping. + // Call char_avail() only when we are going to show something, because + // it takes a bit of time. + if (!redrawing() || (char_avail() && !KeyTyped) || msg_silent != 0) { + redraw_cmdline = TRUE; /* show mode later */ + return 0; } nwr_save = need_wait_return; @@ -6727,11 +6715,10 @@ int showmode(void) need_clear = true; } - mode_displayed = true; - if (need_clear || clear_cmdline || redraw_mode) { + mode_displayed = TRUE; + if (need_clear || clear_cmdline) msg_clr_eos(); - } - msg_didout = false; // overwrite this message + msg_didout = FALSE; /* overwrite this message */ length = msg_col; msg_col = 0; msg_no_more = false; @@ -6740,9 +6727,6 @@ int showmode(void) } else if (clear_cmdline && msg_silent == 0) { // Clear the whole command line. Will reset "clear_cmdline". msg_clr_cmdline(); - } else if (redraw_mode) { - msg_pos_mode(); - msg_clr_eos(); } // NB: also handles clearing the showmode if it was emtpy or disabled @@ -6759,7 +6743,6 @@ int showmode(void) win_redr_ruler(last, true); } redraw_cmdline = false; - redraw_mode = false; clear_cmdline = false; return length; diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 90945eafd7..90af010164 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -3942,7 +3942,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int msg_start(); msg_puts(_(msg_compressing)); msg_clr_eos(); - msg_didout = false; + msg_didout = FALSE; msg_col = 0; ui_flush(); } diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim index 2567dd2be2..076f03fdd8 100644 --- a/src/nvim/testdir/test_bufline.vim +++ b/src/nvim/testdir/test_bufline.vim @@ -19,7 +19,7 @@ func Test_setbufline_getbufline() let b = bufnr('%') wincmd w call assert_equal(1, setbufline(b, 5, ['x'])) - call assert_equal(1, setbufline(bufnr('$') + 1, 1, ['x'])) + call assert_equal(1, setbufline(1234, 1, ['x'])) call assert_equal(0, setbufline(b, 4, ['d', 'e'])) call assert_equal(['c'], getbufline(b, 3)) call assert_equal(['d'], getbufline(b, 4)) diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index d0a8f342c9..30239a90c2 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -89,65 +89,6 @@ func Test_echoerr() call test_ignore_error('RESET') endfunc -func Test_mode_message_at_leaving_insert_by_ctrl_c() - if !has('terminal') || has('gui_running') - return - endif - - " Set custom statusline built by user-defined function. - let testfile = 'Xtest.vim' - call writefile([ - \ 'func StatusLine() abort', - \ ' return ""', - \ 'endfunc', - \ 'set statusline=%!StatusLine()', - \ 'set laststatus=2', - \ ], testfile) - - let rows = 10 - let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows}) - call term_wait(buf, 200) - call assert_equal('run', job_status(term_getjob(buf))) - - call term_sendkeys(buf, "i") - call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, rows))}) - call term_sendkeys(buf, "\<C-C>") - call WaitForAssert({-> assert_match('^\s*$', term_getline(buf, rows))}) - - call term_sendkeys(buf, ":qall!\<CR>") - call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))}) - exe buf . 'bwipe!' - call delete(testfile) -endfunc - -func Test_mode_message_at_leaving_insert_with_esc_mapped() - if !has('terminal') || has('gui_running') - return - endif - - " Set custom statusline built by user-defined function. - let testfile = 'Xtest.vim' - call writefile([ - \ 'set laststatus=2', - \ 'inoremap <Esc> <Esc>00', - \ ], testfile) - - let rows = 10 - let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows}) - call term_wait(buf, 200) - call assert_equal('run', job_status(term_getjob(buf))) - - call term_sendkeys(buf, "i") - call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, rows))}) - call term_sendkeys(buf, "\<Esc>") - call WaitForAssert({-> assert_match('^\s*$', term_getline(buf, rows))}) - - call term_sendkeys(buf, ":qall!\<CR>") - call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))}) - exe buf . 'bwipe!' - call delete(testfile) -endfunc - func Test_echospace() set noruler noshowcmd laststatus=1 call assert_equal(&columns - 1, v:echospace) diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index 8ef8bbc23a..f71da92bf8 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -178,15 +178,20 @@ func Test_mksession_rtp() set sessionoptions& endfunc -" Verify that arglist is stored correctly to the session file. func Test_mksession_arglist() %argdel next file1 file2 file3 file4 + new + next | next mksession! Xtest_mks.out source Xtest_mks.out call assert_equal(['file1', 'file2', 'file3', 'file4'], argv()) + call assert_equal(2, argidx()) + wincmd w + call assert_equal(0, argidx()) call delete('Xtest_mks.out') + enew | only argdel * endfunc @@ -220,6 +225,53 @@ func Test_mksession_one_buffer_two_windows() call delete('Xtest_mks.out') endfunc +func Test_mksession_lcd_multiple_tabs() + tabnew + tabnew + lcd . + tabfirst + lcd . + mksession! Xtest_mks.out + tabonly + source Xtest_mks.out + call assert_true(haslocaldir(), 'Tab 1 localdir') + tabnext 2 + call assert_true(!haslocaldir(), 'Tab 2 localdir') + tabnext 3 + call assert_true(haslocaldir(), 'Tab 3 localdir') + call delete('Xtest_mks.out') +endfunc + +func Test_mksession_blank_tabs() + tabnew + tabnew + tabnew + tabnext 3 + mksession! Xtest_mks.out + tabnew + tabnew + tabnext 2 + source Xtest_mks.out + call assert_equal(4, tabpagenr('$'), 'session restore should restore number of tabs') + call assert_equal(3, tabpagenr(), 'session restore should restore the active tab') + call delete('Xtest_mks.out') +endfunc + +func Test_mksession_blank_windows() + split + split + split + 3 wincmd w + mksession! Xtest_mks.out + split + split + 2 wincmd w + source Xtest_mks.out + call assert_equal(4, winnr('$'), 'session restore should restore number of windows') + call assert_equal(3, winnr(), 'session restore should restore the active window') + call delete('Xtest_mks.out') +endfunc + if has('extra_search') func Test_mksession_hlsearch() @@ -356,24 +408,28 @@ func Test_mksession_globals() set sessionoptions+=globals " create different global variables - let g:Global_string = "Sun is shining" + let g:Global_string = "Sun is shining\r\n" let g:Global_count = 100 let g:Global_pi = 3.14 + let g:Global_neg_float = -2.68 mksession! Xtest_mks.out unlet g:Global_string unlet g:Global_count unlet g:Global_pi + unlet g:Global_neg_float source Xtest_mks.out - call assert_equal("Sun is shining", g:Global_string) + call assert_equal("Sun is shining\r\n", g:Global_string) call assert_equal(100, g:Global_count) call assert_equal(3.14, g:Global_pi) + call assert_equal(-2.68, g:Global_neg_float) unlet g:Global_string unlet g:Global_count unlet g:Global_pi + unlet g:Global_neg_float call delete('Xtest_mks.out') set sessionoptions& endfunc @@ -432,20 +488,123 @@ func Test_mksession_resize() for line in lines if line =~ '^set lines=' let found_resize = v:true + break endif endfor - call assert_equal(v:false, found_resize) + call assert_false(found_resize) let lines = readfile('Xtest_mks2.out') let found_resize = v:false for line in lines if line =~ '^set lines=' let found_resize = v:true + break + endif + endfor + call assert_true(found_resize) + + call delete('Xtest_mks1.out') + call delete('Xtest_mks2.out') + set sessionoptions& +endfunc + +" Test for mksession with a named scratch buffer +func Test_mksession_scratch() + set sessionoptions&vi + enew | only + file Xscratch + set buftype=nofile + mksession! Xtest_mks.out + %bwipe + source Xtest_mks.out + call assert_equal('Xscratch', bufname('')) + call assert_equal('nofile', &buftype) + %bwipe + call delete('Xtest_mks.out') + set sessionoptions& +endfunc + +" Test for mksession with fold options +func Test_mksession_foldopt() + set sessionoptions-=options + set sessionoptions+=folds + new + setlocal foldenable + setlocal foldmethod=expr + setlocal foldmarker=<<<,>>> + setlocal foldignore=% + setlocal foldlevel=2 + setlocal foldminlines=10 + setlocal foldnestmax=15 + mksession! Xtest_mks.out + close + %bwipe + + source Xtest_mks.out + call assert_true(&foldenable) + call assert_equal('expr', &foldmethod) + call assert_equal('<<<,>>>', &foldmarker) + call assert_equal('%', &foldignore) + call assert_equal(2, &foldlevel) + call assert_equal(10, &foldminlines) + call assert_equal(15, &foldnestmax) + + close + %bwipe + set sessionoptions& +endfunc + +" Test for mksession with window position +func Test_mksession_winpos() + if !has('gui_running') + " Only applicable in GUI Vim + return + endif + set sessionoptions+=winpos + mksession! Xtest_mks.out + let found_winpos = v:false + let lines = readfile('Xtest_mks.out') + for line in lines + if line =~ '^winpos ' + let found_winpos = v:true + break + endif + endfor + call assert_true(found_winpos) + call delete('Xtest_mks.out') + set sessionoptions& +endfunc + +" Test for mksession with 'compatible' option +func Test_mksession_compatible() + throw 'skipped: Nvim does not support "compatible" option' + mksession! Xtest_mks1.out + set compatible + mksession! Xtest_mks2.out + set nocp + + let test_success = v:false + let lines = readfile('Xtest_mks1.out') + for line in lines + if line =~ '^if &cp | set nocp | endif' + let test_success = v:true + break + endif + endfor + call assert_true(test_success) + + let test_success = v:false + let lines = readfile('Xtest_mks2.out') + for line in lines + if line =~ '^if !&cp | set cp | endif' + let test_success = v:true + break endif endfor - call assert_equal(v:true, found_resize) + call assert_true(test_success) call delete('Xtest_mks1.out') call delete('Xtest_mks2.out') + set compatible& set sessionoptions& endfunc diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index c630e678fd..bed39d0741 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -850,6 +850,14 @@ func Test_window_resize() exe other_winnr .. 'resize +1' call assert_equal(12, winheight(other_winnr)) call assert_equal(&lines - 10 - 3 -2, winheight(0)) + close + + vsplit + wincmd l + let other_winnr = winnr('h') + call assert_notequal(winnr(), other_winnr) + exe 'vert ' .. other_winnr .. 'resize -100' + call assert_equal(0, winwidth(other_winnr)) %bwipe! endfunc diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 685da77b39..c6c09c80d7 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -61,6 +61,9 @@ static bool pending_mode_info_update = false; static bool pending_mode_update = false; static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE; +static bool has_mouse = false; +static int pending_has_mouse = -1; + #if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL # define UI_LOG(funname) #else @@ -220,6 +223,7 @@ void ui_refresh(void) ui_mode_info_set(); pending_mode_update = true; ui_cursor_shape(); + pending_has_mouse = -1; } int ui_pum_get_height(void) @@ -459,10 +463,69 @@ void ui_flush(void) ui_call_mode_change(cstr_as_string(full_name), ui_mode_idx); pending_mode_update = false; } + if (pending_has_mouse != has_mouse) { + (has_mouse ? ui_call_mouse_on : ui_call_mouse_off)(); + pending_has_mouse = has_mouse; + } ui_call_flush(); } + +/// Check if 'mouse' is active for the current mode +/// +/// TODO(bfredl): precompute the State -> active mapping when 'mouse' changes, +/// then this can be checked directly in ui_flush() +void ui_check_mouse(void) +{ + has_mouse = false; + // Be quick when mouse is off. + if (*p_mouse == NUL) { + return; + } + + int checkfor = MOUSE_NORMAL; // assume normal mode + if (VIsual_active) { + checkfor = MOUSE_VISUAL; + } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) { + checkfor = MOUSE_RETURN; + } else if (State & INSERT) { + checkfor = MOUSE_INSERT; + } else if (State & CMDLINE) { + checkfor = MOUSE_COMMAND; + } else if (State == CONFIRM || State == EXTERNCMD) { + checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd" + } + + // mouse should be active if at least one of the following is true: + // - "c" is in 'mouse', or + // - 'a' is in 'mouse' and "c" is in MOUSE_A, or + // - the current buffer is a help file and 'h' is in 'mouse' and we are in a + // normal editing mode (not at hit-return message). + for (char_u *p = p_mouse; *p; p++) { + switch (*p) { + case 'a': + if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) { + has_mouse = true; + return; + } + break; + case MOUSE_HELP: + if (checkfor != MOUSE_RETURN && curbuf->b_help) { + has_mouse = true; + return; + } + break; + default: + if (checkfor == *p) { + has_mouse = true; + return; + } + } + } +} + /// Check if current mode has changed. +/// /// May update the shape of the cursor. void ui_cursor_shape(void) { diff --git a/src/nvim/window.c b/src/nvim/window.c index 2dcce2d8cb..00f49724b6 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5349,6 +5349,8 @@ void win_setwidth_win(int width, win_T *wp) width = p_wmw; if (width == 0) width = 1; + } else if (width < 0) { + width = 0; } if (wp->w_floating) { wp->w_float_config.width = width; diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua index bef41e52d4..fa8f7d873f 100644 --- a/test/functional/eval/null_spec.lua +++ b/test/functional/eval/null_spec.lua @@ -121,7 +121,7 @@ describe('NULL', function() null_test('does not make Neovim crash when v:oldfiles gets assigned to that', ':let v:oldfiles = L|oldfiles', 0) null_expr_test('does not make complete() crash or error out', 'execute(":normal i\\<C-r>=complete(1, L)[-1]\\n")', - 0, '', function() + '', '\n', function() eq({''}, curbufmeths.get_lines(0, -1, false)) end) null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, 0) diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua index 3f57568b8e..9ee0735e40 100644 --- a/test/functional/eval/timer_spec.lua +++ b/test/functional/eval/timer_spec.lua @@ -130,12 +130,12 @@ describe('timers', function() nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem', {'repeat': -1})") screen:expect([[ - ^ITEM 1 | + ITEM 1 | ITEM 2 | {1:~ }| {1:~ }| {1:~ }| - | + ^ | ]]) nvim_async("command", "let g:cont = 1") diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 8d654f6e5b..32f9ae030f 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -5344,45 +5344,6 @@ describe('floatwin', function() -- at least. Also check invisible EndOfBuffer region blends correctly. meths.buf_set_lines(buf, 0, -1, true, {" x x x xx", " x x x x"}) win = meths.open_win(buf, false, {relative='editor', width=12, height=3, row=0, col=11, style='minimal'}) - if multigrid then - screen:expect{grid=[[ - ## grid 1 - [2:----------------------------------------]| - [2:----------------------------------------]| - [2:----------------------------------------]| - [2:----------------------------------------]| - [2:----------------------------------------]| - [2:----------------------------------------]| - [3:----------------------------------------]| - ## grid 2 - # TODO: 测试字典信息的准确性 | - # FIXME: 测试字典信息的准确^性 | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - ## grid 3 - | - ## grid 6 - {1: x x x xx}| - {1: x x x x}| - {1: }| - ]], float_pos={ - [6] = { { - id = 1003 - }, "NW", 1, 0, 11, true } - }} - else - screen:expect{grid=[[ - # TODO: 测 {1: x x x xx} 确性 | - # FIXME: 测{1: x x x x}准确^性 | - {0:~ }{1: }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - | - ]]} - end meths.win_set_option(win, 'winblend', 30) screen:set_default_attr_ids({ [1] = {foreground = tonumber('0xb282b2'), background = tonumber('0xffcfff')}, @@ -5420,7 +5381,7 @@ describe('floatwin', function() }, "NW", 1, 0, 11, true } }} else - screen:expect{grid=[[ + screen:expect([[ # TODO: 测 {2: x x x}{1:息}{2: xx} 确性 | # FIXME: 测{1:试}{2:x x x}{1:息}{2: x}准确^性 | {3:~ }{4: }{3: }| @@ -5428,7 +5389,7 @@ describe('floatwin', function() {3:~ }| {3:~ }| | - ]]} + ]]) end meths.win_set_config(win, {relative='editor', row=0, col=12}) diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index a741136111..7bca741ae3 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -45,13 +45,33 @@ describe('ui/mouse/input', function() it('single left click moves cursor', function() feed('<LeftMouse><2,1>') - screen:expect([[ + screen:expect{grid=[[ testing | mo^use | support and selection | {0:~ }| | + ]], mouse_enabled=true} + feed('<LeftMouse><0,0>') + screen:expect([[ + ^testing | + mouse | + support and selection | + {0:~ }| + | ]]) + end) + + it("in external ui works with unset 'mouse'", function() + meths.set_option('mouse', '') + feed('<LeftMouse><2,1>') + screen:expect{grid=[[ + testing | + mo^use | + support and selection | + {0:~ }| + | + ]], mouse_enabled=false} feed('<LeftMouse><0,0>') screen:expect([[ ^testing | diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 5104c58796..fcf6926433 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -170,7 +170,7 @@ function Screen.new(width, height) ruler = {}, hl_groups = {}, _default_attr_ids = nil, - _mouse_enabled = true, + mouse_enabled = true, _attrs = {}, _hl_info = {[0]={}}, _attr_table = {[0]={{},{}}}, @@ -318,7 +318,7 @@ function Screen:expect(expected, attr_ids, ...) assert(next({...}) == nil, "invalid args to expect()") if type(expected) == "table" then assert(not (attr_ids ~= nil)) - local is_key = {grid=true, attr_ids=true, condition=true, + local is_key = {grid=true, attr_ids=true, condition=true, mouse_enabled=true, any=true, mode=true, unchanged=true, intermediate=true, reset=true, timeout=true, request_cb=true, hl_groups=true} for _, v in ipairs(ext_keys) do @@ -422,12 +422,15 @@ screen:redraw_debug() to show all intermediate screen states. ]]) if expected.mode ~= nil then extstate.mode = self.mode end + if expected.mouse_enabled ~= nil then + extstate.mouse_enabled = self.mouse_enabled + end if expected.win_viewport == nil then extstate.win_viewport = nil end -- Convert assertion errors into invalid screen state descriptions. - for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do + for _, k in ipairs(concat_tables(ext_keys, {'mode', 'mouse_enabled'})) do -- Empty states are considered the default and need not be mentioned. if (not (expected[k] == nil and isempty(extstate[k]))) then local status, res = pcall(eq, expected[k], extstate[k], k) @@ -799,17 +802,15 @@ function Screen:_handle_busy_stop() end function Screen:_handle_mouse_on() - self._mouse_enabled = true + self.mouse_enabled = true end function Screen:_handle_mouse_off() - self._mouse_enabled = false + self.mouse_enabled = false end function Screen:_handle_mode_change(mode, idx) - if self._mode_info ~= nil then - assert(mode == self._mode_info[idx+1].name) - end + assert(mode == self._mode_info[idx+1].name) self.mode = mode end diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index 3bb72303bf..656f613c6a 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -20,7 +20,6 @@ describe('search highlighting', function() [2] = {background = colors.Yellow}, -- Search [3] = {reverse = true}, [4] = {foreground = colors.Red}, -- Message - [5] = {bold = true, reverse = true}, [6] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}, -- Folded }) end) @@ -176,15 +175,7 @@ describe('search highlighting', function() ]]) feed('/foo') helpers.poke_eventloop() - screen:expect{grid=[[ - {3:foo} bar baz {3:│} | - bar baz {2:foo} {3:│} | - bar {2:foo} baz {3:│} | - {3:│} | - {1:~ }{3:│} | - {5:[No Name] [+] }{3:term }| - /foo^ | - ]]} + screen:expect_unchanged() end) it('works with incsearch', function() @@ -480,6 +471,19 @@ describe('search highlighting', function() {4:search hit BOTTOM, continuing at TOP} | ]]) + -- check hilights work also in folds + feed("zf4j") + command("%foldopen") + screen:expect([[ + very {5:spec^ial}{2: te}{6:xt} | + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {4:search hit BOTTOM, continuing at TOP} | + ]]) + feed_command("call clearmatches()") screen:expect([[ very spec{2:^ial te}xt | |