aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt10
-rw-r--r--runtime/lua/vim/_meta/options.lua10
-rw-r--r--runtime/lua/vim/lsp/completion.lua326
-rw-r--r--scripts/luacats_grammar.lua2
-rw-r--r--src/nvim/api/vim.c1
-rw-r--r--src/nvim/api/win_config.c1
-rw-r--r--src/nvim/api/window.c1
-rw-r--r--src/nvim/arglist.c1
-rw-r--r--src/nvim/autocmd.c1
-rw-r--r--src/nvim/buffer.c1
-rw-r--r--src/nvim/bufwrite.c1
-rw-r--r--src/nvim/channel.c1
-rw-r--r--src/nvim/cmdexpand.c1
-rw-r--r--src/nvim/cmdhist.c1
-rw-r--r--src/nvim/debugger.c1
-rw-r--r--src/nvim/decoration.c18
-rw-r--r--src/nvim/diff.c1
-rw-r--r--src/nvim/digraph.c1
-rw-r--r--src/nvim/drawline.c1
-rw-r--r--src/nvim/drawscreen.c1
-rw-r--r--src/nvim/edit.c28
-rw-r--r--src/nvim/errors.h193
-rw-r--r--src/nvim/eval.c1
-rw-r--r--src/nvim/eval/executor.c1
-rw-r--r--src/nvim/eval/funcs.c3
-rw-r--r--src/nvim/eval/typval.c1
-rw-r--r--src/nvim/eval/userfunc.c1
-rw-r--r--src/nvim/eval/vars.c1
-rw-r--r--src/nvim/eval/window.c1
-rw-r--r--src/nvim/ex_cmds.c1
-rw-r--r--src/nvim/ex_cmds2.c1
-rw-r--r--src/nvim/ex_docmd.c1
-rw-r--r--src/nvim/ex_eval.c1
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/ex_session.c1
-rw-r--r--src/nvim/fileio.c1
-rw-r--r--src/nvim/fold.c1
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua1
-rw-r--r--src/nvim/getchar.c1
-rw-r--r--src/nvim/globals.h196
-rw-r--r--src/nvim/help.c1
-rw-r--r--src/nvim/highlight_group.c1
-rw-r--r--src/nvim/indent.c48
-rw-r--r--src/nvim/insexpand.c1
-rw-r--r--src/nvim/keycodes.c1
-rw-r--r--src/nvim/lua/api_wrappers.c1
-rw-r--r--src/nvim/lua/executor.c1
-rw-r--r--src/nvim/lua/secure.c1
-rw-r--r--src/nvim/lua/spell.c1
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/mapping.c1
-rw-r--r--src/nvim/mark.c1
-rw-r--r--src/nvim/match.c1
-rw-r--r--src/nvim/mbyte.c1
-rw-r--r--src/nvim/memfile.c1
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/menu.c1
-rw-r--r--src/nvim/message.c1
-rw-r--r--src/nvim/move.c1
-rw-r--r--src/nvim/normal.c1
-rw-r--r--src/nvim/ops.c5
-rw-r--r--src/nvim/option.c1
-rw-r--r--src/nvim/options.lua10
-rw-r--r--src/nvim/optionstr.c1
-rw-r--r--src/nvim/os/fs.c1
-rw-r--r--src/nvim/os/shell.c1
-rw-r--r--src/nvim/popupmenu.c1
-rw-r--r--src/nvim/profile.c1
-rw-r--r--src/nvim/quickfix.c1
-rw-r--r--src/nvim/regexp.c1
-rw-r--r--src/nvim/runtime.c1
-rw-r--r--src/nvim/search.c1
-rw-r--r--src/nvim/shada.c1
-rw-r--r--src/nvim/sign.c31
-rw-r--r--src/nvim/spell.c1
-rw-r--r--src/nvim/spellfile.c1
-rw-r--r--src/nvim/spellsuggest.c1
-rw-r--r--src/nvim/strings.c1
-rw-r--r--src/nvim/syntax.c1
-rw-r--r--src/nvim/tag.c1
-rw-r--r--src/nvim/testing.c1
-rw-r--r--src/nvim/undo.c1
-rw-r--r--src/nvim/window.c1
-rw-r--r--src/nvim/winfloat.c1
-rw-r--r--test/functional/lua/buffer_updates_spec.lua19
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua35
-rw-r--r--test/functional/script/luacats_grammar_spec.lua4
-rw-r--r--test/functional/ui/decorations_spec.lua20
-rw-r--r--test/old/testdir/test_vartabs.vim73
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