diff options
89 files changed, 666 insertions, 436 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index edda46e197..a48ebd7199 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5459,8 +5459,8 @@ A jump table for the options with a short description can be found at |Q_op|. message; also for quickfix message (e.g., ":cn") s don't give "search hit BOTTOM, continuing at TOP" or *shm-s* "search hit TOP, continuing at BOTTOM" messages; when using - the search count do not show "W" after the count message (see - S below) + the search count do not show "W" before the count message + (see |shm-S| below) t truncate file message at the start if it is too long *shm-t* to fit on the command-line, "<" will appear in the left most column; ignored in Ex mode @@ -5482,7 +5482,11 @@ A jump table for the options with a short description can be found at |Q_op|. `:silent` was used for the command; note that this also affects messages from 'autoread' reloading S do not show search count message when searching, e.g. *shm-S* - "[1/5]" + "[1/5]". When the "S" flag is not present (e.g. search count + is shown), the "search hit BOTTOM, continuing at TOP" and + "search hit TOP, continuing at BOTTOM" messages are only + indicated by a "W" (Mnemonic: Wrapped) letter before the + search count statistics. This gives you the opportunity to avoid that a change between buffers requires you to hit <Enter>, but still gives as useful a message as diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 428b7c4d4f..2eae0d27a7 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -5781,8 +5781,8 @@ vim.bo.sw = vim.bo.shiftwidth --- message; also for quickfix message (e.g., ":cn") --- s don't give "search hit BOTTOM, continuing at TOP" or *shm-s* --- "search hit TOP, continuing at BOTTOM" messages; when using ---- the search count do not show "W" after the count message (see ---- S below) +--- the search count do not show "W" before the count message +--- (see `shm-S` below) --- t truncate file message at the start if it is too long *shm-t* --- to fit on the command-line, "<" will appear in the left most --- column; ignored in Ex mode @@ -5804,7 +5804,11 @@ vim.bo.sw = vim.bo.shiftwidth --- `:silent` was used for the command; note that this also --- affects messages from 'autoread' reloading --- S do not show search count message when searching, e.g. *shm-S* ---- "[1/5]" +--- "[1/5]". When the "S" flag is not present (e.g. search count +--- is shown), the "search hit BOTTOM, continuing at TOP" and +--- "search hit TOP, continuing at BOTTOM" messages are only +--- indicated by a "W" (Mnemonic: Wrapped) letter before the +--- search count statistics. --- --- This gives you the opportunity to avoid that a change between buffers --- requires you to hit <Enter>, but still gives as useful a message as diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 39c0c5fa29..f8e17ae2f0 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -153,7 +153,8 @@ local function get_completion_word(item) return item.label end elseif item.textEdit then - return item.textEdit.newText + local word = item.textEdit.newText + return word:match('^(%S*)') or word elseif item.insertText and item.insertText ~= '' then return item.insertText end @@ -201,6 +202,24 @@ local function get_items(result) end end +---@param item lsp.CompletionItem +---@return string +local function get_doc(item) + local doc = item.documentation + if not doc then + return '' + end + if type(doc) == 'string' then + return doc + end + if type(doc) == 'table' and type(doc.value) == 'string' then + return doc.value + end + + vim.notify('invalid documentation value: ' .. vim.inspect(doc), vim.log.levels.WARN) + return '' +end + --- Turns the result of a `textDocument/completion` request into vim-compatible --- |complete-items|. --- @@ -216,58 +235,48 @@ function M._lsp_to_complete_items(result, prefix, client_id) return {} end - if prefix ~= '' then - ---@param item lsp.CompletionItem - local function match_prefix(item) - if item.filterText then - return next(vim.fn.matchfuzzy({ item.filterText }, prefix)) - end - return true + local matches = prefix == '' and function() + return true + end or function(item) + if item.filterText then + return next(vim.fn.matchfuzzy({ item.filterText }, prefix)) end - - items = vim.tbl_filter(match_prefix, items) --[[@as lsp.CompletionItem[]|]] + return true end - table.sort(items, function(a, b) - return (a.sortText or a.label) < (b.sortText or b.label) - end) - - local matches = {} + local candidates = {} for _, item in ipairs(items) do - local info = '' - local documentation = item.documentation - if documentation then - if type(documentation) == 'string' and documentation ~= '' then - info = documentation - elseif type(documentation) == 'table' and type(documentation.value) == 'string' then - info = documentation.value - else - vim.notify( - ('invalid documentation value %s'):format(vim.inspect(documentation)), - vim.log.levels.WARN - ) - end - end - local word = get_completion_word(item) - table.insert(matches, { - word = word, - abbr = item.label, - kind = protocol.CompletionItemKind[item.kind] or 'Unknown', - menu = item.detail or '', - info = #info > 0 and info or '', - icase = 1, - dup = 1, - empty = 1, - user_data = { - nvim = { - lsp = { - completion_item = item, - client_id = client_id, + if matches(item) then + local word = get_completion_word(item) + table.insert(candidates, { + word = word, + abbr = item.label, + kind = protocol.CompletionItemKind[item.kind] or 'Unknown', + menu = item.detail or '', + info = get_doc(item), + icase = 1, + dup = 1, + empty = 1, + user_data = { + nvim = { + lsp = { + completion_item = item, + client_id = client_id, + }, }, }, - }, - }) + }) + end end - return matches + ---@diagnostic disable-next-line: no-unknown + table.sort(candidates, function(a, b) + ---@type lsp.CompletionItem + local itema = a.user_data.nvim.lsp.completion_item + ---@type lsp.CompletionItem + local itemb = b.user_data.nvim.lsp.completion_item + return (itema.sortText or itema.label) < (itemb.sortText or itemb.label) + end) + + return candidates end --- @param lnum integer 0-indexed @@ -340,78 +349,6 @@ function M._convert_results( return matches, server_start_boundary end ---- Implements 'omnifunc' compatible LSP completion. ---- ---- @see |complete-functions| ---- @see |complete-items| ---- @see |CompleteDone| ---- ---- @param findstart integer 0 or 1, decides behavior ---- @param base integer findstart=0, text to match against ---- ---- @return integer|table Decided by {findstart}: ---- - findstart=0: column where the completion starts, or -2 or -3 ---- - findstart=1: list of matches (actually just calls |complete()|) -function M._omnifunc(findstart, base) - vim.lsp.log.debug('omnifunc.findstart', { findstart = findstart, base = base }) - assert(base) -- silence luals - local bufnr = api.nvim_get_current_buf() - local clients = lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_completion }) - local remaining = #clients - if remaining == 0 then - return findstart == 1 and -1 or {} - end - - local win = api.nvim_get_current_win() - local cursor = api.nvim_win_get_cursor(win) - local lnum = cursor[1] - 1 - local cursor_col = cursor[2] - local line = api.nvim_get_current_line() - local line_to_cursor = line:sub(1, cursor_col) - local client_start_boundary = vim.fn.match(line_to_cursor, '\\k*$') --[[@as integer]] - local server_start_boundary = nil - local items = {} - - local function on_done() - local mode = api.nvim_get_mode()['mode'] - if mode == 'i' or mode == 'ic' then - vim.fn.complete((server_start_boundary or client_start_boundary) + 1, items) - end - end - - local util = vim.lsp.util - for _, client in ipairs(clients) do - local params = util.make_position_params(win, client.offset_encoding) - client.request(ms.textDocument_completion, params, function(err, result) - if err then - lsp.log.warn(err.message) - end - if result and vim.fn.mode() == 'i' then - local matches - matches, server_start_boundary = M._convert_results( - line, - lnum, - cursor_col, - client.id, - client_start_boundary, - server_start_boundary, - result, - client.offset_encoding - ) - vim.list_extend(items, matches) - end - remaining = remaining - 1 - if remaining == 0 then - vim.schedule(on_done) - end - end, bufnr) - end - - -- Return -2 to signal that we should continue completion so that we can - -- async complete. - return -2 -end - --- @param clients table<integer, vim.lsp.Client> --- @param bufnr integer --- @param win integer @@ -447,6 +384,64 @@ local function request(clients, bufnr, win, callback) end end +local function trigger(bufnr, clients) + reset_timer() + Context:cancel_pending() + + local win = api.nvim_get_current_win() + local cursor_row, cursor_col = unpack(api.nvim_win_get_cursor(win)) --- @type integer, integer + local line = api.nvim_get_current_line() + local line_to_cursor = line:sub(1, cursor_col) + local word_boundary = vim.fn.match(line_to_cursor, '\\k*$') + local start_time = vim.uv.hrtime() + Context.last_request_time = start_time + + local cancel_request = request(clients, bufnr, win, function(responses) + local end_time = vim.uv.hrtime() + rtt_ms = compute_new_average((end_time - start_time) * ns_to_ms) + + Context.pending_requests = {} + Context.isIncomplete = false + + local row_changed = api.nvim_win_get_cursor(win)[1] ~= cursor_row + local mode = api.nvim_get_mode().mode + if row_changed or not (mode == 'i' or mode == 'ic') then + return + end + + local matches = {} + local server_start_boundary --- @type integer? + for client_id, response in pairs(responses) do + if response.err then + vim.notify_once(response.err.message, vim.log.levels.warn) + end + + local result = response.result + if result then + Context.isIncomplete = Context.isIncomplete or result.isIncomplete + local client = lsp.get_client_by_id(client_id) + local encoding = client and client.offset_encoding or 'utf-16' + local client_matches + client_matches, server_start_boundary = M._convert_results( + line, + cursor_row - 1, + cursor_col, + client_id, + word_boundary, + nil, + result, + encoding + ) + vim.list_extend(matches, client_matches) + end + end + local start_col = (server_start_boundary or word_boundary) + 1 + vim.fn.complete(start_col, matches) + end) + + table.insert(Context.pending_requests, cancel_request) +end + --- @param handle vim.lsp.completion.BufHandle local function on_insert_char_pre(handle) if tonumber(vim.fn.pumvisible()) == 1 then @@ -581,8 +576,10 @@ end ---@param bufnr integer ---@param opts vim.lsp.completion.BufferOpts local function enable_completions(client_id, bufnr, opts) - if not buf_handles[bufnr] then - buf_handles[bufnr] = { clients = {}, triggers = {} } + local buf_handle = buf_handles[bufnr] + if not buf_handle then + buf_handle = { clients = {}, triggers = {} } + buf_handles[bufnr] = buf_handle -- Attach to buffer events. api.nvim_buf_attach(bufnr, false, { @@ -623,12 +620,12 @@ local function enable_completions(client_id, bufnr, opts) end end - if not buf_handles[bufnr].clients[client_id] then + if not buf_handle.clients[client_id] then local client = lsp.get_client_by_id(client_id) assert(client, 'invalid client ID') -- Add the new client to the buffer's clients. - buf_handles[bufnr].clients[client_id] = client + buf_handle.clients[client_id] = client -- Add the new client to the clients that should be triggered by its trigger characters. --- @type string[] @@ -638,10 +635,10 @@ local function enable_completions(client_id, bufnr, opts) 'triggerCharacters' ) or {} for _, char in ipairs(triggers) do - local clients_for_trigger = buf_handles[bufnr].triggers[char] + local clients_for_trigger = buf_handle.triggers[char] if not clients_for_trigger then clients_for_trigger = {} - buf_handles[bufnr].triggers[char] = clients_for_trigger + buf_handle.triggers[char] = clients_for_trigger end local client_exists = vim.iter(clients_for_trigger):any(function(c) return c.id == client_id @@ -693,63 +690,38 @@ end --- Trigger LSP completion in the current buffer. function M.trigger() - reset_timer() - Context:cancel_pending() - - local win = api.nvim_get_current_win() local bufnr = api.nvim_get_current_buf() - local cursor_row, cursor_col = unpack(api.nvim_win_get_cursor(win)) --- @type integer, integer - local line = api.nvim_get_current_line() - local line_to_cursor = line:sub(1, cursor_col) local clients = (buf_handles[bufnr] or {}).clients or {} - local word_boundary = vim.fn.match(line_to_cursor, '\\k*$') - local start_time = vim.uv.hrtime() - Context.last_request_time = start_time - - local cancel_request = request(clients, bufnr, win, function(responses) - local end_time = vim.uv.hrtime() - rtt_ms = compute_new_average((end_time - start_time) * ns_to_ms) - - Context.pending_requests = {} - Context.isIncomplete = false - - local row_changed = api.nvim_win_get_cursor(win)[1] ~= cursor_row - local mode = api.nvim_get_mode().mode - if row_changed or not (mode == 'i' or mode == 'ic') then - return - end + trigger(bufnr, clients) +end - local matches = {} - local server_start_boundary --- @type integer? - for client_id, response in pairs(responses) do - if response.err then - vim.notify_once(response.err.message, vim.log.levels.warn) - end +--- Implements 'omnifunc' compatible LSP completion. +--- +--- @see |complete-functions| +--- @see |complete-items| +--- @see |CompleteDone| +--- +--- @param findstart integer 0 or 1, decides behavior +--- @param base integer findstart=0, text to match against +--- +--- @return integer|table Decided by {findstart}: +--- - findstart=0: column where the completion starts, or -2 or -3 +--- - findstart=1: list of matches (actually just calls |complete()|) +function M._omnifunc(findstart, base) + vim.lsp.log.debug('omnifunc.findstart', { findstart = findstart, base = base }) + assert(base) -- silence luals + local bufnr = api.nvim_get_current_buf() + local clients = lsp.get_clients({ bufnr = bufnr, method = ms.textDocument_completion }) + local remaining = #clients + if remaining == 0 then + return findstart == 1 and -1 or {} + end - local result = response.result - if result then - Context.isIncomplete = Context.isIncomplete or result.isIncomplete - local client = lsp.get_client_by_id(client_id) - local encoding = client and client.offset_encoding or 'utf-16' - local client_matches - client_matches, server_start_boundary = M._convert_results( - line, - cursor_row - 1, - cursor_col, - client_id, - word_boundary, - nil, - result, - encoding - ) - vim.list_extend(matches, client_matches) - end - end - local start_col = (server_start_boundary or word_boundary) + 1 - vim.fn.complete(start_col, matches) - end) + trigger(bufnr, clients) - table.insert(Context.pending_requests, cancel_request) + -- Return -2 to signal that we should continue completion so that we can + -- async complete. + return -2 end return M diff --git a/scripts/luacats_grammar.lua b/scripts/luacats_grammar.lua index 6742eab5e9..9360eb9417 100644 --- a/scripts/luacats_grammar.lua +++ b/scripts/luacats_grammar.lua @@ -180,7 +180,7 @@ local grammar = P { fun_param = lname * opt(colon * v.ltype), ty_fun = Pf('fun') * paren(comma(lname * opt(colon * v.ltype))) * opt(colon * comma1(v.ltype)), ty_generic = P('`') * letter * P('`'), - ty_tuple = Pf('[') * comma(v.ty_opt) * fill * P(']'), + ty_tuple = Pf('[') * comma(v.ltype) * fill * P(']'), } return grammar --[[@as nvim.luacats.grammar]] diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ae8f73fa2c..26dc223948 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -28,6 +28,7 @@ #include "nvim/cursor.h" #include "nvim/decoration.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 70235d8db6..f0b90d8512 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -17,6 +17,7 @@ #include "nvim/decoration.h" #include "nvim/decoration_defs.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/window.h" #include "nvim/extmark_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 54a19513db..92dc9dc7e3 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -13,6 +13,7 @@ #include "nvim/buffer_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/window.h" #include "nvim/ex_docmd.h" #include "nvim/gettext_defs.h" diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index 4d493c9d03..700bfc1655 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -13,6 +13,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/window.h" diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index c5d81d4cd2..e5872fcc76 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -15,6 +15,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 39d0d24d47..5d0cd66133 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -43,6 +43,7 @@ #include "nvim/diff.h" #include "nvim/digraph.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c index 27de03954a..6fbcb2dbb8 100644 --- a/src/nvim/bufwrite.c +++ b/src/nvim/bufwrite.c @@ -18,6 +18,7 @@ #include "nvim/bufwrite.h" #include "nvim/change.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/channel.c b/src/nvim/channel.c index e5492caf45..05225cecd0 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -13,6 +13,7 @@ #include "nvim/autocmd_defs.h" #include "nvim/buffer_defs.h" #include "nvim/channel.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 808df44941..bb85620ce6 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -19,6 +19,7 @@ #include "nvim/cmdexpand.h" #include "nvim/cmdhist.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c index 983ab8b59b..ab05ae1cfc 100644 --- a/src/nvim/cmdhist.c +++ b/src/nvim/cmdhist.c @@ -11,6 +11,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/cmdhist.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 7d87b61ce5..b71ff23f57 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -13,6 +13,7 @@ #include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 303d0318b5..52a3fa5924 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -15,6 +15,7 @@ #include "nvim/drawscreen.h" #include "nvim/extmark.h" #include "nvim/fold.h" +#include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/grid_defs.h" #include "nvim/highlight.h" @@ -184,6 +185,21 @@ void buf_put_decor(buf_T *buf, DecorInline decor, int row, int row2) } } +/// When displaying signs in the 'number' column, if the width of the number +/// column is less than 2, then force recomputing the width after placing or +/// unplacing the first sign in "buf". +static void may_force_numberwidth_recompute(buf_T *buf, bool unplace) +{ + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer == buf + && wp->w_minscwidth == SCL_NUM + && (wp->w_p_nu || wp->w_p_rnu) + && (unplace || wp->w_nrwidth_width < 2)) { + wp->w_nrwidth_line_count = 0; + } + } +} + static int sign_add_id = 0; void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row1, int row2) { @@ -191,6 +207,7 @@ void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row1, int row2) sh->sign_add_id = sign_add_id++; if (sh->text[0]) { buf_signcols_count_range(buf, row1, row2, 1, kFalse); + may_force_numberwidth_recompute(buf, false); } } } @@ -218,6 +235,7 @@ void buf_remove_decor_sh(buf_T *buf, int row1, int row2, DecorSignHighlight *sh) if (buf_meta_total(buf, kMTMetaSignText)) { buf_signcols_count_range(buf, row1, row2, -1, kFalse); } else { + may_force_numberwidth_recompute(buf, true); buf->b_signcols.resized = true; buf->b_signcols.max = buf->b_signcols.count[0] = 0; } diff --git a/src/nvim/diff.c b/src/nvim/diff.c index ea846b46ec..54335fc93e 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -26,6 +26,7 @@ #include "nvim/cursor.h" #include "nvim/diff.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index a358a1723a..26fb77df30 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -12,6 +12,7 @@ #include "nvim/charset.h" #include "nvim/digraph.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 4d534d78a2..3bd00ee3f9 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -465,6 +465,7 @@ static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, i int fill = nrcol ? number_width(wp) + 1 : SIGN_WIDTH; draw_col_fill(wlv, schar_from_ascii(' '), fill, attr); int sign_pos = wlv->off - SIGN_WIDTH - (int)nrcol; + assert(sign_pos >= 0); linebuf_char[sign_pos] = sattr.text[0]; linebuf_char[sign_pos + 1] = sattr.text[1]; } else { diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 039bbd219c..bd9a834869 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1548,6 +1548,7 @@ static void win_update(win_T *wp) // Force redraw when width of 'number' or 'relativenumber' column changes. if (wp->w_nrwidth != nrwidth_new) { type = UPD_NOT_VALID; + changed_line_abv_curs_win(wp); wp->w_nrwidth = nrwidth_new; } else { // Set mod_top to the first line that needs displaying because of diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 220b92d099..f6e2dbfa4e 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -18,6 +18,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" @@ -473,7 +474,8 @@ static int insert_check(VimState *state) if (curwin->w_wcol < s->mincol - tabstop_at(get_nolist_virtcol(), curbuf->b_p_ts, - curbuf->b_p_vts_array) + curbuf->b_p_vts_array, + false) && curwin->w_wrow == curwin->w_height_inner - 1 - get_scrolloff_value(curwin) && (curwin->w_cursor.lnum != curwin->w_topline || curwin->w_topfill > 0)) { @@ -4419,18 +4421,30 @@ static bool ins_tab(void) // Delete following spaces. int i = cursor->col - fpos.col; if (i > 0) { - STRMOVE(ptr, ptr + i); + if (!(State & VREPLACE_FLAG)) { + char *newp = xmalloc((size_t)(curbuf->b_ml.ml_line_len - i)); + ptrdiff_t col = ptr - curbuf->b_ml.ml_line_ptr; + if (col > 0) { + memmove(newp, ptr - col, (size_t)col); + } + memmove(newp + col, ptr + i, (size_t)(curbuf->b_ml.ml_line_len - col - i)); + if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) { + xfree(curbuf->b_ml.ml_line_ptr); + } + curbuf->b_ml.ml_line_ptr = newp; + curbuf->b_ml.ml_line_len -= i; + curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; + inserted_bytes(fpos.lnum, change_col, + cursor->col - change_col, fpos.col - change_col); + } else { + STRMOVE(ptr, ptr + i); + } // correct replace stack. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) { for (temp = i; --temp >= 0;) { replace_join(repl_off); } } - if (!(State & VREPLACE_FLAG)) { - curbuf->b_ml.ml_line_len -= i; - inserted_bytes(fpos.lnum, change_col, - cursor->col - change_col, fpos.col - change_col); - } } cursor->col -= i; diff --git a/src/nvim/errors.h b/src/nvim/errors.h new file mode 100644 index 0000000000..39095db952 --- /dev/null +++ b/src/nvim/errors.h @@ -0,0 +1,193 @@ +#pragma once + +#include "nvim/gettext_defs.h" +#include "nvim/macros_defs.h" + +// +// Shared error messages. Excludes errors only used once and debugging messages. +// +// uncrustify:off +EXTERN const char e_abort[] INIT(= N_("E470: Command aborted")); +EXTERN const char e_afterinit[] INIT(= N_("E905: Cannot set this option after startup")); +EXTERN const char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job")); +EXTERN const char e_argreq[] INIT(= N_("E471: Argument required")); +EXTERN const char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); +EXTERN const char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); +EXTERN const char e_curdir[] INIT(= N_("E12: Command not allowed in secure mode in current dir or tag search")); +EXTERN const char e_invalid_buffer_name_str[] INIT(= N_("E158: Invalid buffer name: %s")); +EXTERN const char e_command_too_recursive[] INIT(= N_("E169: Command too recursive")); +EXTERN const char e_buffer_is_not_loaded[] INIT(= N_("E681: Buffer is not loaded")); +EXTERN const char e_endif[] INIT(= N_("E171: Missing :endif")); +EXTERN const char e_endtry[] INIT(= N_("E600: Missing :endtry")); +EXTERN const char e_endwhile[] INIT(= N_("E170: Missing :endwhile")); +EXTERN const char e_endfor[] INIT(= N_("E170: Missing :endfor")); +EXTERN const char e_while[] INIT(= N_("E588: :endwhile without :while")); +EXTERN const char e_for[] INIT(= N_("E588: :endfor without :for")); +EXTERN const char e_exists[] INIT(= N_("E13: File exists (add ! to override)")); +EXTERN const char e_failed[] INIT(= N_("E472: Command failed")); +EXTERN const char e_internal[] INIT(= N_("E473: Internal error")); +EXTERN const char e_intern2[] INIT(= N_("E685: Internal error: %s")); +EXTERN const char e_interr[] INIT(= N_("Interrupted")); +EXTERN const char e_invarg[] INIT(= N_("E474: Invalid argument")); +EXTERN const char e_invarg2[] INIT(= N_("E475: Invalid argument: %s")); +EXTERN const char e_invargval[] INIT(= N_("E475: Invalid value for argument %s")); +EXTERN const char e_invargNval[] INIT(= N_("E475: Invalid value for argument %s: %s")); +EXTERN const char e_duparg2[] INIT(= N_("E983: Duplicate argument: %s")); +EXTERN const char e_invexpr2[] INIT(= N_("E15: Invalid expression: \"%s\"")); +EXTERN const char e_invrange[] INIT(= N_("E16: Invalid range")); +EXTERN const char e_invcmd[] INIT(= N_("E476: Invalid command")); +EXTERN const char e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); +EXTERN const char e_no_spell[] INIT(= N_("E756: Spell checking is not possible")); +EXTERN const char e_invchan[] INIT(= N_("E900: Invalid channel id")); +EXTERN const char e_invchanjob[] INIT(= N_("E900: Invalid channel id: not a job")); +EXTERN const char e_jobtblfull[] INIT(= N_("E901: Job table is full")); +EXTERN const char e_jobspawn[] INIT(= N_("E903: Process failed to start: %s: \"%s\"")); +EXTERN const char e_channotpty[] INIT(= N_("E904: channel is not a pty")); +EXTERN const char e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s")); +EXTERN const char e_invstream[] INIT(= N_("E906: invalid stream for channel")); +EXTERN const char e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'")); +EXTERN const char e_streamkey[] INIT(= N_("E5210: dict key '%s' already set for buffered stream in channel %" PRIu64)); +EXTERN const char e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); +EXTERN const char e_fsync[] INIT(= N_("E667: Fsync failed: %s")); +EXTERN const char e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); +EXTERN const char e_markinval[] INIT(= N_("E19: Mark has invalid line number")); +EXTERN const char e_marknotset[] INIT(= N_("E20: Mark not set")); +EXTERN const char e_modifiable[] INIT(= N_("E21: Cannot make changes, 'modifiable' is off")); +EXTERN const char e_nesting[] INIT(= N_("E22: Scripts nested too deep")); +EXTERN const char e_noalt[] INIT(= N_("E23: No alternate file")); +EXTERN const char e_noabbr[] INIT(= N_("E24: No such abbreviation")); +EXTERN const char e_nobang[] INIT(= N_("E477: No ! allowed")); +EXTERN const char e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); +EXTERN const char e_noinstext[] INIT(= N_("E29: No inserted text yet")); +EXTERN const char e_nolastcmd[] INIT(= N_("E30: No previous command line")); +EXTERN const char e_nomap[] INIT(= N_("E31: No such mapping")); +EXTERN const char e_nomatch[] INIT(= N_("E479: No match")); +EXTERN const char e_nomatch2[] INIT(= N_("E480: No match: %s")); +EXTERN const char e_noname[] INIT(= N_("E32: No file name")); +EXTERN const char e_nopresub[] INIT(= N_("E33: No previous substitute regular expression")); +EXTERN const char e_noprev[] INIT(= N_("E34: No previous command")); +EXTERN const char e_noprevre[] INIT(= N_("E35: No previous regular expression")); +EXTERN const char e_norange[] INIT(= N_("E481: No range allowed")); +EXTERN const char e_noroom[] INIT(= N_("E36: Not enough room")); +EXTERN const char e_notmp[] INIT(= N_("E483: Can't get temp file name")); +EXTERN const char e_notopen[] INIT(= N_("E484: Can't open file %s")); +EXTERN const char e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s")); +EXTERN const char e_notread[] INIT(= N_("E485: Can't read file %s")); +EXTERN const char e_null[] INIT(= N_("E38: Null argument")); +EXTERN const char e_number_exp[] INIT(= N_("E39: Number expected")); +EXTERN const char e_openerrf[] INIT(= N_("E40: Can't open errorfile %s")); +EXTERN const char e_outofmem[] INIT(= N_("E41: Out of memory!")); +EXTERN const char e_patnotf[] INIT(= N_("Pattern not found")); +EXTERN const char e_patnotf2[] INIT(= N_("E486: Pattern not found: %s")); +EXTERN const char e_positive[] INIT(= N_("E487: Argument must be positive")); +EXTERN const char e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory")); + +EXTERN const char e_no_errors[] INIT(= N_("E42: No Errors")); +EXTERN const char e_loclist[] INIT(= N_("E776: No location list")); +EXTERN const char e_re_damg[] INIT(= N_("E43: Damaged match string")); +EXTERN const char e_re_corr[] INIT(= N_("E44: Corrupted regexp program")); +EXTERN const char e_readonly[] INIT(= N_("E45: 'readonly' option is set (add ! to override)")); +EXTERN const char e_letwrong[] INIT(= N_("E734: Wrong variable type for %s=")); +EXTERN const char e_illvar[] INIT(= N_("E461: Illegal variable name: %s")); +EXTERN const char e_cannot_mod[] INIT(= N_("E995: Cannot modify existing variable")); +EXTERN const char e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%.*s\"")); +EXTERN const char e_stringreq[] INIT(= N_("E928: String required")); +EXTERN const char e_dictreq[] INIT(= N_("E715: Dictionary required")); +EXTERN const char e_blobidx[] INIT(= N_("E979: Blob index out of range: %" PRId64)); +EXTERN const char e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); +EXTERN const char e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); +EXTERN const char e_toofewarg[] INIT(= N_("E119: Not enough arguments for function: %s")); +EXTERN const char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"")); +EXTERN const char e_dictkey_len[] INIT(= N_("E716: Key not present in Dictionary: \"%.*s\"")); +EXTERN const char e_listreq[] INIT(= N_("E714: List required")); +EXTERN const char e_listblobreq[] INIT(= N_("E897: List or Blob required")); +EXTERN const char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); +EXTERN const char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob")); +EXTERN const char e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); +EXTERN const char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); +EXTERN const char e_secure[] INIT(= N_("E523: Not allowed here")); +EXTERN const char e_textlock[] INIT(= N_("E565: Not allowed to change text or change window")); +EXTERN const char e_screenmode[] INIT(= N_("E359: Screen mode setting not supported")); +EXTERN const char e_scroll[] INIT(= N_("E49: Invalid scroll size")); +EXTERN const char e_shellempty[] INIT(= N_("E91: 'shell' option is empty")); +EXTERN const char e_signdata[] INIT(= N_("E255: Couldn't read in sign data!")); +EXTERN const char e_swapclose[] INIT(= N_("E72: Close error on swap file")); +EXTERN const char e_toocompl[] INIT(= N_("E74: Command too complex")); +EXTERN const char e_longname[] INIT(= N_("E75: Name too long")); +EXTERN const char e_toomsbra[] INIT(= N_("E76: Too many [")); +EXTERN const char e_toomany[] INIT(= N_("E77: Too many file names")); +EXTERN const char e_trailing[] INIT(= N_("E488: Trailing characters")); +EXTERN const char e_trailing_arg[] INIT(= N_("E488: Trailing characters: %s")); +EXTERN const char e_umark[] INIT(= N_("E78: Unknown mark")); +EXTERN const char e_wildexpand[] INIT(= N_("E79: Cannot expand wildcards")); +EXTERN const char e_winheight[] INIT(= N_("E591: 'winheight' cannot be smaller than 'winminheight'")); +EXTERN const char e_winwidth[] INIT(= N_("E592: 'winwidth' cannot be smaller than 'winminwidth'")); +EXTERN const char e_write[] INIT(= N_("E80: Error while writing")); +EXTERN const char e_zerocount[] INIT(= N_("E939: Positive count required")); +EXTERN const char e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context")); +EXTERN const char e_missingparen[] INIT(= N_("E107: Missing parentheses: %s")); +EXTERN const char e_empty_buffer[] INIT(= N_("E749: Empty buffer")); +EXTERN const char e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist")); + +EXTERN const char e_str_not_inside_function[] INIT(= N_("E193: %s not inside a function")); + +EXTERN const char e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter")); +EXTERN const char e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); +EXTERN const char e_notset[] INIT(= N_("E764: Option '%s' is not set")); +EXTERN const char e_invalidreg[] INIT(= N_("E850: Invalid register name")); +EXTERN const char e_dirnotf[] INIT(= N_("E919: Directory not found in '%s': \"%s\"")); +EXTERN const char e_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior")); +EXTERN const char e_menu_only_exists_in_another_mode[] +INIT(= N_("E328: Menu only exists in another mode")); +EXTERN const char e_autocmd_close[] INIT(= N_("E813: Cannot close autocmd window")); +EXTERN const char e_listarg[] INIT(= N_("E686: Argument of %s must be a List")); +EXTERN const char e_unsupportedoption[] INIT(= N_("E519: Option not supported")); +EXTERN const char e_fnametoolong[] INIT(= N_("E856: Filename too long")); +EXTERN const char e_using_float_as_string[] INIT(= N_("E806: Using a Float as a String")); +EXTERN const char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now")); +EXTERN const char e_using_number_as_bool_nr[] INIT(= N_("E1023: Using a Number as a Bool: %d")); +EXTERN const char e_not_callable_type_str[] INIT(= N_("E1085: Not a callable type: %s")); +EXTERN const char e_auabort[] INIT(= N_("E855: Autocommands caused command to abort")); + +EXTERN const char e_api_error[] INIT(= N_("E5555: API call: %s")); + +EXTERN const char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lua loop callback")); + +EXTERN const char e_floatonly[] INIT(= N_("E5601: Cannot close window, only floating window would remain")); +EXTERN const char e_floatexchange[] INIT(= N_("E5602: Cannot exchange or rotate float")); + +EXTERN const char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events")); + +EXTERN const char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long")); + +EXTERN const char e_line_number_out_of_range[] INIT(= N_("E1247: Line number out of range")); + +EXTERN const char e_highlight_group_name_invalid_char[] INIT(= N_("E5248: Invalid character in group name")); + +EXTERN const char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long")); + +EXTERN const char e_invalid_column_number_nr[] INIT( = N_("E964: Invalid column number: %ld")); +EXTERN const char e_invalid_line_number_nr[] INIT(= N_("E966: Invalid line number: %ld")); + +EXTERN const char e_stray_closing_curly_str[] +INIT(= N_("E1278: Stray '}' without a matching '{': %s")); +EXTERN const char e_missing_close_curly_str[] +INIT(= N_("E1279: Missing '}': %s")); + +EXTERN const char e_val_too_large[] INIT(= N_("E1510: Value too large: %s")); + +EXTERN const char e_undobang_cannot_redo_or_move_branch[] +INIT(= N_("E5767: Cannot use :undo! to redo or move to a different undo branch")); + +EXTERN const char e_winfixbuf_cannot_go_to_buffer[] +INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled")); + +EXTERN const char e_trustfile[] INIT(= N_("E5570: Cannot update trust file: %s")); + +EXTERN const char e_unknown_option2[] INIT(= N_("E355: Unknown option: %s")); + +EXTERN const char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); +EXTERN const char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP")); + +EXTERN const char line_msg[] INIT(= N_(" line ")); +// uncrustify:on diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 48a58228ae..a8778b9489 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -24,6 +24,7 @@ #include "nvim/cmdhist.h" #include "nvim/cursor.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/executor.h" diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 1b8c057d7c..3255e78d09 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -1,6 +1,7 @@ #include <inttypes.h> #include <stdlib.h> +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/executor.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8b22c7a797..e704135366 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -38,6 +38,7 @@ #include "nvim/cursor.h" #include "nvim/diff.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/buffer.h" #include "nvim/eval/decode.h" @@ -8301,7 +8302,7 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (col < 0) { return; // type error; errmsg already given } - rettv->vval.v_number = get_sw_value_col(curbuf, col); + rettv->vval.v_number = get_sw_value_col(curbuf, col, false); return; } rettv->vval.v_number = get_sw_value(curbuf); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index eb8c89c36e..1ea1fe46d2 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -10,6 +10,7 @@ #include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/executor.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 39bd63462c..00fb896797 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -15,6 +15,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 1c15274acc..7b93a291c4 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -15,6 +15,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 68de40f983..d7485c12a3 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -10,6 +10,7 @@ #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/cursor.h" +#include "nvim/errors.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 834cc6698a..2f7673a6f4 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -34,6 +34,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index f4a6e61831..a602719f6d 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -17,6 +17,7 @@ #include "nvim/bufwrite.h" #include "nvim/change.h" #include "nvim/channel.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 1fcfc505df..028ee8f6ae 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -29,6 +29,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 472741d537..2681beb228 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -11,6 +11,7 @@ #include "nvim/ascii_defs.h" #include "nvim/charset.h" #include "nvim/debugger.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index cc2608433d..4323a9d221 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -28,6 +28,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 0e5d2fe4f5..50ee197ef4 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -15,6 +15,7 @@ #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index df9c4928c9..05c9114554 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -27,6 +27,7 @@ #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_eval.h" diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 59a4dc6aad..be1b6acf2c 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -22,6 +22,7 @@ #include "nvim/decoration.h" #include "nvim/diff.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/ex_session.h" diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 62c99ce082..61c80a3d2e 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -306,6 +306,7 @@ local keysets_defs = assert(io.open(keysets_outputf, 'wb')) -- so that the dispatcher can find the C functions that you are creating! -- =========================================================================== output:write([[ +#include "nvim/errors.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/globals.h" diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 9b19644b7e..ce2c85f174 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -19,6 +19,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 83fef1fe75..410e8f2e7c 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -793,195 +793,7 @@ EXTERN disptick_T display_tick INIT( = 0); // cursor position in Insert mode. EXTERN linenr_T spell_redraw_lnum INIT( = 0); -// uncrustify:off - -// The error messages that can be shared are included here. -// Excluded are errors that are only used once and debugging messages. -EXTERN const char e_abort[] INIT(= N_("E470: Command aborted")); -EXTERN const char e_afterinit[] INIT(= N_("E905: Cannot set this option after startup")); -EXTERN const char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job")); -EXTERN const char e_argreq[] INIT(= N_("E471: Argument required")); -EXTERN const char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); -EXTERN const char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); -EXTERN const char e_curdir[] INIT(= N_("E12: Command not allowed in secure mode in current dir or tag search")); -EXTERN const char e_invalid_buffer_name_str[] INIT(= N_("E158: Invalid buffer name: %s")); -EXTERN const char e_command_too_recursive[] INIT(= N_("E169: Command too recursive")); -EXTERN const char e_buffer_is_not_loaded[] INIT(= N_("E681: Buffer is not loaded")); -EXTERN const char e_endif[] INIT(= N_("E171: Missing :endif")); -EXTERN const char e_endtry[] INIT(= N_("E600: Missing :endtry")); -EXTERN const char e_endwhile[] INIT(= N_("E170: Missing :endwhile")); -EXTERN const char e_endfor[] INIT(= N_("E170: Missing :endfor")); -EXTERN const char e_while[] INIT(= N_("E588: :endwhile without :while")); -EXTERN const char e_for[] INIT(= N_("E588: :endfor without :for")); -EXTERN const char e_exists[] INIT(= N_("E13: File exists (add ! to override)")); -EXTERN const char e_failed[] INIT(= N_("E472: Command failed")); -EXTERN const char e_internal[] INIT(= N_("E473: Internal error")); -EXTERN const char e_intern2[] INIT(= N_("E685: Internal error: %s")); -EXTERN const char e_interr[] INIT(= N_("Interrupted")); -EXTERN const char e_invarg[] INIT(= N_("E474: Invalid argument")); -EXTERN const char e_invarg2[] INIT(= N_("E475: Invalid argument: %s")); -EXTERN const char e_invargval[] INIT(= N_("E475: Invalid value for argument %s")); -EXTERN const char e_invargNval[] INIT(= N_("E475: Invalid value for argument %s: %s")); -EXTERN const char e_duparg2[] INIT(= N_("E983: Duplicate argument: %s")); -EXTERN const char e_invexpr2[] INIT(= N_("E15: Invalid expression: \"%s\"")); -EXTERN const char e_invrange[] INIT(= N_("E16: Invalid range")); -EXTERN const char e_invcmd[] INIT(= N_("E476: Invalid command")); -EXTERN const char e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); -EXTERN const char e_no_spell[] INIT(= N_("E756: Spell checking is not possible")); -EXTERN const char e_invchan[] INIT(= N_("E900: Invalid channel id")); -EXTERN const char e_invchanjob[] INIT(= N_("E900: Invalid channel id: not a job")); -EXTERN const char e_jobtblfull[] INIT(= N_("E901: Job table is full")); -EXTERN const char e_jobspawn[] INIT(= N_("E903: Process failed to start: %s: \"%s\"")); -EXTERN const char e_channotpty[] INIT(= N_("E904: channel is not a pty")); -EXTERN const char e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s")); -EXTERN const char e_invstream[] INIT(= N_("E906: invalid stream for channel")); -EXTERN const char e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'")); -EXTERN const char e_streamkey[] INIT(= N_("E5210: dict key '%s' already set for buffered stream in channel %" PRIu64)); -EXTERN const char e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); -EXTERN const char e_fsync[] INIT(= N_("E667: Fsync failed: %s")); -EXTERN const char e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); -EXTERN const char e_markinval[] INIT(= N_("E19: Mark has invalid line number")); -EXTERN const char e_marknotset[] INIT(= N_("E20: Mark not set")); -EXTERN const char e_modifiable[] INIT(= N_("E21: Cannot make changes, 'modifiable' is off")); -EXTERN const char e_nesting[] INIT(= N_("E22: Scripts nested too deep")); -EXTERN const char e_noalt[] INIT(= N_("E23: No alternate file")); -EXTERN const char e_noabbr[] INIT(= N_("E24: No such abbreviation")); -EXTERN const char e_nobang[] INIT(= N_("E477: No ! allowed")); -EXTERN const char e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); -EXTERN const char e_noinstext[] INIT(= N_("E29: No inserted text yet")); -EXTERN const char e_nolastcmd[] INIT(= N_("E30: No previous command line")); -EXTERN const char e_nomap[] INIT(= N_("E31: No such mapping")); -EXTERN const char e_nomatch[] INIT(= N_("E479: No match")); -EXTERN const char e_nomatch2[] INIT(= N_("E480: No match: %s")); -EXTERN const char e_noname[] INIT(= N_("E32: No file name")); -EXTERN const char e_nopresub[] INIT(= N_("E33: No previous substitute regular expression")); -EXTERN const char e_noprev[] INIT(= N_("E34: No previous command")); -EXTERN const char e_noprevre[] INIT(= N_("E35: No previous regular expression")); -EXTERN const char e_norange[] INIT(= N_("E481: No range allowed")); -EXTERN const char e_noroom[] INIT(= N_("E36: Not enough room")); -EXTERN const char e_notmp[] INIT(= N_("E483: Can't get temp file name")); -EXTERN const char e_notopen[] INIT(= N_("E484: Can't open file %s")); -EXTERN const char e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s")); -EXTERN const char e_notread[] INIT(= N_("E485: Can't read file %s")); -EXTERN const char e_null[] INIT(= N_("E38: Null argument")); -EXTERN const char e_number_exp[] INIT(= N_("E39: Number expected")); -EXTERN const char e_openerrf[] INIT(= N_("E40: Can't open errorfile %s")); -EXTERN const char e_outofmem[] INIT(= N_("E41: Out of memory!")); -EXTERN const char e_patnotf[] INIT(= N_("Pattern not found")); -EXTERN const char e_patnotf2[] INIT(= N_("E486: Pattern not found: %s")); -EXTERN const char e_positive[] INIT(= N_("E487: Argument must be positive")); -EXTERN const char e_prev_dir[] INIT(= N_("E459: Cannot go back to previous directory")); - -EXTERN const char e_no_errors[] INIT(= N_("E42: No Errors")); -EXTERN const char e_loclist[] INIT(= N_("E776: No location list")); -EXTERN const char e_re_damg[] INIT(= N_("E43: Damaged match string")); -EXTERN const char e_re_corr[] INIT(= N_("E44: Corrupted regexp program")); -EXTERN const char e_readonly[] INIT(= N_("E45: 'readonly' option is set (add ! to override)")); -EXTERN const char e_letwrong[] INIT(= N_("E734: Wrong variable type for %s=")); -EXTERN const char e_illvar[] INIT(= N_("E461: Illegal variable name: %s")); -EXTERN const char e_cannot_mod[] INIT(= N_("E995: Cannot modify existing variable")); -EXTERN const char e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%.*s\"")); -EXTERN const char e_stringreq[] INIT(= N_("E928: String required")); -EXTERN const char e_dictreq[] INIT(= N_("E715: Dictionary required")); -EXTERN const char e_blobidx[] INIT(= N_("E979: Blob index out of range: %" PRId64)); -EXTERN const char e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); -EXTERN const char e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s")); -EXTERN const char e_toofewarg[] INIT(= N_("E119: Not enough arguments for function: %s")); -EXTERN const char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"")); -EXTERN const char e_dictkey_len[] INIT(= N_("E716: Key not present in Dictionary: \"%.*s\"")); -EXTERN const char e_listreq[] INIT(= N_("E714: List required")); -EXTERN const char e_listblobreq[] INIT(= N_("E897: List or Blob required")); -EXTERN const char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); -EXTERN const char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob")); -EXTERN const char e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); -EXTERN const char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); -EXTERN const char e_secure[] INIT(= N_("E523: Not allowed here")); -EXTERN const char e_textlock[] INIT(= N_("E565: Not allowed to change text or change window")); -EXTERN const char e_screenmode[] INIT(= N_("E359: Screen mode setting not supported")); -EXTERN const char e_scroll[] INIT(= N_("E49: Invalid scroll size")); -EXTERN const char e_shellempty[] INIT(= N_("E91: 'shell' option is empty")); -EXTERN const char e_signdata[] INIT(= N_("E255: Couldn't read in sign data!")); -EXTERN const char e_swapclose[] INIT(= N_("E72: Close error on swap file")); -EXTERN const char e_toocompl[] INIT(= N_("E74: Command too complex")); -EXTERN const char e_longname[] INIT(= N_("E75: Name too long")); -EXTERN const char e_toomsbra[] INIT(= N_("E76: Too many [")); -EXTERN const char e_toomany[] INIT(= N_("E77: Too many file names")); -EXTERN const char e_trailing[] INIT(= N_("E488: Trailing characters")); -EXTERN const char e_trailing_arg[] INIT(= N_("E488: Trailing characters: %s")); -EXTERN const char e_umark[] INIT(= N_("E78: Unknown mark")); -EXTERN const char e_wildexpand[] INIT(= N_("E79: Cannot expand wildcards")); -EXTERN const char e_winheight[] INIT(= N_("E591: 'winheight' cannot be smaller than 'winminheight'")); -EXTERN const char e_winwidth[] INIT(= N_("E592: 'winwidth' cannot be smaller than 'winminwidth'")); -EXTERN const char e_write[] INIT(= N_("E80: Error while writing")); -EXTERN const char e_zerocount[] INIT(= N_("E939: Positive count required")); -EXTERN const char e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context")); -EXTERN const char e_missingparen[] INIT(= N_("E107: Missing parentheses: %s")); -EXTERN const char e_empty_buffer[] INIT(= N_("E749: Empty buffer")); -EXTERN const char e_nobufnr[] INIT(= N_("E86: Buffer %" PRId64 " does not exist")); - -EXTERN const char e_str_not_inside_function[] INIT(= N_("E193: %s not inside a function")); - -EXTERN const char e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter")); -EXTERN const char e_bufloaded[] INIT(= N_("E139: File is loaded in another buffer")); -EXTERN const char e_notset[] INIT(= N_("E764: Option '%s' is not set")); -EXTERN const char e_invalidreg[] INIT(= N_("E850: Invalid register name")); -EXTERN const char e_dirnotf[] INIT(= N_("E919: Directory not found in '%s': \"%s\"")); -EXTERN const char e_au_recursive[] INIT(= N_("E952: Autocommand caused recursive behavior")); -EXTERN const char e_menu_only_exists_in_another_mode[] -INIT(= N_("E328: Menu only exists in another mode")); -EXTERN const char e_autocmd_close[] INIT(= N_("E813: Cannot close autocmd window")); -EXTERN const char e_listarg[] INIT(= N_("E686: Argument of %s must be a List")); -EXTERN const char e_unsupportedoption[] INIT(= N_("E519: Option not supported")); -EXTERN const char e_fnametoolong[] INIT(= N_("E856: Filename too long")); -EXTERN const char e_using_float_as_string[] INIT(= N_("E806: Using a Float as a String")); -EXTERN const char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now")); -EXTERN const char e_using_number_as_bool_nr[] INIT(= N_("E1023: Using a Number as a Bool: %d")); -EXTERN const char e_not_callable_type_str[] INIT(= N_("E1085: Not a callable type: %s")); -EXTERN const char e_auabort[] INIT(= N_("E855: Autocommands caused command to abort")); - -EXTERN const char e_api_error[] INIT(= N_("E5555: API call: %s")); - -EXTERN const char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lua loop callback")); - -EXTERN const char e_floatonly[] INIT(= N_("E5601: Cannot close window, only floating window would remain")); -EXTERN const char e_floatexchange[] INIT(= N_("E5602: Cannot exchange or rotate float")); - -EXTERN const char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events")); - -EXTERN const char e_resulting_text_too_long[] INIT(= N_("E1240: Resulting text too long")); - -EXTERN const char e_line_number_out_of_range[] INIT(= N_("E1247: Line number out of range")); - -EXTERN const char e_highlight_group_name_invalid_char[] INIT(= N_("E5248: Invalid character in group name")); - -EXTERN const char e_highlight_group_name_too_long[] INIT(= N_("E1249: Highlight group name too long")); - -EXTERN const char e_invalid_column_number_nr[] INIT( = N_("E964: Invalid column number: %ld")); -EXTERN const char e_invalid_line_number_nr[] INIT(= N_("E966: Invalid line number: %ld")); - -EXTERN const char e_stray_closing_curly_str[] -INIT(= N_("E1278: Stray '}' without a matching '{': %s")); -EXTERN const char e_missing_close_curly_str[] -INIT(= N_("E1279: Missing '}': %s")); - -EXTERN const char e_val_too_large[] INIT(= N_("E1510: Value too large: %s")); - -EXTERN const char e_undobang_cannot_redo_or_move_branch[] -INIT(= N_("E5767: Cannot use :undo! to redo or move to a different undo branch")); - -EXTERN const char e_winfixbuf_cannot_go_to_buffer[] -INIT(= N_("E1513: Cannot switch buffer. 'winfixbuf' is enabled")); - -EXTERN const char e_trustfile[] INIT(= N_("E5570: Cannot update trust file: %s")); - -EXTERN const char e_unknown_option2[] INIT(= N_("E355: Unknown option: %s")); - -EXTERN const char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); -EXTERN const char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP")); - -EXTERN const char line_msg[] INIT(= N_(" line ")); - -EXTERN FILE *time_fd INIT(= NULL); // Where to write --startuptime report. +EXTERN FILE *time_fd INIT( = NULL); // Where to write --startuptime report. // Some compilers warn for not using a return value, but in some situations we // can't do anything useful with the value. Assign to this variable to avoid @@ -989,11 +801,9 @@ EXTERN FILE *time_fd INIT(= NULL); // Where to write --startuptime report. EXTERN int vim_ignored; // stdio is an RPC channel (--embed). -EXTERN bool embedded_mode INIT(= false); +EXTERN bool embedded_mode INIT( = false); // Do not start UI (--headless, -l) nor read/write to stdio (unless embedding). -EXTERN bool headless_mode INIT(= false); - -// uncrustify:on +EXTERN bool headless_mode INIT( = false); /// Only filled for Win32. EXTERN char windowsVersion[20] INIT( = { 0 }); diff --git a/src/nvim/help.c b/src/nvim/help.c index e9f67ca3e4..d28f195c00 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -13,6 +13,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/cmdexpand_defs.h" +#include "nvim/errors.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index ccb093c116..b5e62e7f31 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -22,6 +22,7 @@ #include "nvim/cursor_shape.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/indent.c b/src/nvim/indent.c index d635c7d7bf..66cb443e4d 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -13,6 +13,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" @@ -146,25 +147,42 @@ int tabstop_padding(colnr_T col, OptInt ts_arg, const colnr_T *vts) } /// Find the size of the tab that covers a particular column. -int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts) +/// +/// If this is being called as part of a shift operation, col is not the cursor +/// column but is the column number to the left of the first non-whitespace +/// character in the line. If the shift is to the left (left == true), then +/// return the size of the tab interval to the left of the column. +int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts, bool left) { - colnr_T tabcol = 0; - int t; - int tab_size = 0; - if (vts == NULL || vts[0] == 0) { return (int)ts; } - const int tabcount = vts[0]; + colnr_T tabcol = 0; // Column of the tab stop under consideration. + int t; // Tabstop index in the list of variable tab stops. + int tab_size = 0; // Size of the tab stop interval to the right or left of the col. + const int tabcount // Number of tab stops in the list of variable tab stops. + = vts[0]; for (t = 1; t <= tabcount; t++) { tabcol += vts[t]; if (tabcol > col) { - tab_size = vts[t]; + // If shifting left (left == true), and if the column to the left of + // the first first non-blank character (col) in the line is + // already to the left of the first tabstop, set the shift amount + // (tab_size) to just enough to shift the line to the left margin. + // The value doesn't seem to matter as long as it is at least that + // distance. + if (left && (t == 1)) { + tab_size = col; + } else { + tab_size = vts[t - (left ? 1 : 0)]; + } break; } } - if (t > tabcount) { + if (t > tabcount) { // If the value of the index t is beyond the + // end of the list, use the tab stop value at + // the end of the list. tab_size = vts[tabcount]; } @@ -311,35 +329,35 @@ int tabstop_first(colnr_T *ts) /// 'tabstop' value when 'shiftwidth' is zero. int get_sw_value(buf_T *buf) { - int result = get_sw_value_col(buf, 0); + int result = get_sw_value_col(buf, 0, false); return result; } /// Idem, using "pos". -int get_sw_value_pos(buf_T *buf, pos_T *pos) +int get_sw_value_pos(buf_T *buf, pos_T *pos, bool left) { pos_T save_cursor = curwin->w_cursor; curwin->w_cursor = *pos; - int sw_value = get_sw_value_col(buf, get_nolist_virtcol()); + int sw_value = get_sw_value_col(buf, get_nolist_virtcol(), left); curwin->w_cursor = save_cursor; return sw_value; } /// Idem, using the first non-black in the current line. -int get_sw_value_indent(buf_T *buf) +int get_sw_value_indent(buf_T *buf, bool left) { pos_T pos = curwin->w_cursor; pos.col = (colnr_T)getwhitecols_curline(); - return get_sw_value_pos(buf, &pos); + return get_sw_value_pos(buf, &pos, left); } /// Idem, using virtual column "col". -int get_sw_value_col(buf_T *buf, colnr_T col) +int get_sw_value_col(buf_T *buf, colnr_T col, bool left) { return buf->b_p_sw ? (int)buf->b_p_sw - : tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array); + : tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array, left); } /// Return the effective softtabstop value for the current buffer, diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 8b1c09b32f..7a652dff2a 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -22,6 +22,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index 44ddfbba00..f7215d3d12 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -8,6 +8,7 @@ #include "nvim/ascii_defs.h" #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" #include "nvim/gettext_defs.h" diff --git a/src/nvim/lua/api_wrappers.c b/src/nvim/lua/api_wrappers.c index 2b7b0c6471..36847d1fc9 100644 --- a/src/nvim/lua/api_wrappers.c +++ b/src/nvim/lua/api_wrappers.c @@ -5,6 +5,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" +#include "nvim/errors.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/func_attr.h" diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index a76b8213e5..6246452b92 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -22,6 +22,7 @@ #include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/lua/secure.c b/src/nvim/lua/secure.c index f62e0ace04..a84d6c4d65 100644 --- a/src/nvim/lua/secure.c +++ b/src/nvim/lua/secure.c @@ -3,6 +3,7 @@ #include <string.h> #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/ex_cmds_defs.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c index ba83239dc5..f4dacd7a55 100644 --- a/src/nvim/lua/spell.c +++ b/src/nvim/lua/spell.c @@ -7,6 +7,7 @@ #include "nvim/ascii_defs.h" #include "nvim/buffer_defs.h" +#include "nvim/errors.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" #include "nvim/highlight_defs.h" diff --git a/src/nvim/main.c b/src/nvim/main.c index db7f16131b..5e243df975 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -37,6 +37,7 @@ #include "nvim/diff.h" #include "nvim/drawline.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 9320390d68..167111f3ae 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -19,6 +19,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/cmdexpand_defs.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 6ce42bb7fe..16f444a316 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -14,6 +14,7 @@ #include "nvim/cursor.h" #include "nvim/diff.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/match.c b/src/nvim/match.c index 580d7d1069..6ae4e41147 100644 --- a/src/nvim/match.c +++ b/src/nvim/match.c @@ -10,6 +10,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/eval/window.h" diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index a345795bbe..23fdd5eb16 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -43,6 +43,7 @@ #include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/getchar.h" diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index a1713edb66..498d212da3 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -46,6 +46,7 @@ #include "nvim/assert_defs.h" #include "nvim/buffer_defs.h" +#include "nvim/errors.h" #include "nvim/fileio.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 6a60ca927e..c4774d68f3 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -19,6 +19,7 @@ #include "nvim/context.h" #include "nvim/decoration_provider.h" #include "nvim/drawline.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/gettext_defs.h" #include "nvim/globals.h" diff --git a/src/nvim/menu.c b/src/nvim/menu.c index ab28eeca1c..a4d49d041e 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -13,6 +13,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/message.c b/src/nvim/message.c index 10b90bde29..9941dcb254 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -18,6 +18,7 @@ #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/move.c b/src/nvim/move.c index 418ece09ed..a2bb1b4685 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -20,6 +20,7 @@ #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/eval/window.h" #include "nvim/fold.h" diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 8ba375f29d..879131c9e8 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -28,6 +28,7 @@ #include "nvim/digraph.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 5c1e291ac6..8ae1d70882 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -24,6 +24,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds2.h" @@ -281,7 +282,7 @@ void op_shift(oparg_T *oap, bool curs_top, int amount) /// @param call_changed_bytes call changed_bytes() void shift_line(bool left, bool round, int amount, int call_changed_bytes) { - const int sw_val = get_sw_value_indent(curbuf); + const int sw_val = get_sw_value_indent(curbuf, left); int count = get_indent(); // get current indent @@ -327,7 +328,7 @@ static void shift_block(oparg_T *oap, int amount) const int oldstate = State; char *newp; const int oldcol = curwin->w_cursor.col; - const int sw_val = get_sw_value_indent(curbuf); + const int sw_val = get_sw_value_indent(curbuf, left); const int ts_val = (int)curbuf->b_p_ts; struct block_def bd; int incr; diff --git a/src/nvim/option.c b/src/nvim/option.c index 799513e018..32fabd4141 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -44,6 +44,7 @@ #include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 452cc6876b..0f3cf6c5b4 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -7317,8 +7317,8 @@ return { message; also for quickfix message (e.g., ":cn") s don't give "search hit BOTTOM, continuing at TOP" or *shm-s* "search hit TOP, continuing at BOTTOM" messages; when using - the search count do not show "W" after the count message (see - S below) + the search count do not show "W" before the count message + (see |shm-S| below) t truncate file message at the start if it is too long *shm-t* to fit on the command-line, "<" will appear in the left most column; ignored in Ex mode @@ -7340,7 +7340,11 @@ return { `:silent` was used for the command; note that this also affects messages from 'autoread' reloading S do not show search count message when searching, e.g. *shm-S* - "[1/5]" + "[1/5]". When the "S" flag is not present (e.g. search count + is shown), the "search hit BOTTOM, continuing at TOP" and + "search hit TOP, continuing at BOTTOM" messages are only + indicated by a "W" (Mnemonic: Wrapped) letter before the + search count statistics. This gives you the opportunity to avoid that a change between buffers requires you to hit <Enter>, but still gives as useful a message as diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 29433ddbb5..be3bec2256 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -14,6 +14,7 @@ #include "nvim/diff.h" #include "nvim/digraph.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 19bdf30311..13e87a1ca5 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -17,6 +17,7 @@ #endif #include "auto/config.h" +#include "nvim/errors.h" #include "nvim/os/fs.h" #include "nvim/os/os_defs.h" diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 958faa4d22..d572e9b933 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -10,6 +10,7 @@ #include "nvim/ascii_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/event/defs.h" diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 86f3611ec5..bf2fe0f72c 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -19,6 +19,7 @@ #include "nvim/charset.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/profile.c b/src/nvim/profile.c index b88b08d3f0..7ea7061b46 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -10,6 +10,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index e022184f2f..e1d35ab9d5 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -20,6 +20,7 @@ #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/window.h" diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 5600d6a2f8..b743664b69 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -18,6 +18,7 @@ #include "nvim/ascii_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index d913d311db..648e574b97 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -22,6 +22,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/debugger.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" diff --git a/src/nvim/search.c b/src/nvim/search.c index 746c253708..bee124e305 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -18,6 +18,7 @@ #include "nvim/cmdhist.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 597c7551fd..d5655b1754 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -19,6 +19,7 @@ #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/cmdhist.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 4e6672c5dd..be207f58b0 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -21,6 +21,7 @@ #include "nvim/decoration_defs.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" @@ -246,12 +247,6 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum) return FAIL; } - // When deleting the last sign need to redraw the windows to remove the - // sign column. Not when curwin is NULL (this means we're exiting). - if (!buf_meta_total(buf, kMTMetaSignText) && curwin != NULL) { - changed_line_abv_curs(); - } - return OK; } @@ -499,17 +494,6 @@ static void sign_list_by_name(char *name) } } -static void may_force_numberwidth_recompute(buf_T *buf, int unplace) -{ - FOR_ALL_TAB_WINDOWS(tp, wp) - if (wp->w_buffer == buf - && (wp->w_p_nu || wp->w_p_rnu) - && (unplace || wp->w_nrwidth_width < 2) - && (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) { - wp->w_nrwidth_line_count = 0; - } -} - /// Place a sign at the specified file location or update a sign. static int sign_place(uint32_t *id, char *group, char *name, buf_T *buf, linenr_T lnum, int prio) { @@ -531,11 +515,7 @@ static int sign_place(uint32_t *id, char *group, char *name, buf_T *buf, linenr_ // ":sign place {id} file={fname}": change sign type and/or priority lnum = buf_mod_sign(buf, id, group, prio, sp); } - if (lnum > 0) { - // When displaying signs in the 'number' column, if the width of the - // number column is less than 2, then force recomputing the width. - may_force_numberwidth_recompute(buf, false); - } else { + if (lnum <= 0) { semsg(_("E885: Not possible to change sign %s"), name); return FAIL; } @@ -562,13 +542,6 @@ static int sign_unplace_inner(buf_T *buf, int id, char *group, linenr_T atlnum) } } - // When all the signs in a buffer are removed, force recomputing the - // number column width (if enabled) in all the windows displaying the - // buffer if 'signcolumn' is set to 'number' in that window. - if (!buf_meta_total(buf, kMTMetaSignText)) { - may_force_numberwidth_recompute(buf, true); - } - return OK; } diff --git a/src/nvim/spell.c b/src/nvim/spell.c index d7a6adef58..f6c326075d 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -72,6 +72,7 @@ #include "nvim/decoration.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 046a0a56e5..9746c3df91 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -240,6 +240,7 @@ #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/ex_cmds_defs.h" #include "nvim/fileio.h" #include "nvim/garray.h" diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index a7de20d14e..0e674c3178 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -14,6 +14,7 @@ #include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 8fef4ba7fd..329b66cea1 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -12,6 +12,7 @@ #include "nvim/ascii_defs.h" #include "nvim/assert_defs.h" #include "nvim/charset.h" +#include "nvim/errors.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index b63d2a729d..c13619797a 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -15,6 +15,7 @@ #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/eval/vars.h" diff --git a/src/nvim/tag.c b/src/nvim/tag.c index e7f483dd3d..ca3885b079 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -18,6 +18,7 @@ #include "nvim/cmdexpand_defs.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/testing.c b/src/nvim/testing.c index 343568d71e..8041cc2e33 100644 --- a/src/nvim/testing.c +++ b/src/nvim/testing.c @@ -7,6 +7,7 @@ #include <string.h> #include "nvim/ascii_defs.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/undo.c b/src/nvim/undo.c index ba720c9f6a..ed5c9a508c 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -92,6 +92,7 @@ #include "nvim/decoration.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/window.c b/src/nvim/window.c index 1a6c3f7263..9203dd1bdb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -22,6 +22,7 @@ #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/errors.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c index e3ca0ff139..77bbaed105 100644 --- a/src/nvim/winfloat.c +++ b/src/nvim/winfloat.c @@ -11,6 +11,7 @@ #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/drawscreen.h" +#include "nvim/errors.h" #include "nvim/globals.h" #include "nvim/grid.h" #include "nvim/grid_defs.h" diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index d4af7e4732..6b575ad0ef 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -379,6 +379,25 @@ describe('lua buffer event callbacks: on_lines', function() ]], }) end) + + it('line lengths are correct when pressing TAB with folding #29119', function() + api.nvim_buf_set_lines(0, 0, -1, true, { 'a', 'b' }) + + exec_lua([[ + _G.res = {} + vim.o.foldmethod = 'indent' + vim.o.softtabstop = -1 + vim.api.nvim_buf_attach(0, false, { + on_lines = function(_, bufnr, _, row, _, end_row) + local lines = vim.api.nvim_buf_get_lines(bufnr, row, end_row, true) + table.insert(_G.res, lines) + end + }) + ]]) + + feed('i<Tab>') + eq({ '\ta' }, exec_lua('return _G.res[#_G.res]')) + end) end) describe('lua: nvim_buf_attach on_bytes', function() diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index d7755dd0c4..d8a3e0acbd 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -126,6 +126,41 @@ describe('vim.lsp.completion: item conversion', function() eq(expected, result) end) + it('trims trailing newline or tab from textEdit', function() + local range0 = { + start = { line = 0, character = 0 }, + ['end'] = { line = 0, character = 0 }, + } + local items = { + { + detail = 'ansible.builtin', + filterText = 'lineinfile ansible.builtin.lineinfile builtin ansible', + kind = 7, + label = 'ansible.builtin.lineinfile', + sortText = '2_ansible.builtin.lineinfile', + textEdit = { + newText = 'ansible.builtin.lineinfile:\n ', + range = range0, + }, + }, + } + local result = complete('|', items) + result = vim.tbl_map(function(x) + return { + abbr = x.abbr, + word = x.word, + } + end, result.items) + + local expected = { + { + abbr = 'ansible.builtin.lineinfile', + word = 'ansible.builtin.lineinfile:', + }, + } + eq(expected, result) + end) + it('prefers wordlike components for snippets', function() -- There are two goals here: -- diff --git a/test/functional/script/luacats_grammar_spec.lua b/test/functional/script/luacats_grammar_spec.lua index d6fff3f409..9c6417f7bf 100644 --- a/test/functional/script/luacats_grammar_spec.lua +++ b/test/functional/script/luacats_grammar_spec.lua @@ -160,10 +160,10 @@ describe('luacats grammar', function() type = '`T`', }) - test('@param type [number,string] this is a tuple type', { + test('@param type [number,string,"good"|"bad"] this is a tuple type', { desc = 'this is a tuple type', kind = 'param', name = 'type', - type = '[number,string]', + type = '[number,string,"good"|"bad"]', }) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 746bfb3262..3e67e33ddb 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -5497,6 +5497,26 @@ l5 api.nvim_buf_clear_namespace(0, ns, 0, -1) end) + + it([[correct numberwidth with 'signcolumn' set to "number" #28984]], function() + command('set number numberwidth=1 signcolumn=number') + api.nvim_buf_set_extmark(0, ns, 0, 0, { sign_text = 'S1' }) + screen:expect({ + grid = [[ + S1 ^ | + {1:~ }|*8 + | + ]] + }) + api.nvim_buf_del_extmark(0, ns, 1) + screen:expect({ + grid = [[ + {8:1 }^ | + {1:~ }|*8 + | + ]] + }) + end) end) describe('decorations: virt_text', function() diff --git a/test/old/testdir/test_vartabs.vim b/test/old/testdir/test_vartabs.vim index e12c71d521..82c3a513f9 100644 --- a/test/old/testdir/test_vartabs.vim +++ b/test/old/testdir/test_vartabs.vim @@ -445,4 +445,77 @@ func Test_shiftwidth_vartabstop() setlocal shiftwidth& vartabstop& tabstop& endfunc +func Test_vartabstop_latin1() + throw "Skipped: Nvim does not support 'compatible'" + let save_encoding = &encoding + new + set encoding=iso8859-1 + set compatible linebreak list revins smarttab + set vartabstop=400 + exe "norm i00\t\<C-D>" + bwipe! + let &encoding = save_encoding + set nocompatible linebreak& list& revins& smarttab& vartabstop& +endfunc + +" Verify that right-shifting and left-shifting adjust lines to the proper +" tabstops. +func Test_vartabstop_shift_right_left() + new + set expandtab + set shiftwidth=0 + set vartabstop=17,11,7 + exe "norm! aword" + let expect = "word" + call assert_equal(expect, getline(1)) + + " Shift to first tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to second tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to third tabstop. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift to fourth tabstop, repeating the third shift width. + norm! >> + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the third tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the second tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the first tabstop. + norm! << + let expect = " word" + call assert_equal(expect, getline(1)) + + " Shift back to the left margin. + norm! << + let expect = "word" + call assert_equal(expect, getline(1)) + + " Shift again back to the left margin. + norm! << + let expect = "word" + call assert_equal(expect, getline(1)) + + bwipeout! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab |