diff options
42 files changed, 405 insertions, 329 deletions
diff --git a/.github/scripts/remove-reviewers.js b/.github/scripts/remove-reviewers.js index 631f08e57d..40a8eca423 100644 --- a/.github/scripts/remove-reviewers.js +++ b/.github/scripts/remove-reviewers.js @@ -6,11 +6,13 @@ module.exports = async ({github, context}) => { }); const reviewers = requestedReviewers.data.users.map(e => e.login) + const team_reviewers = requestedReviewers.data.teams.map(e => e.name); github.rest.pulls.removeRequestedReviewers({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number, - reviewers: reviewers + reviewers: reviewers, + team_reviewers: team_reviewers }); } diff --git a/.github/scripts/reviews.js b/.github/scripts/reviews.js index a31c94eebd..ab81a61047 100644 --- a/.github/scripts/reviews.js +++ b/.github/scripts/reviews.js @@ -7,6 +7,7 @@ module.exports = async ({github, context}) => { const labels = pr_data.data.labels.map(e => e.name) const reviewers = new Set() + const team_reviewers = new Array() if (labels.includes('api')) { reviewers.add("bfredl") reviewers.add("muniter") @@ -18,9 +19,7 @@ module.exports = async ({github, context}) => { } if (labels.includes('ci')) { - reviewers.add("dundargoc") - reviewers.add("jamessan") - reviewers.add("justinmk") + team_reviewers.push('ci'); } if (labels.includes('column')) { @@ -58,8 +57,7 @@ module.exports = async ({github, context}) => { } if (labels.includes('lsp')) { - reviewers.add("glepnir") - reviewers.add("mfussenegger") + team_reviewers.push('lsp'); } if (labels.includes('project-management')) { @@ -76,9 +74,7 @@ module.exports = async ({github, context}) => { } if (labels.includes('treesitter')) { - reviewers.add("bfredl") - reviewers.add("clason") - reviewers.add("vigoux") + team_reviewers.push('treesitter'); } if (labels.includes('typo')) { @@ -102,6 +98,7 @@ module.exports = async ({github, context}) => { owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number, - reviewers: Array.from(reviewers) + reviewers: Array.from(reviewers), + team_reviewers: team_reviewers }); } diff --git a/.github/workflows/add-reviewers.yml b/.github/workflows/add-reviewers.yml index 6c8c7ff8ed..f1abab5c53 100644 --- a/.github/workflows/add-reviewers.yml +++ b/.github/workflows/add-reviewers.yml @@ -13,6 +13,7 @@ jobs: - name: 'Request reviewers' uses: actions/github-script@v6 with: + github-token: ${{ secrets.TEAM_REVIEW }} script: | const script = require('./.github/scripts/reviews.js') await script({github, context}) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 423760fc79..2af9bc49d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - if: success() || failure() && steps.abort_job.outputs.status == 'success' name: lintstylua - uses: JohnnyMorganz/stylua-action@v1 + uses: JohnnyMorganz/stylua-action@v2 with: token: ${{ secrets.GITHUB_TOKEN }} version: latest diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index f85f9d0cda..60689029a3 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -44,6 +44,7 @@ jobs: - name: 'Request reviewers' uses: actions/github-script@v6 with: + github-token: ${{ secrets.TEAM_REVIEW }} script: | const script = require('./.github/scripts/reviews.js') await script({github, context}) diff --git a/.github/workflows/remove-reviewers.yml b/.github/workflows/remove-reviewers.yml index f707f79737..7ab3ef568c 100644 --- a/.github/workflows/remove-reviewers.yml +++ b/.github/workflows/remove-reviewers.yml @@ -12,6 +12,7 @@ jobs: - name: 'Remove reviewers' uses: actions/github-script@v6 with: + github-token: ${{ secrets.TEAM_REVIEW }} script: | const script = require('./.github/scripts/remove-reviewers.js') await script({github, context}) diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 5c1725a1f8..229ed95826 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -78,7 +78,6 @@ centralized reference of the differences. - |g:vimsyn_embed| defaults to "l" to enable Lua highlighting - Default Mouse ~ *default-mouse* *disable-mouse* By default the mouse is enabled, and <RightMouse> opens a |popup-menu| with @@ -99,7 +98,10 @@ the following: \ autocmd CursorMoved * ++once set mouse&<Bar> \ echo 'mouse ON'<CR> < - +To remove the "How-to disable mouse" menu item and the separator above it: >vim + aunmenu PopUp.How-to\ disable\ mouse + aunmenu PopUp.-1- +< Default Mappings ~ *default-mappings* Nvim creates the following default mappings at |startup|. You can disable any diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index a5f20b61a6..ee538dc8c7 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1097,11 +1097,10 @@ function M.sc(bufnr) for _, line in ipairs(getlines(bufnr, 1, 25)) do if findany(line, { - '[A-Za-z0-9]*%s:%s[A-Za-z0-9]', 'var%s<', 'classvar%s<', '%^this.*', - '|%w*|', + '|%w+|', '%+%s%w*%s{', '%*ar%s', }) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 9129500866..5ffd11682c 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -395,15 +395,14 @@ end function vim.tbl_get(o, ...) local keys = { ... } if #keys == 0 then - return + return nil end for i, k in ipairs(keys) do - if type(o[k]) ~= 'table' and next(keys, i) then - return nil - end o = o[k] if o == nil then - return + return nil + elseif type(o) ~= 'table' and next(keys, i) then + return nil end end return o diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 5031aca378..582922ecb6 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -327,12 +327,8 @@ end ---@param lang (string|nil) Language of the parser (default: buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() - local parser = M.get_parser(bufnr, lang) - M.highlighter.new(parser) - - vim.b[bufnr].ts_highlight = true end --- Stops treesitter highlighting for a buffer @@ -344,8 +340,6 @@ function M.stop(bufnr) if M.highlighter.active[bufnr] then M.highlighter.active[bufnr]:destroy() end - - vim.bo[bufnr].syntax = 'on' end --- Open a window that displays a textual representation of the nodes in the language tree. diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index f5e5ca1988..e99994c8a9 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -88,7 +88,11 @@ function TSHighlighter.new(tree, opts) end end + self.orig_syntax = vim.bo[self.bufnr].syntax + self.orig_spelloptions = vim.bo[self.bufnr].spelloptions + vim.bo[self.bufnr].syntax = '' + vim.b[self.bufnr].ts_highlight = true TSHighlighter.active[self.bufnr] = self @@ -114,6 +118,11 @@ function TSHighlighter:destroy() if TSHighlighter.active[self.bufnr] then TSHighlighter.active[self.bufnr] = nil end + + if vim.api.nvim_buf_is_loaded(self.bufnr) then + vim.bo[self.bufnr].syntax = self.orig_syntax + vim.bo[self.bufnr].spelloptions = self.orig_spelloptions + end end ---@private diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index ac1927eeb1..abd265f2cf 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -660,6 +660,12 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods.lockmarks, false, "'mods.lockmarks'"); OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods.noswapfile, false, "'mods.noswapfile'"); + if (cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT) { + // CMOD_ERRSILENT must imply CMOD_SILENT, otherwise apply_cmdmod() and undo_cmdmod() won't + // work properly. + cmdinfo.cmdmod.cmod_flags |= CMOD_SILENT; + } + if ((cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX) && !(ea.argt & EX_SBOXOK)) { VALIDATION_ERROR("Command cannot be run in sandbox"); } 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, diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index 2c92fb26b2..c66571560a 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -147,6 +147,15 @@ void buf_updates_unregister(buf_T *buf, uint64_t channelid) } } +void buf_free_callbacks(buf_T *buf) +{ + kv_destroy(buf->update_channels); + for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) { + buffer_update_callbacks_free(kv_A(buf->update_callbacks, i)); + } + kv_destroy(buf->update_callbacks); +} + void buf_updates_unload(buf_T *buf, bool can_reload) { size_t size = kv_size(buf->update_channels); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a37613dca9..69b074ab99 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1297,7 +1297,7 @@ void free_all_functions(void) ufunc_T *fp; uint64_t skipped = 0; uint64_t todo = 1; - uint64_t used; + int changed; // Clean up the current_funccal chain and the funccal stack. while (current_funccal != NULL) { @@ -1321,9 +1321,9 @@ void free_all_functions(void) if (func_name_refcount((char_u *)fp->uf_name)) { skipped++; } else { - used = func_hashtab.ht_used; + changed = func_hashtab.ht_changed; func_clear(fp, true); - if (used != func_hashtab.ht_used) { + if (changed != func_hashtab.ht_changed) { skipped = 0; break; } @@ -1993,8 +1993,8 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) /// Otherwise functions matching "regmatch". static void list_functions(regmatch_T *regmatch) { - const size_t used = func_hashtab.ht_used; - size_t todo = used; + const int changed = func_hashtab.ht_changed; + size_t todo = func_hashtab.ht_used; const hashitem_T *const ht_array = func_hashtab.ht_array; for (const hashitem_T *hi = ht_array; todo > 0 && !got_int; hi++) { @@ -2008,7 +2008,7 @@ static void list_functions(regmatch_T *regmatch) : (!isdigit(*fp->uf_name) && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { list_func_head(fp, false, false); - if (used != func_hashtab.ht_used || ht_array != func_hashtab.ht_array) { + if (changed != func_hashtab.ht_changed) { emsg(_("E454: function list was modified")); return; } @@ -2730,15 +2730,17 @@ bool function_exists(const char *const name, bool no_deref) char *get_user_func_name(expand_T *xp, int idx) { static size_t done; + static int changed; static hashitem_T *hi; ufunc_T *fp; if (idx == 0) { done = 0; hi = func_hashtab.ht_array; + changed = func_hashtab.ht_changed; } assert(hi); - if (done < func_hashtab.ht_used) { + if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used) { if (done++ > 0) { hi++; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 78d0888e27..e6e6176669 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1502,7 +1502,7 @@ void print_line(linenr_T lnum, int use_number, int list) msg_start(); silent_mode = false; - info_message = true; // use mch_msg(), not mch_errmsg() + info_message = true; // use os_msg(), not os_errmsg() print_line_no_prefix(lnum, use_number, list); if (save_silent) { msg_putchar('\n'); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 88ae0a8226..3a28d557e3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4391,14 +4391,14 @@ static int check_more(int message, bool forceit) vim_snprintf((char *)buff, DIALOG_MSG_SIZE, NGETTEXT("%d more file to edit. Quit anyway?", - "%d more files to edit. Quit anyway?", (unsigned long)n), n); + "%d more files to edit. Quit anyway?", n), n); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) { return OK; } return FAIL; } semsg(NGETTEXT("E173: %" PRId64 " more file to edit", - "E173: %" PRId64 " more files to edit", (unsigned long)n), (int64_t)n); + "E173: %" PRId64 " more files to edit", n), (int64_t)n); quitmore = 2; // next try to quit is allowed } return FAIL; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index eaaed8b25c..fdf1973719 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2560,7 +2560,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. if (!newfile) { - acl = mch_get_acl((char_u *)fname); + acl = os_get_acl((char_u *)fname); } #endif @@ -2800,7 +2800,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en (double)file_info_old.stat.st_mtim.tv_sec); #endif #ifdef HAVE_ACL - mch_set_acl((char_u *)backup, acl); + os_set_acl((char_u *)backup, acl); #endif SET_ERRMSG(NULL); break; @@ -3336,7 +3336,7 @@ restore_backup: // Probably need to set the ACL before changing the user (can't set the // ACL on a file the user doesn't own). if (!backup_copy) { - mch_set_acl((char_u *)wfname, acl); + os_set_acl((char_u *)wfname, acl); } #endif @@ -3552,7 +3552,7 @@ nofail: } #endif #ifdef HAVE_ACL - mch_free_acl(acl); + os_free_acl(acl); #endif if (errmsg != NULL) { @@ -4591,12 +4591,12 @@ int vim_rename(const char *from, const char *to) perm = os_getperm(from); #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. - acl = mch_get_acl((char_u *)from); + acl = os_get_acl((char_u *)from); #endif fd_in = os_open((char *)from, O_RDONLY, 0); if (fd_in < 0) { #ifdef HAVE_ACL - mch_free_acl(acl); + os_free_acl(acl); #endif return -1; } @@ -4607,7 +4607,7 @@ int vim_rename(const char *from, const char *to) if (fd_out < 0) { close(fd_in); #ifdef HAVE_ACL - mch_free_acl(acl); + os_free_acl(acl); #endif return -1; } @@ -4619,7 +4619,7 @@ int vim_rename(const char *from, const char *to) close(fd_out); close(fd_in); #ifdef HAVE_ACL - mch_free_acl(acl); + os_free_acl(acl); #endif return -1; } @@ -4644,8 +4644,8 @@ int vim_rename(const char *from, const char *to) os_setperm((const char *)to, perm); #endif #ifdef HAVE_ACL - mch_set_acl((char_u *)to, acl); - mch_free_acl(acl); + os_set_acl((char_u *)to, acl); + os_free_acl(acl); #endif if (errmsg != NULL) { semsg(errmsg, to); diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 08b963ae89..275ddc6912 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1781,7 +1781,7 @@ char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo } } if (text == NULL) { - unsigned long count = (unsigned long)(lnume - lnum + 1); // NOLINT(bugprone-misplaced-widening-cast) + long count = lnume - lnum + 1; vim_snprintf(buf, FOLD_TEXT_LEN, NGETTEXT("+--%3ld line folded", @@ -3269,7 +3269,7 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } } - int count = foldend - foldstart + 1; + long count = foldend - foldstart + 1; char *txt = NGETTEXT("+-%s%3ld line: ", "+-%s%3ld lines: ", count); size_t len = strlen(txt) + strlen(dashes) // for %s diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 31dc6f5bd4..fdbfdd7d77 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -223,6 +223,7 @@ int hash_add(hashtab_T *ht, char *key) void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash) { ht->ht_used++; + ht->ht_changed++; if (hi->hi_key == NULL) { ht->ht_filled++; } @@ -242,6 +243,7 @@ void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash) void hash_remove(hashtab_T *ht, hashitem_T *hi) { ht->ht_used--; + ht->ht_changed++; hi->hi_key = HI_KEY_REMOVED; hash_may_resize(ht, 0); } @@ -384,6 +386,7 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems) ht->ht_array = newarray; ht->ht_mask = newmask; ht->ht_filled = ht->ht_used; + ht->ht_changed++; } #define HASH_CYCLE_BODY(hash, p) \ diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h index 28a3b69d44..0a50fb2ef8 100644 --- a/src/nvim/hashtab.h +++ b/src/nvim/hashtab.h @@ -61,14 +61,15 @@ typedef struct hashitem_S { /// /// The hashtable grows to accommodate more entries when needed. typedef struct hashtable_S { - hash_T ht_mask; /// mask used for hash value - /// (nr of items in array is "ht_mask" + 1) - size_t ht_used; /// number of items used - size_t ht_filled; /// number of items used or removed - int ht_locked; /// counter for hash_lock() - hashitem_T *ht_array; /// points to the array, allocated when it's - /// not "ht_smallarray" - hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array + hash_T ht_mask; ///< mask used for hash value + ///< (nr of items in array is "ht_mask" + 1) + size_t ht_used; ///< number of items used + size_t ht_filled; ///< number of items used or removed + int ht_changed; ///< incremented when adding or removing an item + int ht_locked; ///< counter for hash_lock() + hashitem_T *ht_array; ///< points to the array, allocated when it's + ///< not "ht_smallarray" + hashitem_T ht_smallarray[HT_INIT_SIZE]; ///< initial array } hashtab_T; /// Iterate over a hashtab diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 6531da6419..0db05d482b 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2755,6 +2755,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict) tv_dict_add_str(di, S_LEN("kind"), EMPTY_IF_NULL(match->cp_text[CPT_KIND])); tv_dict_add_str(di, S_LEN("info"), EMPTY_IF_NULL(match->cp_text[CPT_INFO])); if (match->cp_user_data.v_type == VAR_UNKNOWN) { + // Add an empty string for backwards compatibility tv_dict_add_str(di, S_LEN("user_data"), ""); } else { tv_dict_add_tv(di, S_LEN("user_data"), &match->cp_user_data); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1c8fe3e28e..590d6fa920 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -205,8 +205,8 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags if (status) { if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) { // consider out of memory errors unrecoverable, just like xmalloc() - mch_errmsg(e_outofmem); - mch_errmsg("\n"); + os_errmsg(e_outofmem); + os_errmsg("\n"); preserve_exit(); } const char *error = lua_tostring(lstate, -1); @@ -258,8 +258,8 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) { // Terminate this thread, as the main thread may be able to continue // execution. - mch_errmsg(e_outofmem); - mch_errmsg("\n"); + os_errmsg(e_outofmem); + os_errmsg("\n"); lua_close(lstate); #ifdef MSWIN ExitThread(0); @@ -598,8 +598,8 @@ static bool nlua_init_packages(lua_State *lstate) lua_getglobal(lstate, "require"); lua_pushstring(lstate, "vim._init_packages"); if (nlua_pcall(lstate, 1, 0)) { - mch_errmsg((char *)lua_tostring(lstate, -1)); - mch_errmsg("\n"); + os_errmsg((char *)lua_tostring(lstate, -1)); + os_errmsg("\n"); return false; } @@ -779,12 +779,12 @@ void nlua_init(void) lua_State *lstate = luaL_newstate(); if (lstate == NULL) { - mch_errmsg(_("E970: Failed to initialize lua interpreter\n")); + os_errmsg(_("E970: Failed to initialize lua interpreter\n")); os_exit(1); } luaL_openlibs(lstate); if (!nlua_state_init(lstate)) { - mch_errmsg(_("E970: Failed to initialize builtin lua modules\n")); + os_errmsg(_("E970: Failed to initialize builtin lua modules\n")); os_exit(1); } diff --git a/src/nvim/main.c b/src/nvim/main.c index 78b59887e7..29d50801bb 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -278,6 +278,8 @@ int main(int argc, char **argv) // argument list "global_alist". command_line_scan(¶ms); + open_script_files(¶ms); + nlua_init(); TIME_MSG("init lua interpreter"); @@ -769,15 +771,15 @@ void preserve_exit(void) really_exiting = true; // Ignore SIGHUP while we are already exiting. #9274 signal_reject_deadly(); - mch_errmsg(IObuff); - mch_errmsg("\n"); + os_errmsg(IObuff); + os_errmsg("\n"); ui_flush(); ml_close_notmod(); // close all not-modified buffers FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { - mch_errmsg("Vim: preserving files...\r\n"); + os_errmsg("Vim: preserving files...\r\n"); ui_flush(); ml_sync_all(false, false, true); // preserve all swap files break; @@ -786,7 +788,7 @@ void preserve_exit(void) ml_close_all(false); // close all memfiles, without deleting - mch_errmsg("Vim: Finished.\r\n"); + os_errmsg("Vim: Finished.\r\n"); getout(1); } @@ -868,15 +870,15 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, Object o = nlua_exec(s, a, &err); api_free_array(a); if (ERROR_SET(&err)) { - mch_errmsg(err.msg); - mch_errmsg("\n"); + os_errmsg(err.msg); + os_errmsg("\n"); os_exit(2); } if (o.type == kObjectTypeDictionary) { rvobj.data.dictionary = o.data.dictionary; } else { - mch_errmsg("vim._cs_remote returned unexpected value\n"); + os_errmsg("vim._cs_remote returned unexpected value\n"); os_exit(2); } @@ -886,28 +888,28 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, for (size_t i = 0; i < rvobj.data.dictionary.size; i++) { if (strcmp(rvobj.data.dictionary.items[i].key.data, "errmsg") == 0) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) { - mch_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n"); + os_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n"); os_exit(2); } - mch_errmsg(rvobj.data.dictionary.items[i].value.data.string.data); - mch_errmsg("\n"); + os_errmsg(rvobj.data.dictionary.items[i].value.data.string.data); + os_errmsg("\n"); os_exit(2); } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "tabbed") == 0) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) { - mch_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n"); + os_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n"); os_exit(2); } tabbed = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse; } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "should_exit") == 0) { if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) { - mch_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n"); + os_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n"); os_exit(2); } should_exit = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse; } } if (should_exit == kNone || tabbed == kNone) { - mch_errmsg("vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n"); + os_errmsg("vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n"); os_exit(2); } api_free_object(o); @@ -929,7 +931,7 @@ static bool edit_stdin(bool explicit, mparm_T *parmp) && !embedded_mode && (!exmode_active || parmp->input_neverscript) && !parmp->input_isatty - && scriptin[0] == NULL; // `-s -` was not given. + && parmp->scriptin == NULL; // `-s -` was not given. return explicit || implicit; } @@ -1277,37 +1279,17 @@ static void command_line_scan(mparm_T *parmp) set_option_value_give_err("shadafile", 0L, argv[0], 0); break; - case 's': { // "-s {scriptin}" read from script file - if (scriptin[0] != NULL) { + case 's': // "-s {scriptin}" read from script file + if (parmp->scriptin != NULL) { scripterror: vim_snprintf((char *)IObuff, IOSIZE, _("Attempt to open script file again: \"%s %s\"\n"), argv[-1], argv[0]); - mch_errmsg(IObuff); - os_exit(2); - } - int error; - if (strequal(argv[0], "-")) { - const int stdin_dup_fd = os_dup(STDIN_FILENO); -#ifdef MSWIN - // Replace the original stdin with the console input handle. - os_replace_stdin_to_conin(); -#endif - FileDescriptor *const stdin_dup = file_open_fd_new(&error, stdin_dup_fd, - kFileReadOnly|kFileNonBlocking); - assert(stdin_dup != NULL); - scriptin[0] = stdin_dup; - } else if ((scriptin[0] = file_open_new(&error, argv[0], - kFileReadOnly|kFileNonBlocking, 0)) == NULL) { - vim_snprintf((char *)IObuff, IOSIZE, - _("Cannot open for reading: \"%s\": %s\n"), - argv[0], os_strerror(error)); - mch_errmsg(IObuff); + os_errmsg(IObuff); os_exit(2); } - save_typebuf(); + parmp->scriptin = argv[0]; break; - } case 't': // "-t {tag}" parmp->tagname = argv[0]; @@ -1329,17 +1311,11 @@ scripterror: } FALLTHROUGH; case 'W': // "-W {scriptout}" overwrite script file - if (scriptout != NULL) { + if (parmp->scriptout != NULL) { goto scripterror; } - if ((scriptout = os_fopen(argv[0], c == 'w' ? APPENDBIN : WRITEBIN)) - == NULL) { - mch_errmsg(_("Cannot open for script output: \"")); - mch_errmsg(argv[0]); - mch_errmsg("\"\n"); - os_exit(2); - } - break; + parmp->scriptout = argv[0]; + parmp->scriptout_append = (c == 'w'); } } } else { // File name argument. @@ -1548,6 +1524,45 @@ static void read_stdin(void) check_swap_exists_action(); } +static void open_script_files(mparm_T *parmp) +{ + if (parmp->scriptin) { + int error; + if (strequal(parmp->scriptin, "-")) { + const int stdin_dup_fd = os_dup(STDIN_FILENO); +#ifdef MSWIN + // Replace the original stdin with the console input handle. + os_replace_stdin_to_conin(); +#endif + FileDescriptor *const stdin_dup = file_open_fd_new(&error, stdin_dup_fd, + kFileReadOnly|kFileNonBlocking); + assert(stdin_dup != NULL); + scriptin[0] = stdin_dup; + } else { + scriptin[0] = file_open_new(&error, parmp->scriptin, + kFileReadOnly|kFileNonBlocking, 0); + if (scriptin[0] == NULL) { + vim_snprintf((char *)IObuff, IOSIZE, + _("Cannot open for reading: \"%s\": %s\n"), + parmp->scriptin, os_strerror(error)); + os_errmsg(IObuff); + os_exit(2); + } + } + save_typebuf(); + } + + if (parmp->scriptout) { + scriptout = os_fopen(parmp->scriptout, parmp->scriptout_append ? APPENDBIN : WRITEBIN); + if (scriptout == NULL) { + os_errmsg(_("Cannot open for script output: \"")); + os_errmsg(parmp->scriptout); + os_errmsg("\"\n"); + os_exit(2); + } + } +} + // Create the requested number of windows and edit buffers in them. // Also does recovery if "recoverymode" set. static void create_windows(mparm_T *parmp) @@ -2048,17 +2063,17 @@ static void mainerr(const char *errstr, const char *str) signal_stop(); // kill us with CTRL-C here, if you like - mch_errmsg(prgname); - mch_errmsg(": "); - mch_errmsg(_(errstr)); + os_errmsg(prgname); + os_errmsg(": "); + os_errmsg(_(errstr)); if (str != NULL) { - mch_errmsg(": \""); - mch_errmsg((char *)str); - mch_errmsg("\""); + os_errmsg(": \""); + os_errmsg((char *)str); + os_errmsg("\""); } - mch_errmsg(_("\nMore info with \"")); - mch_errmsg(prgname); - mch_errmsg(" -h\"\n"); + os_errmsg(_("\nMore info with \"")); + os_errmsg(prgname); + os_errmsg(" -h\"\n"); os_exit(1); } @@ -2068,7 +2083,7 @@ static void version(void) { // TODO(bfred): not like this? nlua_init(); - info_message = true; // use mch_msg(), not mch_errmsg() + info_message = true; // use os_msg(), not os_errmsg() list_version(); msg_putchar('\n'); msg_didout = false; @@ -2079,47 +2094,47 @@ static void usage(void) { signal_stop(); // kill us with CTRL-C here, if you like - mch_msg(_("Usage:\n")); - mch_msg(_(" nvim [options] [file ...] Edit file(s)\n")); - mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n")); - mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n")); - mch_msg(_("\nOptions:\n")); - mch_msg(_(" -- Only file names after this\n")); - mch_msg(_(" + Start at end of file\n")); - mch_msg(_(" --cmd <cmd> Execute <cmd> before any config\n")); - mch_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n")); - mch_msg("\n"); - mch_msg(_(" -b Binary mode\n")); - mch_msg(_(" -d Diff mode\n")); - mch_msg(_(" -e, -E Ex mode\n")); - mch_msg(_(" -es, -Es Silent (batch) mode\n")); - mch_msg(_(" -h, --help Print this help message\n")); - mch_msg(_(" -i <shada> Use this shada file\n")); - mch_msg(_(" -m Modifications (writing files) not allowed\n")); - mch_msg(_(" -M Modifications in text not allowed\n")); - mch_msg(_(" -n No swap file, use memory only\n")); - mch_msg(_(" -o[N] Open N windows (default: one per file)\n")); - mch_msg(_(" -O[N] Open N vertical windows (default: one per file)\n")); - mch_msg(_(" -p[N] Open N tab pages (default: one per file)\n")); - mch_msg(_(" -r, -L List swap files\n")); - mch_msg(_(" -r <file> Recover edit state for this file\n")); - mch_msg(_(" -R Read-only mode\n")); - mch_msg(_(" -S <session> Source <session> after loading the first file\n")); - mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); - mch_msg(_(" -u <config> Use this config file\n")); - mch_msg(_(" -v, --version Print version information\n")); - mch_msg(_(" -V[N][file] Verbose [level][file]\n")); - mch_msg("\n"); - mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); - mch_msg(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n")); - mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); - mch_msg(_(" --headless Don't start a user interface\n")); - mch_msg(_(" --listen <address> Serve RPC API from this address\n")); - mch_msg(_(" --noplugin Don't load plugins\n")); - mch_msg(_(" --remote[-subcommand] Execute commands remotely on a server\n")); - mch_msg(_(" --server <address> Specify RPC server to send commands to\n")); - mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); - mch_msg(_("\nSee \":help startup-options\" for all options.\n")); + os_msg(_("Usage:\n")); + os_msg(_(" nvim [options] [file ...] Edit file(s)\n")); + os_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n")); + os_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n")); + os_msg(_("\nOptions:\n")); + os_msg(_(" -- Only file names after this\n")); + os_msg(_(" + Start at end of file\n")); + os_msg(_(" --cmd <cmd> Execute <cmd> before any config\n")); + os_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n")); + os_msg("\n"); + os_msg(_(" -b Binary mode\n")); + os_msg(_(" -d Diff mode\n")); + os_msg(_(" -e, -E Ex mode\n")); + os_msg(_(" -es, -Es Silent (batch) mode\n")); + os_msg(_(" -h, --help Print this help message\n")); + os_msg(_(" -i <shada> Use this shada file\n")); + os_msg(_(" -m Modifications (writing files) not allowed\n")); + os_msg(_(" -M Modifications in text not allowed\n")); + os_msg(_(" -n No swap file, use memory only\n")); + os_msg(_(" -o[N] Open N windows (default: one per file)\n")); + os_msg(_(" -O[N] Open N vertical windows (default: one per file)\n")); + os_msg(_(" -p[N] Open N tab pages (default: one per file)\n")); + os_msg(_(" -r, -L List swap files\n")); + os_msg(_(" -r <file> Recover edit state for this file\n")); + os_msg(_(" -R Read-only mode\n")); + os_msg(_(" -S <session> Source <session> after loading the first file\n")); + os_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n")); + os_msg(_(" -u <config> Use this config file\n")); + os_msg(_(" -v, --version Print version information\n")); + os_msg(_(" -V[N][file] Verbose [level][file]\n")); + os_msg("\n"); + os_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); + os_msg(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n")); + os_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); + os_msg(_(" --headless Don't start a user interface\n")); + os_msg(_(" --listen <address> Serve RPC API from this address\n")); + os_msg(_(" --noplugin Don't load plugins\n")); + os_msg(_(" --remote[-subcommand] Execute commands remotely on a server\n")); + os_msg(_(" --server <address> Specify RPC server to send commands to\n")); + os_msg(_(" --startuptime <file> Write startup timing messages to <file>\n")); + os_msg(_("\nSee \":help startup-options\" for all options.\n")); } // Check the result of the ATTENTION dialog: diff --git a/src/nvim/main.h b/src/nvim/main.h index 780022a9b1..4cf8dfe026 100644 --- a/src/nvim/main.h +++ b/src/nvim/main.h @@ -42,6 +42,9 @@ typedef struct { char *listen_addr; // --listen {address} int remote; // --remote-[subcmd] {file1} {file2} char *server_addr; // --server {address} + char *scriptin; // -s {filename} + char *scriptout; // -w/-W {filename} + bool scriptout_append; // append (-w) instead of overwrite (-W) } mparm_T; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/mark.c b/src/nvim/mark.c index ad325ae057..c38aa834bf 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -551,6 +551,7 @@ MarkMoveRes mark_move_to(fmark_T *fm, MarkMove flags) // Need to change buffer fm_copy = *fm; // Copy, autocommand may change it fm = &fm_copy; + // Jump to the file with the mark res |= switch_to_mark_buf(fm, !(flags & kMarkJumpList)); // Failed switching buffer if (res & kMarkMoveFailed) { @@ -568,6 +569,7 @@ MarkMoveRes mark_move_to(fmark_T *fm, MarkMove flags) // Move the cursor while keeping track of what changed for the caller pos_T prev_pos = curwin->w_cursor; pos_T pos = fm->mark; + // Set lnum again, autocommands my have changed it curwin->w_cursor = fm->mark; if (flags & kMarkBeginLine) { beginline(BL_WHITE | BL_FIX); diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 8bc871344c..a65f45c012 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -14,6 +14,7 @@ #include "nvim/api/extmark.h" #include "nvim/arglist.h" #include "nvim/ascii.h" +#include "nvim/buffer_updates.h" #include "nvim/context.h" #include "nvim/decoration_provider.h" #include "nvim/eval.h" @@ -121,8 +122,8 @@ void *xmalloc(size_t size) { void *ret = try_malloc(size); if (!ret) { - mch_errmsg(e_outofmem); - mch_errmsg("\n"); + os_errmsg(e_outofmem); + os_errmsg("\n"); preserve_exit(); } return ret; @@ -152,8 +153,8 @@ void *xcalloc(size_t count, size_t size) try_to_free_memory(); ret = calloc(allocated_count, allocated_size); if (!ret) { - mch_errmsg(e_outofmem); - mch_errmsg("\n"); + os_errmsg(e_outofmem); + os_errmsg("\n"); preserve_exit(); } } @@ -174,8 +175,8 @@ void *xrealloc(void *ptr, size_t size) try_to_free_memory(); ret = realloc(ptr, allocated_size); if (!ret) { - mch_errmsg(e_outofmem); - mch_errmsg("\n"); + os_errmsg(e_outofmem); + os_errmsg("\n"); preserve_exit(); } } @@ -194,7 +195,7 @@ void *xmallocz(size_t size) { size_t total_size = size + 1; if (total_size < size) { - mch_errmsg(_("Vim: Data too large to fit into virtual memory space\n")); + os_errmsg(_("Vim: Data too large to fit into virtual memory space\n")); preserve_exit(); } @@ -812,6 +813,11 @@ void free_all_mem(void) bufref_T bufref; set_bufref(&bufref, buf); nextbuf = buf->b_next; + + // Since options (in addition to other stuff) have been freed above we need to ensure no + // callbacks are called, so free them before closing the buffer. + buf_free_callbacks(buf); + close_buffer(NULL, buf, DOBUF_WIPE, false, false); // Didn't work, try next one. buf = bufref_valid(&bufref) ? nextbuf : firstbuf; diff --git a/src/nvim/message.c b/src/nvim/message.c index 81adca8b1c..041e5ed6c3 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -214,7 +214,7 @@ void msg_grid_validate(void) } /// Displays the string 's' on the status line -/// When terminal not initialized (yet) mch_errmsg(..) is used. +/// When terminal not initialized (yet) os_errmsg(..) is used. /// /// @return true if wait_return() not called int msg(char *s) @@ -764,7 +764,7 @@ static bool emsg_multiline(const char *s, bool multiline) /// emsg() - display an error message /// /// Rings the bell, if appropriate, and calls message() to do the real work -/// When terminal not initialized (yet) mch_errmsg(..) is used. +/// When terminal not initialized (yet) os_errmsg(..) is used. /// /// @return true if wait_return() not called bool emsg(const char *s) @@ -2726,9 +2726,9 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen) memcpy(p, s, (size_t)len); *(p + len) = '\0'; if (info_message) { - mch_msg(buf); + os_msg(buf); } else { - mch_errmsg(buf); + os_errmsg(buf); } } @@ -3003,7 +3003,7 @@ static int do_more_prompt(int typed_char) } #if defined(MSWIN) -void mch_errmsg(char *str) +void os_errmsg(char *str) { assert(str != NULL); wchar_t *utf16str; @@ -3017,7 +3017,7 @@ void mch_errmsg(char *str) } /// Give a message. To be used when the UI is not initialized yet. -void mch_msg(char *str) +void os_msg(char *str) { assert(str != NULL); wchar_t *utf16str; diff --git a/src/nvim/option.c b/src/nvim/option.c index b1feac7d1b..6cc919a1c6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -560,9 +560,7 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags) /// Used for 'lines' and 'columns'. void set_number_default(char *name, long val) { - int opt_idx; - - opt_idx = findoption(name); + int opt_idx = findoption(name); if (opt_idx >= 0) { options[opt_idx].def_val = (char *)(intptr_t)val; } @@ -726,12 +724,10 @@ void set_helplang_default(const char *lang) /// machine. void set_title_defaults(void) { - int idx1; - // If GUI is (going to be) used, we can always set the window title and // icon name. Saves a bit of time, because the X11 display server does // not need to be contacted. - idx1 = findoption("title"); + int idx1 = findoption("title"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { options[idx1].def_val = 0; p_title = 0; @@ -770,7 +766,6 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, char *save_arg = NULL; char *s = NULL; char_u *oldval = NULL; // previous value if *varp - char *newval; char *origval = NULL; char_u *origval_l = NULL; char_u *origval_g = NULL; @@ -778,8 +773,6 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, char *saved_origval_l = NULL; char *saved_origval_g = NULL; char *saved_newval = NULL; - unsigned newlen; - int comma; char whichwrap[80]; // When using ":set opt=val" for a global option @@ -812,6 +805,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, origval = (char *)oldval; } + char *newval; if (nextchar == '&') { // set to default val newval = options[opt_idx].def_val; // expand environment variables and ~ since the default value was @@ -903,9 +897,9 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, // backslashes. // get a bit too much - newlen = (unsigned)strlen(arg) + 1; + size_t newlen = strlen(arg) + 1; if (op != OP_NONE) { - newlen += (unsigned)strlen(origval) + 1; + newlen += strlen(origval) + 1; } newval = xmalloc(newlen); s = newval; @@ -975,7 +969,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, // concatenate the two strings; add a ',' if needed if (op == OP_ADDING || op == OP_PREPENDING) { - comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL); + int comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL); if (op == OP_ADDING) { len = (int)strlen(origval); // Strip a trailing comma, would get 2. @@ -1118,21 +1112,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, /// @return FAIL if an error is detected, OK otherwise int do_set(char *arg, int opt_flags) { - int opt_idx; - char *errmsg; - char errbuf[80]; - char *startarg; - int prefix; // 1: nothing, 0: "no", 2: "inv" in front of name - char_u nextchar; // next non-white char after option name - int afterchar; // character just after option name - int len; - int i; - varnumber_T value; - int key; - uint32_t flags; // flags for current option - char *varp = NULL; // pointer to variable for current option int did_show = false; // already showed one value - set_op_T op = 0; if (*arg == NUL) { showoptions(0, opt_flags); @@ -1140,9 +1120,11 @@ int do_set(char *arg, int opt_flags) goto theend; } + char errbuf[80]; + while (*arg != NUL) { // loop to process all options - errmsg = NULL; - startarg = arg; // remember for error message + char *errmsg = NULL; + char *startarg = arg; // remember for error message if (strncmp(arg, "all", 3) == 0 && !isalpha(arg[3]) && !(opt_flags & OPT_MODELINE)) { @@ -1162,7 +1144,7 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { - prefix = 1; + int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name if (strncmp(arg, "no", 2) == 0) { prefix = 0; arg += 2; @@ -1172,7 +1154,9 @@ int do_set(char *arg, int opt_flags) } // find end of name - key = 0; + int key = 0; + int len; + int opt_idx; if (*arg == '<') { opt_idx = -1; // look out for <t_>;> @@ -1212,14 +1196,14 @@ int do_set(char *arg, int opt_flags) } // remember character after option name - afterchar = (uint8_t)arg[len]; + int afterchar = (uint8_t)arg[len]; // skip white space, allow ":set ai ?" while (ascii_iswhite(arg[len])) { len++; } - op = OP_NONE; + set_op_T op = OP_NONE; if (arg[len] != NUL && arg[len + 1] == '=') { if (arg[len] == '+') { op = OP_ADDING; // "+=" @@ -1232,13 +1216,16 @@ int do_set(char *arg, int opt_flags) len++; } } - nextchar = (uint8_t)arg[len]; + char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name if (opt_idx == -1 && key == 0) { // found a mismatch: skip errmsg = e_unknown_option; goto skip; } + uint32_t flags; // flags for current option + char *varp = NULL; // pointer to variable for current option + if (opt_idx >= 0) { if (options[opt_idx].var == NULL) { // hidden option: skip // Only give an error message when requesting the value of @@ -1352,6 +1339,7 @@ int do_set(char *arg, int opt_flags) } } else { int value_checked = false; + varnumber_T value; if (flags & P_BOOL) { // boolean if (nextchar == '=' || nextchar == ':') { @@ -1428,6 +1416,7 @@ int do_set(char *arg, int opt_flags) goto skip; } } else if (*arg == '-' || ascii_isdigit(*arg)) { + int i; // Allow negative, octal and hex numbers. vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { @@ -1476,7 +1465,7 @@ skip: // - skip until a blank found, taking care of backslashes // - skip blanks // - skip one "=val" argument (for hidden options ":set gfn =xx") - for (i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { while (*arg != NUL && !ascii_iswhite(*arg)) { if (*arg++ == '\\' && *arg != NUL) { arg++; @@ -1491,7 +1480,7 @@ skip: if (errmsg != NULL) { STRLCPY(IObuff, _(errmsg), IOSIZE); - i = (int)strlen(IObuff) + 2; + int i = (int)strlen(IObuff) + 2; if (i + (arg - startarg) < IOSIZE) { // append the argument with the error STRCAT(IObuff, ": "); @@ -1516,11 +1505,11 @@ theend: if (silent_mode && did_show) { // After displaying option values in silent mode. silent_mode = false; - info_message = true; // use mch_msg(), not mch_errmsg() + info_message = true; // use os_msg(), not os_errmsg() msg_putchar('\n'); ui_flush(); silent_mode = true; - info_message = false; // use mch_msg(), not mch_errmsg() + info_message = false; // use os_msg(), not os_errmsg() } return OK; @@ -1632,9 +1621,7 @@ void set_options_bin(int oldval, int newval, int opt_flags) /// number, return -1. int get_shada_parameter(int type) { - char_u *p; - - p = find_shada_parameter(type); + char_u *p = find_shada_parameter(type); if (p != NULL && ascii_isdigit(*p)) { return atoi((char *)p); } @@ -2661,14 +2648,13 @@ void check_redraw(uint32_t flags) int findoption_len(const char *const arg, const size_t len) { const char *s; - const char *p; static int quick_tab[27] = { 0, 0 }; // quick access table // For first call: Initialize the quick-access table. // It contains the index for the first option that starts with a certain // letter. There are 26 letters, plus the first "t_" option. if (quick_tab[1] == 0) { - p = options[0].fullname; + const char *p = options[0].fullname; for (uint16_t i = 1; (s = options[i].fullname) != NULL; i++) { if (s[0] != p[0]) { if (s[0] == 't' && s[1] == '_') { @@ -3033,10 +3019,7 @@ char *set_option_value(const char *const name, const long number, const char *co return NULL; // Fail silently; many old vimrcs set t_xx options. } - int opt_idx; - char_u *varp; - - opt_idx = findoption(name); + int opt_idx = findoption(name); if (opt_idx < 0) { semsg(_("E355: Unknown option: %s"), name); } else { @@ -3054,7 +3037,7 @@ char *set_option_value(const char *const name, const long number, const char *co return set_string_option(opt_idx, s, opt_flags); } - varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags); + char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags); if (varp != NULL) { // hidden option is not changed if (number == 0 && string != NULL) { int idx; @@ -3125,7 +3108,6 @@ bool is_string_option(const char *name) int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) { int key = 0; - int modifiers; const char_u *arg = arg_arg; // Don't use get_special_key_code() for t_xx, we don't want it to call @@ -3134,7 +3116,7 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) key = TERMCAP2KEY(arg[2], arg[3]); } else if (has_lt) { arg--; // put arg at the '<' - modifiers = 0; + int modifiers = 0; key = find_special_key(&arg, len + 1, &modifiers, FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL); if (modifiers) { // can't handle modifiers here @@ -3155,16 +3137,6 @@ static int find_key_option(const char *arg, bool has_lt) /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL static void showoptions(int all, int opt_flags) { - vimoption_T *p; - int col; - char_u *varp; - int item_count; - int run; - int row, rows; - int cols; - int i; - int len; - #define INC 20 #define GAP 3 @@ -3183,16 +3155,16 @@ static void showoptions(int all, int opt_flags) // 1. display the short items // 2. display the long items (only strings and numbers) // When "opt_flags" has OPT_ONECOLUMN do everything in run 2. - for (run = 1; run <= 2 && !got_int; run++) { + for (int run = 1; run <= 2 && !got_int; run++) { // collect the items in items[] - item_count = 0; - for (p = &options[0]; p->fullname != NULL; p++) { + int item_count = 0; + for (vimoption_T *p = &options[0]; p->fullname != NULL; p++) { // apply :filter /pat/ if (message_filtered(p->fullname)) { continue; } - varp = NULL; + char_u *varp = NULL; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0) { if (p->indir != PV_NONE) { varp = (char_u *)get_varp_scope(p, opt_flags); @@ -3202,6 +3174,7 @@ static void showoptions(int all, int opt_flags) } if (varp != NULL && (all == 1 || (all == 0 && !optval_default(p, varp)))) { + int len; if (opt_flags & OPT_ONECOLUMN) { len = Columns; } else if (p->flags & P_BOOL) { @@ -3217,13 +3190,15 @@ static void showoptions(int all, int opt_flags) } } + int rows; + // display the items if (run == 1) { assert(Columns <= INT_MAX - GAP && Columns + GAP >= INT_MIN + 3 && (Columns + GAP - 3) / INC >= INT_MIN && (Columns + GAP - 3) / INC <= INT_MAX); - cols = (Columns + GAP - 3) / INC; + int cols = (Columns + GAP - 3) / INC; if (cols == 0) { cols = 1; } @@ -3231,13 +3206,13 @@ static void showoptions(int all, int opt_flags) } else { // run == 2 rows = item_count; } - for (row = 0; row < rows && !got_int; row++) { + for (int row = 0; row < rows && !got_int; row++) { msg_putchar('\n'); // go to next line if (got_int) { // 'q' typed in more break; } - col = 0; - for (i = row; i < item_count; i += rows) { + int col = 0; + for (int i = row; i < item_count; i += rows) { msg_col = col; // make columns showoneopt(items[i], opt_flags); col += INC; @@ -3299,7 +3274,7 @@ static void showoneopt(vimoption_T *p, int opt_flags) int save_silent = silent_mode; silent_mode = false; - info_message = true; // use mch_msg(), not mch_errmsg() + info_message = true; // use os_msg(), not os_errmsg() char_u *varp = (char_u *)get_varp_scope(p, opt_flags); @@ -3346,14 +3321,6 @@ static void showoneopt(vimoption_T *p, int opt_flags) /// Return FAIL on error, OK otherwise. int makeset(FILE *fd, int opt_flags, int local_only) { - vimoption_T *p; - char *varp; // currently used value - char_u *varp_fresh; // local value - char_u *varp_local = NULL; // fresh value - char *cmd; - int round; - int pri; - // Some options are never written: // - Options that don't have a default (terminal name, columns, lines). // - Terminal options. @@ -3361,8 +3328,8 @@ int makeset(FILE *fd, int opt_flags, int local_only) // // Do the loop over "options[]" twice: once for options with the // P_PRI_MKRC flag and once without. - for (pri = 1; pri >= 0; pri--) { - for (p = &options[0]; p->fullname; p++) { + for (int pri = 1; pri >= 0; pri--) { + for (vimoption_T *p = &options[0]; p->fullname; p++) { if (!(p->flags & P_NO_MKRC) && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) { // skip global option when only doing locals @@ -3376,7 +3343,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) continue; } - varp = get_varp_scope(p, opt_flags); + char *varp = get_varp_scope(p, opt_flags); // currently used value // Hidden options are never written. if (!varp) { continue; @@ -3391,7 +3358,8 @@ int makeset(FILE *fd, int opt_flags, int local_only) continue; } - round = 2; + int round = 2; + char_u *varp_local = NULL; // fresh value if (p->indir != PV_NONE) { if (p->var == VAR_WIN) { // skip window-local option when only doing globals @@ -3401,7 +3369,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) // When fresh value of window-local option is not at the // default, need to write it too. if (!(opt_flags & OPT_GLOBAL) && !local_only) { - varp_fresh = (char_u *)get_varp_scope(p, OPT_GLOBAL); + char_u *varp_fresh = (char_u *)get_varp_scope(p, OPT_GLOBAL); // local value if (!optval_default(p, varp_fresh)) { round = 1; varp_local = (char_u *)varp; @@ -3414,6 +3382,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) // Round 1: fresh value for window-local options. // Round 2: other values for (; round <= 2; varp = (char *)varp_local, round++) { + char *cmd; if (round == 1 || (opt_flags & OPT_GLOBAL)) { cmd = "set"; } else { @@ -3477,10 +3446,8 @@ int makefoldset(FILE *fd) static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags) { - char_u *s; char_u *buf = NULL; char_u *part = NULL; - char *p; if (fprintf(fd, "%s %s=", cmd, name) < 0) { return FAIL; @@ -3490,7 +3457,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ // options some characters have to be escaped with // CTRL-V or backslash if (valuep == &p_pt) { - s = (char_u *)(*valuep); + char_u *s = (char_u *)(*valuep); while (*s != NUL) { if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, false), 2) == FAIL) { return FAIL; @@ -3514,7 +3481,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ if (put_eol(fd) == FAIL) { goto fail; } - p = (char *)buf; + char *p = (char *)buf; while (*p != NUL) { // for each comma separated option part, append value to // the option, :set rtp+=value @@ -4266,7 +4233,6 @@ void buf_copy_options(buf_T *buf, int flags) { int should_copy = true; char_u *save_p_isk = NULL; // init for GCC - int dont_do_help; int did_isk = false; // Skip this when the option defaults have not been set yet. Happens when @@ -4297,7 +4263,7 @@ void buf_copy_options(buf_T *buf, int flags) // Don't copy the options specific to a help buffer when // BCO_NOHELP is given or the options were initialized already // (jumping back to a help file with CTRL-T or CTRL-O) - dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized; + bool dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized; if (dont_do_help) { // don't free b_p_isk save_p_isk = (char_u *)buf->b_p_isk; buf->b_p_isk = NULL; @@ -4567,13 +4533,10 @@ static int expand_option_flags = 0; /// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) { - char nextchar; uint32_t flags = 0; // init for GCC int opt_idx = 0; // init for GCC char *p; - char *s; int is_term_option = false; - int key; expand_option_flags = opt_flags; @@ -4588,7 +4551,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) return; } while (p > arg) { - s = p; + char *s = p; // count number of backslashes before ' ' or ',' if (*p == ' ' || *p == ',') { while (s > arg && *(s - 1) == '\\') { @@ -4612,13 +4575,16 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) } xp->xp_pattern = p; arg = p; + + char nextchar; + if (*arg == '<') { while (*p != '>') { if (*p++ == NUL) { // expand terminal option name return; } } - key = get_special_key_code((char_u *)arg + 1); + int key = get_special_key_code((char_u *)arg + 1); if (key == 0) { // unknown name xp->xp_context = EXPAND_NOTHING; return; @@ -4721,7 +4687,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) for (p = arg + strlen(arg) - 1; p > xp->xp_pattern; p--) { // count number of backslashes before ' ' or ',' if (*p == ' ' || *p == ',') { - s = p; + char *s = p; while (s > xp->xp_pattern && *(s - 1) == '\\') { s--; } @@ -4744,17 +4710,15 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file) { int num_normal = 0; // Nr of matching non-term-code settings - int match; int count = 0; - char *str; - int loop; static char *(names[]) = { "all" }; int ic = regmatch->rm_ic; // remember the ignore-case flag // do this loop twice: // loop == 0: count the number of matching options // loop == 1: copy the matching options into allocated memory - for (loop = 0; loop <= 1; loop++) { + for (int loop = 0; loop <= 1; loop++) { + int match; regmatch->rm_ic = ic; if (xp->xp_context != EXPAND_BOOL_SETTINGS) { for (match = 0; match < (int)ARRAY_SIZE(names); @@ -4768,6 +4732,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi } } } + char *str; for (size_t opt_idx = 0; (str = options[opt_idx].fullname) != NULL; opt_idx++) { if (options[opt_idx].var == NULL) { @@ -5090,15 +5055,12 @@ void reset_option_was_set(const char *name) /// fill_breakat_flags() -- called when 'breakat' changes value. void fill_breakat_flags(void) { - char_u *p; - int i; - - for (i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { breakat_flags[i] = false; } if (p_breakat != NULL) { - for (p = (char_u *)p_breakat; *p; p++) { + for (char_u *p = (char_u *)p_breakat; *p; p++) { breakat_flags[*p] = true; } } diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 3521703fba..074a8b7936 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -19,21 +19,21 @@ // Return a pointer to the ACL of file "fname" in allocated memory. // Return NULL if the ACL is not available for whatever reason. -vim_acl_T mch_get_acl(const char_u *fname) +vim_acl_T os_get_acl(const char_u *fname) { vim_acl_T ret = NULL; return ret; } // Set the ACL of file "fname" to "acl" (unless it's NULL). -void mch_set_acl(const char_u *fname, vim_acl_T aclent) +void os_set_acl(const char_u *fname, vim_acl_T aclent) { if (aclent == NULL) { return; } } -void mch_free_acl(vim_acl_T aclent) +void os_free_acl(vim_acl_T aclent) { if (aclent == NULL) { return; diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c index 19b89bef74..4e2fa54c26 100644 --- a/src/nvim/regexp_bt.c +++ b/src/nvim/regexp_bt.c @@ -3539,8 +3539,8 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out) #ifdef REGEXP_DEBUG if (scan != NULL && regnarrate) { - mch_errmsg((char *)regprop(scan)); - mch_errmsg("(\n"); + os_errmsg((char *)regprop(scan)); + os_errmsg("(\n"); } #endif @@ -3566,18 +3566,18 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out) #ifdef REGEXP_DEBUG if (regnarrate) { - mch_errmsg((char *)regprop(scan)); - mch_errmsg("...\n"); + os_errmsg((char *)regprop(scan)); + os_errmsg("...\n"); if (re_extmatch_in != NULL) { int i; - mch_errmsg(_("External submatches:\n")); + os_errmsg(_("External submatches:\n")); for (i = 0; i < NSUBEXP; i++) { - mch_errmsg(" \""); + os_errmsg(" \""); if (re_extmatch_in->matches[i] != NULL) { - mch_errmsg((char *)re_extmatch_in->matches[i]); + os_errmsg((char *)re_extmatch_in->matches[i]); } - mch_errmsg("\"\n"); + os_errmsg("\"\n"); } } } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 10a0c9c18c..106e92d43c 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1439,8 +1439,8 @@ static bool send_mouse_event(Terminal *term, int c) int direction = c == K_MOUSEDOWN ? MSCR_DOWN : MSCR_UP; if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { scroll_redraw(direction, curwin->w_botline - curwin->w_topline); - } else { - scroll_redraw(direction, 3L); + } else if (p_mousescroll_vert > 0) { + scroll_redraw(direction, p_mousescroll_vert); } curwin->w_redr_status = true; diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 88f0c74d37..3edfa1b407 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -1555,13 +1555,6 @@ endfunc func Test_sc_file() filetype on - " SC file methods are defined 'Class : Method' - call writefile(['SCNvimDocRenderer : SCDocHTMLRenderer {'], 'srcfile.sc') - split srcfile.sc - call assert_equal('supercollider', &filetype) - bwipe! - call delete('srcfile.sc') - " SC classes are defined with '+ Class {}' call writefile(['+ SCNvim {', '*methodArgs {|method|'], 'srcfile.sc') split srcfile.sc diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index c1c78e9a8f..7a9392545e 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -191,17 +191,17 @@ func s:CompleteDone_CompleteFuncDict( findstart, base ) endif return { - \ 'words': [ - \ { - \ 'word': 'aword', - \ 'abbr': 'wrd', - \ 'menu': 'extra text', - \ 'info': 'words are cool', - \ 'kind': 'W', - \ 'user_data': ['one', 'two'] - \ } - \ ] - \ } + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W', + \ 'user_data': ['one', 'two'] + \ } + \ ] + \ } endfunc func s:CompleteDone_CheckCompletedItemNone() @@ -261,16 +261,16 @@ func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base) endif return { - \ 'words': [ - \ { - \ 'word': 'aword', - \ 'abbr': 'wrd', - \ 'menu': 'extra text', - \ 'info': 'words are cool', - \ 'kind': 'W' - \ } - \ ] - \ } + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W', + \ } + \ ] + \ } endfunc func s:CompleteDone_CheckCompletedItemDictNoUserData() diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim index b432b7bbbc..a7ccca498c 100644 --- a/src/nvim/testdir/test_marks.vim +++ b/src/nvim/testdir/test_marks.vim @@ -304,4 +304,17 @@ func Test_getmarklist() close! endfunc +" This was using freed memory +func Test_jump_mark_autocmd() + next 00 + edit 0 + sargument + au BufEnter 0 all + sil norm + + au! BufEnter + bwipe! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 6e8368f71d..ab63506d3c 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -1811,4 +1811,17 @@ function Test_splitkeep_status() call VerifyScreenDump(buf, 'Test_splitkeep_status_1', {}) endfunction +function Test_new_help_window_on_error() + help change.txt + execute "normal! /CTRL-@\<CR>" + silent! execute "normal! \<C-W>]" + + let wincount = winnr('$') + help 'mod' + + call assert_equal(wincount, winnr('$')) + call assert_equal(expand("<cword>"), "'mod'") +endfunction + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 05adc3c6d3..0777d1309d 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1343,9 +1343,9 @@ write_error: #ifdef HAVE_ACL if (buf->b_ffname != NULL) { // For systems that support ACL: get the ACL from the original file. - vim_acl_T acl = mch_get_acl((char_u *)buf->b_ffname); - mch_set_acl((char_u *)file_name, acl); - mch_free_acl(acl); + vim_acl_T acl = os_get_acl((char_u *)buf->b_ffname); + os_set_acl((char_u *)file_name, acl); + os_free_acl(acl); } #endif diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 3a927d6a55..52af85ccc6 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -253,8 +253,8 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() // been seen at that stage. But it must be before globals.h, where error_ga // is declared. #ifndef MSWIN -# define mch_errmsg(str) fprintf(stderr, "%s", (str)) -# define mch_msg(str) printf("%s", (str)) +# define os_errmsg(str) fprintf(stderr, "%s", (str)) +# define os_msg(str) printf("%s", (str)) #endif #include "nvim/buffer_defs.h" // buffer and windows diff --git a/src/nvim/window.c b/src/nvim/window.c index 05694a8b6d..d026f4551a 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -494,6 +494,7 @@ newwindow: // Execute the command right here, required when // "wincmd ]" was used in a function. do_nv_ident(Ctrl_RSB, NUL); + postponed_split = 0; break; // edit file name under cursor in a new window @@ -594,6 +595,7 @@ wingotofile: // Execute the command right here, required when // "wincmd g}" was used in a function. do_nv_ident('g', xchar); + postponed_split = 0; break; case 'f': // CTRL-W gf: "gf" in a new tab page diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 5677990525..531b9cc2c1 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3853,14 +3853,16 @@ describe('API', function() eq("", meths.cmd({ cmd = "Foo", bang = false }, { output = true })) end) it('works with modifiers', function() - -- with :silent output is still captured + -- with silent = true output is still captured eq('1', meths.cmd({ cmd = 'echomsg', args = { '1' }, mods = { silent = true } }, { output = true })) -- but message isn't added to message history eq('', meths.cmd({ cmd = 'messages' }, { output = true })) + meths.create_user_command("Foo", 'set verbose', {}) eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true })) + meths.create_user_command("Mods", "echo '<mods>'", {}) eq('keepmarks keeppatterns silent 3verbose aboveleft horizontal', meths.cmd({ cmd = "Mods", mods = { @@ -3872,6 +3874,7 @@ describe('API', function() verbose = 3, } }, { output = true })) eq(0, meths.get_option_value("verbose", {})) + command('edit foo.txt | edit bar.txt') eq(' 1 #h "foo.txt" line 1', meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = false } } }, @@ -3879,6 +3882,13 @@ describe('API', function() eq(' 2 %a "bar.txt" line 1', meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = true } } }, { output = true })) + + -- with emsg_silent = true error is suppresed + feed([[:lua vim.api.nvim_cmd({ cmd = 'call', mods = { emsg_silent = true } }, {})<CR>]]) + eq('', meths.cmd({ cmd = 'messages' }, { output = true })) + -- error from the next command typed is not suppressed #21420 + feed(':call<CR><CR>') + eq('E471: Argument required', meths.cmd({ cmd = 'messages' }, { output = true })) end) it('works with magic.file', function() exec_lua([[ diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index e390619a5a..90eccc49c8 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -512,6 +512,8 @@ describe('lua stdlib', function() eq(NIL, exec_lua("return vim.tbl_get({ unindexable = function () end }, 'unindexable', 'missing_key')")) eq(NIL, exec_lua("return vim.tbl_get({}, 'missing_key')")) eq(NIL, exec_lua("return vim.tbl_get({})")) + eq(1, exec_lua("return select('#', vim.tbl_get({}))")) + eq(1, exec_lua("return select('#', vim.tbl_get({ nested = {} }, 'nested', 'missing_key'))")) end) it('vim.tbl_extend', function() diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 899df0ac54..50c8f5e7df 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -289,7 +289,7 @@ describe(':terminal mouse', function() ]]) end) - it('wont lose focus if another window is scrolled', function() + it("won't lose focus if another window is scrolled", function() feed('<ScrollWheelUp><4,0><ScrollWheelUp><4,0>') screen:expect([[ {7: 21 }line │line30 | @@ -312,6 +312,34 @@ describe(':terminal mouse', function() ]]) end) + it("scrolling another window respects 'mousescroll'", function() + command('set mousescroll=ver:1') + feed('<ScrollWheelUp><4,0>') + screen:expect([[ + {7: 26 }line │line30 | + {7: 27 }line │rows: 5, cols: 25 | + {7: 28 }line │rows: 5, cols: 24 | + {7: 29 }line │mouse enabled | + {7: 30 }line │{1: } | + ========== ========== | + {3:-- TERMINAL --} | + ]]) + command('set mousescroll=ver:10') + feed('<ScrollWheelUp><4,0>') + screen:expect([[ + {7: 16 }line │line30 | + {7: 17 }line │rows: 5, cols: 25 | + {7: 18 }line │rows: 5, cols: 24 | + {7: 19 }line │mouse enabled | + {7: 20 }line │{1: } | + ========== ========== | + {3:-- TERMINAL --} | + ]]) + command('set mousescroll=ver:0') + feed('<ScrollWheelUp><4,0>') + screen:expect_unchanged() + end) + it('will lose focus if another window is clicked', function() feed('<LeftMouse><5,1>') screen:expect([[ |