diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 7 | ||||
-rw-r--r-- | src/nvim/buffer.c | 92 | ||||
-rw-r--r-- | src/nvim/change.c | 24 | ||||
-rw-r--r-- | src/nvim/edit.c | 14 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 2 | ||||
-rw-r--r-- | src/nvim/fileio.c | 3 | ||||
-rw-r--r-- | src/nvim/generators/gen_char_blob.lua | 70 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 25 | ||||
-rw-r--r-- | src/nvim/lua/vim.lua | 227 | ||||
-rw-r--r-- | src/nvim/main.c | 2 | ||||
-rw-r--r-- | src/nvim/mark_extended.c | 4 | ||||
-rw-r--r-- | src/nvim/memline.c | 5 | ||||
-rw-r--r-- | src/nvim/ops.c | 28 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 467 | ||||
-rw-r--r-- | src/nvim/search.c | 56 | ||||
-rw-r--r-- | src/nvim/tag.c | 60 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 15 | ||||
-rw-r--r-- | src/nvim/testdir/runtest.vim | 2 | ||||
-rw-r--r-- | src/nvim/testdir/shared.vim | 9 | ||||
-rw-r--r-- | src/nvim/testdir/test_options.vim | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_substitute.vim | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_tagjump.vim | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_textobjects.vim | 7 | ||||
-rw-r--r-- | src/nvim/window.c | 6 |
25 files changed, 663 insertions, 504 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index b00ac866b7..988021ca7a 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -52,7 +52,8 @@ set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua) set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h) -set(VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/lua/vim.lua) +set(LUA_VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/lua/vim.lua) +set(LUA_SHARED_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/shared.lua) set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua) set(LINT_SUPPRESS_FILE ${PROJECT_BINARY_DIR}/errors.json) set(LINT_SUPPRESS_URL_BASE "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint") @@ -317,11 +318,13 @@ add_custom_command( add_custom_command( OUTPUT ${VIM_MODULE_FILE} - COMMAND ${LUA_PRG} ${CHAR_BLOB_GENERATOR} ${VIM_MODULE_SOURCE} - ${VIM_MODULE_FILE} vim_module + COMMAND ${LUA_PRG} ${CHAR_BLOB_GENERATOR} ${VIM_MODULE_FILE} + ${LUA_VIM_MODULE_SOURCE} vim_module + ${LUA_SHARED_MODULE_SOURCE} shared_module DEPENDS ${CHAR_BLOB_GENERATOR} - ${VIM_MODULE_SOURCE} + ${LUA_VIM_MODULE_SOURCE} + ${LUA_SHARED_MODULE_SOURCE} ) list(APPEND NVIM_GENERATED_SOURCES diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 10f7dd1a7b..3535bc3186 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1074,9 +1074,10 @@ fail: /// float where the text should not be edited. Disables /// 'number', 'relativenumber', 'cursorline', 'cursorcolumn', /// 'foldcolumn', 'spell' and 'list' options. 'signcolumn' -/// is changed to `auto`. The end-of-buffer region is hidden -/// by setting `eob` flag of 'fillchars' to a space char, -/// and clearing the |EndOfBuffer| region in 'winhighlight'. +/// is changed to `auto` and 'colorcolumn' is cleared. The +/// end-of-buffer region is hidden by setting `eob` flag of +/// 'fillchars' to a space char, and clearing the +/// |EndOfBuffer| region in 'winhighlight'. /// @param[out] err Error details, if any /// /// @return Window handle, or 0 on error diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c01364aadd..e3b8e9cc6d 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -411,11 +411,11 @@ bool buf_valid(buf_T *buf) /// caller should get a new buffer very soon! /// The 'bufhidden' option can force freeing and deleting. /// @param abort_if_last -/// If TRUE, do not close the buffer if autocommands cause +/// If true, do not close the buffer if autocommands cause /// there to be only one window with this buffer. e.g. when /// ":quit" is supposed to close the window but autocommands /// close all other windows. -void close_buffer(win_T *win, buf_T *buf, int action, int abort_if_last) +void close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) { bool unload_buf = (action != 0); bool del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE); @@ -1585,10 +1585,12 @@ void enter_buffer(buf_T *buf) open_buffer(false, NULL, 0); } else { - if (!msg_silent) { + if (!msg_silent && !shortmess(SHM_FILEINFO)) { need_fileinfo = true; // display file info after redraw } - (void)buf_check_timestamp(curbuf, false); // check if file changed + // check if file changed + (void)buf_check_timestamp(curbuf, false); + curwin->w_topline = 1; curwin->w_topfill = 0; apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf); @@ -2692,7 +2694,7 @@ setfname( buf_T *buf, char_u *ffname, char_u *sfname, - int message // give message when buffer already exists + bool message // give message when buffer already exists ) { buf_T *obuf = NULL; @@ -5626,6 +5628,86 @@ void bufhl_mark_adjust(buf_T* buf, } } +/// Adjust a placed highlight for column changes and joined/broken lines +bool bufhl_mark_col_adjust(buf_T *buf, + linenr_T lnum, + colnr_T mincol, + long lnum_amount, + long col_amount) +{ + bool moved = false; + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, false); + if (!lineinfo) { + // Old line empty, nothing to do + return false; + } + // Create the new line below only if needed + BufhlLine *lineinfo2 = NULL; + + colnr_T delcol = MAXCOL; + if (lnum_amount == 0 && col_amount < 0) { + delcol = mincol+(int)col_amount; + } + + size_t newidx = 0; + for (size_t i = 0; i < kv_size(lineinfo->items); i++) { + BufhlItem *item = &kv_A(lineinfo->items, i); + bool delete = false; + if (item->start >= mincol) { + moved = true; + item->start += (int)col_amount; + if (item->stop < MAXCOL) { + item->stop += (int)col_amount; + } + if (lnum_amount != 0) { + if (lineinfo2 == NULL) { + lineinfo2 = bufhl_tree_ref(&buf->b_bufhl_info, + lnum+lnum_amount, true); + } + kv_push(lineinfo2->items, *item); + delete = true; + } + } else { + if (item->start >= delcol) { + moved = true; + item->start = delcol; + } + if (item->stop == MAXCOL || item->stop+1 >= mincol) { + if (item->stop == MAXCOL) { + if (delcol < MAXCOL + && delcol > (colnr_T)STRLEN(ml_get_buf(buf, lnum, false))) { + delete = true; + } + } else { + moved = true; + item->stop += (int)col_amount; + } + assert(lnum_amount >= 0); + if (lnum_amount > 0) { + item->stop = MAXCOL; + } + } else if (item->stop+1 >= delcol) { + moved = true; + item->stop = delcol-1; + } + // we covered the entire range with a visual delete or something + if (item->stop < item->start) { + delete = true; + } + } + + if (!delete) { + if (i != newidx) { + kv_A(lineinfo->items, newidx) = kv_A(lineinfo->items, i); + } + newidx++; + } + } + kv_size(lineinfo->items) = newidx; + + return moved; +} + /// Get highlights to display at a specific line /// diff --git a/src/nvim/change.c b/src/nvim/change.c index 7558055696..8a782c2b20 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -359,6 +359,24 @@ void changed_bytes(linenr_T lnum, colnr_T col) } } +/// insert/delete bytes at column +/// +/// Like changed_bytes() but also adjust extmark for "added" bytes. +/// When "added" is negative text was deleted. +static void inserted_bytes(linenr_T lnum, colnr_T col, int added) +{ + if (added > 0) { + extmark_col_adjust(curbuf, lnum, col+1, 0, added, kExtmarkUndo); + } else if (added < 0) { + // TODO(bfredl): next revision of extmarks should handle both these + // with the same entry point. Also with more sane params.. + extmark_col_adjust_delete(curbuf, lnum, col+2, + col+(-added)+1, kExtmarkUndo, 0); + } + + changed_bytes(lnum, col); +} + /// Appended "count" lines below line "lnum" in the current buffer. /// Must be called AFTER the change and after mark_adjust(). /// Takes care of marking the buffer to be redrawn and sets the changed flag. @@ -630,7 +648,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) ml_replace(lnum, newp, false); // mark the buffer as changed and prepare for displaying - changed_bytes(lnum, (colnr_T)col); + inserted_bytes(lnum, (colnr_T)col, (int)(newlen - oldlen)); // If we're in Insert or Replace mode and 'showmatch' is set, then briefly // show the match for right parens and braces. @@ -676,7 +694,7 @@ void ins_str(char_u *s) assert(bytes >= 0); memmove(newp + col + newlen, oldp + col, (size_t)bytes); ml_replace(lnum, newp, false); - changed_bytes(lnum, col); + inserted_bytes(lnum, col, newlen); curwin->w_cursor.col += newlen; } @@ -797,7 +815,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) } // mark the buffer as changed and prepare for displaying - changed_bytes(lnum, curwin->w_cursor.col); + inserted_bytes(lnum, col, -count); return OK; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index cd0f3f4b9d..eecea03a19 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -5600,9 +5600,6 @@ insertchar ( do_digraph(buf[i-1]); /* may be the start of a digraph */ buf[i] = NUL; ins_str(buf); - extmark_col_adjust(curbuf, curwin->w_cursor.lnum, - (colnr_T)(curwin->w_cursor.col + 1), 0, - (long)STRLEN(buf), kExtmarkUndo); if (flags & INSCHAR_CTRLV) { redo_literal(*buf); i = 1; @@ -5613,9 +5610,6 @@ insertchar ( } else { int cc; - extmark_col_adjust(curbuf, curwin->w_cursor.lnum, - (colnr_T)(curwin->w_cursor.col + 1), 0, - 1, kExtmarkUndo); if ((cc = utf_char2len(c)) > 1) { char_u buf[MB_MAXBYTES + 1]; @@ -8506,14 +8500,6 @@ static bool ins_tab(void) temp -= get_nolist_virtcol() % temp; - // Move extmarks - extmark_col_adjust(curbuf, - curwin->w_cursor.lnum, - curwin->w_cursor.col, - 0, - temp, - kExtmarkUndo); - /* * Insert the first space with ins_char(). It will delete one char in * replace mode. Insert the rest with ins_str(); it will not delete any diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 4725246764..0c3b467612 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1587,7 +1587,7 @@ int rename_buffer(char_u *new_fname) xfname = curbuf->b_fname; curbuf->b_ffname = NULL; curbuf->b_sfname = NULL; - if (setfname(curbuf, new_fname, NULL, TRUE) == FAIL) { + if (setfname(curbuf, new_fname, NULL, true) == FAIL) { curbuf->b_ffname = fname; curbuf->b_sfname = sfname; return FAIL; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index fcf15638c7..f518e59acc 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3731,8 +3731,9 @@ static int set_rw_fname(char_u *fname, char_u *sfname) return FAIL; } - if (setfname(curbuf, fname, sfname, FALSE) == OK) + if (setfname(curbuf, fname, sfname, false) == OK) { curbuf->b_flags |= BF_NOTEDITED; + } /* ....and a new named one is created */ apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf); diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua index 1702add2e4..a7dad50d48 100644 --- a/src/nvim/generators/gen_char_blob.lua +++ b/src/nvim/generators/gen_char_blob.lua @@ -1,49 +1,59 @@ if arg[1] == '--help' then print('Usage:') - print(' gencharblob.lua source target varname') + print(' '..arg[0]..' target source varname [source varname]...') print('') print('Generates C file with big uint8_t blob.') print('Blob will be stored in a static const array named varname.') os.exit() end -assert(#arg == 3) +assert(#arg >= 3 and (#arg - 1) % 2 == 0) -local source_file = arg[1] -local target_file = arg[2] -local varname = arg[3] - -local source = io.open(source_file, 'r') +local target_file = arg[1] or error('Need a target file') local target = io.open(target_file, 'w') target:write('#include <stdint.h>\n\n') -target:write(('static const uint8_t %s[] = {\n'):format(varname)) - -local num_bytes = 0 -local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line -target:write(' ') - -local increase_num_bytes -increase_num_bytes = function() - num_bytes = num_bytes + 1 - if num_bytes == MAX_NUM_BYTES then - num_bytes = 0 - target:write('\n ') + +local varnames = {} +for argi = 2, #arg, 2 do + local source_file = arg[argi] + local varname = arg[argi + 1] + if varnames[varname] then + error(string.format("varname %q is already specified for file %q", varname, varnames[varname])) end -end + varnames[varname] = source_file + + local source = io.open(source_file, 'r') + or error(string.format("source_file %q doesn't exist", source_file)) + + target:write(('static const uint8_t %s[] = {\n'):format(varname)) -for line in source:lines() do - for i = 1,string.len(line) do - local byte = string.byte(line, i) - assert(byte ~= 0) - target:write(string.format(' %3u,', byte)) + local num_bytes = 0 + local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line + target:write(' ') + + local increase_num_bytes + increase_num_bytes = function() + num_bytes = num_bytes + 1 + if num_bytes == MAX_NUM_BYTES then + num_bytes = 0 + target:write('\n ') + end + end + + for line in source:lines() do + for i = 1, string.len(line) do + local byte = line:byte(i) + assert(byte ~= 0) + target:write(string.format(' %3u,', byte)) + increase_num_bytes() + end + target:write(string.format(' %3u,', string.byte('\n', 1))) increase_num_bytes() end - target:write(string.format(' %3u,', string.byte('\n', 1))) - increase_num_bytes() -end -target:write(' 0};\n') + target:write(' 0};\n') + source:close() +end -source:close() target:close() diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 093c130c5f..5450f62f54 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -268,12 +268,7 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL #endif // vim - const char *code = (char *)&vim_module[0]; - if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") - || lua_pcall(lstate, 0, LUA_MULTRET, 0)) { - nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); - return 1; - } + lua_newtable(lstate); // vim.api nlua_add_api_functions(lstate); // vim.types, vim.type_idx, vim.val_idx @@ -334,6 +329,24 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setglobal(lstate, "vim"); + { + const char *code = (char *)&shared_module[0]; + if (luaL_loadbuffer(lstate, code, strlen(code), "@shared.lua") + || lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5106: Error while creating shared module: %.*s")); + return 1; + } + } + + { + const char *code = (char *)&vim_module[0]; + if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") + || lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); + return 1; + } + } + return 0; } diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua index 1665a55aff..8019511317 100644 --- a/src/nvim/lua/vim.lua +++ b/src/nvim/lua/vim.lua @@ -33,35 +33,35 @@ -- - https://github.com/bakpakin/Fennel (pretty print, repl) -- - https://github.com/howl-editor/howl/tree/master/lib/howl/util +local vim = vim +assert(vim) -- Internal-only until comments in #8107 are addressed. -- Returns: -- {errcode}, {output} -local function _system(cmd) - local out = vim.api.nvim_call_function('system', { cmd }) - local err = vim.api.nvim_get_vvar('shell_error') +function vim._system(cmd) + local out = vim.fn.system(cmd) + local err = vim.v.shell_error return err, out end -- Gets process info from the `ps` command. -- Used by nvim_get_proc() as a fallback. -local function _os_proc_info(pid) +function vim._os_proc_info(pid) if pid == nil or pid <= 0 or type(pid) ~= 'number' then error('invalid pid') end local cmd = { 'ps', '-p', pid, '-o', 'comm=', } - local err, name = _system(cmd) - if 1 == err and string.gsub(name, '%s*', '') == '' then + local err, name = vim._system(cmd) + if 1 == err and vim.trim(name) == '' then return {} -- Process not found. elseif 0 ~= err then - local args_str = vim.api.nvim_call_function('string', { cmd }) - error('command failed: '..args_str) + error('command failed: '..vim.fn.string(cmd)) end - local _, ppid = _system({ 'ps', '-p', pid, '-o', 'ppid=', }) + local _, ppid = vim._system({ 'ps', '-p', pid, '-o', 'ppid=', }) -- Remove trailing whitespace. - name = string.gsub(string.gsub(name, '%s+$', ''), '^.*/', '') - ppid = string.gsub(ppid, '%s+$', '') - ppid = tonumber(ppid) == nil and -1 or tonumber(ppid) + name = vim.trim(name):gsub('^.*/', '') + ppid = tonumber(ppid) or -1 return { name = name, pid = pid, @@ -71,20 +71,19 @@ end -- Gets process children from the `pgrep` command. -- Used by nvim_get_proc_children() as a fallback. -local function _os_proc_children(ppid) +function vim._os_proc_children(ppid) if ppid == nil or ppid <= 0 or type(ppid) ~= 'number' then error('invalid ppid') end local cmd = { 'pgrep', '-P', ppid, } - local err, rv = _system(cmd) - if 1 == err and string.gsub(rv, '%s*', '') == '' then + local err, rv = vim._system(cmd) + if 1 == err and vim.trim(rv) == '' then return {} -- Process not found. elseif 0 ~= err then - local args_str = vim.api.nvim_call_function('string', { cmd }) - error('command failed: '..args_str) + error('command failed: '..vim.fn.string(cmd)) end local children = {} - for s in string.gmatch(rv, '%S+') do + for s in rv:gmatch('%S+') do local i = tonumber(s) if i ~= nil then table.insert(children, i) @@ -98,7 +97,7 @@ end -- Last inserted paths. Used to clear out items from package.[c]path when they -- are no longer in &runtimepath. local last_nvim_paths = {} -local function _update_package_paths() +function vim._update_package_paths() local cur_nvim_paths = {} local rtps = vim.api.nvim_list_runtime_paths() local sep = package.config:sub(1, 1) @@ -162,35 +161,35 @@ local function inspect(object, options) -- luacheck: no unused error(object, options) -- Stub for gen_vimdoc.py end ---- Paste handler, invoked by |nvim_paste()| when a conforming UI ---- (such as the |TUI|) pastes text into the editor. ---- ---- Example: To remove ANSI color codes when pasting: ---- <pre> ---- vim.paste = (function(overridden) ---- return function(lines, phase) ---- for i,line in ipairs(lines) do ---- -- Scrub ANSI color codes from paste input. ---- lines[i] = line:gsub('\27%[[0-9;mK]+', '') ---- end ---- overridden(lines, phase) ---- end ---- end)(vim.paste) ---- </pre> ---- ---@see |paste| ---- ---@param lines |readfile()|-style list of lines to paste. |channel-lines| ---@param phase -1: "non-streaming" paste: the call contains all lines. ---- If paste is "streamed", `phase` indicates the stream state: ---- - 1: starts the paste (exactly once) ---- - 2: continues the paste (zero or more times) ---- - 3: ends the paste (exactly once) ---@returns false if client should cancel the paste. -local function paste(lines, phase) end -- luacheck: no unused -paste = (function() +do local tdots, tick, got_line1 = 0, 0, false - return function(lines, phase) + + --- Paste handler, invoked by |nvim_paste()| when a conforming UI + --- (such as the |TUI|) pastes text into the editor. + --- + --- Example: To remove ANSI color codes when pasting: + --- <pre> + --- vim.paste = (function(overridden) + --- return function(lines, phase) + --- for i,line in ipairs(lines) do + --- -- Scrub ANSI color codes from paste input. + --- lines[i] = line:gsub('\27%[[0-9;mK]+', '') + --- end + --- overridden(lines, phase) + --- end + --- end)(vim.paste) + --- </pre> + --- + --@see |paste| + --- + --@param lines |readfile()|-style list of lines to paste. |channel-lines| + --@param phase -1: "non-streaming" paste: the call contains all lines. + --- If paste is "streamed", `phase` indicates the stream state: + --- - 1: starts the paste (exactly once) + --- - 2: continues the paste (zero or more times) + --- - 3: ends the paste (exactly once) + --@returns false if client should cancel the paste. + function vim.paste(lines, phase) local call = vim.api.nvim_call_function local now = vim.loop.now() local mode = call('mode', {}):sub(1,1) @@ -230,20 +229,33 @@ paste = (function() end return true -- Paste will not continue if not returning `true`. end -end)() +end --- Defers callback `cb` until the Nvim API is safe to call. --- ---@see |lua-loop-callbacks| ---@see |vim.schedule()| ---@see |vim.in_fast_event()| -local function schedule_wrap(cb) +function vim.schedule_wrap(cb) return (function (...) local args = {...} vim.schedule(function() cb(unpack(args)) end) end) end +-- vim.fn.{func}(...) +vim.fn = setmetatable({}, { + __index = function(t, key) + local function _fn(...) + return vim.call(key, ...) + end + t[key] = _fn + return _fn + end +}) + +-- These are for loading runtime modules lazily since they aren't available in +-- the nvim binary as specified in executor.c local function __index(t, key) if key == 'inspect' then t.inspect = require('vim.inspect') @@ -251,10 +263,6 @@ local function __index(t, key) elseif key == 'treesitter' then t.treesitter = require('vim.treesitter') return t.treesitter - elseif require('vim.shared')[key] ~= nil then - -- Expose all `vim.shared` functions on the `vim` module. - t[key] = require('vim.shared')[key] - return t[key] elseif require('vim.uri')[key] ~= nil then -- Expose all `vim.uri` functions on the `vim` module. t[key] = require('vim.uri')[key] @@ -265,29 +273,100 @@ local function __index(t, key) end end +setmetatable(vim, { + __index = __index +}) --- vim.fn.{func}(...) -local function _fn_index(t, key) - local function _fn(...) - return vim.call(key, ...) +do + local a = vim.api + local validate = vim.validate + local function make_meta_accessor(get, set, del) + validate { + get = {get, 'f'}; + set = {set, 'f'}; + del = {del, 'f', true}; + } + local mt = {} + if del then + function mt:__newindex(k, v) + if v == nil then + return del(k) + end + return set(k, v) + end + else + function mt:__newindex(k, v) + return set(k, v) + end + end + function mt:__index(k) + return get(k) + end + return setmetatable({}, mt) + end + local function pcall_ret(status, ...) + if status then return ... end + end + local function nil_wrap(fn) + return function(...) + return pcall_ret(pcall(fn, ...)) + end + end + vim.g = make_meta_accessor(nil_wrap(a.nvim_get_var), a.nvim_set_var, a.nvim_del_var) + vim.v = make_meta_accessor(nil_wrap(a.nvim_get_vvar), a.nvim_set_vvar) + vim.o = make_meta_accessor(nil_wrap(a.nvim_get_option), a.nvim_set_option) + vim.env = make_meta_accessor(vim.fn.getenv, vim.fn.setenv) + -- TODO(ashkan) if/when these are available from an API, generate them + -- instead of hardcoding. + local window_options = { + arab = true; arabic = true; breakindent = true; breakindentopt = true; + bri = true; briopt = true; cc = true; cocu = true; + cole = true; colorcolumn = true; concealcursor = true; conceallevel = true; + crb = true; cuc = true; cul = true; cursorbind = true; + cursorcolumn = true; cursorline = true; diff = true; fcs = true; + fdc = true; fde = true; fdi = true; fdl = true; + fdm = true; fdn = true; fdt = true; fen = true; + fillchars = true; fml = true; fmr = true; foldcolumn = true; + foldenable = true; foldexpr = true; foldignore = true; foldlevel = true; + foldmarker = true; foldmethod = true; foldminlines = true; foldnestmax = true; + foldtext = true; lbr = true; lcs = true; linebreak = true; + list = true; listchars = true; nu = true; number = true; + numberwidth = true; nuw = true; previewwindow = true; pvw = true; + relativenumber = true; rightleft = true; rightleftcmd = true; rl = true; + rlc = true; rnu = true; scb = true; scl = true; + scr = true; scroll = true; scrollbind = true; signcolumn = true; + spell = true; statusline = true; stl = true; wfh = true; + wfw = true; winbl = true; winblend = true; winfixheight = true; + winfixwidth = true; winhighlight = true; winhl = true; wrap = true; + } + local function new_buf_opt_accessor(bufnr) + local function get(k) + if window_options[k] then + return a.nvim_err_writeln(k.." is a window option, not a buffer option") + end + return a.nvim_buf_get_option(bufnr, k) + end + local function set(k, v) + if window_options[k] then + return a.nvim_err_writeln(k.." is a window option, not a buffer option") + end + return a.nvim_buf_set_option(bufnr, k, v) + end + return make_meta_accessor(nil_wrap(get), set) + end + vim.bo = new_buf_opt_accessor(0) + getmetatable(vim.bo).__call = function(_, bufnr) + return new_buf_opt_accessor(bufnr) + end + local function new_win_opt_accessor(winnr) + local function get(k) return a.nvim_win_get_option(winnr, k) end + local function set(k, v) return a.nvim_win_set_option(winnr, k, v) end + return make_meta_accessor(nil_wrap(get), set) + end + vim.wo = new_win_opt_accessor(0) + getmetatable(vim.wo).__call = function(_, winnr) + return new_win_opt_accessor(winnr) end - t[key] = _fn - return _fn end -local fn = setmetatable({}, {__index=_fn_index}) - -local module = { - _update_package_paths = _update_package_paths, - _os_proc_children = _os_proc_children, - _os_proc_info = _os_proc_info, - _system = _system, - paste = paste, - schedule_wrap = schedule_wrap, - fn=fn, -} - -setmetatable(module, { - __index = __index -}) return module diff --git a/src/nvim/main.c b/src/nvim/main.c index e39eec4038..c8959d9ad1 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1516,7 +1516,7 @@ static void create_windows(mparm_T *parmp) /* We can't close the window, it would disturb what * happens next. Clear the file name and set the arg * index to -1 to delete it later. */ - setfname(curbuf, NULL, NULL, FALSE); + setfname(curbuf, NULL, NULL, false); curwin->w_arg_idx = -1; swap_exists_action = SEA_NONE; } else diff --git a/src/nvim/mark_extended.c b/src/nvim/mark_extended.c index 01745f484d..91c2f919ce 100644 --- a/src/nvim/mark_extended.c +++ b/src/nvim/mark_extended.c @@ -910,6 +910,9 @@ void extmark_col_adjust(buf_T *buf, linenr_T lnum, bool marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, lnum_amount, false, col_amount); + marks_moved |= bufhl_mark_col_adjust(buf, lnum, mincol, + lnum_amount, col_amount); + if (undo == kExtmarkUndo && marks_moved) { u_extmark_col_adjust(buf, lnum, mincol, lnum_amount, col_amount); } @@ -938,6 +941,7 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum, marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, 0, true, (long)endcol); + marks_moved |= bufhl_mark_col_adjust(buf, lnum, endcol, 0, mincol-(endcol+1)); // Deletes at the end of the line have different behaviour than the normal // case when deleted. // Cleanup any marks that are floating beyond the end of line. diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 2824d57f49..e5ba17a0a7 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -540,7 +540,7 @@ void ml_open_file(buf_T *buf) /// file, or reading into an existing buffer, create a swap file now. /// /// @param newfile reading file into new buffer -void check_need_swap(int newfile) +void check_need_swap(bool newfile) { int old_msg_silent = msg_silent; // might be reset by an E325 message msg_silent = 0; // If swap dialog prompts for input, user needs to see it! @@ -937,8 +937,9 @@ void ml_recover(bool checkext) */ if (directly) { expand_env(b0p->b0_fname, NameBuff, MAXPATHL); - if (setfname(curbuf, NameBuff, NULL, TRUE) == FAIL) + if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { goto theend; + } } home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 2301b2159f..f2d35d5e43 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1644,8 +1644,6 @@ int op_delete(oparg_T *oap) curwin->w_cursor.col = 0; (void)del_bytes((colnr_T)n, !virtual_op, oap->op_type == OP_DELETE && !oap->is_VIsual); - extmark_col_adjust(curbuf, curwin->w_cursor.lnum, - (colnr_T)0, 0L, (long)-n, kExtmarkUndo); curwin->w_cursor = curpos; // restore curwin->w_cursor (void)do_join(2, false, false, false, false); } @@ -1685,7 +1683,6 @@ setmarks: if (oap->is_VIsual == false) { endcol = MAX(endcol - 1, mincol); } - extmark_col_adjust_delete(curbuf, lnum, mincol, endcol, kExtmarkUndo, 0); } return OK; } @@ -2279,7 +2276,7 @@ void op_insert(oparg_T *oap, long count1) colnr_T col = oap->start.col; for (linenr_T lnum = oap->start.lnum; lnum <= oap->end.lnum; lnum++) { extmark_col_adjust(curbuf, lnum, col, 0, 1, kExtmarkUndo); - } + } } /* @@ -4279,14 +4276,14 @@ format_lines( if (next_leader_len > 0) { (void)del_bytes(next_leader_len, false, false); mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, - (long)-next_leader_len, 0, kExtmarkUndo); + (long)-next_leader_len, 0, kExtmarkNOOP); } else if (second_indent > 0) { // the "leader" for FO_Q_SECOND int indent = (int)getwhitecols_curline(); if (indent > 0) { - (void)del_bytes(indent, FALSE, FALSE); + (void)del_bytes(indent, false, false); mark_col_adjust(curwin->w_cursor.lnum, - (colnr_T)0, 0L, (long)-indent, 0, kExtmarkUndo); + (colnr_T)0, 0L, (long)-indent, 0, kExtmarkNOOP); } } curwin->w_cursor.lnum--; @@ -4951,23 +4948,6 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) curbuf->b_op_end.col--; } - // if buf1 wasn't allocated, only a singe ASCII char was changed in-place. - if (did_change && buf1 != NULL) { - extmark_col_adjust_delete(curbuf, - pos->lnum, - startpos.col + 2, - endpos.col + 1 + length, - kExtmarkUndo, - 0); - long col_amount = (long)STRLEN(buf1); - extmark_col_adjust(curbuf, - pos->lnum, - startpos.col + 1, - 0, - col_amount, - kExtmarkUndo); - } - theend: xfree(buf1); if (visual) { diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index ed57b28029..194cc5781b 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1,9 +1,7 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -/* - * quickfix.c: functions for quickfix mode, using a file with error messages - */ +// quickfix.c: functions for quickfix mode, using a file with error messages #include <assert.h> #include <inttypes.h> @@ -53,9 +51,7 @@ struct dir_stack_T { char_u *dirname; }; -/* - * For each error the next struct is allocated and linked in a list. - */ +// For each error the next struct is allocated and linked in a list. typedef struct qfline_S qfline_T; struct qfline_S { qfline_T *qf_next; ///< pointer to next error in the list @@ -74,9 +70,7 @@ struct qfline_S { char_u qf_valid; ///< valid error message detected }; -/* - * There is a stack of error lists. - */ +// There is a stack of error lists. #define LISTCOUNT 10 #define INVALID_QFIDX (-1) @@ -120,15 +114,13 @@ typedef struct qf_list_S { /// Quickfix/Location list stack definition /// Contains a list of quickfix/location lists (qf_list_T) struct qf_info_S { - /* - * Count of references to this list. Used only for location lists. - * When a location list window reference this list, qf_refcount - * will be 2. Otherwise, qf_refcount will be 1. When qf_refcount - * reaches 0, the list is freed. - */ + // Count of references to this list. Used only for location lists. + // When a location list window reference this list, qf_refcount + // will be 2. Otherwise, qf_refcount will be 1. When qf_refcount + // reaches 0, the list is freed. int qf_refcount; - int qf_listcount; /* current number of lists */ - int qf_curlist; /* current error list */ + int qf_listcount; // current number of lists + int qf_curlist; // current error list qf_list_T qf_lists[LISTCOUNT]; qfltype_T qfl_type; // type of list }; @@ -138,31 +130,29 @@ static unsigned last_qf_id = 0; // Last Used quickfix list id #define FMT_PATTERNS 11 // maximum number of % recognized -/* - * Structure used to hold the info of one part of 'errorformat' - */ +// Structure used to hold the info of one part of 'errorformat' typedef struct efm_S efm_T; struct efm_S { - regprog_T *prog; /* pre-formatted part of 'errorformat' */ - efm_T *next; /* pointer to next (NULL if last) */ - char_u addr[FMT_PATTERNS]; /* indices of used % patterns */ - char_u prefix; /* prefix of this format line: */ - /* 'D' enter directory */ - /* 'X' leave directory */ - /* 'A' start of multi-line message */ - /* 'E' error message */ - /* 'W' warning message */ - /* 'I' informational message */ - /* 'C' continuation line */ - /* 'Z' end of multi-line message */ - /* 'G' general, unspecific message */ - /* 'P' push file (partial) message */ - /* 'Q' pop/quit file (partial) message */ - /* 'O' overread (partial) message */ - char_u flags; /* additional flags given in prefix */ - /* '-' do not include this line */ - /* '+' include whole line in message */ - int conthere; /* %> used */ + regprog_T *prog; // pre-formatted part of 'errorformat' + efm_T *next; // pointer to next (NULL if last) + char_u addr[FMT_PATTERNS]; // indices of used % patterns + char_u prefix; // prefix of this format line: + // 'D' enter directory + // 'X' leave directory + // 'A' start of multi-line message + // 'E' error message + // 'W' warning message + // 'I' informational message + // 'C' continuation line + // 'Z' end of multi-line message + // 'G' general, unspecific message + // 'P' push file (partial) message + // 'Q' pop/quit file (partial) message + // 'O' overread (partial) message + char_u flags; // additional flags given in prefix + // '-' do not include this line + // '+' include whole line in message + int conthere; // %> used }; /// List of location lists to be deleted. @@ -221,7 +211,7 @@ static char_u *e_no_more_items = (char_u *)N_("E553: No more items"); // Quickfix window check helper macro #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) -/* Location list window check helper macro */ +// Location list window check helper macro #define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) // Quickfix and location list stack check helper macros @@ -1156,16 +1146,12 @@ qf_init_ext( goto error2; } - /* - * got_int is reset here, because it was probably set when killing the - * ":make" command, but we still want to read the errorfile then. - */ - got_int = FALSE; + // got_int is reset here, because it was probably set when killing the + // ":make" command, but we still want to read the errorfile then. + got_int = false; - /* - * Read the lines in the error file one by one. - * Try to recognize one of the error formats in each line. - */ + // Read the lines in the error file one by one. + // Try to recognize one of the error formats in each line. while (!got_int) { status = qf_init_process_nextline(qfl, fmt_first, &state, &fields); if (status == QF_END_OF_INPUT) { // end of input @@ -1263,10 +1249,8 @@ static void qf_new_list(qf_info_T *qi, const char_u *qf_title) qf_free(&qi->qf_lists[--qi->qf_listcount]); } - /* - * When the stack is full, remove to oldest entry - * Otherwise, add a new entry. - */ + // When the stack is full, remove to oldest entry + // Otherwise, add a new entry. if (qi->qf_listcount == LISTCOUNT) { qf_free(&qi->qf_lists[0]); for (i = 1; i < LISTCOUNT; i++) { @@ -1714,7 +1698,7 @@ static void ll_free_all(qf_info_T **pqi) qi = *pqi; if (qi == NULL) return; - *pqi = NULL; /* Remove reference to this list */ + *pqi = NULL; // Remove reference to this list qi->qf_refcount--; if (qi->qf_refcount < 1) { @@ -1739,7 +1723,7 @@ void qf_free_all(win_T *wp) qf_info_T *qi = &ql_info; if (wp != NULL) { - /* location list */ + // location list ll_free_all(&wp->w_llist); ll_free_all(&wp->w_llist_ref); } else { @@ -1892,14 +1876,13 @@ static qf_info_T *qf_alloc_stack(qfltype_T qfltype) static qf_info_T *ll_get_or_alloc_list(win_T *wp) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { - if (IS_LL_WINDOW(wp)) - /* For a location list window, use the referenced location list */ + if (IS_LL_WINDOW(wp)) { + // For a location list window, use the referenced location list return wp->w_llist_ref; + } - /* - * For a non-location list window, w_llist_ref should not point to a - * location list. - */ + // For a non-location list window, w_llist_ref should not point to a + // location list. ll_free_all(&wp->w_llist_ref); if (wp->w_llist == NULL) { @@ -2133,22 +2116,21 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, { struct dir_stack_T *ds_ptr; - /* allocate new stack element and hook it in */ + // allocate new stack element and hook it in struct dir_stack_T *ds_new = xmalloc(sizeof(struct dir_stack_T)); ds_new->next = *stackptr; *stackptr = ds_new; - /* store directory on the stack */ + // store directory on the stack if (vim_isAbsName(dirbuf) || (*stackptr)->next == NULL - || (*stackptr && is_file_stack)) + || (*stackptr && is_file_stack)) { (*stackptr)->dirname = vim_strsave(dirbuf); - else { - /* Okay we don't have an absolute path. - * dirbuf must be a subdir of one of the directories on the stack. - * Let's search... - */ + } else { + // Okay we don't have an absolute path. + // dirbuf must be a subdir of one of the directories on the stack. + // Let's search... ds_new = (*stackptr)->next; (*stackptr)->dirname = NULL; while (ds_new) { @@ -2161,7 +2143,7 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, ds_new = ds_new->next; } - /* clean up all dirs we already left */ + // clean up all dirs we already left while ((*stackptr)->next != ds_new) { ds_ptr = (*stackptr)->next; (*stackptr)->next = (*stackptr)->next->next; @@ -2169,7 +2151,7 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, xfree(ds_ptr); } - /* Nothing found -> it must be on top level */ + // Nothing found -> it must be on top level if (ds_new == NULL) { xfree((*stackptr)->dirname); (*stackptr)->dirname = vim_strsave(dirbuf); @@ -2187,18 +2169,16 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, } -/* - * pop dirbuf from the directory stack and return previous directory or NULL if - * stack is empty - */ +// pop dirbuf from the directory stack and return previous directory or NULL if +// stack is empty static char_u *qf_pop_dir(struct dir_stack_T **stackptr) { struct dir_stack_T *ds_ptr; - /* TODO: Should we check if dirbuf is the directory on top of the stack? - * What to do if it isn't? */ + // TODO(vim): Should we check if dirbuf is the directory on top of the stack? + // What to do if it isn't? - /* pop top element and free it */ + // pop top element and free it if (*stackptr != NULL) { ds_ptr = *stackptr; *stackptr = (*stackptr)->next; @@ -2206,13 +2186,11 @@ static char_u *qf_pop_dir(struct dir_stack_T **stackptr) xfree(ds_ptr); } - /* return NEW top element as current dir or NULL if stack is empty*/ + // return NEW top element as current dir or NULL if stack is empty return *stackptr ? (*stackptr)->dirname : NULL; } -/* - * clean up directory stack - */ +// clean up directory stack static void qf_clean_dir_stack(struct dir_stack_T **stackptr) { struct dir_stack_T *ds_ptr; @@ -2887,10 +2865,8 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit) } } - /* - * If there is a file name, - * read the wanted file if needed, and check autowrite etc. - */ + // If there is a file name, + // read the wanted file if needed, and check autowrite etc. old_curbuf = curbuf; old_lnum = curwin->w_cursor.lnum; @@ -2938,8 +2914,8 @@ theend: qfl->qf_index = qf_index; } if (p_swb != old_swb && opened_window) { - /* Restore old 'switchbuf' value, but not when an autocommand or - * modeline has changed the value. */ + // Restore old 'switchbuf' value, but not when an autocommand or + // modeline has changed the value. if (p_swb == empty_option) { p_swb = old_swb; swb_flags = old_swb_flags; @@ -3038,10 +3014,8 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) ui_flush(); // show one line at a time } -/* - * ":clist": list all errors - * ":llist": list all locations - */ +// ":clist": list all errors +// ":llist": list all locations void qf_list(exarg_T *eap) { qf_list_T *qfl; @@ -3116,10 +3090,8 @@ void qf_list(exarg_T *eap) } } -/* - * Remove newlines and leading whitespace from an error message. - * Put the result in "buf[bufsize]". - */ +// Remove newlines and leading whitespace from an error message. +// Put the result in "buf[bufsize]". static void qf_fmt_text(const char_u *restrict text, char_u *restrict buf, int bufsize) FUNC_ATTR_NONNULL_ALL @@ -3277,9 +3249,7 @@ static void qf_free(qf_list_T *qfl) qfl->qf_changedtick = 0L; } -/* - * qf_mark_adjust: adjust marks - */ +// qf_mark_adjust: adjust marks bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after) { @@ -3321,21 +3291,19 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, return found_one; } -/* - * Make a nice message out of the error character and the error number: - * char number message - * e or E 0 " error" - * w or W 0 " warning" - * i or I 0 " info" - * 0 0 "" - * other 0 " c" - * e or E n " error n" - * w or W n " warning n" - * i or I n " info n" - * 0 n " error n" - * other n " c n" - * 1 x "" :helpgrep - */ +// Make a nice message out of the error character and the error number: +// char number message +// e or E 0 " error" +// w or W 0 " warning" +// i or I 0 " info" +// 0 0 "" +// other 0 " c" +// e or E n " error n" +// w or W n " warning n" +// i or I n " info n" +// 0 n " error n" +// other n " c n" +// 1 x "" :helpgrep static char_u *qf_types(int c, int nr) { static char_u buf[20]; @@ -3396,12 +3364,10 @@ void qf_view_result(bool split) do_cmdline_cmd((IS_LL_WINDOW(curwin) ? ".ll" : ".cc")); } -/* - * ":cwindow": open the quickfix window if we have errors to display, - * close it if not. - * ":lwindow": open the location list window if we have locations to display, - * close it if not. - */ +// ":cwindow": open the quickfix window if we have errors to display, +// close it if not. +// ":lwindow": open the location list window if we have locations to display, +// close it if not. void ex_cwindow(exarg_T *eap) { qf_info_T *qi; @@ -3414,14 +3380,12 @@ void ex_cwindow(exarg_T *eap) qfl = qf_get_curlist(qi); - /* Look for an existing quickfix window. */ + // Look for an existing quickfix window. win = qf_find_win(qi); - /* - * If a quickfix window is open but we have no errors to display, - * close the window. If a quickfix window is not open, then open - * it if we have errors; otherwise, leave it closed. - */ + // If a quickfix window is open but we have no errors to display, + // close the window. If a quickfix window is not open, then open + // it if we have errors; otherwise, leave it closed. if (qf_stack_empty(qi) || qfl->qf_nonevalid || qf_list_empty(qf_get_curlist(qi))) { @@ -3433,10 +3397,8 @@ void ex_cwindow(exarg_T *eap) } } -/* - * ":cclose": close the window showing the list of errors. - * ":lclose": close the window showing the location list - */ +// ":cclose": close the window showing the list of errors. +// ":lclose": close the window showing the location list void ex_cclose(exarg_T *eap) { win_T *win = NULL; @@ -3446,7 +3408,7 @@ void ex_cclose(exarg_T *eap) return; } - /* Find existing quickfix window and close it. */ + // Find existing quickfix window and close it. win = qf_find_win(qi); if (win != NULL) { win_close(win, false); @@ -3642,38 +3604,32 @@ void ex_cbottom(exarg_T *eap) } } -/* - * Return the number of the current entry (line number in the quickfix - * window). - */ +// Return the number of the current entry (line number in the quickfix +// window). linenr_T qf_current_entry(win_T *wp) { qf_info_T *qi = &ql_info; - if (IS_LL_WINDOW(wp)) - /* In the location list window, use the referenced location list */ + if (IS_LL_WINDOW(wp)) { + // In the location list window, use the referenced location list qi = wp->w_llist_ref; + } return qf_get_curlist(qi)->qf_index; } -/* - * Update the cursor position in the quickfix window to the current error. - * Return TRUE if there is a quickfix window. - */ -static int -qf_win_pos_update ( +// Update the cursor position in the quickfix window to the current error. +// Return TRUE if there is a quickfix window. +static int qf_win_pos_update( qf_info_T *qi, - int old_qf_index /* previous qf_index or zero */ + int old_qf_index // previous qf_index or zero ) { win_T *win; int qf_index = qf_get_curlist(qi)->qf_index; - /* - * Put the cursor on the current error in the quickfix window, so that - * it's viewable. - */ + // Put the cursor on the current error in the quickfix window, so that + // it's viewable. win = qf_find_win(qi); if (win != NULL && qf_index <= win->w_buffer->b_ml.ml_line_count @@ -3725,10 +3681,8 @@ static win_T *qf_find_win(const qf_info_T *qi) return NULL; } -/* - * Find a quickfix buffer. - * Searches in windows opened in all the tabs. - */ +// Find a quickfix buffer. +// Searches in windows opened in all the tabs. static buf_T *qf_find_buf(const qf_info_T *qi) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { @@ -3754,16 +3708,14 @@ static void qf_update_win_titlevar(qf_info_T *qi) } } -/* - * Find the quickfix buffer. If it exists, update the contents. - */ +// Find the quickfix buffer. If it exists, update the contents. static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { buf_T *buf; win_T *win; aco_save_T aco; - /* Check if a buffer for the quickfix list exists. Update it. */ + // Check if a buffer for the quickfix list exists. Update it. buf = qf_find_buf(qi); if (buf != NULL) { linenr_T old_line_count = buf->b_ml.ml_line_count; @@ -3936,7 +3888,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last) redraw_curbuf_later(NOT_VALID); } - /* Restore KeyTyped, setting 'filetype' may reset it. */ + // Restore KeyTyped, setting 'filetype' may reset it. KeyTyped = old_KeyTyped; } @@ -3990,9 +3942,7 @@ static void qf_jump_first(qf_info_T *qi, unsigned save_qfid, int forceit) } } -/* - * Return TRUE when using ":vimgrep" for ":grep". - */ +// Return TRUE when using ":vimgrep" for ":grep". int grep_internal(cmdidx_T cmdidx) { return (cmdidx == CMD_grep @@ -4055,9 +4005,7 @@ static char *make_get_fullcmd(const char_u *makecmd, const char_u *fname) return cmd; } -/* - * Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd" - */ +// Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd" void ex_make(exarg_T *eap) { char_u *fname; @@ -4128,11 +4076,9 @@ cleanup: xfree(cmd); } -/* - * Return the name for the errorfile, in allocated memory. - * Find a new unique name when 'makeef' contains "##". - * Returns NULL for error. - */ +// Return the name for the errorfile, in allocated memory. +// Find a new unique name when 'makeef' contains "##". +// Returns NULL for error. static char_u *get_mef_name(void) { char_u *p; @@ -4154,7 +4100,7 @@ static char_u *get_mef_name(void) if (*p == NUL) return vim_strsave(p_mef); - /* Keep trying until the name doesn't exist yet. */ + // Keep trying until the name doesn't exist yet. for (;; ) { if (start == -1) { start = (int)os_get_pid(); @@ -4703,10 +4649,8 @@ static char_u * cfile_get_auname(cmdidx_T cmdidx) } -/* - * ":cfile"/":cgetfile"/":caddfile" commands. - * ":lfile"/":lgetfile"/":laddfile" commands. - */ +// ":cfile"/":cgetfile"/":caddfile" commands. +// ":lfile"/":lgetfile"/":laddfile" commands. void ex_cfile(exarg_T *eap) { win_T *wp = NULL; @@ -4947,12 +4891,10 @@ static void vgr_jump_to_match(qf_info_T *qi, int forceit, int *redraw_for_dummy, } } -/* - * ":vimgrep {pattern} file(s)" - * ":vimgrepadd {pattern} file(s)" - * ":lvimgrep {pattern} file(s)" - * ":lvimgrepadd {pattern} file(s)" - */ +// ":vimgrep {pattern} file(s)" +// ":vimgrepadd {pattern} file(s)" +// ":lvimgrep {pattern} file(s)" +// ":lvimgrepadd {pattern} file(s)" void ex_vimgrep(exarg_T *eap) { regmmatch_T regmatch; @@ -4994,7 +4936,7 @@ void ex_vimgrep(exarg_T *eap) else tomatch = MAXLNUM; - /* Get the search pattern: either white-separated or enclosed in // */ + // Get the search pattern: either white-separated or enclosed in // regmatch.regprog = NULL; char_u *title = vim_strsave(qf_cmdtitle(*eap->cmdlinep)); p = skip_vimgrep_pat(eap->arg, &s, &flags); @@ -5021,9 +4963,10 @@ void ex_vimgrep(exarg_T *eap) qf_new_list(qi, title); } - /* parse the list of arguments */ - if (get_arglist_exp(p, &fcount, &fnames, true) == FAIL) + // parse the list of arguments + if (get_arglist_exp(p, &fcount, &fnames, true) == FAIL) { goto theend; + } if (fcount == 0) { EMSG(_(e_nomatch)); goto theend; @@ -5032,8 +4975,8 @@ void ex_vimgrep(exarg_T *eap) dirname_start = xmalloc(MAXPATHL); dirname_now = xmalloc(MAXPATHL); - /* Remember the current directory, because a BufRead autocommand that does - * ":lcd %:p:h" changes the meaning of short path names. */ + // Remember the current directory, because a BufRead autocommand that does + // ":lcd %:p:h" changes the meaning of short path names. os_dirname(dirname_start, MAXPATHL); incr_quickfix_busy(); @@ -5046,15 +4989,15 @@ void ex_vimgrep(exarg_T *eap) for (fi = 0; fi < fcount && !got_int && tomatch > 0; fi++) { fname = path_try_shorten_fname(fnames[fi]); if (time(NULL) > seconds) { - /* Display the file name every second or so, show the user we are - * working on it. */ + // Display the file name every second or so, show the user we are + // working on it. seconds = time(NULL); vgr_display_fname(fname); } buf = buflist_findname_exp(fnames[fi]); if (buf == NULL || buf->b_ml.ml_mfp == NULL) { - /* Remember that a buffer with this name already exists. */ + // Remember that a buffer with this name already exists. duplicate_name = (buf != NULL); using_dummy = TRUE; redraw_for_dummy = TRUE; @@ -5087,20 +5030,20 @@ void ex_vimgrep(exarg_T *eap) if (found_match && first_match_buf == NULL) first_match_buf = buf; if (duplicate_name) { - /* Never keep a dummy buffer if there is another buffer - * with the same name. */ + // Never keep a dummy buffer if there is another buffer + // with the same name. wipe_dummy_buffer(buf, dirname_start); buf = NULL; } else if (!cmdmod.hide - || buf->b_p_bh[0] == 'u' /* "unload" */ - || buf->b_p_bh[0] == 'w' /* "wipe" */ - || buf->b_p_bh[0] == 'd') { /* "delete" */ - /* When no match was found we don't need to remember the - * buffer, wipe it out. If there was a match and it - * wasn't the first one or we won't jump there: only - * unload the buffer. - * Ignore 'hidden' here, because it may lead to having too - * many swap files. */ + || buf->b_p_bh[0] == 'u' // "unload" + || buf->b_p_bh[0] == 'w' // "wipe" + || buf->b_p_bh[0] == 'd') { // "delete" + // When no match was found we don't need to remember the + // buffer, wipe it out. If there was a match and it + // wasn't the first one or we won't jump there: only + // unload the buffer. + // Ignore 'hidden' here, because it may lead to having too + // many swap files. if (!found_match) { wipe_dummy_buffer(buf, dirname_start); buf = NULL; @@ -5124,10 +5067,10 @@ void ex_vimgrep(exarg_T *eap) target_dir = vim_strsave(dirname_now); } - /* The buffer is still loaded, the Filetype autocommands - * need to be done now, in that buffer. And the modelines - * need to be done (again). But not the window-local - * options! */ + // The buffer is still loaded, the Filetype autocommands + // need to be done now, in that buffer. And the modelines + // need to be done (again). But not the window-local + // options! aucmd_prepbuf(&aco, buf); apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, TRUE, buf); @@ -5171,8 +5114,8 @@ void ex_vimgrep(exarg_T *eap) decr_quickfix_busy(); - /* If we loaded a dummy buffer into the current window, the autocommands - * may have messed up things, need to redraw and recompute folds. */ + // If we loaded a dummy buffer into the current window, the autocommands + // may have messed up things, need to redraw and recompute folds. if (redraw_for_dummy) { foldUpdateAll(curwin); } @@ -5185,18 +5128,16 @@ theend: vim_regfree(regmatch.regprog); } -/* - * Restore current working directory to "dirname_start" if they differ, taking - * into account whether it is set locally or globally. - */ +// Restore current working directory to "dirname_start" if they differ, taking +// into account whether it is set locally or globally. static void restore_start_dir(char_u *dirname_start) { char_u *dirname_now = xmalloc(MAXPATHL); os_dirname(dirname_now, MAXPATHL); if (STRCMP(dirname_start, dirname_now) != 0) { - /* If the directory has changed, change it back by building up an - * appropriate ex command and executing it. */ + // If the directory has changed, change it back by building up an + // appropriate ex command and executing it. exarg_T ea = { .arg = dirname_start, .cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd, @@ -5206,23 +5147,21 @@ static void restore_start_dir(char_u *dirname_start) xfree(dirname_now); } -/* - * Load file "fname" into a dummy buffer and return the buffer pointer, - * placing the directory resulting from the buffer load into the - * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller - * prior to calling this function. Restores directory to "dirname_start" prior - * to returning, if autocmds or the 'autochdir' option have changed it. - * - * If creating the dummy buffer does not fail, must call unload_dummy_buffer() - * or wipe_dummy_buffer() later! - * - * Returns NULL if it fails. - */ +// Load file "fname" into a dummy buffer and return the buffer pointer, +// placing the directory resulting from the buffer load into the +// "resulting_dir" pointer. "resulting_dir" must be allocated by the caller +// prior to calling this function. Restores directory to "dirname_start" prior +// to returning, if autocmds or the 'autochdir' option have changed it. +// +// If creating the dummy buffer does not fail, must call unload_dummy_buffer() +// or wipe_dummy_buffer() later! +// +// Returns NULL if it fails. static buf_T * load_dummy_buffer ( char_u *fname, - char_u *dirname_start, /* in: old directory */ - char_u *resulting_dir /* out: new directory */ + char_u *dirname_start, // in: old directory + char_u *resulting_dir // out: new directory ) { buf_T *newbuf; @@ -5239,24 +5178,24 @@ load_dummy_buffer ( } set_bufref(&newbufref, newbuf); - /* Init the options. */ + // Init the options. buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); - /* need to open the memfile before putting the buffer in a window */ + // need to open the memfile before putting the buffer in a window if (ml_open(newbuf) == OK) { // Make sure this buffer isn't wiped out by autocommands. newbuf->b_locked++; // set curwin/curbuf to buf and save a few things aucmd_prepbuf(&aco, newbuf); - /* Need to set the filename for autocommands. */ - (void)setfname(curbuf, fname, NULL, FALSE); + // Need to set the filename for autocommands. + (void)setfname(curbuf, fname, NULL, false); - /* Create swap file now to avoid the ATTENTION message. */ - check_need_swap(TRUE); + // Create swap file now to avoid the ATTENTION message. + check_need_swap(true); - /* Remove the "dummy" flag, otherwise autocommands may not - * work. */ + // Remove the "dummy" flag, otherwise autocommands may not + // work. curbuf->b_flags &= ~BF_DUMMY; newbuf_to_wipe.br_buf = NULL; @@ -5289,11 +5228,9 @@ load_dummy_buffer ( newbuf->b_flags |= BF_DUMMY; } - /* - * When autocommands/'autochdir' option changed directory: go back. - * Let the caller know what the resulting dir was first, in case it is - * important. - */ + // When autocommands/'autochdir' option changed directory: go back. + // Let the caller know what the resulting dir was first, in case it is + // important. os_dirname(resulting_dir, MAXPATHL); restore_start_dir(dirname_start); @@ -5307,42 +5244,38 @@ load_dummy_buffer ( return newbuf; } -/* - * Wipe out the dummy buffer that load_dummy_buffer() created. Restores - * directory to "dirname_start" prior to returning, if autocmds or the - * 'autochdir' option have changed it. - */ +// Wipe out the dummy buffer that load_dummy_buffer() created. Restores +// directory to "dirname_start" prior to returning, if autocmds or the +// 'autochdir' option have changed it. static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start) { - if (curbuf != buf) { /* safety check */ + if (curbuf != buf) { // safety check cleanup_T cs; - /* Reset the error/interrupt/exception state here so that aborting() - * returns FALSE when wiping out the buffer. Otherwise it doesn't - * work when got_int is set. */ + // Reset the error/interrupt/exception state here so that aborting() + // returns FALSE when wiping out the buffer. Otherwise it doesn't + // work when got_int is set. enter_cleanup(&cs); wipe_buffer(buf, FALSE); - /* Restore the error/interrupt/exception state if not discarded by a - * new aborting error, interrupt, or uncaught exception. */ + // Restore the error/interrupt/exception state if not discarded by a + // new aborting error, interrupt, or uncaught exception. leave_cleanup(&cs); - /* When autocommands/'autochdir' option changed directory: go back. */ + // When autocommands/'autochdir' option changed directory: go back. restore_start_dir(dirname_start); } } -/* - * Unload the dummy buffer that load_dummy_buffer() created. Restores - * directory to "dirname_start" prior to returning, if autocmds or the - * 'autochdir' option have changed it. - */ +// Unload the dummy buffer that load_dummy_buffer() created. Restores +// directory to "dirname_start" prior to returning, if autocmds or the +// 'autochdir' option have changed it. static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start) { - if (curbuf != buf) { /* safety check */ - close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); + if (curbuf != buf) { // safety check + close_buffer(NULL, buf, DOBUF_UNLOAD, false); - /* When autocommands/'autochdir' option changed directory: go back. */ + // When autocommands/'autochdir' option changed directory: go back. restore_start_dir(dirname_start); } } @@ -6297,14 +6230,12 @@ static int cbuffer_process_args(exarg_T *eap, return OK; } -/* - * ":[range]cbuffer [bufnr]" command. - * ":[range]caddbuffer [bufnr]" command. - * ":[range]cgetbuffer [bufnr]" command. - * ":[range]lbuffer [bufnr]" command. - * ":[range]laddbuffer [bufnr]" command. - * ":[range]lgetbuffer [bufnr]" command. - */ +// ":[range]cbuffer [bufnr]" command. +// ":[range]caddbuffer [bufnr]" command. +// ":[range]cgetbuffer [bufnr]" command. +// ":[range]lbuffer [bufnr]" command. +// ":[range]laddbuffer [bufnr]" command. +// ":[range]lgetbuffer [bufnr]" command. void ex_cbuffer(exarg_T *eap) { buf_T *buf = NULL; @@ -6405,8 +6336,8 @@ void ex_cexpr(exarg_T *eap) qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp); - /* Evaluate the expression. When the result is a string or a list we can - * use it to fill the errorlist. */ + // Evaluate the expression. When the result is a string or a list we can + // use it to fill the errorlist. typval_T tv; if (eval0(eap->arg, &tv, NULL, true) != FAIL) { if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL) diff --git a/src/nvim/search.c b/src/nvim/search.c index a298f7333e..5e32715e49 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -3777,30 +3777,31 @@ find_prev_quote( return col_start; } -/* - * Find quote under the cursor, cursor at end. - * Returns TRUE if found, else FALSE. - */ -int -current_quote( +// Find quote under the cursor, cursor at end. +// Returns true if found, else false. +bool current_quote( oparg_T *oap, long count, - int include, /* TRUE == include quote char */ - int quotechar /* Quote character */ + bool include, // true == include quote char + int quotechar // Quote character ) + FUNC_ATTR_NONNULL_ALL { char_u *line = get_cursor_line_ptr(); int col_end; int col_start = curwin->w_cursor.col; bool inclusive = false; - int vis_empty = true; // Visual selection <= 1 char - int vis_bef_curs = false; // Visual starts before cursor - int inside_quotes = false; // Looks like "i'" done before - int selected_quote = false; // Has quote inside selection + bool vis_empty = true; // Visual selection <= 1 char + bool vis_bef_curs = false; // Visual starts before cursor + bool did_exclusive_adj = false; // adjusted pos for 'selection' + bool inside_quotes = false; // Looks like "i'" done before + bool selected_quote = false; // Has quote inside selection int i; - int restore_vis_bef = false; // resotre VIsual on abort + bool restore_vis_bef = false; // resotre VIsual on abort - // Correct cursor when 'selection' is "exclusive". + // When 'selection' is "exclusive" move the cursor to where it would be + // with 'selection' "inclusive", so that the logic is the same for both. + // The cursor then is moved forward after adjusting the area. if (VIsual_active) { // this only works within one line if (VIsual.lnum != curwin->w_cursor.lnum) { @@ -3810,6 +3811,14 @@ current_quote( vis_bef_curs = lt(VIsual, curwin->w_cursor); vis_empty = equalpos(VIsual, curwin->w_cursor); if (*p_sel == 'e') { + if (vis_bef_curs) { + dec_cursor(); + did_exclusive_adj = true; + } else if (!vis_empty) { + dec(&VIsual); + did_exclusive_adj = true; + } + vis_empty = equalpos(VIsual, curwin->w_cursor); if (!vis_bef_curs && !vis_empty) { // VIsual needs to be start of Visual selection. pos_T t = curwin->w_cursor; @@ -3819,8 +3828,6 @@ current_quote( vis_bef_curs = true; restore_vis_bef = true; } - dec_cursor(); - vis_empty = equalpos(VIsual, curwin->w_cursor); } } @@ -3846,7 +3853,7 @@ current_quote( /* Find out if we have a quote in the selection. */ while (i <= col_end) if (line[i++] == quotechar) { - selected_quote = TRUE; + selected_quote = true; break; } } @@ -3935,8 +3942,8 @@ current_quote( } } - /* When "include" is TRUE, include spaces after closing quote or before - * the starting quote. */ + // When "include" is true, include spaces after closing quote or before + // the starting quote. if (include) { if (ascii_iswhite(line[col_end + 1])) while (ascii_iswhite(line[col_end + 1])) @@ -3982,9 +3989,10 @@ current_quote( inclusive = true; if (VIsual_active) { if (vis_empty || vis_bef_curs) { - /* decrement cursor when 'selection' is not exclusive */ - if (*p_sel != 'e') + // decrement cursor when 'selection' is not exclusive + if (*p_sel != 'e') { dec_cursor(); + } } else { /* Cursor is at start of Visual area. Set the end of the Visual * area when it was just inside quotes or it didn't end at a @@ -4008,11 +4016,13 @@ current_quote( oap->inclusive = inclusive; } - return OK; + return true; abort_search: if (VIsual_active && *p_sel == 'e') { - inc_cursor(); + if (did_exclusive_adj) { + inc_cursor(); + } if (restore_vis_bef) { pos_T t = curwin->w_cursor; diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 9e8c05fb1e..3629b37c32 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -1194,12 +1194,10 @@ static int find_tagfunc_tags( taglist = rettv.vval.v_list; TV_LIST_ITER_CONST(taglist, li, { - char_u *mfp; char_u *res_name; char_u *res_fname; char_u *res_cmd; char_u *res_kind; - int len; int has_extra = 0; int name_only = flags & TAG_NAMES; @@ -1208,7 +1206,7 @@ static int find_tagfunc_tags( break; } - len = 2; + size_t len = 2; res_name = NULL; res_fname = NULL; res_cmd = NULL; @@ -1254,15 +1252,7 @@ static int find_tagfunc_tags( break; } - if (name_only) { - mfp = vim_strsave(res_name); - } else { - mfp = (char_u *)xmalloc((int)sizeof(char_u) + len + 1); - } - - if (mfp == NULL) { - continue; - } + char_u *const mfp = name_only ? vim_strsave(res_name) : xmalloc(len + 2); if (!name_only) { char_u *p = mfp; @@ -1669,12 +1659,9 @@ find_tags( break; /* End the binary search without a match. */ else search_info.curr_offset = offset; - } - /* - * Skipping back (after a match during binary search). - */ - else if (state == TS_SKIP_BACK) { - search_info.curr_offset -= LSIZE * 2; + } else if (state == TS_SKIP_BACK) { + // Skipping back (after a match during binary search). + search_info.curr_offset -= lbuf_size * 2; if (search_info.curr_offset < 0) { search_info.curr_offset = 0; rewind(fp); @@ -1690,7 +1677,7 @@ find_tags( /* Adjust the search file offset to the correct position */ search_info.curr_offset_used = search_info.curr_offset; vim_fseek(fp, search_info.curr_offset, SEEK_SET); - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); if (!eof && search_info.curr_offset != 0) { /* The explicit cast is to work around a bug in gcc 3.4.2 * (repeated below). */ @@ -1700,12 +1687,12 @@ find_tags( vim_fseek(fp, search_info.low_offset, SEEK_SET); search_info.curr_offset = search_info.low_offset; } - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); } /* skip empty and blank lines */ while (!eof && vim_isblankline(lbuf)) { search_info.curr_offset = vim_ftell(fp); - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); } if (eof) { /* Hit end of file. Skip backwards. */ @@ -1721,10 +1708,9 @@ find_tags( else { /* skip empty and blank lines */ do { - if (use_cscope) - eof = cs_fgets(lbuf, LSIZE); - else - eof = vim_fgets(lbuf, LSIZE, fp); + eof = use_cscope + ? cs_fgets(lbuf, lbuf_size) + : vim_fgets(lbuf, lbuf_size, fp); } while (!eof && vim_isblankline(lbuf)); if (eof) { @@ -1849,19 +1835,14 @@ parse_line: // When the line is too long the NUL will not be in the // last-but-one byte (see vim_fgets()). // Has been reported for Mozilla JS with extremely long names. - // In that case we can't parse it and we ignore the line. - if (lbuf[LSIZE - 2] != NUL && !use_cscope) { - if (p_verbose >= 5) { - verbose_enter(); - MSG(_("Ignoring long line in tags file")); - verbose_leave(); - } - if (state != TS_LINEAR) { - // Avoid getting stuck. - linear = true; - state = TS_LINEAR; - vim_fseek(fp, search_info.low_offset, SEEK_SET); - } + // In that case we need to increase lbuf_size. + if (lbuf[lbuf_size - 2] != NUL && !use_cscope) { + lbuf_size *= 2; + xfree(lbuf); + lbuf = xmalloc(lbuf_size); + // this will try the same thing again, make sure the offset is + // different + search_info.curr_offset = 0; continue; } @@ -2664,6 +2645,9 @@ static int jumpto_tag( str = tagp.command; for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) { *pbuf_end++ = *str++; + if (pbuf_end - pbuf + 1 >= LSIZE) { + break; + } } *pbuf_end = NUL; diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 08353509af..1e9031e098 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -48,7 +48,8 @@ NEW_TESTS_IGNORE := $(NEW_TESTS_IN_ALOT) $(NEW_TESTS_ALOT) \ test_listlbr \ test_largefile \ -NEW_TESTS ?= $(addsuffix .res,$(sort $(filter-out $(NEW_TESTS_IGNORE),$(basename $(notdir $(wildcard test_*.vim))))) $(NEW_TESTS_ALOT)) +NEW_TESTS ?= $(sort $(filter-out $(NEW_TESTS_IGNORE),$(basename $(notdir $(wildcard test_*.vim))))) $(NEW_TESTS_ALOT) +NEW_TESTS_RES ?= $(addsuffix .res,$(NEW_TESTS)) ifdef VALGRIND_GDB @@ -112,6 +113,16 @@ fixff: -$(NVIM_PRG) $(NO_INITS) -u unix.vim "+argdo set ff=dos|upd" +q \ dotest.in +# Execute an individual new style test, e.g.: +# make test_largefile +$(NEW_TESTS): + rm -f $@.res test.log messages + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $@.res + @cat messages + @if test -f test.log; then \ + exit 1; \ + fi + RM_ON_RUN := test.out X* viminfo RM_ON_START := test.ok RUN_VIM := $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in @@ -172,7 +183,7 @@ newtests: newtestssilent cat messages && cat test.log; \ fi" -newtestssilent: $(NEW_TESTS) +newtestssilent: $(NEW_TESTS_RES) %.res: %.vim .gdbinit @echo "[OLDTEST] Running" $* diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 5c2e570adf..2d4134a644 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -297,6 +297,8 @@ let s:flaky_tests = [ \ 'Test_repeat_three()', \ 'Test_state()', \ 'Test_stop_all_in_callback()', + \ 'Test_term_mouse_double_click_to_create_tab', + \ 'Test_term_mouse_multiple_clicks_to_visually_select()', \ 'Test_terminal_composing_unicode()', \ 'Test_terminal_redir_file()', \ 'Test_terminal_tmap()', diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim index a5d83d6a25..b0b59db686 100644 --- a/src/nvim/testdir/shared.vim +++ b/src/nvim/testdir/shared.vim @@ -69,7 +69,8 @@ endfunc " Read the port number from the Xportnr file. func GetPort() let l = [] - for i in range(200) + " with 200 it sometimes failed + for i in range(400) try let l = readfile("Xportnr") catch @@ -279,11 +280,15 @@ func GetVimCommand(...) return cmd endfunc -" Get the command to run Vim, with --clean. +" Get the command to run Vim, with --clean instead of "-u NONE". func GetVimCommandClean() let cmd = GetVimCommand() let cmd = substitute(cmd, '-u NONE', '--clean', '') let cmd = substitute(cmd, '--headless', '', '') + + " Optionally run Vim under valgrind + " let cmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind ' . cmd + return cmd endfunc diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index f4f5cbca61..6fcc372591 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -476,13 +476,19 @@ func Test_shortmess_F2() call assert_match('file2', execute('bn', '')) set shortmess+=F call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) set hidden call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) set nohidden call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) call assert_true(empty(execute('bn', ''))) + " call assert_false(test_getvalue('need_fileinfo')) " Accommodate Nvim default. set shortmess-=F call assert_match('file1', execute('bn', '')) diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index e209310a05..e94bd22cea 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -241,7 +241,7 @@ func Test_sub_cmd_3() call Run_SubCmd_Tests(tests) endfunc -" Test for submatch() on :substitue. +" Test for submatch() on :substitute. func Test_sub_cmd_4() set magic& set cpo& diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index f93af76f17..fe98ef1ae2 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -449,7 +449,8 @@ func Test_tag_line_toolong() call assert_report(v:exception) catch /.*/ endtry - call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1]) + call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) + call writefile([ \ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML' \ ], 'Xtags') @@ -460,8 +461,26 @@ func Test_tag_line_toolong() call assert_report(v:exception) catch /.*/ endtry - call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1]) + call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) + + " binary search works in file with long line + call writefile([ + \ 'asdfasfd nowhere 16', + \ 'foobar Xsomewhere 3; " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567', + \ 'zasdfasfd nowhere 16', + \ ], 'Xtags') + call writefile([ + \ 'one', + \ 'two', + \ 'trhee', + \ 'four', + \ ], 'Xsomewhere') + tag foobar + call assert_equal('Xsomewhere', expand('%')) + call assert_equal(3, getcurpos()[1]) + call delete('Xtags') + call delete('Xsomewhere') set tags& let &verbose = old_vbs endfunc diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim index 448b2dc51c..b20c4df311 100644 --- a/src/nvim/testdir/test_textobjects.vim +++ b/src/nvim/testdir/test_textobjects.vim @@ -46,11 +46,18 @@ func Test_quote_selection_selection_exclusive() new call setline(1, "a 'bcde' f") set selection=exclusive + exe "norm! fdvhi'y" call assert_equal('bcde', @") + let @"='dummy' exe "norm! $gevi'y" call assert_equal('bcde', @") + + let @"='dummy' + exe "norm! 0fbhvi'y" + call assert_equal('bcde', @") + set selection&vim bw! endfunc diff --git a/src/nvim/window.c b/src/nvim/window.c index 2a7578e33c..dee36df433 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -633,6 +633,12 @@ void win_set_minimal_style(win_T *wp) xfree(wp->w_p_scl); wp->w_p_scl = (char_u *)xstrdup("auto"); } + + // colorcolumn: cleared + if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) { + xfree(wp->w_p_cc); + wp->w_p_cc = (char_u *)xstrdup(""); + } } void win_config_float(win_T *wp, FloatConfig fconfig) |