diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 34 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 20 | ||||
-rw-r--r-- | src/nvim/buffer_updates.c | 18 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 7 | ||||
-rw-r--r-- | src/nvim/fileio.c | 3 | ||||
-rw-r--r-- | src/nvim/getchar.c | 1 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 65 | ||||
-rw-r--r-- | src/nvim/mbyte.c | 58 | ||||
-rw-r--r-- | src/nvim/memline.c | 53 | ||||
-rw-r--r-- | src/nvim/misc1.c | 3 | ||||
-rw-r--r-- | src/nvim/spell.c | 6 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell.vim | 13 | ||||
-rw-r--r-- | src/nvim/version.c | 17 |
15 files changed, 279 insertions, 23 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index b0b65545ab..c6f82e9d85 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -109,9 +109,11 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// `nvim_buf_lines_event`. Otherwise, the first notification will be /// a `nvim_buf_changedtick_event`. Not used for lua callbacks. /// @param opts Optional parameters. -/// `on_lines`: lua callback received on change. +/// `on_lines`: lua callback received on change. /// `on_changedtick`: lua callback received on changedtick /// increment without text change. +/// `utf_sizes`: include UTF-32 and UTF-16 size of +/// the replaced region. /// See |api-buffer-updates-lua| for more information /// @param[out] err Error details, if any /// @return False when updates couldn't be enabled because the buffer isn't @@ -156,6 +158,12 @@ Boolean nvim_buf_attach(uint64_t channel_id, } cb.on_detach = v->data.luaref; v->data.integer = LUA_NOREF; + } else if (is_lua && strequal("utf_sizes", k.data)) { + if (v->type != kObjectTypeBoolean) { + api_set_error(err, kErrorTypeValidation, "utf_sizes must be boolean"); + goto error; + } + cb.utf_sizes = v->data.boolean; } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); goto error; @@ -1176,6 +1184,30 @@ free_exit: return 0; } +Dictionary nvim__buf_stats(Buffer buffer, Error *err) +{ + Dictionary rv = ARRAY_DICT_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return rv; + } + + // Number of times the cached line was flushed. + // This should generally not increase while editing the same + // line in the same mode. + PUT(rv, "flush_count", INTEGER_OBJ(buf->flush_count)); + // lnum of current line + PUT(rv, "current_lnum", INTEGER_OBJ(buf->b_ml.ml_line_lnum)); + // whether the line has unflushed changes. + PUT(rv, "line_dirty", BOOLEAN_OBJ(buf->b_ml.ml_flags & ML_LINE_DIRTY)); + // NB: this should be zero at any time API functions are called, + // this exists to debug issues + PUT(rv, "dirty_bytes", INTEGER_OBJ((Integer)buf->deleted_bytes)); + + return rv; +} + // Check if deleting lines made the cursor position invalid. // Changed lines from `lo` to `hi`; added `extra` lines (negative if deleted). static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 143737b478..b11eaefdd0 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -459,8 +459,9 @@ typedef struct { LuaRef on_lines; LuaRef on_changedtick; LuaRef on_detach; + bool utf_sizes; } BufUpdateCallbacks; -#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF } +#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF, false } #define BUF_HAS_QF_ENTRY 1 #define BUF_HAS_LL_ENTRY 2 @@ -802,11 +803,26 @@ struct file_buffer { kvec_t(BufhlLine *) b_bufhl_move_space; // temporary space for highlights - // array of channelids which have asked to receive updates for this + // array of channel_id:s which have asked to receive updates for this // buffer. kvec_t(uint64_t) update_channels; + // array of lua callbacks for buffer updates. kvec_t(BufUpdateCallbacks) update_callbacks; + // whether an update callback has requested codepoint size of deleted regions. + bool update_need_codepoints; + + // Measurements of the deleted or replaced region since the last update + // event. Some consumers of buffer changes need to know the byte size (like + // tree-sitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the + // deleted text. + size_t deleted_bytes; + size_t deleted_codepoints; + size_t deleted_codeunits; + + // The number for times the current line has been flushed in the memline. + int flush_count; + int b_diff_failed; // internal diff failed for this buffer }; diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index 21efda9fd9..3604578b50 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -26,6 +26,9 @@ bool buf_updates_register(buf_T *buf, uint64_t channel_id, if (channel_id == LUA_INTERNAL_CALL) { kv_push(buf->update_callbacks, cb); + if (cb.utf_sizes) { + buf->update_need_codepoints = true; + } return true; } @@ -169,6 +172,10 @@ void buf_updates_send_changes(buf_T *buf, int64_t num_removed, bool send_tick) { + size_t deleted_codepoints, deleted_codeunits; + size_t deleted_bytes = ml_flush_deleted_bytes(buf, &deleted_codepoints, + &deleted_codeunits); + if (!buf_updates_active(buf)) { return; } @@ -231,8 +238,8 @@ void buf_updates_send_changes(buf_T *buf, bool keep = true; if (cb.on_lines != LUA_NOREF) { Array args = ARRAY_DICT_INIT; - Object items[5]; - args.size = 5; + Object items[8]; + args.size = 6; // may be increased to 8 below args.items = items; // the first argument is always the buffer handle @@ -250,6 +257,13 @@ void buf_updates_send_changes(buf_T *buf, // the last line in the updated range args.items[4] = INTEGER_OBJ(firstline - 1 + num_added); + // byte count of previous contents + args.items[5] = INTEGER_OBJ((Integer)deleted_bytes); + if (cb.utf_sizes) { + args.size = 8; + args.items[6] = INTEGER_OBJ((Integer)deleted_codepoints); + args.items[7] = INTEGER_OBJ((Integer)deleted_codeunits); + } textlock++; Object res = executor_exec_lua_cb(cb.on_lines, "lines", args, true); textlock--; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index b315639681..bad844e9d5 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4060,10 +4060,9 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) return p; } -/* - * Expand file name in Ex command argument. - * Return FAIL for failure, OK otherwise. - */ +// Expand file name in Ex command argument. +// When an error is detected, "errormsgp" is set to a non-NULL pointer. +// Return FAIL for failure, OK otherwise. int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp) { int has_wildcards; /* need to expand wildcards */ diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 410c68017d..882bf1b830 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1761,6 +1761,9 @@ failed: ml_delete(curbuf->b_ml.ml_line_count, false); linecnt--; } + curbuf->deleted_bytes = 0; + curbuf->deleted_codepoints = 0; + curbuf->deleted_codeunits = 0; linecnt = curbuf->b_ml.ml_line_count - linecnt; if (filesize == 0) linecnt = 0; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index f7614fd3e1..03f64c2019 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1945,6 +1945,7 @@ static int vgetorpeek(int advance) // No matching mapping found or found a non-matching mapping that // matches at least what the matching mapping matched keylen = 0; + (void)keylen; // suppress clang/dead assignment // If there was no mapping, use the character from the typeahead // buffer right here. Otherwise, use the mapping (loop around). if (mp == NULL) { diff --git a/src/nvim/globals.h b/src/nvim/globals.h index d13b121562..b095e759d9 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -627,6 +627,8 @@ EXTERN pos_T Insstart_orig; EXTERN int orig_line_count INIT(= 0); /* Line count when "gR" started */ EXTERN int vr_lines_changed INIT(= 0); /* #Lines changed by "gR" so far */ +// increase around internal delete/replace +EXTERN int inhibit_delete_count INIT(= 0); /* * These flags are set based upon 'fileencoding'. diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 4051354d65..29682e8add 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -112,6 +112,65 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL return 1; } +/// convert byte index to UTF-32 and UTF-16 indicies +/// +/// Expects a string and an optional index. If no index is supplied, the length +/// of the string is returned. +/// +/// Returns two values: the UTF-32 and UTF-16 indicies. +static int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx; + if (lua_gettop(lstate) >= 2) { + idx = luaL_checkinteger(lstate, 2); + if (idx < 0 || idx > (intptr_t)s1_len) { + return luaL_error(lstate, "index out of range"); + } + } else { + idx = (intptr_t)s1_len; + } + + size_t codepoints = 0, codeunits = 0; + mb_utflen((const char_u *)s1, (size_t)idx, &codepoints, &codeunits); + + lua_pushinteger(lstate, (long)codepoints); + lua_pushinteger(lstate, (long)codeunits); + + return 2; +} + +/// convert UTF-32 or UTF-16 indicies to byte index. +/// +/// Expects up to three args: string, index and use_utf16. +/// If use_utf16 is not supplied it defaults to false (use UTF-32) +/// +/// Returns the byte index. +static int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL +{ + size_t s1_len; + const char *s1 = luaL_checklstring(lstate, 1, &s1_len); + intptr_t idx = luaL_checkinteger(lstate, 2); + if (idx < 0) { + return luaL_error(lstate, "index out of range"); + } + bool use_utf16 = false; + if (lua_gettop(lstate) >= 3) { + use_utf16 = lua_toboolean(lstate, 3); + } + + ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len, + (size_t)idx, use_utf16); + if (byteidx == -1) { + return luaL_error(lstate, "index out of range"); + } + + lua_pushinteger(lstate, (long)byteidx); + + return 1; +} + static void nlua_luv_error_event(void **argv) { char *error = (char *)argv[0]; @@ -220,6 +279,12 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // stricmp lua_pushcfunction(lstate, &nlua_stricmp); lua_setfield(lstate, -2, "stricmp"); + // str_utfindex + lua_pushcfunction(lstate, &nlua_str_utfindex); + lua_setfield(lstate, -2, "str_utfindex"); + // str_byteindex + lua_pushcfunction(lstate, &nlua_str_byteindex); + lua_setfield(lstate, -2, "str_byteindex"); // schedule lua_pushcfunction(lstate, &nlua_schedule); lua_setfield(lstate, -2, "schedule"); diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 3017f3c855..fae7635d34 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1438,6 +1438,64 @@ int utf16_to_utf8(const wchar_t *strw, char **str) #endif +/// Measure the length of a string in corresponding UTF-32 and UTF-16 units. +/// +/// Invalid UTF-8 bytes, or embedded surrogates, count as one code point/unit +/// each. +/// +/// The out parameters are incremented. This is used to measure the size of +/// a buffer region consisting of multiple line segments. +/// +/// @param s the string +/// @param len maximum length (an earlier NUL terminates) +/// @param[out] codepoints incremented with UTF-32 code point size +/// @param[out] codeunits incremented with UTF-16 code unit size +void mb_utflen(const char_u *s, size_t len, size_t *codepoints, + size_t *codeunits) + FUNC_ATTR_NONNULL_ALL +{ + size_t count = 0, extra = 0; + size_t clen; + for (size_t i = 0; i < len && s[i] != NUL; i += clen) { + clen = utf_ptr2len_len(s+i, len-i); + // NB: gets the byte value of invalid sequence bytes. + // we only care whether the char fits in the BMP or not + int c = (clen > 1) ? utf_ptr2char(s+i) : s[i]; + count++; + if (c > 0xFFFF) { + extra++; + } + } + *codepoints += count; + *codeunits += count + extra; +} + +ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, + size_t index, bool use_utf16_units) + FUNC_ATTR_NONNULL_ALL +{ + size_t count = 0; + size_t clen, i; + if (index == 0) { + return 0; + } + for (i = 0; i < len && s[i] != NUL; i += clen) { + clen = utf_ptr2len_len(s+i, len-i); + // NB: gets the byte value of invalid sequence bytes. + // we only care whether the char fits in the BMP or not + int c = (clen > 1) ? utf_ptr2char(s+i) : s[i]; + count++; + if (use_utf16_units && c > 0xFFFF) { + count++; + } + if (count >= index) { + return i+clen; + } + } + return -1; +} + + /* * Version of strnicmp() that handles multi-byte characters. * Needed for Big5, Shift-JIS and UTF-8 encoding. Other DBCS encodings can diff --git a/src/nvim/memline.c b/src/nvim/memline.c index b027459706..3220c7d9b8 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -2383,6 +2383,23 @@ static int ml_append_int( return OK; } +void ml_add_deleted_len(char_u *ptr, ssize_t len) +{ + if (inhibit_delete_count) { + return; + } + if (len == -1) { + len = STRLEN(ptr); + } + curbuf->deleted_bytes += len+1; + if (curbuf->update_need_codepoints) { + mb_utflen(ptr, len, &curbuf->deleted_codepoints, + &curbuf->deleted_codeunits); + curbuf->deleted_codepoints++; // NL char + curbuf->deleted_codeunits++; + } +} + /* * Replace line lnum, with buffering, in current buffer. * @@ -2403,13 +2420,24 @@ int ml_replace(linenr_T lnum, char_u *line, bool copy) if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL) return FAIL; + bool readlen = true; + if (copy) { line = vim_strsave(line); } - if (curbuf->b_ml.ml_line_lnum != lnum) /* other line buffered */ - ml_flush_line(curbuf); /* flush it */ - else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */ - xfree(curbuf->b_ml.ml_line_ptr); /* free it */ + if (curbuf->b_ml.ml_line_lnum != lnum) { // other line buffered + ml_flush_line(curbuf); // flush it + } else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) { // same line allocated + ml_add_deleted_len(curbuf->b_ml.ml_line_ptr, -1); + readlen = false; // already added the length + + xfree(curbuf->b_ml.ml_line_ptr); // free it + } + + if (readlen && kv_size(curbuf->update_callbacks)) { + ml_add_deleted_len(ml_get_buf(curbuf, lnum, false), -1); + } + curbuf->b_ml.ml_line_ptr = line; curbuf->b_ml.ml_line_lnum = lnum; curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; @@ -2491,6 +2519,10 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) else line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start; + // Line should always have an NL char internally (represented as NUL), + // even if 'noeol' is set. + assert(line_size >= 1); + ml_add_deleted_len((char_u *)dp + line_start, line_size-1); /* * special case: If there is only one line in the data block it becomes empty. @@ -2676,6 +2708,17 @@ void ml_clearmarked(void) return; } +size_t ml_flush_deleted_bytes(buf_T *buf, size_t *codepoints, size_t *codeunits) +{ + size_t ret = buf->deleted_bytes; + *codepoints = buf->deleted_codepoints; + *codeunits = buf->deleted_codeunits; + buf->deleted_bytes = 0; + buf->deleted_codepoints = 0; + buf->deleted_codeunits = 0; + return ret; +} + /* * flush ml_line if necessary */ @@ -2704,6 +2747,8 @@ static void ml_flush_line(buf_T *buf) return; entered = TRUE; + buf->flush_count++; + lnum = buf->b_ml.ml_line_lnum; new_line = buf->b_ml.ml_line_ptr; diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index db0d56b5fd..a62fa6d585 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -780,6 +780,7 @@ open_line ( did_append = FALSE; } + inhibit_delete_count++; if (newindent || did_si ) { @@ -821,6 +822,7 @@ open_line ( did_si = false; } } + inhibit_delete_count--; /* * In REPLACE mode, for each character in the extra leader, there must be @@ -1685,6 +1687,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) bool was_alloced = ml_line_alloced(); // check if oldp was allocated char_u *newp; if (was_alloced) { + ml_add_deleted_len(curbuf->b_ml.ml_line_ptr, oldlen); newp = oldp; // use same allocated memory } else { // need to allocate a new line newp = xmalloc((size_t)(oldlen + 1 - count)); diff --git a/src/nvim/spell.c b/src/nvim/spell.c index cc214616f4..404f279e73 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1807,9 +1807,11 @@ void count_common_word(slang_T *lp, char_u *word, int len, int count) char_u buf[MAXWLEN]; char_u *p; - if (len == -1) + if (len == -1) { p = word; - else { + } else if (len >= MAXWLEN) { + return; + } else { STRLCPY(buf, word, len + 1); p = buf; } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index d8d529d0f6..3b0f42aacd 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1306,7 +1306,7 @@ static void refresh_screen(Terminal *term, buf_T *buf) static void adjust_topline(Terminal *term, buf_T *buf, long added) { - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { linenr_T ml_end = buf->b_ml.ml_line_count; bool following = ml_end == wp->w_cursor.lnum + added; // cursor at end? diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index b3438cc649..d7b8ca9e9c 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -1,4 +1,5 @@ " Test spell checking +" Note: this file uses latin1 encoding, but is used with utf-8 encoding. if !has('spell') finish @@ -351,6 +352,18 @@ func Test_zeq_crash() bwipe! endfunc +" Check handling a word longer than MAXWLEN. +func Test_spell_long_word() + set enc=utf-8 + new + call setline(1, "d\xCC\xB4\xCC\xBD\xCD\x88\xCD\x94a\xCC\xB5\xCD\x84\xCD\x84\xCC\xA8\xCD\x9Cr\xCC\xB5\xCC\x8E\xCD\x85\xCD\x85k\xCC\xB6\xCC\x89\xCC\x9D \xCC\xB6\xCC\x83\xCC\x8F\xCC\xA4\xCD\x8Ef\xCC\xB7\xCC\x81\xCC\x80\xCC\xA9\xCC\xB0\xCC\xAC\xCC\xA2\xCD\x95\xCD\x87\xCD\x8D\xCC\x9E\xCD\x99\xCC\xAD\xCC\xAB\xCC\x97\xCC\xBBo\xCC\xB6\xCC\x84\xCC\x95\xCC\x8C\xCC\x8B\xCD\x9B\xCD\x9C\xCC\xAFr\xCC\xB7\xCC\x94\xCD\x83\xCD\x97\xCC\x8C\xCC\x82\xCD\x82\xCD\x80\xCD\x91\xCC\x80\xCC\xBE\xCC\x82\xCC\x8F\xCC\xA3\xCD\x85\xCC\xAE\xCD\x8D\xCD\x99\xCC\xBC\xCC\xAB\xCC\xA7\xCD\x88c\xCC\xB7\xCD\x83\xCC\x84\xCD\x92\xCC\x86\xCC\x83\xCC\x88\xCC\x92\xCC\x94\xCC\xBE\xCC\x9D\xCC\xAF\xCC\x98\xCC\x9D\xCC\xBB\xCD\x8E\xCC\xBB\xCC\xB3\xCC\xA3\xCD\x8E\xCD\x99\xCC\xA5\xCC\xAD\xCC\x99\xCC\xB9\xCC\xAE\xCC\xA5\xCC\x9E\xCD\x88\xCC\xAE\xCC\x9E\xCC\xA9\xCC\x97\xCC\xBC\xCC\x99\xCC\xA5\xCD\x87\xCC\x97\xCD\x8E\xCD\x94\xCC\x99\xCC\x9D\xCC\x96\xCD\x94\xCC\xAB\xCC\xA7\xCC\xA5\xCC\x98\xCC\xBB\xCC\xAF\xCC\xABe\xCC\xB7\xCC\x8E\xCC\x82\xCD\x86\xCD\x9B\xCC\x94\xCD\x83\xCC\x85\xCD\x8A\xCD\x8C\xCC\x8B\xCD\x92\xCD\x91\xCC\x8F\xCC\x81\xCD\x95\xCC\xA2\xCC\xB9\xCC\xB2\xCD\x9C\xCC\xB1\xCC\xA6\xCC\xB3\xCC\xAF\xCC\xAE\xCC\x9C\xCD\x99s\xCC\xB8\xCC\x8C\xCC\x8E\xCC\x87\xCD\x81\xCD\x82\xCC\x86\xCD\x8C\xCD\x8C\xCC\x8B\xCC\x84\xCC\x8C\xCD\x84\xCD\x9B\xCD\x86\xCC\x93\xCD\x90\xCC\x85\xCC\x94\xCD\x98\xCD\x84\xCD\x92\xCD\x8B\xCC\x90\xCC\x83\xCC\x8F\xCD\x84\xCD\x81\xCD\x9B\xCC\x90\xCD\x81\xCC\x8F\xCC\xBD\xCC\x88\xCC\xBF\xCC\x88\xCC\x84\xCC\x8E\xCD\x99\xCD\x94\xCC\x99\xCD\x99\xCC\xB0\xCC\xA8\xCC\xA3\xCC\xA8\xCC\x96\xCC\x99\xCC\xAE\xCC\xBC\xCC\x99\xCD\x9A\xCC\xB2\xCC\xB1\xCC\x9F\xCC\xBB\xCC\xA6\xCD\x85\xCC\xAA\xCD\x89\xCC\x9D\xCC\x99\xCD\x96\xCC\xB1\xCC\xB1\xCC\x99\xCC\xA6\xCC\xA5\xCD\x95\xCC\xB2\xCC\xA0\xCD\x99 within") + set spell spelllang=en + redraw + redraw! + bwipe! + set nospell +endfunc + func LoadAffAndDic(aff_contents, dic_contents) throw 'skipped: Nvim does not support enc=latin1' set enc=latin1 diff --git a/src/nvim/version.c b/src/nvim/version.c index f3326beb4c..74a4852def 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -2030,14 +2030,19 @@ static void version_msg(char *s) version_msg_wrap((char_u *)s, false); } -/// List all features aligned in columns, dictionary style. +/// List all features. +/// This does not use list_in_columns (as in Vim), because there are only a +/// few, and we do not start at a new line. static void list_features(void) { - list_in_columns((char_u **)features, -1, -1); - if (msg_col > 0) { - msg_putchar('\n'); + version_msg(_("\n\nFeatures: ")); + for (int i = 0; features[i] != NULL; i++) { + version_msg(features[i]); + if (features[i+1] != NULL) { + version_msg(" "); + } } - MSG_PUTS("See \":help feature-compile\"\n\n"); + version_msg("\nSee \":help feature-compile\"\n\n"); } /// List string items nicely aligned in columns. @@ -2146,8 +2151,6 @@ void list_version(void) } #endif // ifdef HAVE_PATHDEF - version_msg(_("\n\nFeatures: ")); - list_features(); #ifdef SYS_VIMRC_FILE |