aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/CMakeLists.txt2
-rw-r--r--src/nvim/api/buffer.c520
-rw-r--r--src/nvim/api/deprecated.c367
-rw-r--r--src/nvim/api/deprecated.h11
-rw-r--r--src/nvim/api/private/dispatch.c1
-rw-r--r--src/nvim/api/private/helpers.c4
-rw-r--r--src/nvim/api/private/helpers.h5
-rw-r--r--src/nvim/api/tabpage.c42
-rw-r--r--src/nvim/api/vim.c86
-rw-r--r--src/nvim/api/window.c44
-rw-r--r--src/nvim/arabic.c4
-rw-r--r--src/nvim/ascii.h12
-rw-r--r--src/nvim/autocmd.c31
-rw-r--r--src/nvim/autocmd.h14
-rw-r--r--src/nvim/buffer.c99
-rw-r--r--src/nvim/buffer_defs.h11
-rw-r--r--src/nvim/buffer_updates.c4
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/diff.c5
-rw-r--r--src/nvim/edit.c169
-rw-r--r--src/nvim/eval.c64
-rw-r--r--src/nvim/eval.lua2
-rw-r--r--src/nvim/eval/funcs.c58
-rw-r--r--src/nvim/eval/typval.c13
-rw-r--r--src/nvim/eval/typval.h2
-rw-r--r--src/nvim/eval/userfunc.c5
-rw-r--r--src/nvim/ex_cmds.c146
-rw-r--r--src/nvim/ex_cmds.lua1690
-rw-r--r--src/nvim/ex_cmds2.c12
-rw-r--r--src/nvim/ex_cmds_defs.h84
-rw-r--r--src/nvim/ex_docmd.c524
-rw-r--r--src/nvim/ex_eval.c35
-rw-r--r--src/nvim/ex_getln.c38
-rw-r--r--src/nvim/ex_session.c46
-rw-r--r--src/nvim/extmark.c17
-rw-r--r--src/nvim/fileio.c24
-rw-r--r--src/nvim/fold.c3
-rw-r--r--src/nvim/func_attr.h2
-rw-r--r--src/nvim/generators/c_grammar.lua1
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua17
-rw-r--r--src/nvim/generators/gen_ex_cmds.lua18
-rw-r--r--src/nvim/globals.h7
-rw-r--r--src/nvim/hardcopy.c1
-rw-r--r--src/nvim/log.c9
-rw-r--r--src/nvim/lua/vim.lua6
-rw-r--r--src/nvim/macros.h3
-rw-r--r--src/nvim/main.c38
-rw-r--r--src/nvim/mark.c85
-rw-r--r--src/nvim/marktree.c3
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/message.c17
-rw-r--r--src/nvim/mouse.c46
-rw-r--r--src/nvim/move.c552
-rw-r--r--src/nvim/msgpack_rpc/channel.c6
-rw-r--r--src/nvim/normal.c144
-rw-r--r--src/nvim/ops.c53
-rw-r--r--src/nvim/option.c133
-rw-r--r--src/nvim/option_defs.h8
-rw-r--r--src/nvim/options.lua1
-rw-r--r--src/nvim/os/env.c53
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/os/lang.c3
-rw-r--r--src/nvim/os/users.c2
-rw-r--r--src/nvim/popupmnu.c3
-rw-r--r--src/nvim/quickfix.c324
-rw-r--r--src/nvim/regexp.c25
-rw-r--r--src/nvim/regexp_nfa.c30
-rw-r--r--src/nvim/screen.c48
-rw-r--r--src/nvim/search.c15
-rw-r--r--src/nvim/sign.c70
-rw-r--r--src/nvim/sign_defs.h16
-rw-r--r--src/nvim/spell.c9
-rw-r--r--src/nvim/spell.h1
-rw-r--r--src/nvim/syntax.c37
-rw-r--r--src/nvim/testdir/check.vim11
-rw-r--r--src/nvim/testdir/runtest.vim2
-rw-r--r--src/nvim/testdir/setup.vim1
-rw-r--r--src/nvim/testdir/test49.ok28
-rw-r--r--src/nvim/testdir/test49.vim2342
-rw-r--r--src/nvim/testdir/test_backspace_opt.vim151
-rw-r--r--src/nvim/testdir/test_clientserver.vim9
-rw-r--r--src/nvim/testdir/test_cmdline.vim111
-rw-r--r--src/nvim/testdir/test_const.vim2
-rw-r--r--src/nvim/testdir/test_digraph.vim22
-rw-r--r--src/nvim/testdir/test_excmd.vim91
-rw-r--r--src/nvim/testdir/test_fileformat.vim23
-rw-r--r--src/nvim/testdir/test_filetype.vim25
-rw-r--r--src/nvim/testdir/test_find_complete.vim8
-rw-r--r--src/nvim/testdir/test_findfile.vim43
-rw-r--r--src/nvim/testdir/test_fold.vim7
-rw-r--r--src/nvim/testdir/test_global.vim11
-rw-r--r--src/nvim/testdir/test_hardcopy.vim80
-rw-r--r--src/nvim/testdir/test_help.vim46
-rw-r--r--src/nvim/testdir/test_ins_complete.vim34
-rw-r--r--src/nvim/testdir/test_marks.vim30
-rw-r--r--src/nvim/testdir/test_mksession.vim192
-rw-r--r--src/nvim/testdir/test_normal.vim15
-rw-r--r--src/nvim/testdir/test_options.vim10
-rw-r--r--src/nvim/testdir/test_quickfix.vim274
-rw-r--r--src/nvim/testdir/test_regexp_latin.vim7
-rw-r--r--src/nvim/testdir/test_regexp_utf8.vim11
-rw-r--r--src/nvim/testdir/test_registers.vim57
-rw-r--r--src/nvim/testdir/test_ruby.vim24
-rw-r--r--src/nvim/testdir/test_search.vim25
-rw-r--r--src/nvim/testdir/test_signals.vim140
-rw-r--r--src/nvim/testdir/test_signs.vim61
-rw-r--r--src/nvim/testdir/test_startup.vim50
-rw-r--r--src/nvim/testdir/test_system.vim2
-rw-r--r--src/nvim/testdir/test_tabpage.vim109
-rw-r--r--src/nvim/testdir/test_textformat.vim222
-rw-r--r--src/nvim/testdir/test_trycatch.vim1977
-rw-r--r--src/nvim/testdir/test_usercommands.vim10
-rw-r--r--src/nvim/testdir/test_utf8.vim11
-rw-r--r--src/nvim/testdir/test_vimscript.vim198
-rw-r--r--src/nvim/testdir/test_window_cmd.vim8
-rw-r--r--src/nvim/ui.c63
-rw-r--r--src/nvim/undo.c7
-rw-r--r--src/nvim/version.c1
-rw-r--r--src/nvim/version.h11
-rw-r--r--src/nvim/vim.h1
-rw-r--r--src/nvim/window.c90
121 files changed, 7741 insertions, 4902 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 8ec087c626..db77931c16 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -242,7 +242,7 @@ if(use_git_version)
add_custom_target(update_version_stamp ALL
COMMAND ${LUA_PRG} scripts/update_version_stamp.lua
${relbuild}/config/auto/versiondef_git.h
- "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}"
+ "v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}${NVIM_VERSION_PRERELEASE}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
BYPRODUCTS ${CMAKE_BINARY_DIR}/config/auto/versiondef_git.h)
else()
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 1011f050fd..8d82d22040 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1,7 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-// Much of this code was adapted from 'if_py_both.h' from the original
+// Some of this code was adapted from 'if_py_both.h' from the original
// vim source
#include <stdbool.h>
#include <stdint.h>
@@ -80,34 +80,6 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
return buf->b_ml.ml_line_count;
}
-/// Gets a buffer line
-///
-/// @deprecated use nvim_buf_get_lines instead.
-/// for positive indices (including 0) use
-/// "nvim_buf_get_lines(buffer, index, index+1, true)"
-/// for negative indices use
-/// "nvim_buf_get_lines(buffer, index-1, index, true)"
-///
-/// @param buffer Buffer handle
-/// @param index Line index
-/// @param[out] err Error details, if any
-/// @return Line string
-String buffer_get_line(Buffer buffer, Integer index, Error *err)
-{
- String rv = { .size = 0 };
-
- index = convert_index(index);
- Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err);
-
- if (!ERROR_SET(err) && slice.size) {
- rv = slice.items[0].data.string;
- }
-
- xfree(slice.items);
-
- return rv;
-}
-
/// Activates buffer-update events on a channel, or as Lua callbacks.
///
/// Example (Lua): capture buffer updates in a global `events` variable
@@ -149,6 +121,8 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// - buffer handle
/// - utf_sizes: include UTF-32 and UTF-16 size of the replaced
/// region, as args to `on_lines`.
+/// - preview: also attach to command preview (i.e. 'inccommand')
+/// events.
/// @param[out] err Error details, if any
/// @return False if attach failed (invalid parameter, or buffer isn't loaded);
/// otherwise True. TODO: LUA_API_NO_EVAL
@@ -204,6 +178,12 @@ Boolean nvim_buf_attach(uint64_t channel_id,
goto error;
}
cb.utf_sizes = v->data.boolean;
+ } else if (is_lua && strequal("preview", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation, "preview must be boolean");
+ goto error;
+ }
+ cb.preview = v->data.boolean;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
@@ -258,68 +238,6 @@ void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last,
redraw_buf_range_later(buf, (linenr_T)first+1, (linenr_T)last);
}
-/// Sets a buffer line
-///
-/// @deprecated use nvim_buf_set_lines instead.
-/// for positive indices use
-/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])"
-/// for negative indices use
-/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])"
-///
-/// @param buffer Buffer handle
-/// @param index Line index
-/// @param line Contents of the new line
-/// @param[out] err Error details, if any
-void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
-{
- Object l = STRING_OBJ(line);
- Array array = { .items = &l, .size = 1 };
- index = convert_index(index);
- nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
-}
-
-/// Deletes a buffer line
-///
-/// @deprecated use nvim_buf_set_lines instead.
-/// for positive indices use
-/// "nvim_buf_set_lines(buffer, index, index+1, true, [])"
-/// for negative indices use
-/// "nvim_buf_set_lines(buffer, index-1, index, true, [])"
-/// @param buffer buffer handle
-/// @param index line index
-/// @param[out] err Error details, if any
-void buffer_del_line(Buffer buffer, Integer index, Error *err)
-{
- Array array = ARRAY_DICT_INIT;
- index = convert_index(index);
- nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
-}
-
-/// Retrieves a line range from the buffer
-///
-/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false)
-/// where newstart = start + int(not include_start) - int(start < 0)
-/// newend = end + int(include_end) - int(end < 0)
-/// int(bool) = 1 if bool is true else 0
-/// @param buffer Buffer handle
-/// @param start First line index
-/// @param end Last line index
-/// @param include_start True if the slice includes the `start` parameter
-/// @param include_end True if the slice includes the `end` parameter
-/// @param[out] err Error details, if any
-/// @return Array of lines
-ArrayOf(String) buffer_get_line_slice(Buffer buffer,
- Integer start,
- Integer end,
- Boolean include_start,
- Boolean include_end,
- Error *err)
-{
- start = convert_index(start) + !include_start;
- end = convert_index(end) + include_end;
- return nvim_buf_get_lines(0, buffer, start , end, false, err);
-}
-
/// Gets a line-range from the buffer.
///
/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
@@ -391,36 +309,28 @@ end:
return rv;
}
-
-/// Replaces a line range on the buffer
-///
-/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines)
-/// where newstart = start + int(not include_start) + int(start < 0)
-/// newend = end + int(include_end) + int(end < 0)
-/// int(bool) = 1 if bool is true else 0
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param start First line index
-/// @param end Last line index
-/// @param include_start True if the slice includes the `start` parameter
-/// @param include_end True if the slice includes the `end` parameter
-/// @param replacement Array of lines to use as replacement (0-length
-// array will delete the line range)
-/// @param[out] err Error details, if any
-void buffer_set_line_slice(Buffer buffer,
- Integer start,
- Integer end,
- Boolean include_start,
- Boolean include_end,
- ArrayOf(String) replacement,
- Error *err)
+static bool check_string_array(Array arr, bool disallow_nl, Error *err)
{
- start = convert_index(start) + !include_start;
- end = convert_index(end) + include_end;
- nvim_buf_set_lines(0, buffer, start, end, false, replacement, err);
+ for (size_t i = 0; i < arr.size; i++) {
+ if (arr.items[i].type != kObjectTypeString) {
+ api_set_error(err,
+ kErrorTypeValidation,
+ "All items in the replacement array must be strings");
+ return false;
+ }
+ // Disallow newlines in the middle of the line.
+ if (disallow_nl) {
+ const String l = arr.items[i].data.string;
+ if (memchr(l.data, NL, l.size)) {
+ api_set_error(err, kErrorTypeValidation,
+ "String cannot contain newlines");
+ return false;
+ }
+ }
+ }
+ return true;
}
-
/// Sets (replaces) a line-range in the buffer.
///
/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
@@ -448,6 +358,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
ArrayOf(String) replacement,
Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -472,22 +383,9 @@ void nvim_buf_set_lines(uint64_t channel_id,
return;
}
- for (size_t i = 0; i < replacement.size; i++) {
- if (replacement.items[i].type != kObjectTypeString) {
- api_set_error(err,
- kErrorTypeValidation,
- "All items in the replacement array must be strings");
- return;
- }
- // Disallow newlines in the middle of the line.
- if (channel_id != VIML_INTERNAL_CALL) {
- const String l = replacement.items[i].data.string;
- if (memchr(l.data, NL, l.size)) {
- api_set_error(err, kErrorTypeValidation,
- "String cannot contain newlines");
- return;
- }
- }
+ bool disallow_nl = (channel_id != VIML_INTERNAL_CALL);
+ if (!check_string_array(replacement, disallow_nl, err)) {
+ return;
}
size_t new_len = replacement.size;
@@ -597,6 +495,250 @@ end:
try_end(err);
}
+/// Sets (replaces) a range in the buffer
+///
+/// This is recommended over nvim_buf_set_lines when only modifying parts of a
+/// line, as extmarks will be preserved on non-modified parts of the touched
+/// lines.
+///
+/// Indexing is zero-based and end-exclusive.
+///
+/// To insert text at a given index, set `start` and `end` ranges to the same
+/// index. To delete a range, set `replacement` to an array containing
+/// an empty string, or simply an empty array.
+///
+/// Prefer nvim_buf_set_lines when adding or deleting entire lines only.
+///
+/// @param channel_id
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param start_row First line index
+/// @param start_column Last column
+/// @param end_row Last line index
+/// @param end_column Last column
+/// @param replacement Array of lines to use as replacement
+/// @param[out] err Error details, if any
+void nvim_buf_set_text(uint64_t channel_id, Buffer buffer,
+ Integer start_row, Integer start_col,
+ Integer end_row, Integer end_col,
+ ArrayOf(String) replacement, Error *err)
+ FUNC_API_SINCE(7)
+{
+ FIXED_TEMP_ARRAY(scratch, 1);
+ if (replacement.size == 0) {
+ scratch.items[0] = STRING_OBJ(STATIC_CSTR_AS_STRING(""));
+ replacement = scratch;
+ }
+
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+ if (!buf) {
+ return;
+ }
+
+ bool oob = false;
+
+ // check range is ordered and everything!
+ // start_row, end_row within buffer len (except add text past the end?)
+ start_row = normalize_index(buf, start_row, &oob);
+ if (oob || start_row == buf->b_ml.ml_line_count + 1) {
+ api_set_error(err, kErrorTypeValidation, "start_row out of bounds");
+ return;
+ }
+
+ end_row = normalize_index(buf, end_row, &oob);
+ if (oob || end_row == buf->b_ml.ml_line_count + 1) {
+ api_set_error(err, kErrorTypeValidation, "end_row out of bounds");
+ return;
+ }
+
+ char *str_at_start = (char *)ml_get_buf(buf, start_row, false);
+ if (start_col < 0 || (size_t)start_col > strlen(str_at_start)) {
+ api_set_error(err, kErrorTypeValidation, "start_col out of bounds");
+ return;
+ }
+
+ char *str_at_end = (char *)ml_get_buf(buf, end_row, false);
+ size_t len_at_end = strlen(str_at_end);
+ if (end_col < 0 || (size_t)end_col > len_at_end) {
+ api_set_error(err, kErrorTypeValidation, "end_col out of bounds");
+ return;
+ }
+
+ if (start_row > end_row || (end_row == start_row && start_col > end_col)) {
+ api_set_error(err, kErrorTypeValidation, "start is higher than end");
+ return;
+ }
+
+ bool disallow_nl = (channel_id != VIML_INTERNAL_CALL);
+ if (!check_string_array(replacement, disallow_nl, err)) {
+ return;
+ }
+
+ size_t new_len = replacement.size;
+
+ bcount_t new_byte = 0;
+ bcount_t old_byte = 0;
+
+ // calculate byte size of old region before it gets modified/deleted
+ if (start_row == end_row) {
+ old_byte = (bcount_t)end_col - start_col;
+ } else {
+ const char *bufline;
+ old_byte += (bcount_t)strlen(str_at_start) - start_col;
+ for (int64_t i = 1; i < end_row - start_row; i++) {
+ int64_t lnum = start_row + i;
+
+ bufline = (char *)ml_get_buf(buf, lnum, false);
+ old_byte += (bcount_t)(strlen(bufline))+1;
+ }
+ old_byte += (bcount_t)end_col+1;
+ }
+
+ String first_item = replacement.items[0].data.string;
+ String last_item = replacement.items[replacement.size-1].data.string;
+
+ size_t firstlen = (size_t)start_col+first_item.size;
+ size_t last_part_len = strlen(str_at_end) - (size_t)end_col;
+ if (replacement.size == 1) {
+ firstlen += last_part_len;
+ }
+ char *first = xmallocz(firstlen), *last = NULL;
+ memcpy(first, str_at_start, (size_t)start_col);
+ memcpy(first+start_col, first_item.data, first_item.size);
+ memchrsub(first+start_col, NUL, NL, first_item.size);
+ if (replacement.size == 1) {
+ memcpy(first+start_col+first_item.size, str_at_end+end_col, last_part_len);
+ } else {
+ last = xmallocz(last_item.size+last_part_len);
+ memcpy(last, last_item.data, last_item.size);
+ memchrsub(last, NUL, NL, last_item.size);
+ memcpy(last+last_item.size, str_at_end+end_col, last_part_len);
+ }
+
+ char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL;
+ lines[0] = first;
+ new_byte += (bcount_t)(first_item.size);
+ for (size_t i = 1; i < new_len-1; i++) {
+ const String l = replacement.items[i].data.string;
+
+ // Fill lines[i] with l's contents. Convert NULs to newlines as required by
+ // NL-used-for-NUL.
+ lines[i] = xmemdupz(l.data, l.size);
+ memchrsub(lines[i], NUL, NL, l.size);
+ new_byte += (bcount_t)(l.size)+1;
+ }
+ if (replacement.size > 1) {
+ lines[replacement.size-1] = last;
+ new_byte += (bcount_t)(last_item.size)+1;
+ }
+
+ try_start();
+ aco_save_T aco;
+ aucmd_prepbuf(&aco, (buf_T *)buf);
+
+ if (!MODIFIABLE(buf)) {
+ api_set_error(err, kErrorTypeException, "Buffer is not 'modifiable'");
+ goto end;
+ }
+
+ // Small note about undo states: unlike set_lines, we want to save the
+ // undo state of one past the end_row, since end_row is inclusive.
+ if (u_save((linenr_T)start_row - 1, (linenr_T)end_row + 1) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to save undo information");
+ goto end;
+ }
+
+ ptrdiff_t extra = 0; // lines added to text, can be negative
+ size_t old_len = (size_t)(end_row-start_row+1);
+
+ // If the size of the range is reducing (ie, new_len < old_len) we
+ // need to delete some old_len. We do this at the start, by
+ // repeatedly deleting line "start".
+ size_t to_delete = (new_len < old_len) ? (size_t)(old_len - new_len) : 0;
+ for (size_t i = 0; i < to_delete; i++) {
+ if (ml_delete((linenr_T)start_row, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to delete line");
+ goto end;
+ }
+ }
+
+ if (to_delete > 0) {
+ extra -= (ptrdiff_t)to_delete;
+ }
+
+ // For as long as possible, replace the existing old_len with the
+ // new old_len. This is a more efficient operation, as it requires
+ // less memory allocation and freeing.
+ size_t to_replace = old_len < new_len ? old_len : new_len;
+ for (size_t i = 0; i < to_replace; i++) {
+ int64_t lnum = start_row + (int64_t)i;
+
+ if (lnum >= MAXLNUM) {
+ api_set_error(err, kErrorTypeValidation, "Index value is too high");
+ goto end;
+ }
+
+ if (ml_replace((linenr_T)lnum, (char_u *)lines[i], false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to replace line");
+ goto end;
+ }
+ // Mark lines that haven't been passed to the buffer as they need
+ // to be freed later
+ lines[i] = NULL;
+ }
+
+ // Now we may need to insert the remaining new old_len
+ for (size_t i = to_replace; i < new_len; i++) {
+ int64_t lnum = start_row + (int64_t)i - 1;
+
+ if (lnum >= MAXLNUM) {
+ api_set_error(err, kErrorTypeValidation, "Index value is too high");
+ goto end;
+ }
+
+ if (ml_append((linenr_T)lnum, (char_u *)lines[i], 0, false) == FAIL) {
+ api_set_error(err, kErrorTypeException, "Failed to insert line");
+ goto end;
+ }
+
+ // Same as with replacing, but we also need to free lines
+ xfree(lines[i]);
+ lines[i] = NULL;
+ extra++;
+ }
+
+ // Adjust marks. Invalidate any which lie in the
+ // changed range, and move any in the remainder of the buffer.
+ mark_adjust((linenr_T)start_row,
+ (linenr_T)end_row,
+ MAXLNUM,
+ (long)extra,
+ kExtmarkNOOP);
+
+ colnr_T col_extent = (colnr_T)(end_col
+ - ((end_row == start_row) ? start_col : 0));
+ extmark_splice(buf, (int)start_row-1, (colnr_T)start_col,
+ (int)(end_row-start_row), col_extent, old_byte,
+ (int)new_len-1, (colnr_T)last_item.size, new_byte,
+ kExtmarkUndo);
+
+
+ changed_lines((linenr_T)start_row, 0, (linenr_T)end_row, (long)extra, true);
+
+ // adjust cursor like an extmark ( i e it was inside last_part_len)
+ if (curwin->w_cursor.lnum == end_row && curwin->w_cursor.col > end_col) {
+ curwin->w_cursor.col -= col_extent - (colnr_T)last_item.size;
+ }
+ fix_cursor((linenr_T)start_row, (linenr_T)end_row, (linenr_T)extra);
+
+end:
+ for (size_t i = 0; i < new_len; i++) {
+ xfree(lines[i]);
+ }
+ xfree(lines);
+ aucmd_restbuf(&aco);
+ try_end(err);
+}
+
/// Returns the byte offset of a line (0-indexed). |api-indexing|
///
/// Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte.
@@ -787,48 +929,6 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
dict_set_var(buf->b_vars, name, NIL, true, false, err);
}
-/// Sets a buffer-scoped (b:) variable
-///
-/// @deprecated
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param name Variable name
-/// @param value Variable value
-/// @param[out] err Error details, if any
-/// @return Old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
-Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(buf->b_vars, name, value, false, true, err);
-}
-
-/// Removes a buffer-scoped (b:) variable
-///
-/// @deprecated
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param name Variable name
-/// @param[out] err Error details, if any
-/// @return Old value
-Object buffer_del_var(Buffer buffer, String name, Error *err)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(buf->b_vars, name, NIL, true, true, err);
-}
-
/// Gets a buffer option value
///
@@ -869,28 +969,6 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer,
set_option_to(channel_id, buf, SREQ_BUF, name, value, err);
}
-/// Gets the buffer number
-///
-/// @deprecated The buffer number now is equal to the object id,
-/// so there is no need to use this function.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param[out] err Error details, if any
-/// @return Buffer number
-Integer nvim_buf_get_number(Buffer buffer, Error *err)
- FUNC_API_SINCE(1)
- FUNC_API_DEPRECATED_SINCE(2)
-{
- Integer rv = 0;
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return rv;
- }
-
- return buf->b_fnum;
-}
-
/// Gets the full file name for the buffer
///
/// @param buffer Buffer handle, or 0 for current buffer
@@ -962,6 +1040,7 @@ Boolean nvim_buf_is_loaded(Buffer buffer)
/// - unload: Unloaded only, do not delete. See |:bunload|
void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err)
FUNC_API_SINCE(7)
+ FUNC_API_CHECK_TEXTLOCK
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1017,25 +1096,6 @@ Boolean nvim_buf_is_valid(Buffer buffer)
return ret;
}
-/// Inserts a sequence of lines to a buffer at a certain index
-///
-/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines)
-///
-/// @param buffer Buffer handle
-/// @param lnum Insert the lines after `lnum`. If negative, appends to
-/// the end of the buffer.
-/// @param lines Array of lines
-/// @param[out] err Error details, if any
-void buffer_insert(Buffer buffer,
- Integer lnum,
- ArrayOf(String) lines,
- Error *err)
-{
- // "lnum" will be the index of the line after inserting,
- // no matter if it is negative or not
- nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err);
-}
-
/// Return a tuple (row,col) representing the position of the named mark.
///
/// Marks are (1,0)-indexed. |api-indexing|
@@ -1667,27 +1727,6 @@ void nvim_buf_clear_namespace(Buffer buffer,
(int)line_end-1, MAXCOL);
}
-/// Clears highlights and virtual text from namespace and range of lines
-///
-/// @deprecated use |nvim_buf_clear_namespace()|.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace to clear, or -1 to clear all.
-/// @param line_start Start of range of lines to clear
-/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
-/// to end of file.
-/// @param[out] err Error details, if any
-void nvim_buf_clear_highlight(Buffer buffer,
- Integer ns_id,
- Integer line_start,
- Integer line_end,
- Error *err)
- FUNC_API_SINCE(1)
-{
- nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
-}
-
-
/// Set the virtual text (annotation) for a buffer line.
///
/// By default (and currently the only option) the text will be placed after
@@ -1873,8 +1912,3 @@ static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob)
index++;
return index;
}
-
-static int64_t convert_index(int64_t index)
-{
- return index < 0 ? index - 1 : index;
-}
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
new file mode 100644
index 0000000000..3989386bb9
--- /dev/null
+++ b/src/nvim/api/deprecated.c
@@ -0,0 +1,367 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "nvim/api/deprecated.h"
+#include "nvim/api/buffer.h"
+#include "nvim/api/vim.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/lua/executor.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/deprecated.c.generated.h"
+#endif
+
+/// @deprecated
+/// @see nvim_exec
+String nvim_command_output(String command, Error *err)
+ FUNC_API_SINCE(1)
+ FUNC_API_DEPRECATED_SINCE(7)
+{
+ return nvim_exec(command, true, err);
+}
+
+/// @deprecated Use nvim_exec_lua() instead.
+/// @see nvim_exec_lua
+Object nvim_execute_lua(String code, Array args, Error *err)
+ FUNC_API_SINCE(3)
+ FUNC_API_DEPRECATED_SINCE(7)
+ FUNC_API_REMOTE_ONLY
+{
+ return nlua_exec(code, args, err);
+}
+
+/// Gets the buffer number
+///
+/// @deprecated The buffer number now is equal to the object id,
+/// so there is no need to use this function.
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param[out] err Error details, if any
+/// @return Buffer number
+Integer nvim_buf_get_number(Buffer buffer, Error *err)
+ FUNC_API_SINCE(1)
+ FUNC_API_DEPRECATED_SINCE(2)
+{
+ Integer rv = 0;
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return rv;
+ }
+
+ return buf->b_fnum;
+}
+
+/// Clears highlights and virtual text from namespace and range of lines
+///
+/// @deprecated use |nvim_buf_clear_namespace()|.
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param ns_id Namespace to clear, or -1 to clear all.
+/// @param line_start Start of range of lines to clear
+/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
+/// to end of file.
+/// @param[out] err Error details, if any
+void nvim_buf_clear_highlight(Buffer buffer,
+ Integer ns_id,
+ Integer line_start,
+ Integer line_end,
+ Error *err)
+ FUNC_API_SINCE(1)
+ FUNC_API_DEPRECATED_SINCE(7)
+{
+ nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
+}
+
+
+/// Inserts a sequence of lines to a buffer at a certain index
+///
+/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines)
+///
+/// @param buffer Buffer handle
+/// @param lnum Insert the lines after `lnum`. If negative, appends to
+/// the end of the buffer.
+/// @param lines Array of lines
+/// @param[out] err Error details, if any
+void buffer_insert(Buffer buffer,
+ Integer lnum,
+ ArrayOf(String) lines,
+ Error *err)
+{
+ // "lnum" will be the index of the line after inserting,
+ // no matter if it is negative or not
+ nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err);
+}
+
+/// Gets a buffer line
+///
+/// @deprecated use nvim_buf_get_lines instead.
+/// for positive indices (including 0) use
+/// "nvim_buf_get_lines(buffer, index, index+1, true)"
+/// for negative indices use
+/// "nvim_buf_get_lines(buffer, index-1, index, true)"
+///
+/// @param buffer Buffer handle
+/// @param index Line index
+/// @param[out] err Error details, if any
+/// @return Line string
+String buffer_get_line(Buffer buffer, Integer index, Error *err)
+{
+ String rv = { .size = 0 };
+
+ index = convert_index(index);
+ Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err);
+
+ if (!ERROR_SET(err) && slice.size) {
+ rv = slice.items[0].data.string;
+ }
+
+ xfree(slice.items);
+
+ return rv;
+}
+
+/// Sets a buffer line
+///
+/// @deprecated use nvim_buf_set_lines instead.
+/// for positive indices use
+/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])"
+/// for negative indices use
+/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])"
+///
+/// @param buffer Buffer handle
+/// @param index Line index
+/// @param line Contents of the new line
+/// @param[out] err Error details, if any
+void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
+{
+ Object l = STRING_OBJ(line);
+ Array array = { .items = &l, .size = 1 };
+ index = convert_index(index);
+ nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
+}
+
+/// Deletes a buffer line
+///
+/// @deprecated use nvim_buf_set_lines instead.
+/// for positive indices use
+/// "nvim_buf_set_lines(buffer, index, index+1, true, [])"
+/// for negative indices use
+/// "nvim_buf_set_lines(buffer, index-1, index, true, [])"
+/// @param buffer buffer handle
+/// @param index line index
+/// @param[out] err Error details, if any
+void buffer_del_line(Buffer buffer, Integer index, Error *err)
+{
+ Array array = ARRAY_DICT_INIT;
+ index = convert_index(index);
+ nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
+}
+
+/// Retrieves a line range from the buffer
+///
+/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false)
+/// where newstart = start + int(not include_start) - int(start < 0)
+/// newend = end + int(include_end) - int(end < 0)
+/// int(bool) = 1 if bool is true else 0
+/// @param buffer Buffer handle
+/// @param start First line index
+/// @param end Last line index
+/// @param include_start True if the slice includes the `start` parameter
+/// @param include_end True if the slice includes the `end` parameter
+/// @param[out] err Error details, if any
+/// @return Array of lines
+ArrayOf(String) buffer_get_line_slice(Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean include_start,
+ Boolean include_end,
+ Error *err)
+{
+ start = convert_index(start) + !include_start;
+ end = convert_index(end) + include_end;
+ return nvim_buf_get_lines(0, buffer, start , end, false, err);
+}
+
+/// Replaces a line range on the buffer
+///
+/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines)
+/// where newstart = start + int(not include_start) + int(start < 0)
+/// newend = end + int(include_end) + int(end < 0)
+/// int(bool) = 1 if bool is true else 0
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param start First line index
+/// @param end Last line index
+/// @param include_start True if the slice includes the `start` parameter
+/// @param include_end True if the slice includes the `end` parameter
+/// @param replacement Array of lines to use as replacement (0-length
+// array will delete the line range)
+/// @param[out] err Error details, if any
+void buffer_set_line_slice(Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean include_start,
+ Boolean include_end,
+ ArrayOf(String) replacement,
+ Error *err)
+{
+ start = convert_index(start) + !include_start;
+ end = convert_index(end) + include_end;
+ nvim_buf_set_lines(0, buffer, start, end, false, replacement, err);
+}
+
+
+/// Sets a buffer-scoped (b:) variable
+///
+/// @deprecated
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param name Variable name
+/// @param value Variable value
+/// @param[out] err Error details, if any
+/// @return Old value or nil if there was no previous value.
+///
+/// @warning It may return nil if there was no previous value
+/// or if previous value was `v:null`.
+Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return NIL;
+ }
+
+ return dict_set_var(buf->b_vars, name, value, false, true, err);
+}
+
+/// Removes a buffer-scoped (b:) variable
+///
+/// @deprecated
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param name Variable name
+/// @param[out] err Error details, if any
+/// @return Old value
+Object buffer_del_var(Buffer buffer, String name, Error *err)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return NIL;
+ }
+
+ return dict_set_var(buf->b_vars, name, NIL, true, true, err);
+}
+
+/// Sets a window-scoped (w:) variable
+///
+/// @deprecated
+///
+/// @param window Window handle, or 0 for current window
+/// @param name Variable name
+/// @param value Variable value
+/// @param[out] err Error details, if any
+/// @return Old value or nil if there was no previous value.
+///
+/// @warning It may return nil if there was no previous value
+/// or if previous value was `v:null`.
+Object window_set_var(Window window, String name, Object value, Error *err)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return NIL;
+ }
+
+ return dict_set_var(win->w_vars, name, value, false, true, err);
+}
+
+/// Removes a window-scoped (w:) variable
+///
+/// @deprecated
+///
+/// @param window Window handle, or 0 for current window
+/// @param name variable name
+/// @param[out] err Error details, if any
+/// @return Old value
+Object window_del_var(Window window, String name, Error *err)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return NIL;
+ }
+
+ return dict_set_var(win->w_vars, name, NIL, true, true, err);
+}
+
+/// Sets a tab-scoped (t:) variable
+///
+/// @deprecated
+///
+/// @param tabpage Tabpage handle, or 0 for current tabpage
+/// @param name Variable name
+/// @param value Variable value
+/// @param[out] err Error details, if any
+/// @return Old value or nil if there was no previous value.
+///
+/// @warning It may return nil if there was no previous value
+/// or if previous value was `v:null`.
+Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
+{
+ tabpage_T *tab = find_tab_by_handle(tabpage, err);
+
+ if (!tab) {
+ return NIL;
+ }
+
+ return dict_set_var(tab->tp_vars, name, value, false, true, err);
+}
+
+/// Removes a tab-scoped (t:) variable
+///
+/// @deprecated
+///
+/// @param tabpage Tabpage handle, or 0 for current tabpage
+/// @param name Variable name
+/// @param[out] err Error details, if any
+/// @return Old value
+Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
+{
+ tabpage_T *tab = find_tab_by_handle(tabpage, err);
+
+ if (!tab) {
+ return NIL;
+ }
+
+ return dict_set_var(tab->tp_vars, name, NIL, true, true, err);
+}
+
+/// @deprecated
+/// @see nvim_set_var
+/// @warning May return nil if there was no previous value
+/// OR if previous value was `v:null`.
+/// @return Old value or nil if there was no previous value.
+Object vim_set_var(String name, Object value, Error *err)
+{
+ return dict_set_var(&globvardict, name, value, false, true, err);
+}
+
+/// @deprecated
+/// @see nvim_del_var
+Object vim_del_var(String name, Error *err)
+{
+ return dict_set_var(&globvardict, name, NIL, true, true, err);
+}
+
+static int64_t convert_index(int64_t index)
+{
+ return index < 0 ? index - 1 : index;
+}
diff --git a/src/nvim/api/deprecated.h b/src/nvim/api/deprecated.h
new file mode 100644
index 0000000000..79095167e1
--- /dev/null
+++ b/src/nvim/api/deprecated.h
@@ -0,0 +1,11 @@
+#ifndef NVIM_API_DEPRECATED_H
+#define NVIM_API_DEPRECATED_H
+
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/deprecated.h.generated.h"
+#endif
+#endif // NVIM_API_DEPRECATED_H
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index 2975df3c68..eae4581f42 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -19,6 +19,7 @@
#include "nvim/api/ui.h"
#include "nvim/api/vim.h"
#include "nvim/api/window.h"
+#include "nvim/api/deprecated.h"
static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 2c99d3426c..8f224e8c78 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -820,6 +820,10 @@ void modify_keymap(Buffer buffer, bool is_unmap, String mode, String lhs,
}
buf_T *target_buf = find_buffer_by_handle(buffer, err);
+ if (!target_buf) {
+ return;
+ }
+
MapArguments parsed_args;
memset(&parsed_args, 0, sizeof(parsed_args));
if (parse_keymap_opts(opts, &parsed_args, err)) {
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 271fd5b485..055abb797f 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -16,6 +16,7 @@
#define BOOLEAN_OBJ(b) ((Object) { \
.type = kObjectTypeBoolean, \
.data.boolean = b })
+#define BOOL(b) BOOLEAN_OBJ(b)
#define INTEGER_OBJ(i) ((Object) { \
.type = kObjectTypeInteger, \
@@ -29,6 +30,8 @@
.type = kObjectTypeString, \
.data.string = s })
+#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
+
#define BUFFER_OBJ(s) ((Object) { \
.type = kObjectTypeBuffer, \
.data.integer = s })
@@ -59,6 +62,8 @@
#define PUT(dict, k, v) \
kv_push(dict, ((KeyValuePair) { .key = cstr_to_string(k), .value = v }))
+#define PUT_BOOL(dict, name, condition) PUT(dict, name, BOOLEAN_OBJ(condition));
+
#define ADD(array, item) \
kv_push(array, item)
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index dd17bc03e5..5f727dbc38 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -97,48 +97,6 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
dict_set_var(tab->tp_vars, name, NIL, true, false, err);
}
-/// Sets a tab-scoped (t:) variable
-///
-/// @deprecated
-///
-/// @param tabpage Tabpage handle, or 0 for current tabpage
-/// @param name Variable name
-/// @param value Variable value
-/// @param[out] err Error details, if any
-/// @return Old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
-Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
-{
- tabpage_T *tab = find_tab_by_handle(tabpage, err);
-
- if (!tab) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(tab->tp_vars, name, value, false, true, err);
-}
-
-/// Removes a tab-scoped (t:) variable
-///
-/// @deprecated
-///
-/// @param tabpage Tabpage handle, or 0 for current tabpage
-/// @param name Variable name
-/// @param[out] err Error details, if any
-/// @return Old value
-Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
-{
- tabpage_T *tab = find_tab_by_handle(tabpage, err);
-
- if (!tab) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(tab->tp_vars, name, NIL, true, true, err);
-}
-
/// Gets the current window in a tabpage
///
/// @param tabpage Tabpage handle, or 0 for current tabpage
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 77002697fe..1e972e01be 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -15,6 +15,7 @@
#include "nvim/api/private/dispatch.h"
#include "nvim/api/buffer.h"
#include "nvim/api/window.h"
+#include "nvim/api/deprecated.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
@@ -479,15 +480,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
return cstr_as_string(ptr);
}
-/// @deprecated
-/// @see nvim_exec
-String nvim_command_output(String command, Error *err)
- FUNC_API_SINCE(1)
- FUNC_API_DEPRECATED_SINCE(7)
-{
- return nvim_exec(command, true, err);
-}
-
/// Evaluates a VimL |expression|.
/// Dictionaries and Lists are recursively expanded.
///
@@ -534,16 +526,6 @@ Object nvim_eval(String expr, Error *err)
return rv;
}
-/// @deprecated Use nvim_exec_lua() instead.
-/// @see nvim_exec_lua
-Object nvim_execute_lua(String code, Array args, Error *err)
- FUNC_API_SINCE(3)
- FUNC_API_DEPRECATED_SINCE(7)
- FUNC_API_REMOTE_ONLY
-{
- return nlua_exec(code, args, err);
-}
-
/// Execute Lua code. Parameters (if any) are available as `...` inside the
/// chunk. The chunk can return a value.
///
@@ -875,6 +857,7 @@ String nvim_get_current_line(Error *err)
/// @param[out] err Error details, if any
void nvim_set_current_line(String line, Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err);
}
@@ -884,6 +867,7 @@ void nvim_set_current_line(String line, Error *err)
/// @param[out] err Error details, if any
void nvim_del_current_line(Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
}
@@ -920,23 +904,6 @@ void nvim_del_var(String name, Error *err)
dict_set_var(&globvardict, name, NIL, true, false, err);
}
-/// @deprecated
-/// @see nvim_set_var
-/// @warning May return nil if there was no previous value
-/// OR if previous value was `v:null`.
-/// @return Old value or nil if there was no previous value.
-Object vim_set_var(String name, Object value, Error *err)
-{
- return dict_set_var(&globvardict, name, value, false, true, err);
-}
-
-/// @deprecated
-/// @see nvim_del_var
-Object vim_del_var(String name, Error *err)
-{
- return dict_set_var(&globvardict, name, NIL, true, true, err);
-}
-
/// Gets a v: variable.
///
/// @param name Variable name
@@ -970,6 +937,47 @@ Object nvim_get_option(String name, Error *err)
return get_option_from(NULL, SREQ_GLOBAL, name, err);
}
+/// Gets the option information for all options.
+///
+/// The dictionary has the full option names as keys and option metadata
+/// dictionaries as detailed at |nvim_get_option_info|.
+///
+/// @return dictionary of all options
+Dictionary nvim_get_all_options_info(Error *err)
+ FUNC_API_SINCE(7)
+{
+ return get_all_vimoptions();
+}
+
+/// Gets the option information for one option
+///
+/// Resulting dictionary has keys:
+/// - name: Name of the option (like 'filetype')
+/// - shortname: Shortened name of the option (like 'ft')
+/// - type: type of option ("string", "integer" or "boolean")
+/// - default: The default value for the option
+/// - was_set: Whether the option was set.
+///
+/// - last_set_sid: Last set script id (if any)
+/// - last_set_linenr: line number where option was set
+/// - last_set_chan: Channel where option was set (0 for local)
+///
+/// - scope: one of "global", "win", or "buf"
+/// - global_local: whether win or buf option has a global value
+///
+/// - commalist: List of comma separated values
+/// - flaglist: List of single char flags
+///
+///
+/// @param name Option name
+/// @param[out] err Error details, if any
+/// @return Option Information
+Dictionary nvim_get_option_info(String name, Error *err)
+ FUNC_API_SINCE(7)
+{
+ return get_vimoption(name, err);
+}
+
/// Sets an option value.
///
/// @param channel_id
@@ -1054,6 +1062,7 @@ Buffer nvim_get_current_buf(void)
/// @param[out] err Error details, if any
void nvim_set_current_buf(Buffer buffer, Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -1108,6 +1117,7 @@ Window nvim_get_current_win(void)
/// @param[out] err Error details, if any
void nvim_set_current_win(Window window, Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
win_T *win = find_window_by_handle(window, err);
@@ -1257,6 +1267,7 @@ fail:
Window nvim_open_win(Buffer buffer, Boolean enter, Dictionary config,
Error *err)
FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
{
FloatConfig fconfig = FLOAT_CONFIG_INIT;
if (!parse_float_config(config, &fconfig, false, err)) {
@@ -1321,6 +1332,7 @@ Tabpage nvim_get_current_tabpage(void)
/// @param[out] err Error details, if any
void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
FUNC_API_SINCE(1)
+ FUNC_API_CHECK_TEXTLOCK
{
tabpage_T *tp = find_tab_by_handle(tabpage, err);
@@ -1405,6 +1417,7 @@ Dictionary nvim_get_namespaces(void)
/// - false: Client must cancel the paste.
Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
{
static bool draining = false;
bool cancel = false;
@@ -1477,6 +1490,7 @@ theend:
void nvim_put(ArrayOf(String) lines, String type, Boolean after,
Boolean follow, Error *err)
FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
{
yankreg_T *reg = xcalloc(sizeof(yankreg_T), 1);
if (!prepare_yankreg_from_object(reg, type, lines.size)) {
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index f09a03f592..f4af1632ec 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -44,6 +44,7 @@ Buffer nvim_win_get_buf(Window window, Error *err)
/// @param[out] err Error details, if any
void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
FUNC_API_SINCE(5)
+ FUNC_API_CHECK_TEXTLOCK
{
win_T *win = find_window_by_handle(window, err), *save_curwin = curwin;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -288,48 +289,6 @@ void nvim_win_del_var(Window window, String name, Error *err)
dict_set_var(win->w_vars, name, NIL, true, false, err);
}
-/// Sets a window-scoped (w:) variable
-///
-/// @deprecated
-///
-/// @param window Window handle, or 0 for current window
-/// @param name Variable name
-/// @param value Variable value
-/// @param[out] err Error details, if any
-/// @return Old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
-Object window_set_var(Window window, String name, Object value, Error *err)
-{
- win_T *win = find_window_by_handle(window, err);
-
- if (!win) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(win->w_vars, name, value, false, true, err);
-}
-
-/// Removes a window-scoped (w:) variable
-///
-/// @deprecated
-///
-/// @param window Window handle, or 0 for current window
-/// @param name variable name
-/// @param[out] err Error details, if any
-/// @return Old value
-Object window_del_var(Window window, String name, Error *err)
-{
- win_T *win = find_window_by_handle(window, err);
-
- if (!win) {
- return (Object) OBJECT_INIT;
- }
-
- return dict_set_var(win->w_vars, name, NIL, true, true, err);
-}
-
/// Gets a window option value
///
/// @param window Window handle, or 0 for current window
@@ -542,6 +501,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
/// @param[out] err Error details, if any
void nvim_win_close(Window window, Boolean force, Error *err)
FUNC_API_SINCE(6)
+ FUNC_API_CHECK_TEXTLOCK
{
win_T *win = find_window_by_handle(window, err);
if (!win) {
diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c
index 7f12c0c798..9fba38a49f 100644
--- a/src/nvim/arabic.c
+++ b/src/nvim/arabic.c
@@ -719,9 +719,7 @@ int arabic_shape(int c, int *ccp, int *c1p, int prev_c, int prev_c1,
// half-shape current and previous character
int shape_c = half_shape(prev_c);
- // Save away current character
- int curr_c = c;
-
+ int curr_c;
int curr_laa = A_firstc_laa(c, *c1p);
int prev_laa = A_firstc_laa(prev_c, prev_c1);
diff --git a/src/nvim/ascii.h b/src/nvim/ascii.h
index 2397af27cc..f41068ea70 100644
--- a/src/nvim/ascii.h
+++ b/src/nvim/ascii.h
@@ -89,6 +89,10 @@ static inline bool ascii_iswhite(int)
REAL_FATTR_CONST
REAL_FATTR_ALWAYS_INLINE;
+static inline bool ascii_iswhite_or_nul(int)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
+
static inline bool ascii_isdigit(int)
REAL_FATTR_CONST
REAL_FATTR_ALWAYS_INLINE;
@@ -117,6 +121,14 @@ static inline bool ascii_iswhite(int c)
return c == ' ' || c == '\t';
}
+/// Checks if `c` is a space or tab character or NUL.
+///
+/// @see {ascii_isdigit}
+static inline bool ascii_iswhite_or_nul(int c)
+{
+ return ascii_iswhite(c) || c == NUL;
+}
+
/// Check whether character is a decimal digit.
///
/// Library isdigit() function is officially locale-dependent and, for
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 53b11c250e..42224d0a4f 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1106,9 +1106,9 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
win = curwin;
}
- aco->save_curwin = curwin;
- aco->save_prevwin = prevwin;
+ aco->save_curwin_handle = curwin->handle;
aco->save_curbuf = curbuf;
+ aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle;
if (win != NULL) {
// There is a window for "buf" in the current tab page, make it the
// curwin. This is preferred, it has the least side effects (esp. if
@@ -1148,7 +1148,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
curwin = aucmd_win;
}
curbuf = buf;
- aco->new_curwin = curwin;
+ aco->new_curwin_handle = curwin->handle;
set_bufref(&aco->new_curbuf, curbuf);
}
@@ -1194,14 +1194,14 @@ void aucmd_restbuf(aco_save_T *aco)
unblock_autocmds();
- if (win_valid(aco->save_curwin)) {
- curwin = aco->save_curwin;
+ win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle);
+ if (save_curwin != NULL) {
+ curwin = save_curwin;
} else {
// Hmm, original window disappeared. Just use the first one.
curwin = firstwin;
}
- prevwin = win_valid(aco->save_prevwin) ? aco->save_prevwin
- : firstwin; // window disappeared?
+ prevwin = win_find_by_handle(aco->save_prevwin_handle);
vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
curbuf = curwin->w_buffer;
@@ -1216,11 +1216,14 @@ void aucmd_restbuf(aco_save_T *aco)
curwin->w_topfill = 0;
}
} else {
- // restore curwin
- if (win_valid(aco->save_curwin)) {
+ // Restore curwin. Use the window ID, a window may have been closed
+ // and the memory re-used for another one.
+ win_T *const save_curwin = win_find_by_handle(aco->save_curwin_handle);
+ if (save_curwin != NULL) {
// Restore the buffer which was previously edited by curwin, if it was
// changed, we are still the same window and the buffer is valid.
- if (curwin == aco->new_curwin && curbuf != aco->new_curbuf.br_buf
+ if (curwin->handle == aco->new_curwin_handle
+ && curbuf != aco->new_curbuf.br_buf
&& bufref_valid(&aco->new_curbuf)
&& aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) {
if (curwin->w_s == &curbuf->b_s) {
@@ -1232,10 +1235,9 @@ void aucmd_restbuf(aco_save_T *aco)
curbuf->b_nwindows++;
}
- curwin = aco->save_curwin;
- prevwin = win_valid(aco->save_prevwin) ? aco->save_prevwin
- : firstwin; // window disappeared?
+ curwin = save_curwin;
curbuf = curwin->w_buffer;
+ prevwin = win_find_by_handle(aco->save_prevwin_handle);
// In case the autocommand moves the cursor to a position that does not
// exist in curbuf
check_cursor();
@@ -1717,7 +1719,8 @@ void unblock_autocmds(void)
}
}
-static inline bool is_autocmd_blocked(void)
+bool is_autocmd_blocked(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return autocmd_blocked != 0;
}
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index af1eeb0fc4..1c0f88f08f 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -7,13 +7,13 @@
// Struct to save values in before executing autocommands for a buffer that is
// not the current buffer.
typedef struct {
- buf_T *save_curbuf; ///< saved curbuf
- int use_aucmd_win; ///< using aucmd_win
- win_T *save_curwin; ///< saved curwin
- win_T *save_prevwin; ///< saved prevwin
- win_T *new_curwin; ///< new curwin
- bufref_T new_curbuf; ///< new curbuf
- char_u *globaldir; ///< saved value of globaldir
+ buf_T *save_curbuf; ///< saved curbuf
+ bool use_aucmd_win; ///< using aucmd_win
+ handle_T save_curwin_handle; ///< ID of saved curwin
+ handle_T new_curwin_handle; ///< ID of new curwin
+ handle_T save_prevwin_handle; ///< ID of saved prevwin
+ bufref_T new_curbuf; ///< new curbuf
+ char_u *globaldir; ///< saved value of globaldir
} aco_save_T;
typedef struct AutoCmd {
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 839d61cd2e..0134ee838d 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -602,8 +602,12 @@ void close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
* Remove the buffer from the list.
*/
if (wipe_buf) {
- xfree(buf->b_ffname);
- xfree(buf->b_sfname);
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
+ XFREE_CLEAR(buf->b_ffname);
if (buf->b_prev == NULL) {
firstbuf = buf->b_next;
} else {
@@ -1583,7 +1587,7 @@ void enter_buffer(buf_T *buf)
need_fileinfo = true; // display file info after redraw
}
// check if file changed
- (void)buf_check_timestamp(curbuf, false);
+ (void)buf_check_timestamp(curbuf);
curwin->w_topline = 1;
curwin->w_topfill = 0;
@@ -1693,15 +1697,18 @@ static inline void buf_init_changedtick(buf_T *const buf)
/// if the buffer already exists.
/// This is the ONLY way to create a new buffer.
///
-/// @param ffname full path of fname or relative
-/// @param sfname short fname or NULL
+/// @param ffname_arg full path of fname or relative
+/// @param sfname_arg short fname or NULL
/// @param lnum preferred cursor line
/// @param flags BLN_ defines
/// @param bufnr
///
/// @return pointer to the buffer
-buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
+buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum,
+ int flags)
{
+ char_u *ffname = ffname_arg;
+ char_u *sfname = sfname_arg;
buf_T *buf;
fname_expand(curbuf, &ffname, &sfname); // will allocate ffname
@@ -1787,8 +1794,12 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
buf->b_wininfo = xcalloc(1, sizeof(wininfo_T));
if (ffname != NULL && (buf->b_ffname == NULL || buf->b_sfname == NULL)) {
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
XFREE_CLEAR(buf->b_ffname);
- XFREE_CLEAR(buf->b_sfname);
if (buf != curbuf) {
free_buffer(buf);
}
@@ -2148,10 +2159,11 @@ static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id,
int buflist_findpat(
const char_u *pattern,
const char_u *pattern_end, // pointer to first char after pattern
- int unlisted, // find unlisted buffers
- int diffmode, // find diff-mode buffers only
- int curtab_only // find buffers in current tab only
+ bool unlisted, // find unlisted buffers
+ bool diffmode, // find diff-mode buffers only
+ bool curtab_only // find buffers in current tab only
)
+ FUNC_ATTR_NONNULL_ARG(1)
{
int match = -1;
int find_listed;
@@ -2778,28 +2790,32 @@ int buflist_name_nr(int fnum, char_u **fname, linenr_T *lnum)
return OK;
}
-/*
- * Set the file name for "buf"' to 'ffname', short file name to 'sfname'.
- * The file name with the full path is also remembered, for when :cd is used.
- * Returns FAIL for failure (file name already in use by other buffer)
- * OK otherwise.
- */
-int
-setfname(
+// Set the file name for "buf" to "ffname_arg", short file name to
+// "sfname_arg".
+// The file name with the full path is also remembered, for when :cd is used.
+// Returns FAIL for failure (file name already in use by other buffer)
+// OK otherwise.
+int setfname(
buf_T *buf,
- char_u *ffname,
- char_u *sfname,
+ char_u *ffname_arg,
+ char_u *sfname_arg,
bool message // give message when buffer already exists
)
{
+ char_u *ffname = ffname_arg;
+ char_u *sfname = sfname_arg;
buf_T *obuf = NULL;
FileID file_id;
bool file_id_valid = false;
if (ffname == NULL || *ffname == NUL) {
// Removing the name.
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ } else {
+ buf->b_sfname = NULL;
+ }
XFREE_CLEAR(buf->b_ffname);
- XFREE_CLEAR(buf->b_sfname);
} else {
fname_expand(buf, &ffname, &sfname); // will allocate ffname
if (ffname == NULL) { // out of memory
@@ -2830,8 +2846,10 @@ setfname(
#ifdef USE_FNAME_CASE
path_fix_case(sfname); // set correct case for short file name
#endif
+ if (buf->b_sfname != buf->b_ffname) {
+ xfree(buf->b_sfname);
+ }
xfree(buf->b_ffname);
- xfree(buf->b_sfname);
buf->b_ffname = ffname;
buf->b_sfname = sfname;
}
@@ -2857,7 +2875,9 @@ void buf_set_name(int fnum, char_u *name)
buf = buflist_findnr(fnum);
if (buf != NULL) {
- xfree(buf->b_sfname);
+ if (buf->b_sfname != buf->b_ffname) {
+ xfree(buf->b_sfname);
+ }
xfree(buf->b_ffname);
buf->b_ffname = vim_strsave(name);
buf->b_sfname = NULL;
@@ -4633,16 +4653,18 @@ static bool append_arg_number(win_T *wp, char_u *buf, int buflen, bool add_file)
return true;
}
-/*
- * Make "ffname" a full file name, set "sfname" to "ffname" if not NULL.
- * "ffname" becomes a pointer to allocated memory (or NULL).
- */
+// Make "*ffname" a full file name, set "*sfname" to "*ffname" if not NULL.
+// "*ffname" becomes a pointer to allocated memory (or NULL).
+// When resolving a link both "*sfname" and "*ffname" will point to the same
+// allocated memory.
+// The "*ffname" and "*sfname" pointer values on call will not be freed.
+// Note that the resulting "*ffname" pointer should be considered not allocaed.
void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname)
{
- if (*ffname == NULL) { // if no file name given, nothing to do
+ if (*ffname == NULL) { // no file name given, nothing to do
return;
}
- if (*sfname == NULL) { // if no short file name given, use ffname
+ if (*sfname == NULL) { // no short file name given, use ffname
*sfname = *ffname;
}
*ffname = (char_u *)fix_fname((char *)(*ffname)); // expand to full path
@@ -4685,7 +4707,6 @@ do_arg_all(
int keep_tabs // keep current tabs, for ":tab drop file"
)
{
- int i;
char_u *opened; // Array of weight for which args are open:
// 0: not opened
// 1: opened in other tab
@@ -4694,6 +4715,7 @@ do_arg_all(
int opened_len; // length of opened[]
int use_firstwin = false; // use first window for arglist
+ bool tab_drop_empty_window = false;
int split_ret = OK;
bool p_ea_save;
alist_T *alist; // argument list to be used
@@ -4741,6 +4763,7 @@ do_arg_all(
win_T *wpnext = NULL;
tpnext = curtab->tp_next;
for (win_T *wp = firstwin; wp != NULL; wp = wpnext) {
+ int i;
wpnext = wp->w_next;
buf = wp->w_buffer;
if (buf->b_ffname == NULL
@@ -4846,14 +4869,15 @@ do_arg_all(
last_curwin = curwin;
last_curtab = curtab;
win_enter(lastwin, false);
- // ":drop all" should re-use an empty window to avoid "--remote-tab"
+ // ":tab drop file" should re-use an empty window to avoid "--remote-tab"
// leaving an empty tab page when executed locally.
if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
&& curbuf->b_ffname == NULL && !curbuf->b_changed) {
use_firstwin = true;
+ tab_drop_empty_window = true;
}
- for (i = 0; i < count && i < opened_len && !got_int; i++) {
+ for (int i = 0; i < count && !got_int; i++) {
if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) {
arg_had_last = true;
}
@@ -4873,6 +4897,10 @@ do_arg_all(
}
}
} else if (split_ret == OK) {
+ // trigger events for tab drop
+ if (tab_drop_empty_window && i == count - 1) {
+ autocmd_no_enter--;
+ }
if (!use_firstwin) { // split current window
p_ea_save = p_ea;
p_ea = true; // use space from all windows
@@ -4898,6 +4926,9 @@ do_arg_all(
|| bufIsChanged(curwin->w_buffer))
? ECMD_HIDE : 0) + ECMD_OLDBUF,
curwin);
+ if (tab_drop_empty_window && i == count - 1) {
+ autocmd_no_enter++;
+ }
if (use_firstwin) {
autocmd_no_leave++;
}
@@ -5449,7 +5480,9 @@ int buf_signcols(buf_T *buf)
curline = sign->lnum;
linesum = 0;
}
- linesum++;
+ if (sign->has_text_or_icon) {
+ linesum++;
+ }
}
if (linesum > buf->b_signcols_max) {
buf->b_signcols_max = linesum;
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index dba02a67e8..cc09b7e989 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -491,9 +491,10 @@ typedef struct {
LuaRef on_changedtick;
LuaRef on_detach;
bool utf_sizes;
+ bool preview;
} BufUpdateCallbacks;
#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF, \
- LUA_NOREF, false }
+ LUA_NOREF, false, false }
EXTERN int curbuf_splice_pending INIT(= 0);
@@ -532,9 +533,11 @@ struct file_buffer {
// b_fname is the same as b_sfname, unless ":cd" has been done,
// then it is the same as b_ffname (NULL for no name).
//
- char_u *b_ffname; // full path file name
- char_u *b_sfname; // short file name
- char_u *b_fname; // current file name
+ char_u *b_ffname; // full path file name, allocated
+ char_u *b_sfname; // short file name, allocated, may be equal to
+ // b_ffname
+ char_u *b_fname; // current file name, points to b_ffname or
+ // b_sfname
bool file_id_valid;
FileID file_id;
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c
index fc671ad9e2..68e123896b 100644
--- a/src/nvim/buffer_updates.c
+++ b/src/nvim/buffer_updates.c
@@ -237,7 +237,7 @@ void buf_updates_send_changes(buf_T *buf,
for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) {
BufUpdateCallbacks cb = kv_A(buf->update_callbacks, i);
bool keep = true;
- if (cb.on_lines != LUA_NOREF) {
+ if (cb.on_lines != LUA_NOREF && (cb.preview || !(State & CMDPREVIEW))) {
Array args = ARRAY_DICT_INIT;
Object items[8];
args.size = 6; // may be increased to 8 below
@@ -298,7 +298,7 @@ void buf_updates_send_splice(
for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) {
BufUpdateCallbacks cb = kv_A(buf->update_callbacks, i);
bool keep = true;
- if (cb.on_bytes != LUA_NOREF) {
+ if (cb.on_bytes != LUA_NOREF && (cb.preview || !(State & CMDPREVIEW))) {
FIXED_TEMP_ARRAY(args, 11);
// the first argument is always the buffer handle
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index fb158f377a..3e52b3e3ce 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -45,8 +45,6 @@ static bool chartab_initialized = false;
(buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
#define GET_CHARTAB_TAB(chartab, c) \
((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
-#define GET_CHARTAB(buf, c) \
- GET_CHARTAB_TAB((buf)->b_chartab, c)
// Table used below, see init_chartab() for an explanation
static char_u g_chartab[256];
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 1cdf84f9d0..93bc34fa4b 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -805,7 +805,7 @@ static void diff_try_update(diffio_T *dio,
for (idx_new = idx_orig; idx_new < DB_COUNT; idx_new++) {
buf = curtab->tp_diffbuf[idx_new];
if (buf_valid(buf)) {
- buf_check_timestamp(buf, false);
+ buf_check_timestamp(buf);
}
}
}
@@ -1225,8 +1225,7 @@ void ex_diffpatch(exarg_T *eap)
EMSG(_("E816: Cannot read patch output"));
} else {
if (curbuf->b_fname != NULL) {
- newname = vim_strnsave(curbuf->b_fname,
- (int)(STRLEN(curbuf->b_fname) + 4));
+ newname = vim_strnsave(curbuf->b_fname, STRLEN(curbuf->b_fname) + 4);
STRCAT(newname, ".new");
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 5d44c3274e..b2abb06075 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -196,8 +196,8 @@ static int ctrl_x_mode = CTRL_X_NORMAL;
static int compl_matches = 0;
static char_u *compl_pattern = NULL;
-static int compl_direction = FORWARD;
-static int compl_shows_dir = FORWARD;
+static Direction compl_direction = FORWARD;
+static Direction compl_shows_dir = FORWARD;
static int compl_pending = 0; // > 1 for postponed CTRL-N
static pos_T compl_startpos;
static colnr_T compl_col = 0; /* column where the text starts
@@ -381,7 +381,7 @@ static void insert_enter(InsertState *s)
// Need to recompute the cursor position, it might move when the cursor is
// on a TAB or special character.
- curs_columns(true);
+ curs_columns(curwin, true);
// Enable langmap or IME, indicated by 'iminsert'.
// Note that IME may enabled/disabled without us noticing here, thus the
@@ -594,7 +594,7 @@ static int insert_check(VimState *state)
if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
&& curwin->w_wrow == curwin->w_winrow
- + curwin->w_height_inner - 1 - get_scrolloff_value()
+ + curwin->w_height_inner - 1 - get_scrolloff_value(curwin)
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {
@@ -608,7 +608,7 @@ static int insert_check(VimState *state)
}
// May need to adjust w_topline to show the cursor.
- update_topline();
+ update_topline(curwin);
s->did_backspace = false;
@@ -1561,7 +1561,7 @@ void edit_putchar(int c, bool highlight)
int attr;
if (curwin->w_grid.chars != NULL || default_grid.chars != NULL) {
- update_topline(); // just in case w_topline isn't valid
+ update_topline(curwin); // just in case w_topline isn't valid
validate_cursor();
if (highlight) {
attr = HL_ATTR(HLF_8);
@@ -1677,7 +1677,7 @@ void display_dollar(colnr_T col)
// If on the last byte of a multi-byte move to the first byte.
char_u *p = get_cursor_line_ptr();
curwin->w_cursor.col -= utf_head_off(p, p + col);
- curs_columns(false); // Recompute w_wrow and w_wcol
+ curs_columns(curwin, false); // Recompute w_wrow and w_wcol
if (curwin->w_wcol < curwin->w_grid.Columns) {
edit_putchar('$', false);
dollar_vcol = curwin->w_virtcol;
@@ -2156,7 +2156,7 @@ static bool ins_compl_accept_char(int c)
///
/// @param[in] cont_s_ipos next ^X<> will set initial_pos
int ins_compl_add_infercase(char_u *str_arg, int len, bool icase, char_u *fname,
- int dir, bool cont_s_ipos)
+ Direction dir, bool cont_s_ipos)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u *str = str_arg;
@@ -2308,7 +2308,7 @@ static int ins_compl_add(char_u *const str, int len,
FUNC_ATTR_NONNULL_ARG(1)
{
compl_T *match;
- int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
+ const Direction dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
int flags = flags_arg;
os_breakcheck();
@@ -2511,7 +2511,7 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
FUNC_ATTR_NONNULL_ALL
{
int add_r = OK;
- int dir = compl_direction;
+ Direction dir = compl_direction;
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
@@ -2864,7 +2864,7 @@ ins_compl_dictionaries (
char_u **files;
int count;
int save_p_scs;
- int dir = compl_direction;
+ Direction dir = compl_direction;
if (*dict == NUL) {
/* When 'dictionary' is empty and spell checking is enabled use
@@ -2945,7 +2945,10 @@ theend:
xfree(buf);
}
-static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir)
+static void ins_compl_files(int count, char_u **files, int thesaurus,
+ int flags, regmatch_T *regmatch, char_u *buf,
+ Direction *dir)
+ FUNC_ATTR_NONNULL_ARG(2, 7)
{
char_u *ptr;
int i;
@@ -2955,6 +2958,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags,
for (i = 0; i < count && !got_int && !compl_interrupted; i++) {
fp = os_fopen((char *)files[i], "r"); // open dictionary file
if (flags != DICT_EXACT) {
+ msg_hist_off = true; // reset in msg_trunc_attr()
vim_snprintf((char *)IObuff, IOSIZE,
_("Scanning dictionary: %s"), (char *)files[i]);
(void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R));
@@ -3137,6 +3141,56 @@ bool ins_compl_active(void)
return compl_started;
}
+static void ins_compl_update_sequence_numbers(void)
+{
+ int number = 0;
+ compl_T *match;
+
+ if (compl_direction == FORWARD) {
+ // search backwards for the first valid (!= -1) number.
+ // This should normally succeed already at the first loop
+ // cycle, so it's fast!
+ for (match = compl_curr_match->cp_prev;
+ match != NULL && match != compl_first_match;
+ match = match->cp_prev) {
+ if (match->cp_number != -1) {
+ number = match->cp_number;
+ break;
+ }
+ }
+ if (match != NULL) {
+ // go up and assign all numbers which are not assigned yet
+ for (match = match->cp_next;
+ match != NULL && match->cp_number == -1;
+ match = match->cp_next) {
+ match->cp_number = ++number;
+ }
+ }
+ } else { // BACKWARD
+ assert(compl_direction == BACKWARD);
+ // search forwards (upwards) for the first valid (!= -1)
+ // number. This should normally succeed already at the
+ // first loop cycle, so it's fast!
+ for (match = compl_curr_match->cp_next;
+ match != NULL && match != compl_first_match;
+ match = match->cp_next) {
+ if (match->cp_number != -1) {
+ number = match->cp_number;
+ break;
+ }
+ }
+ if (match != NULL) {
+ // go down and assign all numbers which are not
+ // assigned yet
+ for (match = match->cp_prev;
+ match && match->cp_number == -1;
+ match = match->cp_prev) {
+ match->cp_number = ++number;
+ }
+ }
+ }
+}
+
// Get complete information
void get_complete_info(list_T *what_list, dict_T *retdict)
{
@@ -3214,6 +3268,9 @@ void get_complete_info(list_T *what_list, dict_T *retdict)
}
if (ret == OK && (what_flag & CI_WHAT_SELECTED)) {
+ if (compl_curr_match != NULL && compl_curr_match->cp_number == -1) {
+ ins_compl_update_sequence_numbers();
+ }
ret = tv_dict_add_nr(retdict, S_LEN("selected"),
(compl_curr_match != NULL)
? compl_curr_match->cp_number - 1 : -1);
@@ -3366,7 +3423,7 @@ static void ins_compl_addleader(int c)
xfree(compl_leader);
compl_leader = vim_strnsave(get_cursor_line_ptr() + compl_col,
- (int)(curwin->w_cursor.col - compl_col));
+ curwin->w_cursor.col - compl_col);
ins_compl_new_leader();
}
@@ -3659,7 +3716,7 @@ static bool ins_compl_prep(int c)
retval = true;
}
- auto_format(FALSE, TRUE);
+ auto_format(false, true);
// Trigger the CompleteDonePre event to give scripts a chance to
// act upon the completion before clearing the info, and restore
@@ -3753,10 +3810,10 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
*/
static buf_T *ins_compl_next_buf(buf_T *buf, int flag)
{
- static win_T *wp;
+ static win_T *wp = NULL;
if (flag == 'w') { // just windows
- if (buf == curbuf) { // first call for this flag/expansion
+ if (buf == curbuf || wp == NULL) { // first call for this flag/expansion
wp = curwin;
}
assert(wp);
@@ -3865,7 +3922,7 @@ theend:
*/
static void ins_compl_add_list(list_T *const list)
{
- int dir = compl_direction;
+ Direction dir = compl_direction;
// Go through the List with matches and add each of them.
TV_LIST_ITER(list, li, {
@@ -4057,6 +4114,7 @@ static int ins_compl_get_exp(pos_T *ini)
dict = ins_buf->b_fname;
dict_f = DICT_EXACT;
}
+ msg_hist_off = true; // reset in msg_trunc_attr()
vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
ins_buf->b_fname == NULL
? buf_spname(ins_buf)
@@ -4078,11 +4136,12 @@ static int ins_compl_get_exp(pos_T *ini)
dict = e_cpt;
dict_f = DICT_FIRST;
}
- } else if (*e_cpt == 'i')
+ } else if (*e_cpt == 'i') {
type = CTRL_X_PATH_PATTERNS;
- else if (*e_cpt == 'd')
+ } else if (*e_cpt == 'd') {
type = CTRL_X_PATH_DEFINES;
- else if (*e_cpt == ']' || *e_cpt == 't') {
+ } else if (*e_cpt == ']' || *e_cpt == 't') {
+ msg_hist_off = true; // reset in msg_trunc_attr()
type = CTRL_X_TAGS;
vim_snprintf((char *)IObuff, IOSIZE, "%s", _("Scanning tags."));
(void)msg_trunc_attr(IObuff, true, HL_ATTR(HLF_R));
@@ -4665,9 +4724,11 @@ ins_compl_next (
MB_PTR_ADV(s);
}
}
+ msg_hist_off = true;
vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
s > compl_shown_match->cp_fname ? "<" : "", s);
msg(IObuff);
+ msg_hist_off = false;
redraw_cmdline = false; // don't overwrite!
}
}
@@ -5242,52 +5303,11 @@ static int ins_complete(int c, bool enable_pum)
} else if (compl_curr_match->cp_next == compl_curr_match->cp_prev) {
edit_submode_extra = (char_u *)_("The only match");
edit_submode_highl = HLF_COUNT;
+ compl_curr_match->cp_number = 1;
} else {
// Update completion sequence number when needed.
if (compl_curr_match->cp_number == -1) {
- int number = 0;
- compl_T *match;
-
- if (compl_direction == FORWARD) {
- /* search backwards for the first valid (!= -1) number.
- * This should normally succeed already at the first loop
- * cycle, so it's fast! */
- for (match = compl_curr_match->cp_prev; match != NULL
- && match != compl_first_match;
- match = match->cp_prev)
- if (match->cp_number != -1) {
- number = match->cp_number;
- break;
- }
- if (match != NULL)
- /* go up and assign all numbers which are not assigned
- * yet */
- for (match = match->cp_next;
- match != NULL && match->cp_number == -1;
- match = match->cp_next)
- match->cp_number = ++number;
- } else { // BACKWARD
- // search forwards (upwards) for the first valid (!= -1)
- // number. This should normally succeed already at the
- // first loop cycle, so it's fast!
- for (match = compl_curr_match->cp_next;
- match != NULL && match != compl_first_match;
- match = match->cp_next) {
- if (match->cp_number != -1) {
- number = match->cp_number;
- break;
- }
- }
- if (match != NULL) {
- // go down and assign all numbers which are not
- // assigned yet
- for (match = match->cp_prev;
- match && match->cp_number == -1;
- match = match->cp_prev) {
- match->cp_number = ++number;
- }
- }
- }
+ ins_compl_update_sequence_numbers();
}
/* The match should always have a sequence number now, this is
@@ -5307,8 +5327,9 @@ static int ins_complete(int c, bool enable_pum)
compl_curr_match->cp_number);
edit_submode_extra = match_ref;
edit_submode_highl = HLF_R;
- if (dollar_vcol >= 0)
- curs_columns(FALSE);
+ if (dollar_vcol >= 0) {
+ curs_columns(curwin, false);
+ }
}
}
}
@@ -5318,9 +5339,11 @@ static int ins_complete(int c, bool enable_pum)
if (!shortmess(SHM_COMPLETIONMENU)) {
if (edit_submode_extra != NULL) {
if (!p_smd) {
+ msg_hist_off = true;
msg_attr((const char *)edit_submode_extra,
(edit_submode_highl < HLF_COUNT
? HL_ATTR(edit_submode_highl) : 0));
+ msg_hist_off = false;
}
} else {
msg_clr_cmdline(); // necessary for "noshowmode"
@@ -6136,7 +6159,7 @@ internal_format (
curwin->w_p_lbr = has_lbr;
if (!format_only && haveto_redraw) {
- update_topline();
+ update_topline(curwin);
redraw_curbuf_later(VALID);
}
}
@@ -6481,7 +6504,7 @@ stop_insert (
curwin->w_cursor = tpos;
}
- auto_format(TRUE, FALSE);
+ auto_format(true, false);
if (ascii_iswhite(cc)) {
if (gchar_cursor() != NUL)
@@ -6785,7 +6808,7 @@ cursor_up (
coladvance(curwin->w_curswant);
if (upd_topline) {
- update_topline(); // make sure curwin->w_topline is valid
+ update_topline(curwin); // make sure curwin->w_topline is valid
}
return OK;
@@ -6836,7 +6859,7 @@ cursor_down (
coladvance(curwin->w_curswant);
if (upd_topline) {
- update_topline(); // make sure curwin->w_topline is valid
+ update_topline(curwin); // make sure curwin->w_topline is valid
}
return OK;
@@ -8259,8 +8282,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;
}
@@ -8306,9 +8330,6 @@ static void ins_mouse(int c)
pos_T tpos;
win_T *old_curwin = curwin;
- if (!mouse_has(MOUSE_INSERT))
- return;
-
undisplay_dollar();
tpos = curwin->w_cursor;
if (do_mouse(NULL, c, BACKWARD, 1, 0)) {
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index fa037b59d7..8a1556320c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7,6 +7,8 @@
#include <math.h>
+#include "auto/config.h"
+
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
@@ -74,9 +76,6 @@ static char_u * const namespace_char = (char_u *)"abglstvw";
/// Variable used for g:
static ScopeDictDictItem globvars_var;
-/// g: value
-#define globvarht globvardict.dv_hashtab
-
/*
* Old Vim variables such as "v:version" are also available without the "v:".
* Also in functions. We need a special hashtable for them.
@@ -2554,6 +2553,7 @@ void free_for_info(void *fi_void)
void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
+ FUNC_ATTR_NONNULL_ALL
{
int got_eq = FALSE;
int c;
@@ -2636,6 +2636,23 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
}
}
}
+
+ // ":exe one two" completes "two"
+ if ((cmdidx == CMD_execute
+ || cmdidx == CMD_echo
+ || cmdidx == CMD_echon
+ || cmdidx == CMD_echomsg)
+ && xp->xp_context == EXPAND_EXPRESSION) {
+ for (;;) {
+ char_u *const n = skiptowhite(arg);
+
+ if (n == arg || ascii_iswhite_or_nul(*skipwhite(n))) {
+ break;
+ }
+ arg = skipwhite(n);
+ }
+ }
+
xp->xp_pattern = arg;
}
@@ -5402,7 +5419,7 @@ static int get_literal_key(char_u **arg, typval_T *tv)
for (p = *arg; ASCII_ISALNUM(*p) || *p == '_' || *p == '-'; p++) {
}
tv->v_type = VAR_STRING;
- tv->vval.v_string = vim_strnsave(*arg, (int)(p - *arg));
+ tv->vval.v_string = vim_strnsave(*arg, p - *arg);
*arg = skipwhite(p);
return OK;
@@ -5931,6 +5948,19 @@ int assert_exception(typval_T *argvars)
return 0;
}
+static void assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars,
+ const char *cmd)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) {
+ char *const tofree = encode_tv2echo(&argvars[2], NULL);
+ ga_concat(gap, (char_u *)tofree);
+ xfree(tofree);
+ } else {
+ ga_concat(gap, (char_u *)cmd);
+ }
+}
+
int assert_fails(typval_T *argvars)
FUNC_ATTR_NONNULL_ALL
{
@@ -5949,14 +5979,7 @@ int assert_fails(typval_T *argvars)
if (!called_emsg) {
prepare_assert_error(&ga);
ga_concat(&ga, (const char_u *)"command did not fail: ");
- if (argvars[1].v_type != VAR_UNKNOWN
- && argvars[2].v_type != VAR_UNKNOWN) {
- char *const tofree = encode_tv2echo(&argvars[2], NULL);
- ga_concat(&ga, (char_u *)tofree);
- xfree(tofree);
- } else {
- ga_concat(&ga, (const char_u *)cmd);
- }
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
@@ -5969,6 +5992,8 @@ int assert_fails(typval_T *argvars)
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
&vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER);
+ ga_concat(&ga, (char_u *)": ");
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
@@ -7068,7 +7093,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append,
}
}
check_cursor_col();
- update_topline();
+ update_topline(curwin);
}
if (!is_curbuf) {
@@ -7780,13 +7805,13 @@ pos_T *var2fpos(const typval_T *const tv, const int dollar_lnum,
if (name[0] == 'w' && dollar_lnum) {
pos.col = 0;
if (name[1] == '0') { // "w0": first visible line
- update_topline();
+ update_topline(curwin);
// In silent Ex mode topline is zero, but that's not a valid line
// number; use one instead.
pos.lnum = curwin->w_topline > 0 ? curwin->w_topline : 1;
return &pos;
} else if (name[1] == '$') { // "w$": last visible line
- validate_botline();
+ validate_botline(curwin);
// In silent Ex mode botline is zero, return zero then.
pos.lnum = curwin->w_botline > 0 ? curwin->w_botline - 1 : 0;
return &pos;
@@ -10244,9 +10269,6 @@ repeat:
if (src[*usedlen] == ':'
&& (src[*usedlen + 1] == 's'
|| (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) {
- char_u *str;
- char_u *pat;
- char_u *sub;
int sep;
char_u *flags;
int didit = FALSE;
@@ -10263,13 +10285,13 @@ repeat:
// find end of pattern
p = vim_strchr(s, sep);
if (p != NULL) {
- pat = vim_strnsave(s, (int)(p - s));
+ char_u *const pat = vim_strnsave(s, p - s);
s = p + 1;
// find end of substitution
p = vim_strchr(s, sep);
if (p != NULL) {
- sub = vim_strnsave(s, (int)(p - s));
- str = vim_strnsave(*fnamep, *fnamelen);
+ char_u *const sub = vim_strnsave(s, p - s);
+ char_u *const str = vim_strnsave(*fnamep, *fnamelen);
*usedlen = (size_t)(p + 1 - src);
s = do_string_sub(str, pat, sub, NULL, flags);
*fnamep = s;
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 9f1994e299..952fa35b83 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -150,6 +150,7 @@ return {
getjumplist={args={0, 2}},
getline={args={1, 2}},
getloclist={args={1, 2}},
+ getmarklist={args={0, 1}},
getmatches={args={0, 1}},
getpid={},
getpos={args=1},
@@ -392,6 +393,7 @@ return {
win_screenpos={args=1},
winbufnr={args=1},
wincol={},
+ windowsversion={},
winheight={args=1},
winlayout={args={0, 1}},
winline={},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 4df935469a..8235d74cbb 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -95,7 +95,6 @@ PRAGMA_DIAG_POP
static char *e_listarg = N_("E686: Argument of %s must be a List");
-static char *e_stringreq = N_("E928: String required");
static char *e_invalwindow = N_("E957: Invalid window number");
/// Dummy va_list for passing to vim_snprintf
@@ -727,7 +726,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only)
p_cpo = (char_u *)"";
buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
- TRUE, FALSE, curtab_only));
+ true, false, curtab_only));
p_magic = save_magic;
p_cpo = save_cpo;
@@ -1877,10 +1876,12 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- const char *name = tv_get_string(&argvars[0]);
+ if (tv_check_for_string(&argvars[0]) == FAIL) {
+ return;
+ }
// Check in $PATH and also check directly if there is a directory name
- rettv->vval.v_number = os_can_exe(name, NULL, true);
+ rettv->vval.v_number = os_can_exe(tv_get_string(&argvars[0]), NULL, true);
}
typedef struct {
@@ -1984,10 +1985,13 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "exepath()" function
static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- const char *arg = tv_get_string(&argvars[0]);
+ if (tv_check_for_string(&argvars[0]) == FAIL) {
+ return;
+ }
+
char *path = NULL;
- (void)os_can_exe(arg, &path, true);
+ (void)os_can_exe(tv_get_string(&argvars[0]), &path, true);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *)path;
@@ -2161,7 +2165,7 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
.nextcmd = NULL,
.cmdidx = CMD_USER,
};
- eap.argt |= NOSPC;
+ eap.argt |= EX_NOSPC;
expand_filename(&eap, &cmdstr, &errormsg);
if (errormsg != NULL && *errormsg != NUL) {
@@ -2459,7 +2463,7 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *fbuf = NULL;
- size_t len;
+ size_t len = 0;
char buf[NUMBUFLEN];
const char *fname = tv_get_string_chk(&argvars[0]);
const char *const mods = tv_get_string_buf_chk(&argvars[1], buf);
@@ -2468,8 +2472,10 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} else {
len = strlen(fname);
size_t usedlen = 0;
- (void)modify_fname((char_u *)mods, false, &usedlen,
- (char_u **)&fname, &fbuf, &len);
+ if (mods != NULL && *mods != NUL) {
+ (void)modify_fname((char_u *)mods, false, &usedlen,
+ (char_u **)&fname, &fbuf, &len);
+ }
}
rettv->v_type = VAR_STRING;
@@ -3477,6 +3483,25 @@ static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_qf_loc_list(false, wp, &argvars[1], rettv);
}
+
+/// "getmarklist()" function
+static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ if (argvars[0].v_type == VAR_UNKNOWN) {
+ get_global_marks(rettv->vval.v_list);
+ return;
+ }
+
+ buf_T *buf = tv_get_buf(&argvars[0], false);
+ if (buf == NULL) {
+ return;
+ }
+
+ get_buf_local_marks(buf, rettv->vval.v_list);
+}
+
/*
* "getmatches()" function
*/
@@ -4200,6 +4225,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = true;
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
+ } else if (STRICMP(name, "clipboard_working") == 0) {
+ n = eval_has_provider("clipboard");
#ifdef UNIX
} else if (STRICMP(name, "unnamedplus") == 0) {
n = eval_has_provider("clipboard");
@@ -6545,7 +6572,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
if (prevlen == 0) {
assert(len < INT_MAX);
- s = vim_strnsave(start, (int)len);
+ s = vim_strnsave(start, len);
} else {
/* Change "prev" buffer to be the right size. This way
* the bytes are only copied once, and very long lines are
@@ -10847,7 +10874,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
}
- rettv->vval.v_string = vim_strnsave(head, (int)(tail - head));
+ rettv->vval.v_string = vim_strnsave(head, tail - head);
}
/*
@@ -11213,6 +11240,13 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+// "windowsversion()" function
+static void f_windowsversion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = (char_u *)xstrdup(windowsVersion);
+}
+
/// "wordcount()" function
static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index b62820fecc..02d32a4f86 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -2953,6 +2953,19 @@ float_T tv_get_float(const typval_T *const tv)
return 0;
}
+// Give an error and return FAIL unless "tv" is a non-empty string.
+int tv_check_for_string(const typval_T *const tv)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ if (tv->v_type != VAR_STRING
+ || tv->vval.v_string == NULL
+ || *tv->vval.v_string == NUL) {
+ EMSG(_(e_stringreq));
+ return FAIL;
+ }
+ return OK;
+}
+
/// Get the string value of a "stringish" VimL object.
///
/// @param[in] tv Object to get value of.
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 1e3e9bd366..d8ede1e3ba 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -492,7 +492,7 @@ static inline void tv_list_ref(list_T *const l)
static inline void tv_list_set_ret(typval_T *const tv, list_T *const l)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1);
-/// Set a list as the return value
+/// Set a list as the return value. Increments the reference count.
///
/// @param[out] tv Object to receive the list
/// @param[in,out] l List to pass to the object
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 8daef00985..70c998ef39 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -2297,9 +2297,9 @@ void ex_function(exarg_T *eap)
// Ignore leading white space.
p = skipwhite(p + 4);
heredoc_trimmed =
- vim_strnsave(theline, (int)(skipwhite(theline) - theline));
+ vim_strnsave(theline, skipwhite(theline) - theline);
}
- skip_until = vim_strnsave(p, (int)(skiptowhite(p) - p));
+ skip_until = vim_strnsave(p, skiptowhite(p) - p);
do_concat = false;
is_heredoc = true;
}
@@ -2484,6 +2484,7 @@ errret_2:
ga_clear_strings(&newlines);
ret_free:
xfree(skip_until);
+ xfree(heredoc_trimmed);
xfree(line_to_free);
xfree(fudi.fd_newkey);
xfree(name);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index b0a51eaefd..61e4d634c6 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -629,6 +629,8 @@ void ex_sort(exarg_T *eap)
if (sort_abort)
goto sortend;
+ bcount_t old_count = 0, new_count = 0;
+
// Insert the lines in the sorted order below the last one.
lnum = eap->line2;
for (i = 0; i < count; i++) {
@@ -641,6 +643,8 @@ void ex_sort(exarg_T *eap)
}
s = ml_get(get_lnum);
+ size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen
+ old_count += bytelen;
if (!unique || i == 0
|| (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0) {
// Copy the line into a buffer, it may become invalid in
@@ -649,6 +653,7 @@ void ex_sort(exarg_T *eap)
if (ml_append(lnum++, sortbuf1, (colnr_T)0, false) == FAIL) {
break;
}
+ new_count += bytelen;
}
fast_breakcheck();
if (got_int)
@@ -668,11 +673,16 @@ void ex_sort(exarg_T *eap)
deleted = (long)(count - (lnum - eap->line2));
if (deleted > 0) {
mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted,
- kExtmarkUndo);
+ kExtmarkNOOP);
msgmore(-deleted);
} else if (deleted < 0) {
- mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkUndo);
+ mark_adjust(eap->line2, MAXLNUM, -deleted, 0L, kExtmarkNOOP);
}
+
+ extmark_splice(curbuf, eap->line1-1, 0,
+ count, 0, old_count,
+ lnum - eap->line2, 0, new_count, kExtmarkUndo);
+
if (change_occurred || deleted != 0) {
changed_lines(eap->line1, 0, eap->line2 + 1, -deleted, true);
}
@@ -1032,14 +1042,15 @@ void free_prev_shellcmd(void)
* Bangs in the argument are replaced with the previously entered command.
* Remember the argument.
*/
-void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
+void do_bang(int addr_count, exarg_T *eap, bool forceit,
+ bool do_in, bool do_out)
+ FUNC_ATTR_NONNULL_ALL
{
- char_u *arg = eap->arg; /* command */
- linenr_T line1 = eap->line1; /* start of range */
- linenr_T line2 = eap->line2; /* end of range */
- char_u *newcmd = NULL; /* the new command */
- int free_newcmd = FALSE; /* need to free() newcmd */
- int ins_prevcmd;
+ char_u *arg = eap->arg; // command
+ linenr_T line1 = eap->line1; // start of range
+ linenr_T line2 = eap->line2; // end of range
+ char_u *newcmd = NULL; // the new command
+ bool free_newcmd = false; // need to free() newcmd
char_u *t;
char_u *p;
char_u *trailarg;
@@ -1064,7 +1075,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
* Try to find an embedded bang, like in :!<cmd> ! [args]
* (:!! is indicated by the 'forceit' variable)
*/
- ins_prevcmd = forceit;
+ bool ins_prevcmd = forceit;
trailarg = arg;
do {
len = (int)STRLEN(trailarg) + 1;
@@ -1101,7 +1112,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
else {
trailarg = p;
*trailarg++ = NUL;
- ins_prevcmd = TRUE;
+ ins_prevcmd = true;
break;
}
}
@@ -1131,7 +1142,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
STRCPY(newcmd, p_shq);
STRCAT(newcmd, prevcmd);
STRCAT(newcmd, p_shq);
- free_newcmd = TRUE;
+ free_newcmd = true;
}
if (addr_count == 0) { /* :! */
/* echo the command */
@@ -1164,15 +1175,15 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
// do this.
// Alternatively, if on Unix and redirecting input or output, but not both,
// and the 'shelltemp' option isn't set, use pipes.
-// We use input redirection if do_in is TRUE.
-// We use output redirection if do_out is TRUE.
+// We use input redirection if do_in is true.
+// We use output redirection if do_out is true.
static void do_filter(
linenr_T line1,
linenr_T line2,
exarg_T *eap, /* for forced 'ff' and 'fenc' */
char_u *cmd,
- int do_in,
- int do_out)
+ bool do_in,
+ bool do_out)
{
char_u *itmp = NULL;
char_u *otmp = NULL;
@@ -1669,10 +1680,17 @@ void ex_update(exarg_T *eap)
*/
void ex_write(exarg_T *eap)
{
- if (eap->usefilter) /* input lines to shell command */
- do_bang(1, eap, FALSE, TRUE, FALSE);
- else
+ if (eap->cmdidx == CMD_saveas) {
+ // :saveas does not take a range, uses all lines.
+ eap->line1 = 1;
+ eap->line2 = curbuf->b_ml.ml_line_count;
+ }
+
+ if (eap->usefilter) { // input lines to shell command
+ do_bang(1, eap, false, true, false);
+ } else {
(void)do_write(eap);
+ }
}
/*
@@ -2066,19 +2084,20 @@ static int check_readonly(int *forceit, buf_T *buf)
return FALSE;
}
-/*
- * Try to abandon current file and edit a new or existing file.
- * "fnum" is the number of the file, if zero use ffname/sfname.
- * "lnum" is the line number for the cursor in the new file (if non-zero).
- *
- * Return:
- * GETFILE_ERROR for "normal" error,
- * GETFILE_NOT_WRITTEN for "not written" error,
- * GETFILE_SAME_FILE for success
- * GETFILE_OPEN_OTHER for successfully opening another file.
- */
-int getfile(int fnum, char_u *ffname, char_u *sfname, int setpm, linenr_T lnum, int forceit)
+// Try to abandon the current file and edit a new or existing file.
+// "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg".
+// "lnum" is the line number for the cursor in the new file (if non-zero).
+//
+// Return:
+// GETFILE_ERROR for "normal" error,
+// GETFILE_NOT_WRITTEN for "not written" error,
+// GETFILE_SAME_FILE for success
+// GETFILE_OPEN_OTHER for successfully opening another file.
+int getfile(int fnum, char_u *ffname_arg, char_u *sfname_arg, int setpm,
+ linenr_T lnum, int forceit)
{
+ char_u *ffname = ffname_arg;
+ char_u *sfname = sfname_arg;
int other;
int retval;
char_u *free_me = NULL;
@@ -2322,7 +2341,7 @@ int do_ecmd(
// Existing memfile.
oldbuf = true;
set_bufref(&bufref, buf);
- (void)buf_check_timestamp(buf, false);
+ (void)buf_check_timestamp(buf);
// Check if autocommands made buffer invalid or changed the current
// buffer.
if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf) {
@@ -2705,7 +2724,7 @@ int do_ecmd(
if (topline == 0 && command == NULL) {
*so_ptr = 999; // force cursor to be vertically centered in the window
}
- update_topline();
+ update_topline(curwin);
curwin->w_scbind_pos = curwin->w_topline;
*so_ptr = n;
redraw_curbuf_later(NOT_VALID); // redraw this buffer later
@@ -2795,9 +2814,10 @@ void ex_append(exarg_T *eap)
p = vim_strchr(eap->nextcmd, NL);
if (p == NULL)
p = eap->nextcmd + STRLEN(eap->nextcmd);
- theline = vim_strnsave(eap->nextcmd, (int)(p - eap->nextcmd));
- if (*p != NUL)
- ++p;
+ theline = vim_strnsave(eap->nextcmd, p - eap->nextcmd);
+ if (*p != NUL) {
+ p++;
+ }
eap->nextcmd = p;
} else {
// Set State to avoid the cursor shape to be set to INSERT mode
@@ -3704,7 +3724,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
+ len_change;
highlight_match = TRUE;
- update_topline();
+ update_topline(curwin);
validate_cursor();
update_screen(SOME_VALID);
highlight_match = false;
@@ -3909,17 +3929,13 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
ADJUST_SUB_FIRSTLNUM();
- // TODO(bfredl): adjust also in preview, because decorations?
- // this has some robustness issues, will look into later.
- bool do_splice = !preview;
+ // TODO(bfredl): this has some robustness issues, look into later.
bcount_t replaced_bytes = 0;
lpos_T start = regmatch.startpos[0], end = regmatch.endpos[0];
- if (do_splice) {
- for (i = 0; i < nmatch-1; i++) {
- replaced_bytes += STRLEN(ml_get(lnum_start+i)) + 1;
- }
- replaced_bytes += end.col - start.col;
+ for (i = 0; i < nmatch-1; i++) {
+ replaced_bytes += STRLEN(ml_get(lnum_start+i)) + 1;
}
+ replaced_bytes += end.col - start.col;
// Now the trick is to replace CTRL-M chars with a real line
@@ -3964,14 +3980,12 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
current_match.end.col = new_endcol;
current_match.end.lnum = lnum;
- if (do_splice) {
- int matchcols = end.col - ((end.lnum == start.lnum)
- ? start.col : 0);
- int subcols = new_endcol - ((lnum == lnum_start) ? start_col : 0);
- extmark_splice(curbuf, lnum_start-1, start_col,
- end.lnum-start.lnum, matchcols, replaced_bytes,
- lnum-lnum_start, subcols, sublen-1, kExtmarkUndo);
- }
+ int matchcols = end.col - ((end.lnum == start.lnum)
+ ? start.col : 0);
+ int subcols = new_endcol - ((lnum == lnum_start) ? start_col : 0);
+ extmark_splice(curbuf, lnum_start-1, start_col,
+ end.lnum-start.lnum, matchcols, replaced_bytes,
+ lnum-lnum_start, subcols, sublen-1, kExtmarkUndo);
}
@@ -5254,8 +5268,10 @@ void ex_viusage(exarg_T *eap)
/// @param tagname Name of the tags file ("tags" for English, "tags-fr" for
/// French)
/// @param add_help_tags Whether to add the "help-tags" tag
-static void helptags_one(char_u *const dir, const char_u *const ext,
- const char_u *const tagfname, const bool add_help_tags)
+/// @param ignore_writeerr ignore write error
+static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname,
+ bool add_help_tags, bool ignore_writeerr)
+ FUNC_ATTR_NONNULL_ALL
{
garray_T ga;
int filecount;
@@ -5299,7 +5315,9 @@ static void helptags_one(char_u *const dir, const char_u *const ext,
FILE *const fd_tags = os_fopen((char *)NameBuff, "w");
if (fd_tags == NULL) {
- EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
+ if (!ignore_writeerr) {
+ EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
+ }
FreeWild(filecount, files);
return;
}
@@ -5447,7 +5465,9 @@ static void helptags_one(char_u *const dir, const char_u *const ext,
}
/// Generate tags in one help directory, taking care of translations.
-static void do_helptags(char_u *dirname, bool add_help_tags)
+static void do_helptags(char_u *dirname, bool add_help_tags,
+ bool ignore_writeerr)
+ FUNC_ATTR_NONNULL_ALL
{
int len;
garray_T ga;
@@ -5529,17 +5549,17 @@ static void do_helptags(char_u *dirname, bool add_help_tags)
ext[1] = fname[5];
ext[2] = fname[6];
}
- helptags_one(dirname, ext, fname, add_help_tags);
+ helptags_one(dirname, ext, fname, add_help_tags, ignore_writeerr);
}
ga_clear(&ga);
FreeWild(filecount, files);
}
- static void
-helptags_cb(char_u *fname, void *cookie)
+static void helptags_cb(char_u *fname, void *cookie)
+ FUNC_ATTR_NONNULL_ALL
{
- do_helptags(fname, *(bool *)cookie);
+ do_helptags(fname, *(bool *)cookie, true);
}
/*
@@ -5568,7 +5588,7 @@ void ex_helptags(exarg_T *eap)
if (dirname == NULL || !os_isdir(dirname)) {
EMSG2(_("E150: Not a directory: %s"), eap->arg);
} else {
- do_helptags(dirname, add_help_tags);
+ do_helptags(dirname, add_help_tags, false);
}
xfree(dirname);
}
@@ -5739,7 +5759,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr,
redraw_later(curwin, SOME_VALID);
win_enter(save_curwin, false); // Return to original window
- update_topline();
+ update_topline(curwin);
// Update screen now.
int save_rd = RedrawingDisabled;
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index d62b00fee1..069d5d461b 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -1,6 +1,9 @@
local bit = require 'bit'
+local module = {}
+
-- Description of the values below is contained in ex_cmds_defs.h file.
+-- "EX_" prefix is omitted.
local RANGE = 0x001
local BANG = 0x002
local EXTRA = 0x004
@@ -14,3289 +17,3308 @@ local REGSTR = 0x200
local COUNT = 0x400
local NOTRLCOM = 0x800
local ZEROR = 0x1000
-local USECTRLV = 0x2000
-local NOTADR = 0x4000
-local EDITCMD = 0x8000
-local BUFNAME = 0x10000
-local BUFUNL = 0x20000
-local ARGOPT = 0x40000
-local SBOXOK = 0x80000
-local CMDWIN = 0x100000
-local MODIFY = 0x200000
-local EXFLAGS = 0x400000
-local RESTRICT = 0x800000
+local CTRLV = 0x2000
+local CMDARG = 0x4000
+local BUFNAME = 0x8000
+local BUFUNL = 0x10000
+local ARGOPT = 0x20000
+local SBOXOK = 0x40000
+local CMDWIN = 0x80000
+local MODIFY = 0x100000
+local FLAGS = 0x200000
local FILES = bit.bor(XFILE, EXTRA)
local WORD1 = bit.bor(EXTRA, NOSPC)
local FILE1 = bit.bor(FILES, NOSPC)
-local ADDR_LINES = 0 -- buffer line numbers
-local ADDR_WINDOWS = 1 -- window number
-local ADDR_ARGUMENTS = 2 -- argument number
-local ADDR_LOADED_BUFFERS = 3 -- buffer number of loaded buffer
-local ADDR_BUFFERS = 4 -- buffer number
-local ADDR_TABS = 5 -- tab page number
-local ADDR_TABS_RELATIVE = 6 -- Tab page that only relative
-local ADDR_QUICKFIX = 7 -- quickfix list entry number
-local ADDR_OTHER = 99 -- something else
+module.flags = {
+ RANGE = RANGE,
+ DFLALL = DFLALL,
+}
-- The following table is described in ex_cmds_defs.h file.
-return {
+module.cmds = {
{
command='append',
flags=bit.bor(BANG, RANGE, ZEROR, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_append',
},
{
command='abbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='abclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='aboveleft',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='all',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_all',
},
{
command='amenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='anoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='args',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='argadd',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, FILES, TRLBAR),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, RANGE, ZEROR, FILES, TRLBAR),
+ addr_type='ADDR_ARGUMENTS',
func='ex_argadd',
},
{
command='argdelete',
- flags=bit.bor(BANG, RANGE, NOTADR, FILES, TRLBAR),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, RANGE, FILES, TRLBAR),
+ addr_type='ADDR_ARGUMENTS',
func='ex_argdelete',
},
{
command='argdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_ARGUMENTS',
func='ex_listdo',
},
{
command='argedit',
- flags=bit.bor(BANG, NEEDARG, RANGE, NOTADR, ZEROR, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, NEEDARG, RANGE, ZEROR, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_ARGUMENTS',
func='ex_argedit',
},
{
command='argglobal',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='arglocal',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_args',
},
{
command='argument',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_ARGUMENTS',
func='ex_argument',
},
{
command='ascii',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='do_ascii',
},
{
command='autocmd',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_autocmd',
},
{
command='augroup',
flags=bit.bor(BANG, WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_autocmd',
},
{
command='aunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='buffer',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
- addr_type=ADDR_BUFFERS,
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
+ addr_type='ADDR_BUFFERS',
func='ex_buffer',
},
{
command='bNext',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='ball',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='badd',
- flags=bit.bor(NEEDARG, FILE1, EDITCMD, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='bdelete',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_BUFFERS,
+ flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_BUFFERS',
func='ex_bunload',
},
{
command='behave',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_behave',
},
{
command='belowright',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='bfirst',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_brewind',
},
{
command='blast',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_blast',
},
{
command='bmodified',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bmodified',
},
{
command='bnext',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bnext',
},
{
command='botright',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='bprevious',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='brewind',
- flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_brewind',
},
{
command='break',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_break',
},
{
command='breakadd',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_breakadd',
},
{
command='breakdel',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_breakdel',
},
{
command='breaklist',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_breaklist',
},
{
command='browse',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='buffers',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
command='bufdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_BUFFERS,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_BUFFERS',
func='ex_listdo',
},
{
command='bunload',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_LOADED_BUFFERS,
+ flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_LOADED_BUFFERS',
func='ex_bunload',
},
{
command='bwipeout',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_BUFFERS,
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_BUFFERS',
func='ex_bunload',
},
{
command='change',
flags=bit.bor(BANG, WHOLEFOLD, RANGE, COUNT, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_change',
},
{
command='cNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cNfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cabclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='cabove',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type=ADDR_OTHER ,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='caddbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='caddexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='caddfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
+ command='cafter',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='call',
flags=bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_call',
},
{
command='catch',
flags=bit.bor(EXTRA, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_catch',
},
{
command='cbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
+ command='cbefore',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='cbelow',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type=ADDR_OTHER ,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='cbottom',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cbottom',
},
{
command='cc',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_QUICKFIX',
func='ex_cc',
},
{
command='cclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_cclose',
},
{
command='cd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='cdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_QUICKFIX,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='center',
flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_align',
},
{
command='cexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='cfile',
flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
-- Even though 'cfdo' is alphabetically lower than 'cfile', it is after
-- 'cfile' in this cmd list to support the existing ":cf" abbreviation.
{
command='cfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_QUICKFIX,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='cfirst',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='cgetfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
command='cgetbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='cgetexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='chdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='changes',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_changes',
},
{
command='checkhealth',
flags=bit.bor(EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_checkhealth',
},
{
command='checkpath',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_checkpath',
},
{
command='checktime',
- flags=bit.bor(RANGE, NOTADR, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_checktime',
},
{
command='chistory',
- flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_history',
},
{
command='clist',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='qf_list',
},
{
command='clast',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='close',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR, CMDWIN),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
+ addr_type='ADDR_WINDOWS',
func='ex_close',
},
{
command='clearjumps',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_clearjumps',
},
{
command='cmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='cmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='cmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='cnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cnewer',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='cnfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='cnoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='copy',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_copymove',
},
{
command='colder',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='colorscheme',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_colorscheme',
},
{
command='command',
- flags=bit.bor(EXTRA, BANG, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_command',
},
{
command='comclear',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_comclear',
},
{
command='compiler',
flags=bit.bor(BANG, TRLBAR, WORD1, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_compiler',
},
{
command='continue',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_continue',
},
{
command='confirm',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='const',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_const',
},
{
command='copen',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_copen',
},
{
command='cprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='cpfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_OTHER',
func='ex_cnext',
},
{
command='cquit',
- flags=bit.bor(RANGE, NOTADR, COUNT, ZEROR, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cquit',
},
{
command='crewind',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='cscope',
flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cscope',
},
{
command='cstag',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cstag',
},
{
command='cunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='cunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='cunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='cwindow',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cwindow',
},
{
command='delete',
flags=bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_operators',
},
{
command='delmarks',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_delmarks',
},
{
command='debug',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_debug',
},
{
command='debuggreedy',
- flags=bit.bor(RANGE, NOTADR, ZEROR, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_debuggreedy',
},
{
command='delcommand',
flags=bit.bor(BANG, NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_delcommand',
},
{
command='delfunction',
flags=bit.bor(BANG, NEEDARG, WORD1, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_delfunction',
},
{
command='display',
flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_display',
},
{
command='diffupdate',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_diffupdate',
},
{
command='diffget',
flags=bit.bor(RANGE, EXTRA, TRLBAR, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_diffgetput',
},
{
command='diffoff',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_diffoff',
},
{
command='diffpatch',
flags=bit.bor(EXTRA, FILE1, TRLBAR, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_diffpatch',
},
{
command='diffput',
flags=bit.bor(RANGE, EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_diffgetput',
},
{
command='diffsplit',
flags=bit.bor(EXTRA, FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_diffsplit',
},
{
command='diffthis',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_diffthis',
},
{
command='digraphs',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_digraphs',
},
{
command='djump',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='dlist',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='doautocmd',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_doautocmd',
},
{
command='doautoall',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_doautoall',
},
{
command='drop',
- flags=bit.bor(FILES, EDITCMD, NEEDARG, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_drop',
},
{
command='dsearch',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='dsplit',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='edit',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='earlier',
flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_later',
},
{
command='echo',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_echo',
},
{
command='echoerr',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
command='echohl',
flags=bit.bor(EXTRA, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_echohl',
},
{
command='echomsg',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
command='echon',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_echo',
},
{
command='else',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_else',
},
{
command='elseif',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_else',
},
{
command='emenu',
- flags=bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, NOTADR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_emenu',
},
{
command='endif',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_endif',
},
{
command='endfunction',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_endfunction',
},
{
command='endfor',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_endwhile',
},
{
command='endtry',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_endtry',
},
{
command='endwhile',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_endwhile',
},
{
command='enew',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='ex',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='execute',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_execute',
},
{
command='exit',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_exit',
},
{
command='exusage',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_exusage',
},
{
command='file',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, BANG, FILE1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_file',
},
{
command='files',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
command='filetype',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_filetype',
},
{
command='filter',
flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='find',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, FILE1, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type='ADDR_OTHER',
func='ex_find',
},
{
command='finally',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_finally',
},
{
command='finish',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_finish',
},
{
command='first',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='fold',
flags=bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_fold',
},
{
command='foldclose',
flags=bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_foldopen',
},
{
command='folddoopen',
flags=bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_folddo',
},
{
command='folddoclosed',
flags=bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_folddo',
},
{
command='foldopen',
flags=bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_foldopen',
},
{
command='for',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_while',
},
{
command='function',
flags=bit.bor(EXTRA, BANG, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_function',
},
{
command='global',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, DFLALL, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_global',
},
{
command='goto',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_goto',
},
{
command='grep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='grepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='gui',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_nogui',
},
{
command='gvim',
- flags=bit.bor(BANG, FILES, EDITCMD, ARGOPT, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_nogui',
},
{
command='help',
flags=bit.bor(BANG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_help',
},
{
command='helpclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_helpclose',
},
{
command='helpgrep',
flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_helpgrep',
},
{
command='helptags',
flags=bit.bor(NEEDARG, FILES, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_helptags',
},
{
command='hardcopy',
flags=bit.bor(RANGE, COUNT, EXTRA, TRLBAR, DFLALL, BANG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_hardcopy',
},
{
command='highlight',
flags=bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_highlight',
},
{
command='hide',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, TRLBAR),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR),
+ addr_type='ADDR_WINDOWS',
func='ex_hide',
},
{
command='history',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_history',
},
{
command='insert',
flags=bit.bor(BANG, RANGE, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_append',
},
{
command='iabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='iabclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_abclear',
},
{
command='if',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_if',
},
{
command='ijump',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='ilist',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='imap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='imapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='imenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='inoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='inoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='inoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='intro',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_intro',
},
{
command='isearch',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='isplit',
flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_findpat',
},
{
command='iunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='iunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='iunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='join',
- flags=bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
+ addr_type='ADDR_LINES',
func='ex_join',
},
{
command='jumps',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_jumps',
},
{
command='k',
flags=bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_mark',
},
{
command='keepmarks',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keepjumps',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keeppatterns',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='keepalt',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='list',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_print',
},
{
command='lNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lNfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='last',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_last',
},
{
command='labove',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type=ADDR_OTHER ,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='language',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_language',
},
{
command='laddexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='laddbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='laddfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
+ command='lafter',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='later',
flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_later',
},
{
command='lbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
+ command='lbefore',
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
+ func='ex_cbelow',
+ },
+ {
command='lbelow',
- flags=bit.bor(RANGE, TRLBAR),
- addr_type=ADDR_OTHER ,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='ex_cbelow',
},
{
command='lbottom',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cbottom',
},
{
command='lcd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='lchdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='lclose',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cclose',
},
{
command='lcscope',
flags=bit.bor(EXTRA, NOTRLCOM, XFILE),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cscope',
},
{
command='ldo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_QUICKFIX,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='left',
flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_align',
},
{
command='leftabove',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='let',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_let',
},
{
command='lexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='lfile',
flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
-- Even though 'lfdo' is alphabetically lower than 'lfile', it is after
-- 'lfile' in this cmd list to support the existing ":lf" abbreviation.
{
command='lfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_QUICKFIX,
+ flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_QUICKFIX_VALID',
func='ex_listdo',
},
{
command='lfirst',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='lgetfile',
flags=bit.bor(TRLBAR, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cfile',
},
{
command='lgetbuffer',
- flags=bit.bor(RANGE, NOTADR, WORD1, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cbuffer',
},
{
command='lgetexpr',
flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cexpr',
},
{
command='lgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='lgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_make',
},
{
command='lhelpgrep',
flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_helpgrep',
},
{
command='lhistory',
- flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_history',
},
{
command='ll',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_QUICKFIX',
func='ex_cc',
},
{
command='llast',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='llist',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='qf_list',
},
{
command='lmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='lmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='lmake',
flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_make',
},
{
command='lnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='lnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lnewer',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='lnfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='loadview',
flags=bit.bor(FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_loadview',
},
{
command='loadkeymap',
flags=bit.bor(CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_loadkeymap',
},
{
command='lockmarks',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='lockvar',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_lockvar',
},
{
command='lolder',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_UNSIGNED',
func='qf_age',
},
{
command='lopen',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_copen',
},
{
command='lprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cnext',
},
{
command='lpfile',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_OTHER',
func='ex_cnext',
},
{
command='lrewind',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type='ADDR_UNSIGNED',
func='ex_cc',
},
{
command='ltag',
- flags=bit.bor(NOTADR, TRLBAR, BANG, WORD1),
- addr_type=ADDR_LINES,
+ flags=bit.bor(TRLBAR, BANG, WORD1),
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='lunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='lua',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_lua',
},
{
command='luado',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_luado',
},
{
command='luafile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_luafile',
},
{
command='lvimgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='lvimgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='lwindow',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_cwindow',
},
{
command='ls',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='buflist_list',
},
{
command='move',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_copymove',
},
{
command='mark',
flags=bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_mark',
},
{
command='make',
flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_make',
},
{
command='map',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='mapclear',
flags=bit.bor(EXTRA, BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='marks',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_marks',
},
{
command='match',
- flags=bit.bor(RANGE, NOTADR, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_match',
},
{
command='menu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='menutranslate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menutranslate',
},
{
command='messages',
flags=bit.bor(EXTRA, TRLBAR, RANGE, CMDWIN),
- addr_type=ADDR_OTHER,
+ addr_type='ADDR_OTHER',
func='ex_messages',
},
{
command='mkexrc',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mksession',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mkspell',
flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mkspell',
},
{
command='mkvimrc',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mkview',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mkrc',
},
{
command='mode',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mode',
},
{
command='mzscheme',
flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, SBOXOK),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_script_ni',
},
{
command='mzfile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_ni',
},
{
command='next',
- flags=bit.bor(RANGE, NOTADR, BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_next',
},
{
command='new',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='nmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='nmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='nmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='nnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='nnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='noremap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='noautocmd',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='nohlsearch',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_nohlsearch',
},
{
command='noreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='noremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='noswapfile',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='normal',
- flags=bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, USECTRLV, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_normal',
},
{
command='number',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_print',
},
{
command='nunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='nunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='oldfiles',
flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_oldfiles',
},
{
command='omap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='omapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='omenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='only',
- flags=bit.bor(BANG, NOTADR, RANGE, COUNT, TRLBAR),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_WINDOWS',
func='ex_only',
},
{
command='onoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='onoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='options',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_options',
},
{
command='ounmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='ounmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='ownsyntax',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ownsyntax',
},
{
command='print',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, SBOXOK),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, SBOXOK),
+ addr_type='ADDR_LINES',
func='ex_print',
},
{
command='packadd',
flags=bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_packadd',
},
{
command='packloadall',
flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_packloadall',
},
{
command='pclose',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_pclose',
},
{
command='perl',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_perl',
},
{
command='perldo',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_perldo',
},
{
command='perlfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_perlfile',
},
{
command='pedit',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_pedit',
},
{
command='pop',
- flags=bit.bor(RANGE, NOTADR, BANG, COUNT, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='popup',
flags=bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='ppop',
- flags=bit.bor(RANGE, NOTADR, BANG, COUNT, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='preserve',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_preserve',
},
{
command='previous',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='profile',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_profile',
},
{
command='profdel',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_breakdel',
},
{
command='psearch',
flags=bit.bor(BANG, RANGE, WHOLEFOLD, DFLALL, EXTRA),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_psearch',
},
{
command='ptag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptNext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptfirst',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
command='ptlast',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
command='ptnext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptrewind',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_ptag',
},
{
command='ptselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ptag',
},
{
command='put',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_put',
},
{
command='pwd',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_pwd',
},
{
command='python',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_python',
},
{
command='pydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pydo',
},
{
command='pyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pyfile',
},
{
command='py3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_python3',
},
{
command='py3do',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pydo3',
},
{
command='python3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_python3',
},
{
command='py3file',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_py3file',
},
{
command='pyx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pyx',
},
{
command='pyxdo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pyxdo',
},
{
command='pythonx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pyx',
},
{
command='pyxfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_pyxfile',
},
{
command='quit',
- flags=bit.bor(BANG, RANGE, COUNT, NOTADR, TRLBAR, CMDWIN),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
+ addr_type='ADDR_WINDOWS',
func='ex_quit',
},
{
command='quitall',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_quit_all',
},
{
command='qall',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_quit_all',
},
{
command='read',
flags=bit.bor(BANG, RANGE, WHOLEFOLD, FILE1, ARGOPT, TRLBAR, ZEROR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_read',
},
{
command='recover',
flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_recover',
},
{
command='redo',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_redo',
},
{
command='redir',
flags=bit.bor(BANG, FILES, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_redir',
},
{
command='redraw',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_redraw',
},
{
command='redrawstatus',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_redrawstatus',
},
{
command='redrawtabline',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_redrawtabline',
},
{
command='registers',
flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_display',
},
{
command='resize',
- flags=bit.bor(RANGE, NOTADR, TRLBAR, WORD1, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, TRLBAR, WORD1, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_resize',
},
{
command='retab',
flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, DFLALL, BANG, WORD1, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_retab',
},
{
command='return',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_return',
},
{
command='rewind',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='right',
flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_align',
},
{
command='rightbelow',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='rshada',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='runtime',
flags=bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_runtime',
},
{
command='rundo',
flags=bit.bor(NEEDARG, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_rundo',
},
{
command='ruby',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_ruby',
},
{
command='rubydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_rubydo',
},
{
command='rubyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_rubyfile',
},
{
command='rviminfo',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='substitute',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_substitute',
},
{
command='sNext',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='sargument',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EXTRA, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_ARGUMENTS,
+ flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_ARGUMENTS',
func='ex_argument',
},
{
command='sall',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_all',
},
{
command='sandbox',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='saveas',
- flags=bit.bor(BANG, DFLALL, FILE1, ARGOPT, CMDWIN, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, ARGOPT, CMDWIN, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_write',
},
{
command='sbuffer',
- flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR),
- addr_type=ADDR_BUFFERS,
+ flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
+ addr_type='ADDR_BUFFERS',
func='ex_buffer',
},
{
command='sbNext',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='sball',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='sbfirst',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_brewind',
},
{
command='sblast',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_blast',
},
{
command='sbmodified',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bmodified',
},
{
command='sbnext',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bnext',
},
{
command='sbprevious',
- flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_bprevious',
},
{
command='sbrewind',
- flags=bit.bor(EDITCMD, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(CMDARG, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_brewind',
},
{
command='scriptnames',
- flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR, CMDWIN),
- addr_type=ADDR_OTHER,
+ flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_scriptnames',
},
{
command='scriptencoding',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_scriptencoding',
},
{
command='scscope',
flags=bit.bor(EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_scscope',
},
{
command='set',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='setfiletype',
flags=bit.bor(TRLBAR, EXTRA, NEEDARG, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_setfiletype',
},
{
command='setglobal',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='setlocal',
flags=bit.bor(TRLBAR, EXTRA, CMDWIN, SBOXOK),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_set',
},
{
command='sfind',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='sfirst',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='simalt',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='sign',
- flags=bit.bor(NEEDARG, RANGE, NOTADR, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(NEEDARG, RANGE, EXTRA, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_sign',
},
{
command='silent',
flags=bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='sleep',
- flags=bit.bor(RANGE, NOTADR, COUNT, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, EXTRA, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_sleep',
},
{
command='slast',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_last',
},
{
command='smagic',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_submagic',
},
{
command='smap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='smapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='smenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='snext',
- flags=bit.bor(RANGE, NOTADR, BANG, FILES, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_next',
},
{
command='snomagic',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_submagic',
},
{
command='snoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='snoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='source',
flags=bit.bor(BANG, FILE1, TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_source',
},
{
command='sort',
flags=bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, EXTRA, NOTRLCOM, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_sort',
},
{
command='split',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='spellgood',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='spelldump',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_spelldump',
},
{
command='spellinfo',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_spellinfo',
},
{
command='spellrepall',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_spellrepall',
},
{
command='spellundo',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='spellwrong',
- flags=bit.bor(BANG, RANGE, NOTADR, NEEDARG, EXTRA, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_spell',
},
{
command='sprevious',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='srewind',
- flags=bit.bor(EXTRA, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_rewind',
},
{
command='stop',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_stop',
},
{
command='stag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_stag',
},
{
command='startinsert',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='startgreplace',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='startreplace',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_startinsert',
},
{
command='stopinsert',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_stopinsert',
},
{
command='stjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_stag',
},
{
command='stselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_stag',
},
{
command='sunhide',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='sunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='sunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='suspend',
flags=bit.bor(TRLBAR, BANG, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_stop',
},
{
command='sview',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='swapname',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_swapname',
},
{
command='syntax',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_syntax',
},
{
command='syntime',
flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_syntime',
},
{
command='syncbind',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_syncbind',
},
{
command='t',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_copymove',
},
{
command='tcd',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='tchdir',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_cd',
},
{
command='tNext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tag',
- flags=bit.bor(RANGE, NOTADR, BANG, WORD1, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tags',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='do_tags',
},
{
command='tab',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_TABS,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='tabclose',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
- addr_type=ADDR_TABS,
+ flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
+ addr_type='ADDR_TABS',
func='ex_tabclose',
},
{
command='tabdo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_TABS,
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_TABS',
func='ex_listdo',
},
{
command='tabedit',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_TABS,
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabfind',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, NEEDARG, TRLBAR),
- addr_type=ADDR_TABS,
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, NEEDARG, TRLBAR),
+ addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabfirst',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_TABS,
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabmove',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type=ADDR_TABS,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type='ADDR_TABS',
func='ex_tabmove',
},
{
command='tablast',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_TABS,
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabnext',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type=ADDR_TABS,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type='ADDR_TABS',
func='ex_tabnext',
},
{
command='tabnew',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, ZEROR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_TABS,
+ flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_TABS',
func='ex_splitview',
},
{
command='tabonly',
- flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
- addr_type=ADDR_TABS,
+ flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
+ addr_type='ADDR_TABS',
func='ex_tabonly',
},
{
command='tabprevious',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type=ADDR_TABS_RELATIVE,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type='ADDR_TABS_RELATIVE',
func='ex_tabnext',
},
{
command='tabNext',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type=ADDR_TABS_RELATIVE,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type='ADDR_TABS_RELATIVE',
func='ex_tabnext',
},
{
command='tabrewind',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_TABS,
+ addr_type='ADDR_NONE',
func='ex_tabnext',
},
{
command='tabs',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_TABS,
+ addr_type='ADDR_NONE',
func='ex_tabs',
},
{
command='tcl',
flags=bit.bor(RANGE,EXTRA,NEEDARG,CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_script_ni',
},
{
command='tcldo',
flags=bit.bor(RANGE,DFLALL,EXTRA,NEEDARG,CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_ni',
},
{
command='tclfile',
flags=bit.bor(RANGE,FILE1,NEEDARG,CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_ni',
},
{
command='terminal',
flags=bit.bor(BANG, FILES, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_terminal',
},
{
command='tfirst',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='throw',
flags=bit.bor(EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_throw',
},
{
command='tjump',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tlast',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='tmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='tmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='tnext',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='tnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='topleft',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='tprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='trewind',
- flags=bit.bor(RANGE, NOTADR, BANG, TRLBAR, ZEROR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type='ADDR_OTHER',
func='ex_tag',
},
{
command='try',
flags=bit.bor(TRLBAR, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_try',
},
{
command='tselect',
flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_tag',
},
{
command='tunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='tunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='undo',
- flags=bit.bor(RANGE, NOTADR, COUNT, ZEROR, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_undo',
},
{
command='undojoin',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_undojoin',
},
{
command='undolist',
flags=bit.bor(TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_undolist',
},
{
command='unabbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_abbreviate',
},
{
command='unhide',
- flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_buffer_all',
},
{
command='unlet',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_unlet',
},
{
command='unlockvar',
flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_lockvar',
},
{
command='unmap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='unmenu',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='unsilent',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='update',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_update',
},
{
command='vglobal',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, DFLALL, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_global',
},
{
command='version',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_version',
},
{
command='verbose',
- flags=bit.bor(NEEDARG, RANGE, NOTADR, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_wrongmodifier',
},
{
command='vertical',
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wrongmodifier',
},
{
command='visual',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='view',
- flags=bit.bor(BANG, FILE1, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='ex_edit',
},
{
command='vimgrep',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='vimgrepadd',
- flags=bit.bor(RANGE, NOTADR, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type='ADDR_OTHER',
func='ex_vimgrep',
},
{
command='viusage',
flags=bit.bor(TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_viusage',
},
{
command='vmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='vmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='vmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='vnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='vnew',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='vnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='vsplit',
- flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_splitview',
},
{
command='vunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='vunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='write',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_write',
},
{
command='wNext',
- flags=bit.bor(RANGE, WHOLEFOLD, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
command='wall',
flags=bit.bor(BANG, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='while',
flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_while',
},
{
command='winsize',
flags=bit.bor(EXTRA, NEEDARG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_winsize',
},
{
command='wincmd',
- flags=bit.bor(NEEDARG, WORD1, RANGE, NOTADR, CMDWIN),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(NEEDARG, WORD1, RANGE, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_wincmd',
},
{
command='windo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, NOTADR, DFLALL),
- addr_type=ADDR_WINDOWS,
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type='ADDR_WINDOWS',
func='ex_listdo',
},
{
command='winpos',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_ni',
},
{
command='wnext',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
command='wprevious',
- flags=bit.bor(RANGE, NOTADR, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_wnext',
},
{
command='wq',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_exit',
},
{
command='wqall',
- flags=bit.bor(BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='wshada',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='wundo',
flags=bit.bor(BANG, NEEDARG, FILE1),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_wundo',
},
{
command='wviminfo',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_shada',
},
{
command='xit',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_exit',
},
{
command='xall',
flags=bit.bor(BANG, TRLBAR),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='do_wqall',
},
{
command='xmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='xmapclear',
flags=bit.bor(EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_NONE',
func='ex_mapclear',
},
{
command='xmenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='xnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_map',
},
{
command='xnoremenu',
- flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_OTHER',
func='ex_menu',
},
{
command='xunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_unmap',
},
{
command='xunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, USECTRLV, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN),
+ addr_type='ADDR_NONE',
func='ex_menu',
},
{
command='yank',
flags=bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_operators',
},
{
command='z',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, EXFLAGS, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, FLAGS, TRLBAR, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_z',
},
{
command='!',
enum='CMD_bang',
flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILES, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_bang',
},
{
command='#',
enum='CMD_pound',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_print',
},
{
command='&',
enum='CMD_and',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_substitute',
},
{
command='<',
enum='CMD_lshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
+ addr_type='ADDR_LINES',
func='ex_operators',
},
{
command='=',
enum='CMD_equal',
- flags=bit.bor(RANGE, TRLBAR, DFLALL, EXFLAGS, CMDWIN),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, TRLBAR, DFLALL, FLAGS, CMDWIN),
+ addr_type='ADDR_LINES',
func='ex_equal',
},
{
command='>',
enum='CMD_rshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, EXFLAGS, TRLBAR, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, MODIFY),
+ addr_type='ADDR_LINES',
func='ex_operators',
},
{
command='@',
enum='CMD_at',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_at',
},
{
command='Next',
- flags=bit.bor(EXTRA, RANGE, NOTADR, COUNT, BANG, EDITCMD, ARGOPT, TRLBAR),
- addr_type=ADDR_LINES,
+ flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type='ADDR_OTHER',
func='ex_previous',
},
{
command='~',
enum='CMD_tilde',
flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, MODIFY),
- addr_type=ADDR_LINES,
+ addr_type='ADDR_LINES',
func='ex_substitute',
},
}
+
+return module
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 3b9c44c3cd..c400975108 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2113,7 +2113,7 @@ void ex_listdo(exarg_T *eap)
}
} else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
|| eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) {
- qf_size = qf_get_size(eap);
+ qf_size = qf_get_valid_size(eap);
assert(eap->line1 >= 0);
if (qf_size == 0 || (size_t)eap->line1 > qf_size) {
buf = NULL;
@@ -3392,7 +3392,7 @@ void ex_checktime(exarg_T *eap)
} else {
buf = buflist_findnr((int)eap->line2);
if (buf != NULL) { // cannot happen?
- (void)buf_check_timestamp(buf, false);
+ (void)buf_check_timestamp(buf);
}
}
no_check_timestamps = save_no_check_timestamps;
@@ -3790,6 +3790,14 @@ void ex_drop(exarg_T *eap)
if (wp->w_buffer == buf) {
goto_tabpage_win(tp, wp);
curwin->w_arg_idx = 0;
+ if (!bufIsChanged(curbuf)) {
+ const int save_ar = curbuf->b_p_ar;
+
+ // reload the file if it is newer
+ curbuf->b_p_ar = 1;
+ buf_check_timestamp(curbuf);
+ curbuf->b_p_ar = save_ar;
+ }
return;
}
}
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 21db3936b8..ca84d375ce 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -36,46 +36,50 @@
// 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and
// long name of the command.
-#define RANGE 0x001 // allow a linespecs
-#define BANG 0x002 // allow a ! after the command name
-#define EXTRA 0x004 // allow extra args after command name
-#define XFILE 0x008 // expand wildcards in extra part
-#define NOSPC 0x010 // no spaces allowed in the extra part
-#define DFLALL 0x020 // default file range is 1,$
-#define WHOLEFOLD 0x040 // extend range to include whole fold also
- // when less than two numbers given
-#define NEEDARG 0x080 // argument required
-#define TRLBAR 0x100 // check for trailing vertical bar
-#define REGSTR 0x200 // allow "x for register designation
-#define COUNT 0x400 // allow count in argument, after command
-#define NOTRLCOM 0x800 // no trailing comment allowed
-#define ZEROR 0x1000 // zero line number allowed
-#define USECTRLV 0x2000 // do not remove CTRL-V from argument
-#define NOTADR 0x4000 // number before command is not an address
-#define EDITCMD 0x8000 // allow "+command" argument
-#define BUFNAME 0x10000 // accepts buffer name
-#define BUFUNL 0x20000 // accepts unlisted buffer too
-#define ARGOPT 0x40000 // allow "++opt=val" argument
-#define SBOXOK 0x80000 // allowed in the sandbox
-#define CMDWIN 0x100000 // allowed in cmdline window; when missing
- // disallows editing another buffer when
- // curbuf_lock is set
-#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer
-#define EXFLAGS 0x400000 // allow flags after count in argument
-#define FILES (XFILE | EXTRA) // multiple extra files allowed
-#define WORD1 (EXTRA | NOSPC) // one extra word allowed
-#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file
+#define EX_RANGE 0x001 // allow a linespecs
+#define EX_BANG 0x002 // allow a ! after the command name
+#define EX_EXTRA 0x004 // allow extra args after command name
+#define EX_XFILE 0x008 // expand wildcards in extra part
+#define EX_NOSPC 0x010 // no spaces allowed in the extra part
+#define EX_DFLALL 0x020 // default file range is 1,$
+#define EX_WHOLEFOLD 0x040 // extend range to include whole fold also
+ // when less than two numbers given
+#define EX_NEEDARG 0x080 // argument required
+#define EX_TRLBAR 0x100 // check for trailing vertical bar
+#define EX_REGSTR 0x200 // allow "x for register designation
+#define EX_COUNT 0x400 // allow count in argument, after command
+#define EX_NOTRLCOM 0x800 // no trailing comment allowed
+#define EX_ZEROR 0x1000 // zero line number allowed
+#define EX_CTRLV 0x2000 // do not remove CTRL-V from argument
+#define EX_CMDARG 0x4000 // allow "+command" argument
+#define EX_BUFNAME 0x8000 // accepts buffer name
+#define EX_BUFUNL 0x10000 // accepts unlisted buffer too
+#define EX_ARGOPT 0x20000 // allow "++opt=val" argument
+#define EX_SBOXOK 0x40000 // allowed in the sandbox
+#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing
+ // disallows editing another buffer when
+ // curbuf_lock is set
+#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
+#define EX_FLAGS 0x200000 // allow flags after count in argument
+#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
+#define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file
+#define EX_WORD1 (EX_EXTRA | EX_NOSPC) // one extra word allowed
// values for cmd_addr_type
-#define ADDR_LINES 0
-#define ADDR_WINDOWS 1
-#define ADDR_ARGUMENTS 2
-#define ADDR_LOADED_BUFFERS 3
-#define ADDR_BUFFERS 4
-#define ADDR_TABS 5
-#define ADDR_TABS_RELATIVE 6 // Tab page that only relative
-#define ADDR_QUICKFIX 7
-#define ADDR_OTHER 99
+typedef enum {
+ ADDR_LINES, // buffer line numbers
+ ADDR_WINDOWS, // window number
+ ADDR_ARGUMENTS, // argument number
+ ADDR_LOADED_BUFFERS, // buffer number of loaded buffer
+ ADDR_BUFFERS, // buffer number
+ ADDR_TABS, // tab page number
+ ADDR_TABS_RELATIVE, // Tab page that only relative
+ ADDR_QUICKFIX_VALID, // quickfix list valid entry number
+ ADDR_QUICKFIX, // quickfix list entry number
+ ADDR_UNSIGNED, // positive count or zero, defaults to 1
+ ADDR_OTHER, // something else, use line number for '$', '%', etc.
+ ADDR_NONE // no range used
+} cmd_addr_T;
typedef struct exarg exarg_T;
@@ -93,7 +97,7 @@ typedef struct cmdname {
char_u *cmd_name; ///< Name of the command.
ex_func_T cmd_func; ///< Function with implementation of this command.
uint32_t cmd_argt; ///< Relevant flags from the declared above.
- int cmd_addr_type; ///< Flag for address type
+ cmd_addr_T cmd_addr_type; ///< Flag for address type
} CommandDefinition;
// A list used for saving values of "emsg_silent". Used by ex_try() to save the
@@ -150,7 +154,7 @@ struct exarg {
int addr_count; ///< the number of addresses given
linenr_T line1; ///< the first line number
linenr_T line2; ///< the second line number or count
- int addr_type; ///< type of the count/range
+ cmd_addr_T addr_type; ///< type of the count/range
int flags; ///< extra flags after count: EXFLAG_
char_u *do_ecmd_cmd; ///< +command arg to be used in edited file
linenr_T do_ecmd_lnum; ///< the line number in an edited file
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0ffe67a4db..ccf7dd0f68 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -85,7 +85,7 @@ typedef struct ucmd {
char_u *uc_rep; // The command's replacement string
long uc_def; // The default value for a range/count
int uc_compl; // completion type
- int uc_addr_type; // The command's address type
+ cmd_addr_T uc_addr_type; // The command's address type
sctx_T uc_script_ctx; // SCTX where the command was defined
char_u *uc_compl_arg; // completion argument if any
} ucmd_T;
@@ -1086,7 +1086,10 @@ static int compute_buffer_local_count(int addr_type, int lnum, int offset)
return buf->b_fnum;
}
-static int current_win_nr(win_T *win)
+// Return the window number of "win".
+// When "win" is NULL return the number of windows.
+static int current_win_nr(const win_T *win)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int nr = 0;
@@ -1163,7 +1166,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case 'd':
case Ctrl_D:
// window size or any count
- eap->addr_type = ADDR_LINES; // -V1037
+ eap->addr_type = ADDR_OTHER; // -V1037
break;
case Ctrl_HAT:
@@ -1199,7 +1202,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case '=':
case CAR:
// no count
- eap->addr_type = 0;
+ eap->addr_type = ADDR_NONE;
break;
}
}
@@ -1380,6 +1383,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if (ea.cmdidx == CMD_wincmd && p != NULL) {
get_wincmd_addr_type(skipwhite(p), &ea);
}
+ // :.cc in quickfix window uses line number
+ if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf)) {
+ ea.addr_type = ADDR_OTHER;
+ }
}
ea.cmd = cmd;
@@ -1411,7 +1418,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) {
ea.cmdidx = CMD_print;
- ea.argt = RANGE | COUNT | TRLBAR;
+ ea.argt = EX_RANGE | EX_COUNT | EX_TRLBAR;
if ((errormsg = invalid_range(&ea)) == NULL) {
correct_range(&ea);
ex_print(&ea);
@@ -1490,20 +1497,18 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.forceit = false;
}
- /*
- * 6. Parse arguments.
- */
+ // 6. Parse arguments. Then check for errors.
if (!IS_USER_CMDIDX(ea.cmdidx)) {
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
}
if (!ea.skip) {
- if (sandbox != 0 && !(ea.argt & SBOXOK)) {
+ if (sandbox != 0 && !(ea.argt & EX_SBOXOK)) {
// Command not allowed in sandbox.
errormsg = (char_u *)_(e_sandbox);
goto doend;
}
- if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY)
+ if (!MODIFIABLE(curbuf) && (ea.argt & EX_MODIFY)
// allow :put in terminals
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) {
/* Command not allowed in non-'modifiable' buffer */
@@ -1511,7 +1516,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (text_locked() && !(ea.argt & CMDWIN)
+ if (text_locked() && !(ea.argt & EX_CMDWIN)
&& !IS_USER_CMDIDX(ea.cmdidx)) {
// Command not allowed when editing the command line.
errormsg = (char_u *)_(get_text_locked_msg());
@@ -1522,7 +1527,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
// Do allow ":checktime" (it is postponed).
// Do allow ":edit" (check for an argument later).
// Do allow ":file" with no arguments (check for an argument later).
- if (!(ea.argt & CMDWIN)
+ if (!(ea.argt & EX_CMDWIN)
&& ea.cmdidx != CMD_checktime
&& ea.cmdidx != CMD_edit
&& ea.cmdidx != CMD_file
@@ -1531,14 +1536,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) {
- /* no range allowed */
+ if (!ni && !(ea.argt & EX_RANGE) && ea.addr_count > 0) {
+ // no range allowed
errormsg = (char_u *)_(e_norange);
goto doend;
}
}
- if (!ni && !(ea.argt & BANG) && ea.forceit) { /* no <!> allowed */
+ if (!ni && !(ea.argt & EX_BANG) && ea.forceit) { // no <!> allowed
errormsg = (char_u *)_(e_nobang);
goto doend;
}
@@ -1547,12 +1552,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Don't complain about the range if it is not used
* (could happen if line_count is accidentally set to 0).
*/
- if (!ea.skip && !ni) {
- /*
- * If the range is backwards, ask for confirmation and, if given, swap
- * ea.line1 & ea.line2 so it's forwards again.
- * When global command is busy, don't ask, will fail below.
- */
+ if (!ea.skip && !ni && (ea.argt & EX_RANGE)) {
+ // If the range is backwards, ask for confirmation and, if given, swap
+ // ea.line1 & ea.line2 so it's forwards again.
+ // When global command is busy, don't ask, will fail below.
if (!global_busy && ea.line1 > ea.line2) {
if (msg_silent == 0) {
if ((flags & DOCMD_VERBOSE) || exmode_active) {
@@ -1571,12 +1574,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
+ if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0) {
+ // default is 1, not cursor
ea.line2 = 1;
+ }
correct_range(&ea);
- if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
+ if (((ea.argt & EX_WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
&& ea.addr_type == ADDR_LINES) {
// Put the first line at the start of a closed fold, put the last line
// at the end of a closed fold.
@@ -1610,12 +1615,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "++opt=val" argument.
* Must be first, allow ":w ++enc=utf8 !cmd"
*/
- if (ea.argt & ARGOPT)
- while (ea.arg[0] == '+' && ea.arg[1] == '+')
+ if (ea.argt & EX_ARGOPT) {
+ while (ea.arg[0] == '+' && ea.arg[1] == '+') {
if (getargopt(&ea) == FAIL && !ni) {
errormsg = (char_u *)_(e_invarg);
goto doend;
}
+ }
+ }
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
if (*ea.arg == '>') { /* append */
@@ -1654,14 +1661,15 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "+command" argument, before checking for next command.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & EDITCMD) && !ea.usefilter)
+ if ((ea.argt & EX_CMDARG) && !ea.usefilter) {
ea.do_ecmd_cmd = getargcmd(&ea.arg);
+ }
/*
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !ea.usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !ea.usefilter) {
separate_nextcmd(&ea);
} else if (ea.cmdidx == CMD_bang
|| ea.cmdidx == CMD_terminal
@@ -1688,12 +1696,13 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if ((ea.argt & DFLALL) && ea.addr_count == 0) {
+ if ((ea.argt & EX_DFLALL) && ea.addr_count == 0) {
buf_T *buf;
ea.line1 = 1;
switch (ea.addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
ea.line2 = curbuf->b_ml.ml_line_count;
break;
case ADDR_LOADED_BUFFERS:
@@ -1728,21 +1737,27 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
- ea.line2 = qf_get_size(&ea);
+ case ADDR_QUICKFIX_VALID:
+ ea.line2 = qf_get_valid_size(&ea);
if (ea.line2 == 0) {
ea.line2 = 1;
}
break;
+ case ADDR_NONE:
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
+ IEMSG(_("INTERNAL: Cannot use EX_DFLALL "
+ "with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
+ break;
}
}
- /* accept numbered register only when no count allowed (:put) */
- if ((ea.argt & REGSTR)
+ // accept numbered register only when no count allowed (:put)
+ if ((ea.argt & EX_REGSTR)
&& *ea.arg != NUL
/* Do not allow register = for user commands */
&& (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
- && !((ea.argt & COUNT) && ascii_isdigit(*ea.arg))) {
+ && !((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg))) {
if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
&& !IS_USER_CMDIDX(ea.cmdidx)))) {
ea.regname = *ea.arg++;
@@ -1756,19 +1771,19 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
//
- // Check for a count. When accepting a BUFNAME, don't use "123foo" as a
+ // Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
// count, it's a buffer name.
///
- if ((ea.argt & COUNT) && ascii_isdigit(*ea.arg)
- && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
+ if ((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg)
+ && (!(ea.argt & EX_BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
|| ascii_iswhite(*p))) {
n = getdigits_long(&ea.arg, false, -1);
ea.arg = skipwhite(ea.arg);
- if (n <= 0 && !ni && (ea.argt & ZEROR) == 0) {
+ if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0) {
errormsg = (char_u *)_(e_zerocount);
goto doend;
}
- if (ea.argt & NOTADR) { /* e.g. :buffer 2, :sleep 3 */
+ if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
ea.line2 = n;
if (ea.addr_count == 0)
ea.addr_count = 1;
@@ -1777,8 +1792,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 += n - 1;
++ea.addr_count;
// Be vi compatible: no error message for out of range.
- if (ea.addr_type == ADDR_LINES
- && ea.line2 > curbuf->b_ml.ml_line_count) {
+ if (ea.line2 > curbuf->b_ml.ml_line_count) {
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
@@ -1787,16 +1801,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
/*
* Check for flags: 'l', 'p' and '#'.
*/
- if (ea.argt & EXFLAGS)
+ if (ea.argt & EX_FLAGS) {
get_flags(&ea);
- /* no arguments allowed */
- if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL
- && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & TRLBAR) == 0)) {
+ }
+ if (!ni && !(ea.argt & EX_EXTRA) && *ea.arg != NUL
+ && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & EX_TRLBAR) == 0)) {
+ // no arguments allowed but there is something
errormsg = (char_u *)_(e_trailing);
goto doend;
}
- if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL) {
+ if (!ni && (ea.argt & EX_NEEDARG) && *ea.arg == NUL) {
errormsg = (char_u *)_(e_argreq);
goto doend;
}
@@ -1825,9 +1840,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case CMD_function:
break;
- /* Commands that handle '|' themselves. Check: A command should
- * either have the TRLBAR flag, appear in this list or appear in
- * the list at ":help :bar". */
+ // Commands that handle '|' themselves. Check: A command should
+ // either have the EX_TRLBAR flag, appear in this list or appear in
+ // the list at ":help :bar".
case CMD_aboveleft:
case CMD_and:
case CMD_belowright:
@@ -1898,16 +1913,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if (ea.argt & XFILE) {
- if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
+ if (ea.argt & EX_XFILE) {
+ if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) {
goto doend;
+ }
}
/*
* Accept buffer name. Cannot be used at the same time with a buffer
* number. Don't do this for a user command.
*/
- if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
+ if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
&& !IS_USER_CMDIDX(ea.cmdidx)
) {
/*
@@ -1923,10 +1939,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
while (p > ea.arg && ascii_iswhite(p[-1]))
--p;
}
- ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0,
- FALSE, FALSE);
- if (ea.line2 < 0) /* failed */
+ ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0,
+ false, false);
+ if (ea.line2 < 0) { // failed
goto doend;
+ }
ea.addr_count = 1;
ea.arg = skipwhite(p);
}
@@ -2322,6 +2339,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line1 = eap->line2;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
// default is current line number
eap->line2 = curwin->w_cursor.lnum;
break;
@@ -2342,11 +2360,18 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
eap->line2 = 1;
break;
case ADDR_QUICKFIX:
+ eap->line2 = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
eap->line2 = qf_get_cur_valid_idx(eap);
break;
+ case ADDR_NONE:
+ // Will give an error later if a range is found.
+ break;
}
eap->cmd = skipwhite(eap->cmd);
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip, silent,
@@ -2359,6 +2384,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->cmd++;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
eap->line1 = 1;
eap->line2 = curbuf->b_ml.ml_line_count;
break;
@@ -2394,7 +2420,8 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
}
break;
case ADDR_TABS_RELATIVE:
- case ADDR_OTHER:
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
*errormsg = (char_u *)_(e_invrange);
return FAIL;
case ADDR_ARGUMENTS:
@@ -2405,13 +2432,16 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
+ case ADDR_QUICKFIX_VALID:
eap->line1 = 1;
- eap->line2 = qf_get_size(eap);
+ eap->line2 = qf_get_valid_size(eap);
if (eap->line2 == 0) {
eap->line2 = 1;
}
break;
+ case ADDR_NONE:
+ // Will give an error later if a range is found.
+ break;
}
eap->addr_count++;
} else if (*eap->cmd == '*') {
@@ -2513,14 +2543,13 @@ static void append_command(char_u *cmd)
*d = NUL;
}
-/*
- * Find an Ex command by its name, either built-in or user.
- * Start of the name can be found at eap->cmd.
- * Returns pointer to char after the command name.
- * "full" is set to TRUE if the whole command name matched.
- * Returns NULL for an ambiguous user command.
- */
+// Find an Ex command by its name, either built-in or user.
+// Start of the name can be found at eap->cmd.
+// Sets eap->cmdidx and returns a pointer to char after the command name.
+// "full" is set to TRUE if the whole command name matched.
+// Returns NULL for an ambiguous user command.
static char_u *find_command(exarg_T *eap, int *full)
+ FUNC_ATTR_NONNULL_ARG(1)
{
int len;
char_u *p;
@@ -2970,6 +2999,15 @@ const char * set_one_cmd_context(
const char *arg = (const char *)skipwhite((const char_u *)p);
+ // Skip over ++argopt argument
+ if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
+ p = arg;
+ while (*p && !ascii_isspace(*p)) {
+ MB_PTR_ADV(p);
+ }
+ arg = (const char *)skipwhite((const char_u *)p);
+ }
+
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
if (*arg == '>') { // Append.
if (*++arg == '>') {
@@ -2997,9 +3035,9 @@ const char * set_one_cmd_context(
arg = (const char *)skipwhite((const char_u *)arg);
}
- /* Does command allow "+command"? */
- if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
- /* Check if we're in the +command */
+ // Does command allow "+command"?
+ if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') {
+ // Check if we're in the +command
p = arg + 1;
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
@@ -3015,17 +3053,19 @@ const char * set_one_cmd_context(
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !usefilter) {
p = arg;
/* ":redir @" is not the start of a comment */
if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
p += 2;
while (*p) {
if (*p == Ctrl_V) {
- if (p[1] != NUL)
- ++p;
- } else if ( (*p == '"' && !(ea.argt & NOTRLCOM))
- || *p == '|' || *p == '\n') {
+ if (p[1] != NUL) {
+ p++;
+ }
+ } else if ((*p == '"' && !(ea.argt & EX_NOTRLCOM))
+ || *p == '|'
+ || *p == '\n') {
if (*(p - 1) != '\\') {
if (*p == '|' || *p == '\n')
return p + 1;
@@ -3036,8 +3076,8 @@ const char * set_one_cmd_context(
}
}
- // no arguments allowed
- if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ if (!(ea.argt & EX_EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ // no arguments allowed but there is something
return NULL;
}
@@ -3057,7 +3097,7 @@ const char * set_one_cmd_context(
}
}
- if (ea.argt & XFILE) {
+ if (ea.argt & EX_XFILE) {
int c;
int in_quote = false;
const char *bow = NULL; // Beginning of word.
@@ -3478,8 +3518,8 @@ const char * set_one_cmd_context(
case CMD_USER:
case CMD_USER_BUF:
if (context != EXPAND_NOTHING) {
- // XFILE: file names are handled above.
- if (!(ea.argt & XFILE)) {
+ // EX_XFILE: file names are handled above.
+ if (!(ea.argt & EX_XFILE)) {
if (context == EXPAND_MENUS) {
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
(char_u *)arg, forceit);
@@ -3689,6 +3729,15 @@ char_u *skip_range(
return (char_u *)cmd;
}
+static void addr_error(cmd_addr_T addr_type)
+{
+ if (addr_type == ADDR_NONE) {
+ EMSG(_(e_norange));
+ } else {
+ EMSG(_(e_invrange));
+ }
+}
+
// Get a single EX address
//
// Set ptr to the next character after the part that was interpreted.
@@ -3698,11 +3747,12 @@ char_u *skip_range(
// Return MAXLNUM when no Ex address was found.
static linenr_T get_address(exarg_T *eap,
char_u **ptr,
- int addr_type, // flag: one of ADDR_LINES, ...
+ cmd_addr_T addr_type,
int skip, // only skip the address, don't use it
bool silent, // no errors or side effects
int to_other_file, // flag: may jump to other file
int address_count) // 1 for first, >1 after comma
+ FUNC_ATTR_NONNULL_ALL
{
int c;
int i;
@@ -3721,6 +3771,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
@@ -3736,12 +3787,17 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
break;
+ case ADDR_NONE:
case ADDR_TABS_RELATIVE:
- EMSG(_(e_invrange));
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
}
@@ -3751,6 +3807,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curbuf->b_ml.ml_line_count;
break;
case ADDR_WINDOWS:
@@ -3775,8 +3832,10 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = LAST_TAB_NR;
break;
+ case ADDR_NONE:
case ADDR_TABS_RELATIVE:
- EMSG(_(e_invrange));
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
@@ -3786,6 +3845,12 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
}
break;
+ case ADDR_QUICKFIX_VALID:
+ lnum = qf_get_valid_size(eap);
+ if (lnum == 0) {
+ lnum = 1;
+ }
+ break;
}
break;
@@ -3795,7 +3860,7 @@ static linenr_T get_address(exarg_T *eap,
goto error;
}
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3823,7 +3888,7 @@ static linenr_T get_address(exarg_T *eap,
case '?': /* '/' or '?' - search */
c = *cmd++;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3870,7 +3935,7 @@ static linenr_T get_address(exarg_T *eap,
case '\\': /* "\?", "\/" or "\&", repeat search */
++cmd;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3917,7 +3982,9 @@ static linenr_T get_address(exarg_T *eap,
if (lnum == MAXLNUM) {
switch (addr_type) {
case ADDR_LINES:
- lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
+ case ADDR_OTHER:
+ // "+1" is same as ".+1"
+ lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
lnum = CURRENT_WIN_NR;
@@ -3936,8 +4003,15 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
+ case ADDR_NONE:
+ case ADDR_UNSIGNED:
+ lnum = 0;
+ break;
}
}
@@ -4027,12 +4101,11 @@ static char_u *invalid_range(exarg_T *eap)
return (char_u *)_(e_invrange);
}
- if (eap->argt & RANGE) {
- switch(eap->addr_type) {
+ if (eap->argt & EX_RANGE) {
+ switch (eap->addr_type) {
case ADDR_LINES:
- if (!(eap->argt & NOTADR)
- && eap->line2 > curbuf->b_ml.ml_line_count
- + (eap->cmdidx == CMD_diffget)) {
+ if (eap->line2 > (curbuf->b_ml.ml_line_count
+ + (eap->cmdidx == CMD_diffget))) {
return (char_u *)_(e_invrange);
}
break;
@@ -4081,14 +4154,30 @@ static char_u *invalid_range(exarg_T *eap)
}
break;
case ADDR_TABS_RELATIVE:
- // Do nothing
+ case ADDR_OTHER:
+ // Any range is OK.
break;
case ADDR_QUICKFIX:
assert(eap->line2 >= 0);
- if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) {
+ // No error for value that is too big, will use the last entry.
+ if (eap->line2 <= 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_QUICKFIX_VALID:
+ if ((eap->line2 != 1 && (size_t)eap->line2 > qf_get_valid_size(eap))
+ || eap->line2 < 0) {
return (char_u *)_(e_invrange);
}
break;
+ case ADDR_UNSIGNED:
+ if (eap->line2 < 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_NONE:
+ // Will give an error elsewhere.
+ break;
}
}
return NULL;
@@ -4099,11 +4188,13 @@ static char_u *invalid_range(exarg_T *eap)
*/
static void correct_range(exarg_T *eap)
{
- if (!(eap->argt & ZEROR)) { /* zero in range not allowed */
- if (eap->line1 == 0)
+ if (!(eap->argt & EX_ZEROR)) { // zero in range not allowed
+ if (eap->line1 == 0) {
eap->line1 = 1;
- if (eap->line2 == 0)
+ }
+ if (eap->line2 == 0) {
eap->line2 = 1;
+ }
}
}
@@ -4270,7 +4361,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lmake
&& eap->cmdidx != CMD_make
&& eap->cmdidx != CMD_terminal
- && !(eap->argt & NOSPC)
+ && !(eap->argt & EX_NOSPC)
) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
@@ -4311,7 +4402,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
* One file argument: Expand wildcards.
* Don't do this with ":r !command" or ":w !command".
*/
- if ((eap->argt & NOSPC) && !eap->usefilter) {
+ if ((eap->argt & EX_NOSPC) && !eap->usefilter) {
// Replace environment variables.
if (has_wildcards) {
/*
@@ -4424,38 +4515,39 @@ void separate_nextcmd(exarg_T *eap)
for (; *p; MB_PTR_ADV(p)) {
if (*p == Ctrl_V) {
- if (eap->argt & (USECTRLV | XFILE))
- ++p; /* skip CTRL-V and next char */
- else
- /* remove CTRL-V and skip next char */
+ if (eap->argt & (EX_CTRLV | EX_XFILE)) {
+ p++; // skip CTRL-V and next char
+ } else {
+ // remove CTRL-V and skip next char
STRMOVE(p, p + 1);
- if (*p == NUL) /* stop at NUL after CTRL-V */
+ }
+ if (*p == NUL) { // stop at NUL after CTRL-V
break;
- }
- /* Skip over `=expr` when wildcards are expanded. */
- else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) {
+ }
+ } else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE)) {
+ // Skip over `=expr` when wildcards are expanded.
p += 2;
(void)skip_expr(&p);
if (*p == NUL) { // stop at NUL after CTRL-V
break;
}
- }
- /* Check for '"': start of comment or '|': next command */
- /* :@" does not start a comment!
- * :redir @" doesn't either. */
- else if ((*p == '"' && !(eap->argt & NOTRLCOM)
- && (eap->cmdidx != CMD_at || p != eap->arg)
- && (eap->cmdidx != CMD_redir
- || p != eap->arg + 1 || p[-1] != '@'))
- || *p == '|' || *p == '\n') {
- /*
- * We remove the '\' before the '|', unless USECTRLV is used
- * AND 'b' is present in 'cpoptions'.
- */
+ } else if (
+ // Check for '"': start of comment or '|': next command */
+ // :@" does not start a comment!
+ // :redir @" doesn't either.
+ (*p == '"'
+ && !(eap->argt & EX_NOTRLCOM)
+ && (eap->cmdidx != CMD_at || p != eap->arg)
+ && (eap->cmdidx != CMD_redir
+ || p != eap->arg + 1 || p[-1] != '@'))
+ || *p == '|'
+ || *p == '\n') {
+ // We remove the '\' before the '|', unless EX_CTRLV is used
+ // AND 'b' is present in 'cpoptions'.
if ((vim_strchr(p_cpo, CPO_BAR) == NULL
- || !(eap->argt & USECTRLV)) && *(p - 1) == '\\') {
- STRMOVE(p - 1, p); /* remove the '\' */
- --p;
+ || !(eap->argt & EX_CTRLV)) && *(p - 1) == '\\') {
+ STRMOVE(p - 1, p); // remove the '\'
+ p--;
} else {
eap->nextcmd = check_nextcmd(p);
*p = NUL;
@@ -4464,8 +4556,9 @@ void separate_nextcmd(exarg_T *eap)
}
}
- if (!(eap->argt & NOTRLCOM)) /* remove trailing spaces */
+ if (!(eap->argt & EX_NOTRLCOM)) { // remove trailing spaces
del_trailing_spaces(eap->arg);
+ }
}
/*
@@ -4742,10 +4835,8 @@ static void ex_abclear(exarg_T *eap)
static void ex_autocmd(exarg_T *eap)
{
- /*
- * Disallow auto commands from .exrc and .vimrc in current
- * directory for security reasons.
- */
+ // Disallow autocommands from .exrc and .vimrc in current
+ // directory for security reasons.
if (secure) {
secure = 2;
eap->errmsg = e_curdir;
@@ -4957,10 +5048,10 @@ char_u *get_command_name(expand_T *xp, int idx)
static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
uint32_t argt, long def, int flags, int compl,
- char_u *compl_arg, int addr_type, int force)
+ char_u *compl_arg, cmd_addr_T addr_type, bool force)
+ FUNC_ATTR_NONNULL_ARG(1, 3)
{
ucmd_T *cmd = NULL;
- char_u *p;
int i;
int cmp = 1;
char_u *rep_buf = NULL;
@@ -5020,7 +5111,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep,
if (cmp != 0) {
ga_grow(gap, 1);
- p = vim_strnsave(name, (int)name_len);
+ char_u *const p = vim_strnsave(name, name_len);
cmd = USER_CMD_GA(gap, i);
memmove(cmd + 1, cmd, (gap->ga_len - i) * sizeof(ucmd_T));
@@ -5049,7 +5140,7 @@ fail:
static struct {
- int expand;
+ cmd_addr_T expand;
char *name;
char *shortname;
} addr_type_complete[] =
@@ -5062,7 +5153,7 @@ static struct {
{ ADDR_WINDOWS, "windows", "win" },
{ ADDR_QUICKFIX, "quickfix", "qf" },
{ ADDR_OTHER, "other", "?" },
- { -1, NULL, NULL }
+ { ADDR_NONE, NULL, NULL }
};
/*
@@ -5156,11 +5247,11 @@ static void uc_list(char_u *name, size_t name_len)
// Special cases
int len = 4;
- if (a & BANG) {
+ if (a & EX_BANG) {
msg_putchar('!');
len--;
}
- if (a & REGSTR) {
+ if (a & EX_REGSTR) {
msg_putchar('"');
len--;
}
@@ -5168,7 +5259,7 @@ static void uc_list(char_u *name, size_t name_len)
msg_putchar('b');
len--;
}
- if (a & TRLBAR) {
+ if (a & EX_TRLBAR) {
msg_putchar('|');
len--;
}
@@ -5190,20 +5281,20 @@ static void uc_list(char_u *name, size_t name_len)
len = 0;
// Arguments
- switch (a & (EXTRA|NOSPC|NEEDARG)) {
+ switch (a & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case 0:
IObuff[len++] = '0';
break;
- case (EXTRA):
+ case (EX_EXTRA):
IObuff[len++] = '*';
break;
- case (EXTRA|NOSPC):
+ case (EX_EXTRA | EX_NOSPC):
IObuff[len++] = '?';
break;
- case (EXTRA|NEEDARG):
+ case (EX_EXTRA | EX_NEEDARG):
IObuff[len++] = '+';
break;
- case (EXTRA|NOSPC|NEEDARG):
+ case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
IObuff[len++] = '1';
break;
}
@@ -5213,13 +5304,13 @@ static void uc_list(char_u *name, size_t name_len)
} while (len < 5 - over);
// Address / Range
- if (a & (RANGE|COUNT)) {
- if (a & COUNT) {
+ if (a & (EX_RANGE | EX_COUNT)) {
+ if (a & EX_COUNT) {
// -count=N
snprintf((char *)IObuff + len, IOSIZE, "%" PRId64 "c",
(int64_t)cmd->uc_def);
len += (int)STRLEN(IObuff + len);
- } else if (a & DFLALL) {
+ } else if (a & EX_DFLALL) {
IObuff[len++] = '%';
} else if (cmd->uc_def >= 0) {
// -range=N
@@ -5236,7 +5327,7 @@ static void uc_list(char_u *name, size_t name_len)
} while (len < 8 - over);
// Address Type
- for (j = 0; addr_type_complete[j].expand != -1; j++) {
+ for (j = 0; addr_type_complete[j].expand != ADDR_NONE; j++) {
if (addr_type_complete[j].expand != ADDR_LINES
&& addr_type_complete[j].expand == cmd->uc_addr_type) {
STRCPY(IObuff + len, addr_type_complete[j].shortname);
@@ -5284,7 +5375,8 @@ static void uc_list(char_u *name, size_t name_len)
static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
int *flags, int *complp, char_u **compl_arg,
- int *addr_type_arg)
+ cmd_addr_T *addr_type_arg)
+ FUNC_ATTR_NONNULL_ALL
{
char_u *p;
@@ -5293,16 +5385,16 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
return FAIL;
}
- /* First, try the simple attributes (no arguments) */
- if (STRNICMP(attr, "bang", len) == 0)
- *argt |= BANG;
- else if (STRNICMP(attr, "buffer", len) == 0)
+ // First, try the simple attributes (no arguments)
+ if (STRNICMP(attr, "bang", len) == 0) {
+ *argt |= EX_BANG;
+ } else if (STRNICMP(attr, "buffer", len) == 0) {
*flags |= UC_BUFFER;
- else if (STRNICMP(attr, "register", len) == 0)
- *argt |= REGSTR;
- else if (STRNICMP(attr, "bar", len) == 0)
- *argt |= TRLBAR;
- else {
+ } else if (STRNICMP(attr, "register", len) == 0) {
+ *argt |= EX_REGSTR;
+ } else if (STRNICMP(attr, "bar", len) == 0) {
+ *argt |= EX_TRLBAR;
+ } else {
int i;
char_u *val = NULL;
size_t vallen = 0;
@@ -5320,28 +5412,29 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
if (STRNICMP(attr, "nargs", attrlen) == 0) {
if (vallen == 1) {
- if (*val == '0')
- /* Do nothing - this is the default */;
- else if (*val == '1')
- *argt |= (EXTRA | NOSPC | NEEDARG);
- else if (*val == '*')
- *argt |= EXTRA;
- else if (*val == '?')
- *argt |= (EXTRA | NOSPC);
- else if (*val == '+')
- *argt |= (EXTRA | NEEDARG);
- else
+ if (*val == '0') {
+ // Do nothing - this is the default;
+ } else if (*val == '1') {
+ *argt |= (EX_EXTRA | EX_NOSPC | EX_NEEDARG);
+ } else if (*val == '*') {
+ *argt |= EX_EXTRA;
+ } else if (*val == '?') {
+ *argt |= (EX_EXTRA | EX_NOSPC);
+ } else if (*val == '+') {
+ *argt |= (EX_EXTRA | EX_NEEDARG);
+ } else {
goto wrong_nargs;
+ }
} else {
wrong_nargs:
EMSG(_("E176: Invalid number of arguments"));
return FAIL;
}
} else if (STRNICMP(attr, "range", attrlen) == 0) {
- *argt |= RANGE;
- if (vallen == 1 && *val == '%')
- *argt |= DFLALL;
- else if (val != NULL) {
+ *argt |= EX_RANGE;
+ if (vallen == 1 && *val == '%') {
+ *argt |= EX_DFLALL;
+ } else if (val != NULL) {
p = val;
if (*def >= 0) {
two_count:
@@ -5350,7 +5443,7 @@ two_count:
}
*def = getdigits_long(&p, true, 0);
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
if (p != val + vallen || vallen == 0) {
invalid_count:
@@ -5358,8 +5451,16 @@ invalid_count:
return FAIL;
}
}
+ // default for -range is using buffer lines
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_LINES;
+ }
} else if (STRNICMP(attr, "count", attrlen) == 0) {
- *argt |= (COUNT | ZEROR | RANGE | NOTADR);
+ *argt |= (EX_COUNT | EX_ZEROR | EX_RANGE);
+ // default for -count is using any number
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_OTHER;
+ }
if (val != NULL) {
p = val;
@@ -5385,16 +5486,16 @@ invalid_count:
return FAIL;
}
} else if (STRNICMP(attr, "addr", attrlen) == 0) {
- *argt |= RANGE;
+ *argt |= EX_RANGE;
if (val == NULL) {
EMSG(_("E179: argument required for -addr"));
return FAIL;
}
- if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) == FAIL) {
+ if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL) {
return FAIL;
}
if (*addr_type_arg != ADDR_LINES) {
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
}
} else {
char_u ch = attr[len];
@@ -5421,7 +5522,7 @@ static void ex_command(exarg_T *eap)
int flags = 0;
int compl = EXPAND_NOTHING;
char_u *compl_arg = NULL;
- int addr_type_arg = ADDR_LINES;
+ cmd_addr_T addr_type_arg = ADDR_NONE;
int has_attr = (eap->arg[0] == '-');
int name_len;
@@ -5698,8 +5799,9 @@ uc_check_code(
/* When specified there is a single argument don't split it.
* Works for ":Cmd %" when % is "a b c". */
- if ((eap->argt & NOSPC) && quote == 2)
+ if ((eap->argt & EX_NOSPC) && quote == 2) {
quote = 1;
+ }
switch (quote) {
case 0: /* No quoting, no splitting */
@@ -6079,12 +6181,12 @@ char_u *get_user_cmd_complete(expand_T *xp, int idx)
/*
* Parse address type argument
*/
-int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
- int *addr_type_arg)
+int parse_addr_type_arg(char_u *value, int vallen, cmd_addr_T *addr_type_arg)
+ FUNC_ATTR_NONNULL_ALL
{
int i, a, b;
- for (i = 0; addr_type_complete[i].expand != -1; i++) {
+ for (i = 0; addr_type_complete[i].expand != ADDR_NONE; i++) {
a = (int)STRLEN(addr_type_complete[i].name) == vallen;
b = STRNCMP(value, addr_type_complete[i].name, vallen) == 0;
if (a && b) {
@@ -6093,7 +6195,7 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
}
}
- if (addr_type_complete[i].expand == -1) {
+ if (addr_type_complete[i].expand == ADDR_NONE) {
char_u *err = value;
for (i = 0; err[i] != NUL && !ascii_iswhite(err[i]); i++) {}
@@ -6102,9 +6204,6 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
return FAIL;
}
- if (*addr_type_arg != ADDR_LINES)
- *argt |= NOTADR;
-
return OK;
}
@@ -6117,6 +6216,7 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
*/
int parse_compl_arg(const char_u *value, int vallen, int *complp,
uint32_t *argt, char_u **compl_arg)
+ FUNC_ATTR_NONNULL_ALL
{
const char_u *arg = NULL;
size_t arglen = 0;
@@ -6141,9 +6241,9 @@ int parse_compl_arg(const char_u *value, int vallen, int *complp,
&& STRNCMP(value, command_complete[i], valend) == 0) {
*complp = i;
if (i == EXPAND_BUFFERS) {
- *argt |= BUFNAME;
+ *argt |= EX_BUFNAME;
} else if (i == EXPAND_DIRECTORIES || i == EXPAND_FILES) {
- *argt |= XFILE;
+ *argt |= EX_XFILE;
}
break;
}
@@ -6166,8 +6266,9 @@ int parse_compl_arg(const char_u *value, int vallen, int *complp,
return FAIL;
}
- if (arg != NULL)
- *compl_arg = vim_strnsave(arg, (int)arglen);
+ if (arg != NULL) {
+ *compl_arg = vim_strnsave(arg, arglen);
+ }
return OK;
}
@@ -7340,7 +7441,7 @@ static void ex_syncbind(exarg_T *eap)
topline = curwin->w_topline;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_scb && wp->w_buffer) {
- y = wp->w_buffer->b_ml.ml_line_count - get_scrolloff_value();
+ y = wp->w_buffer->b_ml.ml_line_count - get_scrolloff_value(curwin);
if (topline > y) {
topline = y;
}
@@ -7394,11 +7495,12 @@ static void ex_read(exarg_T *eap)
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
linenr_T lnum;
- if (eap->usefilter) /* :r!cmd */
- do_bang(1, eap, FALSE, FALSE, TRUE);
- else {
- if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
+ if (eap->usefilter) { // :r!cmd
+ do_bang(1, eap, false, false, true);
+ } else {
+ if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
+ }
if (*eap->arg == NUL) {
if (check_fname() == FAIL) /* check for no file name */
@@ -7770,7 +7872,7 @@ static void ex_copymove(exarg_T *eap)
* move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
*/
if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count) {
- EMSG(_(e_invaddr));
+ EMSG(_(e_invrange));
return;
}
@@ -7868,7 +7970,7 @@ static void ex_at(exarg_T *eap)
*/
static void ex_bang(exarg_T *eap)
{
- do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
+ do_bang(eap->addr_count, eap, eap->forceit, true, true);
}
/*
@@ -8028,7 +8130,7 @@ static void ex_redraw(exarg_T *eap)
RedrawingDisabled = 0;
p_lz = FALSE;
validate_cursor();
- update_topline();
+ update_topline(curwin);
if (eap->forceit) {
redraw_all_later(NOT_VALID);
}
@@ -8177,10 +8279,11 @@ static void ex_mark(exarg_T *eap)
*/
void update_topline_cursor(void)
{
- check_cursor(); /* put cursor on valid line */
- update_topline();
- if (!curwin->w_p_wrap)
+ check_cursor(); // put cursor on valid line
+ update_topline(curwin);
+ if (!curwin->w_p_wrap) {
validate_cursor();
+ }
update_curswant();
}
@@ -8617,6 +8720,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
* '#' to curwin->w_altfile
* '<cword>' to word under the cursor
* '<cWORD>' to WORD under the cursor
+ * '<cexpr>' to C-expression under the cursor
* '<cfile>' to path name under the cursor
* '<sfile>' to sourced file name
* '<slnum>' to sourced file line number
@@ -9260,7 +9364,7 @@ static void ex_match(exarg_T *eap)
} else {
p = skiptowhite(eap->arg);
if (!eap->skip) {
- g = vim_strnsave(eap->arg, (int)(p - eap->arg));
+ g = vim_strnsave(eap->arg, p - eap->arg);
}
p = skipwhite(p);
if (*p == NUL) {
@@ -9445,16 +9549,16 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "name", STRING_OBJ(cstr_to_string((char *)cmd->uc_name)));
PUT(d, "definition", STRING_OBJ(cstr_to_string((char *)cmd->uc_rep)));
PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
- PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & BANG)));
- PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & TRLBAR)));
- PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & REGSTR)));
+ PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
+ PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+ PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
- switch (cmd->uc_argt & (EXTRA|NOSPC|NEEDARG)) {
- case 0: arg[0] = '0'; break;
- case(EXTRA): arg[0] = '*'; break;
- case(EXTRA|NOSPC): arg[0] = '?'; break;
- case(EXTRA|NEEDARG): arg[0] = '+'; break;
- case(EXTRA|NOSPC|NEEDARG): arg[0] = '1'; break;
+ switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
+ case 0: arg[0] = '0'; break;
+ case(EX_EXTRA): arg[0] = '*'; break;
+ case(EX_EXTRA | EX_NOSPC): arg[0] = '?'; break;
+ case(EX_EXTRA | EX_NEEDARG): arg[0] = '+'; break;
+ case(EX_EXTRA | EX_NOSPC | EX_NEEDARG): arg[0] = '1'; break;
}
PUT(d, "nargs", STRING_OBJ(cstr_to_string(arg)));
@@ -9465,7 +9569,7 @@ Dictionary commands_array(buf_T *buf)
? NIL : STRING_OBJ(cstr_to_string((char *)cmd->uc_compl_arg)));
Object obj = NIL;
- if (cmd->uc_argt & COUNT) {
+ if (cmd->uc_argt & EX_COUNT) {
if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);
obj = STRING_OBJ(cstr_to_string(str)); // -count=N
@@ -9476,8 +9580,8 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "count", obj);
obj = NIL;
- if (cmd->uc_argt & RANGE) {
- if (cmd->uc_argt & DFLALL) {
+ if (cmd->uc_argt & EX_RANGE) {
+ if (cmd->uc_argt & EX_DFLALL) {
obj = STRING_OBJ(cstr_to_string("%")); // -range=%
} else if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);
@@ -9489,7 +9593,7 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "range", obj);
obj = NIL;
- for (int j = 0; addr_type_complete[j].expand != -1; j++) {
+ for (int j = 0; addr_type_complete[j].expand != ADDR_NONE; j++) {
if (addr_type_complete[j].expand != ADDR_LINES
&& addr_type_complete[j].expand == cmd->uc_addr_type) {
obj = STRING_OBJ(cstr_to_string(addr_type_complete[j].name));
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 0c7562980a..0917c6dd02 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -518,10 +518,13 @@ fail:
* Discard an exception. "was_finished" is set when the exception has been
* caught and the catch clause has been ended normally.
*/
-static void discard_exception(except_T *excp, int was_finished)
+static void discard_exception(except_T *excp, bool was_finished)
{
char_u *saved_IObuff;
+ if (current_exception == excp) {
+ current_exception = NULL;
+ }
if (excp == NULL) {
internal_error("discard_exception()");
return;
@@ -569,7 +572,6 @@ void discard_current_exception(void)
{
if (current_exception != NULL) {
discard_exception(current_exception, false);
- current_exception = NULL;
}
// Note: all globals manipulated here should be saved/restored in
// try_enter/try_leave.
@@ -652,8 +654,8 @@ static void finish_exception(except_T *excp)
set_vim_var_string(VV_THROWPOINT, NULL, -1);
}
- /* Discard the exception, but use the finish message for 'verbose'. */
- discard_exception(excp, TRUE);
+ // Discard the exception, but use the finish message for 'verbose'.
+ discard_exception(excp, true);
}
/*
@@ -1812,11 +1814,12 @@ void leave_cleanup(cleanup_T *csp)
* made pending by it. Report this to the user if required by the
* 'verbose' option or when debugging. */
if (aborting() || need_rethrow) {
- if (pending & CSTP_THROW)
- /* Cancel the pending exception (includes report). */
- discard_exception(csp->exception, FALSE);
- else
+ if (pending & CSTP_THROW) {
+ // Cancel the pending exception (includes report).
+ discard_exception(csp->exception, false);
+ } else {
report_discard_pending(pending, NULL);
+ }
/* If an error was about to be converted to an exception when
* enter_cleanup() was called, free the message list. */
@@ -1916,15 +1919,13 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
default:
if (cstack->cs_flags[idx] & CSF_FINALLY) {
if (cstack->cs_pending[idx] & CSTP_THROW) {
- /* Cancel the pending exception. This is in the
- * finally clause, so that the stack of the
- * caught exceptions is not involved. */
- discard_exception((except_T *)
- cstack->cs_exception[idx],
- FALSE);
- } else
- report_discard_pending(cstack->cs_pending[idx],
- NULL);
+ // Cancel the pending exception. This is in the
+ // finally clause, so that the stack of the
+ // caught exceptions is not involved.
+ discard_exception((except_T *)cstack->cs_exception[idx], false);
+ } else {
+ report_discard_pending(cstack->cs_pending[idx], NULL);
+ }
cstack->cs_pending[idx] = CSTP_NONE;
}
break;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index ed408c28e5..626b840798 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -523,7 +523,7 @@ static void may_do_incsearch_highlighting(int firstc, long count,
// positioned in the same way as the actual search command
restore_viewstate(&s->old_viewstate);
changed_cline_bef_curs();
- update_topline();
+ update_topline(curwin);
if (found != 0) {
pos_T save_pos = curwin->w_cursor;
@@ -1082,6 +1082,7 @@ static int command_line_execute(VimState *state, int key)
if (s->c == K_DOWN && ccline.cmdpos > 0
&& ccline.cmdbuff[ccline.cmdpos - 1] == '.') {
s->c = (int)p_wc;
+ KeyTyped = true; // in case the key was mapped
} else if (s->c == K_UP) {
// Hitting <Up>: Remove one submenu name in front of the
// cursor
@@ -1112,6 +1113,7 @@ static int command_line_execute(VimState *state, int key)
cmdline_del(i);
}
s->c = (int)p_wc;
+ KeyTyped = true; // in case the key was mapped
s->xpc.xp_context = EXPAND_NOTHING;
}
}
@@ -1134,6 +1136,7 @@ static int command_line_execute(VimState *state, int key)
|| ccline.cmdbuff[ccline.cmdpos - 3] != '.')) {
// go down a directory
s->c = (int)p_wc;
+ KeyTyped = true; // in case the key was mapped
} else if (STRNCMP(s->xpc.xp_pattern, upseg + 1, 3) == 0
&& s->c == K_DOWN) {
// If in a direct ancestor, strip off one ../ to go down
@@ -1154,6 +1157,7 @@ static int command_line_execute(VimState *state, int key)
&& (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2)) {
cmdline_del(j - 2);
s->c = (int)p_wc;
+ KeyTyped = true; // in case the key was mapped
}
} else if (s->c == K_UP) {
// go up a directory
@@ -1546,7 +1550,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count,
set_search_match(&s->match_end);
curwin->w_cursor = s->match_start;
changed_cline_bef_curs();
- update_topline();
+ update_topline(curwin);
validate_cursor();
highlight_match = true;
save_viewstate(&s->old_viewstate);
@@ -1880,9 +1884,6 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s); // Ignore mouse
case K_MIDDLEMOUSE:
- if (!mouse_has(MOUSE_COMMAND)) {
- return command_line_not_changed(s); // Ignore mouse
- }
cmdline_paste(eval_has_provider("clipboard") ? '*' : 0, true, true);
redrawcmd();
return command_line_changed(s);
@@ -1906,10 +1907,6 @@ static int command_line_handle_key(CommandLineState *s)
s->ignore_drag_release = false;
}
- if (!mouse_has(MOUSE_COMMAND)) {
- return command_line_not_changed(s); // Ignore mouse
- }
-
ccline.cmdspos = cmd_startcol();
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
ccline.cmdpos++) {
@@ -2242,7 +2239,7 @@ static int command_line_changed(CommandLineState *s)
// Restore the window "view".
curwin->w_cursor = s->is_state.save_cursor;
restore_viewstate(&s->is_state.old_viewstate);
- update_topline();
+ update_topline(curwin);
redrawcmdline();
@@ -2251,7 +2248,9 @@ static int command_line_changed(CommandLineState *s)
close_preview_windows();
update_screen(SOME_VALID); // Clear 'inccommand' preview.
} else {
- may_do_incsearch_highlighting(s->firstc, s->count, &s->is_state);
+ if (s->xpc.xp_context == EXPAND_NOTHING) {
+ may_do_incsearch_highlighting(s->firstc, s->count, &s->is_state);
+ }
}
if (cmdmsg_rl || (p_arshape && !p_tbidi)) {
@@ -4229,17 +4228,11 @@ ExpandOne (
* Prepare an expand structure for use.
*/
void ExpandInit(expand_T *xp)
+ FUNC_ATTR_NONNULL_ALL
{
- xp->xp_pattern = NULL;
- xp->xp_pattern_len = 0;
+ CLEAR_POINTER(xp);
xp->xp_backslash = XP_BS_NONE;
-#ifndef BACKSLASH_IN_FILENAME
- xp->xp_shell = FALSE;
-#endif
xp->xp_numfiles = -1;
- xp->xp_files = NULL;
- xp->xp_arg = NULL;
- xp->xp_line = NULL;
}
/*
@@ -4327,7 +4320,8 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
/// if true then it escapes for a shell command.
///
/// @return [allocated] escaped file name.
-char *vim_strsave_fnameescape(const char *const fname, const bool shell)
+char *vim_strsave_fnameescape(const char *const fname,
+ const bool shell FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
#ifdef BACKSLASH_IN_FILENAME
@@ -4786,7 +4780,7 @@ char_u *addstar(char_u *fname, size_t len, int context)
* EXPAND_COMMANDS Cursor is still touching the command, so complete
* it.
* EXPAND_BUFFERS Complete file names for :buf and :sbuf commands.
- * EXPAND_FILES After command with XFILE set, or after setting
+ * EXPAND_FILES After command with EX_XFILE set, or after setting
* with P_EXPAND set. eg :e ^I, :w>>^I
* EXPAND_DIRECTORIES In some cases this is used instead of the latter
* when we know only directories are of interest. eg
@@ -5398,7 +5392,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
}
/// Call "user_expand_func()" to invoke a user defined Vim script function and
-/// return the result (either a string or a List).
+/// return the result (either a string, a List or NULL).
static void * call_user_expand_func(user_expand_func_T user_expand_func,
expand_T *xp, int *num_file, char_u ***file)
FUNC_ATTR_NONNULL_ALL
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 42a9ef08f9..14dac9a126 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -526,8 +526,12 @@ static int makeopens(FILE *fd, char_u *dirnow)
}
}
- // Close all windows but one.
+ // Close all windows and tabs but one.
PUTLINE_FAIL("silent only");
+ if ((ssop_flags & SSOP_TABPAGES)
+ && put_line(fd, "silent tabonly") == FAIL) {
+ return FAIL;
+ }
//
// Now a :cd command to the session directory or the current directory
@@ -606,13 +610,26 @@ static int makeopens(FILE *fd, char_u *dirnow)
//
tab_firstwin = firstwin; // First window in tab page "tabnr".
tab_topframe = topframe;
+ if ((ssop_flags & SSOP_TABPAGES)) {
+ // Similar to ses_win_rec() below, populate the tab pages first so
+ // later local options won't be copied to the new tabs.
+ FOR_ALL_TABS(tp) {
+ if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL) {
+ return FAIL;
+ }
+ }
+
+ if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL) {
+ return FAIL;
+ }
+ }
for (tabnr = 1;; tabnr++) {
tabpage_T *tp = find_tabpage(tabnr);
if (tp == NULL) {
break; // done all tab pages
}
- int need_tabnew = false;
+ bool need_tabnext = false;
int cnr = 1;
if ((ssop_flags & SSOP_TABPAGES)) {
@@ -624,7 +641,7 @@ static int makeopens(FILE *fd, char_u *dirnow)
tab_topframe = tp->tp_topframe;
}
if (tabnr > 1) {
- need_tabnew = true;
+ need_tabnext = true;
}
}
@@ -639,11 +656,15 @@ static int makeopens(FILE *fd, char_u *dirnow)
&& !bt_help(wp->w_buffer)
&& !bt_nofile(wp->w_buffer)
) {
- if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0
+ if (need_tabnext && put_line(fd, "tabnext") == FAIL) {
+ return FAIL;
+ }
+ need_tabnext = false;
+
+ if (fputs("edit ", fd) < 0
|| ses_fname(fd, wp->w_buffer, &ssop_flags, true) == FAIL) {
return FAIL;
}
- need_tabnew = false;
if (!wp->w_arg_idx_invalid) {
edited_win = wp;
}
@@ -652,7 +673,7 @@ static int makeopens(FILE *fd, char_u *dirnow)
}
// If no file got edited create an empty tab page.
- if (need_tabnew && put_line(fd, "tabnew") == FAIL) {
+ if (need_tabnext && put_line(fd, "tabnext") == FAIL) {
return FAIL;
}
@@ -775,6 +796,7 @@ static int makeopens(FILE *fd, char_u *dirnow)
//
if (fprintf(fd, "%s",
"if exists('s:wipebuf') "
+ "&& len(win_findbuf(s:wipebuf)) == 0"
"&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'\n"
" silent exe 'bwipe ' . s:wipebuf\n"
"endif\n"
@@ -893,6 +915,9 @@ void ex_mkrc(exarg_T *eap)
&& (*flagp & SSOP_OPTIONS))) {
failed |= (makemap(fd, NULL) == FAIL
|| makeset(fd, OPT_GLOBAL, false) == FAIL);
+ if (p_hls && fprintf(fd, "%s", "set hlsearch\n") < 0) {
+ failed = true;
+ }
}
if (!failed && view_session) {
@@ -949,11 +974,16 @@ void ex_mkrc(exarg_T *eap)
}
if (fprintf(fd,
"%s",
- "let &g:so = s:so_save | let &g:siso = s:siso_save\n"
- "doautoall SessionLoadPost\n")
+ "let &g:so = s:so_save | let &g:siso = s:siso_save\n")
< 0) {
failed = true;
}
+ if (no_hlsearch && fprintf(fd, "%s", "nohlsearch\n") < 0) {
+ failed = true;
+ }
+ if (fprintf(fd, "%s", "doautoall SessionLoadPost\n") < 0) {
+ failed = true;
+ }
if (eap->cmdidx == CMD_mksession) {
if (fprintf(fd, "unlet SessionLoad\n") < 0) {
failed = true;
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index ba685b158e..b2d8532cd7 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -560,6 +560,23 @@ void extmark_adjust(buf_T *buf,
new_row, 0, new_byte, undo);
}
+// Adjust extmarks following a text edit.
+//
+// @param buf
+// @param start_row Start row of the region to be changed
+// @param start_col Start col of the region to be changed
+// @param old_row End row of the region to be changed.
+// Encoded as an offset to start_row.
+// @param old_col End col of the region to be changed. Encodes
+// an offset from start_col if old_row = 0; otherwise,
+// encodes the end column of the old region.
+// @param old_byte Byte extent of the region to be changed.
+// @param new_row Row offset of the new region.
+// @param new_col Col offset of the new region. Encodes an offset from
+// start_col if new_row = 0; otherwise, encodes
+// the end column of the new region.
+// @param new_byte Byte extent of the new region.
+// @param undo
void extmark_splice(buf_T *buf,
int start_row, colnr_T start_col,
int old_row, colnr_T old_col, bcount_t old_byte,
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index ab8072ae1d..a542bb19dd 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -15,6 +15,7 @@
#include "nvim/ascii.h"
#include "nvim/fileio.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -1651,9 +1652,6 @@ failed:
# ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
-# ifndef __clang_analyzer__
- iconv_fd = (iconv_t)-1;
-# endif
}
# endif
@@ -2031,7 +2029,7 @@ static char_u *next_fenc(char_u **pp, bool *alloced)
r = enc_canonize(*pp);
*pp += STRLEN(*pp);
} else {
- r = vim_strnsave(*pp, (int)(p - *pp));
+ r = vim_strnsave(*pp, p - *pp);
*pp = p + 1;
p = enc_canonize(r);
xfree(r);
@@ -4216,7 +4214,9 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
&& (force
|| buf->b_sfname == NULL
|| path_is_absolute(buf->b_sfname))) {
- XFREE_CLEAR(buf->b_sfname);
+ if (buf->b_sfname != buf->b_ffname) {
+ XFREE_CLEAR(buf->b_sfname);
+ }
p = path_shorten_fname(buf->b_ffname, dirname);
if (p != NULL) {
buf->b_sfname = vim_strsave(p);
@@ -4672,7 +4672,6 @@ check_timestamps(
)
{
int didit = 0;
- int n;
/* Don't check timestamps while system() or another low-level function may
* cause us to lose and gain focus. */
@@ -4700,7 +4699,7 @@ check_timestamps(
if (buf->b_nwindows > 0) {
bufref_T bufref;
set_bufref(&bufref, buf);
- n = buf_check_timestamp(buf, focus);
+ const int n = buf_check_timestamp(buf);
if (didit < n) {
didit = n;
}
@@ -4770,11 +4769,7 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
* return 2 if a message has been displayed.
* return 0 otherwise.
*/
-int
-buf_check_timestamp(
- buf_T *buf,
- int focus /* called for GUI focus event */
-)
+int buf_check_timestamp(buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
int retval = 0;
@@ -5082,6 +5077,7 @@ void buf_reload(buf_T *buf, int orig_mode)
// Mark all undo states as changed.
u_unchanged(curbuf);
}
+ buf_updates_unregister_all(curbuf);
}
}
xfree(ea.cmd);
@@ -5101,8 +5097,8 @@ void buf_reload(buf_T *buf, int orig_mode)
curwin->w_topline = old_topline;
curwin->w_cursor = old_cursor;
check_cursor();
- update_topline();
- keep_filetype = FALSE;
+ update_topline(curwin);
+ keep_filetype = false;
/* Update folds unless they are defined manually. */
FOR_ALL_TAB_WINDOWS(tp, wp) {
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 654aa6d5ba..0593c16999 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -902,8 +902,9 @@ int foldMoveTo(
bool last = false;
for (;; ) {
if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) {
- if (!updown)
+ if (!updown || gap->ga_len == 0) {
break;
+ }
/* When moving up, consider a fold above the cursor; when
* moving down consider a fold below the cursor. */
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index 38b51b5564..e0b0610646 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -213,6 +213,8 @@
# define FUNC_API_REMOTE_ONLY
/// API function not exposed in VimL/remote.
# define FUNC_API_LUA_ONLY
+/// API function checked textlock.
+# define FUNC_API_CHECK_TEXTLOCK
/// API function introduced at the given API level.
# define FUNC_API_SINCE(X)
/// API function deprecated since the given API level.
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index de098b7a7b..c9ab0cf709 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -43,6 +43,7 @@ local c_proto = Ct(
(fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
(fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) *
(fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) *
+ (fill * Cg((P('FUNC_API_CHECK_TEXTLOCK') * Cc(true)), 'check_textlock') ^ -1) *
(fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) *
(fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) *
(fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) *
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index b31209e8ff..7e78b9e9d6 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -260,6 +260,13 @@ for i = 1, #functions do
args[#args + 1] = converted
end
+ if fn.check_textlock then
+ output:write('\n if (textlock != 0) {')
+ output:write('\n api_set_error(error, kErrorTypeException, "%s", e_secure);')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
+ end
+
-- function call
local call_args = table.concat(args, ', ')
output:write('\n ')
@@ -393,6 +400,16 @@ local function process_function(fn)
}
]], fn.name))
end
+
+ if fn.check_textlock then
+ write_shifted_output(output, [[
+ if (textlock != 0) {
+ api_set_error(&err, kErrorTypeException, "%s", e_secure);
+ goto exit_0;
+ }
+ ]])
+ end
+
local cparams = ''
local free_code = {}
for j = #fn.parameters,1,-1 do
diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua
index 849c82f50e..844661adc3 100644
--- a/src/nvim/generators/gen_ex_cmds.lua
+++ b/src/nvim/generators/gen_ex_cmds.lua
@@ -22,7 +22,10 @@ local defsfname = autodir .. '/ex_cmds_defs.generated.h'
local enumfile = io.open(enumfname, 'w')
local defsfile = io.open(defsfname, 'w')
-local defs = require('ex_cmds')
+local bit = require 'bit'
+local ex_cmds = require('ex_cmds')
+local defs = ex_cmds.cmds
+local flags = ex_cmds.flags
local byte_a = string.byte('a')
local byte_z = string.byte('z')
@@ -51,6 +54,17 @@ static CommandDefinition cmdnames[%u] = {
]], #defs, #defs))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for _, cmd in ipairs(defs) do
+ if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then
+ assert(cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command))
+ else
+ assert(cmd.addr_type == 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command))
+ end
+ if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then
+ assert(cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command))
+ end
local enumname = cmd.enum or ('CMD_' .. cmd.command)
local byte_cmd = cmd.command:sub(1, 1):byte()
if byte_a <= byte_cmd and byte_cmd <= byte_z then
@@ -62,7 +76,7 @@ for _, cmd in ipairs(defs) do
.cmd_name = (char_u *) "%s",
.cmd_func = (ex_func_T)&%s,
.cmd_argt = %uL,
- .cmd_addr_type = %i
+ .cmd_addr_type = %s
},
]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type))
end
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 566a5ae9d6..3b8f4116b7 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -215,6 +215,8 @@ EXTERN bool emsg_severe INIT(= false); // use message of next of several
EXTERN int did_endif INIT(= false); // just had ":endif"
EXTERN dict_T vimvardict; // Dictionary with v: variables
EXTERN dict_T globvardict; // Dictionary with g: variables
+/// g: value
+#define globvarht globvardict.dv_hashtab
EXTERN int did_emsg; // set by emsg() when the message
// is displayed or thrown
EXTERN bool called_vim_beep; // set if vim_beep() is called
@@ -864,7 +866,6 @@ EXTERN char_u e_failed[] INIT(= N_("E472: Command failed"));
EXTERN char_u e_internal[] INIT(= N_("E473: Internal error"));
EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
EXTERN char_u e_interr[] INIT(= N_("Interrupted"));
-EXTERN char_u e_invaddr[] INIT(= N_("E14: Invalid address"));
EXTERN char_u e_invarg[] INIT(= N_("E474: Invalid argument"));
EXTERN char_u e_invarg2[] INIT(= N_("E475: Invalid argument: %s"));
EXTERN char_u e_invargval[] INIT(= N_("E475: Invalid value for argument %s"));
@@ -935,6 +936,7 @@ EXTERN char_u e_readonly[] INIT(= N_(
"E45: 'readonly' option is set (add ! to override)"));
EXTERN char_u e_readonlyvar[] INIT(= N_(
"E46: Cannot change read-only variable \"%.*s\""));
+EXTERN char_u e_stringreq[] INIT(= N_("E928: String required"));
EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required"));
EXTERN char_u e_toomanyarg[] INIT(= N_(
"E118: Too many arguments for function: %s"));
@@ -1052,4 +1054,7 @@ typedef enum {
#define MIN_CD_SCOPE kCdScopeWindow
#define MAX_CD_SCOPE kCdScopeGlobal
+// Only filled for Win32.
+EXTERN char windowsVersion[20] INIT(= { 0 });
+
#endif // NVIM_GLOBALS_H
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index 2c954008b3..4ec949759c 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -964,7 +964,6 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
#define PRT_PS_DEFAULT_DPI (72) // Default user space resolution
#define PRT_PS_DEFAULT_FONTSIZE (10)
-#define PRT_PS_DEFAULT_BUFFER_SIZE (80)
#define PRT_MEDIASIZE_LEN (sizeof(prt_mediasize) / \
sizeof(struct prt_mediasize_S))
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 225e40cdb4..19203a3c2a 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -13,9 +13,6 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
-#if !defined(WIN32)
-# include <sys/time.h> // for gettimeofday()
-#endif
#include <uv.h>
#include "auto/config.h"
@@ -296,12 +293,10 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
}
int millis = 0;
-#if !defined(WIN32)
- struct timeval curtime;
- if (gettimeofday(&curtime, NULL) == 0) {
+ uv_timeval64_t curtime;
+ if (uv_gettimeofday(&curtime) == 0) {
millis = (int)curtime.tv_usec / 1000;
}
-#endif
// Print the log message.
int64_t pid = os_get_pid();
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 2c7ab46ffe..b20fbbf038 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -115,7 +115,8 @@ function vim._load_package(name)
for _,path in ipairs(paths) do
local found = vim.api.nvim_get_runtime_file(path, false)
if #found > 0 then
- return loadfile(found[1])
+ local f, err = loadfile(found[1])
+ return f or error(err)
end
end
@@ -123,7 +124,8 @@ function vim._load_package(name)
local path = "lua/"..trail:gsub('?',basename)
local found = vim.api.nvim_get_runtime_file(path, false)
if #found > 0 then
- return package.loadlib(found[1])
+ local f, err = package.loadlib(found[1])
+ return f or error(err)
end
end
return nil
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index 07dcb4a8e8..303722b4a8 100644
--- a/src/nvim/macros.h
+++ b/src/nvim/macros.h
@@ -98,9 +98,6 @@
# define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2))
-// Whether to draw the vertical bar on the right side of the cell.
-# define CURSOR_BAR_RIGHT (curwin->w_p_rl && (!(State & CMDLINE) || cmdmsg_rl))
-
// MB_PTR_ADV(): advance a pointer to the next character, taking care of
// multi-byte characters if needed.
// MB_PTR_BACK(): backup a pointer to the previous character, taking care of
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 79c165419e..8bf745966e 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -169,6 +169,14 @@ void early_init(mparm_T *paramp)
init_normal_cmds(); // Init the table of Normal mode commands.
highlight_init();
+#ifdef WIN32
+ OSVERSIONINFO ovi;
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+ GetVersionEx(&ovi);
+ snprintf(windowsVersion, sizeof(windowsVersion), "%d.%d",
+ (int)ovi.dwMajorVersion, (int)ovi.dwMinorVersion);
+#endif
+
#if defined(HAVE_LOCALE_H)
// Setup to use the current locale (for ctype() and many other things).
// NOTE: Translated messages with encodings other than latin1 will not
@@ -531,7 +539,7 @@ int main(int argc, char **argv)
// When a startup script or session file setup for diff'ing and
// scrollbind, sync the scrollbind now.
if (curwin->w_p_diff && curwin->w_p_scb) {
- update_topline();
+ update_topline(curwin);
check_scrollbind((linenr_T)0, 0L);
TIME_MSG("diff scrollbinding");
}
@@ -645,7 +653,18 @@ void getout(int exitval)
}
}
}
- apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
+
+ int unblock = 0;
+ // deathtrap() blocks autocommands, but we do want to trigger
+ // VimLeavePre.
+ if (is_autocmd_blocked()) {
+ unblock_autocmds();
+ unblock++;
+ }
+ apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, false, curbuf);
+ if (unblock) {
+ block_autocmds();
+ }
}
if (p_shada && *p_shada != NUL) {
@@ -654,7 +673,17 @@ void getout(int exitval)
}
if (v_dying <= 1) {
+ int unblock = 0;
+
+ // deathtrap() blocks autocommands, but we do want to trigger VimLeave.
+ if (is_autocmd_blocked()) {
+ unblock_autocmds();
+ unblock++;
+ }
apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, false, curbuf);
+ if (unblock) {
+ block_autocmds();
+ }
}
profile_dump();
@@ -1414,7 +1443,10 @@ static void read_stdin(void)
no_wait_return = true;
int save_msg_didany = msg_didany;
set_buflisted(true);
- (void)open_buffer(true, NULL, 0); // create memfile and read file
+
+ // Create memfile and read from stdin.
+ (void)open_buffer(true, NULL, 0);
+
if (BUFEMPTY() && curbuf->b_next != NULL) {
// stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561
do_cmdline_cmd("silent! bnext");
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 1ecfae57ed..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);
}
}
@@ -1552,3 +1553,87 @@ void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
}
}
}
+
+
+// Add information about mark 'mname' to list 'l'
+static int add_mark(list_T *l, const char *mname, const pos_T *pos, int bufnr,
+ const char *fname)
+ FUNC_ATTR_NONNULL_ARG(1, 2, 3)
+{
+ if (pos->lnum <= 0) {
+ return OK;
+ }
+
+ dict_T *d = tv_dict_alloc();
+ tv_list_append_dict(l, d);
+
+ list_T *lpos = tv_list_alloc(kListLenMayKnow);
+
+ tv_list_append_number(lpos, bufnr);
+ tv_list_append_number(lpos, pos->lnum);
+ tv_list_append_number(lpos, pos->col + 1);
+ tv_list_append_number(lpos, pos->coladd);
+
+ if (tv_dict_add_str(d, S_LEN("mark"), mname) == FAIL
+ || tv_dict_add_list(d, S_LEN("pos"), lpos) == FAIL
+ || (fname != NULL && tv_dict_add_str(d, S_LEN("file"), fname) == FAIL)) {
+ return FAIL;
+ }
+
+ return OK;
+}
+
+
+/// Get information about marks local to a buffer.
+///
+/// @param[in] buf Buffer to get the marks from
+/// @param[out] l List to store marks
+void get_buf_local_marks(const buf_T *buf, list_T *l)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char mname[3] = "' ";
+
+ // Marks 'a' to 'z'
+ for (int i = 0; i < NMARKS; i++) {
+ mname[1] = (char)('a' + i);
+ add_mark(l, mname, &buf->b_namedm[i].mark, buf->b_fnum, NULL);
+ }
+
+ // Mark '' is a window local mark and not a buffer local mark
+ add_mark(l, "''", &curwin->w_pcmark, curbuf->b_fnum, NULL);
+
+ add_mark(l, "'\"", &buf->b_last_cursor.mark, buf->b_fnum, NULL);
+ add_mark(l, "'[", &buf->b_op_start, buf->b_fnum, NULL);
+ add_mark(l, "']", &buf->b_op_end, buf->b_fnum, NULL);
+ add_mark(l, "'^", &buf->b_last_insert.mark, buf->b_fnum, NULL);
+ add_mark(l, "'.", &buf->b_last_change.mark, buf->b_fnum, NULL);
+ add_mark(l, "'<", &buf->b_visual.vi_start, buf->b_fnum, NULL);
+ add_mark(l, "'>", &buf->b_visual.vi_end, buf->b_fnum, NULL);
+}
+
+/// Get information about global marks ('A' to 'Z' and '0' to '9')
+///
+/// @param[out] l List to store global marks
+void get_global_marks(list_T *l)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char mname[3] = "' ";
+ char *name;
+
+ // Marks 'A' to 'Z' and '0' to '9'
+ for (int i = 0; i < NMARKS + EXTRA_MARKS; i++) {
+ if (namedfm[i].fmark.fnum != 0) {
+ name = (char *)buflist_nr2name(namedfm[i].fmark.fnum, true, true);
+ } else {
+ name = (char *)namedfm[i].fname;
+ }
+ if (name != NULL) {
+ mname[1] = i >= NMARKS ? (char)(i - NMARKS + '0') : (char)(i + 'A');
+
+ add_mark(l, mname, &namedfm[i].fmark.mark, namedfm[i].fmark.fnum, name);
+ if (namedfm[i].fmark.fnum != 0) {
+ xfree(name);
+ }
+ }
+ }
+}
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index e9ea2cbba9..b3afdefac1 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -55,7 +55,6 @@
#define T MT_BRANCH_FACTOR
#define ILEN (sizeof(mtnode_t)+(2 * T) * sizeof(void *))
-#define key_t SKRAPET
#define RIGHT_GRAVITY (((uint64_t)1) << 63)
#define ANTIGRAVITY(id) ((id)&(RIGHT_GRAVITY-1))
@@ -65,8 +64,6 @@
#define END_FLAG MARKTREE_END_FLAG
#define ID_INCR (((uint64_t)1) << 2)
-#define PROP_MASK (RIGHT_GRAVITY|PAIRED|END_FLAG)
-
#define rawkey(itr) (itr->node->key[itr->i])
static bool pos_leq(mtpos_t a, mtpos_t b)
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 70225484ec..31dc6b3649 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -975,9 +975,9 @@ void ml_recover(bool checkext)
if (b0p->b0_flags & B0_HAS_FENC) {
int fnsize = B0_FNAME_SIZE_NOCRYPT;
- for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; --p)
- ;
- b0_fenc = vim_strnsave(p, (int)(b0p->b0_fname + fnsize - p));
+ for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {
+ }
+ b0_fenc = vim_strnsave(p, b0p->b0_fname + fnsize - p);
}
mf_put(mfp, hp, false, false); /* release block 0 */
diff --git a/src/nvim/message.c b/src/nvim/message.c
index f76a408481..f94529c687 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1157,15 +1157,7 @@ void wait_return(int redraw)
|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
|| c == K_RIGHTDRAG || c == K_RIGHTRELEASE
|| c == K_MOUSELEFT || c == K_MOUSERIGHT
- || c == K_MOUSEDOWN || c == K_MOUSEUP
- || (!mouse_has(MOUSE_RETURN)
- && mouse_row < msg_row
- && (c == K_LEFTMOUSE
- || c == K_MIDDLEMOUSE
- || c == K_RIGHTMOUSE
- || c == K_X1MOUSE
- || c == K_X2MOUSE))
- );
+ || c == K_MOUSEDOWN || c == K_MOUSEUP);
os_breakcheck();
/*
* Avoid that the mouse-up event causes visual mode to start.
@@ -1711,8 +1703,11 @@ void msg_prt_line(char_u *s, int list)
} else if ((l = utfc_ptr2len(s)) > 1) {
col += utf_ptr2cells(s);
char buf[MB_MAXBYTES + 1];
- if (curwin->w_p_lcs_chars.nbsp != NUL && list
- && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) {
+ if (l >= MB_MAXBYTES) {
+ xstrlcpy(buf, "?", sizeof(buf));
+ } else if (curwin->w_p_lcs_chars.nbsp != NUL && list
+ && (utf_ptr2char(s) == 160
+ || utf_ptr2char(s) == 0x202f)) {
utf_char2bytes(curwin->w_p_lcs_chars.nbsp, (char_u *)buf);
buf[utfc_ptr2len((char_u *)buf)] = NUL;
} else {
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index f05dade73f..ff471ea978 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -526,53 +526,9 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
void setmouse(void)
{
ui_cursor_shape();
-
- // Be quick when mouse is off.
- if (*p_mouse == NUL) {
- return;
- }
-
- int checkfor = MOUSE_NORMAL; // assume normal mode
- if (VIsual_active) {
- checkfor = MOUSE_VISUAL;
- } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) {
- checkfor = MOUSE_RETURN;
- } else if (State & INSERT) {
- checkfor = MOUSE_INSERT;
- } else if (State & CMDLINE) {
- checkfor = MOUSE_COMMAND;
- } else if (State == CONFIRM || State == EXTERNCMD) {
- checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd"
- }
-
- if (mouse_has(checkfor)) {
- ui_call_mouse_on();
- } else {
- ui_call_mouse_off();
- }
+ ui_check_mouse();
}
-/*
- * Return true if
- * - "c" is in 'mouse', or
- * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
- * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
- * normal editing mode (not at hit-return message).
- */
-int mouse_has(int c)
-{
- for (char_u *p = p_mouse; *p; ++p)
- switch (*p) {
- case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL)
- return true;
- break;
- case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help)
- return true;
- break;
- default: if (c == *p) return true; break;
- }
- return false;
-}
// Set orig_topline. Used when jumping to another window, so that a double
// click still works.
diff --git a/src/nvim/move.c b/src/nvim/move.c
index fdcf6bb189..a6afdc27d9 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -129,98 +129,99 @@ void redraw_for_cursorline(win_T *wp)
*/
void update_topline_redraw(void)
{
- update_topline();
- if (must_redraw)
+ update_topline(curwin);
+ if (must_redraw) {
update_screen(0);
+ }
}
/*
* Update curwin->w_topline to move the cursor onto the screen.
*/
-void update_topline(void)
+void update_topline(win_T *wp)
{
linenr_T old_topline;
int old_topfill;
bool check_topline = false;
bool check_botline = false;
- long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
+ long *so_ptr = wp->w_p_so >= 0 ? &wp->w_p_so : &p_so;
long save_so = *so_ptr;
// If there is no valid screen and when the window height is zero just use
// the cursor line.
- if (!default_grid.chars || curwin->w_height_inner == 0) {
- curwin->w_topline = curwin->w_cursor.lnum;
- curwin->w_botline = curwin->w_topline;
- curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
- curwin->w_viewport_invalid = true;
- curwin->w_scbind_pos = 1;
+ if (!default_grid.chars || wp->w_height_inner == 0) {
+ wp->w_topline = wp->w_cursor.lnum;
+ wp->w_botline = wp->w_topline;
+ wp->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
+ wp->w_viewport_invalid = true;
+ wp->w_scbind_pos = 1;
return;
}
- check_cursor_moved(curwin);
- if (curwin->w_valid & VALID_TOPLINE)
+ check_cursor_moved(wp);
+ if (wp->w_valid & VALID_TOPLINE) {
return;
+ }
// When dragging with the mouse, don't scroll that quickly
if (mouse_dragging > 0) {
*so_ptr = mouse_dragging - 1;
}
- old_topline = curwin->w_topline;
- old_topfill = curwin->w_topfill;
+ old_topline = wp->w_topline;
+ old_topfill = wp->w_topfill;
// If the buffer is empty, always set topline to 1.
if (BUFEMPTY()) { // special case - file is empty
- if (curwin->w_topline != 1) {
- redraw_later(curwin, NOT_VALID);
+ if (wp->w_topline != 1) {
+ redraw_later(wp, NOT_VALID);
}
- curwin->w_topline = 1;
- curwin->w_botline = 2;
- curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
- curwin->w_viewport_invalid = true;
- curwin->w_scbind_pos = 1;
- }
- /*
- * If the cursor is above or near the top of the window, scroll the window
- * to show the line the cursor is in, with 'scrolloff' context.
- */
- else {
- if (curwin->w_topline > 1) {
- /* If the cursor is above topline, scrolling is always needed.
- * If the cursor is far below topline and there is no folding,
- * scrolling down is never needed. */
- if (curwin->w_cursor.lnum < curwin->w_topline)
+ wp->w_topline = 1;
+ wp->w_botline = 2;
+ wp->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
+ wp->w_viewport_invalid = true;
+ wp->w_scbind_pos = 1;
+ } else {
+ // If the cursor is above or near the top of the window, scroll the window
+ // to show the line the cursor is in, with 'scrolloff' context.
+ if (wp->w_topline > 1) {
+ // If the cursor is above topline, scrolling is always needed.
+ // If the cursor is far below topline and there is no folding,
+ // scrolling down is never needed.
+ if (wp->w_cursor.lnum < wp->w_topline) {
check_topline = true;
- else if (check_top_offset())
+ } else if (check_top_offset()) {
check_topline = true;
+ }
}
- /* Check if there are more filler lines than allowed. */
- if (!check_topline && curwin->w_topfill > diff_check_fill(curwin,
- curwin->w_topline))
+ // Check if there are more filler lines than allowed.
+ if (!check_topline && wp->w_topfill > diff_check_fill(wp, wp->w_topline)) {
check_topline = true;
+ }
if (check_topline) {
- int halfheight = curwin->w_height_inner / 2 - 1;
+ int halfheight = wp->w_height_inner / 2 - 1;
if (halfheight < 2) {
halfheight = 2;
}
long n;
- if (hasAnyFolding(curwin)) {
- /* Count the number of logical lines between the cursor and
- * topline + p_so (approximation of how much will be
- * scrolled). */
+ if (hasAnyFolding(wp)) {
+ // Count the number of logical lines between the cursor and
+ // topline + p_so (approximation of how much will be
+ // scrolled).
n = 0;
- for (linenr_T lnum = curwin->w_cursor.lnum;
- lnum < curwin->w_topline + *so_ptr; lnum++) {
+ for (linenr_T lnum = wp->w_cursor.lnum;
+ lnum < wp->w_topline + *so_ptr; lnum++) {
n++;
// stop at end of file or when we know we are far off
- if (lnum >= curbuf->b_ml.ml_line_count || n >= halfheight) {
+ assert(wp->w_buffer != 0);
+ if (lnum >= wp->w_buffer->b_ml.ml_line_count || n >= halfheight) {
break;
}
- (void)hasFolding(lnum, NULL, &lnum);
+ (void)hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
}
} else {
- n = curwin->w_topline + *so_ptr - curwin->w_cursor.lnum;
+ n = wp->w_topline + *so_ptr - wp->w_cursor.lnum;
}
/* If we weren't very close to begin with, we scroll to put the
@@ -233,8 +234,8 @@ void update_topline(void)
check_botline = true;
}
} else {
- /* Make sure topline is the first line of a fold. */
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ // Make sure topline is the first line of a fold.
+ (void)hasFoldingWin(wp, wp->w_topline, &wp->w_topline, NULL, true, NULL);
check_botline = true;
}
}
@@ -248,35 +249,36 @@ void update_topline(void)
* for every small change.
*/
if (check_botline) {
- if (!(curwin->w_valid & VALID_BOTLINE_AP))
- validate_botline();
-
- if (curwin->w_botline <= curbuf->b_ml.ml_line_count) {
- if (curwin->w_cursor.lnum < curwin->w_botline) {
- if (((long)curwin->w_cursor.lnum
- >= (long)curwin->w_botline - *so_ptr
- || hasAnyFolding(curwin)
- )) {
+ if (!(wp->w_valid & VALID_BOTLINE_AP)) {
+ validate_botline(wp);
+ }
+
+ assert(wp->w_buffer != 0);
+ if (wp->w_botline <= wp->w_buffer->b_ml.ml_line_count) {
+ if (wp->w_cursor.lnum < wp->w_botline) {
+ if (((long)wp->w_cursor.lnum
+ >= (long)wp->w_botline - *so_ptr
+ || hasAnyFolding(wp))) {
lineoff_T loff;
/* Cursor is (a few lines) above botline, check if there are
* 'scrolloff' window lines below the cursor. If not, need to
* scroll. */
- int n = curwin->w_empty_rows;
- loff.lnum = curwin->w_cursor.lnum;
- /* In a fold go to its last line. */
- (void)hasFolding(loff.lnum, NULL, &loff.lnum);
+ int n = wp->w_empty_rows;
+ loff.lnum = wp->w_cursor.lnum;
+ // In a fold go to its last line.
+ (void)hasFoldingWin(wp, loff.lnum, NULL, &loff.lnum, true, NULL);
loff.fill = 0;
- n += curwin->w_filler_rows;
+ n += wp->w_filler_rows;
loff.height = 0;
- while (loff.lnum < curwin->w_botline
- && (loff.lnum + 1 < curwin->w_botline || loff.fill == 0)
+ while (loff.lnum < wp->w_botline
+ && (loff.lnum + 1 < wp->w_botline || loff.fill == 0)
) {
n += loff.height;
if (n >= *so_ptr) {
break;
}
- botline_forw(&loff);
+ botline_forw(wp, &loff);
}
if (n >= *so_ptr) {
// sufficient context, no need to scroll
@@ -289,23 +291,23 @@ void update_topline(void)
}
if (check_botline) {
long line_count = 0;
- if (hasAnyFolding(curwin)) {
- /* Count the number of logical lines between the cursor and
- * botline - p_so (approximation of how much will be
- * scrolled). */
- for (linenr_T lnum = curwin->w_cursor.lnum;
- lnum >= curwin->w_botline - *so_ptr; lnum--) {
+ if (hasAnyFolding(wp)) {
+ // Count the number of logical lines between the cursor and
+ // botline - p_so (approximation of how much will be
+ // scrolled).
+ for (linenr_T lnum = wp->w_cursor.lnum;
+ lnum >= wp->w_botline - *so_ptr; lnum--) {
line_count++;
// stop at end of file or when we know we are far off
- if (lnum <= 0 || line_count > curwin->w_height_inner + 1) {
+ if (lnum <= 0 || line_count > wp->w_height_inner + 1) {
break;
}
(void)hasFolding(lnum, &lnum, NULL);
}
- } else
- line_count = curwin->w_cursor.lnum - curwin->w_botline
- + 1 + *so_ptr;
- if (line_count <= curwin->w_height_inner + 1) {
+ } else {
+ line_count = wp->w_cursor.lnum - wp->w_botline + 1 + *so_ptr;
+ }
+ if (line_count <= wp->w_height_inner + 1) {
scroll_cursor_bot(scrolljump_value(), false);
} else {
scroll_cursor_halfway(false);
@@ -313,25 +315,25 @@ void update_topline(void)
}
}
}
- curwin->w_valid |= VALID_TOPLINE;
- curwin->w_viewport_invalid = true;
- win_check_anchored_floats(curwin);
+ wp->w_valid |= VALID_TOPLINE;
+ wp->w_viewport_invalid = true;
+ win_check_anchored_floats(wp);
/*
* Need to redraw when topline changed.
*/
- if (curwin->w_topline != old_topline
- || curwin->w_topfill != old_topfill
+ if (wp->w_topline != old_topline
+ || wp->w_topfill != old_topfill
) {
dollar_vcol = -1;
- if (curwin->w_skipcol != 0) {
- curwin->w_skipcol = 0;
- redraw_later(curwin, NOT_VALID);
+ if (wp->w_skipcol != 0) {
+ wp->w_skipcol = 0;
+ redraw_later(wp, NOT_VALID);
} else {
- redraw_later(curwin, VALID);
+ redraw_later(wp, VALID);
}
// May need to set w_skipcol when cursor in w_topline.
- if (curwin->w_cursor.lnum == curwin->w_topline) {
+ if (wp->w_cursor.lnum == wp->w_topline) {
validate_cursor();
}
}
@@ -346,7 +348,7 @@ void update_topline_win(win_T* win)
{
win_T *save_curwin;
switch_win(&save_curwin, NULL, win, NULL, true);
- update_topline();
+ update_topline(curwin);
restore_win(save_curwin, NULL, true);
}
@@ -368,7 +370,7 @@ static int scrolljump_value(void)
*/
static bool check_top_offset(void)
{
- long so = get_scrolloff_value();
+ long so = get_scrolloff_value(curwin);
if (curwin->w_cursor.lnum < curwin->w_topline + so
|| hasAnyFolding(curwin)
) {
@@ -378,7 +380,7 @@ static bool check_top_offset(void)
int n = curwin->w_topfill; // always have this context
// Count the visible screen lines above the cursor line.
while (n < so) {
- topline_back(&loff);
+ topline_back(curwin, &loff);
// Stop when included a line above the window.
if (loff.lnum < curwin->w_topline
|| (loff.lnum == curwin->w_topline && loff.fill > 0)
@@ -498,10 +500,11 @@ void changed_line_abv_curs_win(win_T *wp)
/*
* Make sure the value of curwin->w_botline is valid.
*/
-void validate_botline(void)
+void validate_botline(win_T *wp)
{
- if (!(curwin->w_valid & VALID_BOTLINE))
- comp_botline(curwin);
+ if (!(wp->w_valid & VALID_BOTLINE)) {
+ comp_botline(wp);
+ }
}
/*
@@ -539,8 +542,9 @@ int cursor_valid(void)
void validate_cursor(void)
{
check_cursor_moved(curwin);
- if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
- curs_columns(true);
+ if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW)) {
+ curs_columns(curwin, true);
+ }
}
/*
@@ -720,8 +724,10 @@ int curwin_col_off2(void)
// Compute curwin->w_wcol and curwin->w_virtcol.
// Also updates curwin->w_wrow and curwin->w_cline_row.
// Also updates curwin->w_leftcol.
+// @param may_scroll when true, may scroll horizontally
void curs_columns(
- int may_scroll /* when true, may scroll horizontally */
+ win_T *wp,
+ int may_scroll
)
{
int n;
@@ -729,136 +735,136 @@ void curs_columns(
colnr_T startcol;
colnr_T endcol;
colnr_T prev_skipcol;
- long so = get_scrolloff_value();
- long siso = get_sidescrolloff_value();
+ long so = get_scrolloff_value(wp);
+ long siso = get_sidescrolloff_value(wp);
/*
* First make sure that w_topline is valid (after moving the cursor).
*/
- update_topline();
+ update_topline(wp);
// Next make sure that w_cline_row is valid.
- if (!(curwin->w_valid & VALID_CROW)) {
- curs_rows(curwin);
+ if (!(wp->w_valid & VALID_CROW)) {
+ curs_rows(wp);
}
/*
* Compute the number of virtual columns.
*/
- if (curwin->w_cline_folded)
- /* In a folded line the cursor is always in the first column */
- startcol = curwin->w_virtcol = endcol = curwin->w_leftcol;
- else
- getvvcol(curwin, &curwin->w_cursor,
- &startcol, &(curwin->w_virtcol), &endcol);
+ if (wp->w_cline_folded) {
+ // In a folded line the cursor is always in the first column
+ startcol = wp->w_virtcol = endcol = wp->w_leftcol;
+ } else {
+ getvvcol(wp, &wp->w_cursor, &startcol, &(wp->w_virtcol), &endcol);
+ }
/* remove '$' from change command when cursor moves onto it */
if (startcol > dollar_vcol)
dollar_vcol = -1;
- int extra = curwin_col_off();
- curwin->w_wcol = curwin->w_virtcol + extra;
+ int extra = win_col_off(wp);
+ wp->w_wcol = wp->w_virtcol + extra;
endcol += extra;
- /*
- * Now compute w_wrow, counting screen lines from w_cline_row.
- */
- curwin->w_wrow = curwin->w_cline_row;
+ // Now compute w_wrow, counting screen lines from w_cline_row.
+ wp->w_wrow = wp->w_cline_row;
- int textwidth = curwin->w_width_inner - extra;
+ int textwidth = wp->w_width_inner - extra;
if (textwidth <= 0) {
// No room for text, put cursor in last char of window.
- curwin->w_wcol = curwin->w_width_inner - 1;
- curwin->w_wrow = curwin->w_height_inner - 1;
- } else if (curwin->w_p_wrap
- && curwin->w_width_inner != 0
+ wp->w_wcol = wp->w_width_inner - 1;
+ wp->w_wrow = wp->w_height_inner - 1;
+ } else if (wp->w_p_wrap
+ && wp->w_width_inner != 0
) {
- width = textwidth + curwin_col_off2();
+ width = textwidth + win_col_off2(wp);
- // long line wrapping, adjust curwin->w_wrow
- if (curwin->w_wcol >= curwin->w_width_inner) {
+ // long line wrapping, adjust wp->w_wrow
+ if (wp->w_wcol >= wp->w_width_inner) {
// this same formula is used in validate_cursor_col()
- n = (curwin->w_wcol - curwin->w_width_inner) / width + 1;
- curwin->w_wcol -= n * width;
- curwin->w_wrow += n;
+ n = (wp->w_wcol - wp->w_width_inner) / width + 1;
+ wp->w_wcol -= n * width;
+ wp->w_wrow += n;
/* When cursor wraps to first char of next line in Insert
* mode, the 'showbreak' string isn't shown, backup to first
* column */
if (*p_sbr && *get_cursor_pos_ptr() == NUL
- && curwin->w_wcol == (int)vim_strsize(p_sbr))
- curwin->w_wcol = 0;
+ && wp->w_wcol == (int)vim_strsize(p_sbr)) {
+ wp->w_wcol = 0;
+ }
}
- }
- /* No line wrapping: compute curwin->w_leftcol if scrolling is on and line
- * is not folded.
- * If scrolling is off, curwin->w_leftcol is assumed to be 0 */
- else if (may_scroll
- && !curwin->w_cline_folded
- ) {
- /*
- * If Cursor is left of the screen, scroll rightwards.
- * If Cursor is right of the screen, scroll leftwards
- * If we get closer to the edge than 'sidescrolloff', scroll a little
- * extra
- */
+ } else if (may_scroll
+ && !wp->w_cline_folded
+ ) {
+ // No line wrapping: compute wp->w_leftcol if scrolling is on and line
+ // is not folded.
+ // If scrolling is off, wp->w_leftcol is assumed to be 0
+
+ // If Cursor is left of the screen, scroll rightwards.
+ // If Cursor is right of the screen, scroll leftwards
+ // If we get closer to the edge than 'sidescrolloff', scroll a little
+ // extra
assert(siso <= INT_MAX);
- int off_left = startcol - curwin->w_leftcol - (int)siso;
+ int off_left = startcol - wp->w_leftcol - (int)siso;
int off_right =
- endcol - curwin->w_leftcol - curwin->w_width_inner + (int)siso + 1;
+ endcol - wp->w_leftcol - wp->w_width_inner + (int)siso + 1;
if (off_left < 0 || off_right > 0) {
int diff = (off_left < 0) ? -off_left: off_right;
/* When far off or not enough room on either side, put cursor in
* middle of window. */
int new_leftcol;
- if (p_ss == 0 || diff >= textwidth / 2 || off_right >= off_left)
- new_leftcol = curwin->w_wcol - extra - textwidth / 2;
- else {
+ if (p_ss == 0 || diff >= textwidth / 2 || off_right >= off_left) {
+ new_leftcol = wp->w_wcol - extra - textwidth / 2;
+ } else {
if (diff < p_ss) {
assert(p_ss <= INT_MAX);
diff = (int)p_ss;
}
- if (off_left < 0)
- new_leftcol = curwin->w_leftcol - diff;
- else
- new_leftcol = curwin->w_leftcol + diff;
+ if (off_left < 0) {
+ new_leftcol = wp->w_leftcol - diff;
+ } else {
+ new_leftcol = wp->w_leftcol + diff;
+ }
}
if (new_leftcol < 0)
new_leftcol = 0;
- if (new_leftcol != (int)curwin->w_leftcol) {
- curwin->w_leftcol = new_leftcol;
- win_check_anchored_floats(curwin);
- // screen has to be redrawn with new curwin->w_leftcol
- redraw_later(curwin, NOT_VALID);
+ if (new_leftcol != (int)wp->w_leftcol) {
+ wp->w_leftcol = new_leftcol;
+ win_check_anchored_floats(wp);
+ // screen has to be redrawn with new wp->w_leftcol
+ redraw_later(wp, NOT_VALID);
}
}
- curwin->w_wcol -= curwin->w_leftcol;
- } else if (curwin->w_wcol > (int)curwin->w_leftcol)
- curwin->w_wcol -= curwin->w_leftcol;
- else
- curwin->w_wcol = 0;
+ wp->w_wcol -= wp->w_leftcol;
+ } else if (wp->w_wcol > (int)wp->w_leftcol) {
+ wp->w_wcol -= wp->w_leftcol;
+ } else {
+ wp->w_wcol = 0;
+ }
/* Skip over filler lines. At the top use w_topfill, there
* may be some filler lines above the window. */
- if (curwin->w_cursor.lnum == curwin->w_topline)
- curwin->w_wrow += curwin->w_topfill;
- else
- curwin->w_wrow += diff_check_fill(curwin, curwin->w_cursor.lnum);
+ if (wp->w_cursor.lnum == wp->w_topline) {
+ wp->w_wrow += wp->w_topfill;
+ } else {
+ wp->w_wrow += diff_check_fill(wp, wp->w_cursor.lnum);
+ }
- prev_skipcol = curwin->w_skipcol;
+ prev_skipcol = wp->w_skipcol;
int plines = 0;
- if ((curwin->w_wrow >= curwin->w_height_inner
+ if ((wp->w_wrow >= wp->w_height_inner
|| ((prev_skipcol > 0
- || curwin->w_wrow + so >= curwin->w_height_inner)
+ || wp->w_wrow + so >= wp->w_height_inner)
&& (plines =
- plines_win_nofill(curwin, curwin->w_cursor.lnum, false)) - 1
- >= curwin->w_height_inner))
- && curwin->w_height_inner != 0
- && curwin->w_cursor.lnum == curwin->w_topline
+ plines_win_nofill(wp, wp->w_cursor.lnum, false)) - 1
+ >= wp->w_height_inner))
+ && wp->w_height_inner != 0
+ && wp->w_cursor.lnum == wp->w_topline
&& width > 0
- && curwin->w_width_inner != 0
+ && wp->w_width_inner != 0
) {
/* Cursor past end of screen. Happens with a single line that does
* not fit on screen. Find a skipcol to show the text around the
@@ -867,87 +873,88 @@ void curs_columns(
* 2: Less than "p_so" lines below
* 3: both of them */
extra = 0;
- if (curwin->w_skipcol + so * width > curwin->w_virtcol) {
+ if (wp->w_skipcol + so * width > wp->w_virtcol) {
extra = 1;
}
// Compute last display line of the buffer line that we want at the
// bottom of the window.
if (plines == 0) {
- plines = plines_win(curwin, curwin->w_cursor.lnum, false);
+ plines = plines_win(wp, wp->w_cursor.lnum, false);
}
plines--;
- if (plines > curwin->w_wrow + so) {
+ if (plines > wp->w_wrow + so) {
assert(so <= INT_MAX);
- n = curwin->w_wrow + (int)so;
+ n = wp->w_wrow + (int)so;
} else {
n = plines;
}
- if ((colnr_T)n >= curwin->w_height_inner + curwin->w_skipcol / width) {
+ if ((colnr_T)n >= wp->w_height_inner + wp->w_skipcol / width) {
extra += 2;
}
if (extra == 3 || plines < so * 2) {
// not enough room for 'scrolloff', put cursor in the middle
- n = curwin->w_virtcol / width;
- if (n > curwin->w_height_inner / 2) {
- n -= curwin->w_height_inner / 2;
+ n = wp->w_virtcol / width;
+ if (n > wp->w_height_inner / 2) {
+ n -= wp->w_height_inner / 2;
} else {
n = 0;
}
// don't skip more than necessary
- if (n > plines - curwin->w_height_inner + 1) {
- n = plines - curwin->w_height_inner + 1;
+ if (n > plines - wp->w_height_inner + 1) {
+ n = plines - wp->w_height_inner + 1;
}
- curwin->w_skipcol = n * width;
+ wp->w_skipcol = n * width;
} else if (extra == 1) {
// less then 'scrolloff' lines above, decrease skipcol
assert(so <= INT_MAX);
- extra = (curwin->w_skipcol + (int)so * width - curwin->w_virtcol
+ extra = (wp->w_skipcol + (int)so * width - wp->w_virtcol
+ width - 1) / width;
if (extra > 0) {
- if ((colnr_T)(extra * width) > curwin->w_skipcol)
- extra = curwin->w_skipcol / width;
- curwin->w_skipcol -= extra * width;
+ if ((colnr_T)(extra * width) > wp->w_skipcol) {
+ extra = wp->w_skipcol / width;
+ }
+ wp->w_skipcol -= extra * width;
}
} else if (extra == 2) {
// less then 'scrolloff' lines below, increase skipcol
- endcol = (n - curwin->w_height_inner + 1) * width;
- while (endcol > curwin->w_virtcol) {
+ endcol = (n - wp->w_height_inner + 1) * width;
+ while (endcol > wp->w_virtcol) {
endcol -= width;
}
- if (endcol > curwin->w_skipcol) {
- curwin->w_skipcol = endcol;
+ if (endcol > wp->w_skipcol) {
+ wp->w_skipcol = endcol;
}
}
- curwin->w_wrow -= curwin->w_skipcol / width;
- if (curwin->w_wrow >= curwin->w_height_inner) {
+ wp->w_wrow -= wp->w_skipcol / width;
+ if (wp->w_wrow >= wp->w_height_inner) {
// small window, make sure cursor is in it
- extra = curwin->w_wrow - curwin->w_height_inner + 1;
- curwin->w_skipcol += extra * width;
- curwin->w_wrow -= extra;
+ extra = wp->w_wrow - wp->w_height_inner + 1;
+ wp->w_skipcol += extra * width;
+ wp->w_wrow -= extra;
}
// extra could be either positive or negative
- extra = ((int)prev_skipcol - (int)curwin->w_skipcol) / width;
- win_scroll_lines(curwin, 0, extra);
+ extra = ((int)prev_skipcol - (int)wp->w_skipcol) / width;
+ win_scroll_lines(wp, 0, extra);
} else {
- curwin->w_skipcol = 0;
+ wp->w_skipcol = 0;
}
- if (prev_skipcol != curwin->w_skipcol) {
- redraw_later(curwin, NOT_VALID);
+ if (prev_skipcol != wp->w_skipcol) {
+ redraw_later(wp, NOT_VALID);
}
- /* Redraw when w_virtcol changes and 'cursorcolumn' is set */
- if (curwin->w_p_cuc && (curwin->w_valid & VALID_VIRTCOL) == 0
+ // Redraw when w_virtcol changes and 'cursorcolumn' is set
+ if (wp->w_p_cuc && (wp->w_valid & VALID_VIRTCOL) == 0
&& !pum_visible()) {
- redraw_later(curwin, SOME_VALID);
+ redraw_later(wp, SOME_VALID);
}
// now w_leftcol is valid, avoid check_cursor_moved() thinking otherwise
- curwin->w_valid_leftcol = curwin->w_leftcol;
+ wp->w_valid_leftcol = wp->w_leftcol;
- curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
+ wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
}
/// Compute the screen position of text character at "pos" in window "wp"
@@ -1231,7 +1238,7 @@ void scrolldown_clamp(void)
end_row += curwin->w_cline_height - 1 -
curwin->w_virtcol / curwin->w_width_inner;
}
- if (end_row < curwin->w_height_inner - get_scrolloff_value()) {
+ if (end_row < curwin->w_height_inner - get_scrolloff_value(curwin)) {
if (can_fill) {
++curwin->w_topfill;
check_topfill(curwin, true);
@@ -1271,7 +1278,7 @@ void scrollup_clamp(void)
validate_virtcol();
start_row -= curwin->w_virtcol / curwin->w_width_inner;
}
- if (start_row >= get_scrolloff_value()) {
+ if (start_row >= get_scrolloff_value(curwin)) {
if (curwin->w_topfill > 0) {
curwin->w_topfill--;
} else {
@@ -1289,22 +1296,22 @@ void scrollup_clamp(void)
* Returns the height of the added line in "lp->height".
* Lines above the first one are incredibly high: MAXCOL.
*/
-static void topline_back(lineoff_T *lp)
+static void topline_back(win_T *wp, lineoff_T *lp)
{
- if (lp->fill < diff_check_fill(curwin, lp->lnum)) {
- /* Add a filler line. */
- ++lp->fill;
+ if (lp->fill < diff_check_fill(wp, lp->lnum)) {
+ // Add a filler line
+ lp->fill++;
lp->height = 1;
} else {
--lp->lnum;
lp->fill = 0;
- if (lp->lnum < 1)
+ if (lp->lnum < 1) {
lp->height = MAXCOL;
- else if (hasFolding(lp->lnum, &lp->lnum, NULL))
- /* Add a closed fold */
+ } else if (hasFolding(lp->lnum, &lp->lnum, NULL)) {
+ // Add a closed fold
lp->height = 1;
- else {
- lp->height = plines_nofill(lp->lnum);
+ } else {
+ lp->height = plines_win_nofill(wp, lp->lnum, true);
}
}
}
@@ -1315,22 +1322,23 @@ static void topline_back(lineoff_T *lp)
* Returns the height of the added line in "lp->height".
* Lines below the last one are incredibly high.
*/
-static void botline_forw(lineoff_T *lp)
+static void botline_forw(win_T *wp, lineoff_T *lp)
{
- if (lp->fill < diff_check_fill(curwin, lp->lnum + 1)) {
- /* Add a filler line. */
- ++lp->fill;
+ if (lp->fill < diff_check_fill(wp, lp->lnum + 1)) {
+ // Add a filler line.
+ lp->fill++;
lp->height = 1;
} else {
++lp->lnum;
lp->fill = 0;
- if (lp->lnum > curbuf->b_ml.ml_line_count) {
+ assert(wp->w_buffer != 0);
+ if (lp->lnum > wp->w_buffer->b_ml.ml_line_count) {
lp->height = MAXCOL;
- } else if (hasFolding(lp->lnum, NULL, &lp->lnum)) {
+ } else if (hasFoldingWin(wp, lp->lnum, NULL, &lp->lnum, true, NULL)) {
// Add a closed fold
lp->height = 1;
} else {
- lp->height = plines_nofill(lp->lnum);
+ lp->height = plines_win_nofill(wp, lp->lnum, true);
}
}
}
@@ -1374,7 +1382,7 @@ void scroll_cursor_top(int min_scroll, int always)
linenr_T old_topline = curwin->w_topline;
linenr_T old_topfill = curwin->w_topfill;
linenr_T new_topline;
- int off = (int)get_scrolloff_value();
+ int off = (int)get_scrolloff_value(curwin);
if (mouse_dragging > 0)
off = mouse_dragging - 1;
@@ -1518,7 +1526,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
int old_valid = curwin->w_valid;
int old_empty_rows = curwin->w_empty_rows;
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
- long so = get_scrolloff_value();
+ long so = get_scrolloff_value(curwin);
if (set_topbot) {
used = 0;
@@ -1528,7 +1536,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
curwin->w_topline > 1;
curwin->w_topline = loff.lnum) {
loff.lnum = curwin->w_topline;
- topline_back(&loff);
+ topline_back(curwin, &loff);
if (loff.height == MAXCOL
|| used + loff.height > curwin->w_height_inner) {
break;
@@ -1542,8 +1550,9 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|| curwin->w_topfill != old_topfill
)
curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
- } else
- validate_botline();
+ } else {
+ validate_botline(curwin);
+ }
/* The lines of the cursor line itself are always used. */
used = plines_nofill(cln);
@@ -1586,8 +1595,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
break;
}
- /* Add one line above */
- topline_back(&loff);
+ // Add one line above
+ topline_back(curwin, &loff);
if (loff.height == MAXCOL) {
used = MAXCOL;
} else {
@@ -1609,8 +1618,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
}
if (boff.lnum < curbuf->b_ml.ml_line_count) {
- /* Add one line below */
- botline_forw(&boff);
+ // Add one line below
+ botline_forw(curwin, &boff);
used += boff.height;
if (used > curwin->w_height_inner) {
break;
@@ -1647,7 +1656,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
boff.lnum = curwin->w_topline - 1;
int i;
for (i = 0; i < scrolled && boff.lnum < curwin->w_botline; ) {
- botline_forw(&boff);
+ botline_forw(curwin, &boff);
i += boff.height;
++line_count;
}
@@ -1701,7 +1710,7 @@ void scroll_cursor_halfway(int atend)
while (topline > 1) {
if (below <= above) { /* add a line below the cursor first */
if (boff.lnum < curbuf->b_ml.ml_line_count) {
- botline_forw(&boff);
+ botline_forw(curwin, &boff);
used += boff.height;
if (used > curwin->w_height_inner) {
break;
@@ -1714,12 +1723,13 @@ void scroll_cursor_halfway(int atend)
}
}
- if (below > above) { /* add a line above the cursor */
- topline_back(&loff);
- if (loff.height == MAXCOL)
+ if (below > above) { // add a line above the cursor
+ topline_back(curwin, &loff);
+ if (loff.height == MAXCOL) {
used = MAXCOL;
- else
+ } else {
used += loff.height;
+ }
if (used > curwin->w_height_inner) {
break;
}
@@ -1751,8 +1761,8 @@ void cursor_correct(void)
* How many lines we would like to have above/below the cursor depends on
* whether the first/last line of the file is on screen.
*/
- int above_wanted = (int)get_scrolloff_value();
- int below_wanted = (int)get_scrolloff_value();
+ int above_wanted = (int)get_scrolloff_value(curwin);
+ int below_wanted = (int)get_scrolloff_value(curwin);
if (mouse_dragging > 0) {
above_wanted = mouse_dragging - 1;
below_wanted = mouse_dragging - 1;
@@ -1764,7 +1774,7 @@ void cursor_correct(void)
below_wanted = max_off;
}
}
- validate_botline();
+ validate_botline(curwin);
if (curwin->w_botline == curbuf->b_ml.ml_line_count + 1
&& mouse_dragging == 0) {
below_wanted = 0;
@@ -1848,21 +1858,19 @@ int onepage(Direction dir, long count)
int retval = OK;
lineoff_T loff;
linenr_T old_topline = curwin->w_topline;
- long so = get_scrolloff_value();
+ long so = get_scrolloff_value(curwin);
if (curbuf->b_ml.ml_line_count == 1) { /* nothing to do */
beep_flush();
return FAIL;
}
- for (; count > 0; --count) {
- validate_botline();
- /*
- * It's an error to move a page up when the first line is already on
- * the screen. It's an error to move a page down when the last line
- * is on the screen and the topline is 'scrolloff' lines from the
- * last line.
- */
+ for (; count > 0; count--) {
+ validate_botline(curwin);
+ // It's an error to move a page up when the first line is already on
+ // the screen. It's an error to move a page down when the last line
+ // is on the screen and the topline is 'scrolloff' lines from the
+ // last line.
if (dir == FORWARD
? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - so)
&& curwin->w_botline > curbuf->b_ml.ml_line_count)
@@ -1945,11 +1953,12 @@ int onepage(Direction dir, long count)
* at the bottom of the window. */
n = 0;
while (n <= curwin->w_height_inner && loff.lnum >= 1) {
- topline_back(&loff);
- if (loff.height == MAXCOL)
+ topline_back(curwin, &loff);
+ if (loff.height == MAXCOL) {
n = MAXCOL;
- else
+ } else {
n += loff.height;
+ }
}
if (loff.lnum < 1) { /* at begin of file */
curwin->w_topline = 1;
@@ -1958,11 +1967,11 @@ int onepage(Direction dir, long count)
} else {
/* Go two lines forward again. */
topline_botline(&loff);
- botline_forw(&loff);
- botline_forw(&loff);
+ botline_forw(curwin, &loff);
+ botline_forw(curwin, &loff);
botline_topline(&loff);
- /* We're at the wrong end of a fold now. */
- (void)hasFolding(loff.lnum, &loff.lnum, NULL);
+ // We're at the wrong end of a fold now.
+ (void)hasFoldingWin(curwin, loff.lnum, &loff.lnum, NULL, true, NULL);
/* Always scroll at least one line. Avoid getting stuck on
* very long lines. */
@@ -2046,10 +2055,11 @@ static void get_scroll_overlap(lineoff_T *lp, int dir)
return; /* no overlap */
lineoff_T loff0 = *lp;
- if (dir > 0)
- botline_forw(lp);
- else
- topline_back(lp);
+ if (dir > 0) {
+ botline_forw(curwin, lp);
+ } else {
+ topline_back(curwin, lp);
+ }
int h2 = lp->height;
if (h2 == MAXCOL || h2 + h1 > min_height) {
*lp = loff0; /* no overlap */
@@ -2057,10 +2067,11 @@ static void get_scroll_overlap(lineoff_T *lp, int dir)
}
lineoff_T loff1 = *lp;
- if (dir > 0)
- botline_forw(lp);
- else
- topline_back(lp);
+ if (dir > 0) {
+ botline_forw(curwin, lp);
+ } else {
+ topline_back(curwin, lp);
+ }
int h3 = lp->height;
if (h3 == MAXCOL || h3 + h2 > min_height) {
*lp = loff0; /* no overlap */
@@ -2068,10 +2079,11 @@ static void get_scroll_overlap(lineoff_T *lp, int dir)
}
lineoff_T loff2 = *lp;
- if (dir > 0)
- botline_forw(lp);
- else
- topline_back(lp);
+ if (dir > 0) {
+ botline_forw(curwin, lp);
+ } else {
+ topline_back(curwin, lp);
+ }
int h4 = lp->height;
if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height)
*lp = loff1; /* 1 line overlap */
@@ -2094,8 +2106,8 @@ void halfpage(bool flag, linenr_T Prenum)
int n = curwin->w_p_scr <= curwin->w_height_inner ? (int)curwin->w_p_scr
: curwin->w_height_inner;
- update_topline();
- validate_botline();
+ update_topline(curwin);
+ validate_botline(curwin);
int room = curwin->w_empty_rows + curwin->w_filler_rows;
if (flag) {
/*
@@ -2255,7 +2267,7 @@ void do_check_cursorbind(void)
// Only scroll when 'scrollbind' hasn't done this.
if (!curwin->w_p_scb) {
- update_topline();
+ update_topline(curwin);
}
curwin->w_redr_status = true;
}
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 68ef4cd41e..a0b439ac45 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -377,6 +377,10 @@ static void request_event(void **argv)
Channel *channel = e->channel;
MsgpackRpcRequestHandler handler = e->handler;
Error error = ERROR_INIT;
+ if (channel->rpc.closed) {
+ // channel was closed, abort any pending requests
+ goto free_ret;
+ }
Object result = handler.fn(channel->id, e->args, &error);
if (e->type == kMessageTypeRequest || ERROR_SET(&error)) {
// Send the response.
@@ -391,6 +395,8 @@ static void request_event(void **argv)
} else {
api_free_object(result);
}
+
+free_ret:
api_free_array(e->args);
channel_decref(channel);
xfree(e);
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 0293bb4a73..4e955667dc 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -168,7 +168,7 @@ static const struct nv_cmd {
{ NL, nv_down, 0, false },
{ Ctrl_K, nv_error, 0, 0 },
{ Ctrl_L, nv_clear, 0, 0 },
- { Ctrl_M, nv_down, 0, true },
+ { CAR, nv_down, 0, true },
{ Ctrl_N, nv_down, NV_STS, false },
{ Ctrl_O, nv_ctrlo, 0, 0 },
{ Ctrl_P, nv_up, NV_STS, false },
@@ -1261,7 +1261,7 @@ static void normal_redraw(NormalState *s)
{
// Before redrawing, make sure w_topline is correct, and w_leftcol
// if lines don't wrap, and w_skipcol if lines wrap.
- update_topline();
+ update_topline(curwin);
validate_cursor();
// If the cursor moves horizontally when 'concealcursor' is active, then the
@@ -1341,7 +1341,7 @@ static int normal_check(VimState *state)
} else if (do_redraw || stuff_empty()) {
// Need to make sure w_topline and w_leftcol are correct before
// normal_check_window_scrolled() is called.
- update_topline();
+ update_topline(curwin);
normal_check_cursor_moved(s);
normal_check_text_changed(s);
@@ -2375,10 +2375,10 @@ do_mouse (
* Also paste at the cursor if the current mode isn't in 'mouse' (only
* happens for the GUI).
*/
- if ((State & INSERT) || !mouse_has(MOUSE_NORMAL)) {
- if (regname == '.')
+ if ((State & INSERT)) {
+ if (regname == '.') {
insert_reg(regname, true);
- else {
+ } else {
if (regname == 0 && eval_has_provider("clipboard")) {
regname = '*';
}
@@ -2558,8 +2558,9 @@ do_mouse (
* on a status line */
if (VIsual_active)
jump_flags |= MOUSE_MAY_STOP_VIS;
- } else if (mouse_has(MOUSE_VISUAL))
+ } else {
jump_flags |= MOUSE_MAY_VIS;
+ }
} else if (which_button == MOUSE_RIGHT) {
if (is_click && VIsual_active) {
/*
@@ -2575,8 +2576,7 @@ do_mouse (
}
}
jump_flags |= MOUSE_FOCUS;
- if (mouse_has(MOUSE_VISUAL))
- jump_flags |= MOUSE_MAY_VIS;
+ jump_flags |= MOUSE_MAY_VIS;
}
}
@@ -2629,7 +2629,7 @@ do_mouse (
/* Set global flag that we are extending the Visual area with mouse
* dragging; temporarily minimize 'scrolloff'. */
- if (VIsual_active && is_drag && get_scrolloff_value()) {
+ if (VIsual_active && is_drag && get_scrolloff_value(curwin)) {
// In the very first line, allow scrolling one line
if (mouse_row == 0) {
mouse_dragging = 2;
@@ -2790,8 +2790,7 @@ do_mouse (
/* Handle double clicks, unless on status line */
else if (in_status_line) {
} else if (in_sep_line) {
- } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
- && mouse_has(MOUSE_VISUAL)) {
+ } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))) {
if (is_click || !VIsual_active) {
if (VIsual_active) {
orig_cursor = VIsual;
@@ -3052,57 +3051,57 @@ static bool find_is_eval_item(
return false;
}
-/*
- * Find the identifier under or to the right of the cursor.
- * "find_type" can have one of three values:
- * FIND_IDENT: find an identifier (keyword)
- * FIND_STRING: find any non-white string
- * FIND_IDENT + FIND_STRING: find any non-white string, identifier preferred.
- * FIND_EVAL: find text useful for C program debugging
- *
- * There are three steps:
- * 1. Search forward for the start of an identifier/string. Doesn't move if
- * already on one.
- * 2. Search backward for the start of this identifier/string.
- * This doesn't match the real Vi but I like it a little better and it
- * shouldn't bother anyone.
- * 3. Search forward to the end of this identifier/string.
- * When FIND_IDENT isn't defined, we backup until a blank.
- *
- * Returns the length of the string, or zero if no string is found.
- * If a string is found, a pointer to the string is put in "*string". This
- * string is not always NUL terminated.
- */
-size_t find_ident_under_cursor(char_u **string, int find_type)
+// Find the identifier under or to the right of the cursor.
+// "find_type" can have one of three values:
+// FIND_IDENT: find an identifier (keyword)
+// FIND_STRING: find any non-white text
+// FIND_IDENT + FIND_STRING: find any non-white text, identifier preferred.
+// FIND_EVAL: find text useful for C program debugging
+//
+// There are three steps:
+// 1. Search forward for the start of an identifier/text. Doesn't move if
+// already on one.
+// 2. Search backward for the start of this identifier/text.
+// This doesn't match the real Vi but I like it a little better and it
+// shouldn't bother anyone.
+// 3. Search forward to the end of this identifier/text.
+// When FIND_IDENT isn't defined, we backup until a blank.
+//
+// Returns the length of the text, or zero if no text is found.
+// If text is found, a pointer to the text is put in "*text". This
+// points into the current buffer line and is not always NUL terminated.
+size_t find_ident_under_cursor(char_u **text, int find_type)
+ FUNC_ATTR_NONNULL_ARG(1)
{
return find_ident_at_pos(curwin, curwin->w_cursor.lnum,
- curwin->w_cursor.col, string, find_type);
+ curwin->w_cursor.col, text, NULL, find_type);
}
/*
* Like find_ident_under_cursor(), but for any window and any position.
* However: Uses 'iskeyword' from the current window!.
*/
-size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
- char_u **string, int find_type)
-{
- char_u *ptr;
- int col = 0; /* init to shut up GCC */
+size_t find_ident_at_pos(
+ win_T *wp,
+ linenr_T lnum,
+ colnr_T startcol,
+ char_u **text,
+ int *textcol, // column where "text" starts, can be NULL
+ int find_type)
+ FUNC_ATTR_NONNULL_ARG(1, 4)
+{
+ int col = 0; // init to shut up GCC
int i;
int this_class = 0;
int prev_class;
int prevcol;
int bn = 0; // bracket nesting
- /*
- * if i == 0: try to find an identifier
- * if i == 1: try to find any non-white string
- */
- ptr = ml_get_buf(wp->w_buffer, lnum, false);
- for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i) {
- /*
- * 1. skip to start of identifier/string
- */
+ // if i == 0: try to find an identifier
+ // if i == 1: try to find any non-white text
+ char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
+ for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; i++) {
+ // 1. skip to start of identifier/text
col = startcol;
while (ptr[col] != NUL) {
// Stop at a ']' to evaluate "a[x]".
@@ -3120,7 +3119,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
bn = ptr[col] == ']';
//
- // 2. Back up to start of identifier/string.
+ // 2. Back up to start of identifier/text.
//
// Remember class of character under cursor.
if ((find_type & FIND_EVAL) && ptr[col] == ']') {
@@ -3143,7 +3142,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
col = prevcol;
}
- // If we don't want just any old string, or we've found an
+ // If we don't want just any old text, or we've found an
// identifier, stop searching.
if (this_class > 2) {
this_class = 2;
@@ -3154,7 +3153,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
}
if (ptr[col] == NUL || (i == 0 && this_class != 2)) {
- // Didn't find an identifier or string.
+ // Didn't find an identifier or text.
if (find_type & FIND_STRING) {
EMSG(_("E348: No string under cursor"));
} else {
@@ -3163,11 +3162,12 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol,
return 0;
}
ptr += col;
- *string = ptr;
+ *text = ptr;
+ if (textcol != NULL) {
+ *textcol = col;
+ }
- /*
- * 3. Find the end if the identifier/string.
- */
+ // 3. Find the end if the identifier/text.
bn = 0;
startcol -= col;
col = 0;
@@ -4135,7 +4135,7 @@ void scroll_redraw(int up, long count)
scrollup(count, true) :
scrolldown(count, true);
- if (get_scrolloff_value()) {
+ if (get_scrolloff_value(curwin)) {
// Adjust the cursor position for 'scrolloff'. Mark w_topline as
// valid, otherwise the screen jumps back at the end of the file.
cursor_correct();
@@ -4185,7 +4185,7 @@ static void nv_zet(cmdarg_T *cap)
int old_fen = curwin->w_p_fen;
bool undo = false;
- int l_p_siso = (int)get_sidescrolloff_value();
+ int l_p_siso = (int)get_sidescrolloff_value(curwin);
assert(l_p_siso <= INT_MAX);
if (ascii_isdigit(nchar)) {
@@ -4253,12 +4253,13 @@ dozet:
/* "z+", "z<CR>" and "zt": put cursor at top of screen */
case '+':
if (cap->count0 == 0) {
- /* No count given: put cursor at the line below screen */
- validate_botline(); /* make sure w_botline is valid */
- if (curwin->w_botline > curbuf->b_ml.ml_line_count)
+ // No count given: put cursor at the line below screen
+ validate_botline(curwin); // make sure w_botline is valid
+ if (curwin->w_botline > curbuf->b_ml.ml_line_count) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- else
+ } else {
curwin->w_cursor.lnum = curwin->w_botline;
+ }
}
FALLTHROUGH;
case NL:
@@ -5053,7 +5054,7 @@ static void nv_scroll(cmdarg_T *cap)
setpcmark();
if (cap->cmdchar == 'L') {
- validate_botline(); /* make sure curwin->w_botline is valid */
+ validate_botline(curwin); // make sure curwin->w_botline is valid
curwin->w_cursor.lnum = curwin->w_botline - 1;
if (cap->count1 - 1 >= curwin->w_cursor.lnum)
curwin->w_cursor.lnum = 1;
@@ -5074,7 +5075,7 @@ static void nv_scroll(cmdarg_T *cap)
/* Don't count filler lines above the window. */
used -= diff_check_fill(curwin, curwin->w_topline)
- curwin->w_topfill;
- validate_botline(); // make sure w_empty_rows is valid
+ validate_botline(curwin); // make sure w_empty_rows is valid
half = (curwin->w_height_inner - curwin->w_empty_rows + 1) / 2;
for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) {
// Count half he number of filler lines to be "below this
@@ -6653,16 +6654,15 @@ static void nv_g_cmd(cmdarg_T *cap)
VIsual = curwin->w_cursor;
curwin->w_cursor = tpos;
check_cursor();
- update_topline();
- /*
- * When called from normal "g" command: start Select mode when
- * 'selectmode' contains "cmd". When called for K_SELECT, always
- * start Select mode.
- */
- if (cap->arg)
+ update_topline(curwin);
+ // When called from normal "g" command: start Select mode when
+ // 'selectmode' contains "cmd". When called for K_SELECT, always
+ // start Select mode.
+ if (cap->arg) {
VIsual_select = true;
- else
+ } else {
may_start_select('c');
+ }
setmouse();
redraw_curbuf_later(INVERTED);
showmode();
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 40dd5f0b5c..052b07ed44 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1197,7 +1197,13 @@ int insert_reg(
retval = FAIL;
} else {
for (size_t i = 0; i < reg->y_size; i++) {
- stuffescaped((const char *)reg->y_array[i], literally);
+ if (regname == '-') {
+ AppendCharToRedobuff(Ctrl_R);
+ AppendCharToRedobuff(regname);
+ do_put(regname, NULL, BACKWARD, 1L, PUT_CURSEND);
+ } else {
+ stuffescaped((const char *)reg->y_array[i], literally);
+ }
// Insert a newline between lines and after last line if
// y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
@@ -1683,6 +1689,7 @@ int op_delete(oparg_T *oap)
(int)oap->line_count-1, n, deleted_bytes,
0, 0, 0, kExtmarkUndo);
}
+ auto_format(false, true);
}
msgmore(curbuf->b_ml.ml_line_count - old_lcount);
@@ -3547,15 +3554,21 @@ void ex_display(exarg_T *eap)
int name;
char_u *arg = eap->arg;
int clen;
+ char_u type[2];
if (arg != NULL && *arg == NUL)
arg = NULL;
int attr = HL_ATTR(HLF_8);
- /* Highlight title */
- MSG_PUTS_TITLE(_("\n--- Registers ---"));
+ // Highlight title
+ msg_puts_title(_("\nType Name Content"));
for (int i = -1; i < NUM_REGISTERS && !got_int; i++) {
name = get_register_name(i);
+ switch (get_reg_type(name, NULL)) {
+ case kMTLineWise: type[0] = 'l'; break;
+ case kMTCharWise: type[0] = 'c'; break;
+ default: type[0] = 'b'; break;
+ }
if (arg != NULL && vim_strchr(arg, name) == NULL) {
continue; /* did not ask for this register */
@@ -3580,11 +3593,14 @@ void ex_display(exarg_T *eap)
if (yb->y_array != NULL) {
msg_putchar('\n');
+ msg_puts(" ");
+ msg_putchar(type[0]);
+ msg_puts(" ");
msg_putchar('"');
msg_putchar(name);
MSG_PUTS(" ");
- int n = Columns - 6;
+ int n = Columns - 11;
for (size_t j = 0; j < yb->y_size && n > 1; j++) {
if (j) {
MSG_PUTS_ATTR("^J", attr);
@@ -3609,8 +3625,8 @@ void ex_display(exarg_T *eap)
*/
if ((p = get_last_insert()) != NULL
&& (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int) {
- MSG_PUTS("\n\". ");
- dis_msg(p, TRUE);
+ msg_puts("\n c \". ");
+ dis_msg(p, true);
}
/*
@@ -3618,8 +3634,8 @@ void ex_display(exarg_T *eap)
*/
if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
&& !got_int) {
- MSG_PUTS("\n\": ");
- dis_msg(last_cmdline, FALSE);
+ msg_puts("\n c \": ");
+ dis_msg(last_cmdline, false);
}
/*
@@ -3627,8 +3643,8 @@ void ex_display(exarg_T *eap)
*/
if (curbuf->b_fname != NULL
&& (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) {
- MSG_PUTS("\n\"% ");
- dis_msg(curbuf->b_fname, FALSE);
+ msg_puts("\n c \"% ");
+ dis_msg(curbuf->b_fname, false);
}
/*
@@ -3639,8 +3655,8 @@ void ex_display(exarg_T *eap)
linenr_T dummy;
if (buflist_name_nr(0, &fname, &dummy) != FAIL) {
- MSG_PUTS("\n\"# ");
- dis_msg(fname, FALSE);
+ msg_puts("\n c \"# ");
+ dis_msg(fname, false);
}
}
@@ -3649,8 +3665,8 @@ void ex_display(exarg_T *eap)
*/
if (last_search_pat() != NULL
&& (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int) {
- MSG_PUTS("\n\"/ ");
- dis_msg(last_search_pat(), FALSE);
+ msg_puts("\n c \"/ ");
+ dis_msg(last_search_pat(), false);
}
/*
@@ -3658,8 +3674,8 @@ void ex_display(exarg_T *eap)
*/
if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
&& !got_int) {
- MSG_PUTS("\n\"= ");
- dis_msg(expr_line, FALSE);
+ msg_puts("\n c \"= ");
+ dis_msg(expr_line, false);
}
}
@@ -3669,9 +3685,10 @@ void ex_display(exarg_T *eap)
*/
static void
dis_msg(
- char_u *p,
- int skip_esc /* if TRUE, ignore trailing ESC */
+ const char_u *p,
+ bool skip_esc // if true, ignore trailing ESC
)
+ FUNC_ATTR_NONNULL_ALL
{
int n;
int l;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 0034117ddc..47b9e9bb07 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -206,7 +206,6 @@ typedef struct vimoption {
// local option: indirect option index
char_u *def_val[2]; // default values for variable (vi and vim)
LastSet last_set; // script in which the option was last set
-# define SCTX_INIT , { 0, 0, 0 }
} vimoption_T;
#define VI_DEFAULT 0 // def_val[VI_DEFAULT] is Vi default value
@@ -307,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 };
@@ -321,7 +320,7 @@ static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2",
"auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9",
"yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8",
"yes:9", "number", NULL };
-static char *(p_fdc_values[]) = { "auto:1", "auto:2",
+static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2",
"auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
@@ -352,9 +351,6 @@ void set_init_1(bool clean_arg)
langmap_init();
- // Be nocompatible
- p_cp = false;
-
/*
* Find default value for 'shell' option.
* Don't use it if it is empty.
@@ -683,7 +679,7 @@ set_options_default(
{
for (int i = 0; options[i].fullname; i++) {
if (!(options[i].flags & P_NODEFAULT)) {
- set_option_default(i, opt_flags, p_cp);
+ set_option_default(i, opt_flags, false);
}
}
@@ -763,7 +759,7 @@ void set_init_2(bool headless)
// which results in the actual value computed from the window height.
idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
- set_option_default(idx, OPT_LOCAL, p_cp);
+ set_option_default(idx, OPT_LOCAL, false);
}
comp_col();
@@ -1113,7 +1109,7 @@ int do_set(
if (vim_strchr((char_u *)"?=:!&<", nextchar) != NULL) {
arg += len;
- cp_val = p_cp;
+ cp_val = false;
if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') {
if (arg[3] == 'm') { // "opt&vim": set to Vim default
cp_val = false;
@@ -1370,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) {
@@ -2943,7 +2943,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) {
@@ -3214,11 +3214,7 @@ ambw_end:
}
if (varp == &p_mouse) {
- if (*p_mouse == NUL) {
- ui_call_mouse_off();
- } else {
- setmouse(); // in case 'mouse' changed
- }
+ setmouse(); // in case 'mouse' changed
}
if (curwin->w_curswant != MAXCOL
@@ -3617,10 +3613,14 @@ static void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
{
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
int indir = (int)options[opt_idx].indir;
- const LastSet last_set = { .script_ctx =
- { script_ctx.sc_sid, script_ctx.sc_seq,
- script_ctx.sc_lnum + sourcing_lnum },
- current_channel_id };
+ const LastSet last_set = {
+ .script_ctx = {
+ script_ctx.sc_sid,
+ script_ctx.sc_seq,
+ script_ctx.sc_lnum + sourcing_lnum
+ },
+ current_channel_id
+ };
// Remember where the option was set. For local options need to do that
// in the buffer or window structure.
@@ -4338,6 +4338,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
char buf_old[NUMBUFLEN];
char buf_new[NUMBUFLEN];
char buf_type[7];
+
vim_snprintf(buf_old, ARRAY_SIZE(buf_old), "%ld", old_value);
vim_snprintf(buf_new, ARRAY_SIZE(buf_new), "%ld", value);
vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
@@ -4950,7 +4951,7 @@ static int optval_default(vimoption_T *p, char_u *varp)
if (varp == NULL) {
return true; // hidden option is always at default
}
- dvi = ((p->flags & P_VI_DEF) || p_cp) ? VI_DEFAULT : VIM_DEFAULT;
+ dvi = (p->flags & P_VI_DEF) ? VI_DEFAULT : VIM_DEFAULT;
if (p->flags & P_NUM) {
return *(long *)varp == (long)(intptr_t)p->def_val[dvi];
}
@@ -4983,11 +4984,7 @@ void ui_refresh_options(void)
ui_call_option_set(name, value);
}
if (p_mouse != NULL) {
- if (*p_mouse == NUL) {
- ui_call_mouse_off();
- } else {
- setmouse();
- }
+ setmouse();
}
}
@@ -6808,15 +6805,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;
}
@@ -7159,18 +7156,90 @@ dict_T *get_winbuf_options(const int bufopt)
/// Return the effective 'scrolloff' value for the current window, using the
/// global value when appropriate.
-long get_scrolloff_value(void)
+long get_scrolloff_value(win_T *wp)
{
// Disallow scrolloff in terminal-mode. #11915
if (State & TERM_FOCUS) {
return 0;
}
- return curwin->w_p_so < 0 ? p_so : curwin->w_p_so;
+ return wp->w_p_so < 0 ? p_so : wp->w_p_so;
}
/// Return the effective 'sidescrolloff' value for the current window, using the
/// global value when appropriate.
-long get_sidescrolloff_value(void)
+long get_sidescrolloff_value(win_T *wp)
{
- return curwin->w_p_siso < 0 ? p_siso : curwin->w_p_siso;
+ return wp->w_p_siso < 0 ? p_siso : wp->w_p_siso;
+}
+
+Dictionary get_vimoption(String name, Error *err)
+{
+ int opt_idx = findoption_len((const char *)name.data, name.size);
+ if (opt_idx < 0) {
+ api_set_error(err, kErrorTypeValidation, "no such option: '%s'", name.data);
+ return (Dictionary)ARRAY_DICT_INIT;
+ }
+ return vimoption2dict(&options[opt_idx]);
+}
+
+Dictionary get_all_vimoptions(void)
+{
+ Dictionary retval = ARRAY_DICT_INIT;
+ for (size_t i = 0; i < PARAM_COUNT; i++) {
+ Dictionary opt_dict = vimoption2dict(&options[i]);
+ PUT(retval, options[i].fullname, DICTIONARY_OBJ(opt_dict));
+ }
+ return retval;
+}
+
+static Dictionary vimoption2dict(vimoption_T *opt)
+{
+ Dictionary dict = ARRAY_DICT_INIT;
+
+ PUT(dict, "name", CSTR_TO_OBJ(opt->fullname));
+ PUT(dict, "shortname", CSTR_TO_OBJ(opt->shortname));
+
+ const char *scope;
+ if (opt->indir & PV_BUF) {
+ scope = "buf";
+ } else if (opt->indir & PV_WIN) {
+ scope = "win";
+ } else {
+ scope = "global";
+ }
+
+ PUT(dict, "scope", CSTR_TO_OBJ(scope));
+
+ // welcome to the jungle
+ PUT(dict, "global_local", BOOL(opt->indir & PV_BOTH));
+ PUT(dict, "commalist", BOOL(opt->flags & P_COMMA));
+ PUT(dict, "flaglist", BOOL(opt->flags & P_FLAGLIST));
+
+ PUT(dict, "was_set", BOOL(opt->flags & P_WAS_SET));
+
+ PUT(dict, "last_set_sid", INTEGER_OBJ(opt->last_set.script_ctx.sc_sid));
+ PUT(dict, "last_set_linenr", INTEGER_OBJ(opt->last_set.script_ctx.sc_lnum));
+ PUT(dict, "last_set_chan", INTEGER_OBJ((int64_t)opt->last_set.channel_id));
+
+ const char *type;
+ Object def;
+ // TODO(bfredl): do you even nocp?
+ char_u *def_val = opt->def_val[(opt->flags & P_VI_DEF)
+ ? VI_DEFAULT : VIM_DEFAULT];
+ if (opt->flags & P_STRING) {
+ type = "string";
+ def = CSTR_TO_OBJ(def_val ? (char *)def_val : "");
+ } else if (opt->flags & P_NUM) {
+ type = "number";
+ def = INTEGER_OBJ((Integer)(intptr_t)def_val);
+ } else if (opt->flags & P_BOOL) {
+ type = "boolean";
+ def = BOOL((intptr_t)def_val);
+ } else {
+ type = ""; def = NIL;
+ }
+ PUT(dict, "type", CSTR_TO_OBJ(type));
+ PUT(dict, "default", def);
+
+ return dict;
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index af0ea7f4a2..683afc670e 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"
@@ -372,7 +377,6 @@ EXTERN long p_cwh; // 'cmdwinheight'
EXTERN long p_ch; // 'cmdheight'
EXTERN long p_columns; // 'columns'
EXTERN int p_confirm; // 'confirm'
-EXTERN int p_cp; // 'compatible'
EXTERN char_u *p_cot; // 'completeopt'
# ifdef BACKSLASH_IN_FILENAME
EXTERN char_u *p_csl; // 'completeslash'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 64a09dc2b4..df2bfbce34 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2313,6 +2313,7 @@ return {
deny_duplicates=true,
vi_def=true,
secure=true,
+ expand=true,
varname='p_shadafile',
defaults={if_true={vi=""}}
},
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/input.c b/src/nvim/os/input.c
index b7878d9da8..9d6518841a 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -393,7 +393,7 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
prof_inchar_enter();
}
- if ((ms == - 1 || ms > 0) && events == NULL && !input_eof) {
+ if ((ms == - 1 || ms > 0) && events != main_loop.events && !input_eof) {
// The pending input provoked a blocking wait. Do special events now. #6247
blocking = true;
multiqueue_process_events(ch_before_blocking_events);
diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c
index 603191a0ff..b63faacaae 100644
--- a/src/nvim/os/lang.c
+++ b/src/nvim/os/lang.c
@@ -8,9 +8,12 @@
# undef Boolean
#endif
+#include "auto/config.h"
+
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
+
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index 9374693550..16e17a9c60 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -5,6 +5,8 @@
#include <uv.h>
+#include "auto/config.h"
+
#include "nvim/ascii.h"
#include "nvim/os/os.h"
#include "nvim/garray.h"
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index f242b7d71a..aef7ffa397 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -742,6 +742,7 @@ static int pum_set_selected(int n, int repeat)
// Edit a new, empty buffer. Set options for a "wipeout"
// buffer.
set_option_value("swf", 0L, NULL, OPT_LOCAL);
+ set_option_value("bl", 0L, NULL, OPT_LOCAL);
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
set_option_value("diff", 0L, NULL, OPT_LOCAL);
@@ -808,7 +809,7 @@ static int pum_set_selected(int n, int repeat)
no_u_sync++;
win_enter(curwin_save, true);
no_u_sync--;
- update_topline();
+ update_topline(curwin);
}
// Update the screen before drawing the popup menu.
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 7fdc998e20..a625c09f78 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -143,6 +143,7 @@ struct efm_S {
// 'E' error message
// 'W' warning message
// 'I' informational message
+ // 'N' note message
// 'C' continuation line
// 'Z' end of multi-line message
// 'G' general, unspecific message
@@ -457,7 +458,7 @@ static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo,
if (vim_strchr((char_u *)"+-", *efmp) != NULL) {
efminfo->flags = *efmp++;
}
- if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) {
+ if (vim_strchr((char_u *)"DXAEWINCZGOPQ", *efmp) != NULL) {
efminfo->prefix = *efmp;
} else {
snprintf((char *)errmsg, errmsglen,
@@ -967,7 +968,7 @@ restofline:
fmt_start = fmt_ptr;
}
- if (vim_strchr((char_u *)"AEWI", idx) != NULL) {
+ if (vim_strchr((char_u *)"AEWIN", idx) != NULL) {
qfl->qf_multiline = true; // start of a multi-line message
qfl->qf_multiignore = false; // reset continuation
} else if (vim_strchr((char_u *)"CZ", idx) != NULL) {
@@ -1499,7 +1500,7 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr,
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
return QF_FAIL;
}
- if (vim_strchr((char_u *)"EWI", idx) != NULL) {
+ if (vim_strchr((char_u *)"EWIN", idx) != NULL) {
fields->type = idx;
} else {
fields->type = 0;
@@ -3300,6 +3301,24 @@ void qf_history(exarg_T *eap)
qf_info_T *qi = qf_cmd_get_stack(eap, false);
int i;
+ if (eap->addr_count > 0) {
+ if (qi == NULL) {
+ EMSG(_(e_loclist));
+ return;
+ }
+
+ // Jump to the specified quickfix list
+ if (eap->line2 > 0 && eap->line2 <= qi->qf_listcount) {
+ qi->qf_curlist = (int)(eap->line2 - 1);
+ qf_msg(qi, qi->qf_curlist, "");
+ qf_update_buffer(qi, NULL);
+ } else {
+ EMSG(_(e_invrange));
+ }
+
+ return;
+ }
+
if (qf_stack_empty(qi)) {
MSG(_("No entries"));
} else {
@@ -3414,11 +3433,13 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount,
// e or E 0 " error"
// w or W 0 " warning"
// i or I 0 " info"
+// n or N 0 " note"
// 0 0 ""
// other 0 " c"
// e or E n " error n"
// w or W n " warning n"
// i or I n " info n"
+// n or N n " note n"
// 0 n " error n"
// other n " c n"
// 1 x "" :helpgrep
@@ -3428,15 +3449,17 @@ static char_u *qf_types(int c, int nr)
static char_u cc[3];
char_u *p;
- if (c == 'W' || c == 'w')
+ if (c == 'W' || c == 'w') {
p = (char_u *)" warning";
- else if (c == 'I' || c == 'i')
+ } else if (c == 'I' || c == 'i') {
p = (char_u *)" info";
- else if (c == 'E' || c == 'e' || (c == 0 && nr > 0))
+ } else if (c == 'N' || c == 'n') {
+ p = (char_u *)" note";
+ } else if (c == 'E' || c == 'e' || (c == 0 && nr > 0)) {
p = (char_u *)" error";
- else if (c == 0 || c == 1)
+ } else if (c == 0 || c == 1) {
p = (char_u *)"";
- else {
+ } else {
cc[0] = ' ';
cc[1] = (char_u)c;
cc[2] = NUL;
@@ -3622,7 +3645,7 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
// Set the options for the quickfix buffer/window (if not already done)
// Do this even if the quickfix buffer was already present, as an autocmd
// might have previously deleted (:bdelete) the quickfix buffer.
- if (curbuf->b_p_bt[0] != 'q') {
+ if (!bt_quickfix(curbuf)) {
qf_set_cwindow_options();
}
@@ -3696,7 +3719,7 @@ void ex_copen(exarg_T *eap)
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = 0;
check_cursor();
- update_topline(); // scroll to show the line
+ update_topline(curwin); // scroll to show the line
}
// Move the cursor in the quickfix window to "lnum".
@@ -3710,7 +3733,7 @@ static void qf_win_goto(win_T *win, linenr_T lnum)
curwin->w_cursor.col = 0;
curwin->w_cursor.coladd = 0;
curwin->w_curswant = 0;
- update_topline(); // scroll to show the line
+ update_topline(curwin); // scroll to show the line
redraw_later(curwin, VALID);
curwin->w_redr_status = true; // update ruler
curwin = old_curwin;
@@ -3824,17 +3847,21 @@ static buf_T *qf_find_buf(qf_info_T *qi)
return NULL;
}
-/// Update the w:quickfix_title variable in the quickfix/location list window
+/// Update the w:quickfix_title variable in the quickfix/location list window in
+/// all the tab pages.
static void qf_update_win_titlevar(qf_info_T *qi)
+ FUNC_ATTR_NONNULL_ALL
{
- win_T *win;
+ qf_list_T *const qfl = qf_get_curlist(qi);
+ win_T *const save_curwin = curwin;
- if ((win = qf_find_win(qi)) != NULL) {
- win_T *curwin_save = curwin;
- curwin = win;
- qf_set_title_var(qf_get_curlist(qi));
- curwin = curwin_save;
+ FOR_ALL_TAB_WINDOWS(tp, win) {
+ if (is_qf_win(win, qi)) {
+ curwin = win;
+ qf_set_title_var(qfl);
+ }
}
+ curwin = save_curwin;
}
// Find the quickfix buffer. If it exists, update the contents.
@@ -4265,11 +4292,22 @@ static char_u *get_mef_name(void)
return name;
}
-/// Returns the number of valid entries in the current quickfix/location list.
+/// Returns the number of entries in the current quickfix/location list.
size_t qf_get_size(exarg_T *eap)
FUNC_ATTR_NONNULL_ALL
{
qf_info_T *qi;
+
+ if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
+ return 0;
+ }
+ return (size_t)qf_get_curlist(qi)->qf_count;
+}
+
+/// Returns the number of valid entries in the current quickfix/location list.
+size_t qf_get_valid_size(exarg_T *eap)
+{
+ qf_info_T *qi;
qf_list_T *qfl;
if ((qi = qf_cmd_get_stack(eap, false)) == NULL) {
@@ -4558,74 +4596,150 @@ static qfline_T * qf_find_last_entry_on_line(qfline_T *entry, int *errornr)
return entry;
}
-/// Find the first quickfix entry below line 'lnum' in buffer 'bnr'.
+// Returns true if the specified quickfix entry is
+// after the given line (linewise is true)
+// or after the line and column.
+static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum > pos->lnum;
+ }
+ return qfp->qf_lnum > pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// before the given line (linewise is true)
+// or before the line and column.
+static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum < pos->lnum;
+ }
+ return qfp->qf_lnum < pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// on or after the given line (linewise is true)
+// or on or after the line and column.
+static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum >= pos->lnum;
+ }
+ return qfp->qf_lnum > pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col);
+}
+
+// Returns true if the specified quickfix entry is
+// on or before the given line (linewise is true)
+// or on or before the line and column.
+static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos,
+ bool linewise)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (linewise) {
+ return qfp->qf_lnum <= pos->lnum;
+ }
+ return qfp->qf_lnum < pos->lnum
+ || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col);
+}
+
+/// Find the first quickfix entry after position 'pos' in buffer 'bnr'.
+/// If 'linewise' is true, returns the entry after the specified line and treats
+/// multiple entries on a single line as one. Otherwise returns the entry after
+/// the specified line and column.
/// 'qfp' points to the very first entry in the buffer and 'errornr' is the
/// index of the very first entry in the quickfix list.
-/// Returns NULL if an entry is not found after 'lnum'.
-static qfline_T *qf_find_entry_on_next_line(int bnr,
- linenr_T lnum,
- qfline_T *qfp,
- int *errornr)
+/// Returns NULL if an entry is not found after 'pos'.
+static qfline_T *qf_find_entry_after_pos(
+ int bnr,
+ const pos_T *pos,
+ bool linewise,
+ qfline_T *qfp,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
- if (qfp->qf_lnum > lnum) {
- // First entry is after line 'lnum'
+ if (qf_entry_after_pos(qfp, pos, linewise)) {
+ // First entry is after postion 'pos'
return qfp;
}
- // Find the entry just before or at the line 'lnum'
+ // Find the entry just before or at the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
- && qfp->qf_next->qf_lnum <= lnum) {
+ && qf_entry_on_or_before_pos(qfp->qf_next, pos, linewise)) {
qfp = qfp->qf_next;
(*errornr)++;
}
if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr) {
- // No entries found after 'lnum'
+ // No entries found after position 'pos'
return NULL;
}
- // Use the entry just after line 'lnum'
+ // Use the entry just after position 'pos'
qfp = qfp->qf_next;
(*errornr)++;
return qfp;
}
-/// Find the first quickfix entry before line 'lnum' in buffer 'bnr'.
+/// Find the first quickfix entry before position 'pos' in buffer 'bnr'.
+/// If 'linewise' is true, returns the entry before the specified line and
+/// treats multiple entries on a single line as one. Otherwise returns the entry
+/// before the specified line and column.
/// 'qfp' points to the very first entry in the buffer and 'errornr' is the
/// index of the very first entry in the quickfix list.
-/// Returns NULL if an entry is not found before 'lnum'.
-static qfline_T *qf_find_entry_on_prev_line(int bnr,
- linenr_T lnum,
- qfline_T *qfp,
- int *errornr)
+/// Returns NULL if an entry is not found before 'pos'.
+static qfline_T *qf_find_entry_before_pos(
+ int bnr,
+ const pos_T *pos,
+ bool linewise,
+ qfline_T *qfp,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
- // Find the entry just before the line 'lnum'
+ // Find the entry just before the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
- && qfp->qf_next->qf_lnum < lnum) {
+ && qf_entry_before_pos(qfp->qf_next, pos, linewise)) {
qfp = qfp->qf_next;
(*errornr)++;
}
- if (qfp->qf_lnum >= lnum) { // entry is after 'lnum'
+ if (qf_entry_on_or_after_pos(qfp, pos, linewise)) {
return NULL;
}
- // If multiple entries are on the same line, then use the first entry
- qfp = qf_find_first_entry_on_line(qfp, errornr);
+ if (linewise) {
+ // If multiple entries are on the same line, then use the first entry
+ qfp = qf_find_first_entry_on_line(qfp, errornr);
+ }
return qfp;
}
-/// Find a quickfix entry in 'qfl' closest to line 'lnum' in buffer 'bnr' in
+/// Find a quickfix entry in 'qfl' closest to position 'pos' in buffer 'bnr' in
/// the direction 'dir'.
-static qfline_T *qf_find_closest_entry(qf_list_T *qfl,
- int bnr,
- linenr_T lnum,
- int dir,
- int *errornr)
+static qfline_T *qf_find_closest_entry(
+ qf_list_T *qfl,
+ int bnr,
+ const pos_T *pos,
+ Direction dir,
+ bool linewise,
+ int *errornr
+)
+ FUNC_ATTR_NONNULL_ALL
{
qfline_T *qfp;
@@ -4638,33 +4752,38 @@ static qfline_T *qf_find_closest_entry(qf_list_T *qfl,
}
if (dir == FORWARD) {
- qfp = qf_find_entry_on_next_line(bnr, lnum, qfp, errornr);
+ qfp = qf_find_entry_after_pos(bnr, pos, linewise, qfp, errornr);
} else {
- qfp = qf_find_entry_on_prev_line(bnr, lnum, qfp, errornr);
+ qfp = qf_find_entry_before_pos(bnr, pos, linewise, qfp, errornr);
}
return qfp;
}
-/// Get the nth quickfix entry below the specified entry treating multiple
-/// entries on a single line as one. Searches forward in the list.
-static void qf_get_nth_below_entry(qfline_T *entry,
- int *errornr,
- linenr_T n)
+/// Get the nth quickfix entry below the specified entry. Searches forward in
+/// the list. If linewise is true, then treat multiple entries on a single line
+/// as one.
+static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n,
+ bool linewise, int *errornr)
+ FUNC_ATTR_NONNULL_ALL
{
while (n-- > 0 && !got_int) {
// qfline_T *first_entry = entry;
int first_errornr = *errornr;
- // Treat all the entries on the same line in this file as one
- entry = qf_find_last_entry_on_line(entry, errornr);
+ if (linewise) {
+ // Treat all the entries on the same line in this file as one
+ entry = qf_find_last_entry_on_line(entry, errornr);
+ }
if (entry->qf_next == NULL
|| entry->qf_next->qf_fnum != entry->qf_fnum) {
- // If multiple entries are on the same line, then use the first
- // entry
- // entry = first_entry;
- *errornr = first_errornr;
+ if (linewise) {
+ // If multiple entries are on the same line, then use the first
+ // entry
+ // entry = first_entry;
+ *errornr = first_errornr;
+ }
break;
}
@@ -4673,11 +4792,12 @@ static void qf_get_nth_below_entry(qfline_T *entry,
}
}
-/// Get the nth quickfix entry above the specified entry treating multiple
-/// entries on a single line as one. Searches backwards in the list.
-static void qf_get_nth_above_entry(qfline_T *entry,
- int *errornr,
- linenr_T n)
+/// Get the nth quickfix entry above the specified entry. Searches backwards in
+/// the list. If linewise is TRUE, then treat multiple entries on a single line
+/// as one.
+static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n,
+ bool linewise, int *errornr)
+ FUNC_ATTR_NONNULL_ALL
{
while (n-- > 0 && !got_int) {
if (entry->qf_prev == NULL
@@ -4688,25 +4808,30 @@ static void qf_get_nth_above_entry(qfline_T *entry,
entry = entry->qf_prev;
(*errornr)--;
- // If multiple entries are on the same line, then use the first entry
- entry = qf_find_first_entry_on_line(entry, errornr);
+ if (linewise) {
+ entry = qf_find_first_entry_on_line(entry, errornr);
+ }
}
}
-/// Find the n'th quickfix entry adjacent to line 'lnum' in buffer 'bnr' in the
-/// specified direction.
-/// Returns the error number in the quickfix list or 0 if an entry is not found.
-static int qf_find_nth_adj_entry(qf_list_T *qfl,
- int bnr,
- linenr_T lnum,
- linenr_T n,
- int dir)
+/// Find the n'th quickfix entry adjacent to position 'pos' in buffer 'bnr' in
+/// the specified direction. Returns the error number in the quickfix list or 0
+/// if an entry is not found.
+static int qf_find_nth_adj_entry(
+ qf_list_T *qfl,
+ int bnr,
+ pos_T *pos,
+ linenr_T n,
+ Direction dir,
+ bool linewise
+)
+ FUNC_ATTR_NONNULL_ALL
{
- qfline_T *adj_entry;
int errornr;
- // Find an entry closest to the specified line
- adj_entry = qf_find_closest_entry(qfl, bnr, lnum, dir, &errornr);
+ // Find an entry closest to the specified position
+ qfline_T *const adj_entry = qf_find_closest_entry(qfl, bnr, pos, dir,
+ linewise, &errornr);
if (adj_entry == NULL) {
return 0;
}
@@ -4714,24 +4839,25 @@ static int qf_find_nth_adj_entry(qf_list_T *qfl,
if (--n > 0) {
// Go to the n'th entry in the current buffer
if (dir == FORWARD) {
- qf_get_nth_below_entry(adj_entry, &errornr, n);
+ qf_get_nth_below_entry(adj_entry, n, linewise, &errornr);
} else {
- qf_get_nth_above_entry(adj_entry, &errornr, n);
+ qf_get_nth_above_entry(adj_entry, n, linewise, &errornr);
}
}
return errornr;
}
-/// Jump to a quickfix entry in the current file nearest to the current line.
-/// ":cabove", ":cbelow", ":labove" and ":lbelow" commands
+/// Jump to a quickfix entry in the current file nearest to the current line or
+/// current line/col.
+/// ":cabove", ":cbelow", ":labove", ":lbelow", ":cafter", ":cbefore",
+/// ":lafter" and ":lbefore" commands
void ex_cbelow(exarg_T *eap)
{
qf_info_T *qi;
qf_list_T *qfl;
int dir;
int buf_has_flag;
- int errornr = 0;
if (eap->addr_count > 0 && eap->line2 <= 0) {
EMSG(_(e_invrange));
@@ -4739,7 +4865,8 @@ void ex_cbelow(exarg_T *eap)
}
// Check whether the current buffer has any quickfix entries
- if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow) {
+ if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_cbefore || eap->cmdidx == CMD_cafter) {
buf_has_flag = BUF_HAS_QF_ENTRY;
} else {
buf_has_flag = BUF_HAS_LL_ENTRY;
@@ -4760,14 +4887,30 @@ void ex_cbelow(exarg_T *eap)
return;
}
- if (eap->cmdidx == CMD_cbelow || eap->cmdidx == CMD_lbelow) {
+ if (eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_lbelow
+ || eap->cmdidx == CMD_cafter
+ || eap->cmdidx == CMD_lafter) {
+ // Forward motion commands
dir = FORWARD;
} else {
dir = BACKWARD;
}
- errornr = qf_find_nth_adj_entry(qfl, curbuf->b_fnum, curwin->w_cursor.lnum,
- eap->addr_count > 0 ? eap->line2 : 0, dir);
+ pos_T pos = curwin->w_cursor;
+ // A quickfix entry column number is 1 based whereas cursor column
+ // number is 0 based. Adjust the column number.
+ pos.col++;
+ const int errornr = qf_find_nth_adj_entry(
+ qfl,
+ curbuf->b_fnum,
+ &pos,
+ eap->addr_count > 0 ? eap->line2 : 0,
+ dir,
+ eap->cmdidx == CMD_cbelow
+ || eap->cmdidx == CMD_lbelow
+ || eap->cmdidx == CMD_cabove
+ || eap->cmdidx == CMD_labove);
if (errornr > 0) {
qf_jump(qi, 0, errornr, false);
@@ -6814,8 +6957,9 @@ void ex_helpgrep(exarg_T *eap)
if (au_name != NULL) {
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
curbuf->b_fname, true, curbuf);
- if (!new_qi && IS_LL_STACK(qi) && qf_find_buf(qi) == NULL) {
- // autocommands made "qi" invalid
+ // When adding a location list to an existing location list stack,
+ // if the autocmd made the stack invalid, then just return.
+ if (!new_qi && IS_LL_STACK(qi) && qf_find_win_with_loclist(qi) == NULL) {
decr_quickfix_busy();
return;
}
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 1c88bd4ba4..a2589ac431 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -3605,6 +3605,24 @@ theend:
if (backpos.ga_maxlen > BACKPOS_INITIAL)
ga_clear(&backpos);
+ if (retval > 0) {
+ // Make sure the end is never before the start. Can happen when \zs
+ // and \ze are used.
+ if (REG_MULTI) {
+ const lpos_T *const start = &rex.reg_mmatch->startpos[0];
+ const lpos_T *const end = &rex.reg_mmatch->endpos[0];
+
+ if (end->lnum < start->lnum
+ || (end->lnum == start->lnum && end->col < start->col)) {
+ rex.reg_mmatch->endpos[0] = rex.reg_mmatch->startpos[0];
+ }
+ } else {
+ if (rex.reg_match->endp[0] < rex.reg_match->startp[0]) {
+ rex.reg_match->endp[0] = rex.reg_match->startp[0];
+ }
+ }
+ }
+
return retval;
}
@@ -3706,8 +3724,7 @@ static long regtry(bt_regprog_T *prog,
} else {
if (reg_startzp[i] != NULL && reg_endzp[i] != NULL)
re_extmatch_out->matches[i] =
- vim_strnsave(reg_startzp[i],
- (int)(reg_endzp[i] - reg_startzp[i]));
+ vim_strnsave(reg_startzp[i], reg_endzp[i] - reg_startzp[i]);
}
}
}
@@ -6547,7 +6564,7 @@ static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv,
if (s == NULL || rsm.sm_match->endp[i] == NULL) {
s = NULL;
} else {
- s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s));
+ s = vim_strnsave(s, rsm.sm_match->endp[i] - s);
}
TV_LIST_ITEM_TV(li)->v_type = VAR_STRING;
TV_LIST_ITEM_TV(li)->vval.v_string = s;
@@ -7066,7 +7083,7 @@ char_u *reg_submatch(int no)
if (s == NULL || rsm.sm_match->endp[no] == NULL) {
retval = NULL;
} else {
- retval = vim_strnsave(s, (int)(rsm.sm_match->endp[no] - s));
+ retval = vim_strnsave(s, rsm.sm_match->endp[no] - s);
}
}
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 7dfd16fb4f..8b5ee59d40 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -5243,9 +5243,12 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
switch (t->state->c) {
case NFA_MATCH:
{
- // If the match ends before a composing characters and
- // rex.reg_icombine is not set, that is not really a match.
- if (!rex.reg_icombine && utf_iscomposing(curc)) {
+ // If the match is not at the start of the line, ends before a
+ // composing characters and rex.reg_icombine is not set, that
+ // is not really a match.
+ if (!rex.reg_icombine
+ && rex.input != rex.line
+ && utf_iscomposing(curc)) {
break;
}
nfa_match = true;
@@ -6477,8 +6480,7 @@ static long nfa_regtry(nfa_regprog_T *prog,
if (lpos->start != NULL && lpos->end != NULL)
re_extmatch_out->matches[i] =
- vim_strnsave(lpos->start,
- (int)(lpos->end - lpos->start));
+ vim_strnsave(lpos->start, lpos->end - lpos->start);
}
}
}
@@ -6591,6 +6593,24 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol,
#endif
theend:
+ if (retval > 0) {
+ // Make sure the end is never before the start. Can happen when \zs and
+ // \ze are used.
+ if (REG_MULTI) {
+ const lpos_T *const start = &rex.reg_mmatch->startpos[0];
+ const lpos_T *const end = &rex.reg_mmatch->endpos[0];
+
+ if (end->lnum < start->lnum
+ || (end->lnum == start->lnum && end->col < start->col)) {
+ rex.reg_mmatch->endpos[0] = rex.reg_mmatch->startpos[0];
+ }
+ } else {
+ if (rex.reg_match->endp[0] < rex.reg_match->startp[0]) {
+ rex.reg_match->endp[0] = rex.reg_match->startp[0];
+ }
+ }
+ }
+
return retval;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 2eeeebb88d..a78f905a70 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -683,7 +683,7 @@ void conceal_check_cursor_line(void)
redrawWinline(curwin, curwin->w_cursor.lnum);
// Need to recompute cursor column, e.g., when starting Visual mode
// without concealing. */
- curs_columns(true);
+ curs_columns(curwin, true);
}
}
@@ -1698,7 +1698,7 @@ static void win_update(win_T *wp, Providers *providers)
const int new_wcol = wp->w_wcol;
recursive = true;
curwin->w_valid &= ~VALID_TOPLINE;
- update_topline(); // may invalidate w_botline again
+ update_topline(curwin); // may invalidate w_botline again
if (old_wcol != new_wcol
&& (wp->w_valid & (VALID_WCOL|VALID_WROW))
@@ -2013,6 +2013,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// end-of-line
int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used
int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used
+ bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
// saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra = 0;
@@ -2196,7 +2197,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (wp->w_p_spell
- && foldinfo.fi_lines == 0
+ && !has_fold
&& *wp->w_s->b_p_spl != NUL
&& !GA_EMPTY(&wp->w_s->b_langp)
&& *(char **)(wp->w_s->b_langp.ga_data) != NULL) {
@@ -2299,6 +2300,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// handle 'incsearch' and ":s///c" highlighting
} else if (highlight_match
&& wp == curwin
+ && !has_fold
&& lnum >= curwin->w_cursor.lnum
&& lnum <= curwin->w_cursor.lnum + search_match_lines) {
if (lnum == curwin->w_cursor.lnum) {
@@ -2415,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;
@@ -2551,7 +2553,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
cur = wp->w_match_head;
shl_flag = false;
while ((cur != NULL || !shl_flag) && !number_only
- && foldinfo.fi_lines == 0
+ && !has_fold
) {
if (!shl_flag) {
shl = &search_hl;
@@ -2663,7 +2665,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- //sign column
+ // sign column, this is hit until sign_idx reaches count
if (draw_state == WL_SIGN - 1 && n_extra == 0) {
draw_state = WL_SIGN;
/* Show the sign column when there are any signs in this
@@ -2881,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) {
@@ -2903,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) {
@@ -2916,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) {
@@ -3085,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;
@@ -3740,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.
@@ -3833,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;
@@ -3883,8 +3882,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
/* check if line ends before left margin */
if (vcol < v + col - win_col_off(wp))
vcol = v + col - win_col_off(wp);
- /* Get rid of the boguscols now, we want to draw until the right
- * edge for 'cursorcolumn'. */
+ // Get rid of the boguscols now, we want to draw until the right
+ // edge for 'cursorcolumn'.
col -= boguscols;
// boguscols = 0; // Disabled because value never read after this
@@ -4051,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)))) {
@@ -4345,6 +4345,10 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
// Get information needed to display the sign in line 'lnum' in window 'wp'.
// If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
// Otherwise the sign is going to be displayed in the sign column.
+//
+// @param count max number of signs
+// @param[out] n_extrap number of characters from pp_extra to display
+// @param[in, out] sign_idxp Index of the displayed sign
static void get_sign_display_info(
bool nrcol,
win_T *wp,
@@ -4421,6 +4425,8 @@ static void get_sign_display_info(
(*sign_idxp)++;
if (*sign_idxp < count) {
*draw_statep = WL_SIGN - 1;
+ } else {
+ *sign_idxp = 0;
}
}
@@ -7380,7 +7386,7 @@ void screen_resize(int width, int height)
cmdline_pum_display(false);
}
} else {
- update_topline();
+ update_topline(curwin);
if (pum_drawn()) {
// TODO(bfredl): ins_compl_show_pum wants to redraw the screen first.
// For now make sure the nested update_screen(0) won't redraw the
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 90e1e25de2..787a464070 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -89,7 +89,7 @@ static struct spat spats[2] =
static int last_idx = 0; /* index in spats[] for RE_LAST */
static char_u lastc[2] = { NUL, NUL }; // last character searched for
-static int lastcdir = FORWARD; // last direction of character search
+static Direction lastcdir = FORWARD; // last direction of character search
static int last_t_cmd = true; // last search t_cmd
static char_u lastc_bytes[MB_MAXBYTES + 1];
static int lastc_bytelen = 1; // >1 for multi-byte char
@@ -437,7 +437,7 @@ void set_last_csearch(int c, char_u *s, int len)
memset(lastc_bytes, 0, sizeof(lastc_bytes));
}
-void set_csearch_direction(int cdir)
+void set_csearch_direction(Direction cdir)
{
lastcdir = cdir;
}
@@ -1430,7 +1430,7 @@ end_do_search:
* ADDING is set. If p_ic is set then the pattern must be in lowercase.
* Return OK for success, or FAIL if no line found.
*/
-int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
+int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
{
linenr_T start = 0;
char_u *ptr;
@@ -1496,10 +1496,11 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat)
* Return FAIL or OK.
*/
int searchc(cmdarg_T *cap, int t_cmd)
+ FUNC_ATTR_NONNULL_ALL
{
- int c = cap->nchar; /* char to search for */
- int dir = cap->arg; /* TRUE for searching forward */
- long count = cap->count1; /* repeat count */
+ int c = cap->nchar; // char to search for
+ Direction dir = cap->arg; // TRUE for searching forward
+ long count = cap->count1; // repeat count
int col;
char_u *p;
int len;
@@ -4462,7 +4463,7 @@ static void search_stat(int dirc, pos_T *pos,
void
find_pattern_in_path(
char_u *ptr, // pointer to search pattern
- int dir, // direction of expansion
+ Direction dir, // direction of expansion
size_t len, // length of search pattern
bool whole, // match whole words only
bool skip_comments, // don't match inside comments
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index ffe51287c5..fc9f53c192 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -173,13 +173,15 @@ static void insert_sign(
const char_u *group, // sign group; NULL for global group
int prio, // sign priority
linenr_T lnum, // line number which gets the mark
- int typenr // typenr of sign we are adding
+ int typenr, // typenr of sign we are adding
+ bool has_text_or_icon // sign has text or icon
)
{
signlist_T *newsign = xmalloc(sizeof(signlist_T));
newsign->id = id;
newsign->lnum = lnum;
newsign->typenr = typenr;
+ newsign->has_text_or_icon = has_text_or_icon;
if (group != NULL) {
newsign->group = sign_group_ref(group);
} else {
@@ -210,13 +212,14 @@ static void insert_sign(
/// Insert a new sign sorted by line number and sign priority.
static void insert_sign_by_lnum_prio(
- buf_T *buf, // buffer to store sign in
- signlist_T *prev, // previous sign entry
- int id, // sign ID
- const char_u *group, // sign group; NULL for global group
- int prio, // sign priority
- linenr_T lnum, // line number which gets the mark
- int typenr // typenr of sign we are adding
+ buf_T *buf, // buffer to store sign in
+ signlist_T *prev, // previous sign entry
+ int id, // sign ID
+ const char_u *group, // sign group; NULL for global group
+ int prio, // sign priority
+ linenr_T lnum, // line number which gets the mark
+ int typenr, // typenr of sign we are adding
+ bool has_text_or_icon // sign has text or icon
)
{
signlist_T *sign;
@@ -234,7 +237,7 @@ static void insert_sign_by_lnum_prio(
sign = prev->next;
}
- insert_sign(buf, prev, sign, id, group, prio, lnum, typenr);
+ insert_sign(buf, prev, sign, id, group, prio, lnum, typenr, has_text_or_icon);
}
/// Get the name of a sign by its typenr.
@@ -342,12 +345,13 @@ static void sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign)
/// Add the sign into the signlist. Find the right spot to do it though.
void buf_addsign(
- buf_T *buf, // buffer to store sign in
- int id, // sign ID
+ buf_T *buf, // buffer to store sign in
+ int id, // sign ID
const char_u *groupname, // sign group
- int prio, // sign priority
- linenr_T lnum, // line number which gets the mark
- int typenr // typenr of sign we are adding
+ int prio, // sign priority
+ linenr_T lnum, // line number which gets the mark
+ int typenr, // typenr of sign we are adding
+ bool has_text_or_icon // sign has text or icon
)
{
signlist_T *sign; // a sign in the signlist
@@ -363,13 +367,29 @@ void buf_addsign(
sign_sort_by_prio_on_line(buf, sign);
return;
} else if (lnum < sign->lnum) {
- insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr);
+ insert_sign_by_lnum_prio(
+ buf,
+ prev,
+ id,
+ groupname,
+ prio,
+ lnum,
+ typenr,
+ has_text_or_icon);
return;
}
prev = sign;
}
- insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr);
+ insert_sign_by_lnum_prio(
+ buf,
+ prev,
+ id,
+ groupname,
+ prio,
+ lnum,
+ typenr,
+ has_text_or_icon);
}
// For an existing, placed sign "markId" change the type to "typenr".
@@ -786,11 +806,15 @@ static int sign_define_init_text(sign_T *sp, char_u *text)
}
cells += utf_ptr2cells(s);
}
- // Currently must be one or two display cells
- if (s != endp || cells < 1 || cells > 2) {
+ // Currently must be empty, one or two display cells
+ if (s != endp || cells > 2) {
EMSG2(_("E239: Invalid sign text: %s"), text);
return FAIL;
}
+ if (cells < 1) {
+ sp->sn_text = NULL;
+ return OK;
+ }
xfree(sp->sn_text);
// Allocate one byte more if we need to pad up
@@ -939,7 +963,15 @@ int sign_place(
if (lnum > 0) {
// ":sign place {id} line={lnum} name={name} file={fname}":
// place a sign
- buf_addsign(buf, *sign_id, sign_group, prio, lnum, sp->sn_typenr);
+ bool has_text_or_icon = sp->sn_text != NULL || sp->sn_icon != NULL;
+ buf_addsign(
+ buf,
+ *sign_id,
+ sign_group,
+ prio,
+ lnum,
+ sp->sn_typenr,
+ has_text_or_icon);
} else {
// ":sign place {id} file={fname}": change sign type
lnum = buf_change_sign_type(buf, *sign_id, sign_group, sp->sn_typenr);
diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h
index 687c15bbd6..c898dba890 100644
--- a/src/nvim/sign_defs.h
+++ b/src/nvim/sign_defs.h
@@ -1,6 +1,7 @@
#ifndef NVIM_SIGN_DEFS_H
#define NVIM_SIGN_DEFS_H
+#include <stdbool.h>
#include "nvim/pos.h"
#include "nvim/types.h"
@@ -22,13 +23,14 @@ typedef struct signlist signlist_T;
struct signlist
{
- int id; // unique identifier for each placed sign
- linenr_T lnum; // line number which has this sign
- int typenr; // typenr of sign
- signgroup_T *group; // sign group
- int priority; // priority for highlighting
- signlist_T *next; // next signlist entry
- signlist_T *prev; // previous entry -- for easy reordering
+ int id; // unique identifier for each placed sign
+ linenr_T lnum; // line number which has this sign
+ int typenr; // typenr of sign
+ bool has_text_or_icon; // has text or icon
+ signgroup_T *group; // sign group
+ int priority; // priority for highlighting
+ signlist_T *next; // next signlist entry
+ signlist_T *prev; // previous entry -- for easy reordering
};
// Default sign priority for highlighting
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 797fe41320..5714f5e425 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -79,7 +79,6 @@
/* for offsetof() */
#include <stddef.h>
-#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/spell.h"
#include "nvim/buffer.h"
@@ -6653,7 +6652,7 @@ void
spell_dump_compl (
char_u *pat, // leading part of the word
int ic, // ignore case
- int *dir, // direction for adding matches
+ Direction *dir, // direction for adding matches
int dumpflags_arg // DUMPFLAG_*
)
{
@@ -6820,7 +6819,9 @@ spell_dump_compl (
// Dumps one word: apply case modifications and append a line to the buffer.
// When "lnum" is zero add insert mode completion.
-static void dump_word(slang_T *slang, char_u *word, char_u *pat, int *dir, int dumpflags, int wordflags, linenr_T lnum)
+static void dump_word(slang_T *slang, char_u *word, char_u *pat,
+ Direction *dir, int dumpflags, int wordflags,
+ linenr_T lnum)
{
bool keepcap = false;
char_u *p;
@@ -6906,7 +6907,7 @@ dump_prefixes (
slang_T *slang,
char_u *word, // case-folded word
char_u *pat,
- int *dir,
+ Direction *dir,
int dumpflags,
int flags, // flags with prefix ID
linenr_T startlnum
diff --git a/src/nvim/spell.h b/src/nvim/spell.h
index ad66df4c5d..e93c82b91d 100644
--- a/src/nvim/spell.h
+++ b/src/nvim/spell.h
@@ -6,6 +6,7 @@
#include "nvim/spell_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/globals.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "spell.h.generated.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index e91d560284..f99eca7953 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -4186,10 +4186,10 @@ get_syn_options(
arg = skiptowhite(arg);
if (gname_start == arg)
return NULL;
- gname = vim_strnsave(gname_start, (int)(arg - gname_start));
- if (STRCMP(gname, "NONE") == 0)
+ gname = vim_strnsave(gname_start, arg - gname_start);
+ if (STRCMP(gname, "NONE") == 0) {
*opt->sync_idx = NONE_IDX;
- else {
+ } else {
syn_id = syn_name2id(gname);
int i;
for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; )
@@ -4275,7 +4275,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
* Everything that's left, up to the next command, should be the
* filename to include.
*/
- eap->argt |= (XFILE | NOSPC);
+ eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute(eap->arg)) {
// For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
@@ -4587,7 +4587,7 @@ syn_cmd_region(
while (*key_end && !ascii_iswhite(*key_end) && *key_end != '=')
++key_end;
xfree(key);
- key = vim_strnsave_up(rest, (int)(key_end - rest));
+ key = vim_strnsave_up(rest, key_end - rest);
if (STRCMP(key, "MATCHGROUP") == 0) {
item = ITEM_MATCHGROUP;
} else if (STRCMP(key, "START") == 0) {
@@ -5047,8 +5047,8 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
EMSG2(_("E401: Pattern delimiter not found: %s"), arg);
return NULL;
}
- /* store the pattern and compiled regexp program */
- ci->sp_pattern = vim_strnsave(arg + 1, (int)(end - arg - 1));
+ // store the pattern and compiled regexp program
+ ci->sp_pattern = vim_strnsave(arg + 1, end - arg - 1);
/* Make 'cpoptions' empty, to avoid the 'l' flag */
cpo_save = p_cpo;
@@ -5136,7 +5136,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
arg_end = skiptowhite(arg_start);
next_arg = skipwhite(arg_end);
xfree(key);
- key = vim_strnsave_up(arg_start, (int)(arg_end - arg_start));
+ key = vim_strnsave_up(arg_start, arg_end - arg_start);
if (STRCMP(key, "CCOMMENT") == 0) {
if (!eap->skip)
curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT;
@@ -5195,7 +5195,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
if (!eap->skip) {
/* store the pattern and compiled regexp program */
curwin->w_s->b_syn_linecont_pat =
- vim_strnsave(next_arg + 1, (int)(arg_end - next_arg - 1));
+ vim_strnsave(next_arg + 1, arg_end - next_arg - 1);
curwin->w_s->b_syn_linecont_ic = curwin->w_s->b_syn_ic;
/* Make 'cpoptions' empty, to avoid the 'l' flag */
@@ -5555,18 +5555,17 @@ void ex_syntax(exarg_T *eap)
{
char_u *arg = eap->arg;
char_u *subcmd_end;
- char_u *subcmd_name;
- int i;
syn_cmdlinep = eap->cmdlinep;
- /* isolate subcommand name */
- for (subcmd_end = arg; ASCII_ISALPHA(*subcmd_end); ++subcmd_end)
- ;
- subcmd_name = vim_strnsave(arg, (int)(subcmd_end - arg));
- if (eap->skip) /* skip error messages for all subcommands */
- ++emsg_skip;
- for (i = 0;; ++i) {
+ // isolate subcommand name
+ for (subcmd_end = arg; ASCII_ISALPHA(*subcmd_end); subcmd_end++) {
+ }
+ char_u *const subcmd_name = vim_strnsave(arg, subcmd_end - arg);
+ if (eap->skip) { // skip error messages for all subcommands
+ emsg_skip++;
+ }
+ for (int i = 0;; i++) {
if (subcommands[i].name == NULL) {
EMSG2(_("E410: Invalid :syntax subcommand: %s"), subcmd_name);
break;
@@ -6719,7 +6718,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
xfree(key);
key = (char *)vim_strnsave_up((const char_u *)key_start,
- (int)(linep - key_start));
+ linep - key_start);
linep = (const char *)skipwhite((const char_u *)linep);
if (strcmp(key, "NONE") == 0) {
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index 7f6b7dcfec..24d3959f83 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -12,6 +12,9 @@ endfunc
" Command to check for the presence of a working option.
command -nargs=1 CheckOption call CheckOption(<f-args>)
func CheckOption(name)
+ if !exists('&' .. a:name)
+ throw 'Checking for non-existent option ' .. a:name
+ endif
if !exists('+' .. a:name)
throw 'Skipped: ' .. a:name .. ' option not supported'
endif
@@ -74,6 +77,14 @@ func CheckCanRunGui()
endif
endfunc
+" Command to check that we are using the GUI
+command CheckGui call CheckGui()
+func CheckGui()
+ if !has('gui_running')
+ throw 'Skipped: only works in the GUI'
+ endif
+endfunc
+
" Command to check that not currently using the GUI
command CheckNotGui call CheckNotGui()
func CheckNotGui()
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index b02514143c..275edece1e 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -414,7 +414,7 @@ for s:test in sort(s:tests)
" Repeat a flaky test. Give up when:
" - it fails again with the same message
- " - it fails five times (with a different mesage)
+ " - it fails five times (with a different message)
if len(v:errors) > 0
\ && (index(s:flaky_tests, s:test) >= 0
\ || v:errors[0] =~ s:flaky_errors_re)
diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim
index d032c9a739..fd9cfb54be 100644
--- a/src/nvim/testdir/setup.vim
+++ b/src/nvim/testdir/setup.vim
@@ -20,6 +20,7 @@ set tags=./tags,tags
set undodir^=.
set wildoptions=
set startofline
+set sessionoptions&vi
" Prevent Nvim log from writing to stderr.
let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log'
diff --git a/src/nvim/testdir/test49.ok b/src/nvim/testdir/test49.ok
index 50fc5d2cef..9f283e808b 100644
--- a/src/nvim/testdir/test49.ok
+++ b/src/nvim/testdir/test49.ok
@@ -1,6 +1,4 @@
Results of test49.vim:
-*** Test 16: OK (8722)
-*** Test 17: OK (285127993)
*** Test 18: OK (67224583)
*** Test 19: OK (69275973)
*** Test 20: OK (1874575085)
@@ -8,16 +6,11 @@ Results of test49.vim:
*** Test 22: OK (4161)
*** Test 23: OK (49)
*** Test 24: OK (41)
-*** Test 25: OK (260177811)
-*** Test 26: OK (1681500476)
*** Test 27: OK (1996459)
*** Test 28: OK (1996459)
*** Test 29: OK (170428555)
*** Test 30: OK (190905173)
*** Test 31: OK (190905173)
-*** Test 32: OK (354833067)
---- Test 33: sum = 178275600 (ok)
-*** Test 33: OK (1216907538)
*** Test 34: OK (2146584868)
*** Test 35: OK (2146584868)
*** Test 36: OK (1071644672)
@@ -25,17 +18,8 @@ Results of test49.vim:
*** Test 38: OK (357908480)
*** Test 39: OK (357908480)
*** Test 40: OK (357908480)
-*** Test 41: OK (3076095)
-*** Test 42: OK (1505155949)
-*** Test 43: OK (1157763329)
-*** Test 44: OK (1031761407)
-*** Test 45: OK (1157763329)
-*** Test 46: OK (739407)
-*** Test 47: OK (371213935)
-*** Test 48: OK (756255461)
*** Test 49: OK (179000669)
*** Test 50: OK (363550045)
-*** Test 51: OK (40744667)
*** Test 52: OK (1247112011)
*** Test 53: OK (131071)
*** Test 54: OK (2047)
@@ -53,13 +37,6 @@ Results of test49.vim:
*** Test 66: OK (5464)
*** Test 67: OK (212514423)
*** Test 68: OK (212514423)
-*** Test 69: OK (8995471)
-*** Test 70: OK (69544277)
-*** Test 71: OK (34886997)
-*** Test 72: OK (1789569365)
-*** Test 73: OK (9032615)
-*** Test 74: OK (224907669)
-*** Test 75: OK (2000403408)
*** Test 76: OK (1610087935)
*** Test 77: OK (1388671)
*** Test 78: OK (134217728)
@@ -72,11 +49,6 @@ Results of test49.vim:
*** Test 85: OK (198689)
--- Test 86: No Crash for vimgrep on BufUnload
*** Test 86: OK (0)
---- Test 87: 3
---- Test 87: 5
---- Test 87: abcdefghijk
---- Test 87: Successfully executed funcref Add2
-*** Test 87: OK (0)
--- Test 88: All tests were run with throwing exceptions on error.
The $VIMNOERRTHROW control is not configured.
--- Test 88: All tests were run with throwing exceptions on interrupt.
diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
index 5468f7c4aa..3ee5e9ff7c 100644
--- a/src/nvim/testdir/test49.vim
+++ b/src/nvim/testdir/test49.vim
@@ -1,6 +1,6 @@
" Vim script language tests
" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
-" Last Change: 2019 Oct 08
+" Last Change: 2019 Nov 03
"-------------------------------------------------------------------------------
" Test environment {{{1
@@ -521,7 +521,7 @@ endfunction
"
" Create a script that consists of the body of the function a:funcname.
" Replace any ":return" by a ":finish", any argument variable by a global
-" variable, and and every ":call" by a ":source" for the next following argument
+" variable, and every ":call" by a ":source" for the next following argument
" in the variable argument list. This function is useful if similar tests are
" to be made for a ":return" from a function call or a ":finish" in a script
" file.
@@ -608,196 +608,8 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
-" Tests 1 to 15 were moved to test_vimscript.vim
-let Xtest = 16
-
-"-------------------------------------------------------------------------------
-" Test 16: Double :else or :elseif after :else {{{1
-"
-" Multiple :elses or an :elseif after an :else are forbidden.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F() abort
- if 0
- Xpath 1 " X: 0
- else
- Xpath 2 " X: 2
- else " aborts function
- Xpath 4 " X: 0
- endif
-endfunction
-
-function! G() abort
- if 0
- Xpath 8 " X: 0
- else
- Xpath 16 " X: 16
- elseif 1 " aborts function
- Xpath 32 " X: 0
- else
- Xpath 64 " X: 0
- endif
-endfunction
-
-function! H() abort
- if 0
- Xpath 128 " X: 0
- elseif 0
- Xpath 256 " X: 0
- else
- Xpath 512 " X: 512
- else " aborts function
- Xpath 1024 " X: 0
- endif
-endfunction
-
-function! I() abort
- if 0
- Xpath 2048 " X: 0
- elseif 0
- Xpath 4096 " X: 0
- else
- Xpath 8192 " X: 8192
- elseif 1 " aborts function
- Xpath 16384 " X: 0
- else
- Xpath 32768 " X: 0
- endif
-endfunction
-
-call F()
-call G()
-call H()
-call I()
-
-delfunction F
-delfunction G
-delfunction H
-delfunction I
-
-Xcheck 8722
-
-
-"-------------------------------------------------------------------------------
-" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
-"
-" The :while/:endwhile takes precedence in nesting over an unclosed
-" :if or an unopened :endif.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! MSG(enr, emsg)
- let english = v:lang == "C" || v:lang =~ '^[Ee]n'
- if a:enr == ""
- Xout "TODO: Add message number for:" a:emsg
- let v:errmsg = ":" . v:errmsg
- endif
- let match = 1
- if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
- let match = 0
- if v:errmsg == ""
- Xout "Message missing."
- else
- let v:errmsg = escape(v:errmsg, '"')
- Xout "Unexpected message:" v:errmsg
- endif
- endif
- return match
-endfunction
-
-let messages = ""
-
-" While loops inside a function are continued on error.
-function! F()
- let v:errmsg = ""
- XloopINIT 1 16
- let loops = 3
- while loops > 0
- let loops = loops - 1 " 2: 1: 0:
- Xloop 1 " X: 1 + 1*16 + 1*16*16
- if (loops == 1)
- Xloop 2 " X: 2*16
- XloopNEXT
- continue
- elseif (loops == 0)
- Xloop 4 " X: 4*16*16
- break
- elseif 1
- Xloop 8 " X: 8
- XloopNEXT
- " endif missing!
- endwhile " :endwhile after :if 1
- Xpath 4096 " X: 16*16*16
- if MSG('E171', "Missing :endif")
- let g:messages = g:messages . "A"
- endif
-
- let v:errmsg = ""
- XloopINIT! 8192 4
- let loops = 2
- while loops > 0 " 2: 1:
- XloopNEXT
- let loops = loops - 1
- Xloop 1 " X: 8192 + 8192*4
- if 0
- Xloop 2 " X: 0
- " endif missing
- endwhile " :endwhile after :if 0
- Xpath 131072 " X: 8192*4*4
- if MSG('E171', "Missing :endif")
- let g:messages = g:messages . "B"
- endif
-
- let v:errmsg = ""
- XloopINIT 262144 4
- let loops = 2
- while loops > 0 " 2: 1:
- let loops = loops - 1
- Xloop 1 " X: 262144 + 262144 * 4
- " if missing!
- endif " :endif without :if in while
- Xloop 2 " X: 524288 + 524288 * 4
- XloopNEXT
- endwhile
- Xpath 4194304 " X: 262144*4*4
- if MSG('E580', ":endif without :if")
- let g:messages = g:messages . "C"
- endif
-endfunction
-
-call F()
-
-" Error continuation outside a function is at the outermost :endwhile or :endif.
-let v:errmsg = ""
-XloopINIT! 8388608 4
-let loops = 2
-while loops > 0 " 2: 1:
- XloopNEXT
- let loops = loops - 1
- Xloop 1 " X: 8388608 + 0 * 4
- if 0
- Xloop 2 " X: 0
- " endif missing! Following :endwhile fails.
-endwhile | Xpath 134217728 " X: 0
-Xpath 268435456 " X: 2*8388608*4*4
-if MSG('E171', "Missing :endif")
- let messages = g:messages . "D"
-endif
-
-if messages != "ABCD"
- Xpath 536870912 " X: 0
- Xout "messages is" messages "instead of ABCD"
-endif
-
-unlet loops messages
-delfunction F
-delfunction MSG
-
-Xcheck 285127993
-
+" Tests 1 to 17 were moved to test_vimscript.vim
+let Xtest = 18
"-------------------------------------------------------------------------------
" Test 18: Interrupt (Ctrl-C pressed) {{{1
@@ -1313,140 +1125,8 @@ endif
Xcheck 41
-
-"-------------------------------------------------------------------------------
-" Test 25: Executing :finally clauses on normal control flow {{{1
-"
-" Control flow in a :try conditional should always fall through to its
-" :finally clause. A :finally clause of a :try conditional inside an
-" inactive conditional should never be executed.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F()
- let loops = 3
- XloopINIT 1 256
- while loops > 0 " 3: 2: 1:
- Xloop 1 " X: 1 + 1*256 + 1*256*256
- if loops >= 2
- try
- Xloop 2 " X: 2 + 2*256
- if loops == 2
- try
- Xloop 4 " X: 4*256
- finally
- Xloop 8 " X: 8*256
- endtry
- endif
- finally
- Xloop 16 " X: 16 + 16*256
- if loops == 2
- try
- Xloop 32 " X: 32*256
- finally
- Xloop 64 " X: 64*256
- endtry
- endif
- endtry
- endif
- Xloop 128 " X: 128 + 128*256 + 128*256*256
- let loops = loops - 1
- XloopNEXT
- endwhile
- Xpath 16777216 " X: 16777216
-endfunction
-
-if 1
- try
- Xpath 33554432 " X: 33554432
- call F()
- Xpath 67108864 " X: 67108864
- finally
- Xpath 134217728 " X: 134217728
- endtry
-else
- try
- Xpath 268435456 " X: 0
- finally
- Xpath 536870912 " X: 0
- endtry
-endif
-
-delfunction F
-
-Xcheck 260177811
-
-
-"-------------------------------------------------------------------------------
-" Test 26: Executing :finally clauses after :continue or :break {{{1
-"
-" For a :continue or :break dynamically enclosed in a :try/:endtry
-" region inside the next surrounding :while/:endwhile, if the
-" :continue/:break is before the :finally, the :finally clause is
-" executed first. If the :continue/:break is after the :finally, the
-" :finally clause is broken (like an :if/:endif region).
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-try
- let loops = 3
- XloopINIT! 1 32
- while loops > 0
- XloopNEXT
- try
- try
- if loops == 2 " 3: 2: 1:
- Xloop 1 " X: 1*32
- let loops = loops - 1
- continue
- elseif loops == 1
- Xloop 2 " X: 2*32*32
- break
- finish
- endif
- Xloop 4 " X: 4
- endtry
- finally
- Xloop 8 " X: 8 + 8*32 + 8*32*32
- endtry
- Xloop 16 " X: 16
- let loops = loops - 1
- endwhile
- Xpath 32768 " X: 32768
-finally
- Xpath 65536 " X: 65536
- let loops = 3
- XloopINIT 131072 16
- while loops > 0
- try
- finally
- try
- if loops == 2
- Xloop 1 " X: 131072*16
- let loops = loops - 1
- XloopNEXT
- continue
- elseif loops == 1
- Xloop 2 " X: 131072*2*16*16
- break
- finish
- endif
- endtry
- Xloop 4 " X: 131072*4
- endtry
- Xloop 8 " X: 131072*8
- let loops = loops - 1
- XloopNEXT
- endwhile
- Xpath 536870912 " X: 536870912
-endtry
-Xpath 1073741824 " X: 1073741824
-
-unlet loops
-
-Xcheck 1681500476
+" Tests 25 and 26 were moved to test_trycatch.vim
+let Xtest = 27
"-------------------------------------------------------------------------------
@@ -1783,252 +1463,8 @@ endif
Xcheck 190905173
-
-"-------------------------------------------------------------------------------
-" Test 32: Remembering the :return value on :finally {{{1
-"
-" If a :finally clause is executed due to a :return specifying
-" a value, this is the value visible to the caller if not overwritten
-" by a new :return in the :finally clause. A :return without a value
-" in the :finally clause overwrites with value 0.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F()
- try
- Xpath 1 " X: 1
- try
- Xpath 2 " X: 2
- return "ABCD"
- Xpath 4 " X: 0
- finally
- Xpath 8 " X: 8
- endtry
- Xpath 16 " X: 0
- finally
- Xpath 32 " X: 32
- endtry
- Xpath 64 " X: 0
-endfunction
-
-function! G()
- try
- Xpath 128 " X: 128
- return 8
- Xpath 256 " X: 0
- finally
- Xpath 512 " X: 512
- return 16 + strlen(F())
- Xpath 1024 " X: 0
- endtry
- Xpath 2048 " X: 0
-endfunction
-
-function! H()
- try
- Xpath 4096 " X: 4096
- return 32
- Xpath 8192 " X: 0
- finally
- Xpath 16384 " X: 16384
- return
- Xpath 32768 " X: 0
- endtry
- Xpath 65536 " X: 0
-endfunction
-
-function! I()
- try
- Xpath 131072 " X: 131072
- finally
- Xpath 262144 " X: 262144
- return G() + H() + 64
- Xpath 524288 " X: 0
- endtry
- Xpath 1048576 " X: 0
-endfunction
-
-let retcode = I()
-Xpath 2097152 " X: 2097152
-
-if retcode < 0
- Xpath 4194304 " X: 0
-endif
-if retcode % 4
- Xpath 8388608 " X: 0
-endif
-if (retcode/4) % 2
- Xpath 16777216 " X: 16777216
-endif
-if (retcode/8) % 2
- Xpath 33554432 " X: 0
-endif
-if (retcode/16) % 2
- Xpath 67108864 " X: 67108864
-endif
-if (retcode/32) % 2
- Xpath 134217728 " X: 0
-endif
-if (retcode/64) % 2
- Xpath 268435456 " X: 268435456
-endif
-if retcode/128
- Xpath 536870912 " X: 0
-endif
-
-unlet retcode
-delfunction F
-delfunction G
-delfunction H
-delfunction I
-
-Xcheck 354833067
-
-
-"-------------------------------------------------------------------------------
-" Test 33: :return under :execute or user command and :finally {{{1
-"
-" A :return command may be executed under an ":execute" or from
-" a user command. Executing of :finally clauses and passing through
-" the return code works also then.
-"-------------------------------------------------------------------------------
-XpathINIT
-
-command! -nargs=? RETURN
- \ try | return <args> | finally | return <args> * 2 | endtry
-
-function! F()
- try
- RETURN 8
- Xpath 1 " X: 0
- finally
- Xpath 2 " X: 2
- endtry
- Xpath 4 " X: 0
-endfunction
-
-function! G()
- try
- RETURN 32
- Xpath 8 " X: 0
- finally
- Xpath 16 " X: 16
- RETURN 128
- Xpath 32 " X: 0
- endtry
- Xpath 64 " X: 0
-endfunction
-
-function! H()
- try
- execute "try | return 512 | finally | return 1024 | endtry"
- Xpath 128 " X: 0
- finally
- Xpath 256 " X: 256
- endtry
- Xpath 512 " X: 0
-endfunction
-
-function! I()
- try
- execute "try | return 2048 | finally | return 4096 | endtry"
- Xpath 1024 " X: 0
- finally
- Xpath 2048 " X: 2048
- execute "try | return 8192 | finally | return 16384 | endtry"
- Xpath 4096 " X: 0
- endtry
- Xpath 8192 " X: 0
-endfunction
-
-function! J()
- try
- RETURN 32768
- Xpath 16384 " X: 0
- finally
- Xpath 32768 " X: 32768
- return
- Xpath 65536 " X: 0
- endtry
- Xpath 131072 " X: 0
-endfunction
-
-function! K()
- try
- execute "try | return 131072 | finally | return 262144 | endtry"
- Xpath 262144 " X: 0
- finally
- Xpath 524288 " X: 524288
- execute "try | return 524288 | finally | return | endtry"
- Xpath 1048576 " X: 0
- endtry
- Xpath 2097152 " X: 0
-endfunction
-
-function! L()
- try
- return
- Xpath 4194304 " X: 0
- finally
- Xpath 8388608 " X: 8388608
- RETURN 1048576
- Xpath 16777216 " X: 0
- endtry
- Xpath 33554432 " X: 0
-endfunction
-
-function! M()
- try
- return
- Xpath 67108864 " X: 0
- finally
- Xpath 134217728 " X: 134217728
- execute "try | return 4194304 | finally | return 8388608 | endtry"
- Xpath 268435456 " X: 0
- endtry
- Xpath 536870912 " X: 0
-endfunction
-
-function! N()
- RETURN 16777216
-endfunction
-
-function! O()
- execute "try | return 67108864 | finally | return 134217728 | endtry"
-endfunction
-
-let sum = F() + G() + H() + I() + J() + K() + L() + M()
-let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608
-let sum = sum + N() + O()
-let expected = expected + 33554432 + 134217728
-
-if sum == expected
- Xout "sum = " . sum . " (ok)"
-else
- Xout "sum = " . sum . ", expected: " . expected
-endif
-
-Xpath 1073741824 " X: 1073741824
-
-if sum != expected
- " The Xpath command does not accept 2^31 (negative); add explicitly:
- let Xpath = Xpath + 2147483648 " X: 0
-endif
-
-unlet sum expected
-delfunction F
-delfunction G
-delfunction H
-delfunction I
-delfunction J
-delfunction K
-delfunction L
-delfunction M
-delfunction N
-delfunction O
-
-Xcheck 1216907538
+" Tests 32 and 33 were moved to test_trycatch.vim
+let Xtest = 34
"-------------------------------------------------------------------------------
@@ -2654,643 +2090,8 @@ endif
Xcheck 357908480
-
-"-------------------------------------------------------------------------------
-" Test 41: Skipped :throw finding next command {{{1
-"
-" A :throw in an inactive conditional must not hide a following
-" command.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F()
- Xpath 1 " X: 1
- if 0 | throw "never" | endif | Xpath 2 " X: 2
- Xpath 4 " X: 4
-endfunction
-
-function! G()
- Xpath 8 " X: 8
- while 0 | throw "never" | endwhile | Xpath 16 " X: 16
- Xpath 32 " X: 32
-endfunction
-
-function H()
- Xpath 64 " X: 64
- if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128
- Xpath 256 " X: 256
-endfunction
-
-Xpath 512 " X: 512
-
-try
- Xpath 1024 " X: 1024
- call F()
- Xpath 2048 " X: 2048
-catch /.*/
- Xpath 4096 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 8192 " X: 8192
-
-try
- Xpath 16384 " X: 16384
- call G()
- Xpath 32768 " X: 32768
-catch /.*/
- Xpath 65536 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 131072 " X: 131072
-
-try
- Xpath 262144 " X: 262144
- call H()
- Xpath 524288 " X: 524288
-catch /.*/
- Xpath 1048576 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 2097152 " X: 2097152
-
-delfunction F
-delfunction G
-delfunction H
-
-Xcheck 3076095
-
-
-"-------------------------------------------------------------------------------
-" Test 42: Catching number and string exceptions {{{1
-"
-" When a number is thrown, it is converted to a string exception.
-" Numbers and strings may be caught by specifying a regular exception
-" as argument to the :catch command.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-try
-
- try
- Xpath 1 " X: 1
- throw 4711
- Xpath 2 " X: 0
- catch /4711/
- Xpath 4 " X: 4
- endtry
-
- try
- Xpath 8 " X: 8
- throw 4711
- Xpath 16 " X: 0
- catch /^4711$/
- Xpath 32 " X: 32
- endtry
-
- try
- Xpath 64 " X: 64
- throw 4711
- Xpath 128 " X: 0
- catch /\d/
- Xpath 256 " X: 256
- endtry
-
- try
- Xpath 512 " X: 512
- throw 4711
- Xpath 1024 " X: 0
- catch /^\d\+$/
- Xpath 2048 " X: 2048
- endtry
-
- try
- Xpath 4096 " X: 4096
- throw "arrgh"
- Xpath 8192 " X: 0
- catch /arrgh/
- Xpath 16384 " X: 16384
- endtry
-
- try
- Xpath 32768 " X: 32768
- throw "arrgh"
- Xpath 65536 " X: 0
- catch /^arrgh$/
- Xpath 131072 " X: 131072
- endtry
-
- try
- Xpath 262144 " X: 262144
- throw "arrgh"
- Xpath 524288 " X: 0
- catch /\l/
- Xpath 1048576 " X: 1048576
- endtry
-
- try
- Xpath 2097152 " X: 2097152
- throw "arrgh"
- Xpath 4194304 " X: 0
- catch /^\l\+$/
- Xpath 8388608 " X: 8388608
- endtry
-
- try
- try
- Xpath 16777216 " X: 16777216
- throw "ARRGH"
- Xpath 33554432 " X: 0
- catch /^arrgh$/
- Xpath 67108864 " X: 0
- endtry
- catch /^\carrgh$/
- Xpath 134217728 " X: 134217728
- endtry
-
- try
- Xpath 268435456 " X: 268435456
- throw ""
- Xpath 536870912 " X: 0
- catch /^$/
- Xpath 1073741824 " X: 1073741824
- endtry
-
-catch /.*/
- " The Xpath command does not accept 2^31 (negative); add explicitly:
- let Xpath = Xpath + 2147483648 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xcheck 1505155949
-
-
-"-------------------------------------------------------------------------------
-" Test 43: Selecting the correct :catch clause {{{1
-"
-" When an exception is thrown and there are multiple :catch clauses,
-" the first matching one is taken.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-XloopINIT 1 1024
-let loops = 3
-while loops > 0
- try
- if loops == 3
- Xloop 1 " X: 1
- throw "a"
- Xloop 2 " X: 0
- elseif loops == 2
- Xloop 4 " X: 4*1024
- throw "ab"
- Xloop 8 " X: 0
- elseif loops == 1
- Xloop 16 " X: 16*1024*1024
- throw "abc"
- Xloop 32 " X: 0
- endif
- catch /abc/
- Xloop 64 " X: 64*1024*1024
- catch /ab/
- Xloop 128 " X: 128*1024
- catch /.*/
- Xloop 256 " X: 256
- catch /a/
- Xloop 512 " X: 0
- endtry
-
- let loops = loops - 1
- XloopNEXT
-endwhile
-Xpath 1073741824 " X: 1073741824
-
-unlet loops
-
-Xcheck 1157763329
-
-
-"-------------------------------------------------------------------------------
-" Test 44: Missing or empty :catch patterns {{{1
-"
-" A missing or empty :catch pattern means the same as /.*/, that is,
-" catches everything. To catch only empty exceptions, /^$/ must be
-" used. A :catch with missing, empty, or /.*/ argument also works
-" when followed by another command separated by a bar on the same
-" line. :catch patterns cannot be specified between ||. But other
-" pattern separators can be used instead of //.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-try
- try
- Xpath 1 " X: 1
- throw ""
- catch /^$/
- Xpath 2 " X: 2
- endtry
-
- try
- Xpath 4 " X: 4
- throw ""
- catch /.*/
- Xpath 8 " X: 8
- endtry
-
- try
- Xpath 16 " X: 16
- throw ""
- catch //
- Xpath 32 " X: 32
- endtry
-
- try
- Xpath 64 " X: 64
- throw ""
- catch
- Xpath 128 " X: 128
- endtry
-
- try
- Xpath 256 " X: 256
- throw "oops"
- catch /^$/
- Xpath 512 " X: 0
- catch /.*/
- Xpath 1024 " X: 1024
- endtry
-
- try
- Xpath 2048 " X: 2048
- throw "arrgh"
- catch /^$/
- Xpath 4096 " X: 0
- catch //
- Xpath 8192 " X: 8192
- endtry
-
- try
- Xpath 16384 " X: 16384
- throw "brrr"
- catch /^$/
- Xpath 32768 " X: 0
- catch
- Xpath 65536 " X: 65536
- endtry
-
- try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry
- " X: 131072 + 262144
-
- try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry
- " X: 524288 + 1048576
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- " Extra try level: if ":catch" without arguments below raises
- " a syntax error because it misinterprets the "Xpath" as a pattern,
- " let it be caught by the ":catch /.*/" below.
- try
- try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | :
- endtry " X: 2097152 + 4194304
- endtry
- catch /.*/
- let caught = 1
- Xout v:exception "in" v:throwpoint
- finally
- if $VIMNOERRTHROW && v:errmsg != ""
- Xout v:errmsg
- endif
- if caught || $VIMNOERRTHROW && v:errmsg != ""
- Xpath 8388608 " X: 0
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-
- let cologne = 4711
- try
- try
- Xpath 16777216 " X: 16777216
- throw "throw cologne"
- " Next lines catches all and throws 4711:
- catch |throw cologne|
- Xpath 33554432 " X: 0
- endtry
- catch /4711/
- Xpath 67108864 " X: 67108864
- endtry
-
- try
- Xpath 134217728 " X: 134217728
- throw "plus"
- catch +plus+
- Xpath 268435456 " X: 268435456
- endtry
-
- Xpath 536870912 " X: 536870912
-catch /.*/
- Xpath 1073741824 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-unlet! caught cologne
-
-Xcheck 1031761407
-
-
-"-------------------------------------------------------------------------------
-" Test 45: Catching exceptions from nested :try blocks {{{1
-"
-" When :try blocks are nested, an exception is caught by the innermost
-" try conditional that has a matching :catch clause.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-XloopINIT 1 1024
-let loops = 3
-while loops > 0
- try
- try
- try
- try
- if loops == 3
- Xloop 1 " X: 1
- throw "a"
- Xloop 2 " X: 0
- elseif loops == 2
- Xloop 4 " X: 4*1024
- throw "ab"
- Xloop 8 " X: 0
- elseif loops == 1
- Xloop 16 " X: 16*1024*1024
- throw "abc"
- Xloop 32 " X: 0
- endif
- catch /abc/
- Xloop 64 " X: 64*1024*1024
- endtry
- catch /ab/
- Xloop 128 " X: 128*1024
- endtry
- catch /.*/
- Xloop 256 " X: 256
- endtry
- catch /a/
- Xloop 512 " X: 0
- endtry
-
- let loops = loops - 1
- XloopNEXT
-endwhile
-Xpath 1073741824 " X: 1073741824
-
-unlet loops
-
-Xcheck 1157763329
-
-
-"-------------------------------------------------------------------------------
-" Test 46: Executing :finally after a :throw in nested :try {{{1
-"
-" When an exception is thrown from within nested :try blocks, the
-" :finally clauses of the non-catching try conditionals should be
-" executed before the matching :catch of the next surrounding :try
-" gets the control. If this also has a :finally clause, it is
-" executed afterwards.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let sum = 0
-
-try
- Xpath 1 " X: 1
- try
- Xpath 2 " X: 2
- try
- Xpath 4 " X: 4
- try
- Xpath 8 " X: 8
- throw "ABC"
- Xpath 16 " X: 0
- catch /xyz/
- Xpath 32 " X: 0
- finally
- Xpath 64 " X: 64
- if sum != 0
- Xpath 128 " X: 0
- endif
- let sum = sum + 1
- endtry
- Xpath 256 " X: 0
- catch /123/
- Xpath 512 " X: 0
- catch /321/
- Xpath 1024 " X: 0
- finally
- Xpath 2048 " X: 2048
- if sum != 1
- Xpath 4096 " X: 0
- endif
- let sum = sum + 2
- endtry
- Xpath 8192 " X: 0
- finally
- Xpath 16384 " X: 16384
- if sum != 3
- Xpath 32768 " X: 0
- endif
- let sum = sum + 4
- endtry
- Xpath 65536 " X: 0
-catch /ABC/
- Xpath 131072 " X: 131072
- if sum != 7
- Xpath 262144 " X: 0
- endif
- let sum = sum + 8
-finally
- Xpath 524288 " X: 524288
- if sum != 15
- Xpath 1048576 " X: 0
- endif
- let sum = sum + 16
-endtry
-Xpath 65536 " X: 65536
-if sum != 31
- Xpath 131072 " X: 0
-endif
-
-unlet sum
-
-Xcheck 739407
-
-
-"-------------------------------------------------------------------------------
-" Test 47: Throwing exceptions from a :catch clause {{{1
-"
-" When an exception is thrown from a :catch clause, it should not be
-" caught by a :catch of the same :try conditional. After executing
-" the :finally clause (if present), surrounding try conditionals
-" should be checked for a matching :catch.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-Xpath 1 " X: 1
-try
- Xpath 2 " X: 2
- try
- Xpath 4 " X: 4
- try
- Xpath 8 " X: 8
- throw "x1"
- Xpath 16 " X: 0
- catch /x1/
- Xpath 32 " X: 32
- try
- Xpath 64 " X: 64
- throw "x2"
- Xpath 128 " X: 0
- catch /x1/
- Xpath 256 " X: 0
- catch /x2/
- Xpath 512 " X: 512
- try
- Xpath 1024 " X: 1024
- throw "x3"
- Xpath 2048 " X: 0
- catch /x1/
- Xpath 4096 " X: 0
- catch /x2/
- Xpath 8192 " X: 0
- finally
- Xpath 16384 " X: 16384
- endtry
- Xpath 32768 " X: 0
- catch /x3/
- Xpath 65536 " X: 0
- endtry
- Xpath 131072 " X: 0
- catch /x1/
- Xpath 262144 " X: 0
- catch /x2/
- Xpath 524288 " X: 0
- catch /x3/
- Xpath 1048576 " X: 0
- finally
- Xpath 2097152 " X: 2097152
- endtry
- Xpath 4194304 " X: 0
- catch /x1/
- Xpath 8388608 " X: 0
- catch /x2/
- Xpath 16777216 " X: 0
- catch /x3/
- Xpath 33554432 " X: 33554432
- endtry
- Xpath 67108864 " X: 67108864
-catch /.*/
- Xpath 134217728 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-Xpath 268435456 " X: 268435456
-
-Xcheck 371213935
-
-
-"-------------------------------------------------------------------------------
-" Test 48: Throwing exceptions from a :finally clause {{{1
-"
-" When an exception is thrown from a :finally clause, it should not be
-" caught by a :catch of the same :try conditional. Surrounding try
-" conditionals should be checked for a matching :catch. A previously
-" thrown exception is discarded.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-try
-
- try
- try
- Xpath 1 " X: 1
- catch /x1/
- Xpath 2 " X: 0
- finally
- Xpath 4 " X: 4
- throw "x1"
- Xpath 8 " X: 0
- endtry
- Xpath 16 " X: 0
- catch /x1/
- Xpath 32 " X: 32
- endtry
- Xpath 64 " X: 64
-
- try
- try
- Xpath 128 " X: 128
- throw "x2"
- Xpath 256 " X: 0
- catch /x2/
- Xpath 512 " X: 512
- catch /x3/
- Xpath 1024 " X: 0
- finally
- Xpath 2048 " X: 2048
- throw "x3"
- Xpath 4096 " X: 0
- endtry
- Xpath 8192 " X: 0
- catch /x2/
- Xpath 16384 " X: 0
- catch /x3/
- Xpath 32768 " X: 32768
- endtry
- Xpath 65536 " X: 65536
-
- try
- try
- try
- Xpath 131072 " X: 131072
- throw "x4"
- Xpath 262144 " X: 0
- catch /x5/
- Xpath 524288 " X: 0
- finally
- Xpath 1048576 " X: 1048576
- throw "x5" " discards "x4"
- Xpath 2097152 " X: 0
- endtry
- Xpath 4194304 " X: 0
- catch /x4/
- Xpath 8388608 " X: 0
- finally
- Xpath 16777216 " X: 16777216
- endtry
- Xpath 33554432 " X: 0
- catch /x5/
- Xpath 67108864 " X: 67108864
- endtry
- Xpath 134217728 " X: 134217728
-
-catch /.*/
- Xpath 268435456 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-Xpath 536870912 " X: 536870912
-
-Xcheck 756255461
+" Tests 41 to 48 were moved to test_trycatch.vim
+let Xtest = 49
"-------------------------------------------------------------------------------
@@ -3443,124 +2244,8 @@ delfunction F
Xcheck 363550045
-
-"-------------------------------------------------------------------------------
-" Test 51: Throwing exceptions across :execute and user commands {{{1
-"
-" A :throw command may be executed under an ":execute" or from
-" a user command.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-command! -nargs=? THROW1 throw <args> | throw 1
-command! -nargs=? THROW2 try | throw <args> | endtry | throw 2
-command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry
-command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry
-
-try
-
- try
- try
- Xpath 1 " X: 1
- THROW1 "A"
- catch /A/
- Xpath 2 " X: 2
- endtry
- catch /1/
- Xpath 4 " X: 0
- endtry
-
- try
- try
- Xpath 8 " X: 8
- THROW2 "B"
- catch /B/
- Xpath 16 " X: 16
- endtry
- catch /2/
- Xpath 32 " X: 0
- endtry
-
- try
- try
- Xpath 64 " X: 64
- THROW3 "C"
- catch /C/
- Xpath 128 " X: 128
- endtry
- catch /3/
- Xpath 256 " X: 0
- endtry
-
- try
- try
- Xpath 512 " X: 512
- THROW4 "D"
- catch /D/
- Xpath 1024 " X: 1024
- endtry
- catch /4/
- Xpath 2048 " X: 0
- endtry
-
- try
- try
- Xpath 4096 " X: 4096
- execute 'throw "E" | throw 5'
- catch /E/
- Xpath 8192 " X: 8192
- endtry
- catch /5/
- Xpath 16384 " X: 0
- endtry
-
- try
- try
- Xpath 32768 " X: 32768
- execute 'try | throw "F" | endtry | throw 6'
- catch /F/
- Xpath 65536 " X: 65536
- endtry
- catch /6/
- Xpath 131072 " X: 0
- endtry
-
- try
- try
- Xpath 262144 " X: 262144
- execute'try | throw 7 | catch /7/ | throw "G" | endtry'
- catch /G/
- Xpath 524288 " X: 524288
- endtry
- catch /7/
- Xpath 1048576 " X: 0
- endtry
-
- try
- try
- Xpath 2097152 " X: 2097152
- execute 'try | throw 8 | finally | throw "H" | endtry'
- catch /H/
- Xpath 4194304 " X: 4194304
- endtry
- catch /8/
- Xpath 8388608 " X: 0
- endtry
-
-catch /.*/
- Xpath 16777216 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 33554432 " X: 33554432
-
-delcommand THROW1
-delcommand THROW2
-delcommand THROW3
-delcommand THROW4
-
-Xcheck 40744667
+" Test 51 was moved to test_trycatch.vim
+let Xtest = 52
"-------------------------------------------------------------------------------
@@ -3694,7 +2379,7 @@ endif
if ExtraVim(msgfile)
try
Xpath 4194304 " X: 4194304
- let x = novar " error E121; exception: E121
+ let x = novar " error E121/E15; exception: E121
catch /E15:/ " should not catch
Xpath 8388608 " X: 0
endtry
@@ -3702,7 +2387,7 @@ if ExtraVim(msgfile)
endif
Xpath 33554432 " X: 33554432
-if !MESSAGES('E121', "Undefined variable")
+if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression")
Xpath 67108864 " X: 0
endif
@@ -4236,14 +2921,18 @@ if MESSAGES('E170', "Missing :endwhile")
endif
if ExtraVim(msgfile)
-" try
-" throw "a"
-" catch /a/
-" if 1
-" endtry
+ try
+ Xpath 4194304 " X: 4194304
+ let x = novar " error E121; exception: E121
+ catch /E15:/ " should not catch
+ Xpath 8388608 " X: 0
+ endtry
+ Xpath 16777216 " X: 0
endif
-if MESSAGES('E171', "Missing :endif")
- Xpath 128 " X: 128
+
+Xpath 33554432 " X: 33554432
+if !MESSAGES('E121', "Undefined variable")
+ Xpath 67108864 " X: 0
endif
if ExtraVim(msgfile)
@@ -6227,954 +4916,8 @@ delfunction F
Xcheck 212514423
-
-"-------------------------------------------------------------------------------
-" Test 69: :throw across :if, :elseif, :while {{{1
-"
-" On an :if, :elseif, or :while command, an exception might be thrown
-" during evaluation of the expression to test. The exception can be
-" caught by the script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-XloopINIT! 1 2
-
-function! THROW(x)
- XloopNEXT
- Xloop 1 " X: 1 + 2 + 4
- throw a:x
-endfunction
-
-try
-
- try
- Xpath 8 " X: 8
- if 4711 == THROW("if") + 111
- Xpath 16 " X: 0
- else
- Xpath 32 " X: 0
- endif
- Xpath 64 " X: 0
- catch /^if$/
- Xpath 128 " X: 128
- catch /.*/
- Xpath 256 " X: 0
- Xout "if:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 512 " X: 512
- if 4711 == 4 + 7 + 1 + 1
- Xpath 1024 " X: 0
- elseif 4711 == THROW("elseif") + 222
- Xpath 2048 " X: 0
- else
- Xpath 4096 " X: 0
- endif
- Xpath 8192 " X: 0
- catch /^elseif$/
- Xpath 16384 " X: 16384
- catch /.*/
- Xpath 32768 " X: 0
- Xout "elseif:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 65536 " X: 65536
- while 4711 == THROW("while") + 4711
- Xpath 131072 " X: 0
- break
- endwhile
- Xpath 262144 " X: 0
- catch /^while$/
- Xpath 524288 " X: 524288
- catch /.*/
- Xpath 1048576 " X: 0
- Xout "while:" v:exception "in" v:throwpoint
- endtry
-
-catch /^0$/ " default return value
- Xpath 2097152 " X: 0
- Xout v:throwpoint
-catch /.*/
- Xout v:exception "in" v:throwpoint
- Xpath 4194304 " X: 0
-endtry
-
-Xpath 8388608 " X: 8388608
-
-delfunction THROW
-
-Xcheck 8995471
-
-
-"-------------------------------------------------------------------------------
-" Test 70: :throw across :return or :throw {{{1
-"
-" On a :return or :throw command, an exception might be thrown during
-" evaluation of the expression to return or throw, respectively. The
-" exception can be caught by the script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let taken = ""
-
-function! THROW(x, n)
- let g:taken = g:taken . "T" . a:n
- throw a:x
-endfunction
-
-function! F(x, y, n)
- let g:taken = g:taken . "F" . a:n
- return a:x + THROW(a:y, a:n)
-endfunction
-
-function! G(x, y, n)
- let g:taken = g:taken . "G" . a:n
- throw a:x . THROW(a:y, a:n)
- return a:x
-endfunction
-
-try
- try
- Xpath 1 " X: 1
- call F(4711, "return", 1)
- Xpath 2 " X: 0
- catch /^return$/
- Xpath 4 " X: 4
- catch /.*/
- Xpath 8 " X: 0
- Xout "return:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 16 " X: 16
- let var = F(4712, "return-var", 2)
- Xpath 32 " X: 0
- catch /^return-var$/
- Xpath 64 " X: 64
- catch /.*/
- Xpath 128 " X: 0
- Xout "return-var:" v:exception "in" v:throwpoint
- finally
- unlet! var
- endtry
-
- try
- Xpath 256 " X: 256
- throw "except1" . THROW("throw1", 3)
- Xpath 512 " X: 0
- catch /^except1/
- Xpath 1024 " X: 0
- catch /^throw1$/
- Xpath 2048 " X: 2048
- catch /.*/
- Xpath 4096 " X: 0
- Xout "throw1:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 8192 " X: 8192
- call G("except2", "throw2", 4)
- Xpath 16384 " X: 0
- catch /^except2/
- Xpath 32768 " X: 0
- catch /^throw2$/
- Xpath 65536 " X: 65536
- catch /.*/
- Xpath 131072 " X: 0
- Xout "throw2:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 262144 " X: 262144
- let var = G("except3", "throw3", 5)
- Xpath 524288 " X: 0
- catch /^except3/
- Xpath 1048576 " X: 0
- catch /^throw3$/
- Xpath 2097152 " X: 2097152
- catch /.*/
- Xpath 4194304 " X: 0
- Xout "throw3:" v:exception "in" v:throwpoint
- finally
- unlet! var
- endtry
-
- let expected = "F1T1F2T2T3G4T4G5T5"
- if taken != expected
- Xpath 8388608 " X: 0
- Xout "'taken' is" taken "instead of" expected
- endif
-
-catch /^0$/ " default return value
- Xpath 16777216 " X: 0
- Xout v:throwpoint
-catch /.*/
- Xpath 33554432 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 67108864 " X: 67108864
-
-unlet taken expected
-delfunction THROW
-delfunction F
-delfunction G
-
-Xcheck 69544277
-
-
-"-------------------------------------------------------------------------------
-" Test 71: :throw across :echo variants and :execute {{{1
-"
-" On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
-" exception might be thrown during evaluation of the arguments to
-" be displayed or executed as a command, respectively. Any following
-" arguments are not evaluated, then. The exception can be caught by
-" the script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let taken = ""
-
-function! THROW(x, n)
- let g:taken = g:taken . "T" . a:n
- throw a:x
-endfunction
-
-function! F(n)
- let g:taken = g:taken . "F" . a:n
- return "F" . a:n
-endfunction
-
-try
- try
- Xpath 1 " X: 1
- echo "echo" . THROW("echo-except", 1) F(1)
- Xpath 2 " X: 0
- catch /^echo-except$/
- Xpath 4 " X: 4
- catch /.*/
- Xpath 8 " X: 0
- Xout "echo:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 16 " X: 16
- echon "echon" . THROW("echon-except", 2) F(2)
- Xpath 32 " X: 0
- catch /^echon-except$/
- Xpath 64 " X: 64
- catch /.*/
- Xpath 128 " X: 0
- Xout "echon:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 256 " X: 256
- echomsg "echomsg" . THROW("echomsg-except", 3) F(3)
- Xpath 512 " X: 0
- catch /^echomsg-except$/
- Xpath 1024 " X: 1024
- catch /.*/
- Xpath 2048 " X: 0
- Xout "echomsg:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 4096 " X: 4096
- echoerr "echoerr" . THROW("echoerr-except", 4) F(4)
- Xpath 8192 " X: 0
- catch /^echoerr-except$/
- Xpath 16384 " X: 16384
- catch /Vim/
- Xpath 32768 " X: 0
- catch /echoerr/
- Xpath 65536 " X: 0
- catch /.*/
- Xpath 131072 " X: 0
- Xout "echoerr:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 262144 " X: 262144
- execute "echo 'execute" . THROW("execute-except", 5) F(5) "'"
- Xpath 524288 " X: 0
- catch /^execute-except$/
- Xpath 1048576 " X: 1048576
- catch /.*/
- Xpath 2097152 " X: 0
- Xout "execute:" v:exception "in" v:throwpoint
- endtry
-
- let expected = "T1T2T3T4T5"
- if taken != expected
- Xpath 4194304 " X: 0
- Xout "'taken' is" taken "instead of" expected
- endif
-
-catch /^0$/ " default return value
- Xpath 8388608 " X: 0
- Xout v:throwpoint
-catch /.*/
- Xpath 16777216 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 33554432 " X: 33554432
-
-unlet taken expected
-delfunction THROW
-delfunction F
-
-Xcheck 34886997
-
-
-"-------------------------------------------------------------------------------
-" Test 72: :throw across :let or :unlet {{{1
-"
-" On a :let command, an exception might be thrown during evaluation
-" of the expression to assign. On an :let or :unlet command, the
-" evaluation of the name of the variable to be assigned or list or
-" deleted, respectively, may throw an exception. Any following
-" arguments are not evaluated, then. The exception can be caught by
-" the script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let throwcount = 0
-
-function! THROW(x)
- let g:throwcount = g:throwcount + 1
- throw a:x
-endfunction
-
-try
- try
- let $VAR = "old_value"
- Xpath 1 " X: 1
- let $VAR = "let(" . THROW("var") . ")"
- Xpath 2 " X: 0
- catch /^var$/
- Xpath 4 " X: 4
- finally
- if $VAR != "old_value"
- Xpath 8 " X: 0
- endif
- endtry
-
- try
- let @a = "old_value"
- Xpath 16 " X: 16
- let @a = "let(" . THROW("reg") . ")"
- Xpath 32 " X: 0
- catch /^reg$/
- try
- Xpath 64 " X: 64
- let @A = "let(" . THROW("REG") . ")"
- Xpath 128 " X: 0
- catch /^REG$/
- Xpath 256 " X: 256
- endtry
- finally
- if @a != "old_value"
- Xpath 512 " X: 0
- endif
- if @A != "old_value"
- Xpath 1024 " X: 0
- endif
- endtry
-
- try
- let saved_gpath = &g:path
- let saved_lpath = &l:path
- Xpath 2048 " X: 2048
- let &path = "let(" . THROW("opt") . ")"
- Xpath 4096 " X: 0
- catch /^opt$/
- try
- Xpath 8192 " X: 8192
- let &g:path = "let(" . THROW("gopt") . ")"
- Xpath 16384 " X: 0
- catch /^gopt$/
- try
- Xpath 32768 " X: 32768
- let &l:path = "let(" . THROW("lopt") . ")"
- Xpath 65536 " X: 0
- catch /^lopt$/
- Xpath 131072 " X: 131072
- endtry
- endtry
- finally
- if &g:path != saved_gpath || &l:path != saved_lpath
- Xpath 262144 " X: 0
- endif
- let &g:path = saved_gpath
- let &l:path = saved_lpath
- endtry
-
- unlet! var1 var2 var3
-
- try
- Xpath 524288 " X: 524288
- let var1 = "let(" . THROW("var1") . ")"
- Xpath 1048576 " X: 0
- catch /^var1$/
- Xpath 2097152 " X: 2097152
- finally
- if exists("var1")
- Xpath 4194304 " X: 0
- endif
- endtry
-
- try
- let var2 = "old_value"
- Xpath 8388608 " X: 8388608
- let var2 = "let(" . THROW("var2"). ")"
- Xpath 16777216 " X: 0
- catch /^var2$/
- Xpath 33554432 " X: 33554432
- finally
- if var2 != "old_value"
- Xpath 67108864 " X: 0
- endif
- endtry
-
- try
- Xpath 134217728 " X: 134217728
- let var{THROW("var3")} = 4711
- Xpath 268435456 " X: 0
- catch /^var3$/
- Xpath 536870912 " X: 536870912
- endtry
-
- let addpath = ""
-
- function ADDPATH(p)
- let g:addpath = g:addpath . a:p
- endfunction
-
- try
- call ADDPATH("T1")
- let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3")
- call ADDPATH("T4")
- catch /^var4$/
- call ADDPATH("T5")
- endtry
-
- try
- call ADDPATH("T6")
- unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8")
- call ADDPATH("T9")
- catch /^var5$/
- call ADDPATH("T10")
- endtry
-
- if addpath != "T1T5T6T10" || throwcount != 11
- throw "addpath: " . addpath . ", throwcount: " . throwcount
- endif
-
- Xpath 1073741824 " X: 1073741824
-
-catch /.*/
- " The Xpath command does not accept 2^31 (negative); add explicitly:
- let Xpath = Xpath + 2147483648 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-unlet! var1 var2 var3 addpath throwcount
-delfunction THROW
-
-Xcheck 1789569365
-
-
-"-------------------------------------------------------------------------------
-" Test 73: :throw across :function, :delfunction {{{1
-"
-" The :function and :delfunction commands may cause an expression
-" specified in braces to be evaluated. During evaluation, an
-" exception might be thrown. The exception can be caught by the
-" script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let taken = ""
-
-function! THROW(x, n)
- let g:taken = g:taken . "T" . a:n
- throw a:x
-endfunction
-
-function! EXPR(x, n)
- let g:taken = g:taken . "E" . a:n
- if a:n % 2 == 0
- call THROW(a:x, a:n)
- endif
- return 2 - a:n % 2
-endfunction
-
-try
- try
- " Define function.
- Xpath 1 " X: 1
- function! F0()
- endfunction
- Xpath 2 " X: 2
- function! F{EXPR("function-def-ok", 1)}()
- endfunction
- Xpath 4 " X: 4
- function! F{EXPR("function-def", 2)}()
- endfunction
- Xpath 8 " X: 0
- catch /^function-def-ok$/
- Xpath 16 " X: 0
- catch /^function-def$/
- Xpath 32 " X: 32
- catch /.*/
- Xpath 64 " X: 0
- Xout "def:" v:exception "in" v:throwpoint
- endtry
-
- try
- " List function.
- Xpath 128 " X: 128
- function F0
- Xpath 256 " X: 256
- function F{EXPR("function-lst-ok", 3)}
- Xpath 512 " X: 512
- function F{EXPR("function-lst", 4)}
- Xpath 1024 " X: 0
- catch /^function-lst-ok$/
- Xpath 2048 " X: 0
- catch /^function-lst$/
- Xpath 4096 " X: 4096
- catch /.*/
- Xpath 8192 " X: 0
- Xout "lst:" v:exception "in" v:throwpoint
- endtry
-
- try
- " Delete function
- Xpath 16384 " X: 16384
- delfunction F0
- Xpath 32768 " X: 32768
- delfunction F{EXPR("function-del-ok", 5)}
- Xpath 65536 " X: 65536
- delfunction F{EXPR("function-del", 6)}
- Xpath 131072 " X: 0
- catch /^function-del-ok$/
- Xpath 262144 " X: 0
- catch /^function-del$/
- Xpath 524288 " X: 524288
- catch /.*/
- Xpath 1048576 " X: 0
- Xout "del:" v:exception "in" v:throwpoint
- endtry
-
- let expected = "E1E2T2E3E4T4E5E6T6"
- if taken != expected
- Xpath 2097152 " X: 0
- Xout "'taken' is" taken "instead of" expected
- endif
-
-catch /.*/
- Xpath 4194304 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-Xpath 8388608 " X: 8388608
-
-unlet taken expected
-delfunction THROW
-delfunction EXPR
-
-Xcheck 9032615
-
-
-"-------------------------------------------------------------------------------
-" Test 74: :throw across builtin functions and commands {{{1
-"
-" Some functions like exists(), searchpair() take expression
-" arguments, other functions or commands like substitute() or
-" :substitute cause an expression (specified in the regular
-" expression) to be evaluated. During evaluation an exception
-" might be thrown. The exception can be caught by the script.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let taken = ""
-
-function! THROW(x, n)
- let g:taken = g:taken . "T" . a:n
- throw a:x
-endfunction
-
-function! EXPR(x, n)
- let g:taken = g:taken . "E" . a:n
- call THROW(a:x . a:n, a:n)
- return "EXPR"
-endfunction
-
-function! SKIP(x, n)
- let g:taken = g:taken . "S" . a:n . "(" . line(".")
- let theline = getline(".")
- if theline =~ "skip"
- let g:taken = g:taken . "s)"
- return 1
- elseif theline =~ "throw"
- let g:taken = g:taken . "t)"
- call THROW(a:x . a:n, a:n)
- else
- let g:taken = g:taken . ")"
- return 0
- endif
-endfunction
-
-function! SUBST(x, n)
- let g:taken = g:taken . "U" . a:n . "(" . line(".")
- let theline = getline(".")
- if theline =~ "not" " SUBST() should not be called for this line
- let g:taken = g:taken . "n)"
- call THROW(a:x . a:n, a:n)
- elseif theline =~ "throw"
- let g:taken = g:taken . "t)"
- call THROW(a:x . a:n, a:n)
- else
- let g:taken = g:taken . ")"
- return "replaced"
- endif
-endfunction
-
-try
- try
- Xpath 1 " X: 1
- let result = exists('*{EXPR("exists", 1)}')
- Xpath 2 " X: 0
- catch /^exists1$/
- Xpath 4 " X: 4
- try
- let result = exists('{EXPR("exists", 2)}')
- Xpath 8 " X: 0
- catch /^exists2$/
- Xpath 16 " X: 16
- catch /.*/
- Xpath 32 " X: 0
- Xout "exists2:" v:exception "in" v:throwpoint
- endtry
- catch /.*/
- Xpath 64 " X: 0
- Xout "exists1:" v:exception "in" v:throwpoint
- endtry
-
- try
- let file = tempname()
- exec "edit" file
- insert
-begin
- xx
-middle 3
- xx
-middle 5 skip
- xx
-middle 7 throw
- xx
-end
-.
- normal! gg
- Xpath 128 " X: 128
- let result =
- \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)')
- Xpath 256 " X: 256
- let result =
- \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)')
- Xpath 512 " X: 0
- let result =
- \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)')
- Xpath 1024 " X: 0
- catch /^searchpair[35]$/
- Xpath 2048 " X: 0
- catch /^searchpair4$/
- Xpath 4096 " X: 4096
- catch /.*/
- Xpath 8192 " X: 0
- Xout "searchpair:" v:exception "in" v:throwpoint
- finally
- bwipeout!
- call delete(file)
- endtry
-
- try
- let file = tempname()
- exec "edit" file
- insert
-subst 1
-subst 2
-not
-subst 4
-subst throw
-subst 6
-.
- normal! gg
- Xpath 16384 " X: 16384
- 1,2substitute/subst/\=SUBST("substitute", 6)/
- try
- Xpath 32768 " X: 32768
- try
- let v:errmsg = ""
- 3substitute/subst/\=SUBST("substitute", 7)/
- finally
- if v:errmsg != ""
- " If exceptions are not thrown on errors, fake the error
- " exception in order to get the same execution path.
- throw "faked Vim(substitute)"
- endif
- endtry
- catch /Vim(substitute)/ " Pattern not found ('e' flag missing)
- Xpath 65536 " X: 65536
- 3substitute/subst/\=SUBST("substitute", 8)/e
- Xpath 131072 " X: 131072
- endtry
- Xpath 262144 " X: 262144
- 4,6substitute/subst/\=SUBST("substitute", 9)/
- Xpath 524288 " X: 0
- catch /^substitute[678]/
- Xpath 1048576 " X: 0
- catch /^substitute9/
- Xpath 2097152 " X: 2097152
- finally
- bwipeout!
- call delete(file)
- endtry
-
- try
- Xpath 4194304 " X: 4194304
- let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '')
- Xpath 8388608 " X: 0
- catch /substitute()y/
- Xpath 16777216 " X: 16777216
- catch /.*/
- Xpath 33554432 " X: 0
- Xout "substitute()y:" v:exception "in" v:throwpoint
- endtry
-
- try
- Xpath 67108864 " X: 67108864
- let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '')
- Xpath 134217728 " X: 134217728
- catch /substitute()n/
- Xpath 268435456 " X: 0
- catch /.*/
- Xpath 536870912 " X: 0
- Xout "substitute()n:" v:exception "in" v:throwpoint
- endtry
-
- let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10"
- if taken != expected
- Xpath 1073741824 " X: 0
- Xout "'taken' is" taken "instead of" expected
- endif
-
-catch /.*/
- " The Xpath command does not accept 2^31 (negative); add explicitly:
- let Xpath = Xpath + 2147483648 " X: 0
- Xout v:exception "in" v:throwpoint
-endtry
-
-unlet result var taken expected
-delfunction THROW
-delfunction EXPR
-delfunction SKIP
-delfunction SUBST
-
-Xcheck 224907669
-
-
-"-------------------------------------------------------------------------------
-" Test 75: Errors in builtin functions. {{{1
-"
-" On an error in a builtin function called inside a :try/:endtry
-" region, the evaluation of the expression calling that function and
-" the command containing that expression are abandoned. The error can
-" be caught as an exception.
-"
-" A simple :call of the builtin function is a trivial case. If the
-" builtin function is called in the argument list of another function,
-" no further arguments are evaluated, and the other function is not
-" executed. If the builtin function is called from the argument of
-" a :return command, the :return command is not executed. If the
-" builtin function is called from the argument of a :throw command,
-" the :throw command is not executed. The evaluation of the
-" expression calling the builtin function is abandoned.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F1(arg1)
- Xpath 1 " X: 0
-endfunction
-
-function! F2(arg1, arg2)
- Xpath 2 " X: 0
-endfunction
-
-function! G()
- Xpath 4 " X: 0
-endfunction
-
-function! H()
- Xpath 8 " X: 0
-endfunction
-
-function! R()
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 16 " X: 16
- return append(1, "s")
- catch /E21/
- let caught = 1
- catch /.*/
- Xpath 32 " X: 0
- finally
- Xpath 64 " X: 64
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 128 " X: 128
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
- Xpath 256 " X: 256
-endfunction
-
-try
- set noma " let append() fail with "E21"
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 512 " X: 512
- call append(1, "s")
- catch /E21/
- let caught = 1
- catch /.*/
- Xpath 1024 " X: 0
- finally
- Xpath 2048 " X: 2048
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 4096 " X: 4096
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 8192 " X: 8192
- call F1('x' . append(1, "s"))
- catch /E21/
- let caught = 1
- catch /.*/
- Xpath 16384 " X: 0
- finally
- Xpath 32768 " X: 32768
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 65536 " X: 65536
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 131072 " X: 131072
- call F2('x' . append(1, "s"), G())
- catch /E21/
- let caught = 1
- catch /.*/
- Xpath 262144 " X: 0
- finally
- Xpath 524288 " X: 524288
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 1048576 " X: 1048576
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-
- call R()
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 2097152 " X: 2097152
- throw "T" . append(1, "s")
- catch /E21/
- let caught = 1
- catch /^T.*/
- Xpath 4194304 " X: 0
- catch /.*/
- Xpath 8388608 " X: 0
- finally
- Xpath 16777216 " X: 16777216
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 33554432 " X: 33554432
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-
- while 1
- try
- let caught = 0
- let v:errmsg = ""
- Xpath 67108864 " X: 67108864
- let x = "a"
- let x = x . "b" . append(1, "s") . H()
- catch /E21/
- let caught = 1
- catch /.*/
- Xpath 134217728 " X: 0
- finally
- Xpath 268435456 " X: 268435456
- if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
- Xpath 536870912 " X: 536870912
- endif
- if x == "a"
- Xpath 1073741824 " X: 1073741824
- endif
- break " discard error for $VIMNOERRTHROW
- endtry
- endwhile
-catch /.*/
- " The Xpath command does not accept 2^31 (negative); add explicitly:
- let Xpath = Xpath + 2147483648 " X: 0
- Xout v:exception "in" v:throwpoint
-finally
- set ma&
-endtry
-
-unlet! caught x
-delfunction F1
-delfunction F2
-delfunction G
-delfunction H
-delfunction R
-
-Xcheck 2000403408
+" Tests 69 to 75 were moved to test_trycatch.vim
+let Xtest = 76
"-------------------------------------------------------------------------------
@@ -8780,36 +6523,9 @@ delfunction F
Xout "No Crash for vimgrep on BufUnload"
Xcheck 0
-"-------------------------------------------------------------------------------
-" Test 87 using (expr) ? funcref : funcref {{{1
-"
-" Vim needs to correctly parse the funcref and even when it does
-" not execute the funcref, it needs to consume the trailing ()
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-func Add2(x1, x2)
- return a:x1 + a:x2
-endfu
-
-func GetStr()
- return "abcdefghijklmnopqrstuvwxyp"
-endfu
+" Test 87 was moved to test_vimscript.vim
+let Xtest = 88
-echo function('Add2')(2,3)
-
-Xout 1 ? function('Add2')(1,2) : function('Add2')(2,3)
-Xout 0 ? function('Add2')(1,2) : function('Add2')(2,3)
-" Make sure, GetStr() still works.
-Xout GetStr()[0:10]
-
-
-delfunction GetStr
-delfunction Add2
-Xout "Successfully executed funcref Add2"
-
-Xcheck 0
"-------------------------------------------------------------------------------
" Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
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_clientserver.vim b/src/nvim/testdir/test_clientserver.vim
index 3377f86126..53704bd094 100644
--- a/src/nvim/testdir/test_clientserver.vim
+++ b/src/nvim/testdir/test_clientserver.vim
@@ -61,6 +61,15 @@ func Test_client_server()
call assert_fails('call remote_send("XXX", ":let testvar = ''yes''\<CR>")', 'E241')
+ call writefile(['one'], 'Xclientfile')
+ let cmd = GetVimProg() .. ' --servername ' .. name .. ' --remote Xclientfile'
+ call system(cmd)
+ call WaitForAssert({-> assert_equal('Xclientfile', remote_expr(name, "bufname()", "", 2))})
+ call WaitForAssert({-> assert_equal('one', remote_expr(name, "getline(1)", "", 2))})
+ call writefile(['one', 'two'], 'Xclientfile')
+ call system(cmd)
+ call WaitForAssert({-> assert_equal('two', remote_expr(name, "getline(2)", "", 2))})
+
" Expression evaluated locally.
if v:servername == ''
call remote_startserver('MYSELF')
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 81f653c393..39f865144a 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -51,6 +51,22 @@ func Test_complete_wildmenu()
call feedkeys(":e Xdir1/\<Tab>\<Down>\<Up>\<Right>\<CR>", 'tx')
call assert_equal('testfile1', getline(1))
+ " this fails in some Unix GUIs, not sure why
+ if !has('unix') || !has('gui_running')
+ " <C-J>/<C-K> mappings to go up/down directories when 'wildcharm' is
+ " different than 'wildchar'.
+ set wildcharm=<C-Z>
+ cnoremap <C-J> <Down><C-Z>
+ cnoremap <C-K> <Up><C-Z>
+ call feedkeys(":e Xdir1/\<Tab>\<C-J>\<CR>", 'tx')
+ call assert_equal('testfile3', getline(1))
+ call feedkeys(":e Xdir1/\<Tab>\<C-J>\<C-K>\<CR>", 'tx')
+ call assert_equal('testfile1', getline(1))
+ set wildcharm=0
+ cunmap <C-J>
+ cunmap <C-K>
+ endif
+
" cleanup
%bwipe
call delete('Xdir1/Xdir2/Xtestfile4')
@@ -62,6 +78,33 @@ func Test_complete_wildmenu()
set nowildmenu
endfunc
+func Test_wildmenu_screendump()
+ CheckScreendump
+
+ let lines =<< trim [SCRIPT]
+ set wildmenu hlsearch
+ [SCRIPT]
+ call writefile(lines, 'XTest_wildmenu')
+
+ let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8})
+ call term_sendkeys(buf, ":vim\<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_1', {})
+
+ call term_sendkeys(buf, "\<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_2', {})
+
+ call term_sendkeys(buf, "\<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_3', {})
+
+ call term_sendkeys(buf, "\<Tab>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_4', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XTest_wildmenu')
+endfunc
+
func Test_map_completion()
if !has('cmdline_compl')
return
@@ -548,6 +591,13 @@ func Test_cmdline_complete_user_names()
endif
endfunc
+func Test_cmdline_complete_bang()
+ if executable('whoami')
+ call feedkeys(":!whoam\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_match('^".*\<whoami\>', @:)
+ endif
+endfunc
+
funct Test_cmdline_complete_languages()
let lang = substitute(execute('language messages'), '.*"\(.*\)"$', '\1', '')
@@ -570,6 +620,17 @@ funct Test_cmdline_complete_languages()
endif
endfunc
+func Test_cmdline_complete_expression()
+ let g:SomeVar = 'blah'
+ for cmd in ['exe', 'echo', 'echon', 'echomsg']
+ call feedkeys(":" .. cmd .. " SomeV\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"' .. cmd .. ' SomeVar', @:)
+ call feedkeys(":" .. cmd .. " foo SomeV\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"' .. cmd .. ' foo SomeVar', @:)
+ endfor
+ unlet g:SomeVar
+endfunc
+
func Test_cmdline_write_alternatefile()
new
call setline('.', ['one', 'two'])
@@ -819,6 +880,36 @@ func Test_cmdwin_cedit()
delfunc CmdWinType
endfunc
+func Test_cmdwin_restore()
+ CheckScreendump
+
+ let lines =<< trim [SCRIPT]
+ call setline(1, range(30))
+ 2split
+ [SCRIPT]
+ call writefile(lines, 'XTest_restore')
+
+ let buf = RunVimInTerminal('-S XTest_restore', {'rows': 12})
+ call term_wait(buf, 100)
+ call term_sendkeys(buf, "q:")
+ call VerifyScreenDump(buf, 'Test_cmdwin_restore_1', {})
+
+ " normal restore
+ call term_sendkeys(buf, ":q\<CR>")
+ call VerifyScreenDump(buf, 'Test_cmdwin_restore_2', {})
+
+ " restore after setting 'lines' with one window
+ call term_sendkeys(buf, ":close\<CR>")
+ call term_sendkeys(buf, "q:")
+ call term_sendkeys(buf, ":set lines=18\<CR>")
+ call term_sendkeys(buf, ":q\<CR>")
+ call VerifyScreenDump(buf, 'Test_cmdwin_restore_3', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XTest_restore')
+endfunc
+
func Test_buffers_lastused()
" check that buffers are sorted by time when wildmode has lastused
edit bufc " oldest
@@ -894,5 +985,23 @@ func Test_zero_line_search()
q!
endfunc
+func Test_read_shellcmd()
+ CheckUnix
+ if executable('ls')
+ " There should be ls in the $PATH
+ call feedkeys(":r! l\<c-a>\<c-b>\"\<cr>", 'tx')
+ call assert_match('^"r! .*\<ls\>', @:)
+ endif
+
+ if executable('rm')
+ call feedkeys(":r! ++enc=utf-8 r\<c-a>\<c-b>\"\<cr>", 'tx')
+ call assert_notmatch('^"r!.*\<runtest.vim\>', @:)
+ call assert_match('^"r!.*\<rm\>', @:)
+
+ call feedkeys(":r ++enc=utf-8 !rm\<c-a>\<c-b>\"\<cr>", 'tx')
+ call assert_notmatch('^"r.*\<runtest.vim\>', @:)
+ call assert_match('^"r ++enc\S\+ !.*\<rm\>', @:)
+ endif
+endfunc
-" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_const.vim b/src/nvim/testdir/test_const.vim
index fc7ea71f6e..ea69c8cba4 100644
--- a/src/nvim/testdir/test_const.vim
+++ b/src/nvim/testdir/test_const.vim
@@ -109,7 +109,7 @@ func Test_define_script_var_with_lock()
unlet s:x
endfunc
-func Test_descructuring_with_lock()
+func Test_destructuring_with_lock()
const [a, b, c] = [1, 1.1, 'vim']
call assert_fails('let a = 1', 'E741:')
diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim
index 9eea27740d..b6d9687560 100644
--- a/src/nvim/testdir/test_digraph.vim
+++ b/src/nvim/testdir/test_digraph.vim
@@ -1,8 +1,8 @@
" Tests for digraphs
-if !has("digraphs")
- finish
-endif
+source check.vim
+CheckFeature digraphs
+source term_util.vim
func Put_Dig(chars)
exe "norm! o\<c-k>".a:chars
@@ -487,4 +487,20 @@ func Test_show_digraph_cp1251()
bwipe!
endfunc
+" Test for the characters displayed on the screen when entering a digraph
+func Test_entering_digraph()
+ CheckRunVimInTerminal
+ let buf = RunVimInTerminal('', {'rows': 6})
+ call term_sendkeys(buf, "i\<C-K>")
+ call term_wait(buf)
+ call assert_equal('?', term_getline(buf, 1))
+ call term_sendkeys(buf, "1")
+ call term_wait(buf)
+ call assert_equal('1', term_getline(buf, 1))
+ call term_sendkeys(buf, "2")
+ call term_wait(buf)
+ call assert_equal('½', term_getline(buf, 1))
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_excmd.vim b/src/nvim/testdir/test_excmd.vim
index 4a027c3864..20508b12d3 100644
--- a/src/nvim/testdir/test_excmd.vim
+++ b/src/nvim/testdir/test_excmd.vim
@@ -1,5 +1,7 @@
" Tests for various Ex commands.
+source check.vim
+
func Test_ex_delete()
new
call setline(1, ['a', 'b', 'c'])
@@ -9,6 +11,17 @@ func Test_ex_delete()
call assert_equal(['a', 'c'], getline(1, 2))
endfunc
+func Test_range_error()
+ call assert_fails(':.echo 1', 'E481:')
+ call assert_fails(':$echo 1', 'E481:')
+ call assert_fails(':1,2echo 1', 'E481:')
+ call assert_fails(':+1echo 1', 'E481:')
+ call assert_fails(':/1/echo 1', 'E481:')
+ call assert_fails(':\/echo 1', 'E481:')
+ normal vv
+ call assert_fails(":'<,'>echo 1", 'E481:')
+endfunc
+
func Test_buffers_lastused()
edit bufc " oldest
@@ -40,3 +53,81 @@ func Test_buffers_lastused()
bwipeout bufb
bwipeout bufc
endfunc
+
+" Test for the :confirm command dialog
+func Test_confirm_cmd()
+ CheckNotGui
+ CheckRunVimInTerminal
+ call writefile(['foo1'], 'foo')
+ call writefile(['bar1'], 'bar')
+ " Test for saving all the modified buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo2')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar2')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "A")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo2'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+ " Test for discarding all the changes to modified buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo3')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar3')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "D")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo2'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+ " Test for saving and discarding changes to some buffers
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new foo\n")
+ call term_sendkeys(buf, ":call setline(1, 'foo4')\n")
+ call term_sendkeys(buf, ":new bar\n")
+ call term_sendkeys(buf, ":call setline(1, 'bar4')\n")
+ call term_sendkeys(buf, ":wincmd b\n")
+ call term_sendkeys(buf, ":confirm qall\n")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, Save (A)ll, (D)iscard All, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "N")
+ call WaitForAssert({-> assert_match('\[Y\]es, (N)o, (C)ancel: ', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "Y")
+ call StopVimInTerminal(buf)
+ call assert_equal(['foo4'], readfile('foo'))
+ call assert_equal(['bar2'], readfile('bar'))
+
+ call delete('foo')
+ call delete('bar')
+endfunc
+
+func Test_confirm_cmd_cancel()
+ CheckNotGui
+ CheckRunVimInTerminal
+
+ " Test for closing a window with a modified buffer
+ let buf = RunVimInTerminal('', {'rows': 20})
+ call term_sendkeys(buf, ":set nomore\n")
+ call term_sendkeys(buf, ":new\n")
+ call term_sendkeys(buf, ":call setline(1, 'abc')\n")
+ call term_sendkeys(buf, ":confirm close\n")
+ call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+ \ term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "C")
+ call WaitForAssert({-> assert_equal('', term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, ":confirm close\n")
+ call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+ \ term_getline(buf, 20))}, 1000)
+ call term_sendkeys(buf, "N")
+ call WaitForAssert({-> assert_match('^ *0,0-1 All$',
+ \ term_getline(buf, 20))}, 1000)
+ call StopVimInTerminal(buf)
+endfunc
diff --git a/src/nvim/testdir/test_fileformat.vim b/src/nvim/testdir/test_fileformat.vim
index 8dc25f62b1..465613f1cf 100644
--- a/src/nvim/testdir/test_fileformat.vim
+++ b/src/nvim/testdir/test_fileformat.vim
@@ -31,3 +31,26 @@ func Test_fileformat_autocommand()
au! BufReadPre Xfile
bw!
endfunc
+
+" Test for changing the fileformat using ++read
+func Test_fileformat_plusplus_read()
+ new
+ call setline(1, ['one', 'two', 'three'])
+ w ++ff=dos Xfile1
+ enew!
+ set ff=unix
+ " A :read doesn't change the fileformat, but does apply to the read lines.
+ r ++fileformat=unix Xfile1
+ call assert_equal('unix', &fileformat)
+ call assert_equal("three\r", getline('$'))
+ 3r ++edit Xfile1
+ call assert_equal('dos', &fileformat)
+ close!
+ call delete('Xfile1')
+ set fileformat&
+ call assert_fails('e ++fileformat Xfile1', 'E474:')
+ call assert_fails('e ++ff=abc Xfile1', 'E474:')
+ call assert_fails('e ++abc1 Xfile1', 'E474:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 52b5884c8b..1cb68e7fef 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -150,6 +150,7 @@ let s:filename_checks = {
\ 'dsl': ['file.dsl'],
\ 'dtd': ['file.dtd'],
\ 'dts': ['file.dts', 'file.dtsi'],
+ \ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
\ 'dylan': ['file.dylan'],
\ 'dylanintr': ['file.intr'],
\ 'dylanlid': ['file.lid'],
@@ -181,6 +182,7 @@ let s:filename_checks = {
\ 'gdb': ['.gdbinit'],
\ 'gdmo': ['file.mo', 'file.gdmo'],
\ 'gedcom': ['file.ged', 'lltxxxxx.txt'],
+ \ 'gift': ['file.gift'],
\ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'],
\ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig'],
\ 'gitolite': ['gitolite.conf'],
@@ -321,9 +323,10 @@ let s:filename_checks = {
\ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom'],
\ 'nsis': ['file.nsi', 'file.nsh'],
\ 'obj': ['file.obj'],
- \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit'],
+ \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'],
\ 'occam': ['file.occ'],
\ 'omnimark': ['file.xom', 'file.xin'],
+ \ 'opam': ['opam', 'file.opam', 'file.opam.template'],
\ 'openroad': ['file.or'],
\ 'ora': ['file.ora'],
\ 'pamconf': ['/etc/pam.conf'],
@@ -397,6 +400,7 @@ let s:filename_checks = {
\ 'scheme': ['file.scm', 'file.ss', 'file.rkt'],
\ 'scilab': ['file.sci', 'file.sce'],
\ 'screen': ['.screenrc', 'screenrc'],
+ \ 'sexplib': ['file.sexp'],
\ 'scss': ['file.scss'],
\ 'sd': ['file.sd'],
\ 'sdc': ['file.sdc'],
@@ -463,6 +467,7 @@ let s:filename_checks = {
\ 'tilde': ['file.t.html'],
\ 'tli': ['file.tli'],
\ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf'],
+ \ 'toml': ['file.toml'],
\ 'tpp': ['file.tpp'],
\ 'treetop': ['file.treetop'],
\ 'trustees': ['trustees.conf'],
@@ -471,7 +476,6 @@ let s:filename_checks = {
\ 'tssgm': ['file.tssgm'],
\ 'tssop': ['file.tssop'],
\ 'twig': ['file.twig'],
- \ 'typescript': ['file.ts'],
\ 'typescriptreact': ['file.tsx'],
\ 'uc': ['file.uc'],
\ 'udevconf': ['/etc/udev/udev.conf'],
@@ -668,5 +672,22 @@ func Test_hook_file()
filetype off
endfunc
+func Test_ts_file()
+ filetype on
+
+ call writefile(['<?xml version="1.0" encoding="utf-8"?>'], 'Xfile.ts')
+ split Xfile.ts
+ call assert_equal('xml', &filetype)
+ bwipe!
+
+ call writefile(['// looks like Typescript'], 'Xfile.ts')
+ split Xfile.ts
+ call assert_equal('typescript', &filetype)
+ bwipe!
+
+ call delete('Xfile.hook')
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_find_complete.vim b/src/nvim/testdir/test_find_complete.vim
index a7bc135d47..0a00d9432f 100644
--- a/src/nvim/testdir/test_find_complete.vim
+++ b/src/nvim/testdir/test_find_complete.vim
@@ -15,22 +15,22 @@ func Test_find_complete()
new
set path=
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E345:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=.
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=.,,
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
new
set path=./**
- call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:')
+ call assert_fails('call feedkeys(":find \t\n", "xt")', 'E471:')
close
" We shouldn't find any file till this point
diff --git a/src/nvim/testdir/test_findfile.vim b/src/nvim/testdir/test_findfile.vim
index f5488a6a27..2195bf527e 100644
--- a/src/nvim/testdir/test_findfile.vim
+++ b/src/nvim/testdir/test_findfile.vim
@@ -184,3 +184,46 @@ func Test_finddir_error()
call assert_fails('call finddir("x", "**x")', 'E343:')
call assert_fails('call finddir("x", repeat("x", 5000))', 'E854:')
endfunc
+
+" Test for the :find, :sfind and :tabfind commands
+func Test_find_cmd()
+ new
+ let save_path = &path
+ let save_dir = getcwd()
+ set path=.,./**/*
+ call CreateFiles()
+ cd Xdir1
+ " Test for :find
+ find foo
+ call assert_equal('foo', expand('%:.'))
+ 2find foo
+ call assert_equal('Xdir2/foo', expand('%:.'))
+ call assert_fails('3find foo', 'E347:')
+ " Test for :sfind
+ enew
+ sfind barfoo
+ call assert_equal('Xdir2/Xdir3/barfoo', expand('%:.'))
+ call assert_equal(3, winnr('$'))
+ close
+ call assert_fails('sfind baz', 'E345:')
+ call assert_equal(2, winnr('$'))
+ " Test for :tabfind
+ enew
+ tabfind foobar
+ call assert_equal('Xdir2/foobar', expand('%:.'))
+ call assert_equal(2, tabpagenr('$'))
+ tabclose
+ call assert_fails('tabfind baz', 'E345:')
+ call assert_equal(1, tabpagenr('$'))
+ " call chdir(save_dir)
+ exe 'cd ' . save_dir
+ call CleanFiles()
+ let &path = save_path
+ close
+
+ call assert_fails('find', 'E471:')
+ call assert_fails('sfind', 'E471:')
+ call assert_fails('tabfind', 'E471:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 3c90c45952..88ce64b9eb 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -815,4 +815,11 @@ func Test_fold_create_delete_create()
bwipe!
endfunc
+" this was crashing
+func Test_fold_create_delete()
+ new
+ norm zFzFzdzj
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_global.vim b/src/nvim/testdir/test_global.vim
index bdeaf8e2cf..7ccf2812ff 100644
--- a/src/nvim/testdir/test_global.vim
+++ b/src/nvim/testdir/test_global.vim
@@ -1,3 +1,4 @@
+source check.vim
func Test_yank_put_clipboard()
new
@@ -10,6 +11,16 @@ func Test_yank_put_clipboard()
bwipe!
endfunc
+func Test_global_set_clipboard()
+ CheckFeature clipboard_working
+ new
+ set clipboard=unnamedplus
+ let @+='clipboard' | g/^/set cb= | let @" = 'unnamed' | put
+ call assert_equal(['','unnamed'], getline(1, '$'))
+ set clipboard&
+ bwipe!
+endfunc
+
func Test_nested_global()
new
call setline(1, ['nothing', 'found', 'found bad', 'bad'])
diff --git a/src/nvim/testdir/test_hardcopy.vim b/src/nvim/testdir/test_hardcopy.vim
index 6125f9b993..e390bd5cc8 100644
--- a/src/nvim/testdir/test_hardcopy.vim
+++ b/src/nvim/testdir/test_hardcopy.vim
@@ -1,5 +1,7 @@
" Test :hardcopy
+source check.vim
+
func Test_printoptions()
edit test_hardcopy.vim
syn on
@@ -8,8 +10,10 @@ func Test_printoptions()
\ 'left:2in,top:30pt,right:16mm,bottom:3pc',
\ 'header:3,syntax:y,number:y,wrap:n',
\ 'header:3,syntax:n,number:y,wrap:y',
+ \ 'header:0,syntax:a,number:y,wrap:y',
\ 'duplex:short,collate:n,jobsplit:y,portrait:n',
\ 'duplex:long,collate:y,jobsplit:n,portrait:y',
+ \ 'duplex:off,collate:y,jobsplit:y,portrait:y',
\ 'paper:10x14',
\ 'paper:A3',
\ 'paper:A4',
@@ -28,7 +32,7 @@ func Test_printoptions()
\ '']
exe 'set printoptions=' .. opt
if has('postscript')
- hardcopy > Xhardcopy_printoptions
+ 1,50hardcopy > Xhardcopy_printoptions
let lines = readfile('Xhardcopy_printoptions')
call assert_true(len(lines) > 20, opt)
call assert_true(lines[0] =~ 'PS-Adobe', opt)
@@ -44,8 +48,8 @@ func Test_printoptions()
endfunc
func Test_printmbfont()
- " Print a small help page which contains tabs to cover code that expands tabs to spaces.
- help help
+ " Print a help page which contains tabs, underlines (etc) to recover more code.
+ help syntax.txt
syn on
for opt in [':WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-Bold-Italic,c:yes,a:no',
@@ -63,10 +67,39 @@ func Test_printmbfont()
bwipe
endfunc
+func Test_printmbcharset()
+ CheckFeature postscript
+
+ " digraph.txt has plenty of non-latin1 characters.
+ help digraph.txt
+ set printmbcharset=ISO10646 printencoding=utf-8
+ for courier in ['yes', 'no']
+ for ascii in ['yes', 'no']
+ exe 'set printmbfont=r:WadaMin-Regular,b:WadaMin-Bold,i:WadaMin-Italic,o:WadaMin-BoldItalic'
+ \ .. ',c:' .. courier .. ',a:' .. ascii
+ hardcopy > Xhardcopy_printmbcharset
+ let lines = readfile('Xhardcopy_printmbcharset')
+ call assert_true(len(lines) > 20)
+ call assert_true(lines[0] =~ 'PS-Adobe')
+ endfor
+ endfor
+
+ set printmbcharset=does-not-exist printencoding=utf-8 printmbfont=r:WadaMin-Regular
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E456:')
+
+ set printmbcharset=GB_2312-80 printencoding=utf-8 printmbfont=r:WadaMin-Regular
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E673:')
+
+ set printmbcharset=ISO10646 printencoding=utf-8 printmbfont=
+ call assert_fails('hardcopy > Xhardcopy_printmbcharset', 'E675:')
+
+ call delete('Xhardcopy_printmbcharset')
+ set printmbcharset& printencoding& printmbfont&
+ bwipe
+endfunc
+
func Test_printexpr()
- if !has('unix')
- return
- endif
+ CheckFeature postscript
" Not a very useful printexpr value, but enough to test
" hardcopy with 'printexpr'.
@@ -84,7 +117,7 @@ func Test_printexpr()
\ readfile('Xhardcopy_printexpr'))
call delete('Xhardcopy_printexpr')
- " Function return 1 to test print failure.
+ " Function returns 1 to test print failure.
function PrintFails(fname)
call delete(a:fname)
return 1
@@ -97,12 +130,11 @@ func Test_printexpr()
endfunc
func Test_errors()
- " FIXME: Windows fails differently than Unix.
- if has('unix')
- edit test_hardcopy.vim
- call assert_fails('hardcopy >', 'E324:')
- bwipe
- endif
+ CheckFeature postscript
+
+ edit test_hardcopy.vim
+ call assert_fails('hardcopy >', 'E324:')
+ bwipe
endfunc
func Test_dark_background()
@@ -126,12 +158,11 @@ func Test_dark_background()
endfun
func Test_empty_buffer()
- " FIXME: Unclear why this fails on Windows.
- if has('unix')
- new
- call assert_equal("\nNo text to be printed", execute('hardcopy'))
- bwipe
- endif
+ CheckFeature postscript
+
+ new
+ call assert_equal("\nNo text to be printed", execute('hardcopy'))
+ bwipe
endfunc
func Test_printheader_parsing()
@@ -145,9 +176,8 @@ func Test_printheader_parsing()
endfunc
func Test_fname_with_spaces()
- if !has('postscript')
- return
- endif
+ CheckFeature postscript
+
split t\ e\ s\ t.txt
call setline(1, ['just', 'some', 'text'])
hardcopy > %.ps
@@ -157,9 +187,11 @@ func Test_fname_with_spaces()
endfunc
func Test_illegal_byte()
- if !has('postscript') || &enc != 'utf-8'
+ CheckFeature postscript
+ if &enc != 'utf-8'
return
endif
+
new
" conversion of 0xff will fail, this used to cause a crash
call setline(1, "\xff")
@@ -168,3 +200,5 @@ func Test_illegal_byte()
bwipe!
call delete('Xpstest')
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_help.vim b/src/nvim/testdir/test_help.vim
index 01fb9917e9..8e59efd22d 100644
--- a/src/nvim/testdir/test_help.vim
+++ b/src/nvim/testdir/test_help.vim
@@ -56,3 +56,49 @@ func Test_help_local_additions()
call delete('Xruntime', 'rf')
let &rtp = rtp_save
endfunc
+
+" Test for the :helptags command
+func Test_helptag_cmd()
+ call mkdir('Xdir/a/doc', 'p')
+
+ " No help file to process in the directory
+ call assert_fails('helptags Xdir', 'E151:')
+
+ call writefile([], 'Xdir/a/doc/sample.txt')
+
+ " Test for ++t argument
+ helptags ++t Xdir
+ call assert_equal(["help-tags\ttags\t1"], readfile('Xdir/tags'))
+ call delete('Xdir/tags')
+
+ " The following tests fail on FreeBSD for some reason
+ if has('unix') && !has('bsd')
+ " Read-only tags file
+ call mkdir('Xdir/doc', 'p')
+ call writefile([''], 'Xdir/doc/tags')
+ call writefile([], 'Xdir/doc/sample.txt')
+ call setfperm('Xdir/doc/tags', 'r-xr--r--')
+ call assert_fails('helptags Xdir/doc', 'E152:', getfperm('Xdir/doc/tags'))
+
+ let rtp = &rtp
+ let &rtp = 'Xdir'
+ helptags ALL
+ let &rtp = rtp
+
+ call delete('Xdir/doc/tags')
+
+ " No permission to read the help file
+ call setfperm('Xdir/a/doc/sample.txt', '-w-------')
+ call assert_fails('helptags Xdir', 'E153:', getfperm('Xdir/a/doc/sample.txt'))
+ call delete('Xdir/a/doc/sample.txt')
+ call delete('Xdir/tags')
+ endif
+
+ " Duplicate tags in the help file
+ call writefile(['*tag1*', '*tag1*', '*tag2*'], 'Xdir/a/doc/sample.txt')
+ call assert_fails('helptags Xdir', 'E154:')
+
+ call delete('Xdir', 'rf')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 57a0a7aaf4..9435931d41 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -280,7 +280,7 @@ func Test_omni_dash()
set omnifunc=Omni
new
exe "normal Gofind -\<C-x>\<C-o>"
- call assert_equal("\n-\nmatch 1 of 2", execute(':2mess'))
+ call assert_equal("find -help", getline('$'))
bwipe!
delfunc Omni
@@ -312,6 +312,24 @@ func Test_completefunc_args()
delfunc CompleteFunc
endfunc
+func CompleteTest(findstart, query)
+ if a:findstart
+ return col('.')
+ endif
+ return ['matched']
+endfunc
+
+func Test_completefunc_info()
+ new
+ set completeopt=menuone
+ set completefunc=CompleteTest
+ call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
+ call assert_equal("matched{'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
+ bwipe!
+ set completeopt&
+ set completefunc&
+endfunc
+
" Check that when using feedkeys() typeahead does not interrupt searching for
" completions.
func Test_compl_feedkeys()
@@ -450,3 +468,17 @@ func Test_pum_with_folds_two_tabs()
call StopVimInTerminal(buf)
call delete('Xpumscript')
endfunc
+
+" Test to ensure 'Scanning...' messages are not recorded in messages history
+func Test_z1_complete_no_history()
+ new
+ messages clear
+ let currmess = execute('messages')
+ setlocal dictionary=README.txt
+ exe "normal owh\<C-X>\<C-K>"
+ exe "normal owh\<C-N>"
+ call assert_equal(currmess, execute('messages'))
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim
index 66df57ea39..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
@@ -201,3 +206,28 @@ func Test_mark_error()
call assert_fails('mark xx', 'E488:')
call assert_fails('mark _', 'E191:')
endfunc
+
+" Test for the getmarklist() function
+func Test_getmarklist()
+ new
+ " global marks
+ delmarks A-Z 0-9 \" ^.[]
+ call assert_equal([], getmarklist())
+ call setline(1, ['one', 'two', 'three'])
+ mark A
+ call cursor(3, 5)
+ normal mN
+ call assert_equal([{'file' : '', 'mark' : "'A", 'pos' : [bufnr(), 1, 1, 0]},
+ \ {'file' : '', 'mark' : "'N", 'pos' : [bufnr(), 3, 5, 0]}],
+ \ getmarklist())
+ " buffer local marks
+ delmarks!
+ call assert_equal([{'mark' : "''", 'pos' : [bufnr(), 1, 1, 0]},
+ \ {'mark' : "'\"", 'pos' : [bufnr(), 1, 1, 0]}], getmarklist(bufnr()))
+ call cursor(2, 2)
+ normal mr
+ call assert_equal({'mark' : "'r", 'pos' : [bufnr(), 2, 2, 0]},
+ \ getmarklist(bufnr())[0])
+ call assert_equal([], getmarklist({}))
+ close!
+endfunc
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index 215065f941..f71da92bf8 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -128,6 +128,7 @@ func Test_mksession()
call delete('Xtest_mks.out')
call delete(tmpfile)
let &wrap = wrap_save
+ set sessionoptions&
endfunc
func Test_mksession_winheight()
@@ -154,7 +155,7 @@ func Test_mksession_rtp()
return
endif
new
- set sessionoptions+=options
+ set sessionoptions&vi
let _rtp=&rtp
" Make a real long (invalid) runtimepath value,
" that should exceed PATH_MAX (hopefully)
@@ -174,17 +175,23 @@ func Test_mksession_rtp()
call assert_equal(expected, li)
call delete('Xtest_mks.out')
+ set sessionoptions&
endfunc
-" Verify that arglist is stored correctly to the session file.
func Test_mksession_arglist()
%argdel
next file1 file2 file3 file4
+ new
+ next | next
mksession! Xtest_mks.out
source Xtest_mks.out
call assert_equal(['file1', 'file2', 'file3', 'file4'], argv())
+ call assert_equal(2, argidx())
+ wincmd w
+ call assert_equal(0, argidx())
call delete('Xtest_mks.out')
+ enew | only
argdel *
endfunc
@@ -218,6 +225,72 @@ func Test_mksession_one_buffer_two_windows()
call delete('Xtest_mks.out')
endfunc
+func Test_mksession_lcd_multiple_tabs()
+ tabnew
+ tabnew
+ lcd .
+ tabfirst
+ lcd .
+ mksession! Xtest_mks.out
+ tabonly
+ source Xtest_mks.out
+ call assert_true(haslocaldir(), 'Tab 1 localdir')
+ tabnext 2
+ call assert_true(!haslocaldir(), 'Tab 2 localdir')
+ tabnext 3
+ call assert_true(haslocaldir(), 'Tab 3 localdir')
+ call delete('Xtest_mks.out')
+endfunc
+
+func Test_mksession_blank_tabs()
+ tabnew
+ tabnew
+ tabnew
+ tabnext 3
+ mksession! Xtest_mks.out
+ tabnew
+ tabnew
+ tabnext 2
+ source Xtest_mks.out
+ call assert_equal(4, tabpagenr('$'), 'session restore should restore number of tabs')
+ call assert_equal(3, tabpagenr(), 'session restore should restore the active tab')
+ call delete('Xtest_mks.out')
+endfunc
+
+func Test_mksession_blank_windows()
+ split
+ split
+ split
+ 3 wincmd w
+ mksession! Xtest_mks.out
+ split
+ split
+ 2 wincmd w
+ source Xtest_mks.out
+ call assert_equal(4, winnr('$'), 'session restore should restore number of windows')
+ call assert_equal(3, winnr(), 'session restore should restore the active window')
+ call delete('Xtest_mks.out')
+endfunc
+
+if has('extra_search')
+
+func Test_mksession_hlsearch()
+ set sessionoptions&vi
+ set hlsearch
+ mksession! Xtest_mks.out
+ nohlsearch
+ source Xtest_mks.out
+ call assert_equal(1, v:hlsearch, 'session should restore search highlighting state')
+ nohlsearch
+ mksession! Xtest_mks.out
+ source Xtest_mks.out
+ call assert_equal(0, v:hlsearch, 'session should restore search highlighting state')
+ set sessionoptions&
+ call delete('Xtest_mks.out')
+endfunc
+
+endif
+
" Test :mkview with a file argument.
func Test_mkview_file()
" Create a view with line number and a fold.
@@ -335,24 +408,28 @@ func Test_mksession_globals()
set sessionoptions+=globals
" create different global variables
- let g:Global_string = "Sun is shining"
+ let g:Global_string = "Sun is shining\r\n"
let g:Global_count = 100
let g:Global_pi = 3.14
+ let g:Global_neg_float = -2.68
mksession! Xtest_mks.out
unlet g:Global_string
unlet g:Global_count
unlet g:Global_pi
+ unlet g:Global_neg_float
source Xtest_mks.out
- call assert_equal("Sun is shining", g:Global_string)
+ call assert_equal("Sun is shining\r\n", g:Global_string)
call assert_equal(100, g:Global_count)
call assert_equal(3.14, g:Global_pi)
+ call assert_equal(-2.68, g:Global_neg_float)
unlet g:Global_string
unlet g:Global_count
unlet g:Global_pi
+ unlet g:Global_neg_float
call delete('Xtest_mks.out')
set sessionoptions&
endfunc
@@ -411,20 +488,123 @@ func Test_mksession_resize()
for line in lines
if line =~ '^set lines='
let found_resize = v:true
+ break
endif
endfor
- call assert_equal(v:false, found_resize)
+ call assert_false(found_resize)
let lines = readfile('Xtest_mks2.out')
let found_resize = v:false
for line in lines
if line =~ '^set lines='
let found_resize = v:true
+ break
+ endif
+ endfor
+ call assert_true(found_resize)
+
+ call delete('Xtest_mks1.out')
+ call delete('Xtest_mks2.out')
+ set sessionoptions&
+endfunc
+
+" Test for mksession with a named scratch buffer
+func Test_mksession_scratch()
+ set sessionoptions&vi
+ enew | only
+ file Xscratch
+ set buftype=nofile
+ mksession! Xtest_mks.out
+ %bwipe
+ source Xtest_mks.out
+ call assert_equal('Xscratch', bufname(''))
+ call assert_equal('nofile', &buftype)
+ %bwipe
+ call delete('Xtest_mks.out')
+ set sessionoptions&
+endfunc
+
+" Test for mksession with fold options
+func Test_mksession_foldopt()
+ set sessionoptions-=options
+ set sessionoptions+=folds
+ new
+ setlocal foldenable
+ setlocal foldmethod=expr
+ setlocal foldmarker=<<<,>>>
+ setlocal foldignore=%
+ setlocal foldlevel=2
+ setlocal foldminlines=10
+ setlocal foldnestmax=15
+ mksession! Xtest_mks.out
+ close
+ %bwipe
+
+ source Xtest_mks.out
+ call assert_true(&foldenable)
+ call assert_equal('expr', &foldmethod)
+ call assert_equal('<<<,>>>', &foldmarker)
+ call assert_equal('%', &foldignore)
+ call assert_equal(2, &foldlevel)
+ call assert_equal(10, &foldminlines)
+ call assert_equal(15, &foldnestmax)
+
+ close
+ %bwipe
+ set sessionoptions&
+endfunc
+
+" Test for mksession with window position
+func Test_mksession_winpos()
+ if !has('gui_running')
+ " Only applicable in GUI Vim
+ return
+ endif
+ set sessionoptions+=winpos
+ mksession! Xtest_mks.out
+ let found_winpos = v:false
+ let lines = readfile('Xtest_mks.out')
+ for line in lines
+ if line =~ '^winpos '
+ let found_winpos = v:true
+ break
+ endif
+ endfor
+ call assert_true(found_winpos)
+ call delete('Xtest_mks.out')
+ set sessionoptions&
+endfunc
+
+" Test for mksession with 'compatible' option
+func Test_mksession_compatible()
+ throw 'skipped: Nvim does not support "compatible" option'
+ mksession! Xtest_mks1.out
+ set compatible
+ mksession! Xtest_mks2.out
+ set nocp
+
+ let test_success = v:false
+ let lines = readfile('Xtest_mks1.out')
+ for line in lines
+ if line =~ '^if &cp | set nocp | endif'
+ let test_success = v:true
+ break
+ endif
+ endfor
+ call assert_true(test_success)
+
+ let test_success = v:false
+ let lines = readfile('Xtest_mks2.out')
+ for line in lines
+ if line =~ '^if !&cp | set cp | endif'
+ let test_success = v:true
+ break
endif
endfor
- call assert_equal(v:true, found_resize)
+ call assert_true(test_success)
call delete('Xtest_mks1.out')
call delete('Xtest_mks2.out')
+ set compatible&
set sessionoptions&
endfunc
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index ad6d325510..7a846e5ea0 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -222,6 +222,21 @@ func Test_normal05_formatexpr_setopt()
set formatexpr=
endfunc
+" When 'formatexpr' returns non-zero, internal formatting is used.
+func Test_normal_formatexpr_returns_nonzero()
+ new
+ call setline(1, ['one', 'two'])
+ func! Format()
+ return 1
+ endfunc
+ setlocal formatexpr=Format()
+ normal VGgq
+ call assert_equal(['one two'], getline(1, '$'))
+ setlocal formatexpr=
+ delfunc Format
+ close!
+endfunc
+
func Test_normal06_formatprg()
" basic test for formatprg
" only test on non windows platform
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 15c1836c9a..ccc5e6ffc9 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -348,6 +348,16 @@ func Test_set_values()
endif
endfunc
+func Test_renderoptions()
+ throw 'skipped: Nvim does not support renderoptions'
+ " Only do this for Windows Vista and later, fails on Windows XP and earlier.
+ " Doesn't hurt to do this on a non-Windows system.
+ if windowsversion() !~ '^[345]\.'
+ set renderoptions=type:directx
+ set rop=type:directx
+ endif
+endfunc
+
func ResetIndentexpr()
set indentexpr=
endfunc
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index e06c4f59da..48c0a83053 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -29,7 +29,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>cnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
command! -nargs=* Xexpr <mods>cexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
@@ -40,6 +40,8 @@ func s:setup_commands(cchar)
command! -nargs=0 -count Xcc <count>cc
command! -count=1 -nargs=0 Xbelow <mods><count>cbelow
command! -count=1 -nargs=0 Xabove <mods><count>cabove
+ command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
+ command! -count=1 -nargs=0 Xafter <mods><count>cafter
let g:Xgetlist = function('getqflist')
let g:Xsetlist = function('setqflist')
call setqflist([], 'f')
@@ -64,7 +66,7 @@ func s:setup_commands(cchar)
command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>lnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
command! -nargs=* Xexpr <mods>lexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
@@ -75,6 +77,8 @@ func s:setup_commands(cchar)
command! -nargs=0 -count Xcc <count>ll
command! -count=1 -nargs=0 Xbelow <mods><count>lbelow
command! -count=1 -nargs=0 Xabove <mods><count>labove
+ command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
+ command! -count=1 -nargs=0 Xafter <mods><count>lafter
let g:Xgetlist = function('getloclist', [0])
let g:Xsetlist = function('setloclist', [0])
call setloclist(0, [], 'f')
@@ -260,6 +264,9 @@ func XwindowTests(cchar)
\ winheight('.') == 7 &&
\ getline('.') ==# '|| non-error 1')
+ " :cnext in quickfix window should move to the next entry
+ Xnext
+ call assert_equal(2, g:Xgetlist({'idx' : 0}).idx)
" Calling cwindow should close the quickfix window with no valid errors
Xwindow
@@ -431,13 +438,19 @@ func Xtest_browse(cchar)
" result in failure
if a:cchar == 'c'
let err = 'E42:'
+ let cmd = '$cc'
else
let err = 'E776:'
+ let cmd = '$ll'
endif
call assert_fails('Xnext', err)
call assert_fails('Xprev', err)
call assert_fails('Xnfile', err)
call assert_fails('Xpfile', err)
+ call assert_fails(cmd, err)
+
+ Xexpr ''
+ call assert_fails(cmd, 'E42:')
call s:create_test_file('Xqftestfile1')
call s:create_test_file('Xqftestfile2')
@@ -1247,6 +1260,36 @@ func Test_efm2()
let &efm = save_efm
endfunc
+" Test for '%t' (error type) field in 'efm'
+func Test_efm_error_type()
+ let save_efm = &efm
+
+ " error type
+ set efm=%f:%l:%t:%m
+ cexpr ["Xfile1:10:E:msg1", "Xfile1:20:W:msg2", "Xfile1:30:I:msg3",
+ \ "Xfile1:40:N:msg4", "Xfile1:50:R:msg5"]
+ let output = split(execute('clist'), "\n")
+ call assert_equal([
+ \ ' 1 Xfile1:10 error: msg1',
+ \ ' 2 Xfile1:20 warning: msg2',
+ \ ' 3 Xfile1:30 info: msg3',
+ \ ' 4 Xfile1:40 note: msg4',
+ \ ' 5 Xfile1:50 R: msg5'], output)
+
+ " error type and a error number
+ set efm=%f:%l:%t:%n:%m
+ cexpr ["Xfile1:10:E:2:msg1", "Xfile1:20:W:4:msg2", "Xfile1:30:I:6:msg3",
+ \ "Xfile1:40:N:8:msg4", "Xfile1:50:R:3:msg5"]
+ let output = split(execute('clist'), "\n")
+ call assert_equal([
+ \ ' 1 Xfile1:10 error 2: msg1',
+ \ ' 2 Xfile1:20 warning 4: msg2',
+ \ ' 3 Xfile1:30 info 6: msg3',
+ \ ' 4 Xfile1:40 note 8: msg4',
+ \ ' 5 Xfile1:50 R 3: msg5'], output)
+ let &efm = save_efm
+endfunc
+
func XquickfixChangedByAutocmd(cchar)
call s:setup_commands(a:cchar)
if a:cchar == 'c'
@@ -1744,7 +1787,7 @@ func Test_switchbuf()
call assert_equal(1, bufwinnr('Xqftestfile3'))
" If only quickfix window is open in the current tabpage, jumping to an
- " entry with 'switchubf' set to 'usetab' should search in other tabpages.
+ " entry with 'switchbuf' set to 'usetab' should search in other tabpages.
enew | only
set switchbuf=usetab
tabedit Xqftestfile1
@@ -1810,14 +1853,27 @@ func s:test_xgrep(cchar)
enew! | only
set makeef&vim
silent Xgrep Grep_Test_Text: test_quickfix.vim
- call assert_true(len(g:Xgetlist()) == 3)
+ call assert_true(len(g:Xgetlist()) == 5)
Xopen
call assert_true(w:quickfix_title =~ '^:grep')
Xclose
enew
set makeef=Temp_File_##
silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
- call assert_true(len(g:Xgetlist()) == 6)
+
+ " Try with 'grepprg' set to 'internal'
+ set grepprg=internal
+ silent Xgrep Grep_Test_Text: test_quickfix.vim
+ silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
+ call assert_true(len(g:Xgetlist()) == 9)
+ set grepprg&vim
+
+ call writefile(['Vim'], 'XtestTempFile')
+ set makeef=XtestTempFile
+ silent Xgrep Grep_Test_Text: test_quickfix.vim
+ call assert_equal(5, len(g:Xgetlist()))
+ call assert_false(filereadable('XtestTempFile'))
+ set makeef&vim
endfunc
func Test_grep()
@@ -1914,9 +1970,23 @@ func HistoryTest(cchar)
call assert_equal(' error list 2 of 3; 2 ' . common, res[1])
call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
+ " Test for changing the quickfix lists
+ call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
+ exe '1' . a:cchar . 'hist'
+ call assert_equal(1, g:Xgetlist({'nr' : 0}).nr)
+ exe '3' . a:cchar . 'hist'
+ call assert_equal(3, g:Xgetlist({'nr' : 0}).nr)
+ call assert_fails('-2' . a:cchar . 'hist', 'E16:')
+ call assert_fails('4' . a:cchar . 'hist', 'E16:')
+
call g:Xsetlist([], 'f')
let l = split(execute(a:cchar . 'hist'), "\n")
call assert_equal('No entries', l[0])
+ if a:cchar == 'c'
+ call assert_fails('4chist', 'E16:')
+ else
+ call assert_fails('4lhist', 'E776:')
+ endif
" An empty list should still show the stack history
call g:Xsetlist([])
@@ -2365,14 +2435,28 @@ func Test_Autocmd()
silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
silent grep abc123def Xtest
silent grepadd abc123def Xtest
+ set grepprg=internal
+ silent grep Grep_Autocmd_Text test_quickfix.vim
+ silent grepadd GrepAdd_Autocmd_Text test_quickfix.vim
+ silent lgrep Grep_Autocmd_Text test_quickfix.vim
+ silent lgrepadd GrepAdd_Autocmd_Text test_quickfix.vim
+ set grepprg&vim
let l = ['pregrep',
- \ 'postgrep',
- \ 'pregrepadd',
- \ 'postgrepadd',
- \ 'pregrep',
- \ 'postgrep',
- \ 'pregrepadd',
- \ 'postgrepadd']
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'pregrep',
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'pregrep',
+ \ 'postgrep',
+ \ 'pregrepadd',
+ \ 'postgrepadd',
+ \ 'prelgrep',
+ \ 'postlgrep',
+ \ 'prelgrepadd',
+ \ 'postlgrepadd']
call assert_equal(l, g:acmds)
endif
@@ -2491,6 +2575,19 @@ func Test_cwindow_jump()
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
+ " Jumping to a file from the location list window should find a usuable
+ " window by wrapping around the window list.
+ enew | only
+ call setloclist(0, [], 'f')
+ new | new
+ lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
+ lopen
+ 1close
+ call assert_equal(0, getloclist(3, {'id' : 0}).id)
+ lnext
+ call assert_equal(3, winnr())
+ call assert_equal(getloclist(1, {'id' : 0}).id, getloclist(3, {'id' : 0}).id)
+
enew | only
set efm&vim
endfunc
@@ -3762,6 +3859,30 @@ func Test_qftitle()
call setqflist([], 'r', {'items' : [{'filename' : 'a.c', 'lnum' : 10}]})
call assert_equal('Errors', w:quickfix_title)
cclose
+
+ " Switching to another quickfix list in one tab page should update the
+ " quickfix window title and statusline in all the other tab pages also
+ call setqflist([], 'f')
+ %bw!
+ cgetexpr ['file_one:1:1: error in the first quickfix list']
+ call setqflist([], 'a', {'title': 'first quickfix list'})
+ cgetexpr ['file_two:2:1: error in the second quickfix list']
+ call setqflist([], 'a', {'title': 'second quickfix list'})
+ copen
+ wincmd t
+ tabnew two
+ copen
+ wincmd t
+ colder
+ call assert_equal('first quickfix list', gettabwinvar(1, 2, 'quickfix_title'))
+ call assert_equal('first quickfix list', gettabwinvar(2, 2, 'quickfix_title'))
+ call assert_equal(1, tabpagewinnr(1))
+ call assert_equal(1, tabpagewinnr(2))
+ tabnew
+ call setqflist([], 'a', {'title': 'new quickfix title'})
+ call assert_equal('new quickfix title', gettabwinvar(1, 2, 'quickfix_title'))
+ call assert_equal('new quickfix title', gettabwinvar(2, 2, 'quickfix_title'))
+ %bw!
endfunc
func Test_lbuffer_with_bwipe()
@@ -4177,17 +4298,22 @@ func Test_empty_qfbuf()
endfunc
" Test for the :cbelow, :cabove, :lbelow and :labove commands.
+" And for the :cafter, :cbefore, :lafter and :lbefore commands.
func Xtest_below(cchar)
call s:setup_commands(a:cchar)
" No quickfix/location list
call assert_fails('Xbelow', 'E42:')
call assert_fails('Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
" Empty quickfix/location list
call g:Xsetlist([])
call assert_fails('Xbelow', 'E42:')
call assert_fails('Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
call s:create_test_file('X1')
call s:create_test_file('X2')
@@ -4201,39 +4327,74 @@ func Xtest_below(cchar)
call assert_fails('Xabove', 'E42:')
call assert_fails('3Xbelow', 'E42:')
call assert_fails('4Xabove', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
+ call assert_fails('3Xbefore', 'E42:')
+ call assert_fails('4Xafter', 'E42:')
" Test the commands with various arguments
- Xexpr ["X1:5:L5", "X2:5:L5", "X2:10:L10", "X2:15:L15", "X3:3:L3"]
+ Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"]
edit +7 X2
Xabove
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
+ normal 7G
+ Xbefore
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xbefore', 'E553:')
+
normal 2j
Xbelow
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal 7G
+ Xafter
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
" Last error in this file
Xbelow 99
call assert_equal(['X2', 15], [bufname(''), line('.')])
call assert_fails('Xbelow', 'E553:')
+ normal gg
+ Xafter 99
+ call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xafter', 'E553:')
+
" First error in this file
Xabove 99
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
+ normal G
+ Xbefore 99
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+ call assert_fails('Xbefore', 'E553:')
+
normal gg
Xbelow 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal gg
+ Xafter 2
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
normal G
Xabove 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
+ normal G
+ Xbefore 2
+ call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')])
+
edit X4
call assert_fails('Xabove', 'E42:')
call assert_fails('Xbelow', 'E42:')
+ call assert_fails('Xbefore', 'E42:')
+ call assert_fails('Xafter', 'E42:')
if a:cchar == 'l'
" If a buffer has location list entries from some other window but not
" from the current window, then the commands should fail.
edit X1 | split | call setloclist(0, [], 'f')
call assert_fails('Xabove', 'E776:')
call assert_fails('Xbelow', 'E776:')
+ call assert_fails('Xbefore', 'E776:')
+ call assert_fails('Xafter', 'E776:')
close
endif
@@ -4244,31 +4405,52 @@ func Xtest_below(cchar)
edit +1 X2
Xbelow 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
+ normal 1G
+ Xafter 2
+ call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')])
+
normal gg
Xbelow 99
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
+ normal gg
+ Xafter 99
+ call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')])
+
normal G
Xabove 2
call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')])
normal G
+ Xbefore 2
+ call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
+
+ normal G
Xabove 99
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+ normal G
+ Xbefore 99
+ call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+
normal 10G
Xabove
call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')])
+ normal 10G$
+ 2Xbefore
+ call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')])
+
normal 10G
Xbelow
call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')])
+ normal 9G
+ 5Xafter
+ call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')])
" Invalid range
if a:cchar == 'c'
- call assert_fails('-2cbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0cabove
+ call assert_fails('-2cbelow', 'E16:')
+ call assert_fails('-2cafter', 'E16:')
else
- call assert_fails('-2lbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0labove
+ call assert_fails('-2lbelow', 'E16:')
+ call assert_fails('-2lafter', 'E16:')
endif
call delete('X1')
@@ -4282,6 +4464,42 @@ func Test_cbelow()
call Xtest_below('l')
endfunc
+func Test_quickfix_count()
+ let commands = [
+ \ 'cNext',
+ \ 'cNfile',
+ \ 'cabove',
+ \ 'cbelow',
+ \ 'cfirst',
+ \ 'clast',
+ \ 'cnewer',
+ \ 'cnext',
+ \ 'cnfile',
+ \ 'colder',
+ \ 'cprevious',
+ \ 'crewind',
+ \
+ \ 'lNext',
+ \ 'lNfile',
+ \ 'labove',
+ \ 'lbelow',
+ \ 'lfirst',
+ \ 'llast',
+ \ 'lnewer',
+ \ 'lnext',
+ \ 'lnfile',
+ \ 'lolder',
+ \ 'lprevious',
+ \ 'lrewind',
+ \ ]
+ for cmd in commands
+ call assert_fails('-1' .. cmd, 'E16:')
+ call assert_fails('.' .. cmd, 'E16:')
+ call assert_fails('%' .. cmd, 'E16:')
+ call assert_fails('$' .. cmd, 'E16:')
+ endfor
+endfunc
+
" Test for aborting quickfix commands using QuickFixCmdPre
func Xtest_qfcmd_abort(cchar)
call s:setup_commands(a:cchar)
@@ -4437,6 +4655,24 @@ func Test_cquit()
call assert_fails('-3cquit', 'E16:')
endfunc
+" Running :lhelpgrep command more than once in a help window, doesn't jump to
+" the help topic
+func Test_lhelpgrep_from_help_window()
+ call mkdir('Xtestdir/doc', 'p')
+ call writefile(['window'], 'Xtestdir/doc/a.txt')
+ call writefile(['buffer'], 'Xtestdir/doc/b.txt')
+ let save_rtp = &rtp
+ let &rtp = 'Xtestdir'
+ lhelpgrep window
+ lhelpgrep buffer
+ call assert_equal('b.txt', fnamemodify(@%, ":p:t"))
+ lhelpgrep window
+ call assert_equal('a.txt', fnamemodify(@%, ":p:t"))
+ let &rtp = save_rtp
+ call delete('Xtestdir', 'rf')
+ new | only!
+endfunc
+
" Test for adding an invalid entry with the quickfix window open and making
" sure that the window contents are not changed
func Test_add_invalid_entry_with_qf_window()
diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim
index 2ee0ee1c0c..1bb2ee53de 100644
--- a/src/nvim/testdir/test_regexp_latin.vim
+++ b/src/nvim/testdir/test_regexp_latin.vim
@@ -755,6 +755,13 @@ func Test_start_end_of_buffer_match()
bwipe!
endfunc
+func Test_ze_before_zs()
+ call assert_equal('', matchstr(' ', '\%#=1\ze \zs'))
+ call assert_equal('', matchstr(' ', '\%#=2\ze \zs'))
+ call assert_equal(repeat([''], 10), matchlist(' ', '\%#=1\ze \zs'))
+ call assert_equal(repeat([''], 10), matchlist(' ', '\%#=2\ze \zs'))
+endfunc
+
" Check for detecting error
func Test_regexp_error()
set regexpengine=2
diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim
index 4466ad436a..513780938e 100644
--- a/src/nvim/testdir/test_regexp_utf8.vim
+++ b/src/nvim/testdir/test_regexp_utf8.vim
@@ -533,4 +533,15 @@ func Test_search_with_end_offset()
close!
endfunc
+" Check that "^" matches even when the line starts with a combining char
+func Test_match_start_of_line_combining()
+ new
+ call setline(1, ['', "\u05ae", ''])
+ exe "normal gg/^\<CR>"
+ call assert_equal(2, getcurpos()[1])
+ bwipe!
+endfunc
+
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index 19a7c6c9d0..8d2a768ba0 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -2,6 +2,9 @@
" Tests for register operations
"
+source check.vim
+source view_util.vim
+
" This test must be executed first to check for empty and unset registers.
func Test_aaa_empty_reg_test()
call assert_fails('normal @@', 'E748:')
@@ -52,31 +55,44 @@ func Test_display_registers()
let b = execute('registers')
call assert_equal(a, b)
- call assert_match('^\n--- Registers ---\n'
- \ . '"" a\n'
- \ . '"0 ba\n'
- \ . '"1 b\n'
- \ . '"a b\n'
+ call assert_match('^\nType Name Content\n'
+ \ . ' c "" a\n'
+ \ . ' c "0 ba\n'
+ \ . ' c "1 b\n'
+ \ . ' c "a b\n'
\ . '.*'
- \ . '"- a\n'
+ \ . ' c "- a\n'
\ . '.*'
- \ . '": ls\n'
- \ . '"% file2\n'
- \ . '"# file1\n'
- \ . '"/ bar\n'
- \ . '"= 2\*4', a)
+ \ . ' c ": ls\n'
+ \ . ' c "% file2\n'
+ \ . ' c "# file1\n'
+ \ . ' c "/ bar\n'
+ \ . ' c "= 2\*4', a)
let a = execute('registers a')
- call assert_match('^\n--- Registers ---\n'
- \ . '"a b', a)
+ call assert_match('^\nType Name Content\n'
+ \ . ' c "a b', a)
let a = execute('registers :')
- call assert_match('^\n--- Registers ---\n'
- \ . '": ls', a)
+ call assert_match('^\nType Name Content\n'
+ \ . ' c ": ls', a)
bwipe!
endfunc
+func Test_recording_status_in_ex_line()
+ norm qx
+ redraw!
+ call assert_equal('recording @x', Screenline(&lines))
+ set shortmess=q
+ redraw!
+ call assert_equal('recording', Screenline(&lines))
+ set shortmess&
+ norm q
+ redraw!
+ call assert_equal('', Screenline(&lines))
+endfunc
+
" Check that replaying a typed sequence does not use an Esc and following
" characters as an escape sequence.
func Test_recording_esc_sequence()
@@ -254,4 +270,15 @@ func Test_ve_blockpaste()
bwipe!
endfunc
+func Test_insert_small_delete()
+ new
+ call setline(1, ['foo foobar bar'])
+ call cursor(1,1)
+ exe ":norm! ciw'\<C-R>-'"
+ call assert_equal("'foo' foobar bar", getline(1))
+ exe ":norm! w.w."
+ call assert_equal("'foo' 'foobar' 'bar'", getline(1))
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_ruby.vim b/src/nvim/testdir/test_ruby.vim
index 9c74c35049..1a274d1fec 100644
--- a/src/nvim/testdir/test_ruby.vim
+++ b/src/nvim/testdir/test_ruby.vim
@@ -27,6 +27,19 @@ func Test_rubydo()
%bwipe!
endfunc
+func Test_rubydo_dollar_underscore()
+ throw 'skipped: TODO: '
+ new
+ call setline(1, ['one', 'two', 'three', 'four'])
+ 2,3rubydo $_ = '[' + $_ + ']'
+ call assert_equal(['one', '[two]', '[three]', 'four'], getline(1, '$'))
+ bwipe!
+
+ call assert_fails('rubydo $_ = 0', 'E265:')
+ call assert_fails('rubydo (')
+ bwipe!
+endfunc
+
func Test_rubyfile()
" Check :rubyfile does not SEGV with Ruby level exception but just fails
let tempfile = tempname() . '.rb'
@@ -391,3 +404,14 @@ func Test_ruby_p()
let messages = GetMessages()
call assert_equal(0, len(messages))
endfunc
+
+func Test_rubyeval_error()
+ " On Linux or Windows the error matches:
+ " "syntax error, unexpected end-of-input"
+ " whereas on macOS in CI, the error message makes less sense:
+ " "SyntaxError: array length must be 2"
+ " Unclear why. The test does not check the error message.
+ call assert_fails('call rubyeval("(")')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim
index 6824c50112..0703a6b141 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -270,7 +270,7 @@ func Test_search_cmdline2()
" nor "/foo\<c-u>\<cr>" works to delete the commandline.
" In that case Vim should return "E35 no previous regular expression",
" but it looks like Vim still sees /foo and therefore the test fails.
- " Therefore, disableing this test
+ " Therefore, disabling this test
"call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35')
"call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview())
@@ -508,7 +508,7 @@ endfunc
func Test_search_cmdline7()
throw 'skipped: Nvim does not support test_override()'
- " Test that an pressing <c-g> in an empty command line
+ " Test that pressing <c-g> in an empty command line
" does not move the cursor
if !exists('+incsearch')
return
@@ -1172,3 +1172,24 @@ func Test_search_special()
set t_PE=
exe "norm /\x80PS"
endfunc
+
+" Test 'smartcase' with utf-8.
+func Test_search_smartcase_utf8()
+ new
+ let save_enc = &encoding
+ set encoding=utf8 ignorecase smartcase
+
+ call setline(1, 'Café cafÉ')
+ 1s/café/x/g
+ call assert_equal('x x', getline(1))
+
+ call setline(1, 'Café cafÉ')
+ 1s/cafÉ/x/g
+ call assert_equal('Café x', getline(1))
+
+ set ignorecase& smartcase&
+ let &encoding = save_enc
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_signals.vim b/src/nvim/testdir/test_signals.vim
new file mode 100644
index 0000000000..338c0d79ff
--- /dev/null
+++ b/src/nvim/testdir/test_signals.vim
@@ -0,0 +1,140 @@
+" Test signal handling.
+
+source check.vim
+source term_util.vim
+
+CheckUnix
+
+source shared.vim
+
+" Check whether a signal is available on this system.
+func HasSignal(signal)
+ let signals = system('kill -l')
+ return signals =~# '\<' .. a:signal .. '\>'
+endfunc
+
+" Test signal WINCH (window resize signal)
+func Test_signal_WINCH()
+ throw 'skipped: Nvim cannot avoid terminal resize'
+ if has('gui_running') || !HasSignal('WINCH')
+ return
+ endif
+
+ " We do not actually want to change the size of the terminal.
+ let old_WS = ''
+ if exists('&t_WS')
+ let old_WS = &t_WS
+ let &t_WS = ''
+ endif
+
+ let old_lines = &lines
+ let old_columns = &columns
+ let new_lines = &lines - 2
+ let new_columns = &columns - 2
+
+ exe 'set lines=' .. new_lines
+ exe 'set columns=' .. new_columns
+ call assert_equal(new_lines, &lines)
+ call assert_equal(new_columns, &columns)
+
+ " Send signal and wait for signal to be processed.
+ " 'lines' and 'columns' should have been restored
+ " after handing signal WINCH.
+ exe 'silent !kill -s WINCH ' .. getpid()
+ call WaitForAssert({-> assert_equal(old_lines, &lines)})
+ call assert_equal(old_columns, &columns)
+
+ if old_WS != ''
+ let &t_WS = old_WS
+ endif
+endfunc
+
+" Test signal PWR, which should update the swap file.
+func Test_signal_PWR()
+ if !HasSignal('PWR')
+ return
+ endif
+
+ " Set a very large 'updatetime' and 'updatecount', so that we can be sure
+ " that swap file is updated as a result of sending PWR signal, and not
+ " because of exceeding 'updatetime' or 'updatecount' when changing buffer.
+ set updatetime=100000 updatecount=100000
+ new Xtest_signal_PWR
+ let swap_name = swapname('%')
+ call setline(1, '123')
+ preserve
+ let swap_content = readfile(swap_name, 'b')
+
+ " Update the buffer and check that the swap file is not yet updated,
+ " since we set 'updatetime' and 'updatecount' to large values.
+ call setline(1, 'abc')
+ call assert_equal(swap_content, readfile(swap_name, 'b'))
+
+ " Sending PWR signal should update the swap file.
+ exe 'silent !kill -s PWR ' .. getpid()
+ call WaitForAssert({-> assert_notequal(swap_content, readfile(swap_name, 'b'))})
+
+ bwipe!
+ set updatetime& updatecount&
+endfunc
+
+" Test a deadly signal.
+"
+" There are several deadly signals: SISEGV, SIBUS, SIGTERM...
+" Test uses signal SIGTERM as it does not create a core
+" dump file unlike SIGSEGV, SIGBUS, etc. See "man 7 signals.
+"
+" Vim should exit with a deadly signal and unsaved changes
+" should be recoverable from the swap file preserved as a
+" result of the deadly signal handler.
+func Test_deadly_signal_TERM()
+ if !HasSignal('TERM')
+ throw 'Skipped: TERM signal not supported'
+ endif
+ if !CanRunVimInTerminal()
+ throw 'Skipped: cannot run vim in terminal'
+ endif
+ let cmd = GetVimCommand()
+ if cmd =~ 'valgrind'
+ throw 'Skipped: cannot test signal TERM with valgrind'
+ endif
+
+ " If test fails once, it can leave temporary files and trying to rerun
+ " the test would then fail again if they are not deleted first.
+ call delete('.Xsig_TERM.swp')
+ call delete('XsetupAucmd')
+ call delete('XautoOut')
+ let lines =<< trim END
+ au VimLeave * call writefile(["VimLeave triggered"], "XautoOut", "as")
+ au VimLeavePre * call writefile(["VimLeavePre triggered"], "XautoOut", "as")
+ END
+ call writefile(lines, 'XsetupAucmd')
+
+ let buf = RunVimInTerminal('-S XsetupAucmd Xsig_TERM', {'rows': 6})
+ let pid_vim = term_getjob(buf)->job_info().process
+
+ call term_sendkeys(buf, ":call setline(1, 'foo')\n")
+ call WaitForAssert({-> assert_equal('foo', term_getline(buf, 1))})
+
+ call assert_false(filereadable('Xsig_TERM'))
+ exe 'silent !kill -s TERM ' .. pid_vim
+ call WaitForAssert({-> assert_true(filereadable('.Xsig_TERM.swp'))})
+
+ " Don't call StopVimInTerminal() as it expects job to be still running.
+ call WaitForAssert({-> assert_equal("finished", term_getstatus(buf))})
+
+ new
+ silent recover .Xsig_TERM.swp
+ call assert_equal(['foo'], getline(1, '$'))
+
+ let result = readfile('XautoOut')
+ call assert_match('VimLeavePre triggered', result[0])
+ call assert_match('VimLeave triggered', result[1])
+
+ %bwipe!
+ call delete('.Xsig_TERM.swp')
+ call delete('XsetupAucmd')
+ call delete('XautoOut')
+endfunc
+
+" vim: ts=8 sw=2 sts=2 tw=80 fdm=marker
diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim
index 2b7672f1af..4bbd722fdb 100644
--- a/src/nvim/testdir/test_signs.vim
+++ b/src/nvim/testdir/test_signs.vim
@@ -15,14 +15,8 @@ func Test_sign()
" icon is ignored when not supported. "(not supported)" is shown after
" the icon name when listing signs.
sign define Sign1 text=x
- try
- sign define Sign2 text=xy texthl=Title linehl=Error
- \ icon=../../pixmaps/stock_vim_find_help.png
- catch /E255:/
- " Ignore error: E255: Couldn't read in sign data!
- " This error can happen when running in the GUI.
- " Some gui like Motif do not support the png icon format.
- endtry
+
+ call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png')
" Test listing signs.
let a=execute('sign list')
@@ -104,12 +98,7 @@ func Test_sign()
edit foo
call setline(1, ['A', 'B', 'C', 'D'])
- try
- sign define Sign3 text=y texthl=DoesNotExist linehl=DoesNotExist
- \ icon=doesnotexist.xpm
- catch /E255:/
- " ignore error: E255: it can happens for guis.
- endtry
+ call Sign_command_ignore_error('sign define Sign3 text=y texthl=DoesNotExist linehl=DoesNotExist icon=doesnotexist.xpm')
let fn = expand('%:p')
exe 'sign place 43 line=2 name=Sign3 file=' . fn
@@ -133,9 +122,9 @@ func Test_sign()
call assert_fails("sign define Sign4 text=a\e linehl=Comment", 'E239:')
call assert_fails("sign define Sign4 text=\ea linehl=Comment", 'E239:')
- " Only 1 or 2 character text is allowed
+ " Only 0, 1 or 2 character text is allowed
call assert_fails("sign define Sign4 text=abc linehl=Comment", 'E239:')
- call assert_fails("sign define Sign4 text= linehl=Comment", 'E239:')
+ " call assert_fails("sign define Sign4 text= linehl=Comment", 'E239:')
call assert_fails("sign define Sign4 text=\\ ab linehl=Comment", 'E239:')
" define sign with whitespace
@@ -317,7 +306,7 @@ func Test_sign_invalid_commands()
call assert_fails('sign jump 1 name=', 'E474:')
call assert_fails('sign jump 1 name=Sign1', 'E474:')
call assert_fails('sign jump 1 line=100', '474:')
- call assert_fails('sign define Sign2 text=', 'E239:')
+ " call assert_fails('sign define Sign2 text=', 'E239:')
" Non-numeric identifier for :sign place
call assert_fails("sign place abc line=3 name=Sign1 buffer=" . bufnr(''),
\ 'E474:')
@@ -378,6 +367,25 @@ func Test_sign_delete_buffer()
sign undefine Sign
endfunc
+" Ignore error: E255: Couldn't read in sign data!
+" This error can happen when running in the GUI.
+" Some gui like Motif do not support the png icon format.
+func Sign_command_ignore_error(cmd)
+ try
+ exe a:cmd
+ catch /E255:/
+ endtry
+endfunc
+
+" ignore error: E255: Couldn't read in sign data!
+" This error can happen when running in gui.
+func Sign_define_ignore_error(name, attr)
+ try
+ call sign_define(a:name, a:attr)
+ catch /E255:/
+ endtry
+endfunc
+
" Test for Vim script functions for managing signs
func Test_sign_funcs()
" Remove all the signs
@@ -394,12 +402,7 @@ func Test_sign_funcs()
call sign_define("sign2")
let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
\ 'icon' : 'sign2.ico'}
- try
- call sign_define("sign2", attr)
- catch /E255:/
- " ignore error: E255: Couldn't read in sign data!
- " This error can happen when running in gui.
- endtry
+ call Sign_define_ignore_error("sign2", attr)
call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
\ 'linehl' : 'DiffAdd', 'text' : '!!', 'icon' : 'sign2.ico'}],
\ sign_getdefined("sign2"))
@@ -412,7 +415,7 @@ func Test_sign_funcs()
" Tests for invalid arguments to sign_define()
call assert_fails('call sign_define("sign4", {"text" : "===>"})', 'E239:')
- call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:')
+ " call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:')
call assert_fails('call sign_define([])', 'E730:')
call assert_fails('call sign_define("sign6", [])', 'E715:')
@@ -508,6 +511,16 @@ func Test_sign_funcs()
call assert_fails('call sign_undefine("none")', 'E155:')
call assert_fails('call sign_undefine([])', 'E730:')
+ " Test for using '.' as the line number for sign_place()
+ call Sign_define_ignore_error("sign1", attr)
+ call cursor(22, 1)
+ call assert_equal(15, sign_place(15, '', 'sign1', 'Xsign',
+ \ {'lnum' : '.'}))
+ call assert_equal([{'bufnr' : bufnr(''), 'signs' :
+ \ [{'id' : 15, 'group' : '', 'lnum' : 22, 'name' : 'sign1',
+ \ 'priority' : 10}]}],
+ \ sign_getplaced('%', {'lnum' : 22}))
+
call delete("Xsign")
call sign_unplace('*')
call sign_undefine()
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 6214975ef5..e7f332bc4c 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -686,3 +686,53 @@ func Test_v_argv()
call assert_true(idx > 2)
call assert_equal(['arg1', '--cmd', 'echo v:argv', '--cmd', 'q'']'], list[idx:])
endfunc
+
+" Test the '-T' argument which sets the 'term' option.
+func Test_T_arg()
+ throw 'skipped: Nvim does not support "-T" argument'
+ CheckNotGui
+ let after =<< trim [CODE]
+ call writefile([&term], "Xtest_T_arg")
+ qall
+ [CODE]
+
+ for t in ['builtin_dumb', 'builtin_ansi']
+ if RunVim([], after, '-T ' .. t)
+ let lines = readfile('Xtest_T_arg')
+ call assert_equal([t], lines)
+ endif
+ endfor
+
+ call delete('Xtest_T_arg')
+endfunc
+
+" Test the '-x' argument to read/write encrypted files.
+func Test_x_arg()
+ CheckRunVimInTerminal
+ CheckFeature cryptv
+
+ " Create an encrypted file Xtest_x_arg.
+ let buf = RunVimInTerminal('-n -x Xtest_x_arg', #{rows: 10, wait_for_ruler: 0})
+ call WaitForAssert({-> assert_match('^Enter encryption key: ', term_getline(buf, 10))})
+ call term_sendkeys(buf, "foo\n")
+ call WaitForAssert({-> assert_match('^Enter same key again: ', term_getline(buf, 10))})
+ call term_sendkeys(buf, "foo\n")
+ call WaitForAssert({-> assert_match(' All$', term_getline(buf, 10))})
+ call term_sendkeys(buf, "itest\<Esc>:w\<Enter>")
+ call WaitForAssert({-> assert_match('"Xtest_x_arg" \[New\]\[blowfish2\] 1L, 5B written',
+ \ term_getline(buf, 10))})
+ call StopVimInTerminal(buf)
+
+ " Read the encrypted file and check that it contains the expected content "test"
+ let buf = RunVimInTerminal('-n -x Xtest_x_arg', #{rows: 10, wait_for_ruler: 0})
+ call WaitForAssert({-> assert_match('^Enter encryption key: ', term_getline(buf, 10))})
+ call term_sendkeys(buf, "foo\n")
+ call WaitForAssert({-> assert_match('^Enter same key again: ', term_getline(buf, 10))})
+ call term_sendkeys(buf, "foo\n")
+ call WaitForAssert({-> assert_match('^test', term_getline(buf, 1))})
+ call StopVimInTerminal(buf)
+
+ call delete('Xtest_x_arg')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim
index 424cb4abd0..9cf8690d57 100644
--- a/src/nvim/testdir/test_system.vim
+++ b/src/nvim/testdir/test_system.vim
@@ -3,7 +3,7 @@
source shared.vim
source check.vim
-function! Test_System()
+func Test_System()
if !executable('echo') || !executable('cat') || !executable('wc')
return
endif
diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim
index 55dff3d476..2b6a89647e 100644
--- a/src/nvim/testdir/test_tabpage.vim
+++ b/src/nvim/testdir/test_tabpage.vim
@@ -1,6 +1,7 @@
" Tests for tabpage
source screendump.vim
+source check.vim
function Test_tabpage()
bw!
@@ -58,7 +59,7 @@ function Test_tabpage()
q
"
"
- " Test for ":tab drop multi-opend-file" to keep current tabpage and window.
+ " Test for ":tab drop multi-opened-file" to keep current tabpage and window.
new test1
tabnew
new test1
@@ -222,6 +223,34 @@ function Test_tabpage_with_autocmd()
1tabonly!
endfunction
+" Test autocommands on tab drop
+function Test_tabpage_with_autocmd_tab_drop()
+ augroup TestTabpageGroup
+ au!
+ autocmd TabEnter * call add(s:li, 'TabEnter')
+ autocmd WinEnter * call add(s:li, 'WinEnter')
+ autocmd BufEnter * call add(s:li, 'BufEnter')
+ autocmd TabLeave * call add(s:li, 'TabLeave')
+ autocmd WinLeave * call add(s:li, 'WinLeave')
+ autocmd BufLeave * call add(s:li, 'BufLeave')
+ augroup END
+
+ let s:li = []
+ tab drop test1
+ call assert_equal(['BufLeave', 'BufEnter'], s:li)
+
+ let s:li = []
+ tab drop test2 test3
+ call assert_equal([
+ \ 'TabLeave', 'TabEnter', 'TabLeave', 'TabEnter',
+ \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter',
+ \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter'], s:li)
+
+ autocmd! TestTabpageGroup
+ augroup! TestTabpageGroup
+ 1tabonly!
+endfunction
+
function Test_tabpage_with_tab_modifier()
for n in range(4)
tabedit
@@ -579,4 +608,82 @@ func Test_tabpage_cmdheight()
call delete('XTest_tabpage_cmdheight')
endfunc
+" Return the terminal key code for selecting a tab page from the tabline. This
+" sequence contains the following codes: a CSI (0x9b), KS_TABLINE (0xf0),
+" KS_FILLER (0x58) and then the tab page number.
+func TabLineSelectPageCode(tabnr)
+ return "\x9b\xf0\x58" .. nr2char(a:tabnr)
+endfunc
+
+" Return the terminal key code for opening a new tabpage from the tabpage
+" menu. This sequence consists of the following codes: a CSI (0x9b),
+" KS_TABMENU (0xef), KS_FILLER (0x58), the tab page number and
+" TABLINE_MENU_NEW (2).
+func TabMenuNewItemCode(tabnr)
+ return "\x9b\xef\x58" .. nr2char(a:tabnr) .. nr2char(2)
+endfunc
+
+" Return the terminal key code for closing a tabpage from the tabpage menu.
+" This sequence consists of the following codes: a CSI (0x9b), KS_TABMENU
+" (0xef), KS_FILLER (0x58), the tab page number and TABLINE_MENU_CLOSE (1).
+func TabMenuCloseItemCode(tabnr)
+ return "\x9b\xef\x58" .. nr2char(a:tabnr) .. nr2char(1)
+endfunc
+
+" Test for using the tabpage menu from the insert and normal modes
+func Test_tabline_tabmenu()
+ " only works in GUI
+ CheckGui
+
+ %bw!
+ tabnew
+ tabnew
+ call assert_equal(3, tabpagenr())
+
+ " go to tab page 2 in normal mode
+ call feedkeys(TabLineSelectPageCode(2), "Lx!")
+ call assert_equal(2, tabpagenr())
+
+ " close tab page 3 in normal mode
+ call feedkeys(TabMenuCloseItemCode(3), "Lx!")
+ call assert_equal(2, tabpagenr('$'))
+ call assert_equal(2, tabpagenr())
+
+ " open new tab page before tab page 1 in normal mode
+ call feedkeys(TabMenuNewItemCode(1), "Lx!")
+ call assert_equal(1, tabpagenr())
+ call assert_equal(3, tabpagenr('$'))
+
+ " go to tab page 2 in operator-pending mode (should beep)
+ call assert_beeps('call feedkeys("f" .. TabLineSelectPageCode(2), "Lx!")')
+
+ " open new tab page before tab page 1 in operator-pending mode (should beep)
+ call assert_beeps('call feedkeys("f" .. TabMenuNewItemCode(1), "Lx!")')
+
+ " open new tab page after tab page 3 in normal mode
+ call feedkeys(TabMenuNewItemCode(4), "Lx!")
+ call assert_equal(4, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+
+ " go to tab page 2 in insert mode
+ call feedkeys("i" .. TabLineSelectPageCode(2) .. "\<C-C>", "Lx!")
+ call assert_equal(2, tabpagenr())
+
+ " close tab page 2 in insert mode
+ call feedkeys("i" .. TabMenuCloseItemCode(2) .. "\<C-C>", "Lx!")
+ call assert_equal(3, tabpagenr('$'))
+
+ " open new tab page before tab page 3 in insert mode
+ call feedkeys("i" .. TabMenuNewItemCode(3) .. "\<C-C>", "Lx!")
+ call assert_equal(3, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+
+ " open new tab page after tab page 4 in insert mode
+ call feedkeys("i" .. TabMenuNewItemCode(5) .. "\<C-C>", "Lx!")
+ call assert_equal(5, tabpagenr())
+ call assert_equal(5, tabpagenr('$'))
+
+ %bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_textformat.vim b/src/nvim/testdir/test_textformat.vim
index 2223be952c..4af52b536c 100644
--- a/src/nvim/testdir/test_textformat.vim
+++ b/src/nvim/testdir/test_textformat.vim
@@ -424,6 +424,15 @@ func Test_format_align()
\ ], getline(1, '$'))
enew!
+ " align text with 'wrapmargin'
+ 50vnew
+ call setline(1, ['Vim'])
+ setl textwidth=0
+ setl wrapmargin=30
+ right
+ call assert_equal("\t\t Vim", getline(1))
+ q!
+
set tw&
endfunc
@@ -931,4 +940,217 @@ func Test_substitute()
call assert_equal('a1a2a3a', substitute('123', '\zs', 'a', 'g'))
endfunc
+" Test for 'a' and 'w' flags in 'formatoptions'
+func Test_fo_a_w()
+ new
+ setlocal fo+=aw tw=10
+ call feedkeys("iabc abc a abc\<Esc>k0weade", 'xt')
+ call assert_equal(['abc abcde ', 'a abc'], getline(1, '$'))
+
+ " Test for 'a', 'w' and '1' options.
+ setlocal textwidth=0
+ setlocal fo=1aw
+ %d
+ call setline(1, '. foo')
+ normal 72ig
+ call feedkeys('a uu uu uu', 'xt')
+ call assert_equal('g uu uu ', getline(1)[-8:])
+ call assert_equal(['uu. foo'], getline(2, '$'))
+
+ " using backspace or "x" triggers reformat
+ call setline(1, ['1 2 3 4 5 ', '6 7 8 9'])
+ set tw=10
+ set fo=taw
+ set bs=indent,eol,start
+ exe "normal 1G4la\<BS>\<BS>\<Esc>"
+ call assert_equal(['1 2 4 5 6 ', '7 8 9'], getline(1, 2))
+ exe "normal f4xx"
+ call assert_equal(['1 2 5 6 7 ', '8 9'], getline(1, 2))
+
+ set tw=0
+ set fo&
+ %bw!
+endfunc
+
+" Test for formatting lines using gq in visual mode
+func Test_visual_gq_format()
+ new
+ call setline(1, ['one two three four', 'five six', 'one two'])
+ setl textwidth=10
+ call feedkeys('ggv$jj', 'xt')
+ redraw!
+ normal gq
+ %d
+ call setline(1, ['one two three four', 'five six', 'one two'])
+ normal G$
+ call feedkeys('v0kk', 'xt')
+ redraw!
+ normal gq
+ setl textwidth&
+ close!
+endfunc
+
+" Test for 'n' flag in 'formatoptions' to format numbered lists
+func Test_fo_n()
+ new
+ setlocal autoindent
+ setlocal textwidth=12
+ setlocal fo=n
+ call setline(1, [' 1) one two three four', ' 2) two'])
+ normal gggqG
+ call assert_equal([' 1) one two', ' three', ' four', ' 2) two'],
+ \ getline(1, '$'))
+ close!
+endfunc
+
+" Test for 'formatlistpat' option
+func Test_formatlistpat()
+ new
+ setlocal autoindent
+ setlocal textwidth=10
+ setlocal fo=n
+ setlocal formatlistpat=^\\s*-\\s*
+ call setline(1, [' - one two three', ' - two'])
+ normal gggqG
+ call assert_equal([' - one', ' two', ' three', ' - two'],
+ \ getline(1, '$'))
+ close!
+endfunc
+
+" Test for the 'b' and 'v' flags in 'formatoptions'
+" Text should wrap only if a space character is inserted at or before
+" 'textwidth'
+func Test_fo_b()
+ new
+ setlocal textwidth=20
+
+ setlocal formatoptions=t
+ call setline(1, 'one two three four')
+ call feedkeys('Amore', 'xt')
+ call assert_equal(['one two three', 'fourmore'], getline(1, '$'))
+
+ setlocal formatoptions=bt
+ %d
+ call setline(1, 'one two three four')
+ call feedkeys('Amore five', 'xt')
+ call assert_equal(['one two three fourmore five'], getline(1, '$'))
+
+ setlocal formatoptions=bt
+ %d
+ call setline(1, 'one two three four')
+ call feedkeys('A five', 'xt')
+ call assert_equal(['one two three four', 'five'], getline(1, '$'))
+
+ setlocal formatoptions=vt
+ %d
+ call setline(1, 'one two three four')
+ call feedkeys('Amore five', 'xt')
+ call assert_equal(['one two three fourmore', 'five'], getline(1, '$'))
+
+ close!
+endfunc
+
+" Test for the '1' flag in 'formatoptions'. Don't wrap text after a one letter
+" word.
+func Test_fo_1()
+ new
+ setlocal textwidth=20
+
+ setlocal formatoptions=t
+ call setline(1, 'one two three four')
+ call feedkeys('A a bird', 'xt')
+ call assert_equal(['one two three four a', 'bird'], getline(1, '$'))
+
+ %d
+ setlocal formatoptions=t1
+ call setline(1, 'one two three four')
+ call feedkeys('A a bird', 'xt')
+ call assert_equal(['one two three four', 'a bird'], getline(1, '$'))
+
+ close!
+endfunc
+
+" Test for 'l' flag in 'formatoptions'. When starting insert mode, if a line
+" is longer than 'textwidth', then it is not broken.
+func Test_fo_l()
+ new
+ setlocal textwidth=20
+
+ setlocal formatoptions=t
+ call setline(1, 'one two three four five')
+ call feedkeys('A six', 'xt')
+ call assert_equal(['one two three four', 'five six'], getline(1, '$'))
+
+ %d
+ setlocal formatoptions=tl
+ call setline(1, 'one two three four five')
+ call feedkeys('A six', 'xt')
+ call assert_equal(['one two three four five six'], getline(1, '$'))
+
+ close!
+endfunc
+
+" Test for the '2' flag in 'formatoptions'
+func Test_fo_2()
+ new
+ setlocal autoindent
+ setlocal formatoptions=t2
+ setlocal textwidth=30
+ call setline(1, ["\tfirst line of a paragraph.",
+ \ "second line of the same paragraph.",
+ \ "third line."])
+ normal gggqG
+ call assert_equal(["\tfirst line of a",
+ \ "paragraph. second line of the",
+ \ "same paragraph. third line."], getline(1, '$'))
+ close!
+endfunc
+
+" Test for formatting lines where only the first line has a comment.
+func Test_fo_gq_with_firstline_comment()
+ new
+ setlocal formatoptions=tcq
+ call setline(1, ['- one two', 'three'])
+ normal gggqG
+ call assert_equal(['- one two three'], getline(1, '$'))
+
+ %d
+ call setline(1, ['- one', '- two'])
+ normal gggqG
+ call assert_equal(['- one', '- two'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for trying to join a comment line with a non-comment line
+func Test_join_comments()
+ new
+ call setline(1, ['one', '/* two */', 'three'])
+ normal gggqG
+ call assert_equal(['one', '/* two */', 'three'], getline(1, '$'))
+ close!
+endfunc
+
+" Test for using 'a' in 'formatoptions' with comments
+func Test_autoformat_comments()
+ new
+ setlocal formatoptions+=a
+ call feedkeys("a- one\n- two\n", 'xt')
+ call assert_equal(['- one', '- two', ''], getline(1, '$'))
+
+ %d
+ call feedkeys("a\none\n", 'xt')
+ call assert_equal(['', 'one', ''], getline(1, '$'))
+
+ setlocal formatoptions+=aw
+ %d
+ call feedkeys("aone \ntwo\n", 'xt')
+ call assert_equal(['one two', ''], getline(1, '$'))
+
+ %d
+ call feedkeys("aone\ntwo\n", 'xt')
+ call assert_equal(['one', 'two', ''], getline(1, '$'))
+
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_trycatch.vim b/src/nvim/testdir/test_trycatch.vim
new file mode 100644
index 0000000000..7e513180a3
--- /dev/null
+++ b/src/nvim/testdir/test_trycatch.vim
@@ -0,0 +1,1977 @@
+" Test try-catch-finally exception handling
+" Most of this was formerly in test49.
+
+source check.vim
+source shared.vim
+
+"-------------------------------------------------------------------------------
+" Test environment {{{1
+"-------------------------------------------------------------------------------
+
+com! XpathINIT let g:Xpath = ''
+com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args>
+
+" Test 25: Executing :finally clauses on normal control flow {{{1
+"
+" Control flow in a :try conditional should always fall through to its
+" :finally clause. A :finally clause of a :try conditional inside an
+" inactive conditional should never be executed.
+"-------------------------------------------------------------------------------
+
+func T25_F()
+ let loops = 3
+ while loops > 0
+ Xpath 'a' . loops
+ if loops >= 2
+ try
+ Xpath 'b' . loops
+ if loops == 2
+ try
+ Xpath 'c' . loops
+ finally
+ Xpath 'd' . loops
+ endtry
+ endif
+ finally
+ Xpath 'e' . loops
+ if loops == 2
+ try
+ Xpath 'f' . loops
+ finally
+ Xpath 'g' . loops
+ endtry
+ endif
+ endtry
+ endif
+ Xpath 'h' . loops
+ let loops = loops - 1
+ endwhile
+ Xpath 'i'
+endfunc
+
+func T25_G()
+ if 1
+ try
+ Xpath 'A'
+ call T25_F()
+ Xpath 'B'
+ finally
+ Xpath 'C'
+ endtry
+ else
+ try
+ Xpath 'D'
+ finally
+ Xpath 'E'
+ endtry
+ endif
+endfunc
+
+func Test_finally()
+ XpathINIT
+ call T25_G()
+ call assert_equal('Aa3b3e3h3a2b2c2d2e2f2g2h2a1h1iBC', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 26: Executing :finally clauses after :continue or :break {{{1
+"
+" For a :continue or :break dynamically enclosed in a :try/:endtry
+" region inside the next surrounding :while/:endwhile, if the
+" :continue/:break is before the :finally, the :finally clause is
+" executed first. If the :continue/:break is after the :finally, the
+" :finally clause is broken (like an :if/:endif region).
+"-------------------------------------------------------------------------------
+
+func T26_F()
+ try
+ let loops = 3
+ while loops > 0
+ try
+ try
+ if loops == 2
+ Xpath 'a' . loops
+ let loops = loops - 1
+ continue
+ elseif loops == 1
+ Xpath 'b' . loops
+ break
+ finish
+ endif
+ Xpath 'c' . loops
+ endtry
+ finally
+ Xpath 'd' . loops
+ endtry
+ Xpath 'e' . loops
+ let loops = loops - 1
+ endwhile
+ Xpath 'f'
+ finally
+ Xpath 'g'
+ let loops = 3
+ while loops > 0
+ try
+ finally
+ try
+ if loops == 2
+ Xpath 'h' . loops
+ let loops = loops - 1
+ continue
+ elseif loops == 1
+ Xpath 'i' . loops
+ break
+ finish
+ endif
+ endtry
+ Xpath 'j' . loops
+ endtry
+ Xpath 'k' . loops
+ let loops = loops - 1
+ endwhile
+ Xpath 'l'
+ endtry
+ Xpath 'm'
+endfunc
+
+func Test_finally_after_continue()
+ XpathINIT
+ call T26_F()
+ call assert_equal('c3d3e3a2d1b1d1fgj3k3h2i1lm', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 32: Remembering the :return value on :finally {{{1
+"
+" If a :finally clause is executed due to a :return specifying
+" a value, this is the value visible to the caller if not overwritten
+" by a new :return in the :finally clause. A :return without a value
+" in the :finally clause overwrites with value 0.
+"-------------------------------------------------------------------------------
+
+func T32_F()
+ try
+ Xpath 'a'
+ try
+ Xpath 'b'
+ return "ABCD"
+ Xpath 'c'
+ finally
+ Xpath 'd'
+ endtry
+ Xpath 'e'
+ finally
+ Xpath 'f'
+ endtry
+ Xpath 'g'
+endfunc
+
+func T32_G()
+ try
+ Xpath 'h'
+ return 8
+ Xpath 'i'
+ finally
+ Xpath 'j'
+ return 16 + strlen(T32_F())
+ Xpath 'k'
+ endtry
+ Xpath 'l'
+endfunc
+
+func T32_H()
+ try
+ Xpath 'm'
+ return 32
+ Xpath 'n'
+ finally
+ Xpath 'o'
+ return
+ Xpath 'p'
+ endtry
+ Xpath 'q'
+endfunc
+
+func T32_I()
+ try
+ Xpath 'r'
+ finally
+ Xpath 's'
+ return T32_G() + T32_H() + 64
+ Xpath 't'
+ endtry
+ Xpath 'u'
+endfunc
+
+func Test_finally_return()
+ XpathINIT
+ call assert_equal(84, T32_I())
+ call assert_equal('rshjabdfmo', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 33: :return under :execute or user command and :finally {{{1
+"
+" A :return command may be executed under an ":execute" or from
+" a user command. Executing of :finally clauses and passing through
+" the return code works also then.
+"-------------------------------------------------------------------------------
+
+func T33_F()
+ try
+ RETURN 10
+ Xpath 'a'
+ finally
+ Xpath 'b'
+ endtry
+ Xpath 'c'
+endfunc
+
+func T33_G()
+ try
+ RETURN 20
+ Xpath 'd'
+ finally
+ Xpath 'e'
+ RETURN 30
+ Xpath 'f'
+ endtry
+ Xpath 'g'
+endfunc
+
+func T33_H()
+ try
+ execute "try | return 40 | finally | return 50 | endtry"
+ Xpath 'h'
+ finally
+ Xpath 'i'
+ endtry
+ Xpath 'j'
+endfunc
+
+func T33_I()
+ try
+ execute "try | return 60 | finally | return 70 | endtry"
+ Xpath 'k'
+ finally
+ Xpath 'l'
+ execute "try | return 80 | finally | return 90 | endtry"
+ Xpath 'm'
+ endtry
+ Xpath 'n'
+endfunc
+
+func T33_J()
+ try
+ RETURN 100
+ Xpath 'o'
+ finally
+ Xpath 'p'
+ return
+ Xpath 'q'
+ endtry
+ Xpath 'r'
+endfunc
+
+func T33_K()
+ try
+ execute "try | return 110 | finally | return 120 | endtry"
+ Xpath 's'
+ finally
+ Xpath 't'
+ execute "try | return 130 | finally | return | endtry"
+ Xpath 'u'
+ endtry
+ Xpath 'v'
+endfunc
+
+func T33_L()
+ try
+ return
+ Xpath 'w'
+ finally
+ Xpath 'x'
+ RETURN 140
+ Xpath 'y'
+ endtry
+ Xpath 'z'
+endfunc
+
+func T33_M()
+ try
+ return
+ Xpath 'A'
+ finally
+ Xpath 'B'
+ execute "try | return 150 | finally | return 160 | endtry"
+ Xpath 'C'
+ endtry
+ Xpath 'D'
+endfunc
+
+func T33_N()
+ RETURN 170
+endfunc
+
+func T33_O()
+ execute "try | return 180 | finally | return 190 | endtry"
+endfunc
+
+func Test_finally_cmd_return()
+ command! -nargs=? RETURN
+ \ try | return <args> | finally | return <args> * 2 | endtry
+ XpathINIT
+ call assert_equal(20, T33_F())
+ call assert_equal(60, T33_G())
+ call assert_equal(50, T33_H())
+ call assert_equal(90, T33_I())
+ call assert_equal(0, T33_J())
+ call assert_equal(0, T33_K())
+ call assert_equal(280, T33_L())
+ call assert_equal(160, T33_M())
+ call assert_equal(340, T33_N())
+ call assert_equal(190, T33_O())
+ call assert_equal('beilptxB', g:Xpath)
+ delcommand RETURN
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 41: Skipped :throw finding next command {{{1
+"
+" A :throw in an inactive conditional must not hide a following
+" command.
+"-------------------------------------------------------------------------------
+
+func T41_F()
+ Xpath 'a'
+ if 0 | throw 'never' | endif | Xpath 'b'
+ Xpath 'c'
+endfunc
+
+func T41_G()
+ Xpath 'd'
+ while 0 | throw 'never' | endwhile | Xpath 'e'
+ Xpath 'f'
+endfunc
+
+func T41_H()
+ Xpath 'g'
+ if 0 | try | throw 'never' | endtry | endif | Xpath 'h'
+ Xpath 'i'
+endfunc
+
+func Test_throw_inactive_cond()
+ XpathINIT
+ try
+ Xpath 'j'
+ call T41_F()
+ Xpath 'k'
+ catch /.*/
+ Xpath 'l'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'm'
+ call T41_G()
+ Xpath 'n'
+ catch /.*/
+ Xpath 'o'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'p'
+ call T41_H()
+ Xpath 'q'
+ catch /.*/
+ Xpath 'r'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('jabckmdefnpghiq', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 42: Catching number and string exceptions {{{1
+"
+" When a number is thrown, it is converted to a string exception.
+" Numbers and strings may be caught by specifying a regular exception
+" as argument to the :catch command.
+"-------------------------------------------------------------------------------
+
+
+func T42_F()
+ try
+
+ try
+ Xpath 'a'
+ throw 4711
+ Xpath 'b'
+ catch /4711/
+ Xpath 'c'
+ endtry
+
+ try
+ Xpath 'd'
+ throw 4711
+ Xpath 'e'
+ catch /^4711$/
+ Xpath 'f'
+ endtry
+
+ try
+ Xpath 'g'
+ throw 4711
+ Xpath 'h'
+ catch /\d/
+ Xpath 'i'
+ endtry
+
+ try
+ Xpath 'j'
+ throw 4711
+ Xpath 'k'
+ catch /^\d\+$/
+ Xpath 'l'
+ endtry
+
+ try
+ Xpath 'm'
+ throw "arrgh"
+ Xpath 'n'
+ catch /arrgh/
+ Xpath 'o'
+ endtry
+
+ try
+ Xpath 'p'
+ throw "arrgh"
+ Xpath 'q'
+ catch /^arrgh$/
+ Xpath 'r'
+ endtry
+
+ try
+ Xpath 's'
+ throw "arrgh"
+ Xpath 't'
+ catch /\l/
+ Xpath 'u'
+ endtry
+
+ try
+ Xpath 'v'
+ throw "arrgh"
+ Xpath 'w'
+ catch /^\l\+$/
+ Xpath 'x'
+ endtry
+
+ try
+ try
+ Xpath 'y'
+ throw "ARRGH"
+ Xpath 'z'
+ catch /^arrgh$/
+ Xpath 'A'
+ endtry
+ catch /^\carrgh$/
+ Xpath 'B'
+ endtry
+
+ try
+ Xpath 'C'
+ throw ""
+ Xpath 'D'
+ catch /^$/
+ Xpath 'E'
+ endtry
+
+ catch /.*/
+ Xpath 'F'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+endfunc
+
+func Test_catch_number_string()
+ XpathINIT
+ call T42_F()
+ call assert_equal('acdfgijlmoprsuvxyBCE', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 43: Selecting the correct :catch clause {{{1
+"
+" When an exception is thrown and there are multiple :catch clauses,
+" the first matching one is taken.
+"-------------------------------------------------------------------------------
+
+func T43_F()
+ let loops = 3
+ while loops > 0
+ try
+ if loops == 3
+ Xpath 'a' . loops
+ throw "a"
+ Xpath 'b' . loops
+ elseif loops == 2
+ Xpath 'c' . loops
+ throw "ab"
+ Xpath 'd' . loops
+ elseif loops == 1
+ Xpath 'e' . loops
+ throw "abc"
+ Xpath 'f' . loops
+ endif
+ catch /abc/
+ Xpath 'g' . loops
+ catch /ab/
+ Xpath 'h' . loops
+ catch /.*/
+ Xpath 'i' . loops
+ catch /a/
+ Xpath 'j' . loops
+ endtry
+
+ let loops = loops - 1
+ endwhile
+ Xpath 'k'
+endfunc
+
+func Test_multi_catch()
+ XpathINIT
+ call T43_F()
+ call assert_equal('a3i3c2h2e1g1k', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 44: Missing or empty :catch patterns {{{1
+"
+" A missing or empty :catch pattern means the same as /.*/, that is,
+" catches everything. To catch only empty exceptions, /^$/ must be
+" used. A :catch with missing, empty, or /.*/ argument also works
+" when followed by another command separated by a bar on the same
+" line. :catch patterns cannot be specified between ||. But other
+" pattern separators can be used instead of //.
+"-------------------------------------------------------------------------------
+
+func T44_F()
+ try
+ try
+ Xpath 'a'
+ throw ""
+ catch /^$/
+ Xpath 'b'
+ endtry
+
+ try
+ Xpath 'c'
+ throw ""
+ catch /.*/
+ Xpath 'd'
+ endtry
+
+ try
+ Xpath 'e'
+ throw ""
+ catch //
+ Xpath 'f'
+ endtry
+
+ try
+ Xpath 'g'
+ throw ""
+ catch
+ Xpath 'h'
+ endtry
+
+ try
+ Xpath 'i'
+ throw "oops"
+ catch /^$/
+ Xpath 'j'
+ catch /.*/
+ Xpath 'k'
+ endtry
+
+ try
+ Xpath 'l'
+ throw "arrgh"
+ catch /^$/
+ Xpath 'm'
+ catch //
+ Xpath 'n'
+ endtry
+
+ try
+ Xpath 'o'
+ throw "brrr"
+ catch /^$/
+ Xpath 'p'
+ catch
+ Xpath 'q'
+ endtry
+
+ try | Xpath 'r' | throw "x" | catch /.*/ | Xpath 's' | endtry
+
+ try | Xpath 't' | throw "y" | catch // | Xpath 'u' | endtry
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ " Extra try level: if ":catch" without arguments below raises
+ " a syntax error because it misinterprets the "Xpath" as a pattern,
+ " let it be caught by the ":catch /.*/" below.
+ try
+ try | Xpath 'v' | throw "z" | catch | Xpath 'w' | :
+ endtry
+ endtry
+ catch /.*/
+ let caught = 1
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ finally
+ if $VIMNOERRTHROW && v:errmsg != ""
+ call assert_report(v:errmsg)
+ endif
+ if caught || $VIMNOERRTHROW && v:errmsg != ""
+ Xpath 'x'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ let cologne = 4711
+ try
+ try
+ Xpath 'y'
+ throw "throw cologne"
+ " Next lines catches all and throws 4711:
+ catch |throw cologne|
+ Xpath 'z'
+ endtry
+ catch /4711/
+ Xpath 'A'
+ endtry
+
+ try
+ Xpath 'B'
+ throw "plus"
+ catch +plus+
+ Xpath 'C'
+ endtry
+
+ Xpath 'D'
+ catch /.*/
+ Xpath 'E'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+endfunc
+
+func Test_empty_catch()
+ XpathINIT
+ call T44_F()
+ call assert_equal('abcdefghiklnoqrstuvwyABCD', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 45: Catching exceptions from nested :try blocks {{{1
+"
+" When :try blocks are nested, an exception is caught by the innermost
+" try conditional that has a matching :catch clause.
+"-------------------------------------------------------------------------------
+
+func T45_F()
+ let loops = 3
+ while loops > 0
+ try
+ try
+ try
+ try
+ if loops == 3
+ Xpath 'a' . loops
+ throw "a"
+ Xpath 'b' . loops
+ elseif loops == 2
+ Xpath 'c' . loops
+ throw "ab"
+ Xpath 'd' . loops
+ elseif loops == 1
+ Xpath 'e' . loops
+ throw "abc"
+ Xpath 'f' . loops
+ endif
+ catch /abc/
+ Xpath 'g' . loops
+ endtry
+ catch /ab/
+ Xpath 'h' . loops
+ endtry
+ catch /.*/
+ Xpath 'i' . loops
+ endtry
+ catch /a/
+ Xpath 'j' . loops
+ endtry
+
+ let loops = loops - 1
+ endwhile
+ Xpath 'k'
+endfunc
+
+func Test_catch_from_nested_try()
+ XpathINIT
+ call T45_F()
+ call assert_equal('a3i3c2h2e1g1k', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 46: Executing :finally after a :throw in nested :try {{{1
+"
+" When an exception is thrown from within nested :try blocks, the
+" :finally clauses of the non-catching try conditionals should be
+" executed before the matching :catch of the next surrounding :try
+" gets the control. If this also has a :finally clause, it is
+" executed afterwards.
+"-------------------------------------------------------------------------------
+
+func T46_F()
+ let sum = 0
+
+ try
+ Xpath 'a'
+ try
+ Xpath 'b'
+ try
+ Xpath 'c'
+ try
+ Xpath 'd'
+ throw "ABC"
+ Xpath 'e'
+ catch /xyz/
+ Xpath 'f'
+ finally
+ Xpath 'g'
+ if sum != 0
+ Xpath 'h'
+ endif
+ let sum = sum + 1
+ endtry
+ Xpath 'i'
+ catch /123/
+ Xpath 'j'
+ catch /321/
+ Xpath 'k'
+ finally
+ Xpath 'l'
+ if sum != 1
+ Xpath 'm'
+ endif
+ let sum = sum + 2
+ endtry
+ Xpath 'n'
+ finally
+ Xpath 'o'
+ if sum != 3
+ Xpath 'p'
+ endif
+ let sum = sum + 4
+ endtry
+ Xpath 'q'
+ catch /ABC/
+ Xpath 'r'
+ if sum != 7
+ Xpath 's'
+ endif
+ let sum = sum + 8
+ finally
+ Xpath 't'
+ if sum != 15
+ Xpath 'u'
+ endif
+ let sum = sum + 16
+ endtry
+ Xpath 'v'
+ if sum != 31
+ Xpath 'w'
+ endif
+endfunc
+
+func Test_finally_after_throw()
+ XpathINIT
+ call T46_F()
+ call assert_equal('abcdglortv', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 47: Throwing exceptions from a :catch clause {{{1
+"
+" When an exception is thrown from a :catch clause, it should not be
+" caught by a :catch of the same :try conditional. After executing
+" the :finally clause (if present), surrounding try conditionals
+" should be checked for a matching :catch.
+"-------------------------------------------------------------------------------
+
+func T47_F()
+ Xpath 'a'
+ try
+ Xpath 'b'
+ try
+ Xpath 'c'
+ try
+ Xpath 'd'
+ throw "x1"
+ Xpath 'e'
+ catch /x1/
+ Xpath 'f'
+ try
+ Xpath 'g'
+ throw "x2"
+ Xpath 'h'
+ catch /x1/
+ Xpath 'i'
+ catch /x2/
+ Xpath 'j'
+ try
+ Xpath 'k'
+ throw "x3"
+ Xpath 'l'
+ catch /x1/
+ Xpath 'm'
+ catch /x2/
+ Xpath 'n'
+ finally
+ Xpath 'o'
+ endtry
+ Xpath 'p'
+ catch /x3/
+ Xpath 'q'
+ endtry
+ Xpath 'r'
+ catch /x1/
+ Xpath 's'
+ catch /x2/
+ Xpath 't'
+ catch /x3/
+ Xpath 'u'
+ finally
+ Xpath 'v'
+ endtry
+ Xpath 'w'
+ catch /x1/
+ Xpath 'x'
+ catch /x2/
+ Xpath 'y'
+ catch /x3/
+ Xpath 'z'
+ endtry
+ Xpath 'A'
+ catch /.*/
+ Xpath 'B'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+ Xpath 'C'
+endfunc
+
+func Test_throw_from_catch()
+ XpathINIT
+ call T47_F()
+ call assert_equal('abcdfgjkovzAC', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 48: Throwing exceptions from a :finally clause {{{1
+"
+" When an exception is thrown from a :finally clause, it should not be
+" caught by a :catch of the same :try conditional. Surrounding try
+" conditionals should be checked for a matching :catch. A previously
+" thrown exception is discarded.
+"-------------------------------------------------------------------------------
+
+func T48_F()
+ try
+
+ try
+ try
+ Xpath 'a'
+ catch /x1/
+ Xpath 'b'
+ finally
+ Xpath 'c'
+ throw "x1"
+ Xpath 'd'
+ endtry
+ Xpath 'e'
+ catch /x1/
+ Xpath 'f'
+ endtry
+ Xpath 'g'
+
+ try
+ try
+ Xpath 'h'
+ throw "x2"
+ Xpath 'i'
+ catch /x2/
+ Xpath 'j'
+ catch /x3/
+ Xpath 'k'
+ finally
+ Xpath 'l'
+ throw "x3"
+ Xpath 'm'
+ endtry
+ Xpath 'n'
+ catch /x2/
+ Xpath 'o'
+ catch /x3/
+ Xpath 'p'
+ endtry
+ Xpath 'q'
+
+ try
+ try
+ try
+ Xpath 'r'
+ throw "x4"
+ Xpath 's'
+ catch /x5/
+ Xpath 't'
+ finally
+ Xpath 'u'
+ throw "x5" " discards 'x4'
+ Xpath 'v'
+ endtry
+ Xpath 'w'
+ catch /x4/
+ Xpath 'x'
+ finally
+ Xpath 'y'
+ endtry
+ Xpath 'z'
+ catch /x5/
+ Xpath 'A'
+ endtry
+ Xpath 'B'
+
+ catch /.*/
+ Xpath 'C'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+ Xpath 'D'
+endfunc
+
+func Test_throw_from_finally()
+ XpathINIT
+ call T48_F()
+ call assert_equal('acfghjlpqruyABD', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 51: Throwing exceptions across :execute and user commands {{{1
+"
+" A :throw command may be executed under an ":execute" or from
+" a user command.
+"-------------------------------------------------------------------------------
+
+func T51_F()
+ command! -nargs=? THROW1 throw <args> | throw 1
+ command! -nargs=? THROW2 try | throw <args> | endtry | throw 2
+ command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry
+ command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry
+
+ try
+
+ try
+ try
+ Xpath 'a'
+ THROW1 "A"
+ catch /A/
+ Xpath 'b'
+ endtry
+ catch /1/
+ Xpath 'c'
+ endtry
+
+ try
+ try
+ Xpath 'd'
+ THROW2 "B"
+ catch /B/
+ Xpath 'e'
+ endtry
+ catch /2/
+ Xpath 'f'
+ endtry
+
+ try
+ try
+ Xpath 'g'
+ THROW3 "C"
+ catch /C/
+ Xpath 'h'
+ endtry
+ catch /3/
+ Xpath 'i'
+ endtry
+
+ try
+ try
+ Xpath 'j'
+ THROW4 "D"
+ catch /D/
+ Xpath 'k'
+ endtry
+ catch /4/
+ Xpath 'l'
+ endtry
+
+ try
+ try
+ Xpath 'm'
+ execute 'throw "E" | throw 5'
+ catch /E/
+ Xpath 'n'
+ endtry
+ catch /5/
+ Xpath 'o'
+ endtry
+
+ try
+ try
+ Xpath 'p'
+ execute 'try | throw "F" | endtry | throw 6'
+ catch /F/
+ Xpath 'q'
+ endtry
+ catch /6/
+ Xpath 'r'
+ endtry
+
+ try
+ try
+ Xpath 's'
+ execute'try | throw 7 | catch /7/ | throw "G" | endtry'
+ catch /G/
+ Xpath 't'
+ endtry
+ catch /7/
+ Xpath 'u'
+ endtry
+
+ try
+ try
+ Xpath 'v'
+ execute 'try | throw 8 | finally | throw "H" | endtry'
+ catch /H/
+ Xpath 'w'
+ endtry
+ catch /8/
+ Xpath 'x'
+ endtry
+
+ catch /.*/
+ Xpath 'y'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ Xpath 'z'
+
+ delcommand THROW1
+ delcommand THROW2
+ delcommand THROW3
+ delcommand THROW4
+endfunc
+
+func Test_throw_across_commands()
+ XpathINIT
+ call T51_F()
+ call assert_equal('abdeghjkmnpqstvwz', g:Xpath)
+endfunc
+
+
+
+"-------------------------------------------------------------------------------
+" Test 69: :throw across :if, :elseif, :while {{{1
+"
+" On an :if, :elseif, or :while command, an exception might be thrown
+" during evaluation of the expression to test. The exception can be
+" caught by the script.
+"-------------------------------------------------------------------------------
+
+func T69_throw(x)
+ Xpath 'x'
+ throw a:x
+endfunc
+
+func Test_throw_ifelsewhile()
+ XpathINIT
+
+ try
+ try
+ Xpath 'a'
+ if 111 == T69_throw("if") + 111
+ Xpath 'b'
+ else
+ Xpath 'c'
+ endif
+ Xpath 'd'
+ catch /^if$/
+ Xpath 'e'
+ catch /.*/
+ Xpath 'f'
+ call assert_report("if: " . v:exception . " in " . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'g'
+ if v:false
+ Xpath 'h'
+ elseif 222 == T69_throw("elseif") + 222
+ Xpath 'i'
+ else
+ Xpath 'j'
+ endif
+ Xpath 'k'
+ catch /^elseif$/
+ Xpath 'l'
+ catch /.*/
+ Xpath 'm'
+ call assert_report("elseif: " . v:exception . " in " . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'n'
+ while 333 == T69_throw("while") + 333
+ Xpath 'o'
+ break
+ endwhile
+ Xpath 'p'
+ catch /^while$/
+ Xpath 'q'
+ catch /.*/
+ Xpath 'r'
+ call assert_report("while: " .. v:exception .. " in " .. v:throwpoint)
+ endtry
+ catch /^0$/ " default return value
+ Xpath 's'
+ call assert_report(v:throwpoint)
+ catch /.*/
+ call assert_report(v:exception .. " in " .. v:throwpoint)
+ Xpath 't'
+ endtry
+
+ call assert_equal('axegxlnxq', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 70: :throw across :return or :throw {{{1
+"
+" On a :return or :throw command, an exception might be thrown during
+" evaluation of the expression to return or throw, respectively. The
+" exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+let T70_taken = ""
+
+func T70_throw(x, n)
+ let g:T70_taken = g:T70_taken . "T" . a:n
+ throw a:x
+endfunc
+
+func T70_F(x, y, n)
+ let g:T70_taken = g:T70_taken . "F" . a:n
+ return a:x + T70_throw(a:y, a:n)
+endfunc
+
+func T70_G(x, y, n)
+ let g:T70_taken = g:T70_taken . "G" . a:n
+ throw a:x . T70_throw(a:y, a:n)
+ return a:x
+endfunc
+
+func Test_throwreturn()
+ XpathINIT
+
+ try
+ try
+ Xpath 'a'
+ call T70_F(4711, "return", 1)
+ Xpath 'b'
+ catch /^return$/
+ Xpath 'c'
+ catch /.*/
+ Xpath 'd'
+ call assert_report("return: " .. v:exception .. " in " .. v:throwpoint)
+ endtry
+
+ try
+ Xpath 'e'
+ let var = T70_F(4712, "return-var", 2)
+ Xpath 'f'
+ catch /^return-var$/
+ Xpath 'g'
+ catch /.*/
+ Xpath 'h'
+ call assert_report("return-var: " . v:exception . " in " . v:throwpoint)
+ finally
+ unlet! var
+ endtry
+
+ try
+ Xpath 'i'
+ throw "except1" . T70_throw("throw1", 3)
+ Xpath 'j'
+ catch /^except1/
+ Xpath 'k'
+ catch /^throw1$/
+ Xpath 'l'
+ catch /.*/
+ Xpath 'm'
+ call assert_report("throw1: " .. v:exception .. " in " .. v:throwpoint)
+ endtry
+
+ try
+ Xpath 'n'
+ call T70_G("except2", "throw2", 4)
+ Xpath 'o'
+ catch /^except2/
+ Xpath 'p'
+ catch /^throw2$/
+ Xpath 'q'
+ catch /.*/
+ Xpath 'r'
+ call assert_report("throw2: " .. v:exception .. " in " .. v:throwpoint)
+ endtry
+
+ try
+ Xpath 's'
+ let var = T70_G("except3", "throw3", 5)
+ Xpath 't'
+ catch /^except3/
+ Xpath 'u'
+ catch /^throw3$/
+ Xpath 'v'
+ catch /.*/
+ Xpath 'w'
+ call assert_report("throw3: " .. v:exception .. " in " .. v:throwpoint)
+ finally
+ unlet! var
+ endtry
+
+ call assert_equal('F1T1F2T2T3G4T4G5T5', g:T70_taken)
+ Xpath 'x'
+ catch /^0$/ " default return value
+ Xpath 'y'
+ call assert_report(v:throwpoint)
+ catch /.*/
+ Xpath 'z'
+ call assert_report('Caught' .. v:exception .. ' in ' .. v:throwpoint)
+ endtry
+
+ call assert_equal('acegilnqsvx', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 71: :throw across :echo variants and :execute {{{1
+"
+" On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
+" exception might be thrown during evaluation of the arguments to
+" be displayed or executed as a command, respectively. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+let T71_taken = ""
+
+func T71_throw(x, n)
+ let g:T71_taken = g:T71_taken . "T" . a:n
+ throw a:x
+endfunc
+
+func T71_F(n)
+ let g:T71_taken = g:T71_taken . "F" . a:n
+ return "F" . a:n
+endfunc
+
+func Test_throw_echo()
+ XpathINIT
+
+ try
+ try
+ Xpath 'a'
+ echo 'echo ' . T71_throw("echo-except", 1) . T71_F(1)
+ Xpath 'b'
+ catch /^echo-except$/
+ Xpath 'c'
+ catch /.*/
+ Xpath 'd'
+ call assert_report("echo: " .. v:exception .. " in " .. v:throwpoint)
+ endtry
+
+ try
+ Xpath 'e'
+ echon "echon " . T71_throw("echon-except", 2) . T71_F(2)
+ Xpath 'f'
+ catch /^echon-except$/
+ Xpath 'g'
+ catch /.*/
+ Xpath 'h'
+ call assert_report('echon: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'i'
+ echomsg "echomsg " . T71_throw("echomsg-except", 3) . T71_F(3)
+ Xpath 'j'
+ catch /^echomsg-except$/
+ Xpath 'k'
+ catch /.*/
+ Xpath 'l'
+ call assert_report('echomsg: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'm'
+ echoerr "echoerr " . T71_throw("echoerr-except", 4) . T71_F(4)
+ Xpath 'n'
+ catch /^echoerr-except$/
+ Xpath 'o'
+ catch /Vim/
+ Xpath 'p'
+ catch /echoerr/
+ Xpath 'q'
+ catch /.*/
+ Xpath 'r'
+ call assert_report('echoerr: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ Xpath 's'
+ execute "echo 'execute " . T71_throw("execute-except", 5) . T71_F(5) "'"
+ Xpath 't'
+ catch /^execute-except$/
+ Xpath 'u'
+ catch /.*/
+ Xpath 'v'
+ call assert_report('execute: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('T1T2T3T4T5', g:T71_taken)
+ Xpath 'w'
+ catch /^0$/ " default return value
+ Xpath 'x'
+ call assert_report(v:throwpoint)
+ catch /.*/
+ Xpath 'y'
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('acegikmosuw', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 72: :throw across :let or :unlet {{{1
+"
+" On a :let command, an exception might be thrown during evaluation
+" of the expression to assign. On an :let or :unlet command, the
+" evaluation of the name of the variable to be assigned or list or
+" deleted, respectively, may throw an exception. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+let throwcount = 0
+
+func T72_throw(x)
+ let g:throwcount = g:throwcount + 1
+ throw a:x
+endfunc
+
+let T72_addpath = ''
+
+func T72_addpath(p)
+ let g:T72_addpath = g:T72_addpath . a:p
+endfunc
+
+func Test_throw_let()
+ XpathINIT
+
+ try
+ try
+ let $VAR = 'old_value'
+ Xpath 'a'
+ let $VAR = 'let(' . T72_throw('var') . ')'
+ Xpath 'b'
+ catch /^var$/
+ Xpath 'c'
+ finally
+ call assert_equal('old_value', $VAR)
+ endtry
+
+ try
+ let @a = 'old_value'
+ Xpath 'd'
+ let @a = 'let(' . T72_throw('reg') . ')'
+ Xpath 'e'
+ catch /^reg$/
+ try
+ Xpath 'f'
+ let @A = 'let(' . T72_throw('REG') . ')'
+ Xpath 'g'
+ catch /^REG$/
+ Xpath 'h'
+ endtry
+ finally
+ call assert_equal('old_value', @a)
+ call assert_equal('old_value', @A)
+ endtry
+
+ try
+ let saved_gpath = &g:path
+ let saved_lpath = &l:path
+ Xpath 'i'
+ let &path = 'let(' . T72_throw('opt') . ')'
+ Xpath 'j'
+ catch /^opt$/
+ try
+ Xpath 'k'
+ let &g:path = 'let(' . T72_throw('gopt') . ')'
+ Xpath 'l'
+ catch /^gopt$/
+ try
+ Xpath 'm'
+ let &l:path = 'let(' . T72_throw('lopt') . ')'
+ Xpath 'n'
+ catch /^lopt$/
+ Xpath 'o'
+ endtry
+ endtry
+ finally
+ call assert_equal(saved_gpath, &g:path)
+ call assert_equal(saved_lpath, &l:path)
+ let &g:path = saved_gpath
+ let &l:path = saved_lpath
+ endtry
+
+ unlet! var1 var2 var3
+
+ try
+ Xpath 'p'
+ let var1 = 'let(' . T72_throw('var1') . ')'
+ Xpath 'q'
+ catch /^var1$/
+ Xpath 'r'
+ finally
+ call assert_true(!exists('var1'))
+ endtry
+
+ try
+ let var2 = 'old_value'
+ Xpath 's'
+ let var2 = 'let(' . T72_throw('var2'). ')'
+ Xpath 't'
+ catch /^var2$/
+ Xpath 'u'
+ finally
+ call assert_equal('old_value', var2)
+ endtry
+
+ try
+ Xpath 'v'
+ let var{T72_throw('var3')} = 4711
+ Xpath 'w'
+ catch /^var3$/
+ Xpath 'x'
+ endtry
+
+ try
+ call T72_addpath('T1')
+ let var{T72_throw('var4')} var{T72_addpath('T2')} | call T72_addpath('T3')
+ call T72_addpath('T4')
+ catch /^var4$/
+ call T72_addpath('T5')
+ endtry
+
+ try
+ call T72_addpath('T6')
+ unlet var{T72_throw('var5')} var{T72_addpath('T7')}
+ \ | call T72_addpath('T8')
+ call T72_addpath('T9')
+ catch /^var5$/
+ call T72_addpath('T10')
+ endtry
+
+ call assert_equal('T1T5T6T10', g:T72_addpath)
+ call assert_equal(11, g:throwcount)
+ catch /.*/
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('acdfhikmoprsuvx', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 73: :throw across :function, :delfunction {{{1
+"
+" The :function and :delfunction commands may cause an expression
+" specified in braces to be evaluated. During evaluation, an
+" exception might be thrown. The exception can be caught by the
+" script.
+"-------------------------------------------------------------------------------
+
+let T73_taken = ''
+
+func T73_throw(x, n)
+ let g:T73_taken = g:T73_taken . 'T' . a:n
+ throw a:x
+endfunc
+
+func T73_expr(x, n)
+ let g:T73_taken = g:T73_taken . 'E' . a:n
+ if a:n % 2 == 0
+ call T73_throw(a:x, a:n)
+ endif
+ return 2 - a:n % 2
+endfunc
+
+func Test_throw_func()
+ XpathINIT
+
+ try
+ try
+ " Define function.
+ Xpath 'a'
+ function! F0()
+ endfunction
+ Xpath 'b'
+ function! F{T73_expr('function-def-ok', 1)}()
+ endfunction
+ Xpath 'c'
+ function! F{T73_expr('function-def', 2)}()
+ endfunction
+ Xpath 'd'
+ catch /^function-def-ok$/
+ Xpath 'e'
+ catch /^function-def$/
+ Xpath 'f'
+ catch /.*/
+ call assert_report('def: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ " List function.
+ Xpath 'g'
+ function F0
+ Xpath 'h'
+ function F{T73_expr('function-lst-ok', 3)}
+ Xpath 'i'
+ function F{T73_expr('function-lst', 4)}
+ Xpath 'j'
+ catch /^function-lst-ok$/
+ Xpath 'k'
+ catch /^function-lst$/
+ Xpath 'l'
+ catch /.*/
+ call assert_report('lst: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ " Delete function
+ Xpath 'm'
+ delfunction F0
+ Xpath 'n'
+ delfunction F{T73_expr('function-del-ok', 5)}
+ Xpath 'o'
+ delfunction F{T73_expr('function-del', 6)}
+ Xpath 'p'
+ catch /^function-del-ok$/
+ Xpath 'q'
+ catch /^function-del$/
+ Xpath 'r'
+ catch /.*/
+ call assert_report('del: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+ call assert_equal('E1E2T2E3E4T4E5E6T6', g:T73_taken)
+ catch /.*/
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('abcfghilmnor', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 74: :throw across builtin functions and commands {{{1
+"
+" Some functions like exists(), searchpair() take expression
+" arguments, other functions or commands like substitute() or
+" :substitute cause an expression (specified in the regular
+" expression) to be evaluated. During evaluation an exception
+" might be thrown. The exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+let T74_taken = ""
+
+func T74_throw(x, n)
+ let g:T74_taken = g:T74_taken . "T" . a:n
+ throw a:x
+endfunc
+
+func T74_expr(x, n)
+ let g:T74_taken = g:T74_taken . "E" . a:n
+ call T74_throw(a:x . a:n, a:n)
+ return "EXPR"
+endfunc
+
+func T74_skip(x, n)
+ let g:T74_taken = g:T74_taken . "S" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "skip"
+ let g:T74_taken = g:T74_taken . "s)"
+ return 1
+ elseif theline =~ "throw"
+ let g:T74_taken = g:T74_taken . "t)"
+ call T74_throw(a:x . a:n, a:n)
+ else
+ let g:T74_taken = g:T74_taken . ")"
+ return 0
+ endif
+endfunc
+
+func T74_subst(x, n)
+ let g:T74_taken = g:T74_taken . "U" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "not" " T74_subst() should not be called for this line
+ let g:T74_taken = g:T74_taken . "n)"
+ call T74_throw(a:x . a:n, a:n)
+ elseif theline =~ "throw"
+ let g:T74_taken = g:T74_taken . "t)"
+ call T74_throw(a:x . a:n, a:n)
+ else
+ let g:T74_taken = g:T74_taken . ")"
+ return "replaced"
+ endif
+endfunc
+
+func Test_throw_builtin_func()
+ XpathINIT
+
+ try
+ try
+ Xpath 'a'
+ let result = exists('*{T74_expr("exists", 1)}')
+ Xpath 'b'
+ catch /^exists1$/
+ Xpath 'c'
+ try
+ let result = exists('{T74_expr("exists", 2)}')
+ Xpath 'd'
+ catch /^exists2$/
+ Xpath 'e'
+ catch /.*/
+ call assert_report('exists2: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+ catch /.*/
+ call assert_report('exists1: ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ call append(0, [
+ \ 'begin',
+ \ 'xx',
+ \ 'middle 3',
+ \ 'xx',
+ \ 'middle 5 skip',
+ \ 'xx',
+ \ 'middle 7 throw',
+ \ 'xx',
+ \ 'end'])
+ normal! gg
+ Xpath 'f'
+ let result = searchpair("begin", "middle", "end", '',
+ \ 'T74_skip("searchpair", 3)')
+ Xpath 'g'
+ let result = searchpair("begin", "middle", "end", '',
+ \ 'T74_skip("searchpair", 4)')
+ Xpath 'h'
+ let result = searchpair("begin", "middle", "end", '',
+ \ 'T74_skip("searchpair", 5)')
+ Xpath 'i'
+ catch /^searchpair[35]$/
+ Xpath 'j'
+ catch /^searchpair4$/
+ Xpath 'k'
+ catch /.*/
+ call assert_report('searchpair: ' . v:exception . ' in ' . v:throwpoint)
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ call append(0, [
+ \ 'subst 1',
+ \ 'subst 2',
+ \ 'not',
+ \ 'subst 4',
+ \ 'subst throw',
+ \ 'subst 6'])
+ normal! gg
+ Xpath 'l'
+ 1,2substitute/subst/\=T74_subst("substitute", 6)/
+ try
+ Xpath 'm'
+ try
+ let v:errmsg = ""
+ 3substitute/subst/\=T74_subst("substitute", 7)/
+ finally
+ if v:errmsg != ""
+ " If exceptions are not thrown on errors, fake the error
+ " exception in order to get the same execution path.
+ throw "faked Vim(substitute)"
+ endif
+ endtry
+ catch /Vim(substitute)/ " Pattern not found ('e' flag missing)
+ Xpath 'n'
+ 3substitute/subst/\=T74_subst("substitute", 8)/e
+ Xpath 'o'
+ endtry
+ Xpath 'p'
+ 4,6substitute/subst/\=T74_subst("substitute", 9)/
+ Xpath 'q'
+ catch /^substitute[678]/
+ Xpath 'r'
+ catch /^substitute9/
+ Xpath 's'
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ Xpath 't'
+ let var = substitute("sub", "sub", '\=T74_throw("substitute()y", 10)', '')
+ Xpath 'u'
+ catch /substitute()y/
+ Xpath 'v'
+ catch /.*/
+ call assert_report('substitute()y: ' . v:exception . ' in '
+ \ . v:throwpoint)
+ endtry
+
+ try
+ Xpath 'w'
+ let var = substitute("not", "sub", '\=T74_throw("substitute()n", 11)', '')
+ Xpath 'x'
+ catch /substitute()n/
+ Xpath 'y'
+ catch /.*/
+ call assert_report('substitute()n: ' . v:exception . ' in '
+ \ . v:throwpoint)
+ endtry
+
+ call assert_equal('E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10',
+ \ g:T74_taken)
+
+ catch /.*/
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ endtry
+
+ call assert_equal('acefgklmnopstvwx', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 75: Errors in builtin functions. {{{1
+"
+" On an error in a builtin function called inside a :try/:endtry
+" region, the evaluation of the expression calling that function and
+" the command containing that expression are abandoned. The error can
+" be caught as an exception.
+"
+" A simple :call of the builtin function is a trivial case. If the
+" builtin function is called in the argument list of another function,
+" no further arguments are evaluated, and the other function is not
+" executed. If the builtin function is called from the argument of
+" a :return command, the :return command is not executed. If the
+" builtin function is called from the argument of a :throw command,
+" the :throw command is not executed. The evaluation of the
+" expression calling the builtin function is abandoned.
+"-------------------------------------------------------------------------------
+
+func T75_F1(arg1)
+ Xpath 'a'
+endfunc
+
+func T75_F2(arg1, arg2)
+ Xpath 'b'
+endfunc
+
+func T75_G()
+ Xpath 'c'
+endfunc
+
+func T75_H()
+ Xpath 'd'
+endfunc
+
+func T75_R()
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'e'
+ return append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 'f'
+ finally
+ Xpath 'g'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'h'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ Xpath 'i'
+endfunc
+
+func Test_builtin_func_error()
+ XpathINIT
+
+ try
+ set noma " let append() fail with "E21"
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'j'
+ call append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 'k'
+ finally
+ Xpath 'l'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'm'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'n'
+ call T75_F1('x' . append(1, "s"))
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 'o'
+ finally
+ Xpath 'p'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'q'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'r'
+ call T75_F2('x' . append(1, "s"), T75_G())
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 's'
+ finally
+ Xpath 't'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'u'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ call T75_R()
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'v'
+ throw "T" . append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /^T.*/
+ Xpath 'w'
+ catch /.*/
+ Xpath 'x'
+ finally
+ Xpath 'y'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'z'
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 'A'
+ let x = "a"
+ let x = x . "b" . append(1, "s") . T75_H()
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 'B'
+ finally
+ Xpath 'C'
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 'D'
+ endif
+ call assert_equal('a', x)
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ catch /.*/
+ call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
+ finally
+ set ma&
+ endtry
+
+ call assert_equal('jlmnpqrtueghivyzACD', g:Xpath)
+endfunc
+
+" Modelines {{{1
+" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+"-------------------------------------------------------------------------------
diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim
index 0a89066a2b..4621207d19 100644
--- a/src/nvim/testdir/test_usercommands.vim
+++ b/src/nvim/testdir/test_usercommands.vim
@@ -393,9 +393,13 @@ func Test_addr_all()
call assert_equal(len(gettabinfo()), g:a2)
bwipe
- command! -addr=other DoSomething echo 'nothing'
+ command! -addr=other DoSomething let g:a1 = <line1> | let g:a2 = <line2>
DoSomething
- call assert_fails('%DoSomething')
+ call assert_equal(line('.'), g:a1)
+ call assert_equal(line('.'), g:a2)
+ %DoSomething
+ call assert_equal(1, g:a1)
+ call assert_equal(line('$'), g:a2)
delcommand DoSomething
endfunc
@@ -421,7 +425,7 @@ func Test_command_list()
\ execute('command DoCmd'))
command! -count=2 DoCmd :
call assert_equal("\n Name Args Address Complete Definition"
- \ .. "\n DoCmd 0 2c :",
+ \ .. "\n DoCmd 0 2c ? :",
\ execute('command DoCmd'))
" Test with various -addr= argument values.
diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim
index 8302ccb67f..e8161f8fcb 100644
--- a/src/nvim/testdir/test_utf8.vim
+++ b/src/nvim/testdir/test_utf8.vim
@@ -103,3 +103,14 @@ func Test_list2str_str2list_latin1()
call assert_equal(l, lres)
call assert_equal(s, sres)
endfunc
+
+func Test_print_overlong()
+ " Text with more composing characters than MB_MAXBYTES.
+ new
+ call setline(1, 'axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
+ s/x/\=nr2char(1629)/g
+ print
+ bwipe!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 4edf8308e7..43907de1d9 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -919,9 +919,203 @@ func Test_if_bar_fail()
call assert_equal('acdfh-acfh', g:test15_result)
endfunc
+"-------------------------------------------------------------------------------
+" Test 16: Double :else or :elseif after :else {{{1
+"
+" Multiple :elses or an :elseif after an :else are forbidden.
+"-------------------------------------------------------------------------------
+
+func T16_F() abort
+ if 0
+ Xpath 'a'
+ else
+ Xpath 'b'
+ else " aborts function
+ Xpath 'c'
+ endif
+ Xpath 'd'
+endfunc
+
+func T16_G() abort
+ if 0
+ Xpath 'a'
+ else
+ Xpath 'b'
+ elseif 1 " aborts function
+ Xpath 'c'
+ else
+ Xpath 'd'
+ endif
+ Xpath 'e'
+endfunc
+
+func T16_H() abort
+ if 0
+ Xpath 'a'
+ elseif 0
+ Xpath 'b'
+ else
+ Xpath 'c'
+ else " aborts function
+ Xpath 'd'
+ endif
+ Xpath 'e'
+endfunc
+
+func T16_I() abort
+ if 0
+ Xpath 'a'
+ elseif 0
+ Xpath 'b'
+ else
+ Xpath 'c'
+ elseif 1 " aborts function
+ Xpath 'd'
+ else
+ Xpath 'e'
+ endif
+ Xpath 'f'
+endfunc
+
+func Test_Multi_Else()
+ XpathINIT
+ try
+ call T16_F()
+ catch /E583:/
+ Xpath 'e'
+ endtry
+ call assert_equal('be', g:Xpath)
+
+ XpathINIT
+ try
+ call T16_G()
+ catch /E584:/
+ Xpath 'f'
+ endtry
+ call assert_equal('bf', g:Xpath)
+
+ XpathINIT
+ try
+ call T16_H()
+ catch /E583:/
+ Xpath 'f'
+ endtry
+ call assert_equal('cf', g:Xpath)
+
+ XpathINIT
+ try
+ call T16_I()
+ catch /E584:/
+ Xpath 'g'
+ endtry
+ call assert_equal('cg', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
+"
+" The :while/:endwhile takes precedence in nesting over an unclosed
+" :if or an unopened :endif.
+"-------------------------------------------------------------------------------
+
+" While loops inside a function are continued on error.
+func T17_F()
+ let loops = 3
+ while loops > 0
+ let loops -= 1
+ Xpath 'a' . loops
+ if (loops == 1)
+ Xpath 'b' . loops
+ continue
+ elseif (loops == 0)
+ Xpath 'c' . loops
+ break
+ elseif 1
+ Xpath 'd' . loops
+ " endif missing!
+ endwhile " :endwhile after :if 1
+ Xpath 'e'
+endfunc
+
+func T17_G()
+ let loops = 2
+ while loops > 0
+ let loops -= 1
+ Xpath 'a' . loops
+ if 0
+ Xpath 'b' . loops
+ " endif missing
+ endwhile " :endwhile after :if 0
+endfunc
+
+func T17_H()
+ let loops = 2
+ while loops > 0
+ let loops -= 1
+ Xpath 'a' . loops
+ " if missing!
+ endif " :endif without :if in while
+ Xpath 'b' . loops
+ endwhile
+endfunc
+
+" Error continuation outside a function is at the outermost :endwhile or :endif.
+XpathINIT
+let v:errmsg = ''
+let loops = 2
+while loops > 0
+ let loops -= 1
+ Xpath 'a' . loops
+ if 0
+ Xpath 'b' . loops
+ " endif missing! Following :endwhile fails.
+endwhile | Xpath 'c'
+Xpath 'd'
+call assert_match('E171:', v:errmsg)
+call assert_equal('a1d', g:Xpath)
+
+func Test_unmatched_if_in_while()
+ XpathINIT
+ call assert_fails('call T17_F()', 'E171:')
+ call assert_equal('a2d2a1b1a0c0e', g:Xpath)
+
+ XpathINIT
+ call assert_fails('call T17_G()', 'E171:')
+ call assert_equal('a1a0', g:Xpath)
+
+ XpathINIT
+ call assert_fails('call T17_H()', 'E580:')
+ call assert_equal('a1b1a0b0', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+"-------------------------------------------------------------------------------
+"-------------------------------------------------------------------------------
+" Test 87 using (expr) ? funcref : funcref {{{1
+"
+" Vim needs to correctly parse the funcref and even when it does
+" not execute the funcref, it needs to consume the trailing ()
+"-------------------------------------------------------------------------------
+
+func Add2(x1, x2)
+ return a:x1 + a:x2
+endfu
+
+func GetStr()
+ return "abcdefghijklmnopqrstuvwxyp"
+endfu
+
+func Test_funcref_with_condexpr()
+ call assert_equal(5, function('Add2')(2,3))
+
+ call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
+ call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
+ " Make sure, GetStr() still works.
+ call assert_equal('abcdefghijk', GetStr()[0:10])
+endfunc
"-------------------------------------------------------------------------------
-" Test 16: Recognizing {} in variable name. {{{1
+" Test 90: Recognizing {} in variable name. {{{1
"-------------------------------------------------------------------------------
func Test_curlies()
@@ -1490,5 +1684,5 @@ endfunc
"-------------------------------------------------------------------------------
" Modelines {{{1
-" vim: ts=8 sw=4 tw=80 fdm=marker
+" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
"-------------------------------------------------------------------------------
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index c630e678fd..687b1cb989 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -850,6 +850,14 @@ func Test_window_resize()
exe other_winnr .. 'resize +1'
call assert_equal(12, winheight(other_winnr))
call assert_equal(&lines - 10 - 3 -2, winheight(0))
+ close
+
+ vsplit
+ wincmd l
+ let other_winnr = winnr('h')
+ call assert_notequal(winnr(), other_winnr)
+ exe 'vert ' .. other_winnr .. 'resize -' .. &columns
+ call assert_equal(0, winwidth(other_winnr))
%bwipe!
endfunc
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 685da77b39..c6c09c80d7 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -61,6 +61,9 @@ static bool pending_mode_info_update = false;
static bool pending_mode_update = false;
static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE;
+static bool has_mouse = false;
+static int pending_has_mouse = -1;
+
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
# define UI_LOG(funname)
#else
@@ -220,6 +223,7 @@ void ui_refresh(void)
ui_mode_info_set();
pending_mode_update = true;
ui_cursor_shape();
+ pending_has_mouse = -1;
}
int ui_pum_get_height(void)
@@ -459,10 +463,69 @@ void ui_flush(void)
ui_call_mode_change(cstr_as_string(full_name), ui_mode_idx);
pending_mode_update = false;
}
+ if (pending_has_mouse != has_mouse) {
+ (has_mouse ? ui_call_mouse_on : ui_call_mouse_off)();
+ pending_has_mouse = has_mouse;
+ }
ui_call_flush();
}
+
+/// Check if 'mouse' is active for the current mode
+///
+/// TODO(bfredl): precompute the State -> active mapping when 'mouse' changes,
+/// then this can be checked directly in ui_flush()
+void ui_check_mouse(void)
+{
+ has_mouse = false;
+ // Be quick when mouse is off.
+ if (*p_mouse == NUL) {
+ return;
+ }
+
+ int checkfor = MOUSE_NORMAL; // assume normal mode
+ if (VIsual_active) {
+ checkfor = MOUSE_VISUAL;
+ } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) {
+ checkfor = MOUSE_RETURN;
+ } else if (State & INSERT) {
+ checkfor = MOUSE_INSERT;
+ } else if (State & CMDLINE) {
+ checkfor = MOUSE_COMMAND;
+ } else if (State == CONFIRM || State == EXTERNCMD) {
+ checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd"
+ }
+
+ // mouse should be active if at least one of the following is true:
+ // - "c" is in 'mouse', or
+ // - 'a' is in 'mouse' and "c" is in MOUSE_A, or
+ // - the current buffer is a help file and 'h' is in 'mouse' and we are in a
+ // normal editing mode (not at hit-return message).
+ for (char_u *p = p_mouse; *p; p++) {
+ switch (*p) {
+ case 'a':
+ if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) {
+ has_mouse = true;
+ return;
+ }
+ break;
+ case MOUSE_HELP:
+ if (checkfor != MOUSE_RETURN && curbuf->b_help) {
+ has_mouse = true;
+ return;
+ }
+ break;
+ default:
+ if (checkfor == *p) {
+ has_mouse = true;
+ return;
+ }
+ }
+ }
+}
+
/// Check if current mode has changed.
+///
/// May update the shape of the cursor.
void ui_cursor_shape(void)
{
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index a8b8f7aa50..da464c56dc 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -82,6 +82,8 @@
#include <string.h>
#include <fcntl.h>
+#include "auto/config.h"
+
#include "nvim/buffer.h"
#include "nvim/ascii.h"
#include "nvim/change.h"
@@ -1255,7 +1257,8 @@ theend:
/// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
-void u_read_undo(char *name, char_u *hash, char_u *orig_name)
+void u_read_undo(char *name, const char_u *hash,
+ const char_u *orig_name FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
@@ -1273,7 +1276,7 @@ void u_read_undo(char *name, char_u *hash, char_u *orig_name)
// owner of the text file or equal to the current user.
FileInfo file_info_orig;
FileInfo file_info_undo;
- if (os_fileinfo((char *)orig_name, &file_info_orig)
+ if (os_fileinfo((const char *)orig_name, &file_info_orig)
&& os_fileinfo((char *)file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 6be2a61c6a..834d27cc84 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -16,7 +16,6 @@
#include "nvim/iconv.h"
#include "nvim/version.h"
#include "nvim/charset.h"
-#include "nvim/macros.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
diff --git a/src/nvim/version.h b/src/nvim/version.h
index c10f6fa534..4af038dd6c 100644
--- a/src/nvim/version.h
+++ b/src/nvim/version.h
@@ -2,6 +2,7 @@
#define NVIM_VERSION_H
#include "nvim/ex_cmds_defs.h"
+#include "nvim/macros.h"
// defined in version.c
extern char* Version;
@@ -10,14 +11,20 @@ extern char* longVersion;
//
// Vim version number, name, etc. Patchlevel is defined in version.c.
//
+
+// Values that change for a new release
#define VIM_VERSION_MAJOR 8
#define VIM_VERSION_MINOR 0
+
+// Values based on the above
+#define VIM_VERSION_MAJOR_STR STR(VIM_VERSION_MAJOR)
+#define VIM_VERSION_MINOR_STR STR(VIM_VERSION_MINOR)
#define VIM_VERSION_100 (VIM_VERSION_MAJOR * 100 + VIM_VERSION_MINOR)
// used for the runtime directory name
-#define VIM_VERSION_NODOT "vim80"
+#define VIM_VERSION_NODOT "vim" VIM_VERSION_MAJOR_STR VIM_VERSION_MINOR_STR
// swap file compatibility (max. length is 6 chars)
-#define VIM_VERSION_SHORT "8.0"
+#define VIM_VERSION_SHORT VIM_VERSION_MAJOR_STR "." VIM_VERSION_MINOR_STR
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "version.h.generated.h"
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 900f2acd81..01f20cf29a 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -208,6 +208,7 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
// Size in bytes of the hash used in the undo file.
#define UNDO_HASH_SIZE 32
+#define CLEAR_POINTER(ptr) memset((ptr), 0, sizeof(*(ptr)))
// defines to avoid typecasts from (char_u *) to (char *) and back
// (vim_strchr() is now in strings.c)
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 72ee400e40..00f49724b6 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -641,7 +641,7 @@ void win_set_minimal_style(win_T *wp)
wp->w_p_scl = (char_u *)xstrdup("auto");
}
- // foldcolumn: use 'auto'
+ // foldcolumn: use '0'
if (wp->w_p_fdc[0] != '0') {
xfree(wp->w_p_fdc);
wp->w_p_fdc = (char_u *)xstrdup("0");
@@ -700,9 +700,10 @@ int win_fdccol_count(win_T *wp)
const char *fdc = (const char *)wp->w_p_fdc;
// auto:<NUM>
- if (strncmp(fdc, "auto:", 5) == 0) {
+ if (strncmp(fdc, "auto", 4) == 0) {
+ const int fdccol = fdc[4] == ':' ? fdc[5] - '0' : 1;
int needed_fdccols = getDeepestNesting(wp);
- return MIN(fdc[5] - '0', needed_fdccols);
+ return MIN(fdccol, needed_fdccols);
} else {
return fdc[0] - '0';
}
@@ -1636,6 +1637,19 @@ bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
return false;
}
+// Find window "handle" in the current tab page.
+// Return NULL if not found.
+win_T *win_find_by_handle(handle_T handle)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->handle == handle) {
+ return wp;
+ }
+ }
+ return NULL;
+}
+
/// Check if "win" is a pointer to an existing window in any tabpage.
///
/// @param win window to check
@@ -3787,32 +3801,35 @@ void free_tabpage(tabpage_T *tp)
/// @return Was the new tabpage created successfully? FAIL or OK.
int win_new_tabpage(int after, char_u *filename)
{
- tabpage_T *tp = curtab;
+ tabpage_T *old_curtab = curtab;
tabpage_T *newtp;
int n;
newtp = alloc_tabpage();
- /* Remember the current windows in this Tab page. */
- if (leave_tabpage(curbuf, TRUE) == FAIL) {
+ // Remember the current windows in this Tab page.
+ if (leave_tabpage(curbuf, true) == FAIL) {
xfree(newtp);
return FAIL;
}
- newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL;
+ newtp->tp_localdir = old_curtab->tp_localdir
+ ? vim_strsave(old_curtab->tp_localdir) : NULL;
curtab = newtp;
- /* Create a new empty window. */
- if (win_alloc_firstwin(tp->tp_curwin) == OK) {
- /* Make the new Tab page the new topframe. */
+ // Create a new empty window.
+ if (win_alloc_firstwin(old_curtab->tp_curwin) == OK) {
+ // Make the new Tab page the new topframe.
if (after == 1) {
- /* New tab page becomes the first one. */
+ // New tab page becomes the first one.
newtp->tp_next = first_tabpage;
first_tabpage = newtp;
} else {
+ tabpage_T *tp = old_curtab;
+
if (after > 0) {
- /* Put new tab page before tab page "after". */
+ // Put new tab page before tab page "after".
n = 2;
for (tp = first_tabpage; tp->tp_next != NULL
&& n < after; tp = tp->tp_next)
@@ -3826,13 +3843,13 @@ int win_new_tabpage(int after, char_u *filename)
win_comp_scroll(curwin);
newtp->tp_topframe = topframe;
- last_status(FALSE);
+ last_status(false);
redraw_all_later(NOT_VALID);
- tabpage_check_windows(tp);
+ tabpage_check_windows(old_curtab);
- lastused_tabpage = tp;
+ lastused_tabpage = old_curtab;
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
@@ -3842,8 +3859,8 @@ int win_new_tabpage(int after, char_u *filename)
return OK;
}
- /* Failed, get back the previous Tab page */
- enter_tabpage(curtab, curbuf, TRUE, TRUE);
+ // Failed, get back the previous Tab page
+ enter_tabpage(curtab, curbuf, true, true);
return FAIL;
}
@@ -4523,7 +4540,7 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
// Might need to scroll the old window before switching, e.g., when the
// cursor was moved.
- update_topline();
+ update_topline(curwin);
// may have to copy the buffer options when 'cpo' contains 'S'
if (wp->w_buffer != curbuf) {
@@ -4996,7 +5013,10 @@ void win_size_save(garray_T *gap)
{
ga_init(gap, (int)sizeof(int), 1);
- ga_grow(gap, win_count() * 2);
+ ga_grow(gap, win_count() * 2 + 1);
+ // first entry is value of 'lines'
+ ((int *)gap->ga_data)[gap->ga_len++] = Rows;
+
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
((int *)gap->ga_data)[gap->ga_len++] =
wp->w_width + wp->w_vsep_width;
@@ -5004,18 +5024,18 @@ void win_size_save(garray_T *gap)
}
}
-/*
- * Restore window sizes, but only if the number of windows is still the same.
- * Does not free the growarray.
- */
+// Restore window sizes, but only if the number of windows is still the same
+// and 'lines' didn't change.
+// Does not free the growarray.
void win_size_restore(garray_T *gap)
+ FUNC_ATTR_NONNULL_ALL
{
- if (win_count() * 2 == gap->ga_len) {
- /* The order matters, because frames contain other frames, but it's
- * difficult to get right. The easy way out is to do it twice. */
- for (int j = 0; j < 2; ++j)
- {
- int i = 0;
+ if (win_count() * 2 + 1 == gap->ga_len
+ && ((int *)gap->ga_data)[0] == Rows) {
+ // The order matters, because frames contain other frames, but it's
+ // difficult to get right. The easy way out is to do it twice.
+ for (int j = 0; j < 2; j++) {
+ int i = 1;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
int width = ((int *)gap->ga_data)[i++];
int height = ((int *)gap->ga_data)[i++];
@@ -5329,6 +5349,8 @@ void win_setwidth_win(int width, win_T *wp)
width = p_wmw;
if (width == 0)
width = 1;
+ } else if (width < 0) {
+ width = 0;
}
if (wp->w_floating) {
wp->w_float_config.width = width;
@@ -5856,10 +5878,10 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
if (wp == curwin) {
- if (get_scrolloff_value()) {
- update_topline();
+ if (get_scrolloff_value(wp)) {
+ update_topline(wp);
}
- curs_columns(false); // validate w_wrow
+ curs_columns(wp, false); // validate w_wrow
}
if (prev_height > 0) {
wp->w_prev_fraction_row = wp->w_wrow;
@@ -5915,8 +5937,8 @@ void win_set_inner_size(win_T *wp)
changed_line_abv_curs_win(wp);
invalidate_botline_win(wp);
if (wp == curwin) {
- update_topline();
- curs_columns(true); // validate w_wrow
+ update_topline(wp);
+ curs_columns(wp, true); // validate w_wrow
}
redraw_later(wp, NOT_VALID);
}