aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/README.md2
-rw-r--r--src/nvim/api/buffer.c45
-rw-r--r--src/nvim/api/private/helpers.c37
-rw-r--r--src/nvim/api/vim.c42
-rw-r--r--src/nvim/autocmd.c14
-rw-r--r--src/nvim/buffer.c17
-rw-r--r--src/nvim/channel.c12
-rw-r--r--src/nvim/charset.c4
-rw-r--r--src/nvim/decoration.c2
-rw-r--r--src/nvim/edit.c10
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/eval/decode.c4
-rw-r--r--src/nvim/eval/encode.c4
-rw-r--r--src/nvim/eval/executor.c2
-rw-r--r--src/nvim/eval/funcs.c173
-rw-r--r--src/nvim/eval/typval.c37
-rw-r--r--src/nvim/event/libuv_process.c14
-rw-r--r--src/nvim/event/process.h3
-rw-r--r--src/nvim/ex_cmds.c31
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/ex_docmd.c30
-rw-r--r--src/nvim/ex_getln.c17
-rw-r--r--src/nvim/extmark.c9
-rw-r--r--src/nvim/file_search.c2
-rw-r--r--src/nvim/fold.c7
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/log.c18
-rw-r--r--src/nvim/lua/converter.c6
-rw-r--r--src/nvim/lua/executor.c89
-rw-r--r--src/nvim/lua/vim.lua171
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/mark.c1
-rw-r--r--src/nvim/message.c34
-rw-r--r--src/nvim/message.h9
-rw-r--r--src/nvim/normal.c29
-rw-r--r--src/nvim/ops.c4
-rw-r--r--src/nvim/option.c58
-rw-r--r--src/nvim/option_defs.h20
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/os/env.c53
-rw-r--r--src/nvim/os/pty_process_unix.c37
-rw-r--r--src/nvim/os/pty_process_win.c78
-rw-r--r--src/nvim/os/stdpaths.c11
-rw-r--r--src/nvim/os/time.c2
-rw-r--r--src/nvim/po/af.po7
-rw-r--r--src/nvim/po/ca.po4
-rw-r--r--src/nvim/po/cs.cp1250.po4
-rw-r--r--src/nvim/po/cs.po4
-rw-r--r--src/nvim/po/da.po3
-rw-r--r--src/nvim/po/de.po4
-rw-r--r--src/nvim/po/en_GB.po4
-rw-r--r--src/nvim/po/eo.po3
-rw-r--r--src/nvim/po/es.po4
-rw-r--r--src/nvim/po/fi.po7
-rw-r--r--src/nvim/po/fr.po3
-rw-r--r--src/nvim/po/ga.po3
-rw-r--r--src/nvim/po/it.po4
-rw-r--r--src/nvim/po/ja.euc-jp.po3
-rw-r--r--src/nvim/po/ja.po3
-rw-r--r--src/nvim/po/ko.UTF-8.po4
-rw-r--r--src/nvim/po/nb.po4
-rw-r--r--src/nvim/po/nl.po4
-rw-r--r--src/nvim/po/no.po4
-rw-r--r--src/nvim/po/pl.UTF-8.po4
-rw-r--r--src/nvim/po/pt_BR.po4
-rw-r--r--src/nvim/po/ru.po4
-rw-r--r--src/nvim/po/sk.cp1250.po4
-rw-r--r--src/nvim/po/sk.po4
-rw-r--r--src/nvim/po/sr.po3
-rw-r--r--src/nvim/po/sv.po4
-rw-r--r--src/nvim/po/uk.po253
-rw-r--r--src/nvim/po/vi.po4
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po4
-rw-r--r--src/nvim/po/zh_TW.UTF-8.po4
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/screen.c24
-rw-r--r--src/nvim/search.c87
-rw-r--r--src/nvim/shada.c16
-rw-r--r--src/nvim/spell.c11
-rw-r--r--src/nvim/spellfile.c3
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/terminal.c57
-rw-r--r--src/nvim/testdir/test_autocmd.vim40
-rw-r--r--src/nvim/testdir/test_backspace_opt.vim151
-rw-r--r--src/nvim/testdir/test_compiler.vim18
-rw-r--r--src/nvim/testdir/test_eval_stuff.vim11
-rw-r--r--src/nvim/testdir/test_filetype.vim56
-rw-r--r--src/nvim/testdir/test_fold.vim35
-rw-r--r--src/nvim/testdir/test_highlight.vim14
-rw-r--r--src/nvim/testdir/test_marks.vim5
-rw-r--r--src/nvim/testdir/test_mksession.vim26
-rw-r--r--src/nvim/testdir/test_options.vim25
-rw-r--r--src/nvim/testdir/test_quickfix.vim19
-rw-r--r--src/nvim/testdir/test_sleep.vim26
-rw-r--r--src/nvim/testdir/test_startup.vim78
-rw-r--r--src/nvim/testdir/test_window_cmd.vim4
-rw-r--r--src/nvim/tui/input.c2
-rw-r--r--src/nvim/ui_compositor.c2
-rw-r--r--src/nvim/version.c6
-rw-r--r--src/nvim/vim.h1
-rw-r--r--src/nvim/viml/parser/expressions.c6
102 files changed, 1713 insertions, 541 deletions
diff --git a/src/nvim/README.md b/src/nvim/README.md
index d14ba85546..affc5c79cc 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -38,7 +38,7 @@ alternate file (e.g. stderr) use `LOG_CALLSTACK_TO_FILE(FILE*)`. Requires
Many log messages have a shared prefix, such as "UI" or "RPC". Use the shell to
filter the log, e.g. at DEBUG level you might want to exclude UI messages:
- tail -F ~/.local/share/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
+ tail -F ~/.cache/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
Build with ASAN
---------------
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 8d82d22040..67f4f92bf6 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1200,8 +1200,7 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
/// @param ns_id Namespace id from |nvim_create_namespace()|
/// @param id Extmark id
/// @param opts Optional parameters. Keys:
-/// - limit: Maximum number of marks to return
-/// - details Whether to include the details dict
+/// - details: Whether to include the details dict
/// @param[out] err Error details, if any
/// @return (row, col) tuple or empty list () if extmark id was absent
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
@@ -1400,6 +1399,13 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// callbacks. The mark will only be used for the current
/// redraw cycle, and not be permantently stored in the
/// buffer.
+/// - right_gravity : boolean that indicates the direction
+/// the extmark will be shifted in when new text is inserted
+/// (true for right, false for left). defaults to true.
+/// - end_right_gravity : boolean that indicates the direction
+/// the extmark end position (if it exists) will be shifted
+/// in when new text is inserted (true for right, false
+/// for left). Defaults to false.
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
@@ -1440,6 +1446,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
DecorPriority priority = DECOR_PRIORITY_BASE;
colnr_T col2 = 0;
VirtText virt_text = KV_INITIAL_VALUE;
+ bool right_gravity = true;
+ bool end_right_gravity = false;
+ bool end_gravity_set = false;
+
for (size_t i = 0; i < opts.size; i++) {
String k = opts.items[i].key;
Object *v = &opts.items[i].value;
@@ -1522,12 +1532,35 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
goto error;
}
priority = (DecorPriority)v->data.integer;
+ } else if (strequal("right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "right_gravity must be a boolean");
+ goto error;
+ }
+ right_gravity = v->data.boolean;
+ } else if (strequal("end_right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_right_gravity must be a boolean");
+ goto error;
+ }
+ end_right_gravity = v->data.boolean;
+ end_gravity_set = true;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
}
}
+ // Only error out if they try to set end_right_gravity without
+ // setting end_col or end_line
+ if (line2 == -1 && col2 == 0 && end_gravity_set) {
+ api_set_error(err, kErrorTypeValidation,
+ "cannot set end_right_gravity "
+ "without setting end_line or end_col");
+ }
+
if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
@@ -1572,7 +1605,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
}
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
- line2, col2, decor, kExtmarkNoUndo);
+ line2, col2, decor, right_gravity,
+ end_right_gravity, kExtmarkNoUndo);
}
return (Integer)id;
@@ -1687,7 +1721,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
extmark_set(buf, ns_id, 0,
(int)line, (colnr_T)col_start,
end_line, (colnr_T)col_end,
- decor_hl(hl_id), kExtmarkNoUndo);
+ decor_hl(hl_id), true, false, kExtmarkNoUndo);
return src_id;
}
@@ -1796,7 +1830,8 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
Decoration *decor = xcalloc(1, sizeof(*decor));
decor->virt_text = virt_text;
- extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, kExtmarkNoUndo);
+ extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
+ false, kExtmarkNoUndo);
return src_id;
}
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 8f224e8c78..7cee569989 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1645,6 +1645,43 @@ bool api_object_to_bool(Object obj, const char *what,
}
}
+HlMessage parse_hl_msg(Array chunks, Error *err)
+{
+ HlMessage hl_msg = KV_INITIAL_VALUE;
+ for (size_t i = 0; i < chunks.size; i++) {
+ if (chunks.items[i].type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
+ goto free_exit;
+ }
+ Array chunk = chunks.items[i].data.array;
+ if (chunk.size == 0 || chunk.size > 2
+ || chunk.items[0].type != kObjectTypeString
+ || (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
+ api_set_error(err, kErrorTypeValidation,
+ "Chunk is not an array with one or two strings");
+ goto free_exit;
+ }
+
+ String str = copy_string(chunk.items[0].data.string);
+
+ int attr = 0;
+ if (chunk.size == 2) {
+ String hl = chunk.items[1].data.string;
+ if (hl.size > 0) {
+ int hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
+ attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
+ }
+ }
+ kv_push(hl_msg, ((HlMessageChunk){ .text = str, .attr = attr }));
+ }
+
+ return hl_msg;
+
+free_exit:
+ clear_hl_msg(&hl_msg);
+ return hl_msg;
+}
+
const char *describe_ns(NS ns_id)
{
String name;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 1e972e01be..09895a2119 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -990,6 +990,48 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err);
}
+/// Echo a message.
+///
+/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// text chunk with specified highlight. `hl_group` element
+/// can be omitted for no highlight.
+/// @param history if true, add to |message-history|.
+/// @param opts Optional parameters. Reserved for future use.
+void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
+ FUNC_API_SINCE(7)
+{
+ HlMessage hl_msg = parse_hl_msg(chunks, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ goto error;
+ }
+
+ no_wait_return++;
+ msg_start();
+ msg_clr_eos();
+ bool need_clear = false;
+ for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
+ HlMessageChunk chunk = kv_A(hl_msg, i);
+ msg_multiline_attr((const char *)chunk.text.data, chunk.attr,
+ false, &need_clear);
+ }
+ if (history) {
+ msg_ext_set_kind("echomsg");
+ add_hl_msg_hist(hl_msg);
+ } else {
+ msg_ext_set_kind("echo");
+ }
+ no_wait_return--;
+ msg_end();
+
+error:
+ clear_hl_msg(&hl_msg);
+}
+
/// Writes a message to the Vim output buffer. Does not append "\n", the
/// message is buffered (won't display) until a linefeed is written.
///
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 42224d0a4f..140a9c6bcb 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -700,11 +700,15 @@ void do_autocmd(char_u *arg_in, int forceit)
last_event = (event_T)-1; // for listing the event name
last_group = AUGROUP_ERROR; // for listing the group name
if (*arg == '*' || *arg == NUL || *arg == '|') {
- for (event_T event = (event_T)0; event < (int)NUM_EVENTS;
- event = (event_T)(event + 1)) {
- if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
- == FAIL) {
- break;
+ if (!forceit && *cmd != NUL) {
+ EMSG(_(e_cannot_define_autocommands_for_all_events));
+ } else {
+ for (event_T event = (event_T)0; event < (int)NUM_EVENTS;
+ event = (event_T)(event + 1)) {
+ if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
+ == FAIL) {
+ break;
+ }
}
}
} else {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 0134ee838d..7116b25b29 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -3270,7 +3270,7 @@ void maketitle(void)
case 6: buf_p = strappend(buf_p, " -"); break;
case 5:
case 7: buf_p = strappend(buf_p, " -+"); break;
- default: assert(false);
+ default: abort();
}
if (curbuf->b_fname != NULL) {
@@ -3486,7 +3486,7 @@ int build_stl_str_hl(
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
stl_hltab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
- stl_tabtab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
+ stl_tabtab = xmalloc(sizeof(StlClickRecord) * stl_items_len);
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
}
@@ -4482,22 +4482,15 @@ int build_stl_str_hl(
int num_separators = 0;
for (int i = 0; i < itemcnt; i++) {
if (stl_items[i].type == Separate) {
+ // Create an array of the start location for each
+ // separator mark.
+ stl_separator_locations[num_separators] = i;
num_separators++;
}
}
// If we have separated groups, then we deal with it now
if (num_separators) {
- // Create an array of the start location for each
- // separator mark.
- int index = 0;
- for (int i = 0; i < itemcnt; i++) {
- if (stl_items[i].type == Separate) {
- stl_separator_locations[index] = i;
- index++;
- }
- }
-
int standard_spaces = (maxwidth - width) / num_separators;
int final_spaces = (maxwidth - width) -
standard_spaces * (num_separators - 1);
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 37cbfb968b..5628ede2e6 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -304,7 +304,8 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
bool pty, bool rpc, bool overlapped, bool detach,
const char *cwd,
uint16_t pty_width, uint16_t pty_height,
- char *term_name, char **env, varnumber_T *status_out)
+ char *term_name, dict_T *env,
+ varnumber_T *status_out)
{
assert(cwd == NULL || os_isdir_executable(cwd));
@@ -358,7 +359,9 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
if (status) {
EMSG3(_(e_jobspawn), os_strerror(status), cmd);
xfree(cmd);
- os_free_fullenv(proc->env);
+ if (proc->env) {
+ tv_dict_free(proc->env);
+ }
if (proc->type == kProcessTypePty) {
xfree(chan->stream.pty.term_name);
}
@@ -367,8 +370,9 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
return NULL;
}
xfree(cmd);
- os_free_fullenv(proc->env);
-
+ if (proc->env) {
+ tv_dict_free(proc->env);
+ }
wstream_init(&proc->in, 0);
if (has_out) {
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 3e52b3e3ce..be265e3f27 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1747,7 +1747,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
goto vim_str2nr_dec;
}
default: {
- assert(false);
+ abort();
}
}
} else if ((what & (STR2NR_HEX|STR2NR_OCT|STR2NR_BIN))
@@ -1788,7 +1788,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len,
}
// Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
- assert(false); // Should’ve used goto earlier.
+ abort(); // Should’ve used goto earlier.
#define PARSE_NUMBER(base, cond, conv) \
do { \
while (!STRING_ENDED(ptr) && (cond)) { \
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index e6a616c927..f3ee42fab1 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -69,7 +69,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
}
(void)extmark_set(buf, (uint64_t)src_id, 0,
(int)lnum-1, hl_start, (int)lnum-1+end_off, hl_end,
- decor, kExtmarkNoUndo);
+ decor, true, false, kExtmarkNoUndo);
}
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 876e53e3cd..100e88e261 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -313,6 +313,11 @@ static void insert_enter(InsertState *s)
set_vim_var_string(VV_CHAR, NULL, -1);
ins_apply_autocmds(EVENT_INSERTENTER);
+ // Check for changed highlighting, e.g. for ModeMsg.
+ if (need_highlight_changed) {
+ highlight_changed();
+ }
+
// Make sure the cursor didn't move. Do call check_cursor_col() in
// case the text was modified. Since Insert mode was not started yet
// a call to check_cursor_col() may move the cursor, especially with
@@ -8282,8 +8287,9 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
}
} while (revins_on
|| (curwin->w_cursor.col > mincol
- && (curwin->w_cursor.lnum != Insstart_orig.lnum
- || curwin->w_cursor.col != Insstart_orig.col)));
+ && (can_bs(BS_NOSTOP)
+ || (curwin->w_cursor.lnum != Insstart_orig.lnum
+ || curwin->w_cursor.col != Insstart_orig.col))));
}
did_backspace = true;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 8a1556320c..a25b140b2f 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -365,7 +365,7 @@ void eval_init(void)
eval_msgpack_type_lists[i] = type_list;
if (tv_dict_add(msgpack_types_dict, di) == FAIL) {
// There must not be duplicate items in this dictionary by definition.
- assert(false);
+ abort();
}
}
msgpack_types_dict->dv_lock = VAR_FIXED;
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 638fef331a..bd4dc87d31 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -147,7 +147,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
tv_clear(&key.val);
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
== FAIL) {
- assert(false);
+ abort();
}
obj_di->di_tv = obj.val;
} else {
@@ -480,7 +480,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
break;
}
default: {
- assert(false);
+ abort();
}
}
} else {
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 9a9f2e4287..a4d7af7971 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -174,7 +174,7 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
case kMPConvPartial: {
switch (v.data.p.stage) {
case kMPConvPartialArgs: {
- assert(false);
+ abort();
break;
}
case kMPConvPartialSelf: {
@@ -237,7 +237,7 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len,
char *const buf = xmalloc(len);
size_t read_bytes;
if (encode_read_from_list(&lrstate, buf, len, &read_bytes) != OK) {
- assert(false);
+ abort();
}
assert(len == read_bytes);
*ret_buf = buf;
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index da05ecda43..bbba9d12f2 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -118,7 +118,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
return OK;
}
case VAR_UNKNOWN: {
- assert(false);
+ abort();
}
}
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 8235d74cbb..1a7bbf2d0e 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -1798,7 +1798,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
os_copy_fullenv(env, env_size);
- for (size_t i = 0; i < env_size; i++) {
+ for (ssize_t i = env_size - 1; i >= 0; i--) {
const char * str = env[i];
const char * const end = strchr(str + (str[0] == '=' ? 1 : 0),
'=');
@@ -1806,6 +1806,12 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
ptrdiff_t len = end - str;
assert(len > 0);
const char * value = str + len + 1;
+ if (tv_dict_find(rettv->vval.v_dict, str, len) != NULL) {
+ // Since we're traversing from the end of the env block to the front, any
+ // duplicate names encountered should be ignored. This preserves the
+ // semantics of env vars defined later in the env block taking precedence.
+ continue;
+ }
tv_dict_add_str(rettv->vval.v_dict,
str, len,
value);
@@ -3301,7 +3307,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
break;
case kCdScopeInvalid: // We should never get here
- assert(false);
+ abort();
}
if (from) {
@@ -4354,7 +4360,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
case kCdScopeInvalid:
// We should never get here
- assert(false);
+ abort();
}
}
@@ -4875,6 +4881,95 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = 1;
}
+static const char *ignored_env_vars[] = {
+#ifndef WIN32
+ "COLUMNS",
+ "LINES",
+ "TERMCAP",
+ "COLORFGBG",
+#endif
+ NULL
+};
+
+/// According to comments in src/win/process.c of libuv, Windows has a few
+/// "essential" environment variables.
+static const char *required_env_vars[] = {
+#ifdef WIN32
+ "HOMEDRIVE",
+ "HOMEPATH",
+ "LOGONSERVER",
+ "PATH",
+ "SYSTEMDRIVE",
+ "SYSTEMROOT",
+ "TEMP",
+ "USERDOMAIN",
+ "USERNAME",
+ "USERPROFILE",
+ "WINDIR",
+#endif
+ NULL
+};
+
+static dict_T *create_environment(const dictitem_T *job_env,
+ const bool clear_env,
+ const bool pty)
+{
+ dict_T * env = tv_dict_alloc();
+
+ if (!clear_env) {
+ typval_T temp_env = TV_INITIAL_VALUE;
+ f_environ(NULL, &temp_env, NULL);
+ tv_dict_extend(env, temp_env.vval.v_dict, "force");
+ tv_dict_free(temp_env.vval.v_dict);
+
+ if (pty) {
+ // These environment variables generally shouldn't be propagated to the
+ // child process. We're removing them here so the user can still decide
+ // they want to explicitly set them.
+ for (size_t i = 0;
+ i < ARRAY_SIZE(ignored_env_vars) && ignored_env_vars[i];
+ i++) {
+ dictitem_T *dv = tv_dict_find(env, ignored_env_vars[i], -1);
+ if (dv) {
+ tv_dict_item_remove(env, dv);
+ }
+ }
+#ifndef WIN32
+ // Set COLORTERM to "truecolor" if termguicolors is set and 256
+ // otherwise, but only if it was set in the parent terminal at all
+ dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM"));
+ if (dv) {
+ tv_dict_item_remove(env, dv);
+ tv_dict_add_str(env, S_LEN("COLORTERM"), p_tgc ? "truecolor" : "256");
+ }
+#endif
+ }
+ }
+
+ if (job_env) {
+ tv_dict_extend(env, job_env->di_tv.vval.v_dict, "force");
+ }
+
+ if (pty) {
+ // Now that the custom environment is configured, we need to ensure certain
+ // environment variables are present.
+ for (size_t i = 0;
+ i < ARRAY_SIZE(required_env_vars) && required_env_vars[i];
+ i++) {
+ size_t len = strlen(required_env_vars[i]);
+ dictitem_T *dv = tv_dict_find(env, required_env_vars[i], len);
+ if (!dv) {
+ const char *env_var = os_getenv(required_env_vars[i]);
+ if (env_var) {
+ tv_dict_add_str(env, required_env_vars[i], len, env_var);
+ }
+ }
+ }
+ }
+
+ return env;
+}
+
// "jobstart()" function
static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
@@ -4887,7 +4982,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
bool executable = true;
char **argv = tv_to_argv(&argvars[0], NULL, &executable);
- char **env = NULL;
+ dict_T *env = NULL;
if (!argv) {
rettv->vval.v_number = executable ? 0 : -1;
return; // Did error message in tv_to_argv.
@@ -4911,6 +5006,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
on_stderr = CALLBACK_READER_INIT;
Callback on_exit = CALLBACK_NONE;
char *cwd = NULL;
+ dictitem_T *job_env = NULL;
if (argvars[1].v_type == VAR_DICT) {
job_opts = argvars[1].vval.v_dict;
@@ -4936,7 +5032,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#endif
char *new_cwd = tv_dict_get_string(job_opts, "cwd", false);
- if (new_cwd && strlen(new_cwd) > 0) {
+ if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
if (!os_isdir_executable((const char *)cwd)) {
@@ -4945,52 +5041,22 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
}
- dictitem_T *job_env = tv_dict_find(job_opts, S_LEN("env"));
- if (job_env) {
- if (job_env->di_tv.v_type != VAR_DICT) {
- EMSG2(_(e_invarg2), "env");
- shell_free_argv(argv);
- return;
- }
-
- size_t custom_env_size = (size_t)tv_dict_len(job_env->di_tv.vval.v_dict);
- size_t i = 0;
- size_t env_size = 0;
-
- if (clear_env) {
- // + 1 for last null entry
- env = xmalloc((custom_env_size + 1) * sizeof(*env));
- env_size = 0;
- } else {
- env_size = os_get_fullenv_size();
- env = xmalloc((custom_env_size + env_size + 1) * sizeof(*env));
-
- os_copy_fullenv(env, env_size);
- i = env_size;
- }
- assert(env); // env must be allocated at this point
-
- TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, {
- const char *str = tv_get_string(&var->di_tv);
- assert(str);
- size_t len = STRLEN(var->di_key) + strlen(str) + strlen("=") + 1;
- env[i] = xmalloc(len);
- snprintf(env[i], len, "%s=%s", (char *)var->di_key, str);
- i++;
- });
-
- // must be null terminated
- env[env_size + custom_env_size] = NULL;
+ job_env = tv_dict_find(job_opts, S_LEN("env"));
+ if (job_env && job_env->di_tv.v_type != VAR_DICT) {
+ EMSG2(_(e_invarg2), "env");
+ shell_free_argv(argv);
+ return;
}
-
if (!common_job_callbacks(job_opts, &on_stdout, &on_stderr, &on_exit)) {
shell_free_argv(argv);
return;
}
}
+ env = create_environment(job_env, clear_env, pty);
+
uint16_t width = 0, height = 0;
char *term_name = NULL;
@@ -10518,6 +10584,11 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
Callback on_exit = CALLBACK_NONE;
dict_T *job_opts = NULL;
const char *cwd = ".";
+ dict_T *env = NULL;
+ const bool pty = true;
+ bool clear_env = false;
+ dictitem_T *job_env = NULL;
+
if (argvars[1].v_type == VAR_DICT) {
job_opts = argvars[1].vval.v_dict;
@@ -10532,17 +10603,31 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+ job_env = tv_dict_find(job_opts, S_LEN("env"));
+ if (job_env && job_env->di_tv.v_type != VAR_DICT) {
+ EMSG2(_(e_invarg2), "env");
+ shell_free_argv(argv);
+ return;
+ }
+
+ clear_env = tv_dict_get_number(job_opts, "clear_env") != 0;
+
if (!common_job_callbacks(job_opts, &on_stdout, &on_stderr, &on_exit)) {
shell_free_argv(argv);
return;
}
}
+ env = create_environment(job_env, clear_env, pty);
+
+ const bool rpc = false;
+ const bool overlapped = false;
+ const bool detach = false;
uint16_t term_width = MAX(0, curwin->w_width_inner - win_col_off(curwin));
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit,
- true, false, false, false, cwd,
+ pty, rpc, overlapped, detach, cwd,
term_width, curwin->w_height_inner,
- xstrdup("xterm-256color"), NULL,
+ xstrdup("xterm-256color"), env,
&rettv->vval.v_number);
if (rettv->vval.v_number <= 0) {
return;
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 02d32a4f86..9be487f4fd 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -1523,6 +1523,33 @@ varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key)
return tv_get_number(&di->di_tv);
}
+/// Converts a dict to an environment
+///
+///
+char **tv_dict_to_env(dict_T *denv)
+{
+ size_t env_size = (size_t)tv_dict_len(denv);
+
+ size_t i = 0;
+ char **env = NULL;
+
+ // + 1 for NULL
+ env = xmalloc((env_size + 1) * sizeof(*env));
+
+ TV_DICT_ITER(denv, var, {
+ const char *str = tv_get_string(&var->di_tv);
+ assert(str);
+ size_t len = STRLEN(var->di_key) + strlen(str) + strlen("=") + 1;
+ env[i] = xmalloc(len);
+ snprintf(env[i], len, "%s=%s", (char *)var->di_key, str);
+ i++;
+ });
+
+ // must be null terminated
+ env[env_size] = NULL;
+ return env;
+}
+
/// Get a string item from a dictionary
///
/// @param[in] d Dictionary to get item from.
@@ -2494,7 +2521,7 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
break;
}
case VAR_UNKNOWN: {
- assert(false);
+ abort();
}
}
#undef CHANGE_LOCK
@@ -2666,7 +2693,7 @@ bool tv_equal(typval_T *const tv1, typval_T *const tv2, const bool ic,
}
}
- assert(false);
+ abort();
return false;
}
@@ -2719,7 +2746,7 @@ bool tv_check_str_or_nr(const typval_T *const tv)
return false;
}
}
- assert(false);
+ abort();
return false;
}
@@ -2764,7 +2791,7 @@ bool tv_check_num(const typval_T *const tv)
return false;
}
}
- assert(false);
+ abort();
return false;
}
@@ -2809,7 +2836,7 @@ bool tv_check_str(const typval_T *const tv)
return false;
}
}
- assert(false);
+ abort();
return false;
}
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index 13517d3df1..0b1ecb12e2 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -41,7 +41,6 @@ int libuv_process_spawn(LibuvProcess *uvproc)
#endif
uvproc->uvopts.exit_cb = exit_cb;
uvproc->uvopts.cwd = proc->cwd;
- uvproc->uvopts.env = proc->env;
uvproc->uvopts.stdio = uvproc->uvstdio;
uvproc->uvopts.stdio_count = 3;
uvproc->uvstdio[0].flags = UV_IGNORE;
@@ -49,6 +48,12 @@ int libuv_process_spawn(LibuvProcess *uvproc)
uvproc->uvstdio[2].flags = UV_IGNORE;
uvproc->uv.data = proc;
+ if (proc->env) {
+ uvproc->uvopts.env = tv_dict_to_env(proc->env);
+ } else {
+ uvproc->uvopts.env = NULL;
+ }
+
if (!proc->in.closed) {
uvproc->uvstdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
#ifdef WIN32
@@ -78,6 +83,9 @@ int libuv_process_spawn(LibuvProcess *uvproc)
int status;
if ((status = uv_spawn(&proc->loop->uv, &uvproc->uv, &uvproc->uvopts))) {
ELOG("uv_spawn failed: %s", uv_strerror(status));
+ if (uvproc->uvopts.env) {
+ os_free_fullenv(uvproc->uvopts.env);
+ }
return status;
}
@@ -97,6 +105,10 @@ static void close_cb(uv_handle_t *handle)
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
+ LibuvProcess *uvproc = (LibuvProcess *)proc;
+ if (uvproc->uvopts.env) {
+ os_free_fullenv(uvproc->uvopts.env);
+ }
}
static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 84e81238e9..24debdb276 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -4,6 +4,7 @@
#include "nvim/event/loop.h"
#include "nvim/event/rstream.h"
#include "nvim/event/wstream.h"
+#include "nvim/eval/typval.h"
typedef enum {
kProcessTypeUv,
@@ -23,7 +24,7 @@ struct process {
uint64_t stopped_time; // process_stop() timestamp
const char *cwd;
char **argv;
- char **env;
+ dict_T *env;
Stream in, out, err;
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 61e4d634c6..6d26c5f69c 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -790,7 +790,10 @@ void ex_retab(exarg_T *eap)
for (col = 0; col < len; col++) {
ptr[col] = (col < num_tabs) ? '\t' : ' ';
}
- ml_replace(lnum, new_line, false);
+ if (ml_replace(lnum, new_line, false) == OK) {
+ // "new_line" may have been copied
+ new_line = curbuf->b_ml.ml_line_ptr;
+ }
if (first_line == 0) {
first_line = lnum;
}
@@ -2413,7 +2416,10 @@ int do_ecmd(
(flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
false);
- the_curwin->w_closing = false;
+ // Autocommands may have closed the window.
+ if (win_valid(the_curwin)) {
+ the_curwin->w_closing = false;
+ }
buf->b_locked--;
// autocmds may abort script processing
@@ -3126,6 +3132,9 @@ static bool sub_joining_lines(exarg_T *eap, char_u *pat, char_u *sub,
|| *cmd == 'l'
|| *cmd == 'p'
|| *cmd == '#')))) {
+ if (eap->skip) {
+ return true;
+ }
curwin->w_cursor.lnum = eap->line1;
if (*cmd == 'l') {
eap->flags = EXFLAG_LIST;
@@ -3307,11 +3316,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int save_b_changed = curbuf->b_changed;
bool preview = (State & CMDPREVIEW);
- // inccommand tests fail without this check
- if (!preview) {
- // Required for Undo to work for extmarks.
- u_save_cursor();
- }
+ bool did_save = false;
if (!global_busy) {
sub_nsubs = 0;
@@ -3693,6 +3698,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
} else {
char_u *orig_line = NULL;
int len_change = 0;
+ const bool save_p_lz = p_lz;
int save_p_fen = curwin->w_p_fen;
curwin->w_p_fen = FALSE;
@@ -3701,6 +3707,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int temp = RedrawingDisabled;
RedrawingDisabled = 0;
+ // avoid calling update_screen() in vgetorpeek()
+ p_lz = false;
+
if (new_start != NULL) {
/* There already was a substitution, we would
* like to show this to the user. We cannot
@@ -3754,7 +3763,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
/* clear the question */
msg_didout = FALSE; /* don't scroll up */
msg_col = 0;
- gotocmdline(TRUE);
+ gotocmdline(true);
+ p_lz = save_p_lz;
// restore the line
if (orig_line != NULL) {
@@ -3983,6 +3993,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
int matchcols = end.col - ((end.lnum == start.lnum)
? start.col : 0);
int subcols = new_endcol - ((lnum == lnum_start) ? start_col : 0);
+ if (!did_save) {
+ // Required for Undo to work for extmarks.
+ u_save_cursor();
+ did_save = true;
+ }
extmark_splice(curbuf, lnum_start-1, start_col,
end.lnum-start.lnum, matchcols, replaced_bytes,
lnum-lnum_start, subcols, sublen-1, kExtmarkUndo);
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 069d5d461b..e9046da800 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2455,7 +2455,7 @@ module.cmds = {
},
{
command='sleep',
- flags=bit.bor(RANGE, COUNT, EXTRA, TRLBAR, CMDWIN),
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, CMDWIN),
addr_type='ADDR_OTHER',
func='ex_sleep',
},
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index c400975108..e49bb99aa0 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -1639,10 +1639,10 @@ int get_arglist_exp(char_u *str, int *fcountp, char_u ***fnamesp, bool wig)
if (wig) {
i = expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
- fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
+ fcountp, fnamesp, EW_FILE|EW_NOTFOUND|EW_NOTWILD);
} else {
i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data,
- fcountp, fnamesp, EW_FILE|EW_NOTFOUND);
+ fcountp, fnamesp, EW_FILE|EW_NOTFOUND|EW_NOTWILD);
}
ga_clear(&ga);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index ccf7dd0f68..52da7fe4f6 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -317,7 +317,9 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
int count = 0; /* line number count */
int did_inc = FALSE; /* incremented RedrawingDisabled */
int retval = OK;
- cstack_T cstack; // conditional stack
+ cstack_T cstack = { // conditional stack
+ .cs_idx = -1,
+ };
garray_T lines_ga; // keep lines for ":while"/":for"
int current_line = 0; // active line in lines_ga
char_u *fname = NULL; // function or script name
@@ -360,11 +362,6 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
call_depth++;
start_batch_changes();
- cstack.cs_idx = -1;
- cstack.cs_looplevel = 0;
- cstack.cs_trylevel = 0;
- cstack.cs_emsg_silent_list = NULL;
- cstack.cs_lflags = 0;
ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
real_cookie = getline_cookie(fgetline, cookie);
@@ -3041,9 +3038,10 @@ const char * set_one_cmd_context(
p = arg + 1;
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
- /* Still touching the command after '+'? */
- if (*arg == NUL)
+ // Still touching the command after '+'?
+ if (*arg == NUL) {
return p;
+ }
// Skip space(s) after +command to get to the real argument.
arg = (const char *)skipwhite((const char_u *)arg);
@@ -3680,6 +3678,10 @@ const char * set_one_cmd_context(
xp->xp_pattern = (char_u *)arg;
break;
+ case CMD_lua:
+ xp->xp_context = EXPAND_LUA;
+ break;
+
default:
break;
}
@@ -3968,7 +3970,7 @@ static linenr_T get_address(exarg_T *eap,
break;
default:
- if (ascii_isdigit(*cmd)) { // absolute line number
+ if (ascii_isdigit(*cmd)) { // absolute line number
lnum = getdigits_long(&cmd, false, 0);
}
}
@@ -5187,6 +5189,7 @@ static const char *command_complete[] =
#ifdef HAVE_WORKING_LIBINTL
[EXPAND_LOCALES] = "locale",
#endif
+ [EXPAND_LUA] = "lua",
[EXPAND_MAPCLEAR] = "mapclear",
[EXPAND_MAPPINGS] = "mapping",
[EXPAND_MENUS] = "menu",
@@ -5400,8 +5403,8 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
size_t vallen = 0;
size_t attrlen = len;
- /* Look for the attribute name - which is the part before any '=' */
- for (i = 0; i < (int)len; ++i) {
+ // Look for the attribute name - which is the part before any '='
+ for (i = 0; i < (int)len; i++) {
if (attr[i] == '=') {
val = &attr[i + 1];
vallen = len - i - 1;
@@ -7503,8 +7506,9 @@ static void ex_read(exarg_T *eap)
}
if (*eap->arg == NUL) {
- if (check_fname() == FAIL) /* check for no file name */
+ if (check_fname() == FAIL) { // check for no file name
return;
+ }
i = readfile(curbuf->b_ffname, curbuf->b_fname,
eap->line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, 0);
} else {
@@ -7587,7 +7591,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
curwin->w_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeInvalid:
- assert(false);
+ abort();
}
shorten_fnames(true);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 626b840798..cf6bb6d492 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -69,6 +69,7 @@
#include "nvim/lib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/highlight_defs.h"
+#include "nvim/lua/executor.h"
#include "nvim/viml/parser/parser.h"
#include "nvim/viml/parser/expressions.h"
@@ -3828,7 +3829,7 @@ static void cmd_cursor_goto(int row, int col)
ui_grid_cursor_goto(grid->handle, row, col);
}
-void gotocmdline(int clr)
+void gotocmdline(bool clr)
{
if (ui_has(kUICmdline)) {
return;
@@ -3945,6 +3946,12 @@ nextwild (
p2 = ExpandOne(xp, p1, vim_strnsave(&ccline.cmdbuff[i], xp->xp_pattern_len),
use_options, type);
xfree(p1);
+
+ // xp->xp_pattern might have been modified by ExpandOne (for example,
+ // in lua completion), so recompute the pattern index and length
+ i = (int)(xp->xp_pattern - ccline.cmdbuff);
+ xp->xp_pattern_len = (size_t)ccline.cmdpos - (size_t)i;
+
// Longest match: make sure it is not shorter, happens with :help.
if (p2 != NULL && type == WILD_LONGEST) {
for (j = 0; (size_t)j < xp->xp_pattern_len; j++) {
@@ -3960,7 +3967,7 @@ nextwild (
}
if (p2 != NULL && !got_int) {
- difflen = (int)STRLEN(p2) - (int)xp->xp_pattern_len;
+ difflen = (int)STRLEN(p2) - (int)(xp->xp_pattern_len);
if (ccline.cmdlen + difflen + 4 > ccline.cmdbufflen) {
realloc_cmdbuff(ccline.cmdlen + difflen + 4);
xp->xp_pattern = ccline.cmdbuff + i;
@@ -5106,6 +5113,10 @@ ExpandFromContext (
if (xp->xp_context == EXPAND_PACKADD) {
return ExpandPackAddDir(pat, num_file, file);
}
+ if (xp->xp_context == EXPAND_LUA) {
+ ILOG("PAT %s", pat);
+ return nlua_expand_pat(xp, pat, num_file, file);
+ }
regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
if (regmatch.regprog == NULL)
@@ -6372,7 +6383,7 @@ int hist_type2char(int type)
return '>';
}
default: {
- assert(false);
+ abort();
}
}
return NUL;
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index b2d8532cd7..cacbeddb32 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -71,7 +71,8 @@ static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) {
/// @returns the mark id
uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
int row, colnr_T col, int end_row, colnr_T end_col,
- Decoration *decor, ExtmarkOp op)
+ Decoration *decor, bool right_gravity,
+ bool end_right_gravity, ExtmarkOp op)
{
ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true);
assert(ns != NULL);
@@ -109,10 +110,10 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
if (end_row > -1) {
mark = marktree_put_pair(buf->b_marktree,
- row, col, true,
- end_row, end_col, false);
+ row, col, right_gravity,
+ end_row, end_col, end_right_gravity);
} else {
- mark = marktree_put(buf->b_marktree, row, col, true);
+ mark = marktree_put(buf->b_marktree, row, col, right_gravity);
}
revised:
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index b1fa0b6779..8beba38509 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1595,7 +1595,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
}
case kCdScopeInvalid: {
// Should never happen.
- assert(false);
+ abort();
}
}
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 0593c16999..5032646d7e 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2999,7 +2999,6 @@ static void foldlevelDiff(fline_T *flp)
static void foldlevelExpr(fline_T *flp)
{
win_T *win;
- int n;
int c;
linenr_T lnum = flp->lnum + flp->off;
@@ -3017,7 +3016,7 @@ static void foldlevelExpr(fline_T *flp)
/* KeyTyped may be reset to 0 when calling a function which invokes
* do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */
const bool save_keytyped = KeyTyped;
- n = (int)eval_foldexpr(flp->wp->w_p_fde, &c);
+ const int n = eval_foldexpr(flp->wp->w_p_fde, &c);
KeyTyped = save_keytyped;
switch (c) {
@@ -3202,8 +3201,10 @@ int put_folds(FILE *fd, win_T *wp)
{
if (foldmethodIsManual(wp)) {
if (put_line(fd, "silent! normal! zE") == FAIL
- || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL)
+ || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL
+ || put_line(fd, "let &fdl = &fdl") == FAIL) {
return FAIL;
+ }
}
/* If some folds are manually opened/closed, need to restore that. */
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 3b8f4116b7..22f06941aa 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1009,6 +1009,8 @@ EXTERN char_u e_floatonly[] INIT(=N_(
EXTERN char_u e_floatexchange[] INIT(=N_(
"E5602: Cannot exchange or rotate float"));
+EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_(
+ "E1155: Cannot define autocommands for ALL events"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"));
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 19203a3c2a..324382a0f7 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -51,7 +51,7 @@ static bool log_try_create(char *fname)
/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty.
///
-/// Tries $NVIM_LOG_FILE, or falls back to $XDG_DATA_HOME/nvim/log. Path to log
+/// Tries $NVIM_LOG_FILE, or falls back to $XDG_CACHE_HOME/nvim/log. Path to log
/// file is cached, so only the first call has effect, unless first call was not
/// successful. Failed initialization indicates either a bug in expand_env()
/// or both $NVIM_LOG_FILE and $HOME environment variables are undefined.
@@ -69,8 +69,16 @@ static bool log_path_init(void)
|| log_file_path[0] == '\0'
|| os_isdir((char_u *)log_file_path)
|| !log_try_create(log_file_path)) {
+ // Make kXDGCacheHome if it does not exist.
+ char *cachehome = get_xdg_home(kXDGCacheHome);
+ char *failed_dir = NULL;
+ bool log_dir_failure = false;
+ if (!os_isdir((char_u *)cachehome)) {
+ log_dir_failure = (os_mkdir_recurse(cachehome, 0700, &failed_dir) != 0);
+ }
+ XFREE_CLEAR(cachehome);
// Invalid $NVIM_LOG_FILE or failed to expand; fall back to default.
- char *defaultpath = stdpaths_user_data_subpath("log", 0, true);
+ char *defaultpath = stdpaths_user_cache_subpath("log");
size_t len = xstrlcpy(log_file_path, defaultpath, size);
xfree(defaultpath);
// Fall back to .nvimlog
@@ -83,6 +91,11 @@ static bool log_path_init(void)
return false;
}
os_setenv(LOG_FILE_ENV, log_file_path, true);
+ if (log_dir_failure) {
+ WLOG("Failed to create directory %s for writing logs: %s",
+ failed_dir, os_strerror(log_dir_failure));
+ }
+ XFREE_CLEAR(failed_dir);
}
return true;
}
@@ -323,4 +336,3 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
return true;
}
-
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 030df69caa..83b3729ad3 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -245,7 +245,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
} else {
dictitem_T *const di = tv_dict_item_alloc_len(s, len);
if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) {
- assert(false);
+ abort();
}
kv_push(stack, cur);
cur = (TVPopStackItem) { &di->di_tv, false, false, 0 };
@@ -391,7 +391,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
break;
}
default: {
- assert(false);
+ abort();
}
}
nlua_pop_typval_table_processing_end:
@@ -1200,7 +1200,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
break;
}
default: {
- assert(false);
+ abort();
}
}
break;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 344a2387d6..310b194c8c 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -5,6 +5,7 @@
#include <lualib.h>
#include <lauxlib.h>
+#include "nvim/version.h"
#include "nvim/misc1.h"
#include "nvim/getchar.h"
#include "nvim/garray.h"
@@ -78,6 +79,17 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
lua_pop(lstate, 1);
}
+/// Return version of current neovim build
+///
+/// @param lstate Lua interpreter state.
+static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
+{
+ Dictionary version = version_dict();
+ nlua_push_Dictionary(lstate, version, true);
+ api_free_dictionary(version);
+ return 1;
+}
+
/// Compare two strings, ignoring case
///
/// Expects two values on the stack: compared strings. Returns one of the
@@ -420,6 +432,9 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
// str_byteindex
lua_pushcfunction(lstate, &nlua_str_byteindex);
lua_setfield(lstate, -2, "str_byteindex");
+ // neovim version
+ lua_pushcfunction(lstate, &nlua_nvim_version);
+ lua_setfield(lstate, -2, "version");
// schedule
lua_pushcfunction(lstate, &nlua_schedule);
lua_setfield(lstate, -2, "schedule");
@@ -1277,6 +1292,80 @@ static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_setfield(lstate, -2, "_ts_parse_query");
}
+int nlua_expand_pat(expand_T *xp,
+ char_u *pat,
+ int *num_results,
+ char_u ***results)
+{
+ lua_State *const lstate = nlua_enter();
+ int ret = OK;
+
+ // [ vim ]
+ lua_getglobal(lstate, "vim");
+
+ // [ vim, vim._expand_pat ]
+ lua_getfield(lstate, -1, "_expand_pat");
+ luaL_checktype(lstate, -1, LUA_TFUNCTION);
+
+ // [ vim, vim._log_keystroke, buf ]
+ lua_pushlstring(lstate, (const char *)pat, STRLEN(pat));
+
+ if (lua_pcall(lstate, 1, 2, 0) != 0) {
+ nlua_error(
+ lstate,
+ _("Error executing vim._expand_pat: %.*s"));
+ return FAIL;
+ }
+
+ Error err = ERROR_INIT;
+
+ *num_results = 0;
+ *results = NULL;
+
+ int prefix_len = (int)nlua_pop_Integer(lstate, &err);
+ if (ERROR_SET(&err)) {
+ ret = FAIL;
+ goto cleanup;
+ }
+
+ Array completions = nlua_pop_Array(lstate, &err);
+ if (ERROR_SET(&err)) {
+ ret = FAIL;
+ goto cleanup_array;
+ }
+
+ garray_T result_array;
+ ga_init(&result_array, (int)sizeof(char *), 80);
+ for (size_t i = 0; i < completions.size; i++) {
+ Object v = completions.items[i];
+
+ if (v.type != kObjectTypeString) {
+ ret = FAIL;
+ goto cleanup_array;
+ }
+
+ GA_APPEND(
+ char_u *,
+ &result_array,
+ vim_strsave((char_u *)v.data.string.data));
+ }
+
+ xp->xp_pattern += prefix_len;
+ *results = result_array.ga_data;
+ *num_results = result_array.ga_len;
+
+cleanup_array:
+ api_free_array(completions);
+
+cleanup:
+
+ if (ret == FAIL) {
+ ga_clear(&result_array);
+ }
+
+ return ret;
+}
+
static int nlua_regex(lua_State *lstate)
{
Error err = ERROR_INIT;
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index b20fbbf038..dbf4f6014c 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -121,10 +121,17 @@ function vim._load_package(name)
end
for _,trail in ipairs(vim._so_trails) do
- local path = "lua/"..trail:gsub('?',basename)
+ local path = "lua"..trail:gsub('?', basename) -- so_trails contains a leading slash
local found = vim.api.nvim_get_runtime_file(path, false)
if #found > 0 then
- local f, err = package.loadlib(found[1])
+ -- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
+ -- a) strip prefix up to and including the first dash, if any
+ -- b) replace all dots by underscores
+ -- c) prepend "luaopen_"
+ -- So "foo-bar.baz" should result in "luaopen_bar_baz"
+ local dash = name:find("-", 1, true)
+ local modname = dash and name:sub(dash + 1) or name
+ local f, err = package.loadlib(found[1], "luaopen_"..modname:gsub("%.", "_"))
return f or error(err)
end
end
@@ -527,4 +534,164 @@ function vim._log_keystroke(char)
end
end
+--- Generate a list of possible completions for the string.
+--- String starts with ^ and then has the pattern.
+---
+--- 1. Can we get it to just return things in the global namespace with that name prefix
+--- 2. Can we get it to return things from global namespace even with `print(` in front.
+function vim._expand_pat(pat, env)
+ env = env or _G
+
+ pat = string.sub(pat, 2, #pat)
+
+ if pat == '' then
+ local result = vim.tbl_keys(env)
+ table.sort(result)
+ return result, 0
+ end
+
+ -- TODO: We can handle spaces in [] ONLY.
+ -- We should probably do that at some point, just for cooler completion.
+ -- TODO: We can suggest the variable names to go in []
+ -- This would be difficult as well.
+ -- Probably just need to do a smarter match than just `:match`
+
+ -- Get the last part of the pattern
+ local last_part = pat:match("[%w.:_%[%]'\"]+$")
+ if not last_part then return {}, 0 end
+
+ local parts, search_index = vim._expand_pat_get_parts(last_part)
+
+ local match_part = string.sub(last_part, search_index, #last_part)
+ local prefix_match_pat = string.sub(pat, 1, #pat - #match_part) or ''
+
+ local final_env = env
+
+ for _, part in ipairs(parts) do
+ if type(final_env) ~= 'table' then
+ return {}, 0
+ end
+ local key
+
+ -- Normally, we just have a string
+ -- Just attempt to get the string directly from the environment
+ if type(part) == "string" then
+ key = part
+ else
+ -- However, sometimes you want to use a variable, and complete on it
+ -- With this, you have the power.
+
+ -- MY_VAR = "api"
+ -- vim[MY_VAR]
+ -- -> _G[MY_VAR] -> "api"
+ local result_key = part[1]
+ if not result_key then
+ return {}, 0
+ end
+
+ local result = rawget(env, result_key)
+
+ if result == nil then
+ return {}, 0
+ end
+
+ key = result
+ end
+ local field = rawget(final_env, key)
+ if field == nil then
+ local mt = getmetatable(final_env)
+ if mt and type(mt.__index) == "table" then
+ field = rawget(mt.__index, key)
+ end
+ end
+ final_env = field
+
+ if not final_env then
+ return {}, 0
+ end
+ end
+
+ local keys = {}
+ local function insert_keys(obj)
+ for k,_ in pairs(obj) do
+ if type(k) == "string" and string.sub(k,1,string.len(match_part)) == match_part then
+ table.insert(keys,k)
+ end
+ end
+ end
+
+ if type(final_env) == "table" then
+ insert_keys(final_env)
+ end
+ local mt = getmetatable(final_env)
+ if mt and type(mt.__index) == "table" then
+ insert_keys(mt.__index)
+ end
+
+ table.sort(keys)
+
+ return keys, #prefix_match_pat
+end
+
+vim._expand_pat_get_parts = function(lua_string)
+ local parts = {}
+
+ local accumulator, search_index = '', 1
+ local in_brackets, bracket_end = false, -1
+ local string_char = nil
+ for idx = 1, #lua_string do
+ local s = lua_string:sub(idx, idx)
+
+ if not in_brackets and (s == "." or s == ":") then
+ table.insert(parts, accumulator)
+ accumulator = ''
+
+ search_index = idx + 1
+ elseif s == "[" then
+ in_brackets = true
+
+ table.insert(parts, accumulator)
+ accumulator = ''
+
+ search_index = idx + 1
+ elseif in_brackets then
+ if idx == bracket_end then
+ in_brackets = false
+ search_index = idx + 1
+
+ if string_char == "VAR" then
+ table.insert(parts, { accumulator })
+ accumulator = ''
+
+ string_char = nil
+ end
+ elseif not string_char then
+ bracket_end = string.find(lua_string, ']', idx, true)
+
+ if s == '"' or s == "'" then
+ string_char = s
+ elseif s ~= ' ' then
+ string_char = "VAR"
+ accumulator = s
+ end
+ elseif string_char then
+ if string_char ~= s then
+ accumulator = accumulator .. s
+ else
+ table.insert(parts, accumulator)
+ accumulator = ''
+
+ string_char = nil
+ end
+ end
+ else
+ accumulator = accumulator .. s
+ end
+ end
+
+ parts = vim.tbl_filter(function(val) return #val > 0 end, parts)
+
+ return parts, search_index
+end
+
return module
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 8bf745966e..9f71df3a46 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -2044,7 +2044,6 @@ static void usage(void)
mch_msg(_(" -u <config> Use this config file\n"));
mch_msg(_(" -v, --version Print version information\n"));
mch_msg(_(" -V[N][file] Verbose [level][file]\n"));
- mch_msg(_(" -Z Restricted mode\n"));
mch_msg("\n");
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 45ca097033..73a9c1d1d7 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -777,6 +777,7 @@ void ex_delmarks(exarg_T *eap)
n = i - 'A';
}
namedfm[n].fmark.mark.lnum = 0;
+ namedfm[n].fmark.fnum = 0;
XFREE_CLEAR(namedfm[n].fname);
}
}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index f94529c687..ba7a667a60 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -890,6 +890,40 @@ char_u *msg_may_trunc(int force, char_u *s)
return s;
}
+void clear_hl_msg(HlMessage *hl_msg)
+{
+ for (size_t i = 0; i < kv_size(*hl_msg); i++) {
+ xfree(kv_A(*hl_msg, i).text.data);
+ }
+ kv_destroy(*hl_msg);
+ *hl_msg = (HlMessage)KV_INITIAL_VALUE;
+}
+
+#define LINE_BUFFER_SIZE 4096
+
+void add_hl_msg_hist(HlMessage hl_msg)
+{
+ // TODO(notomo): support multi highlighted message history
+ size_t pos = 0;
+ char buf[LINE_BUFFER_SIZE];
+ for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
+ HlMessageChunk chunk = kv_A(hl_msg, i);
+ for (uint32_t j = 0; j < chunk.text.size; j++) {
+ if (pos == LINE_BUFFER_SIZE - 1) {
+ buf[pos] = NUL;
+ add_msg_hist((const char *)buf, -1, MSG_HIST, true);
+ pos = 0;
+ continue;
+ }
+ buf[pos++] = chunk.text.data[j];
+ }
+ }
+ if (pos != 0) {
+ buf[pos] = NUL;
+ add_msg_hist((const char *)buf, -1, MSG_HIST, true);
+ }
+}
+
/// @param[in] len Length of s or -1.
static void add_msg_hist(const char *s, int len, int attr, bool multiline)
{
diff --git a/src/nvim/message.h b/src/nvim/message.h
index fdb9bc96ca..377c725fa1 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -8,6 +8,8 @@
#include "nvim/macros.h"
#include "nvim/types.h"
#include "nvim/grid_defs.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/lib/kvec.h"
/*
* Types of dialogs passed to do_dialog().
@@ -75,6 +77,13 @@
/// Like #MSG_PUTS_ATTR, but if middle part of long messages will be replaced
#define MSG_PUTS_LONG_ATTR(s, a) msg_puts_long_attr((char_u *)(s), (a))
+typedef struct {
+ String text;
+ int attr;
+} HlMessageChunk;
+
+typedef kvec_t(HlMessageChunk) HlMessage;
+
/// Message history for `:messages`
typedef struct msg_hist {
struct msg_hist *next; ///< Next message.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 4e955667dc..8f22243348 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -3978,16 +3978,19 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
curwin->w_curswant -= width2;
} else {
// to previous line
+
+ // Move to the start of a closed fold. Don't do that when
+ // 'foldopen' contains "all": it will open in a moment.
+ if (!(fdo_flags & FDO_ALL)) {
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+ }
if (curwin->w_cursor.lnum == 1) {
retval = false;
break;
}
- --curwin->w_cursor.lnum;
- /* Move to the start of a closed fold. Don't do that when
- * 'foldopen' contains "all": it will open in a moment. */
- if (!(fdo_flags & FDO_ALL))
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
+ curwin->w_cursor.lnum--;
+
linelen = linetabsize(get_cursor_line_ptr());
if (linelen > width1) {
int w = (((linelen - width1 - 1) / width2) + 1) * width2;
@@ -6708,11 +6711,8 @@ static void nv_g_cmd(cmdarg_T *cap)
*/
case 'j':
case K_DOWN:
- /* with 'nowrap' it works just like the normal "j" command; also when
- * in a closed fold */
- if (!curwin->w_p_wrap
- || hasFolding(curwin->w_cursor.lnum, NULL, NULL)
- ) {
+ // with 'nowrap' it works just like the normal "j" command.
+ if (!curwin->w_p_wrap) {
oap->motion_type = kMTLineWise;
i = cursor_down(cap->count1, oap->op_type == OP_NOP);
} else
@@ -6723,11 +6723,8 @@ static void nv_g_cmd(cmdarg_T *cap)
case 'k':
case K_UP:
- /* with 'nowrap' it works just like the normal "k" command; also when
- * in a closed fold */
- if (!curwin->w_p_wrap
- || hasFolding(curwin->w_cursor.lnum, NULL, NULL)
- ) {
+ // with 'nowrap' it works just like the normal "k" command.
+ if (!curwin->w_p_wrap) {
oap->motion_type = kMTLineWise;
i = cursor_up(cap->count1, oap->op_type == OP_NOP);
} else
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 052b07ed44..87d092281a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2623,7 +2623,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
}
// NOTREACHED
case kMTUnknown:
- assert(false);
+ abort();
}
}
@@ -6092,7 +6092,7 @@ static void set_clipboard(int name, yankreg_T *reg)
break;
}
case kMTUnknown: {
- assert(false);
+ abort();
}
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index d43dd9ba15..7cc83399e5 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -306,7 +306,7 @@ static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix",
static char *(p_bufhidden_values[]) = { "hide", "unload", "delete",
"wipe", NULL };
-static char *(p_bs_values[]) = { "indent", "eol", "start", NULL };
+static char *(p_bs_values[]) = { "indent", "eol", "start", "nostop", NULL };
static char *(p_fdm_values[]) = { "manual", "expr", "marker", "indent",
"syntax", "diff", NULL };
static char *(p_fcl_values[]) = { "all", NULL };
@@ -1366,6 +1366,10 @@ int do_set(
*(char_u **)varp = vim_strsave(
(char_u *)"indent,eol,start");
break;
+ case 3:
+ *(char_u **)varp = vim_strsave(
+ (char_u *)"indent,eol,nostop");
+ break;
}
xfree(oldval);
if (origval == oldval) {
@@ -1938,6 +1942,7 @@ static void didset_options(void)
(void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
(void)opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true);
(void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
+ (void)opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true);
(void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
(void)opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
(void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, true);
@@ -2909,7 +2914,7 @@ ambw_end:
#endif
} else if (varp == &curwin->w_p_scl) {
// 'signcolumn'
- if (check_opt_strings(*varp, p_scl_values, false) != OK) {
+ if (check_signcolumn(*varp) != OK) {
errmsg = e_invarg;
}
// When changing the 'signcolumn' to or from 'number', recompute the
@@ -2939,7 +2944,7 @@ ambw_end:
}
} else if (varp == &p_bs) { // 'backspace'
if (ascii_isdigit(*p_bs)) {
- if (*p_bs >'2' || p_bs[1] != NUL) {
+ if (*p_bs > '3' || p_bs[1] != NUL) {
errmsg = e_invarg;
}
} else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
@@ -3073,6 +3078,10 @@ ambw_end:
if (!parse_winhl_opt(curwin)) {
errmsg = e_invarg;
}
+ } else if (varp == &p_tpf) {
+ if (opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true) != OK) {
+ errmsg = e_invarg;
+ }
} else {
// Options that are a list of flags.
p = NULL;
@@ -3228,6 +3237,34 @@ static int int_cmp(const void *a, const void *b)
return *(const int *)a - *(const int *)b;
}
+/// Handle setting 'signcolumn' for value 'val'
+///
+/// @return OK when the value is valid, FAIL otherwise
+int check_signcolumn(char_u *val)
+{
+ // check for basic match
+ if (check_opt_strings(val, p_scl_values, false) == OK) {
+ return OK;
+ }
+
+ // check for 'auto:<NUMBER>-<NUMBER>'
+ if (STRLEN(val) == 8
+ && !STRNCMP(val, "auto:", 5)
+ && ascii_isdigit(val[5])
+ && val[6] == '-'
+ && ascii_isdigit(val[7])
+ ) {
+ int min = val[5] - '0';
+ int max = val[7] - '0';
+ if (min < 1 || max < 2 || min > 8 || max > 9 || min >= max) {
+ return FAIL;
+ }
+ return OK;
+ }
+
+ return FAIL;
+}
+
/// Handle setting 'colorcolumn' or 'textwidth' in window "wp".
///
/// @return error message, NULL if it's OK.
@@ -6801,15 +6838,15 @@ static int check_opt_wim(void)
}
/// Check if backspacing over something is allowed.
-/// The parameter what is one of the following: whatBS_INDENT, BS_EOL
-/// or BS_START
+/// @param what BS_INDENT, BS_EOL, BS_START, or BS_NOSTOP
bool can_bs(int what)
{
if (what == BS_START && bt_prompt(curbuf)) {
return false;
}
switch (*p_bs) {
- case '2': return true;
+ case '3': return true;
+ case '2': return what != BS_NOSTOP;
case '1': return what != BS_START;
case '0': return false;
}
@@ -7091,7 +7128,7 @@ int csh_like_shell(void)
/// buffer signs and on user configuration.
int win_signcol_count(win_T *wp)
{
- int maximum = 1, needed_signcols;
+ int minimum = 0, maximum = 1, needed_signcols;
const char *scl = (const char *)wp->w_p_scl;
// Note: It checks "no" or "number" in 'signcolumn' option
@@ -7115,9 +7152,14 @@ int win_signcol_count(win_T *wp)
if (!strncmp(scl, "auto:", 5)) {
// Variable depending on a configuration
maximum = scl[5] - '0';
+ // auto:<NUM>-<NUM>
+ if (strlen(scl) == 8 && *(scl + 6) == '-') {
+ minimum = maximum;
+ maximum = scl[7] - '0';
+ }
}
- return MIN(maximum, needed_signcols);
+ return MAX(minimum, MIN(maximum, needed_signcols));
}
/// Get window or buffer local options
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index ec2160d365..43b0107800 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -282,9 +282,14 @@ enum {
#define WIM_BUFLASTUSED 8
// arguments for can_bs()
+// each defined char should be unique over all values
+// except for BS_START, that intentionally also matches BS_NOSTOP
+// because BS_NOSTOP behaves exactly the same except it
+// does not stop at the start of the insert point
#define BS_INDENT 'i' // "Indent"
-#define BS_EOL 'o' // "eOl"
+#define BS_EOL 'l' // "eoL"
#define BS_START 's' // "Start"
+#define BS_NOSTOP 'p' // "nostoP
#define LISPWORD_VALUE \
"defun,define,defmacro,set!,lambda,if,case,let,flet,let*,letrec,do,do*,define-syntax,let-syntax,letrec-syntax,destructuring-bind,defpackage,defparameter,defstruct,deftype,defvar,do-all-symbols,do-external-symbols,do-symbols,dolist,dotimes,ecase,etypecase,eval-when,labels,macrolet,multiple-value-bind,multiple-value-call,multiple-value-prog1,multiple-value-setq,prog1,progv,typecase,unless,unwind-protect,when,with-input-from-string,with-open-file,with-open-stream,with-output-to-string,with-package-iterator,define-condition,handler-bind,handler-case,restart-bind,restart-case,with-simple-restart,store-value,use-value,muffle-warning,abort,continue,with-slots,with-slots*,with-accessors,with-accessors*,defclass,defmethod,print-unreadable-object"
@@ -616,6 +621,19 @@ EXTERN int p_sta; // 'smarttab'
EXTERN int p_sb; // 'splitbelow'
EXTERN long p_tpm; // 'tabpagemax'
EXTERN char_u *p_tal; // 'tabline'
+EXTERN char_u *p_tpf; // 'termpastefilter'
+EXTERN unsigned int tpf_flags; ///< flags from 'termpastefilter'
+#ifdef IN_OPTION_C
+static char *(p_tpf_values[]) =
+ { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL };
+#endif
+# define TPF_BS 0x001
+# define TPF_HT 0x002
+# define TPF_FF 0x004
+# define TPF_ESC 0x008
+# define TPF_DEL 0x010
+# define TPF_C0 0x020
+# define TPF_C1 0x040
EXTERN char_u *p_sps; // 'spellsuggest'
EXTERN int p_spr; // 'splitright'
EXTERN int p_sol; // 'startofline'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index df2bfbce34..fe108ef1cc 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2821,6 +2821,14 @@ return {
defaults={if_true={vi=false}}
},
{
+ full_name='termpastefilter', abbreviation='tpf',
+ type='string', list='onecomma', scope={'global'},
+ deny_duplicates=true,
+ vim=true,
+ varname='p_tpf',
+ defaults={if_true={vi="", vim="BS,HT,ESC,DEL"}}
+ },
+ {
full_name='terse',
short_desc=N_("hides notification of search wrap"),
type='bool', scope={'global'},
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 879266e3d4..008f5ef63b 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -394,13 +394,21 @@ void os_get_hostname(char *hostname, size_t size)
}
/// To get the "real" home directory:
-/// - get value of $HOME
+/// 1. get value of $HOME
+/// 2. if $HOME is not set, try the following
+/// For Windows:
+/// 1. assemble homedir using HOMEDRIVE and HOMEPATH
+/// 2. try os_homedir()
+/// 3. resolve a direct reference to another system variable
+/// 4. guess C drive
/// For Unix:
-/// - go to that directory
-/// - do os_dirname() to get the real name of that directory.
-/// This also works with mounts and links.
-/// Don't do this for Windows, it will change the "current dir" for a drive.
+/// 1. try os_homedir()
+/// 2. go to that directory
+/// This also works with mounts and links.
+/// Don't do this for Windows, it will change the "current dir" for a drive.
+/// 3. fall back to current working directory as a last resort
static char *homedir = NULL;
+static char *os_homedir(void);
void init_homedir(void)
{
@@ -430,7 +438,7 @@ void init_homedir(void)
}
}
if (var == NULL) {
- var = os_getenv("USERPROFILE");
+ var = os_homedir();
}
// Weird but true: $HOME may contain an indirect reference to another
@@ -440,6 +448,7 @@ void init_homedir(void)
const char *p = strchr(var + 1, '%');
if (p != NULL) {
vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
+ var = NULL;
const char *exp = os_getenv(os_buf);
if (exp != NULL && *exp != NUL
&& STRLEN(exp) + STRLEN(p) < MAXPATHL) {
@@ -458,8 +467,12 @@ void init_homedir(void)
}
#endif
- if (var != NULL) {
#ifdef UNIX
+ if (var == NULL) {
+ var = os_homedir();
+ }
+
+ if (var != NULL) {
// Change to the directory and get the actual path. This resolves
// links. Don't do it when we can't return.
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
@@ -470,11 +483,37 @@ void init_homedir(void)
EMSG(_(e_prev_dir));
}
}
+ }
+
+ // Fall back to current working directory if home is not found
+ if ((var == NULL || *var == NUL)
+ && os_dirname((char_u *)os_buf, sizeof(os_buf)) == OK) {
+ var = os_buf;
+ }
#endif
+ if (var != NULL) {
homedir = xstrdup(var);
}
}
+static char homedir_buf[MAXPATHL];
+
+static char *os_homedir(void)
+{
+ homedir_buf[0] = NUL;
+ size_t homedir_size = MAXPATHL;
+ uv_mutex_lock(&mutex);
+ // http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir
+ int ret_value = uv_os_homedir(homedir_buf, &homedir_size);
+ uv_mutex_unlock(&mutex);
+ if (ret_value == 0 && homedir_size < MAXPATHL) {
+ return homedir_buf;
+ }
+ ELOG("uv_os_homedir() failed %d: %s", ret_value, os_strerror(ret_value));
+ homedir_buf[0] = NUL;
+ return NULL;
+}
+
#if defined(EXITFREE)
void free_homedir(void)
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index 4d7d9a45df..348a139e79 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -20,6 +20,10 @@
# include <pty.h>
#endif
+#ifdef __APPLE__
+# include <crt_externs.h>
+#endif
+
#include <uv.h>
#include "nvim/lib/klist.h"
@@ -154,28 +158,14 @@ void pty_process_teardown(Loop *loop)
static void init_child(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
+#if defined(HAVE__NSGETENVIRON)
+#define environ (*_NSGetEnviron())
+#else
+ extern char **environ;
+#endif
// New session/process-group. #6530
setsid();
- os_unsetenv("COLUMNS");
- os_unsetenv("LINES");
- os_unsetenv("TERMCAP");
- os_unsetenv("COLORFGBG");
- // setting COLORTERM to "truecolor" if termguicolors is set and 256
- // otherwise, but only if it was set in the parent terminal at all
- if (os_env_exists("COLORTERM")) {
- const char *colorterm = os_getenv("COLORTERM");
- if (colorterm != NULL) {
- if (p_tgc) {
- os_setenv("COLORTERM", "truecolor", 1);
- } else {
- os_setenv("COLORTERM", "256", 1);
- }
- } else {
- os_unsetenv("COLORTERM");
- }
- }
-
signal(SIGCHLD, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGINT, SIG_DFL);
@@ -190,9 +180,14 @@ static void init_child(PtyProcess *ptyproc)
}
char *prog = ptyproc->process.argv[0];
- os_setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1);
- execvp(prog, ptyproc->process.argv);
+
+ assert(proc->env);
+ tv_dict_add_str(proc->env, S_LEN("TERM"),
+ ptyproc->term_name ? ptyproc->term_name : "ansi");
+ environ = tv_dict_to_env(proc->env);
+ execvp(prog, proc->argv);
ELOG("execvp failed: %s: %s", strerror(errno), prog);
+
_exit(122); // 122 is EXEC_FAILED in the Vim source.
}
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index 6f7100e846..52d2f84ace 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -52,6 +52,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
uv_connect_t *out_req = NULL;
wchar_t *cmd_line = NULL;
wchar_t *cwd = NULL;
+ wchar_t *env = NULL;
const char *emsg = NULL;
assert(proc->err.closed);
@@ -124,13 +125,22 @@ int pty_process_spawn(PtyProcess *ptyproc)
goto cleanup;
}
+ if (proc->env != NULL) {
+ status = build_env_block(proc->env, &env);
+ }
+
+ if (status != 0) {
+ emsg = "build_env_block failed";
+ goto cleanup;
+ }
+
if (ptyproc->type == kConpty) {
if (!os_conpty_spawn(conpty_object,
&process_handle,
NULL,
cmd_line,
cwd,
- NULL)) {
+ env)) {
emsg = "os_conpty_spawn failed";
status = (int)GetLastError();
goto cleanup;
@@ -141,7 +151,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
NULL, // Optional application name
cmd_line,
cwd,
- NULL, // Optional environment variables
+ env,
&err);
if (spawncfg == NULL) {
emsg = "winpty_spawn_config_new failed";
@@ -213,6 +223,7 @@ cleanup:
xfree(in_req);
xfree(out_req);
xfree(cmd_line);
+ xfree(env);
xfree(cwd);
return status;
}
@@ -454,3 +465,66 @@ int translate_winpty_error(int winpty_errno)
default: return UV_UNKNOWN;
}
}
+
+typedef struct EnvNode {
+ wchar_t *str;
+ size_t len;
+ QUEUE node;
+} EnvNode;
+
+/// Build the environment block to pass to CreateProcessW.
+///
+/// @param[in] denv Dict of environment name/value pairs
+/// @param[out] env Allocated environment block
+///
+/// @returns zero on success or error code of MultiByteToWideChar function.
+static int build_env_block(dict_T *denv, wchar_t **env_block)
+{
+ const size_t denv_size = (size_t)tv_dict_len(denv);
+ size_t env_block_len = 0;
+ int rc;
+ char **env = tv_dict_to_env(denv);
+
+ QUEUE *q;
+ QUEUE env_q;
+ QUEUE_INIT(&env_q);
+ // Convert env vars to wchar_t and calculate how big the final env block
+ // needs to be
+ for (size_t i = 0; i < denv_size; i++) {
+ EnvNode *env_node = xmalloc(sizeof(*env_node));
+ rc = utf8_to_utf16(env[i], -1, &env_node->str);
+ if (rc != 0) {
+ goto cleanup;
+ }
+ env_node->len = wcslen(env_node->str) + 1;
+ env_block_len += env_node->len;
+ QUEUE_INSERT_TAIL(&env_q, &env_node->node);
+ }
+
+ // Additional '\0' after the final entry
+ env_block_len++;
+
+ *env_block = xmalloc(sizeof(**env_block) * env_block_len);
+ wchar_t *pos = *env_block;
+
+ QUEUE_FOREACH(q, &env_q) {
+ EnvNode *env_node = QUEUE_DATA(q, EnvNode, node);
+ memcpy(pos, env_node->str, env_node->len * sizeof(*pos));
+ pos += env_node->len;
+ }
+
+ *pos = L'\0';
+
+cleanup:
+ q = QUEUE_HEAD(&env_q);
+ while (q != &env_q) {
+ QUEUE *next = q->next;
+ EnvNode *env_node = QUEUE_DATA(q, EnvNode, node);
+ XFREE_CLEAR(env_node->str);
+ QUEUE_REMOVE(q);
+ xfree(env_node);
+ q = next;
+ }
+
+ return rc;
+}
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 66bc990402..93b8d5ca12 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -108,6 +108,17 @@ char *get_xdg_home(const XDGVarType idx)
return dir;
}
+/// Return subpath of $XDG_CACHE_HOME
+///
+/// @param[in] fname New component of the path.
+///
+/// @return [allocated] `$XDG_CACHE_HOME/nvim/{fname}`
+char *stdpaths_user_cache_subpath(const char *fname)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
+{
+ return concat_fnames_realloc(get_xdg_home(kXDGCacheHome), fname, true);
+}
+
/// Return subpath of $XDG_CONFIG_HOME
///
/// @param[in] fname New component of the path.
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 4b6533cd0c..5cf628935f 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -97,7 +97,7 @@ void os_microdelay(uint64_t us, bool ignoreinput)
const int rv = uv_cond_timedwait(&delay_cond, &delay_mutex, ns_delta);
if (0 != rv && UV_ETIMEDOUT != rv) {
- assert(false);
+ abort();
break;
} // Else: Timeout proceeded normally.
diff --git a/src/nvim/po/af.po b/src/nvim/po/af.po
index fa6674469c..db44f50a46 100644
--- a/src/nvim/po/af.po
+++ b/src/nvim/po/af.po
@@ -3290,10 +3290,6 @@ msgstr "-o[N]\t\tMaak N vensters oop (verstek: een vir elke ler)"
#~ msgid " -V[N][file] Verbose [level][file]\n"
#~ msgstr ""
-#, fuzzy
-#~ msgid " -Z Restricted mode\n"
-#~ msgstr " vir twee modusse "
-
#~ msgid " --api-info Write msgpack-encoded API metadata to stdout\n"
#~ msgstr ""
@@ -7473,9 +7469,6 @@ msgstr "E446: Geen lernaam onder loper"
#~ msgid "-b\t\t\tBinary mode"
#~ msgstr "-b\t\t\tBinre modus"
-#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-#~ msgstr "-Z\t\t\tBeperkte modus (soos \"rvim\")"
-
#~ msgid "-R\t\t\tReadonly mode (like \"view\")"
#~ msgstr "-R\t\t\tLeesalleen modus (soos \"view\")"
diff --git a/src/nvim/po/ca.po b/src/nvim/po/ca.po
index be4206f36e..6c4d6ddd22 100644
--- a/src/nvim/po/ca.po
+++ b/src/nvim/po/ca.po
@@ -3469,10 +3469,6 @@ msgstr "-y\t\t\tMode senzill (com \"evim\", sense modes)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMode noms lectura (com \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tMode restringit (com \"rvim)"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tNo permet modificar (escriure) fitxers"
diff --git a/src/nvim/po/cs.cp1250.po b/src/nvim/po/cs.cp1250.po
index 5b9f3d3a58..859039eb87 100644
--- a/src/nvim/po/cs.cp1250.po
+++ b/src/nvim/po/cs.cp1250.po
@@ -3547,10 +3547,6 @@ msgstr "-v\t\t\tSnadn reim (stejn jako \"evim\", dn mdy )"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tReim pouze_pro_ten (jako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tOmezen reim (stejn jako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmny (ukldn soubor) zakzny"
diff --git a/src/nvim/po/cs.po b/src/nvim/po/cs.po
index 31a90dc514..4d9ad58836 100644
--- a/src/nvim/po/cs.po
+++ b/src/nvim/po/cs.po
@@ -3547,10 +3547,6 @@ msgstr "-v\t\t\tSnadn reim (stejn jako \"evim\", dn mdy )"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tReim pouze_pro_ten (jako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tOmezen reim (stejn jako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmny (ukldn soubor) zakzny"
diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po
index f35272810b..7a75425019 100644
--- a/src/nvim/po/da.po
+++ b/src/nvim/po/da.po
@@ -3015,9 +3015,6 @@ msgstr "-y\t\t\tEasy-tilstand (ligesom \"evim\", tilstandsløs)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet tilstand (ligesom \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tRestriktiv tilstand (ligesom \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tÆndringer (skrivning af filer) ikke tilladt"
diff --git a/src/nvim/po/de.po b/src/nvim/po/de.po
index a2e04965e5..740e9e5f6a 100644
--- a/src/nvim/po/de.po
+++ b/src/nvim/po/de.po
@@ -2895,10 +2895,6 @@ msgstr "-y\t\t\tLeichter Modus (wie \"evim\", ohne Modi)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModus ohne Schreibrechte (wie \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tEingeschrnkter Modus (wie \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tnderungen (beim Schreiben von Dateien) sind nicht erlaubt"
diff --git a/src/nvim/po/en_GB.po b/src/nvim/po/en_GB.po
index 7919fc8946..66cdba6f92 100644
--- a/src/nvim/po/en_GB.po
+++ b/src/nvim/po/en_GB.po
@@ -3368,10 +3368,6 @@ msgstr ""
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr ""
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr ""
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr ""
diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po
index 99c46c7275..5480e6a4d8 100644
--- a/src/nvim/po/eo.po
+++ b/src/nvim/po/eo.po
@@ -2989,9 +2989,6 @@ msgstr "-y\t\t\tFacila reĝimo (kiel \"evim\", senreĝima)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tNurlegebla reĝimo (kiel \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tLimigita reĝimo (kiel \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tŜanĝoj (skribo al dosieroj) nepermeseblaj"
diff --git a/src/nvim/po/es.po b/src/nvim/po/es.po
index eeea27610d..064484d1a4 100644
--- a/src/nvim/po/es.po
+++ b/src/nvim/po/es.po
@@ -3524,10 +3524,6 @@ msgstr "-y\t\t\tModo fácil (como \"evim\", sin modo)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModo de solo lectura (como \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tModo restringido (como \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModificación de archivos desactivada"
diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po
index 4489139cfb..5986a57488 100644
--- a/src/nvim/po/fi.po
+++ b/src/nvim/po/fi.po
@@ -3249,10 +3249,6 @@ msgstr ""
#~ msgstr " kahta tilaa varten "
#, fuzzy
-#~ msgid " -Z Restricted mode\n"
-#~ msgstr " kahta tilaa varten "
-
-#, fuzzy
#~ msgid " -m Modifications (writing files) not allowed\n"
#~ msgstr "-m\t\t\tMuokkaukset (kirjoittaminen tiedostoon) pois käytöstä"
@@ -6961,9 +6957,6 @@ msgstr "Lista tai luku tarvitaan"
#~ msgid "-b\t\t\tBinary mode"
#~ msgstr "-b\t\t\tBinääritila"
-#~ msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-#~ msgstr "-Z\t\t\tRajoitettu tila (kuten rvimillä)"
-
#~ msgid "-R\t\t\tReadonly mode (like \"view\")"
#~ msgstr "-R\t\t\tKirjoitussuojattu tila (kuten view'lla)"
diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po
index bb60649c91..5f1ca2fec5 100644
--- a/src/nvim/po/fr.po
+++ b/src/nvim/po/fr.po
@@ -3231,9 +3231,6 @@ msgstr "-y\t\tMode facile (comme \"evim\", vim sans modes)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\tMode lecture seule (comme \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\tMode restreint (comme \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\tInterdire l'enregistrement des fichiers"
diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po
index 1104b31c32..bad01d592a 100644
--- a/src/nvim/po/ga.po
+++ b/src/nvim/po/ga.po
@@ -3022,9 +3022,6 @@ msgstr "-y\t\t\tMd asca (mar \"evim\", gan mhid)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMd inlite amhin (mar \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tMd srianta (mar \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tN cheadatear athruithe (.i. scrobh na gcomhad)"
diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po
index 511f910b71..dfabc4bee0 100644
--- a/src/nvim/po/it.po
+++ b/src/nvim/po/it.po
@@ -3510,10 +3510,6 @@ msgstr "-y\t\t\tModalit Facile (come \"evim\", senza modalit)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tModalit Sola Lettura (come \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tModalit Ristretta (come \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tRiscritture del file non permesse"
diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po
index 523e9ca4e3..e2cf68f016 100644
--- a/src/nvim/po/ja.euc-jp.po
+++ b/src/nvim/po/ja.euc-jp.po
@@ -3024,9 +3024,6 @@ msgstr "-y\t\t\t⡼ (\"evim\" Ʊ⡼̵)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tɹѥ⡼ (\"view\" Ʊ)"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t¥⡼ (\"rvim\" Ʊ)"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tѹ (ե¸) Ǥʤ褦ˤ"
diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po
index 5a69d0c5bf..85a45cd171 100644
--- a/src/nvim/po/ja.po
+++ b/src/nvim/po/ja.po
@@ -3024,9 +3024,6 @@ msgstr "-y\t\t\tイージーモード (\"evim\" と同じ、モード無)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\t読込専用モード (\"view\" と同じ)"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t制限モード (\"rvim\" と同じ)"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t変更 (ファイル保存時) をできないようにする"
diff --git a/src/nvim/po/ko.UTF-8.po b/src/nvim/po/ko.UTF-8.po
index 128b238f8b..b99c22caeb 100644
--- a/src/nvim/po/ko.UTF-8.po
+++ b/src/nvim/po/ko.UTF-8.po
@@ -3438,10 +3438,6 @@ msgstr "-y\t\t\t쉬운 상태 (\"evim\"과 같음, modeless)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\t읽기 전용 상태 (\"view\"와 같음)"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t제한된 상태 (\"rvim\"과 같음)"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t수정(파일 쓰기)이 허용되지 않음"
diff --git a/src/nvim/po/nb.po b/src/nvim/po/nb.po
index 34617ccf18..2285d755cf 100644
--- a/src/nvim/po/nb.po
+++ b/src/nvim/po/nb.po
@@ -3452,10 +3452,6 @@ msgstr "-y\t\t\tLett modus (som \"evim\", uten modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet modus (som \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegrenset modus (som \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifisering (lagring av filer) ikke tillatt"
diff --git a/src/nvim/po/nl.po b/src/nvim/po/nl.po
index 30f34508f5..00d113c83c 100644
--- a/src/nvim/po/nl.po
+++ b/src/nvim/po/nl.po
@@ -3449,10 +3449,6 @@ msgstr "-y\t\t\tEenvoudige modus (zoals \"evim\", zonder modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tAlleen-lezen modus (zoals \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBeperkte modus (zoals \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tAanpassingen (bestanden opslaan) niet toegestaan"
diff --git a/src/nvim/po/no.po b/src/nvim/po/no.po
index 34617ccf18..2285d755cf 100644
--- a/src/nvim/po/no.po
+++ b/src/nvim/po/no.po
@@ -3452,10 +3452,6 @@ msgstr "-y\t\t\tLett modus (som \"evim\", uten modus)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivebeskyttet modus (som \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegrenset modus (som \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifisering (lagring av filer) ikke tillatt"
diff --git a/src/nvim/po/pl.UTF-8.po b/src/nvim/po/pl.UTF-8.po
index f5c452e924..5f1779d1bd 100644
--- a/src/nvim/po/pl.UTF-8.po
+++ b/src/nvim/po/pl.UTF-8.po
@@ -3417,10 +3417,6 @@ msgstr "-y\t\t\tTryb łatwy (jak \"evim\", bez trybów)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tTryb wyłącznie do odczytu (jak \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tTryb ograniczenia (jak \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModyfikacje (zapisywanie plików) niedozwolone"
diff --git a/src/nvim/po/pt_BR.po b/src/nvim/po/pt_BR.po
index 4f39cb5bdb..533d916de1 100644
--- a/src/nvim/po/pt_BR.po
+++ b/src/nvim/po/pt_BR.po
@@ -6229,10 +6229,6 @@ msgstr "-y\t\t\tModo fácil (como \"evim\", o Vim não modal)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tmodo somente-leitura (como \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tmodo restrito (como \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tNo permitir alteraes (gravao de arquivos)"
diff --git a/src/nvim/po/ru.po b/src/nvim/po/ru.po
index 62f892d257..3a96ece2fb 100644
--- a/src/nvim/po/ru.po
+++ b/src/nvim/po/ru.po
@@ -3442,10 +3442,6 @@ msgstr "-y\t\t\tПростой режим (как \"evim\", безрежимны
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tТолько для чтения (как \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tОграниченный режим (как \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tБез возможности сохранения изменений (записи файлов)"
diff --git a/src/nvim/po/sk.cp1250.po b/src/nvim/po/sk.cp1250.po
index ced343bf6b..ff95c68a12 100644
--- a/src/nvim/po/sk.cp1250.po
+++ b/src/nvim/po/sk.cp1250.po
@@ -3450,10 +3450,6 @@ msgstr "-y\t\t\tJednoduch md (rovnak ako \"evim\", bezmdov)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMd iba pre tanie (ako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tObmedzen md (rovnak ako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmeny (ukladanie sborov) zakzan"
diff --git a/src/nvim/po/sk.po b/src/nvim/po/sk.po
index 66b3d5abb1..d35622726f 100644
--- a/src/nvim/po/sk.po
+++ b/src/nvim/po/sk.po
@@ -3450,10 +3450,6 @@ msgstr "-y\t\t\tJednoduch md (rovnak ako \"evim\", bezmdov)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tMd iba pre tanie (ako \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tObmedzen md (rovnak ako \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tZmeny (ukladanie sborov) zakzan"
diff --git a/src/nvim/po/sr.po b/src/nvim/po/sr.po
index 4c157658e5..a93a2ec584 100644
--- a/src/nvim/po/sr.po
+++ b/src/nvim/po/sr.po
@@ -3028,9 +3028,6 @@ msgstr "-y\t\t\tEasy режим (као \"evim\", безрежимни)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tReadonly режим (као \"view\")"
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tRestricted режим (као \"rvim\")"
-
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tИзмене (уписивање датотека) нису дозвољене"
diff --git a/src/nvim/po/sv.po b/src/nvim/po/sv.po
index db7bada888..d50c9d695d 100644
--- a/src/nvim/po/sv.po
+++ b/src/nvim/po/sv.po
@@ -5735,10 +5735,6 @@ msgstr "-y\t\t\tLtt lge (som \"evim\", lgesls)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tSkrivskyddat lge (som \"view\")"
-#: ../main.c:2186
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tBegrnsat lge (som \"rvim\")"
-
#: ../main.c:2187
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tModifieringar (skriva filer) inte tilltet"
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index 604e425bd0..f0ae154648 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: vim 7.4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-23 18:45+0300\n"
+"POT-Creation-Date: 2021-01-18 17:46+0200\n"
"PO-Revision-Date: 2020-08-23 20:19+0300\n"
"Last-Translator: Анатолій Сахнік <sakhnik@gmail.com>\n"
"Language-Team: Ukrainian\n"
@@ -23,6 +23,67 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+msgid "--Deleted--"
+msgstr "--Знищено--"
+
+#, c-format
+msgid "auto-removing autocommand: %s <buffer=%d>"
+msgstr "Автоматичне знищення автокоманди: %s <буфер=%d>"
+
+#, c-format
+msgid "E367: No such group: \"%s\""
+msgstr "E367: Немає такої групи: «%s»"
+
+msgid "E936: Cannot delete the current group"
+msgstr "E936: Не вдалося знищити цю групу"
+
+msgid "W19: Deleting augroup that is still in use"
+msgstr "W19: Знищення автогрупи, яка все ще використовується"
+
+#, c-format
+msgid "E215: Illegal character after *: %s"
+msgstr "E215: Недозволений символ після *: %s"
+
+#, c-format
+msgid "E216: No such event: %s"
+msgstr "E216: Немає такої події: %s"
+
+#, c-format
+msgid "E216: No such group or event: %s"
+msgstr "E216: Немає такої групи чи події: %s"
+
+msgid ""
+"\n"
+"--- Autocommands ---"
+msgstr ""
+"\n"
+"--- Автокоманди ---"
+
+#, c-format
+msgid "E680: <buffer=%d>: invalid buffer number "
+msgstr "E680: <буфер=%d>: некоректний номер буфера "
+
+msgid "E217: Can't execute autocommands for ALL events"
+msgstr "E217: Не можу виконувати автокоманди для УСІХ подій"
+
+msgid "No matching autocommands"
+msgstr "Немає відповідних автокоманд"
+
+msgid "E218: autocommand nesting too deep"
+msgstr "E218: Забагато вкладених автокоманд"
+
+#, c-format
+msgid "%s Autocommands for \"%s\""
+msgstr "%s Автокоманди для «%s»"
+
+#, c-format
+msgid "Executing %s"
+msgstr "Виконується %s"
+
+#, c-format
+msgid "autocommand %s"
+msgstr "автокоманда %s"
+
msgid "[Location List]"
msgstr "[Список місць]"
@@ -95,9 +156,15 @@ msgid ""
"E89: No write since last change for buffer %<PRId64> (add ! to override)"
msgstr "E89: Буфер %<PRId64> має зміни (! щоб не зважати)"
+msgid "E948: Job still running (add ! to end the job)"
+msgstr "E948: Задача все ще виконується (! щоб закінчити)"
+
msgid "E37: No write since last change (add ! to override)"
msgstr "E37: Зміни не було записано (! щоб не зважати)"
+msgid "E948: Job still running"
+msgstr "E948: Задача все ще виконується"
+
msgid "E37: No write since last change"
msgstr "E37: Не записано після останніх змін"
@@ -465,6 +532,10 @@ msgid "E957: Invalid window number"
msgstr "E957: Некоректний номер вікна"
#, c-format
+msgid "E940: Cannot lock or unlock variable %s"
+msgstr "E940: Неможливо заблокувати чи розблокувати змінну %s"
+
+#, c-format
msgid "E734: Wrong variable type for %s="
msgstr "E734: Неправильний тип змінної для %s="
@@ -544,10 +615,6 @@ msgstr "E690: Пропущено «in» після :for"
msgid "E108: No such variable: \"%s\""
msgstr "E108: Змінної немає: «%s»"
-#, c-format
-msgid "E940: Cannot lock or unlock variable %s"
-msgstr "E940: Неможливо заблокувати чи розблокувати змінну %s"
-
msgid "E109: Missing ':' after '?'"
msgstr "E109: Бракує ':' після '?'"
@@ -950,9 +1017,6 @@ msgstr "E684: Індекс списку поза межами: %<PRId64>"
msgid "E686: Argument of %s must be a List"
msgstr "E686: Аргумент у %s має бути списком"
-msgid "E928: String required"
-msgstr "E928: Потрібен String"
-
#, c-format
msgid "Error converting the call result: %s"
msgstr "Не вдалося перетворити результат виклику: %s"
@@ -1591,6 +1655,10 @@ msgid "Close \"%s\"?"
msgstr "Закрити «%s»?"
#, c-format
+msgid "E947: Job still running in buffer \"%s\""
+msgstr "E947: Задача все ще запущена у буфері «%s»"
+
+#, c-format
msgid "E162: No write since last change for buffer \"%s\""
msgstr "E162: Буфер «%s» має незбережені зміни"
@@ -1615,18 +1683,6 @@ msgid "E666: compiler not supported: %s"
msgstr "E666: Компілятор не підтримується: %s"
#, c-format
-msgid "Searching for \"%s\" in \"%s\""
-msgstr "Пошук «%s» в «%s»"
-
-#, c-format
-msgid "Searching for \"%s\""
-msgstr "Пошук «%s»"
-
-#, c-format
-msgid "not found in '%s': \"%s\""
-msgstr "не знайдено в '%s': «%s»"
-
-#, c-format
msgid ":source error parsing command %s"
msgstr ":source помилка розбору команди %s"
@@ -1702,12 +1758,16 @@ msgstr "Режим Ex. Для повернення до нормального
msgid "E501: At end-of-file"
msgstr "E501: Кінець файлу"
-msgid "E169: Command too recursive"
-msgstr "E169: Команда занадто рекурсивна"
+#, c-format
+msgid "Executing: %s"
+msgstr "Виконується: %s"
msgid "line %"
msgstr "рядок %"
+msgid "E169: Command too recursive"
+msgstr "E169: Команда занадто рекурсивна"
+
#, c-format
msgid "E605: Exception not caught: %s"
msgstr "E605: Виняткова ситуація не оброблена: %s"
@@ -1724,9 +1784,6 @@ msgstr "E464: Неоднозначний вжиток команди корис
msgid "E492: Not an editor command"
msgstr "E492: Це не команда редактора"
-msgid "E981: Command not allowed in restricted mode"
-msgstr "E981: Команду не дозволено у обмеженому режимі"
-
msgid "E493: Backwards range given"
msgstr "E493: Інтервал задано навиворіт"
@@ -1736,6 +1793,11 @@ msgstr "Інтервал задано навиворіт, щоб помінят
msgid "E494: Use w or w>>"
msgstr "E494: Спробуйте w або w>>"
+msgid ""
+"INTERNAL: Cannot use EX_DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"
+msgstr ""
+"ВНУТРІШНЄ: Не можна вживати EX_DFLALL з ADDR_NONE, ADDR_UNSIGNED чи ADDR_QUICKFIX"
+
msgid "E943: Command table needs to be updated, run 'make'"
msgstr "E943: Потрібно поновити таблицю команд, запустіть 'make'"
@@ -1762,10 +1824,10 @@ msgstr "E174: Команда вже існує, ! щоб замінити її:
msgid ""
"\n"
-" Name Args Address Complete Definition"
+" Name Args Address Complete Definition"
msgstr ""
"\n"
-" Назва Арг. Адреса Доповнення Визначення"
+" Назва Арг. Адреса Доповнення Визначення"
msgid "No user-defined commands found"
msgstr "Не знайдено команд користувача"
@@ -2077,12 +2139,12 @@ msgstr "E347: У шляху пошуку більше немає файлів «
msgid "E812: Autocommands changed buffer or buffer name"
msgstr "E812: Автокоманди змінили буфер чи його назву"
-msgid "Illegal file name"
-msgstr "Недозволена назва файлу"
-
msgid "is a directory"
msgstr "каталог"
+msgid "Illegal file name"
+msgstr "Недозволена назва файлу"
+
msgid "is not a file"
msgstr "не файл"
@@ -2104,9 +2166,6 @@ msgstr "E201: Автокоманди *ReadPre не повинні змінюва
msgid "E202: Conversion made file unreadable!"
msgstr "E202: Конвертація унеможливила читання файлу!"
-msgid "[fifo/socket]"
-msgstr "[канал/сокет]"
-
msgid "[fifo]"
msgstr "[канал]"
@@ -2353,67 +2412,6 @@ msgstr "E462: Не вдалося підготувати «%s», щоб пере
msgid "E321: Could not reload \"%s\""
msgstr "E321: Не вдалося перечитати «%s»"
-msgid "--Deleted--"
-msgstr "--Знищено--"
-
-#, c-format
-msgid "auto-removing autocommand: %s <buffer=%d>"
-msgstr "Автоматичне знищення автокоманди: %s <буфер=%d>"
-
-#, c-format
-msgid "E367: No such group: \"%s\""
-msgstr "E367: Немає такої групи: «%s»"
-
-msgid "E936: Cannot delete the current group"
-msgstr "E936: Не вдалося знищити цю групу"
-
-msgid "W19: Deleting augroup that is still in use"
-msgstr "W19: Знищення автогрупи, яка все ще використовується"
-
-#, c-format
-msgid "E215: Illegal character after *: %s"
-msgstr "E215: Недозволений символ після *: %s"
-
-#, c-format
-msgid "E216: No such event: %s"
-msgstr "E216: Немає такої події: %s"
-
-#, c-format
-msgid "E216: No such group or event: %s"
-msgstr "E216: Немає такої групи чи події: %s"
-
-msgid ""
-"\n"
-"--- Autocommands ---"
-msgstr ""
-"\n"
-"--- Автокоманди ---"
-
-#, c-format
-msgid "E680: <buffer=%d>: invalid buffer number "
-msgstr "E680: <буфер=%d>: некоректний номер буфера "
-
-msgid "E217: Can't execute autocommands for ALL events"
-msgstr "E217: Не можу виконувати автокоманди для УСІХ подій"
-
-msgid "No matching autocommands"
-msgstr "Немає відповідних автокоманд"
-
-msgid "E218: autocommand nesting too deep"
-msgstr "E218: Забагато вкладених автокоманд"
-
-#, c-format
-msgid "%s Autocommands for \"%s\""
-msgstr "%s Автокоманди для «%s»"
-
-#, c-format
-msgid "Executing %s"
-msgstr "Виконується %s"
-
-#, c-format
-msgid "autocommand %s"
-msgstr "автокоманда %s"
-
msgid "E219: Missing {."
msgstr "E219: Бракує {."
@@ -2519,9 +2517,6 @@ msgstr "E685: Внутрішня помилка: %s"
msgid "Interrupted"
msgstr "Перервано"
-msgid "E14: Invalid address"
-msgstr "E14: Неправильна адреса"
-
msgid "E474: Invalid argument"
msgstr "E474: Некоректний аргумент"
@@ -2719,6 +2714,9 @@ msgstr "E45: Встановлено опцію 'readonly' (! щоб не зва
msgid "E46: Cannot change read-only variable \"%.*s\""
msgstr "E46: Змінна тільки для читання: «%.*s»"
+msgid "E928: String required"
+msgstr "E928: Потрібен String"
+
msgid "E715: Dictionary required"
msgstr "E715: Потрібен словник"
@@ -2727,8 +2725,8 @@ msgid "E118: Too many arguments for function: %s"
msgstr "E118: Забагато аргументів для функції: %s"
#, c-format
-msgid "E716: Key not present in Dictionary: %s"
-msgstr "E716: Немає такого ключа у словнику: %s"
+msgid "E716: Key not present in Dictionary: \"%s\""
+msgstr "E716: Немає такого ключа у словнику: «%s»"
msgid "E714: List required"
msgstr "E714: Потрібен список"
@@ -3158,6 +3156,10 @@ msgid "E5106: Error while creating shared module: %.*s"
msgstr "E5106: Помилка створення розділюваного модуля: %.*s"
#, c-format
+msgid "E5106: Error while creating inspect module: %.*s"
+msgstr "E5106: Помилка створення модуля inspect: %.*s"
+
+#, c-format
msgid "E5106: Error while creating vim module: %.*s"
msgstr "E5106: Помилка створення модуля vim: %.*s"
@@ -3165,10 +3167,6 @@ msgid "E970: Failed to initialize lua interpreter"
msgstr "E970: Не вдалося ініціалізувати інтерпретатор lua"
#, c-format
-msgid "E5117: Error while updating package paths: %.*s"
-msgstr "E5117: Помилка оновлення шляхів пакунку: %.*s"
-
-#, c-format
msgid "E5114: Error while converting print argument #%i: %.*s"
msgstr "E5114: Не вдалося перетворити аргумент #%i друку: %.*s"
@@ -3256,6 +3254,10 @@ msgid "pre-vimrc command line"
msgstr "команди перед vimrc"
#, c-format
+msgid "Conflicting configs: \"%s\" \"%s\""
+msgstr "Суперечливі конфігурації: «%s» «%s»"
+
+#, c-format
msgid "E282: Cannot read from \"%s\""
msgstr "E282: Не вдалося прочитати з «%s»"
@@ -3367,9 +3369,6 @@ msgstr " -v, --version Надрукувати інформацію пр
msgid " -V[N][file] Verbose [level][file]\n"
msgstr " -V[N][файл] Більше повідомлень [рівень][файл]\n"
-msgid " -Z Restricted mode\n"
-msgstr " -Z Обмежений режим\n"
-
msgid " --api-info Write msgpack-encoded API metadata to stdout\n"
msgstr ""
" --api-info Записати метадані API, серіалізовані у msgpack, у "
@@ -4005,8 +4004,7 @@ msgstr ""
"Введіть :qa! і натисність <Enter> щоб відкинути всі зміни і вийти Nvim"
msgid "Type :qa and press <Enter> to exit Nvim"
-msgstr ""
-"Введіть :qa і натисність <Enter> щоб вийти з Nvim"
+msgstr "Введіть :qa і натисність <Enter> щоб вийти з Nvim"
#, c-format
msgid "1 line %sed 1 time"
@@ -4071,10 +4069,10 @@ msgstr "E353: У регістрі %s нічого немає"
msgid ""
"\n"
-"--- Registers ---"
+"Type Name Content"
msgstr ""
"\n"
-"--- Регістри ---"
+"Тип Наз. Вміст "
msgid ""
"E883: search pattern and expression register may not contain two or more "
@@ -4187,9 +4185,6 @@ msgstr "E537: 'commentstring' має бути порожньою чи місти
msgid "E540: Unclosed expression sequence"
msgstr "E540: Послідовність виразів не завершено"
-msgid "E541: too many items"
-msgstr "E541: Забагато елементів"
-
msgid "E542: unbalanced groups"
msgstr "E542: Групи не збалансовано"
@@ -4277,6 +4272,9 @@ msgstr ""
msgid "E5677: Error writing input to shell-command: %s"
msgstr "E5677: Не вдалося записати на вхід команди оболонки: %s"
+msgid "%a %b %d %H:%M:%S %Y"
+msgstr "%H:%M:%S %a, %d %B %Y р."
+
#, c-format
msgid "E447: Can't find file \"%s\" in path"
msgstr "E447: Файл «%s» не знайдено у шляху пошуку"
@@ -4284,8 +4282,11 @@ msgstr "E447: Файл «%s» не знайдено у шляху пошуку"
msgid "E553: No more items"
msgstr "E553: Немає більше елементів"
+msgid "E925: Current quickfix list was changed"
+msgstr "E925: Поточний список quickfix змінився"
+
msgid "E926: Current location list was changed"
-msgstr "E926: Цей список місць було змінено"
+msgstr "E926: Поточний список місць змінився"
#, c-format
msgid "E372: Too many %%%c in format string"
@@ -4319,9 +4320,6 @@ msgstr "E379: Пропущена чи порожня назва каталогу
msgid "E924: Current window was closed"
msgstr "E924: Активне вікно було закрито"
-msgid "E925: Current quickfix was changed"
-msgstr "E925: Цей quickfix було змінено"
-
#, c-format
msgid "(%d of %d)%s%s: "
msgstr "(%d з %d)%s%s: "
@@ -4349,6 +4347,9 @@ msgstr "E683: Пропущено назву файлу чи некоректни
msgid "Cannot open file \"%s\""
msgstr "Не вдалося відкрити файл «%s»"
+msgid "cannot have both a list and a \"what\" argument"
+msgstr "не можна задавати одночасно список і аргумент «що»"
+
msgid "E681: Buffer is not loaded"
msgstr "E681: Буфер не завантажено"
@@ -4469,6 +4470,18 @@ msgstr ""
msgid "Switching to backtracking RE engine for pattern: "
msgstr "Перемикання до простого рушія регулярних виразів: "
+#, c-format
+msgid "Searching for \"%s\" in \"%s\""
+msgstr "Пошук «%s» в «%s»"
+
+#, c-format
+msgid "Searching for \"%s\""
+msgstr "Пошук «%s»"
+
+#, c-format
+msgid "not found in '%s': \"%s\""
+msgstr "не знайдено в '%s': «%s»"
+
msgid " TERMINAL"
msgstr " ТЕРМІНАЛ"
@@ -5252,6 +5265,9 @@ msgstr "синхронізується по коментарях стилю С"
msgid "no syncing"
msgstr "без синхронізації"
+msgid "syncing starts at the first line"
+msgstr "синхронізація починається з першого рядка"
+
msgid "syncing starts "
msgstr "починається синхронізація за "
@@ -5283,6 +5299,9 @@ msgstr ""
msgid "E392: No such syntax cluster: %s"
msgstr "E392: Немає такого синтаксичного кластера: %s"
+msgid "from the first line"
+msgstr "з першого рядка"
+
msgid "minimal "
msgstr "мінімальний "
diff --git a/src/nvim/po/vi.po b/src/nvim/po/vi.po
index a954ea6e34..c693f910d8 100644
--- a/src/nvim/po/vi.po
+++ b/src/nvim/po/vi.po
@@ -3479,10 +3479,6 @@ msgstr "-y\t\t\tChế độ đơn giản (giống \"evim\", không có chế đ
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\tChế độ chỉ đọc (giống \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\tChế độ hạn chế (giống \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\tKhông có khả năng ghi nhớ thay đổi (ghi nhớ tập tin)"
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 542157002a..1e329443ce 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -3427,10 +3427,6 @@ msgstr "-y\t\t\t容易模式 (同 \"evim\",无模式)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\t只读模式 (同 \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t限制模式 (同 \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t不可修改(写入文件)"
diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po
index 6a11b5e669..c97f31ddcf 100644
--- a/src/nvim/po/zh_TW.UTF-8.po
+++ b/src/nvim/po/zh_TW.UTF-8.po
@@ -3482,10 +3482,6 @@ msgstr "-y\t\t\t簡易模式 (同 \"evim\", modeless)"
msgid "-R\t\t\tReadonly mode (like \"view\")"
msgstr "-R\t\t\t唯讀模式 (同 \"view\")"
-#: ../main.c:2208
-msgid "-Z\t\t\tRestricted mode (like \"rvim\")"
-msgstr "-Z\t\t\t限制模式 (同 \"rvim\")"
-
#: ../main.c:2209
msgid "-m\t\t\tModifications (writing files) not allowed"
msgstr "-m\t\t\t不可修改 (寫入檔案)"
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index a625c09f78..e074f73d04 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -5264,7 +5264,7 @@ void ex_vimgrep(exarg_T *eap)
qf_new_list(qi, title);
}
- // parse the list of arguments
+ // Parse the list of arguments, wildcards have already been expanded.
if (get_arglist_exp(p, &fcount, &fnames, true) == FAIL) {
goto theend;
}
@@ -5648,7 +5648,7 @@ static int get_qfline_items(qfline_T *qfp, list_T *list)
== FAIL)) {
// tv_dict_add* fail only if key already exist, but this is a newly
// allocated dictionary which is thus guaranteed to have no existing keys.
- assert(false);
+ abort();
}
return OK;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 377e8f58fa..a78f905a70 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2417,8 +2417,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- if (wp->w_p_list) {
- if (curwin->w_p_lcs_chars.space
+ if (wp->w_p_list && !has_fold) {
+ if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.trail
|| wp->w_p_lcs_chars.nbsp) {
extra_check = true;
@@ -2883,8 +2883,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& vcol == 0
&& n_extra == 0
&& row == startrow) {
@@ -2905,8 +2904,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& col < grid->Columns
&& n_extra == 0
&& row == startrow) {
@@ -2918,8 +2916,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (draw_state == WL_LINE
- && foldinfo.fi_level != 0
- && foldinfo.fi_lines > 0
+ && has_fold
&& col >= grid->Columns
&& n_extra != 0
&& row == startrow) {
@@ -3087,7 +3084,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|| vcol < fromcol || vcol_prev < fromcol_prev
|| vcol >= tocol)) {
char_attr = line_attr;
- } else {
+ } else {
attr_pri = false;
if (has_syntax) {
char_attr = syntax_attr;
@@ -3742,7 +3739,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
wp->w_wrow = row;
did_wcol = true;
- curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
+ wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
}
// Don't override visual selection highlighting.
@@ -3835,9 +3832,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// Add a blank character to highlight.
schar_from_ascii(linebuf_char[off], ' ');
}
- if (area_attr == 0) {
- /* Use attributes from match with highest priority among
- * 'search_hl' and the match list. */
+ if (area_attr == 0 && !has_fold) {
+ // Use attributes from match with highest priority among
+ // 'search_hl' and the match list.
char_attr = search_hl.attr;
cur = wp->w_match_head;
shl_flag = FALSE;
@@ -4053,6 +4050,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& !wp->w_p_wrap
&& filler_todo <= 0
&& (wp->w_p_rl ? col == 0 : col == grid->Columns - 1)
+ && !has_fold
&& (*ptr != NUL
|| lcs_eol_one > 0
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 787a464070..2802da6f7f 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -4497,9 +4497,9 @@ find_pattern_in_path(
regmatch_T regmatch;
regmatch_T incl_regmatch;
regmatch_T def_regmatch;
- int matched = FALSE;
- int did_show = FALSE;
- int found = FALSE;
+ bool matched = false;
+ bool did_show = false;
+ bool found = false;
int i;
char_u *already = NULL;
char_u *startp = NULL;
@@ -4611,7 +4611,7 @@ find_pattern_in_path(
}
MSG_PUTS_TITLE(_("in path ---\n"));
}
- did_show = TRUE;
+ did_show = true;
while (depth_displayed < depth && !got_int) {
++depth_displayed;
for (i = 0; i < depth_displayed; i++)
@@ -4761,10 +4761,10 @@ search_line:
matched = !STRNCMP(startp, ptr, len);
if (matched && define_matched && whole
&& vim_iswordc(startp[len]))
- matched = FALSE;
+ matched = false;
} else if (regmatch.regprog != NULL
&& vim_regexec(&regmatch, line, (colnr_T)(p - line))) {
- matched = TRUE;
+ matched = true;
startp = regmatch.startp[0];
// Check if the line is not a comment line (unless we are
// looking for a define). A line starting with "# define"
@@ -4789,15 +4789,16 @@ search_line:
if (matched
&& p[0] == '/'
&& (p[1] == '*' || p[1] == '/')) {
- matched = FALSE;
- /* After "//" all text is comment */
- if (p[1] == '/')
+ matched = false;
+ // After "//" all text is comment
+ if (p[1] == '/') {
break;
- ++p;
+ }
+ p++;
} else if (!matched && p[0] == '*' && p[1] == '/') {
- /* Can find match after "* /". */
- matched = TRUE;
- ++p;
+ // Can find match after "* /".
+ matched = true;
+ p++;
}
}
}
@@ -4811,7 +4812,7 @@ search_line:
if (depth == -1 && lnum == curwin->w_cursor.lnum)
break;
- found = TRUE;
+ found = true;
aux = p = startp;
if (compl_cont_status & CONT_ADDING) {
p += compl_length;
@@ -4879,9 +4880,10 @@ search_line:
break;
}
} else if (action == ACTION_SHOW_ALL) {
- found = TRUE;
- if (!did_show)
- gotocmdline(TRUE); /* cursor at status line */
+ found = true;
+ if (!did_show) {
+ gotocmdline(true); // cursor at status line
+ }
if (curr_fname != prev_fname) {
if (did_show)
msg_putchar('\n'); /* cursor below last one */
@@ -4890,28 +4892,28 @@ search_line:
msg_home_replace_hl(curr_fname);
prev_fname = curr_fname;
}
- did_show = TRUE;
- if (!got_int)
- show_pat_in_path(line, type, TRUE, action,
- (depth == -1) ? NULL : files[depth].fp,
- (depth == -1) ? &lnum : &files[depth].lnum,
- match_count++);
+ did_show = true;
+ if (!got_int) {
+ show_pat_in_path(line, type, true, action,
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum,
+ match_count++);
+ }
/* Set matched flag for this file and all the ones that
* include it */
for (i = 0; i <= depth; ++i)
files[i].matched = TRUE;
} else if (--count <= 0) {
- found = TRUE;
+ found = true;
if (depth == -1 && lnum == curwin->w_cursor.lnum
- && l_g_do_tagpreview == 0
- )
+ && l_g_do_tagpreview == 0) {
EMSG(_("E387: Match is on current line"));
- else if (action == ACTION_SHOW) {
+ } else if (action == ACTION_SHOW) {
show_pat_in_path(line, type, did_show, action,
- (depth == -1) ? NULL : files[depth].fp,
- (depth == -1) ? &lnum : &files[depth].lnum, 1L);
- did_show = TRUE;
+ (depth == -1) ? NULL : files[depth].fp,
+ (depth == -1) ? &lnum : &files[depth].lnum, 1L);
+ did_show = true;
} else {
/* ":psearch" uses the preview window */
if (l_g_do_tagpreview != 0) {
@@ -4960,15 +4962,16 @@ search_line:
break;
}
exit_matched:
- matched = FALSE;
- /* look for other matches in the rest of the line if we
- * are not at the end of it already */
+ matched = false;
+ // look for other matches in the rest of the line if we
+ // are not at the end of it already
if (def_regmatch.regprog == NULL
&& action == ACTION_EXPAND
&& !(compl_cont_status & CONT_SOL)
&& *startp != NUL
- && *(p = startp + utfc_ptr2len(startp)) != NUL)
+ && *(p = startp + utfc_ptr2len(startp)) != NUL) {
goto search_line;
+ }
}
line_breakcheck();
if (action == ACTION_EXPAND)
@@ -5046,16 +5049,20 @@ fpip_end:
vim_regfree(def_regmatch.regprog);
}
-static void show_pat_in_path(char_u *line, int type, int did_show, int action, FILE *fp, linenr_T *lnum, long count)
+static void show_pat_in_path(char_u *line, int type, bool did_show, int action,
+ FILE *fp, linenr_T *lnum, long count)
+ FUNC_ATTR_NONNULL_ARG(1, 6)
{
char_u *p;
- if (did_show)
- msg_putchar('\n'); /* cursor below last one */
- else if (!msg_silent)
- gotocmdline(TRUE); /* cursor at status line */
- if (got_int) /* 'q' typed at "--more--" message */
+ if (did_show) {
+ msg_putchar('\n'); // cursor below last one
+ } else if (!msg_silent) {
+ gotocmdline(true); // cursor at status line
+ }
+ if (got_int) { // 'q' typed at "--more--" message
return;
+ }
for (;; ) {
p = line + STRLEN(line) - 1;
if (fp != NULL) {
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 2444910bb3..c0e787380f 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -765,7 +765,7 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader,
(uint64_t) offset);
return kSDReadStatusNotShaDa;
}
- assert(false);
+ abort();
}
return kSDReadStatusSuccess;
}
@@ -1224,7 +1224,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
case kSDReadStatusFinished: {
// Should be handled by the while condition.
- assert(false);
+ abort();
}
case kSDReadStatusNotShaDa:
case kSDReadStatusReadError: {
@@ -1236,7 +1236,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
switch (cur_entry.type) {
case kSDItemMissing: {
- assert(false);
+ abort();
}
case kSDItemUnknown: {
break;
@@ -1628,7 +1628,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
((size_t) (!CHECK_DEFAULT(entry, attr)))
switch (entry.type) {
case kSDItemMissing: {
- assert(false);
+ abort();
}
case kSDItemUnknown: {
if (spacker->callback(spacker->data, entry.data.unknown_item.contents,
@@ -1850,7 +1850,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
break;
}
default: {
- assert(false);
+ abort();
}
}
}
@@ -2147,7 +2147,7 @@ static inline ShaDaWriteResult shada_read_when_writing(
}
case kSDReadStatusFinished: {
// Should be handled by the while condition.
- assert(false);
+ abort();
}
case kSDReadStatusNotShaDa: {
ret = kSDWriteReadNotShada;
@@ -2184,7 +2184,7 @@ static inline ShaDaWriteResult shada_read_when_writing(
}
case kSDItemHeader:
case kSDItemBufferList: {
- assert(false);
+ abort();
}
case kSDItemUnknown: {
ret = shada_pack_entry(packer, entry, 0);
@@ -4044,7 +4044,7 @@ shada_read_next_item_start:
}
case kSDItemMissing:
case kSDItemUnknown: {
- assert(false);
+ abort();
}
}
entry->type = (ShadaEntryType) type_u64;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 5714f5e425..6425c9fed5 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -3123,6 +3123,7 @@ spell_find_suggest (
static bool expr_busy = false;
int c;
langp_T *lp;
+ bool did_intern = false;
// Set the info in "*su".
memset(su, 0, sizeof(suginfo_T));
@@ -3206,14 +3207,16 @@ spell_find_suggest (
spell_suggest_expr(su, buf + 5);
expr_busy = false;
}
- } else if (STRNCMP(buf, "file:", 5) == 0)
+ } else if (STRNCMP(buf, "file:", 5) == 0) {
// Use list of suggestions in a file.
spell_suggest_file(su, buf + 5);
- else {
- // Use internal method.
+ } else if (!did_intern) {
+ // Use internal method once.
spell_suggest_intern(su, interactive);
- if (sps_flags & SPS_DOUBLE)
+ if (sps_flags & SPS_DOUBLE) {
do_combine = true;
+ }
+ did_intern = true;
}
}
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 90af010164..3c125959a9 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -5387,7 +5387,8 @@ spell_add_word (
len, word, NameBuff);
}
}
- if (fseek(fd, fpos_next, SEEK_SET) <= 0) {
+ if (fseek(fd, fpos_next, SEEK_SET) != 0) {
+ PERROR(_("Seek error in spellfile"));
break;
}
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index c6b1a0d04c..84ca240734 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1461,7 +1461,7 @@ find_tags(
p_ic = ignorecase_opt(pat, true, true);
break;
default:
- assert(false);
+ abort();
}
help_save = curbuf->b_help;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 39e2ca6171..642c443318 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -535,8 +535,44 @@ void terminal_send(Terminal *term, char *data, size_t size)
term->opts.write_cb(data, size, term->opts.data);
}
+static bool is_filter_char(int c)
+{
+ unsigned int flag = 0;
+ switch (c) {
+ case 0x08:
+ flag = TPF_BS;
+ break;
+ case 0x09:
+ flag = TPF_HT;
+ break;
+ case 0x0A:
+ case 0x0D:
+ break;
+ case 0x0C:
+ flag = TPF_FF;
+ break;
+ case 0x1b:
+ flag = TPF_ESC;
+ break;
+ case 0x7F:
+ flag = TPF_DEL;
+ break;
+ default:
+ if (c < ' ') {
+ flag = TPF_C0;
+ } else if (c >= 0x80 && c <= 0x9F) {
+ flag = TPF_C1;
+ }
+ }
+ return !!(tpf_flags & flag);
+}
+
void terminal_paste(long count, char_u **y_array, size_t y_size)
{
+ vterm_keyboard_start_paste(curbuf->terminal->vt);
+ terminal_flush_output(curbuf->terminal);
+ size_t buff_len = STRLEN(y_array[0]);
+ char_u *buff = xmalloc(buff_len);
for (int i = 0; i < count; i++) { // -V756
// feed the lines to the terminal
for (size_t j = 0; j < y_size; j++) {
@@ -544,9 +580,28 @@ void terminal_paste(long count, char_u **y_array, size_t y_size)
// terminate the previous line
terminal_send(curbuf->terminal, "\n", 1);
}
- terminal_send(curbuf->terminal, (char *)y_array[j], STRLEN(y_array[j]));
+ size_t len = STRLEN(y_array[j]);
+ if (len > buff_len) {
+ buff = xrealloc(buff, len);
+ buff_len = len;
+ }
+ char_u *dst = buff;
+ char_u *src = y_array[j];
+ while (*src != '\0') {
+ len = (size_t)utf_ptr2len(src);
+ int c = utf_ptr2char(src);
+ if (!is_filter_char(c)) {
+ memcpy(dst, src, len);
+ dst += len;
+ }
+ src += len;
+ }
+ terminal_send(curbuf->terminal, (char *)buff, (size_t)(dst - buff));
}
}
+ xfree(buff);
+ vterm_keyboard_end_paste(curbuf->terminal->vt);
+ terminal_flush_output(curbuf->terminal);
}
void terminal_flush_output(Terminal *term)
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 641e98ab30..1f3a45a9ab 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -1110,14 +1110,14 @@ func Test_BufReadCmd()
endfunc
func SetChangeMarks(start, end)
- exe a:start. 'mark ['
- exe a:end. 'mark ]'
+ exe a:start .. 'mark ['
+ exe a:end .. 'mark ]'
endfunc
" Verify the effects of autocmds on '[ and ']
func Test_change_mark_in_autocmds()
edit! Xtest
- call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
+ call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn')
call SetChangeMarks(2, 3)
write
@@ -1279,26 +1279,9 @@ func Test_TextYankPost()
bwipe!
endfunc
-func Test_nocatch_wipe_all_buffers()
- " Real nasty autocommand: wipe all buffers on any event.
- au * * bwipe *
- call assert_fails('next x', 'E93')
- bwipe
- au!
-endfunc
-
-func Test_nocatch_wipe_dummy_buffer()
- " Nasty autocommand: wipe buffer on any event.
- au * x bwipe
- call assert_fails('lv½ /x', 'E480')
- au!
-endfunc
-
-func Test_wipe_cbuffer()
- sv x
- au * * bw
- lb
- au!
+func Test_autocommand_all_events()
+ call assert_fails('au * * bwipe', 'E1155:')
+ call assert_fails('au * x bwipe', 'E1155:')
endfunc
" Test TextChangedI and TextChangedP
@@ -1956,4 +1939,15 @@ func Test_autocmd_window()
%bw!
endfunc
+func Test_autocmd_closes_window()
+ au BufNew,BufWinLeave * e %e
+ file yyy
+ au BufNew,BufWinLeave * ball
+ call assert_fails('n xxx', 'E143:')
+
+ bwipe %
+ au! BufNew
+ au! BufWinLeave
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_backspace_opt.vim b/src/nvim/testdir/test_backspace_opt.vim
new file mode 100644
index 0000000000..d680b442db
--- /dev/null
+++ b/src/nvim/testdir/test_backspace_opt.vim
@@ -0,0 +1,151 @@
+" Tests for 'backspace' settings
+
+func Exec(expr)
+ let str=''
+ try
+ exec a:expr
+ catch /.*/
+ let str=v:exception
+ endtry
+ return str
+endfunc
+
+func Test_backspace_option()
+ set backspace=
+ call assert_equal('', &backspace)
+ set backspace=indent
+ call assert_equal('indent', &backspace)
+ set backspace=eol
+ call assert_equal('eol', &backspace)
+ set backspace=start
+ call assert_equal('start', &backspace)
+ set backspace=nostop
+ call assert_equal('nostop', &backspace)
+ " Add the value
+ set backspace=
+ set backspace=indent
+ call assert_equal('indent', &backspace)
+ set backspace+=eol
+ call assert_equal('indent,eol', &backspace)
+ set backspace+=start
+ call assert_equal('indent,eol,start', &backspace)
+ set backspace+=nostop
+ call assert_equal('indent,eol,start,nostop', &backspace)
+ " Delete the value
+ set backspace-=nostop
+ call assert_equal('indent,eol,start', &backspace)
+ set backspace-=indent
+ call assert_equal('eol,start', &backspace)
+ set backspace-=start
+ call assert_equal('eol', &backspace)
+ set backspace-=eol
+ call assert_equal('', &backspace)
+ " Check the error
+ call assert_equal(0, match(Exec('set backspace=ABC'), '.*E474'))
+ call assert_equal(0, match(Exec('set backspace+=def'), '.*E474'))
+ " NOTE: Vim doesn't check following error...
+ "call assert_equal(0, match(Exec('set backspace-=ghi'), '.*E474'))
+
+ " Check backwards compatibility with version 5.4 and earlier
+ set backspace=0
+ call assert_equal('0', &backspace)
+ set backspace=1
+ call assert_equal('1', &backspace)
+ set backspace=2
+ call assert_equal('2', &backspace)
+ set backspace=3
+ call assert_equal('3', &backspace)
+ call assert_false(match(Exec('set backspace=4'), '.*E474'))
+ call assert_false(match(Exec('set backspace=10'), '.*E474'))
+
+ " Cleared when 'compatible' is set
+ " set compatible
+ " call assert_equal('', &backspace)
+ set nocompatible viminfo+=nviminfo
+endfunc
+
+" Test with backspace set to the non-compatible setting
+func Test_backspace_ctrl_u()
+ new
+ call append(0, [
+ \ "1 this shouldn't be deleted",
+ \ "2 this shouldn't be deleted",
+ \ "3 this shouldn't be deleted",
+ \ "4 this should be deleted",
+ \ "5 this shouldn't be deleted",
+ \ "6 this shouldn't be deleted",
+ \ "7 this shouldn't be deleted",
+ \ "8 this shouldn't be deleted (not touched yet)"])
+ call cursor(2, 1)
+
+ " set compatible
+ set backspace=2
+
+ exe "normal Avim1\<C-U>\<Esc>\<CR>"
+ exe "normal Avim2\<C-G>u\<C-U>\<Esc>\<CR>"
+
+ set cpo-=<
+ inoremap <c-u> <left><c-u>
+ exe "normal Avim3\<C-U>\<Esc>\<CR>"
+ iunmap <c-u>
+ exe "normal Avim4\<C-U>\<C-U>\<Esc>\<CR>"
+
+ " Test with backspace set to the compatible setting
+ set backspace= visualbell
+ exe "normal A vim5\<Esc>A\<C-U>\<C-U>\<Esc>\<CR>"
+ exe "normal A vim6\<Esc>Azwei\<C-G>u\<C-U>\<Esc>\<CR>"
+
+ inoremap <c-u> <left><c-u>
+ exe "normal A vim7\<C-U>\<C-U>\<Esc>\<CR>"
+
+ call assert_equal([
+ \ "1 this shouldn't be deleted",
+ \ "2 this shouldn't be deleted",
+ \ "3 this shouldn't be deleted",
+ \ "4 this should be deleted3",
+ \ "",
+ \ "6 this shouldn't be deleted vim5",
+ \ "7 this shouldn't be deleted vim6",
+ \ "8 this shouldn't be deleted (not touched yet) vim7",
+ \ ""], getline(1, '$'))
+
+ " Reset values
+ set compatible&vim
+ set visualbell&vim
+ set backspace&vim
+
+ " Test new nostop option
+ %d_
+ let expected = "foo bar foobar"
+ call setline(1, expected)
+ call cursor(1, 8)
+ exe ":norm! ianotherone\<c-u>"
+ call assert_equal(expected, getline(1))
+ call cursor(1, 8)
+ exe ":norm! ianothertwo\<c-w>"
+ call assert_equal(expected, getline(1))
+
+ let content = getline(1)
+ for value in ['indent,nostop', 'eol,nostop', 'indent,eol,nostop', 'indent,eol,start,nostop']
+ exe ":set bs=".. value
+ %d _
+ call setline(1, content)
+ let expected = " foobar"
+ call cursor(1, 8)
+ exe ":norm! ianotherone\<c-u>"
+ call assert_equal(expected, getline(1), 'CTRL-U backspace value: '.. &bs)
+ let expected = "foo foobar"
+ call setline(1, content)
+ call cursor(1, 8)
+ exe ":norm! ianothertwo\<c-w>"
+ call assert_equal(expected, getline(1), 'CTRL-W backspace value: '.. &bs)
+ endfor
+
+ " Reset options
+ set compatible&vim
+ set visualbell&vim
+ set backspace&vim
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_compiler.vim b/src/nvim/testdir/test_compiler.vim
index 9101f8cfa0..d361205baa 100644
--- a/src/nvim/testdir/test_compiler.vim
+++ b/src/nvim/testdir/test_compiler.vim
@@ -37,17 +37,27 @@ func Test_compiler()
bw!
endfunc
+func GetCompilerNames()
+ " return glob('$VIMRUNTIME/compiler/*.vim', 0, 1)
+ " \ ->map({i, v -> substitute(v, '.*[\\/]\([a-zA-Z0-9_\-]*\).vim', '\1', '')})
+ " \ ->sort()
+ return sort(map(glob('$VIMRUNTIME/compiler/*.vim', 0, 1), {i, v -> substitute(v, '.*[\\/]\([a-zA-Z0-9_\-]*\).vim', '\1', '')}))
+endfunc
+
func Test_compiler_without_arg()
let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
let a = split(execute('compiler'))
- call assert_match(runtime .. '/compiler/ant.vim$', a[0])
- call assert_match(runtime .. '/compiler/bcc.vim$', a[1])
- call assert_match(runtime .. '/compiler/xo.vim$', a[-1])
+ let exp = GetCompilerNames()
+ call assert_match(runtime .. '/compiler/' .. exp[0] .. '.vim$', a[0])
+ call assert_match(runtime .. '/compiler/' .. exp[1] .. '.vim$', a[1])
+ call assert_match(runtime .. '/compiler/' .. exp[-1] .. '.vim$', a[-1])
endfunc
func Test_compiler_completion()
+ " let clist = GetCompilerNames()->join(' ')
+ let clist = join(GetCompilerNames(), ' ')
call feedkeys(":compiler \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"compiler ant bcc .* xmlwf xo$', @:)
+ call assert_match('^"compiler ' .. clist .. '$', @:)
call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"compiler pbx perl php pylint pyunit', @:)
diff --git a/src/nvim/testdir/test_eval_stuff.vim b/src/nvim/testdir/test_eval_stuff.vim
index 061364fb73..ff50d53d86 100644
--- a/src/nvim/testdir/test_eval_stuff.vim
+++ b/src/nvim/testdir/test_eval_stuff.vim
@@ -22,6 +22,17 @@ func Test_E963()
call assert_equal(v_o, v:oldfiles)
endfunc
+func Test_for_invalid()
+ call assert_fails("for x in 99", 'E714:')
+ call assert_fails("for x in 'asdf'", 'E714:')
+ call assert_fails("for x in {'a': 9}", 'E714:')
+
+ if 0
+ /1/5/2/s/\n
+ endif
+ redraw
+endfunc
+
func Test_mkdir_p()
call mkdir('Xmkdir/nested', 'p')
call assert_true(isdirectory('Xmkdir/nested'))
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 1cb68e7fef..f9f0ade1f6 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -159,6 +159,7 @@ let s:filename_checks = {
\ 'elinks': ['elinks.conf'],
\ 'elm': ['file.elm'],
\ 'elmfilt': ['filter-rules'],
+ \ 'epuppet': ['file.epp'],
\ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'],
\ 'eruby': ['file.erb', 'file.rhtml'],
\ 'esmtprc': ['anyesmtprc'],
@@ -171,6 +172,7 @@ let s:filename_checks = {
\ 'factor': ['file.factor'],
\ 'falcon': ['file.fal'],
\ 'fan': ['file.fan', 'file.fwt'],
+ \ 'fennel': ['file.fnl'],
\ 'fetchmail': ['.fetchmailrc'],
\ 'fgl': ['file.4gl', 'file.4gh', 'file.m4gl'],
\ 'focexec': ['file.fex', 'file.focexec'],
@@ -332,7 +334,7 @@ let s:filename_checks = {
\ 'pamconf': ['/etc/pam.conf'],
\ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment'],
\ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'],
- \ 'pascal': ['file.pas', 'file.pp', 'file.dpr', 'file.lpr'],
+ \ 'pascal': ['file.pas', 'file.dpr', 'file.lpr'],
\ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak'],
\ 'pbtxt': ['file.pbtxt'],
\ 'pccts': ['file.g'],
@@ -368,11 +370,13 @@ let s:filename_checks = {
\ 'proto': ['file.proto'],
\ 'protocols': ['/etc/protocols'],
\ 'psf': ['file.psf'],
+ \ 'puppet': ['file.pp'],
\ 'pyrex': ['file.pyx', 'file.pxd'],
\ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'],
\ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg'],
\ 'radiance': ['file.rad', 'file.mat'],
\ 'ratpoison': ['.ratpoisonrc', 'ratpoisonrc'],
+ \ 'rbs': ['file.rbs'],
\ 'rc': ['file.rc', 'file.rch'],
\ 'rcs': ['file,v'],
\ 'readline': ['.inputrc', 'inputrc'],
@@ -389,7 +393,7 @@ let s:filename_checks = {
\ 'rpl': ['file.rpl'],
\ 'rst': ['file.rst'],
\ 'rtf': ['file.rtf'],
- \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake'],
+ \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile'],
\ 'rust': ['file.rs'],
\ 'samba': ['smb.conf'],
\ 'sas': ['file.sas'],
@@ -428,6 +432,7 @@ let s:filename_checks = {
\ 'smith': ['file.smt', 'file.smith'],
\ 'sml': ['file.sml'],
\ 'snobol4': ['file.sno', 'file.spt'],
+ \ 'sparql': ['file.rq', 'file.sparql'],
\ 'spec': ['file.spec'],
\ 'spice': ['file.sp', 'file.spice'],
\ 'spup': ['file.speedup', 'file.spdata', 'file.spd'],
@@ -619,6 +624,8 @@ let s:script_checks = {
\ 'cpp': [['// Standard iostream objects -*- C++ -*-'],
\ ['// -*- C++ -*-']],
\ 'yaml': [['%YAML 1.2']],
+ \ 'pascal': [['#!/path/instantfpc']],
+ \ 'fennel': [['#!/path/fennel']],
\ }
" Various forms of "env" optional arguments.
@@ -689,5 +696,50 @@ func Test_ts_file()
filetype off
endfunc
+func Test_ttl_file()
+ filetype on
+
+ call writefile(['@base <http://example.org/> .'], 'Xfile.ttl')
+ split Xfile.ttl
+ call assert_equal('turtle', &filetype)
+ bwipe!
+
+ call writefile(['looks like Tera Term Language'], 'Xfile.ttl')
+ split Xfile.ttl
+ call assert_equal('teraterm', &filetype)
+ bwipe!
+
+ call delete('Xfile.ttl')
+ filetype off
+endfunc
+
+func Test_pp_file()
+ filetype on
+
+ call writefile(['looks like puppet'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('puppet', &filetype)
+ bwipe!
+
+ let g:filetype_pp = 'pascal'
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ " Test dist#ft#FTpp()
+ call writefile(['{ pascal comment'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ call writefile(['procedure pascal'], 'Xfile.pp')
+ split Xfile.pp
+ call assert_equal('pascal', &filetype)
+ bwipe!
+
+ call delete('Xfile.pp')
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 88ce64b9eb..2d058e8e32 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -822,4 +822,39 @@ func Test_fold_create_delete()
bwipe!
endfunc
+func Test_fold_relative_move()
+ enew!
+ set fdm=indent sw=2 wrap tw=80
+
+ let content = [ ' foo', ' bar', ' baz',
+ \ repeat('x', &columns + 1),
+ \ ' foo', ' bar', ' baz'
+ \ ]
+ call append(0, content)
+
+ normal zM
+
+ call cursor(3, 1)
+ call assert_true(foldclosed(line('.')))
+ normal gj
+ call assert_equal(2, winline())
+
+ call cursor(2, 1)
+ call assert_true(foldclosed(line('.')))
+ normal 2gj
+ call assert_equal(3, winline())
+
+ call cursor(5, 1)
+ call assert_true(foldclosed(line('.')))
+ normal gk
+ call assert_equal(3, winline())
+
+ call cursor(6, 1)
+ call assert_true(foldclosed(line('.')))
+ normal 2gk
+ call assert_equal(2, winline())
+
+ set fdm& sw& wrap& tw&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index 8f6834c2ab..4cc4d775d1 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -2,6 +2,7 @@
source view_util.vim
source screendump.vim
+source check.vim
func Test_highlight()
" basic test if ":highlight" doesn't crash
@@ -610,3 +611,16 @@ func Test_1_highlight_Normalgroup_exists()
call assert_match('hi Normal\s*font=.*', hlNormal)
endif
endfunc
+
+" Test for using RGB color values in a highlight group
+func Test_xxlast_highlight_RGB_color()
+ CheckCanRunGui
+ gui -f
+ hi MySearch guifg=#110000 guibg=#001100 guisp=#000011
+ call assert_equal('#110000', synIDattr(synIDtrans(hlID('MySearch')), 'fg#'))
+ call assert_equal('#001100', synIDattr(synIDtrans(hlID('MySearch')), 'bg#'))
+ call assert_equal('#000011', synIDattr(synIDtrans(hlID('MySearch')), 'sp#'))
+ hi clear
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index e25fe33bb7..2fd82a4b6d 100644
--- a/src/nvim/testdir/test_marks.vim
+++ b/src/nvim/testdir/test_marks.vim
@@ -171,6 +171,11 @@ func Test_delmarks()
" Deleting an already deleted mark should not fail.
delmarks x
+ " getpos() should return all zeros after deleting a filemark.
+ norm mA
+ delmarks A
+ call assert_equal([0, 0, 0, 0], getpos("'A"))
+
" Test deleting a range of marks.
norm ma
norm mb
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index f71da92bf8..88320e0c22 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -291,6 +291,32 @@ endfunc
endif
+func Test_mkview_open_folds()
+ enew!
+
+ call append(0, ['a', 'b', 'c'])
+ 1,3fold
+ " zR affects 'foldlevel', make sure the option is applied after the folds
+ " have been recreated.
+ normal zR
+ write! Xtestfile
+
+ call assert_equal(-1, foldclosed(1))
+ call assert_equal(-1, foldclosed(2))
+ call assert_equal(-1, foldclosed(3))
+
+ mkview! Xtestview
+ source Xtestview
+
+ call assert_equal(-1, foldclosed(1))
+ call assert_equal(-1, foldclosed(2))
+ call assert_equal(-1, foldclosed(3))
+
+ call delete('Xtestview')
+ call delete('Xtestfile')
+ %bwipe
+endfunc
+
" Test :mkview with a file argument.
func Test_mkview_file()
" Create a view with line number and a fold.
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index ccc5e6ffc9..5a10c9baa6 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -266,8 +266,14 @@ func Test_set_errors()
call assert_fails('set foldmarker=x', 'E536:')
call assert_fails('set commentstring=x', 'E537:')
call assert_fails('set complete=x', 'E539:')
+ call assert_fails('set rulerformat=%-', 'E539:')
+ call assert_fails('set rulerformat=%(', 'E542:')
+ call assert_fails('set rulerformat=%15(%%', 'E542:')
+ call assert_fails('set statusline=%$', 'E539:')
call assert_fails('set statusline=%{', 'E540:')
call assert_fails('set statusline=%(', 'E542:')
+ call assert_fails('set statusline=%)', 'E542:')
+
if has('cursorshape')
" This invalid value for 'guicursor' used to cause Vim to crash.
call assert_fails('set guicursor=i-ci,r-cr:h', 'E545:')
@@ -281,6 +287,21 @@ func Test_set_errors()
call assert_fails('set winminwidth=10 winwidth=9', 'E592:')
call assert_fails("set showbreak=\x01", 'E595:')
call assert_fails('set t_foo=', 'E846:')
+ if has('python') || has('python3')
+ call assert_fails('set pyxversion=6', 'E474:')
+ endif
+ call assert_fails("let &tabstop='ab'", 'E521:')
+ call assert_fails('set sessionoptions=curdir,sesdir', 'E474:')
+ call assert_fails('set foldmarker={{{,', 'E474:')
+ call assert_fails('set sessionoptions=sesdir,curdir', 'E474:')
+ call assert_fails('set listchars=trail:· ambiwidth=double', 'E834:')
+ set listchars&
+ call assert_fails('set fillchars=stl:· ambiwidth=double', 'E835:')
+ set fillchars&
+ call assert_fails('set fileencoding=latin1,utf-8', 'E474:')
+ set nomodifiable
+ call assert_fails('set fileencoding=latin1', 'E21:')
+ set modifiable&
endfunc
" Must be executed before other tests that set 'term'.
@@ -309,12 +330,10 @@ func Test_set_ttytype()
set ttytype=xterm
call assert_equal('xterm', &ttytype)
call assert_equal(&ttytype, &term)
- " "set ttytype=" gives E522 instead of E529
- " in travis on some builds. Why? Catch both for now
try
set ttytype=
call assert_report('set ttytype= did not fail')
- catch /E529\|E522/
+ catch /E529/
endtry
" Some systems accept any terminal name and return dumb settings,
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 48c0a83053..704fdacdcd 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -2650,6 +2650,13 @@ func Test_vimgrep()
call XvimgrepTests('l')
endfunc
+func Test_vimgrep_wildcards_expanded_once()
+ new X[id-01] file.txt
+ call setline(1, 'some text to search for')
+ vimgrep text %
+ bwipe!
+endfunc
+
" Test for incsearch highlighting of the :vimgrep pattern
" This test used to cause "E315: ml_get: invalid lnum" errors.
func Test_vimgrep_incsearch()
@@ -3540,7 +3547,7 @@ func Test_lbuffer_crash()
sv Xtest
augroup QF_Test
au!
- au * * bw
+ au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bw
augroup END
lbuffer
augroup QF_Test
@@ -3552,7 +3559,7 @@ endfunc
func Test_lexpr_crash()
augroup QF_Test
au!
- au * * call setloclist(0, [], 'f')
+ au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
augroup END
lexpr ""
augroup QF_Test
@@ -3587,7 +3594,7 @@ func Test_lvimgrep_crash()
sv Xtest
augroup QF_Test
au!
- au * * call setloclist(0, [], 'f')
+ au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call setloclist(0, [], 'f')
augroup END
lvimgrep quickfix test_quickfix.vim
augroup QF_Test
@@ -3889,7 +3896,7 @@ func Test_lbuffer_with_bwipe()
new
new
augroup nasty
- au * * bwipe
+ au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * bwipe
augroup END
lbuffer
augroup nasty
@@ -3902,9 +3909,9 @@ endfunc
func Xexpr_acmd_freelist(cchar)
call s:setup_commands(a:cchar)
- " This was using freed memory.
+ " This was using freed memory (but with what events?)
augroup nasty
- au * * call g:Xsetlist([], 'f')
+ au QuickFixCmdPre,QuickFixCmdPost,BufEnter,BufLeave * call g:Xsetlist([], 'f')
augroup END
Xexpr "x"
augroup nasty
diff --git a/src/nvim/testdir/test_sleep.vim b/src/nvim/testdir/test_sleep.vim
new file mode 100644
index 0000000000..f71855fd4b
--- /dev/null
+++ b/src/nvim/testdir/test_sleep.vim
@@ -0,0 +1,26 @@
+" Test for sleep and sleep! commands
+
+func! s:get_time_ms()
+ let timestr = reltimestr(reltime())
+ let dotidx = stridx(timestr, '.')
+ let sec = str2nr(timestr[:dotidx])
+ let msec = str2nr(timestr[dotidx + 1:])
+ return (sec * 1000) + (msec / 1000)
+endfunc
+
+func! s:assert_takes_longer(cmd, time_ms)
+ let start = s:get_time_ms()
+ execute a:cmd
+ let end = s:get_time_ms()
+ call assert_true(end - start >=# a:time_ms)
+endfun
+
+func! Test_sleep_bang()
+ call s:assert_takes_longer('sleep 50m', 50)
+ call s:assert_takes_longer('sleep! 50m', 50)
+ call s:assert_takes_longer('sl 50m', 50)
+ call s:assert_takes_longer('sl! 50m', 50)
+ call s:assert_takes_longer('1sleep', 1000)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index e7f332bc4c..e6ad92f483 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -735,4 +735,82 @@ func Test_x_arg()
call delete('Xtest_x_arg')
endfunc
+" Test starting vim with various names: vim, ex, view, evim, etc.
+func Test_progname()
+ CheckUnix
+
+ call mkdir('Xprogname', 'p')
+ call writefile(['silent !date',
+ \ 'call writefile([mode(1), '
+ \ .. '&insertmode, &diff, &readonly, &updatecount, '
+ \ .. 'join(split(execute("message"), "\n")[1:])], "Xprogname_out")',
+ \ 'qall'], 'Xprogname_after')
+
+ " +---------------------------------------------- progname
+ " | +--------------------------------- mode(1)
+ " | | +--------------------------- &insertmode
+ " | | | +---------------------- &diff
+ " | | | | +----------------- &readonly
+ " | | | | | +-------- &updatecount
+ " | | | | | | +--- :messages
+ " | | | | | | |
+ " let expectations = {
+ " \ 'vim': ['n', '0', '0', '0', '200', ''],
+ " \ 'gvim': ['n', '0', '0', '0', '200', ''],
+ " \ 'ex': ['ce', '0', '0', '0', '200', ''],
+ " \ 'exim': ['cv', '0', '0', '0', '200', ''],
+ " \ 'view': ['n', '0', '0', '1', '10000', ''],
+ " \ 'gview': ['n', '0', '0', '1', '10000', ''],
+ " \ 'evim': ['n', '1', '0', '0', '200', ''],
+ " \ 'eview': ['n', '1', '0', '1', '10000', ''],
+ " \ 'rvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rgvim': ['n', '0', '0', '0', '200', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'rgview': ['n', '0', '0', '1', '10000', 'line 1: E145: Shell commands and some functionality not allowed in rvim'],
+ " \ 'vimdiff': ['n', '0', '1', '0', '200', ''],
+ " \ 'gvimdiff': ['n', '0', '1', '0', '200', '']}
+ let expectations = {'nvim': ['n', '0', '0', '0', '200', '']}
+
+ " let prognames = ['vim', 'gvim', 'ex', 'exim', 'view', 'gview',
+ " \ 'evim', 'eview', 'rvim', 'rgvim', 'rview', 'rgview',
+ " \ 'vimdiff', 'gvimdiff']
+ let prognames = ['nvim']
+
+ for progname in prognames
+ if empty($DISPLAY)
+ if progname =~# 'g'
+ " Can't run gvim, gview (etc.) if $DISPLAY is not setup.
+ continue
+ endif
+ if has('gui') && (progname ==# 'evim' || progname ==# 'eview')
+ " evim or eview will start the GUI if there is gui support.
+ " So don't try to start them either if $DISPLAY is not setup.
+ continue
+ endif
+ endif
+
+ exe 'silent !ln -s -f ' ..exepath(GetVimProg()) .. ' Xprogname/' .. progname
+
+ let stdout_stderr = ''
+ if progname =~# 'g'
+ let stdout_stderr = system('Xprogname/'..progname..' -f --clean --not-a-term -S Xprogname_after')
+ else
+ exe 'sil !Xprogname/'..progname..' -f --clean -S Xprogname_after'
+ endif
+
+ if progname =~# 'g' && !has('gui')
+ call assert_equal("E25: GUI cannot be used: Not enabled at compile time\n", stdout_stderr, progname)
+ else
+ call assert_equal('', stdout_stderr, progname)
+ call assert_equal(expectations[progname], readfile('Xprogname_out'), progname)
+ endif
+
+ call delete('Xprogname/' .. progname)
+ call delete('Xprogname_out')
+ endfor
+
+ call delete('Xprogname_after')
+ call delete('Xprogname', 'd')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index 687b1cb989..969b75d424 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -513,8 +513,8 @@ func Test_window_colon_command()
endfunc
func Test_access_freed_mem()
- " This was accessing freed memory
- au * 0 vs xxx
+ " This was accessing freed memory (but with what events?)
+ au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
arg 0
argadd
all
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 124f96e039..3e683a4926 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -297,7 +297,7 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Release");
break;
case TERMKEY_MOUSE_UNKNOWN:
- assert(false);
+ abort();
}
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "><%d,%d>", col, row);
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 9d3ec21949..06efc9fa99 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -157,7 +157,7 @@ bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width,
#ifndef NDEBUG
for (size_t i = 0; i < kv_size(layers); i++) {
if (kv_A(layers, i) == grid) {
- assert(false);
+ abort();
}
}
#endif
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 834d27cc84..deba3f6e49 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -300,7 +300,7 @@ static const int included_patches[] = {
1620,
1619,
1618,
- // 1617,
+ 1617,
// 1616,
1615,
1614,
@@ -392,7 +392,7 @@ static const int included_patches[] = {
1528,
1527,
1526,
- // 1525,
+ 1525,
1524,
1523,
1522,
@@ -462,7 +462,7 @@ static const int included_patches[] = {
1458,
1457,
1456,
- // 1455,
+ 1455,
1454,
1453,
1452,
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 01f20cf29a..e70749795b 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -159,6 +159,7 @@ enum {
EXPAND_MAPCLEAR,
EXPAND_ARGLIST,
EXPAND_CHECKHEALTH,
+ EXPAND_LUA,
};
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 44b6ab5f5a..e9d82ca87d 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -2078,7 +2078,7 @@ viml_pexpr_parse_process_token:
case kExprLexMissing:
case kExprLexSpacing:
case kExprLexEOC: {
- assert(false);
+ abort();
}
case kExprLexInvalid: {
ERROR_FROM_TOKEN(cur_token);
@@ -3028,7 +3028,7 @@ viml_pexpr_parse_end:
// Until trailing "}" it is impossible to distinguish curly braces
// identifier and dictionary, so it must not appear in the stack like
// this.
- assert(false);
+ abort();
}
case kExprNodeInteger:
case kExprNodeFloat:
@@ -3042,7 +3042,7 @@ viml_pexpr_parse_end:
// These are plain values and not containers, for them it should only
// be possible to show up in the topmost stack element, but it was
// unconditionally popped at the start.
- assert(false);
+ abort();
}
case kExprNodeComma:
case kExprNodeColon: