aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/helpers.c5
-rw-r--r--src/nvim/diff.c211
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/ex_docmd.c5
-rw-r--r--src/nvim/lua/executor.c4
-rw-r--r--src/nvim/lua/treesitter.c4
-rw-r--r--src/nvim/lua/vim.lua60
-rw-r--r--src/nvim/memfile.c6
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/screen.c4
-rw-r--r--src/nvim/spell.c2
-rw-r--r--src/nvim/state.c2
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_filetype.vim55
-rw-r--r--src/nvim/testdir/test_filetype_lua.vim2
-rw-r--r--src/nvim/testdir/test_search_stat.vim1
-rw-r--r--src/nvim/testdir/test_spell.vim8
17 files changed, 250 insertions, 128 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 38a82343c3..f9603acbda 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1387,6 +1387,11 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int
LuaRef luaref = LUA_NOREF;
LuaRef compl_luaref = LUA_NOREF;
+ if (mb_islower(name.data[0])) {
+ api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
+ goto err;
+ }
+
if (HAS_KEY(opts->range) && HAS_KEY(opts->count)) {
api_set_error(err, kErrorTypeValidation, "'range' and 'count' are mutually exclusive");
goto err;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 4f4da7c2a9..340fec230c 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -82,6 +82,14 @@ typedef struct {
garray_T dout_ga; // used for internal diff
} diffout_T;
+// used for recording hunks from xdiff
+typedef struct {
+ linenr_T lnum_orig;
+ long count_orig;
+ linenr_T lnum_new;
+ long count_new;
+} diffhunk_T;
+
// two diff inputs and one result
typedef struct {
diffin_T dio_orig; // original file input
@@ -852,7 +860,7 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
}
// Read the diff output and add each entry to the diff list.
- diff_read(idx_orig, idx_new, &dio->dio_diff);
+ diff_read(idx_orig, idx_new, dio);
clear_diffin(&dio->dio_new);
clear_diffout(&dio->dio_diff);
@@ -1078,7 +1086,7 @@ static int diff_file_internal(diffio_T *diffio)
emit_cfg.ctxlen = 0; // don't need any diff_context here
emit_cb.priv = &diffio->dio_diff;
- emit_cb.out_line = xdiff_out;
+ emit_cfg.hunk_func = xdiff_out;
if (xdl_diff(&diffio->dio_orig.din_mmfile,
&diffio->dio_new.din_mmfile,
&param, &emit_cfg, &emit_cb) < 0) {
@@ -1519,20 +1527,20 @@ void ex_diffoff(exarg_T *eap)
/// @param idx_orig idx of original file
/// @param idx_new idx of new file
/// @dout diff output
-static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
+static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
{
FILE *fd = NULL;
int line_idx = 0;
diff_T *dprev = NULL;
diff_T *dp = curtab->tp_first_diff;
diff_T *dn, *dpl;
+ diffout_T *dout = &dio->dio_diff;
char_u linebuf[LBUFLEN]; // only need to hold the diff line
char_u *line;
long off;
int i;
- linenr_T lnum_orig, lnum_new;
- long count_orig, count_new;
int notset = true; // block "*dp" not set yet
+ diffhunk_T *hunk;
enum {
DIFF_ED,
DIFF_UNIFIED,
@@ -1549,70 +1557,79 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
}
+ if (!dio->dio_internal) {
+ hunk = xmalloc(sizeof(*hunk));
+ }
+
for (;;) {
- if (fd == NULL) {
+ if (dio->dio_internal) {
if (line_idx >= dout->dout_ga.ga_len) {
break; // did last line
}
- line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
+ hunk = ((diffhunk_T **)dout->dout_ga.ga_data)[line_idx++];
} else {
- if (vim_fgets(linebuf, LBUFLEN, fd)) {
- break; // end of file
- }
- line = linebuf;
- }
-
- if (diffstyle == DIFF_NONE) {
- // Determine diff style.
- // ed like diff looks like this:
- // {first}[,{last}]c{first}[,{last}]
- // {first}a{first}[,{last}]
- // {first}[,{last}]d{first}
- //
- // unified diff looks like this:
- // --- file1 2018-03-20 13:23:35.783153140 +0100
- // +++ file2 2018-03-20 13:23:41.183156066 +0100
- // @@ -1,3 +1,5 @@
- if (isdigit(*line)) {
- diffstyle = DIFF_ED;
- } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
- } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "+++ ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
+ if (fd == NULL) {
+ if (line_idx >= dout->dout_ga.ga_len) {
+ break; // did last line
+ }
+ line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
} else {
- // Format not recognized yet, skip over this line. Cygwin diff
- // may put a warning at the start of the file.
- continue;
+ if (vim_fgets(linebuf, LBUFLEN, fd)) {
+ break; // end of file
+ }
+ line = linebuf;
}
- }
- if (diffstyle == DIFF_ED) {
- if (!isdigit(*line)) {
- continue; // not the start of a diff block
- }
- if (parse_diff_ed(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
- }
- } else {
- assert(diffstyle == DIFF_UNIFIED);
- if (STRNCMP(line, "@@ ", 3) != 0) {
- continue; // not the start of a diff block
+ if (diffstyle == DIFF_NONE) {
+ // Determine diff style.
+ // ed like diff looks like this:
+ // {first}[,{last}]c{first}[,{last}]
+ // {first}a{first}[,{last}]
+ // {first}[,{last}]d{first}
+ //
+ // unified diff looks like this:
+ // --- file1 2018-03-20 13:23:35.783153140 +0100
+ // +++ file2 2018-03-20 13:23:41.183156066 +0100
+ // @@ -1,3 +1,5 @@
+ if (isdigit(*line)) {
+ diffstyle = DIFF_ED;
+ } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "+++ ", 4) == 0)
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else {
+ // Format not recognized yet, skip over this line. Cygwin diff
+ // may put a warning at the start of the file.
+ continue;
+ }
}
- if (parse_diff_unified(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
+
+ if (diffstyle == DIFF_ED) {
+ if (!isdigit(*line)) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_ed(line, hunk) == FAIL) {
+ continue;
+ }
+ } else {
+ assert(diffstyle == DIFF_UNIFIED);
+ if (STRNCMP(line, "@@ ", 3) != 0) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_unified(line, hunk) == FAIL) {
+ continue;
+ }
}
}
// Go over blocks before the change, for which orig and new are equal.
// Copy blocks from orig to new.
while (dp != NULL
- && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
+ && hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
if (notset) {
diff_copy_entry(dprev, dp, idx_orig, idx_new);
}
@@ -1622,19 +1639,19 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
if ((dp != NULL)
- && (lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
- && (lnum_orig + count_orig >= dp->df_lnum[idx_orig])) {
+ && (hunk->lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
+ && (hunk->lnum_orig + hunk->count_orig >= dp->df_lnum[idx_orig])) {
// New block overlaps with existing block(s).
// First find last block that overlaps.
for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) {
- if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig]) {
+ if (hunk->lnum_orig + hunk->count_orig < dpl->df_next->df_lnum[idx_orig]) {
break;
}
}
// If the newly found block starts before the old one, set the
// start back a number of lines.
- off = dp->df_lnum[idx_orig] - lnum_orig;
+ off = dp->df_lnum[idx_orig] - hunk->lnum_orig;
if (off > 0) {
for (i = idx_orig; i < idx_new; ++i) {
@@ -1642,15 +1659,15 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
dp->df_lnum[i] -= off;
}
}
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
} else if (notset) {
// new block inside existing one, adjust new block
- dp->df_lnum[idx_new] = lnum_new + off;
- dp->df_count[idx_new] = count_new - off;
+ dp->df_lnum[idx_new] = hunk->lnum_new + off;
+ dp->df_count[idx_new] = hunk->count_new - off;
} else {
// second overlap of new block with existing block
- dp->df_count[idx_new] += count_new - count_orig
+ dp->df_count[idx_new] += hunk->count_new - hunk->count_orig
+ dpl->df_lnum[idx_orig] +
dpl->df_count[idx_orig]
- (dp->df_lnum[idx_orig] +
@@ -1659,7 +1676,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Adjust the size of the block to include all the lines to the
// end of the existing block or the new diff, whatever ends last.
- off = (lnum_orig + count_orig)
+ off = (hunk->lnum_orig + hunk->count_orig)
- (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]);
if (off < 0) {
@@ -1691,10 +1708,10 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Allocate a new diffblock.
dp = diff_alloc_new(curtab, dprev, dp);
- dp->df_lnum[idx_orig] = lnum_orig;
- dp->df_count[idx_orig] = count_orig;
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_orig] = hunk->lnum_orig;
+ dp->df_count[idx_orig] = hunk->count_orig;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
// Set values for other buffers, these must be equal to the
// original buffer, otherwise there would have been a change
@@ -1718,6 +1735,10 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
notset = true;
}
+ if (!dio->dio_internal) {
+ xfree(hunk);
+ }
+
if (fd != NULL) {
fclose(fd);
}
@@ -3026,8 +3047,7 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
/// Handle an ED style diff line.
/// Return FAIL if the line does not contain diff info.
///
-static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, linenr_T *lnum_new,
- long *count_new)
+static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
{
char_u *p;
long f1, l1, f2, l2;
@@ -3061,18 +3081,18 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
}
if (difftype == 'a') {
- *lnum_orig = f1 + 1;
- *count_orig = 0;
+ hunk->lnum_orig = f1 + 1;
+ hunk->count_orig = 0;
} else {
- *lnum_orig = f1;
- *count_orig = l1 - f1 + 1;
+ hunk->lnum_orig = f1;
+ hunk->count_orig = l1 - f1 + 1;
}
if (difftype == 'd') {
- *lnum_new = f2 + 1;
- *count_new = 0;
+ hunk->lnum_new = f2 + 1;
+ hunk->count_new = 0;
} else {
- *lnum_new = f2;
- *count_new = l2 - f2 + 1;
+ hunk->lnum_new = f2;
+ hunk->count_new = l2 - f2 + 1;
}
return OK;
}
@@ -3081,8 +3101,7 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
/// Parses unified diff with zero(!) context lines.
/// Return FAIL if there is no diff information in "line".
///
-static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_orig,
- linenr_T *lnum_new, long *count_new)
+static int parse_diff_unified(char_u *line, diffhunk_T *hunk)
{
char_u *p;
long oldline, oldcount, newline, newcount;
@@ -3120,10 +3139,10 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
newline = 1;
}
- *lnum_orig = oldline;
- *count_orig = oldcount;
- *lnum_new = newline;
- *count_new = newcount;
+ hunk->lnum_orig = oldline;
+ hunk->count_orig = oldcount;
+ hunk->lnum_new = newline;
+ hunk->count_new = newcount;
return OK;
}
@@ -3135,25 +3154,17 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
/// Callback function for the xdl_diff() function.
/// Stores the diff output in a grow array.
///
-static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf)
+static int xdiff_out(long start_a, long count_a, long start_b, long count_b,
+ void *priv)
{
diffout_T *dout = (diffout_T *)priv;
- char_u *p;
-
- // The header line always comes by itself, text lines in at least two
- // parts. We drop the text part.
- if (nbuf > 1) {
- return 0;
- }
-
- // sanity check
- if (STRNCMP(mb[0].ptr, "@@ ", 3) != 0) {
- return 0;
- }
+ diffhunk_T *p = xmalloc(sizeof(*p));
ga_grow(&dout->dout_ga, 1);
-
- p = vim_strnsave((char_u *)mb[0].ptr, mb[0].size);
- ((char_u **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
+ p->lnum_orig = start_a + 1;
+ p->count_orig = count_a;
+ p->lnum_new = start_b + 1;
+ p->count_new = count_b;
+ ((diffhunk_T **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
return 0;
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 5eef4350b7..aa37d1b2dd 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3620,7 +3620,7 @@ static bool ins_compl_prep(int c)
// Ignore end of Select mode mapping and mouse scroll buttons.
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT
- || c == K_COMMAND) {
+ || c == K_COMMAND || c == K_LUA) {
return retval;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 71c34f98ff..3a285cdf90 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4370,7 +4370,7 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep)
++i;
}
len = (int)STRLEN(p);
- new_cmdline = xmalloc(STRLEN(program) + i * (len - 2) + 1);
+ new_cmdline = xmalloc(STRLEN(program) + (size_t)i * (len - 2) + 1);
ptr = new_cmdline;
while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) {
i = (int)(pos - program);
@@ -6028,7 +6028,7 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
break;
}
- case ct_MODS: {
+ case ct_MODS:
result = quote ? 2 : 0;
if (buf != NULL) {
if (quote) {
@@ -6044,7 +6044,6 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
*buf = '"';
}
break;
- }
case ct_REGISTER:
result = eap->regname ? 1 : 0;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index c814974fe7..cfdbe7b344 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1131,12 +1131,12 @@ void ex_lua(exarg_T *const eap)
}
// When =expr is used transform it to print(vim.inspect(expr))
if (code[0] == '=') {
- len += sizeof("print(vim.inspect())") - sizeof("=");
+ len += sizeof("vim.pretty_print()") - sizeof("=");
// code_buf needs to be 1 char larger then len for null byte in the end.
// lua nlua_typval_exec doesn't expect null terminated string so len
// needs to end before null byte.
char *code_buf = xmallocz(len);
- vim_snprintf(code_buf, len+1, "print(vim.inspect(%s))", code+1);
+ vim_snprintf(code_buf, len+1, "vim.pretty_print(%s)", code+1);
xfree(code);
code = code_buf;
}
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 60a000843f..f4067ad02f 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -129,6 +129,10 @@ void tslua_init(lua_State *L)
build_meta(L, TS_META_QUERY, query_meta);
build_meta(L, TS_META_QUERYCURSOR, querycursor_meta);
build_meta(L, TS_META_TREECURSOR, treecursor_meta);
+
+#ifdef NVIM_TS_HAS_SET_ALLOCATOR
+ ts_set_allocator(xmalloc, xcalloc, xrealloc, xfree);
+#endif
}
int tslua_has_language(lua_State *L)
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 6ef46ee844..731e7d8d36 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -115,6 +115,9 @@ setmetatable(vim, {
elseif key == 'ui' then
t.ui = require('vim.ui')
return t.ui
+ elseif key == 'keymap' then
+ t.keymap = require('vim.keymap')
+ return t.keymap
end
end
})
@@ -422,23 +425,43 @@ function vim.defer_fn(fn, timeout)
end
---- Notification provider
+--- Display a notification to the user.
---
---- Without a runtime, writes to :Messages
----@see :help nvim_notify
----@param msg string Content of the notification to show to the user
----@param log_level number|nil enum from |vim.log.levels|
----@param opts table|nil additional options (timeout, etc)
-function vim.notify(msg, log_level, opts) -- luacheck: no unused
- if log_level == vim.log.levels.ERROR then
+--- This function can be overridden by plugins to display notifications using a
+--- custom provider (such as the system notification provider). By default,
+--- writes to |:messages|.
+---
+---@param msg string Content of the notification to show to the user.
+---@param level number|nil One of the values from |vim.log.levels|.
+---@param opts table|nil Optional parameters. Unused by default.
+function vim.notify(msg, level, opts) -- luacheck: no unused args
+ if level == vim.log.levels.ERROR then
vim.api.nvim_err_writeln(msg)
- elseif log_level == vim.log.levels.WARN then
+ elseif level == vim.log.levels.WARN then
vim.api.nvim_echo({{msg, 'WarningMsg'}}, true, {})
else
vim.api.nvim_echo({{msg}}, true, {})
end
end
+do
+ local notified = {}
+
+ --- Display a notification only one time.
+ ---
+ --- Like |vim.notify()|, but subsequent calls with the same message will not
+ --- display a notification.
+ ---
+ ---@param msg string Content of the notification to show to the user.
+ ---@param level number|nil One of the values from |vim.log.levels|.
+ ---@param opts table|nil Optional parameters. Unused by default.
+ function vim.notify_once(msg, level, opts) -- luacheck: no unused args
+ if not notified[msg] then
+ vim.notify(msg, level, opts)
+ notified[msg] = true
+ end
+ end
+end
---@private
function vim.register_keystroke_callback()
@@ -666,4 +689,23 @@ vim._expand_pat_get_parts = function(lua_string)
return parts, search_index
end
+---Prints given arguments in human-readable format.
+---Example:
+---<pre>
+--- -- Print highlight group Normal and store it's contents in a variable.
+--- local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true))
+---</pre>
+---@see |vim.inspect()|
+---@return given arguments.
+function vim.pretty_print(...)
+ local objects = {}
+ for i = 1, select('#', ...) do
+ local v = select(i, ...)
+ table.insert(objects, vim.inspect(v))
+ end
+
+ print(table.concat(objects, ' '))
+ return ...
+end
+
return module
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 3397296b3a..2a72d1e6a0 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -247,7 +247,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count)
} else { // need to allocate memory for this block
// If the number of pages matches use the bhdr_T from the free list and
// allocate the data.
- void *p = xmalloc(mfp->mf_page_size * page_count);
+ void *p = xmalloc((size_t)mfp->mf_page_size * page_count);
hp = mf_rem_free(mfp);
hp->bh_data = p;
}
@@ -269,7 +269,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count)
// Init the data to all zero, to avoid reading uninitialized data.
// This also avoids that the passwd file ends up in the swap file!
- (void)memset(hp->bh_data, 0, mfp->mf_page_size * page_count);
+ (void)memset(hp->bh_data, 0, (size_t)mfp->mf_page_size * page_count);
return hp;
}
@@ -528,7 +528,7 @@ bool mf_release_all(void)
static bhdr_T *mf_alloc_bhdr(memfile_T *mfp, unsigned page_count)
{
bhdr_T *hp = xmalloc(sizeof(bhdr_T));
- hp->bh_data = xmalloc(mfp->mf_page_size * page_count);
+ hp->bh_data = xmalloc((size_t)mfp->mf_page_size * page_count);
hp->bh_page_count = page_count;
return hp;
}
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 08521c0dc3..9925971783 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1032,9 +1032,9 @@ void ml_recover(bool checkext)
line_count = 0;
idx = 0; // start with first index in block 1
error = 0;
- buf->b_ml.ml_stack_top = 0;
+ buf->b_ml.ml_stack_top = 0; // -V1048
buf->b_ml.ml_stack = NULL;
- buf->b_ml.ml_stack_size = 0; // no stack yet
+ buf->b_ml.ml_stack_size = 0; // -V1048
if (curbuf->b_ffname == NULL) {
cannot_open = true;
@@ -4139,7 +4139,7 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
|| (offset != 0
&& offset > size +
buf->b_ml.ml_chunksize[curix].mlcs_totalsize
- + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) {
+ + (long)ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) {
curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize;
if (offset && ffdos) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b1ca8c5805..538604cf79 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -4130,7 +4130,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (((wp->w_p_cuc
&& (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off
&& (int)wp->w_virtcol <
- grid->Columns * (row - startrow + 1) + v
+ (long)grid->Columns * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum)
|| draw_color_col || line_attr_lowprio || line_attr
|| diff_hlf != (hlf_T)0 || has_virttext)) {
@@ -6762,7 +6762,7 @@ void grid_clear_line(ScreenGrid *grid, unsigned off, int width, bool valid)
void grid_invalidate(ScreenGrid *grid)
{
- (void)memset(grid->attrs, -1, grid->Rows * grid->Columns * sizeof(sattr_T));
+ (void)memset(grid->attrs, -1, sizeof(sattr_T) * grid->Rows * grid->Columns);
}
bool grid_invalid_row(ScreenGrid *grid, int row)
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 9429a06e92..1296d410f6 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -4082,7 +4082,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// char, e.g., "thes," -> "these".
p = fword + sp->ts_fidx;
MB_PTR_BACK(fword, p);
- if (!spell_iswordp(p, curwin)) {
+ if (!spell_iswordp(p, curwin) && *preword != NUL) {
p = preword + STRLEN(preword);
MB_PTR_BACK(preword, p);
if (spell_iswordp(p, curwin)) {
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 68bc76660d..1fe8bb671d 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -180,7 +180,7 @@ char *get_mode(void)
buf[1] = 'x';
}
}
- } else if (State & CMDLINE) {
+ } else if ((State & CMDLINE) || exmode_active) {
buf[0] = 'c';
if (exmode_active) {
buf[1] = 'v';
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index cc767a9bcf..c0ac4393c4 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -27,6 +27,7 @@ source test_join.vim
source test_jumps.vim
source test_fileformat.vim
source test_filetype.vim
+source test_filetype_lua.vim
source test_lambda.vim
source test_menu.vim
source test_messages.vim
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 4da68539fb..45a10cc193 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -195,7 +195,7 @@ let s:filename_checks = {
\ 'gedcom': ['file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'],
\ 'gemtext': ['file.gmi', 'file.gemini'],
\ 'gift': ['file.gift'],
- \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'],
+ \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'],
\ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'],
\ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'],
\ 'gitrebase': ['git-rebase-todo'],
@@ -1042,7 +1042,58 @@ func Test_dep3patch_file()
call assert_notequal('dep3patch', &filetype)
bwipe!
- call delete('debian/patches', 'rf')
+ call delete('debian', 'rf')
+endfunc
+
+func Test_patch_file()
+ filetype on
+
+ call writefile([], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('diff', &filetype)
+ bwipe!
+
+ call writefile(['From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001'], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('gitsendemail', &filetype)
+ bwipe!
+
+ call writefile(['From 0000000000000000000000000000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001'], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('gitsendemail', &filetype)
+ bwipe!
+
+ call delete('Xfile.patch')
+ filetype off
+endfunc
+
+func Test_git_file()
+ filetype on
+
+ call assert_true(mkdir('Xrepo.git', 'p'))
+
+ call writefile([], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('', &filetype)
+ bwipe!
+
+ call writefile(['0000000000000000000000000000000000000000'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call writefile(['0000000000000000000000000000000000000000000000000000000000000000'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call writefile(['ref: refs/heads/master'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call delete('Xrepo.git', 'rf')
+ filetype off
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype_lua.vim b/src/nvim/testdir/test_filetype_lua.vim
new file mode 100644
index 0000000000..f73e4ca33f
--- /dev/null
+++ b/src/nvim/testdir/test_filetype_lua.vim
@@ -0,0 +1,2 @@
+let g:do_filetype_lua = 1
+source test_filetype.vim
diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim
index 335a51268d..f7f7467e91 100644
--- a/src/nvim/testdir/test_search_stat.vim
+++ b/src/nvim/testdir/test_search_stat.vim
@@ -73,7 +73,6 @@ func Test_search_stat()
let stat = '\[2/50\]'
let g:a = execute(':unsilent :norm! n')
call assert_notmatch(pat .. stat, g:a)
- call writefile(getline(1, '$'), 'sample.txt')
" n does not update search stat
call assert_equal(
\ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index cf0faeee31..1ecb5c8070 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -768,6 +768,14 @@ func Test_spell_screendump()
call delete('XtestSpell')
endfunc
+func Test_spell_single_word()
+ new
+ silent! norm 0R00
+ spell! ßÂ
+ silent 0norm 0r$ Dvz=
+ bwipe!
+endfunc
+
let g:test_data_aff1 = [
\"SET ISO8859-1",
\"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ",