From 65cbe0cc35c07a929152b86e78717efa4ba155da Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 5 Jul 2022 17:33:23 +0800 Subject: vim-patch:8.1.0342: crash when a callback deletes a window that is being used Problem: Crash when a callback deletes a window that is being used. Solution: Do not unload a buffer that is being displayed while redrawing the screen. Also avoid invoking callbacks while redrawing. (closes vim/vim#2107) https://github.com/vim/vim/commit/94f01956a583223dafe24135489d0ab1100ab0ad Omit parse_queued_messages(): N/A. Cherry-pick a break statement from patch 8.1.0425. --- src/nvim/buffer.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 85f79deb2f..e3f923a2c0 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -93,7 +93,6 @@ #endif static char *e_auabort = N_("E855: Autocommands caused command to abort"); -static char *e_buflocked = N_("E937: Attempt to delete a buffer that is in use"); // Number of times free_buffer() was called. static int buf_free_count = 0; @@ -401,6 +400,27 @@ bool buf_valid(buf_T *buf) return false; } +/// Return true when buffer "buf" can be unloaded. +/// Give an error message and return false when the buffer is locked or the +/// screen is being redrawn and the buffer is in a window. +static bool can_unload_buffer(buf_T *buf) +{ + bool can_unload = !buf->b_locked; + + if (can_unload && updating_screen) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer == buf) { + can_unload = false; + break; + } + } + } + if (!can_unload) { + emsg(_("E937: Attempt to delete a buffer that is in use")); + } + return can_unload; +} + /// Close the link to a buffer. /// /// @param win If not NULL, set b_last_cursor. @@ -458,8 +478,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i // Disallow deleting the buffer when it is locked (already being closed or // halfway a command that relies on it). Unloading is allowed. - if (buf->b_locked > 0 && (del_buf || wipe_buf)) { - emsg(_(e_buflocked)); + if ((del_buf || wipe_buf) && !can_unload_buffer(buf)) { return false; } @@ -1206,8 +1225,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (unload) { int forward; bufref_T bufref; - if (buf->b_locked) { - emsg(_(e_buflocked)); + if (!can_unload_buffer(buf)) { return FAIL; } set_bufref(&bufref, buf); -- cgit From 6bc2d6b66b683faedded01128af8ad98b7130fef Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 15 Oct 2022 16:10:56 +0800 Subject: vim-patch:9.0.0614: SpellFileMissing autocmd may delete buffer Problem: SpellFileMissing autocmd may delete buffer. Solution: Disallow deleting the current buffer to avoid using freed memory. https://github.com/vim/vim/commit/ef976323e770315b5fca544efb6b2faa25674d15 --- src/nvim/buffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index e3f923a2c0..29b00bad2a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -93,6 +93,8 @@ #endif static char *e_auabort = N_("E855: Autocommands caused command to abort"); +static char e_attempt_to_delete_buffer_that_is_in_use_str[] + = N_("E937: Attempt to delete a buffer that is in use: %s"); // Number of times free_buffer() was called. static int buf_free_count = 0; @@ -416,7 +418,9 @@ static bool can_unload_buffer(buf_T *buf) } } if (!can_unload) { - emsg(_("E937: Attempt to delete a buffer that is in use")); + char *fname = buf->b_fname != NULL ? buf->b_fname : buf->b_ffname; + semsg(_(e_attempt_to_delete_buffer_that_is_in_use_str), + fname != NULL ? fname : "[No Name]"); } return can_unload; } -- cgit From 19eb7054ff7b1fbc78e56e7f9ed6537b085147bc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Oct 2022 08:06:07 +0800 Subject: vim-patch:9.0.0761: cannot use 'indentexpr' for Lisp indenting Problem: Cannot use 'indentexpr' for Lisp indenting. Solution: Add the 'lispoptions' option. https://github.com/vim/vim/commit/49846fb1a31de99f49d6a7e70efe685197423c84 vim-patch:9.0.0762: build failure Problem: Build failure. Solution: Add missing change. https://github.com/vim/vim/commit/4b082c4bd05f504fda1acaa9d28fca55a2d04857 --- src/nvim/buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 29b00bad2a..84ff2fa59b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1959,8 +1959,9 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_ft); clear_string_option(&buf->b_p_cink); clear_string_option(&buf->b_p_cino); - clear_string_option(&buf->b_p_cinw); + clear_string_option(&buf->b_p_lop); clear_string_option(&buf->b_p_cinsd); + clear_string_option(&buf->b_p_cinw); clear_string_option(&buf->b_p_cpt); clear_string_option(&buf->b_p_cfu); clear_string_option(&buf->b_p_ofu); -- cgit From 66933b45dcff8cc9f323a71583bca3698566abb9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 19 Oct 2022 07:10:22 +0800 Subject: vim-patch:9.0.0789: dummy buffer ends up in a window Problem: Dummy buffer ends up in a window. Solution: Disallow navigating to a dummy buffer. https://github.com/vim/vim/commit/8f3c3c6cd044e3b5bf08dbfa3b3f04bb3f711bad --- src/nvim/buffer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 84ff2fa59b..8016904702 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1224,6 +1224,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } return FAIL; } + if ((action == DOBUF_GOTO || action == DOBUF_SPLIT) && (buf->b_flags & BF_DUMMY)) { + // disallow navigating to the dummy buffer + semsg(_(e_nobufnr), count); + return FAIL; + } // delete buffer "buf" from memory and/or the list if (unload) { -- cgit From 4158ad38ecb107cfe3d1dd7472cc9e17039f6ee2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 30 Oct 2022 07:56:10 +0800 Subject: vim-patch:9.0.0819: still a build error, tests are failing Problem: Still a build error, tests are failing. Solution: Correct recent changes. Add missing init for 'eof'. https://github.com/vim/vim/commit/1577537f109d97a975fda9a899cacfb598617767 vim-patch:1577537f109d Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 8016904702..ade5c35450 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -689,6 +689,8 @@ void buf_clear_file(buf_T *buf) { buf->b_ml.ml_line_count = 1; unchanged(buf, true, true); + buf->b_p_eof = false; + buf->b_start_eof = false; buf->b_p_eol = true; buf->b_start_eol = true; buf->b_p_bomb = false; -- cgit From 900dd2bdab85b25237cec638265d44c2174154ed Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 20 Aug 2022 08:27:10 +0800 Subject: vim-patch:8.2.3665: cannot use a lambda for 'tagfunc' Problem: Cannot use a lambda for 'tagfunc'. Solution: Use 'tagfunc' like 'opfunc'. (Yegappan Lakshmanan, closes vim/vim#9204) https://github.com/vim/vim/commit/19916a8c8920b6a1fd737ffa6d4e363fc7a96319 Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ade5c35450..4c8faccaa7 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1981,6 +1981,7 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_tags); clear_string_option(&buf->b_p_tc); clear_string_option(&buf->b_p_tfu); + callback_free(&buf->b_tfu_cb); clear_string_option(&buf->b_p_dict); clear_string_option(&buf->b_p_tsr); clear_string_option(&buf->b_p_qe); -- cgit From 1e4adf4b56cb7a360d16c4d04290c50ae7e80fbc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 20 Aug 2022 08:45:15 +0800 Subject: vim-patch:8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc' Problem: Cannot use a lambda for 'completefunc' and 'omnifunc'. Solution: Implement lambda support. (Yegappan Lakshmanan, closes vim/vim#9257) https://github.com/vim/vim/commit/8658c759f05b317707d56e3b65a5ef63930c7498 Comment out Vim9 script in tests. Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 4c8faccaa7..2c87677925 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1971,8 +1971,11 @@ void free_buf_options(buf_T *buf, int free_p_ff) clear_string_option(&buf->b_p_cinw); clear_string_option(&buf->b_p_cpt); clear_string_option(&buf->b_p_cfu); + callback_free(&buf->b_cfu_cb); clear_string_option(&buf->b_p_ofu); + callback_free(&buf->b_ofu_cb); clear_string_option(&buf->b_p_tsrfu); + callback_free(&buf->b_tsrfu_cb); clear_string_option(&buf->b_p_gp); clear_string_option(&buf->b_p_mp); clear_string_option(&buf->b_p_efm); -- cgit From 8147d3df284a075f89746f9d5e948b5220c45f0b Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Tue, 8 Nov 2022 00:21:22 +0100 Subject: vim-patch:9.0.0844: handling 'statusline' errors is spread out (#20992) Problem: Handling 'statusline' errors is spread out. Solution: Pass the option name to the lower levels so the option can be reset there when an error is encountered. (Luuk van Baal, closes vim/vim#11467) https://github.com/vim/vim/commit/7b224fdf4a29f115567d4fc8629c1cef92d8444a --- src/nvim/buffer.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 2c87677925..fa0b2a83c8 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3203,17 +3203,9 @@ void maketitle(void) if (*p_titlestring != NUL) { if (stl_syntax & STL_IN_TITLE) { - int use_sandbox = false; - const int called_emsg_before = called_emsg; - - use_sandbox = was_set_insecurely(curwin, "titlestring", 0); - build_stl_str_hl(curwin, buf, sizeof(buf), - p_titlestring, use_sandbox, - 0, maxlen, NULL, NULL); + build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring, + "titlestring", 0, 0, maxlen, NULL, NULL); title_str = buf; - if (called_emsg > called_emsg_before) { - set_string_option_direct("titlestring", -1, "", OPT_FREE, SID_ERROR); - } } else { title_str = p_titlestring; } @@ -3317,16 +3309,8 @@ void maketitle(void) icon_str = buf; if (*p_iconstring != NUL) { if (stl_syntax & STL_IN_ICON) { - int use_sandbox = false; - const int called_emsg_before = called_emsg; - - use_sandbox = was_set_insecurely(curwin, "iconstring", 0); - build_stl_str_hl(curwin, icon_str, sizeof(buf), - p_iconstring, use_sandbox, - 0, 0, NULL, NULL); - if (called_emsg > called_emsg_before) { - set_string_option_direct("iconstring", -1, "", OPT_FREE, SID_ERROR); - } + build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring, + "iconstring", 0, 0, 0, NULL, NULL); } else { icon_str = p_iconstring; } -- cgit From 0d8e8d36ec7d3f4967f27389b4b94edf3ba57433 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 11 Nov 2022 17:50:52 +0800 Subject: vim-patch:8.2.1919: assert_fails() setting emsg_silent changes normal execution (#20998) Problem: Assert_fails() setting emsg_silent changes normal execution. Solution: Use a separate flag in_assert_fails. https://github.com/vim/vim/commit/28ee892ac4197421b3317f195512ca64cc56a5b4 Cherry-pick no_wait_return from patch 9.0.0846. Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index fa0b2a83c8..78b058ea9a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1842,7 +1842,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf); if (top_file_num < 0) { // wrap around (may cause duplicates) emsg(_("W14: Warning: List of file names overflow")); - if (emsg_silent == 0) { + if (emsg_silent == 0 && !in_assert_fails) { ui_flush(); os_delay(3001L, true); // make sure it is noticed } -- cgit From 66360675cf4d091b7460e4a8e1435c13216c1929 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 11 Sep 2022 17:12:44 +0200 Subject: build: allow IWYU to fix includes for all .c files Allow Include What You Use to remove unnecessary includes and only include what is necessary. This helps with reducing compilation times and makes it easier to visualise which dependencies are actually required. Work on https://github.com/neovim/neovim/issues/549, but doesn't close it since this only works fully for .c files and not headers. --- src/nvim/buffer.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 78b058ea9a..485a6669ef 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -20,10 +20,16 @@ // #include +#include #include #include +#include #include +#include +#include +#include "auto/config.h" +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/arglist.h" #include "nvim/ascii.h" @@ -44,6 +50,7 @@ #include "nvim/eval/vars.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" @@ -53,21 +60,25 @@ #include "nvim/fold.h" #include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" #include "nvim/hashtab.h" #include "nvim/help.h" -#include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/main.h" +#include "nvim/map.h" #include "nvim/mapping.h" #include "nvim/mark.h" -#include "nvim/mark_defs.h" #include "nvim/mbyte.h" +#include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" +#include "nvim/normal.h" #include "nvim/option.h" #include "nvim/optionstr.h" +#include "nvim/os/fs_defs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" @@ -76,11 +87,14 @@ #include "nvim/quickfix.h" #include "nvim/regexp.h" #include "nvim/runtime.h" +#include "nvim/screen.h" #include "nvim/sign.h" #include "nvim/spell.h" #include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/syntax.h" +#include "nvim/terminal.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/usercmd.h" -- cgit From 3b96ccf7d35be90e49029dec76344d3d92ad91dc Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 26 Nov 2022 18:57:46 +0100 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/buffer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 485a6669ef..67c3307e50 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3735,8 +3735,8 @@ static int chk_modeline(linenr_T lnum, int flags) prev = -1; for (s = ml_get(lnum); *s != NUL; s++) { if (prev == -1 || ascii_isspace(prev)) { - if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0) - || STRNCMP(s, "vi:", (size_t)3) == 0) { + if ((prev != -1 && strncmp(s, "ex:", (size_t)3) == 0) + || strncmp(s, "vi:", (size_t)3) == 0) { break; } // Accept both "vim" and "Vim". @@ -3752,7 +3752,7 @@ static int chk_modeline(linenr_T lnum, int flags) if (*e == ':' && (s[0] != 'V' - || STRNCMP(skipwhite((char *)e + 1), "set", 3) == 0) + || strncmp(skipwhite(e + 1), "set", 3) == 0) && (s[3] == ':' || (VIM_VERSION_100 >= vers && isdigit(s[3])) || (VIM_VERSION_100 < vers && s[3] == '<') @@ -3801,8 +3801,8 @@ static int chk_modeline(linenr_T lnum, int flags) // "vi:set opt opt opt: foo" -- foo not interpreted // "vi:opt opt opt: foo" -- foo interpreted // Accept "se" for compatibility with Elvis. - if (STRNCMP(s, "set ", (size_t)4) == 0 - || STRNCMP(s, "se ", (size_t)3) == 0) { + if (strncmp(s, "set ", (size_t)4) == 0 + || strncmp(s, "se ", (size_t)3) == 0) { if (*e != ':') { // no terminating ':'? break; } -- cgit From 0b79137c59fbe44bded76f123602e552dc6f7b03 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 16:47:29 +0800 Subject: vim-patch:8.1.2001: some source files are too big (#21231) Problem: Some source files are too big. Solution: Move buffer and window related functions to evalbuffer.c and evalwindow.c. (Yegappan Lakshmanan, closes vim/vim#4898) https://github.com/vim/vim/commit/261f346f8154c0ec7094a4a211c653c74e9f7c2e --- src/nvim/buffer.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 67c3307e50..6cb171978b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3961,30 +3961,6 @@ char *buf_spname(buf_T *buf) return NULL; } -/// Find a window for buffer "buf". -/// If found true is returned and "wp" and "tp" are set to -/// the window and tabpage. -/// If not found, false is returned. -/// -/// @param buf buffer to find a window for -/// @param[out] wp stores the found window -/// @param[out] tp stores the found tabpage -/// -/// @return true if a window was found for the buffer. -bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp) -{ - *wp = NULL; - *tp = NULL; - FOR_ALL_TAB_WINDOWS(tp2, wp2) { - if (wp2->w_buffer == buf) { - *tp = tp2; - *wp = wp2; - return true; - } - } - return false; -} - static int buf_signcols_inner(buf_T *buf, int maximum) { sign_entry_T *sign; // a sign in the sign list -- cgit From 273358651af6b6d172944cd1b1b41a9869d53b10 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 20:09:07 +0800 Subject: refactor: buffer_ensure_loaded() Cherry-picked from Vim patch 8.1.1612. --- src/nvim/buffer.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 6cb171978b..1ac19a4699 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -175,6 +175,19 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) return retval; } +/// Ensure buffer "buf" is loaded. Does not trigger the swap-exists action. +void buffer_ensure_loaded(buf_T *buf) +{ + if (buf->b_ml.ml_mfp == NULL) { + aco_save_T aco; + + aucmd_prepbuf(&aco, buf); + swap_exists_action = SEA_NONE; + open_buffer(false, NULL, 0); + aucmd_restbuf(&aco); + } +} + /// Open current buffer, that is: open the memfile and read the file into /// memory. /// -- cgit From 3173d07564e7cdf0834099a379f0faf480c76224 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 18:20:11 +0800 Subject: vim-patch:9.0.0965: using one window for executing autocommands is insufficient Problem: Using one window for executing autocommands is insufficient. Solution: Use up to five windows for executing autocommands. https://github.com/vim/vim/commit/e76062c078debed0df818f70e4db14ad7a7cb53a N/A patches for version.c: vim-patch:9.0.0966: some compilers don't allow a declaration after a label Problem: Some compilers don't allow a declaration after a label. Solution: Move the declaration to the start of the block. (John Marriott) https://github.com/vim/vim/commit/f86490ed4fdab213a28f667abd055c023a73d645 Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 1ac19a4699..2060f799bd 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -181,10 +181,13 @@ void buffer_ensure_loaded(buf_T *buf) if (buf->b_ml.ml_mfp == NULL) { aco_save_T aco; + // Make sure the buffer is in a window. If not then skip it. aucmd_prepbuf(&aco, buf); - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); - aucmd_restbuf(&aco); + if (curbuf == buf) { + swap_exists_action = SEA_NONE; + open_buffer(false, NULL, 0); + aucmd_restbuf(&aco); + } } } @@ -365,18 +368,21 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) if (bufref_valid(&old_curbuf) && old_curbuf.br_buf->b_ml.ml_mfp != NULL) { aco_save_T aco; - // Go to the buffer that was opened. + // Go to the buffer that was opened, make sure it is in a window. + // If not then skip it. aucmd_prepbuf(&aco, old_curbuf.br_buf); - do_modelines(0); - curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); + if (curbuf == old_curbuf.br_buf) { + do_modelines(0); + curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); - if ((flags & READ_NOWINENTER) == 0) { - apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, - &retval); - } + if ((flags & READ_NOWINENTER) == 0) { + apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, + &retval); + } - // restore curwin/curbuf and a few other things - aucmd_restbuf(&aco); + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); + } } return retval; @@ -1329,7 +1335,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) // Repeat this so long as we end up in a window with this buffer. while (buf == curbuf && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) - && (lastwin == aucmd_win || !last_window(curwin))) { + && (is_aucmd_win(lastwin) || !last_window(curwin))) { if (win_close(curwin, false, false) == FAIL) { break; } @@ -4168,9 +4174,14 @@ bool buf_contents_changed(buf_T *buf) exarg_T ea; prep_exarg(&ea, buf); - // set curwin/curbuf to buf and save a few things + // Set curwin/curbuf to buf and save a few things. aco_save_T aco; aucmd_prepbuf(&aco, newbuf); + if (curbuf != newbuf) { + // Failed to find a window for "newbuf". + wipe_buffer(newbuf, false); + return true; + } if (ml_open(curbuf) == OK && readfile(buf->b_ffname, buf->b_fname, -- cgit From 1145a9b2485a4e5072cffe28a958da983cd59e84 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Dec 2022 20:39:24 +0800 Subject: feat(aucmd_win): allow crazy things with hidden buffers (#21250) Problem: Crash when doing crazy things with hidden buffers. Solution: Dynamically allocate the list of autocommand windows. --- src/nvim/buffer.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 2060f799bd..c9fe5f9670 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -181,13 +181,11 @@ void buffer_ensure_loaded(buf_T *buf) if (buf->b_ml.ml_mfp == NULL) { aco_save_T aco; - // Make sure the buffer is in a window. If not then skip it. + // Make sure the buffer is in a window. aucmd_prepbuf(&aco, buf); - if (curbuf == buf) { - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); - aucmd_restbuf(&aco); - } + swap_exists_action = SEA_NONE; + open_buffer(false, NULL, 0); + aucmd_restbuf(&aco); } } @@ -369,20 +367,17 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) aco_save_T aco; // Go to the buffer that was opened, make sure it is in a window. - // If not then skip it. aucmd_prepbuf(&aco, old_curbuf.br_buf); - if (curbuf == old_curbuf.br_buf) { - do_modelines(0); - curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); - - if ((flags & READ_NOWINENTER) == 0) { - apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, - &retval); - } + do_modelines(0); + curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED); - // restore curwin/curbuf and a few other things - aucmd_restbuf(&aco); + if ((flags & READ_NOWINENTER) == 0) { + apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, false, curbuf, + &retval); } + + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); } return retval; @@ -4177,11 +4172,6 @@ bool buf_contents_changed(buf_T *buf) // Set curwin/curbuf to buf and save a few things. aco_save_T aco; aucmd_prepbuf(&aco, newbuf); - if (curbuf != newbuf) { - // Failed to find a window for "newbuf". - wipe_buffer(newbuf, false); - return true; - } if (ml_open(curbuf) == OK && readfile(buf->b_ffname, buf->b_fname, -- cgit From a91ba088abf7b21f640f671ad7f211c0957b4765 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 4 Dec 2022 08:38:38 +0800 Subject: vim-patch:8.2.2182: Vim9: value of 'magic' is still relevant Problem: Vim9: value of 'magic' is still relevant. Solution: Always behave like 'magic' is on in Vim9 script (closes vim/vim#7509) https://github.com/vim/vim/commit/f4e2099e39ed4d71aed0f9a9579455aed5ec6cc2 EX_NONWHITE_OK is N/A: only applies to Vim9 script. Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c9fe5f9670..b67aee6907 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2250,7 +2250,7 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted, } regmatch_T regmatch; - regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); + regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0); if (regmatch.regprog == NULL) { xfree(pat); return -1; -- cgit From 4d860a537076d7eddfb29372ecbdacf1eb5b7d3b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 17 Dec 2022 08:11:35 +0800 Subject: fix(folds): use long for number of folded lines (#21447) Also remove some duplicate unsigned long casts. --- src/nvim/buffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b67aee6907..0c74ccf0f4 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1090,13 +1090,13 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b errormsg = (char *)IObuff; } else if (deleted >= p_report) { if (command == DOBUF_UNLOAD) { - smsg(NGETTEXT("%d buffer unloaded", "%d buffers unloaded", (unsigned long)deleted), + smsg(NGETTEXT("%d buffer unloaded", "%d buffers unloaded", deleted), deleted); } else if (command == DOBUF_DEL) { - smsg(NGETTEXT("%d buffer deleted", "%d buffers deleted", (unsigned long)deleted), + smsg(NGETTEXT("%d buffer deleted", "%d buffers deleted", deleted), deleted); } else { - smsg(NGETTEXT("%d buffer wiped out", "%d buffers wiped out", (unsigned long)deleted), + smsg(NGETTEXT("%d buffer wiped out", "%d buffers wiped out", deleted), deleted); } } @@ -3149,7 +3149,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) vim_snprintf_add(buffer, IOSIZE, NGETTEXT("%" PRId64 " line --%d%%--", "%" PRId64 " lines --%d%%--", - (unsigned long)curbuf->b_ml.ml_line_count), + curbuf->b_ml.ml_line_count), (int64_t)curbuf->b_ml.ml_line_count, n); } else { vim_snprintf_add(buffer, IOSIZE, -- cgit From 4dd793a256fefb481159f9f93bf7572391e266de Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 3 Jan 2023 14:55:00 +0800 Subject: vim-patch:9.0.1132: code is indented more than needed (#21626) Problem: Code is indented more than needed. Solution: Use an early return to reduce indentation. (Yegappan Lakshmanan, closes vim/vim#11769) https://github.com/vim/vim/commit/dc4daa3a3915fba11ac87d27977240d9a5e0d47d Omit expand_autoload_callback(): only applies to Vim9 script. Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 58 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 26 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 0c74ccf0f4..239f2aa8ba 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -178,15 +178,17 @@ static int read_buffer(int read_stdin, exarg_T *eap, int flags) /// Ensure buffer "buf" is loaded. Does not trigger the swap-exists action. void buffer_ensure_loaded(buf_T *buf) { - if (buf->b_ml.ml_mfp == NULL) { - aco_save_T aco; - - // Make sure the buffer is in a window. - aucmd_prepbuf(&aco, buf); - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); - aucmd_restbuf(&aco); + if (buf->b_ml.ml_mfp != NULL) { + return; } + + aco_save_T aco; + + // Make sure the buffer is in a window. + aucmd_prepbuf(&aco, buf); + swap_exists_action = SEA_NONE; + open_buffer(false, NULL, 0); + aucmd_restbuf(&aco); } /// Open current buffer, that is: open the memfile and read the file into @@ -2903,18 +2905,20 @@ int setfname(buf_T *buf, char *ffname_arg, char *sfname_arg, bool message) void buf_set_name(int fnum, char *name) { buf_T *buf = buflist_findnr(fnum); - if (buf != NULL) { - if (buf->b_sfname != buf->b_ffname) { - xfree(buf->b_sfname); - } - xfree(buf->b_ffname); - buf->b_ffname = xstrdup(name); - buf->b_sfname = NULL; - // Allocate ffname and expand into full path. Also resolves .lnk - // files on Win32. - fname_expand(buf, &buf->b_ffname, &buf->b_sfname); - buf->b_fname = buf->b_sfname; + if (buf == NULL) { + return; } + + if (buf->b_sfname != buf->b_ffname) { + xfree(buf->b_sfname); + } + xfree(buf->b_ffname); + buf->b_ffname = xstrdup(name); + buf->b_sfname = NULL; + // Allocate ffname and expand into full path. Also resolves .lnk + // files on Win32. + fname_expand(buf, &buf->b_ffname, &buf->b_sfname); + buf->b_fname = buf->b_sfname; } /// Take care of what needs to be done when the name of buffer "buf" has changed. @@ -4138,13 +4142,15 @@ char *buf_get_fname(const buf_T *buf) /// Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed. void set_buflisted(int on) { - if (on != curbuf->b_p_bl) { - curbuf->b_p_bl = on; - if (on) { - apply_autocmds(EVENT_BUFADD, NULL, NULL, false, curbuf); - } else { - apply_autocmds(EVENT_BUFDELETE, NULL, NULL, false, curbuf); - } + if (on == curbuf->b_p_bl) { + return; + } + + curbuf->b_p_bl = on; + if (on) { + apply_autocmds(EVENT_BUFADD, NULL, NULL, false, curbuf); + } else { + apply_autocmds(EVENT_BUFDELETE, NULL, NULL, false, curbuf); } } -- cgit From 149209400383c673fdb4fdd1c9a7639139f17936 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:13:06 +0100 Subject: refactor: replace char_u with char 17 - remove STRLCPY (#21235) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/buffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 239f2aa8ba..58abec351b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2760,7 +2760,7 @@ void buflist_list(exarg_T *eap) continue; } if (buf_spname(buf) != NULL) { - STRLCPY(NameBuff, buf_spname(buf), MAXPATHL); + xstrlcpy(NameBuff, buf_spname(buf), MAXPATHL); } else { home_replace(buf, buf->b_fname, (char *)NameBuff, MAXPATHL, true); } @@ -3110,7 +3110,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate) *p++ = '"'; if (buf_spname(curbuf) != NULL) { - STRLCPY(p, buf_spname(curbuf), IOSIZE - (p - buffer)); + xstrlcpy(p, buf_spname(curbuf), (size_t)(IOSIZE - (p - buffer))); } else { if (!fullname && curbuf->b_fname != NULL) { name = curbuf->b_fname; @@ -3436,9 +3436,9 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) } below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1; if (below <= 0) { - STRLCPY(buf, (above == 0 ? _("All") : _("Bot")), buflen); + xstrlcpy(buf, (above == 0 ? _("All") : _("Bot")), (size_t)buflen); } else if (above <= 0) { - STRLCPY(buf, _("Top"), buflen); + xstrlcpy(buf, _("Top"), (size_t)buflen); } else { vim_snprintf(buf, (size_t)buflen, "%2d%%", above > 1000000L ? (int)(above / ((above + below) / 100L)) -- cgit From 50f03773f4b9f4638489ccfd0503dc9e39e5de78 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:37:34 +0100 Subject: refactor: replace char_u with char 18 (#21237) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/buffer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 58abec351b..e6d0dcb8cf 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1089,7 +1089,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b } else { STRCPY(IObuff, _("E517: No buffers were wiped out")); } - errormsg = (char *)IObuff; + errormsg = IObuff; } else if (deleted >= p_report) { if (command == DOBUF_UNLOAD) { smsg(NGETTEXT("%d buffer unloaded", "%d buffers unloaded", deleted), @@ -2762,7 +2762,7 @@ void buflist_list(exarg_T *eap) if (buf_spname(buf) != NULL) { xstrlcpy(NameBuff, buf_spname(buf), MAXPATHL); } else { - home_replace(buf, buf->b_fname, (char *)NameBuff, MAXPATHL, true); + home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, true); } if (message_filtered(NameBuff)) { @@ -2778,7 +2778,7 @@ void buflist_list(exarg_T *eap) } msg_putchar('\n'); - len = vim_snprintf((char *)IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"", + len = vim_snprintf(IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"", buf->b_fnum, buf->b_p_bl ? ' ' : 'u', buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '), @@ -2792,18 +2792,18 @@ void buflist_list(exarg_T *eap) } // put "line 999" in column 40 or after the file name - i = 40 - vim_strsize((char *)IObuff); + i = 40 - vim_strsize(IObuff); do { IObuff[len++] = ' '; } while (--i > 0 && len < IOSIZE - 18); if (vim_strchr(eap->arg, 't') && buf->b_last_used) { - undo_fmt_time((char_u *)IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); + undo_fmt_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used); } else { - vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), _("line %" PRId64), + vim_snprintf(IObuff + len, (size_t)(IOSIZE - len), _("line %" PRId64), buf == curbuf ? (int64_t)curwin->w_cursor.lnum : (int64_t)buflist_findlnum(buf)); } - msg_outtrans((char *)IObuff); + msg_outtrans(IObuff); line_breakcheck(); } -- cgit From 364b131f42509326c912c9b0fef5dfc94ed23b41 Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:12:06 +0100 Subject: feat(ui): add 'statuscolumn' option Problem: Unable to customize the column next to a window ('gutter'). Solution: Add 'statuscolumn' option that follows the 'statusline' syntax, allowing to customize the status column. Also supporting the %@ click execute function label. Adds new items @C and @s which will print the fold and sign columns. Line numbers and signs can be clicked, highlighted, aligned, transformed, margined etc. --- src/nvim/buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index e6d0dcb8cf..1bba146caf 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3236,7 +3236,7 @@ void maketitle(void) if (*p_titlestring != NUL) { if (stl_syntax & STL_IN_TITLE) { build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring, - "titlestring", 0, 0, maxlen, NULL, NULL); + "titlestring", 0, 0, maxlen, NULL, NULL, NULL); title_str = buf; } else { title_str = p_titlestring; @@ -3342,7 +3342,7 @@ void maketitle(void) if (*p_iconstring != NUL) { if (stl_syntax & STL_IN_ICON) { build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring, - "iconstring", 0, 0, 0, NULL, NULL); + "iconstring", 0, 0, 0, NULL, NULL, NULL); } else { icon_str = p_iconstring; } -- cgit From dc7edce650bc2abbcad2fdc12cb77561b36b35af Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 10 Jan 2023 08:46:42 +0800 Subject: vim-patch:partial:9.0.1166: code is indented more than necessary (#21716) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11792) https://github.com/vim/vim/commit/1cfb14aa972ccf3235ac67f07b7db1175b7c5384 Partial port as some highlight.c changes depend on previous patches. Cherry-pick fname_match() change from patch 8.2.4959. Omit internal_func_check_arg_types(): only used for Vim9 script. N/A patches for version.c: vim-patch:9.0.1167: EditorConfig files do not have their own filetype Problem: EditorConfig files do not have their own filetype. Solution: Add the "editorconfig" filetype. (Gregory Anders, closes vim/vim#11779) https://github.com/vim/vim/commit/d41262ed06564cef98a3800e2928e6e0db91abbf Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 73 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 33 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 1bba146caf..cd1059eb0d 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -359,8 +359,9 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg) } apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, false, curbuf, &retval); + // if (retval != OK) { if (retval == FAIL) { - return FAIL; + return retval; } // The autocommands may have changed the current buffer. Apply the @@ -2473,19 +2474,22 @@ static char *fname_match(regmatch_T *rmp, char *name, bool ignore_case) char *match = NULL; char *p; - if (name != NULL) { - // Ignore case when 'fileignorecase' or the argument is set. - rmp->rm_ic = p_fic || ignore_case; - if (vim_regexec(rmp, name, (colnr_T)0)) { + // extra check for valid arguments + if (name == NULL || rmp->regprog == NULL) { + return NULL; + } + + // Ignore case when 'fileignorecase' or the argument is set. + rmp->rm_ic = p_fic || ignore_case; + if (vim_regexec(rmp, name, (colnr_T)0)) { + match = name; + } else if (rmp->regprog != NULL) { + // Replace $(HOME) with '~' and try matching again. + p = home_replace_save(NULL, name); + if (vim_regexec(rmp, p, (colnr_T)0)) { match = name; - } else if (rmp->regprog != NULL) { - // Replace $(HOME) with '~' and try matching again. - p = home_replace_save(NULL, name); - if (vim_regexec(rmp, p, (colnr_T)0)) { - match = name; - } - xfree(p); } + xfree(p); } return match; @@ -2592,17 +2596,18 @@ void buflist_setfpos(buf_T *const buf, win_T *const win, linenr_T lnum, colnr_T static bool wininfo_other_tab_diff(wininfo_T *wip) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - if (wip->wi_opt.wo_diff) { - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - // return false when it's a window in the current tab page, thus - // the buffer was in diff mode here - if (wip->wi_win == wp) { - return false; - } + if (!wip->wi_opt.wo_diff) { + return false; + } + + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + // return false when it's a window in the current tab page, thus + // the buffer was in diff mode here + if (wip->wi_win == wp) { + return false; } - return true; } - return false; + return true; } /// Find info for the current window in buffer "buf". @@ -2625,25 +2630,27 @@ static wininfo_T *find_wininfo(buf_T *buf, bool need_options, bool skip_diff_buf } } + if (wip != NULL) { + return wip; + } + // If no wininfo for curwin, use the first in the list (that doesn't have // 'diff' set and is in another tab page). // If "need_options" is true skip entries that don't have options set, // unless the window is editing "buf", so we can copy from the window // itself. - if (wip == NULL) { - if (skip_diff_buffer) { - for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { - if (!wininfo_other_tab_diff(wip) - && (!need_options - || wip->wi_optset - || (wip->wi_win != NULL - && wip->wi_win->w_buffer == buf))) { - break; - } + if (skip_diff_buffer) { + for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next) { + if (!wininfo_other_tab_diff(wip) + && (!need_options + || wip->wi_optset + || (wip->wi_win != NULL + && wip->wi_win->w_buffer == buf))) { + break; } - } else { - wip = buf->b_wininfo; } + } else { + wip = buf->b_wininfo; } return wip; } -- cgit From 6734dd250355f8621a710d59c2089b38a65dbf18 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sun, 20 Feb 2022 00:18:15 +0000 Subject: vim-patch:8.2.4463: completion only uses strict matching Problem: Completion only uses strict matching. Solution: Add the "fuzzy" item for 'wildoptions'. (Yegappan Lakshmanan, closes vim/vim#9803) https://github.com/vim/vim/commit/38b85cb4d7216705058708bacbc25ab90cd61595 Use MAX_FUZZY_MATCHES in fuzzy_match_str(). Omit fuzmatch_str_free() as it is only used on allocation failure. Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 135 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 46 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index cd1059eb0d..32e0cf5acf 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -88,6 +88,7 @@ #include "nvim/regexp.h" #include "nvim/runtime.h" #include "nvim/screen.h" +#include "nvim/search.h" #include "nvim/sign.h" #include "nvim/spell.h" #include "nvim/statusline.h" @@ -2337,7 +2338,6 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) int round; char *p; int attempt; - char *patc; bufmatch_T *matches = NULL; *num_file = 0; // return values in case of FAIL @@ -2347,31 +2347,40 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) return FAIL; } - // Make a copy of "pat" and change "^" to "\(^\|[\/]\)". - if (*pat == '^') { - patc = xmalloc(strlen(pat) + 11); - STRCPY(patc, "\\(^\\|[\\/]\\)"); - STRCPY(patc + 11, pat + 1); - } else { - patc = pat; + const bool fuzzy = cmdline_fuzzy_complete(pat); + + char *patc = NULL; + // Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular + // expression matching) + if (!fuzzy) { + if (*pat == '^') { + patc = xmalloc(strlen(pat) + 11); + STRCPY(patc, "\\(^\\|[\\/]\\)"); + STRCPY(patc + 11, pat + 1); + } else { + patc = pat; + } } + fuzmatch_str_T *fuzmatch = NULL; // attempt == 0: try match with '\<', match at start of word // attempt == 1: try match without '\<', match anywhere - for (attempt = 0; attempt <= 1; attempt++) { - if (attempt > 0 && patc == pat) { - break; // there was no anchor, no need to try again - } - + for (attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) { regmatch_T regmatch; - regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC); - if (regmatch.regprog == NULL) { - if (patc != pat) { - xfree(patc); + if (!fuzzy) { + if (attempt > 0 && patc == pat) { + break; // there was no anchor, no need to try again + } + regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC); + if (regmatch.regprog == NULL) { + if (patc != pat) { + xfree(patc); + } + return FAIL; } - return FAIL; } + int score = 0; // round == 1: Count the matches. // round == 2: Build the array to keep the matches. for (round = 1; round <= 2; round++) { @@ -2387,7 +2396,23 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) continue; } } - p = buflist_match(®match, buf, p_wic); + + if (!fuzzy) { + p = buflist_match(®match, buf, p_wic); + } else { + p = NULL; + // first try matching with the short file name + if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) { + p = buf->b_sfname; + } + if (p == NULL) { + // next try matching with the full path file name + if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) { + p = buf->b_ffname; + } + } + } + if (p != NULL) { if (round == 1) { count++; @@ -2397,12 +2422,20 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) } else { p = xstrdup(p); } - if (matches != NULL) { - matches[count].buf = buf; - matches[count].match = p; - count++; + + if (!fuzzy) { + if (matches != NULL) { + matches[count].buf = buf; + matches[count].match = p; + count++; + } else { + (*file)[count++] = p; + } } else { - (*file)[count++] = p; + fuzmatch[count].idx = count; + fuzmatch[count].str = p; + fuzmatch[count].score = score; + count++; } } } @@ -2411,40 +2444,50 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) break; } if (round == 1) { - *file = xmalloc((size_t)count * sizeof(**file)); - - if (options & WILD_BUFLASTUSED) { - matches = xmalloc((size_t)count * sizeof(*matches)); + if (!fuzzy) { + *file = xmalloc((size_t)count * sizeof(**file)); + if (options & WILD_BUFLASTUSED) { + matches = xmalloc((size_t)count * sizeof(*matches)); + } + } else { + fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T)); } } } - vim_regfree(regmatch.regprog); - if (count) { // match(es) found, break here - break; + + if (!fuzzy) { + vim_regfree(regmatch.regprog); + if (count) { // match(es) found, break here + break; + } } } - if (patc != pat) { + if (!fuzzy && patc != pat) { xfree(patc); } - if (matches != NULL) { - if (count > 1) { - qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare); - } - - // if the current buffer is first in the list, place it at the end - if (matches[0].buf == curbuf) { - for (int i = 1; i < count; i++) { - (*file)[i - 1] = matches[i].match; + if (!fuzzy) { + if (matches != NULL) { + if (count > 1) { + qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare); } - (*file)[count - 1] = matches[0].match; - } else { - for (int i = 0; i < count; i++) { - (*file)[i] = matches[i].match; + + // if the current buffer is first in the list, place it at the end + if (matches[0].buf == curbuf) { + for (int i = 1; i < count; i++) { + (*file)[i - 1] = matches[i].match; + } + (*file)[count - 1] = matches[0].match; + } else { + for (int i = 0; i < count; i++) { + (*file)[i] = matches[i].match; + } } + xfree(matches); } - xfree(matches); + } else { + fuzzymatches_to_strmatches(fuzmatch, file, count, false); } *num_file = count; -- cgit From ddd69a6c81c1a2595e81377503dd2b47f2c41b83 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 17 Jan 2023 17:02:25 +0800 Subject: vim-patch:8.2.4959: using NULL regexp program (#21855) Problem: Using NULL regexp program. Solution: Check for regexp program becoming NULL in more places. https://github.com/vim/vim/commit/b62dc5e7825bc195efe3041d5b3a9f1528359e1c Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 32e0cf5acf..9dd5fdaea5 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2255,12 +2255,13 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted, regmatch_T regmatch; regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0); - if (regmatch.regprog == NULL) { - xfree(pat); - return -1; - } FOR_ALL_BUFFERS_BACKWARDS(buf) { + if (regmatch.regprog == NULL) { + // invalid pattern, possibly after switching engine + xfree(pat); + return -1; + } if (buf->b_p_bl == find_listed && (!diffmode || diff_mode_buf(buf)) && buflist_match(®match, buf, false) != NULL) { @@ -2372,12 +2373,6 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) break; // there was no anchor, no need to try again } regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC); - if (regmatch.regprog == NULL) { - if (patc != pat) { - xfree(patc); - } - return FAIL; - } } int score = 0; @@ -2398,6 +2393,13 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) } if (!fuzzy) { + if (regmatch.regprog == NULL) { + // invalid pattern, possibly after recompiling + if (patc != pat) { + xfree(patc); + } + return FAIL; + } p = buflist_match(®match, buf, p_wic); } else { p = NULL; @@ -2495,6 +2497,7 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) } /// Check for a match on the file name for buffer "buf" with regprog "prog". +/// Note that rmp->regprog may become NULL when switching regexp engine. /// /// @param ignore_case When true, ignore case. Use 'fic' otherwise. static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case) @@ -2507,7 +2510,8 @@ static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case) return match; } -/// Try matching the regexp in "prog" with file name "name". +/// Try matching the regexp in "rmp->regprog" with file name "name". +/// Note that rmp->regprog may become NULL when switching regexp engine. /// /// @param ignore_case When true, ignore case. Use 'fileignorecase' otherwise. /// -- cgit From 132f001ce84d8d750ac5c492a23b7d499fb47c6a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 17 Jan 2023 19:52:02 +0800 Subject: vim-patch:8.2.4483: command completion makes two rounds to collect matches (#21857) Problem: Command completion makes two rounds to collect matches. Solution: Use a growarray to collect matches. (Yegappan Lakshmanan, closes vim/vim#9860) https://github.com/vim/vim/commit/5de4c4372d4366bc85cb66efb3e373439b9471c5 Co-authored-by: Yegappan Lakshmanan --- src/nvim/buffer.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 9dd5fdaea5..3f93d85624 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2415,31 +2415,34 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) } } - if (p != NULL) { - if (round == 1) { + if (p == NULL) { + continue; + } + + if (round == 1) { + count++; + continue; + } + + if (options & WILD_HOME_REPLACE) { + p = home_replace_save(buf, p); + } else { + p = xstrdup(p); + } + + if (!fuzzy) { + if (matches != NULL) { + matches[count].buf = buf; + matches[count].match = p; count++; } else { - if (options & WILD_HOME_REPLACE) { - p = home_replace_save(buf, p); - } else { - p = xstrdup(p); - } - - if (!fuzzy) { - if (matches != NULL) { - matches[count].buf = buf; - matches[count].match = p; - count++; - } else { - (*file)[count++] = p; - } - } else { - fuzmatch[count].idx = count; - fuzmatch[count].str = p; - fuzmatch[count].score = score; - count++; - } + (*file)[count++] = p; } + } else { + fuzmatch[count].idx = count; + fuzmatch[count].str = p; + fuzmatch[count].score = score; + count++; } } if (count == 0) { // no match found, break here -- cgit From 0344bfad0fc87d2e256ea2b80de7abd069ba1dd2 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 17 Jan 2023 14:17:40 +0100 Subject: refactor: replace char_u with char 22 (#21786) Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 3f93d85624..bc0bd9e004 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3829,7 +3829,7 @@ static int chk_modeline(linenr_T lnum, int flags) && (s[0] != 'V' || strncmp(skipwhite(e + 1), "set", 3) == 0) && (s[3] == ':' - || (VIM_VERSION_100 >= vers && isdigit(s[3])) + || (VIM_VERSION_100 >= vers && isdigit((uint8_t)s[3])) || (VIM_VERSION_100 < vers && s[3] == '<') || (VIM_VERSION_100 > vers && s[3] == '>') || (VIM_VERSION_100 == vers && s[3] == '='))) { -- cgit From 363d153bb94a965ff811d8c7514047264b37d61d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 19 Jan 2023 11:48:49 +0100 Subject: fix: pass value instead of pointer to isalpha (#21898) --- src/nvim/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index bc0bd9e004..5dcb10751f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3343,7 +3343,7 @@ void maketitle(void) (SPACE_FOR_DIR - (size_t)(buf_p - buf)), true); #ifdef BACKSLASH_IN_FILENAME // Avoid "c:/name" to be reduced to "c". - if (isalpha((uint8_t)buf_p) && *(buf_p + 1) == ':') { + if (isalpha((uint8_t)(*buf_p)) && *(buf_p + 1) == ':') { buf_p += 2; } #endif -- cgit From 0371d0f7afa5e01dd2ac8bbd3abcf0f7454872b3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 23 Jan 2023 18:55:11 +0800 Subject: refactor(win_close): remove "force", don't pass on "free_buf" (#21921) Problem: The "force" flag of win_close() complicates the code and adds edge cases where it is not clear what the correct behavior should be. The "free_buf" flag of win_close() is passed on to float windows when closing the last window of a tabpage, which doesn't make much sense. Solution: Remove the "force" flag and always close float windows as if :close! is used when closing the last window of a tabpage, and set the "free_buf" flag for a float window based on whether its buffer can be freed. As 'hidden' is on by default, this change shouldn't affect many people. --- src/nvim/buffer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5dcb10751f..332c6cadb8 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -933,7 +933,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) enter_cleanup(&cs); // Quitting means closing the split window, nothing else. - win_close(curwin, true, false); + win_close(curwin, true); swap_exists_action = SEA_NONE; swap_exists_did_quit = true; @@ -1335,7 +1335,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) while (buf == curbuf && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) && (is_aucmd_win(lastwin) || !last_window(curwin))) { - if (win_close(curwin, false, false) == FAIL) { + if (win_close(curwin, false) == FAIL) { break; } } @@ -3620,7 +3620,7 @@ void ex_buffer_all(exarg_T *eap) && !ONE_WINDOW && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { - win_close(wp, false, false); + win_close(wp, false); wpnext = firstwin; // just in case an autocommand does // something strange with windows tpnext = first_tabpage; // start all over... @@ -3700,7 +3700,7 @@ void ex_buffer_all(exarg_T *eap) enter_cleanup(&cs); // User selected Quit at ATTENTION prompt; close this window. - win_close(curwin, true, false); + win_close(curwin, true); open_wins--; swap_exists_action = SEA_NONE; swap_exists_did_quit = true; @@ -3740,7 +3740,7 @@ void ex_buffer_all(exarg_T *eap) // BufWrite Autocommands made the window invalid, start over wp = lastwin; } else if (r) { - win_close(wp, !buf_hide(wp->w_buffer), false); + win_close(wp, !buf_hide(wp->w_buffer)); open_wins--; wp = lastwin; } else { -- cgit From c6ab8dfc15e0f6f1a805ce2145e2b4f0072b33d1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 24 Jan 2023 18:31:07 +0800 Subject: revert: "refactor(win_close): remove "force", don't pass on "free_buf" (#21921)" (#21979) This reverts commit 0371d0f7afa5e01dd2ac8bbd3abcf0f7454872b3. > 'bufhidden' option exists. I don't think we should assume autoclosing windows are fine just because 'hidden' is set. --- src/nvim/buffer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/buffer.c') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 332c6cadb8..5dcb10751f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -933,7 +933,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count) enter_cleanup(&cs); // Quitting means closing the split window, nothing else. - win_close(curwin, true); + win_close(curwin, true, false); swap_exists_action = SEA_NONE; swap_exists_did_quit = true; @@ -1335,7 +1335,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) while (buf == curbuf && !(curwin->w_closing || curwin->w_buffer->b_locked > 0) && (is_aucmd_win(lastwin) || !last_window(curwin))) { - if (win_close(curwin, false) == FAIL) { + if (win_close(curwin, false, false) == FAIL) { break; } } @@ -3620,7 +3620,7 @@ void ex_buffer_all(exarg_T *eap) && !ONE_WINDOW && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { - win_close(wp, false); + win_close(wp, false, false); wpnext = firstwin; // just in case an autocommand does // something strange with windows tpnext = first_tabpage; // start all over... @@ -3700,7 +3700,7 @@ void ex_buffer_all(exarg_T *eap) enter_cleanup(&cs); // User selected Quit at ATTENTION prompt; close this window. - win_close(curwin, true); + win_close(curwin, true, false); open_wins--; swap_exists_action = SEA_NONE; swap_exists_did_quit = true; @@ -3740,7 +3740,7 @@ void ex_buffer_all(exarg_T *eap) // BufWrite Autocommands made the window invalid, start over wp = lastwin; } else if (r) { - win_close(wp, !buf_hide(wp->w_buffer)); + win_close(wp, !buf_hide(wp->w_buffer), false); open_wins--; wp = lastwin; } else { -- cgit