aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/clint.py2
-rwxr-xr-xsrc/nvim/CMakeLists.txt2
-rw-r--r--src/nvim/api/autocmd.c8
-rw-r--r--src/nvim/api/command.c117
-rw-r--r--src/nvim/api/extmark.c8
-rw-r--r--src/nvim/api/options.c4
-rw-r--r--src/nvim/api/private/helpers.c18
-rw-r--r--src/nvim/api/ui.c4
-rw-r--r--src/nvim/api/vim.c14
-rw-r--r--src/nvim/api/win_config.c2
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/change.c2
-rw-r--r--src/nvim/charset.c2
-rw-r--r--src/nvim/debugger.c2
-rw-r--r--src/nvim/drawscreen.c3
-rw-r--r--src/nvim/eval.c5
-rw-r--r--src/nvim/eval/funcs.c11
-rw-r--r--src/nvim/eval/typval.c4
-rw-r--r--src/nvim/eval/vars.c8
-rw-r--r--src/nvim/ex_docmd.c61
-rw-r--r--src/nvim/ex_getln.c15
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/hashtab.c2
-rw-r--r--src/nvim/highlight_group.c2
-rw-r--r--src/nvim/if_cscope.c2
-rw-r--r--src/nvim/input.c5
-rw-r--r--src/nvim/keycodes.c9
-rw-r--r--src/nvim/lua/executor.c3
-rw-r--r--src/nvim/lua/stdlib.c19
-rw-r--r--src/nvim/lua/treesitter.c2
-rw-r--r--src/nvim/mapping.c2
-rw-r--r--src/nvim/mapping.h2
-rw-r--r--src/nvim/message.c15
-rw-r--r--src/nvim/option.c101
-rw-r--r--src/nvim/option_defs.h37
-rw-r--r--src/nvim/optionstr.c76
-rw-r--r--src/nvim/os/shell.c2
-rw-r--r--src/nvim/path.c2
-rw-r--r--src/nvim/sign.c55
-rw-r--r--src/nvim/spell.c12
-rw-r--r--src/nvim/terminal.c22
-rw-r--r--src/nvim/testdir/test_filetype.vim6
-rw-r--r--src/nvim/testdir/test_messages.vim67
-rw-r--r--src/nvim/textobject.c2
-rw-r--r--src/nvim/tui/input.c4
-rw-r--r--src/nvim/tui/input.h2
-rw-r--r--src/nvim/tui/tui.c8
-rw-r--r--src/nvim/undo.c8
-rw-r--r--src/nvim/window.c4
50 files changed, 452 insertions, 319 deletions
diff --git a/src/clint.py b/src/clint.py
index c4ddbf706e..1a355e0218 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -202,7 +202,7 @@ _ERROR_CATEGORIES = [
'whitespace/cast',
]
-# The default state of the category filter. This is overrided by the --filter=
+# The default state of the category filter. This is overridden by the --filter=
# flag. By default all errors are on, so only add here categories that should be
# off by default (i.e., categories that must be enabled by the --filter= flags).
# All entries here should start with a '-' or '+', as in the --filter= flag.
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index f28b7a7e28..6f5f2b53f6 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -159,7 +159,7 @@ list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
if(NOT MSVC)
# xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
set_source_files_properties(
- ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion")
+ ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes")
endif()
if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$")
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index ac4cb953b8..b5c695b9ce 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -599,7 +599,7 @@ void nvim_del_autocmd(Integer id, Error *err)
}
/// Clear all autocommands that match the corresponding {opts}. To delete
-/// a particular autocmd, see |nvim_del_autocmd|.
+/// a particular autocmd, see |nvim_del_autocmd()|.
/// @param opts Parameters
/// - event: (string|table)
/// Examples:
@@ -728,7 +728,7 @@ Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augrou
///
/// To get a group id one can use |nvim_get_autocmds()|.
///
-/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in
+/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in
/// this group will also be deleted and cleared. This group will no longer exist.
/// @param id Integer The id of the group.
/// @see |nvim_del_augroup_by_name()|
@@ -746,10 +746,10 @@ void nvim_del_augroup_by_id(Integer id, Error *err)
/// Delete an autocommand group by name.
///
-/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in
+/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in
/// this group will also be deleted and cleared. This group will no longer exist.
/// @param name String The name of the group.
-/// @see |autocommand-groups|
+/// @see |autocmd-groups|
void nvim_del_augroup_by_name(String name, Error *err)
FUNC_API_SINCE(9)
{
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index ed0907e8f8..8cd2c0f8b8 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -31,14 +31,15 @@
/// @param[out] err Error details, if any.
/// @return Dictionary containing command information, with these keys:
/// - cmd: (string) Command name.
-/// - range: (array) Command <range>. Can have 0-2 elements depending on how many items the
-/// range contains. Has no elements if command doesn't accept a range or if
-/// no range was specified, one element if only a single range item was
-/// specified and two elements if both range items were specified.
-/// - count: (number) Any |<count>| that was supplied to the command. -1 if command cannot
-/// take a count.
-/// - reg: (number) The optional command |<register>|, if specified. Empty string if not
-/// specified or if command cannot take a register.
+/// - range: (array) (optional) Command range (|<line1>| |<line2>|).
+/// Omitted if command doesn't accept a range.
+/// Otherwise, has no elements if no range was specified, one element if
+/// only a single range item was specified, or two elements if both range
+/// items were specified.
+/// - count: (number) (optional) Command |<count>|.
+/// Omitted if command cannot take a count.
+/// - reg: (string) (optional) Command |<register>|.
+/// Omitted if command cannot take a register.
/// - bang: (boolean) Whether command contains a |<bang>| (!) modifier.
/// - args: (array) Command arguments.
/// - addr: (string) Value of |:command-addr|. Uses short name.
@@ -142,15 +143,15 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
PUT(result, "cmd", CSTR_TO_OBJ((char *)get_command_name(NULL, ea.cmdidx)));
}
- if ((ea.argt & EX_RANGE) && ea.addr_count > 0) {
+ if (ea.argt & EX_RANGE) {
Array range = ARRAY_DICT_INIT;
- if (ea.addr_count > 1) {
- ADD(range, INTEGER_OBJ(ea.line1));
+ if (ea.addr_count > 0) {
+ if (ea.addr_count > 1) {
+ ADD(range, INTEGER_OBJ(ea.line1));
+ }
+ ADD(range, INTEGER_OBJ(ea.line2));
}
- ADD(range, INTEGER_OBJ(ea.line2));
PUT(result, "range", ARRAY_OBJ(range));
- } else {
- PUT(result, "range", ARRAY_OBJ(ARRAY_DICT_INIT));
}
if (ea.argt & EX_COUNT) {
@@ -161,14 +162,12 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
} else {
PUT(result, "count", INTEGER_OBJ(0));
}
- } else {
- PUT(result, "count", INTEGER_OBJ(-1));
}
- char reg[2];
- reg[0] = (char)ea.regname;
- reg[1] = '\0';
- PUT(result, "reg", CSTR_TO_OBJ(reg));
+ if (ea.argt & EX_REGSTR) {
+ char reg[2] = { (char)ea.regname, NUL };
+ PUT(result, "reg", CSTR_TO_OBJ(reg));
+ }
PUT(result, "bang", BOOLEAN_OBJ(ea.forceit));
PUT(result, "args", ARRAY_OBJ(args));
@@ -285,7 +284,11 @@ end:
/// Unlike |nvim_command()| this command takes a structured Dictionary instead of a String. This
/// allows for easier construction and manipulation of an Ex command. This also allows for things
/// such as having spaces inside a command argument, expanding filenames in a command that otherwise
-/// doesn't expand filenames, etc.
+/// doesn't expand filenames, etc. Command arguments may also be Number, Boolean or String.
+///
+/// The first argument may also be used instead of count for commands that support it in order to
+/// make their usage simpler with |vim.cmd()|. For example, instead of
+/// `vim.cmd.bdelete{ count = 2 }`, you may do `vim.cmd.bdelete(2)`.
///
/// On execution error: fails with VimL error, updates v:errmsg.
///
@@ -310,8 +313,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
char *cmdline = NULL;
char *cmdname = NULL;
- ArrayOf(String) args;
- size_t argc = 0;
+ ArrayOf(String) args = ARRAY_DICT_INIT;
String retv = (String)STRING_INIT;
@@ -383,48 +385,70 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
if (cmd->args.type != kObjectTypeArray) {
VALIDATION_ERROR("'args' must be an Array");
}
- // Check if every argument is valid
+
+ // Process all arguments. Convert non-String arguments to String and check if String arguments
+ // have non-whitespace characters.
for (size_t i = 0; i < cmd->args.data.array.size; i++) {
Object elem = cmd->args.data.array.items[i];
- if (elem.type != kObjectTypeString) {
- VALIDATION_ERROR("Command argument must be a String");
- } else if (string_iswhite(elem.data.string)) {
- VALIDATION_ERROR("Command argument must have non-whitespace characters");
+ char *data_str;
+
+ switch (elem.type) {
+ case kObjectTypeBoolean:
+ data_str = xcalloc(2, sizeof(char));
+ data_str[0] = elem.data.boolean ? '1' : '0';
+ data_str[1] = '\0';
+ break;
+ case kObjectTypeBuffer:
+ case kObjectTypeWindow:
+ case kObjectTypeTabpage:
+ case kObjectTypeInteger:
+ data_str = xcalloc(NUMBUFLEN, sizeof(char));
+ snprintf(data_str, NUMBUFLEN, "%" PRId64, elem.data.integer);
+ break;
+ case kObjectTypeString:
+ if (string_iswhite(elem.data.string)) {
+ VALIDATION_ERROR("String command argument must have at least one non-whitespace "
+ "character");
+ }
+ data_str = xstrndup(elem.data.string.data, elem.data.string.size);
+ break;
+ default:
+ VALIDATION_ERROR("Invalid type for command argument");
+ break;
}
+
+ ADD(args, STRING_OBJ(cstr_as_string(data_str)));
}
- argc = cmd->args.data.array.size;
bool argc_valid;
// Check if correct number of arguments is used.
switch (ea.argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case EX_EXTRA | EX_NOSPC | EX_NEEDARG:
- argc_valid = argc == 1;
+ argc_valid = args.size == 1;
break;
case EX_EXTRA | EX_NOSPC:
- argc_valid = argc <= 1;
+ argc_valid = args.size <= 1;
break;
case EX_EXTRA | EX_NEEDARG:
- argc_valid = argc >= 1;
+ argc_valid = args.size >= 1;
break;
case EX_EXTRA:
argc_valid = true;
break;
default:
- argc_valid = argc == 0;
+ argc_valid = args.size == 0;
break;
}
if (!argc_valid) {
VALIDATION_ERROR("Incorrect number of arguments supplied");
}
-
- args = cmd->args.data.array;
}
// Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()`
// since it only ever checks the first argument.
- set_cmd_addr_type(&ea, argc > 0 ? args.items[0].data.string.data : NULL);
+ set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL);
if (HAS_KEY(cmd->range)) {
if (!(ea.argt & EX_RANGE)) {
@@ -628,7 +652,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
// Finally, build the command line string that will be stored inside ea.cmdlinep.
// This also sets the values of ea.cmd, ea.arg, ea.args and ea.arglens.
- build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc);
+ build_cmdline_str(&cmdline, &ea, &cmdinfo, args);
ea.cmdlinep = &cmdline;
garray_T capture_local;
@@ -684,6 +708,7 @@ clear_ga:
ga_clear(&capture_local);
}
end:
+ api_free_array(args);
xfree(cmdline);
xfree(cmdname);
xfree(ea.args);
@@ -713,8 +738,9 @@ static bool string_iswhite(String str)
/// Build cmdline string for command, used by `nvim_cmd()`.
static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo,
- ArrayOf(String) args, size_t argc)
+ ArrayOf(String) args)
{
+ size_t argc = args.size;
StringBuilder cmdline = KV_INITIAL_VALUE;
kv_resize(cmdline, 32); // Make it big enough to handle most typical commands
@@ -800,7 +826,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
}
eap->argc = argc;
- eap->arglens = xcalloc(argc, sizeof(size_t));
+ eap->arglens = eap->argc > 0 ? xcalloc(argc, sizeof(size_t)) : NULL;
size_t argstart_idx = cmdline.size;
for (size_t i = 0; i < argc; i++) {
String s = args.items[i].data.string;
@@ -815,7 +841,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
// Now that all the arguments are appended, use the command index and argument indices to set the
// values of eap->cmd, eap->arg and eap->args.
eap->cmd = cmdline.items + cmdname_idx;
- eap->args = xcalloc(argc, sizeof(char *));
+ eap->args = eap->argc > 0 ? xcalloc(argc, sizeof(char *)) : NULL;
size_t offset = argstart_idx;
for (size_t i = 0; i < argc; i++) {
offset++; // Account for space
@@ -832,13 +858,12 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
// Replace, :make and :grep with 'makeprg' and 'grepprg'.
char *p = replace_makeprg(eap, eap->arg, cmdlinep);
if (p != eap->arg) {
- // If replace_makeprg modified the cmdline string, correct the argument pointers.
+ // If replace_makeprg() modified the cmdline string, correct the eap->arg pointer.
eap->arg = p;
- // We can only know the position of the first argument because the argument list can be used
- // multiple times in makeprg / grepprg.
- if (argc >= 1) {
- eap->args[0] = p;
- }
+ // This cannot be a user command, so eap->args will not be used.
+ XFREE_CLEAR(eap->args);
+ XFREE_CLEAR(eap->arglens);
+ eap->argc = 0;
}
}
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index edcea52838..3b1b470629 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -389,11 +389,11 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// - virt_text : virtual text to link to this mark.
/// A list of [text, highlight] tuples, each representing a
/// text chunk with specified highlight. `highlight` element
-/// can either be a a single highlight group, or an array of
+/// can either be a single highlight group, or an array of
/// multiple highlight groups that will be stacked
/// (highest priority last). A highlight group can be supplied
/// either as a string or as an integer, the latter which
-/// can be obtained using |nvim_get_hl_id_by_name|.
+/// can be obtained using |nvim_get_hl_id_by_name()|.
/// - virt_text_pos : position of virtual text. Possible values:
/// - "eol": right after eol character (default)
/// - "overlay": display over the specified column, without
@@ -430,7 +430,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// column of the window, bypassing
/// sign and number columns.
///
-/// - ephemeral : for use with |nvim_set_decoration_provider|
+/// - ephemeral : for use with |nvim_set_decoration_provider()|
/// callbacks. The mark will only be used for the current
/// redraw cycle, and not be permantently stored in the
/// buffer.
@@ -958,7 +958,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// being triggered during the redraw code.
///
/// The expected usage is to set extmarks for the currently
-/// redrawn buffer. |nvim_buf_set_extmark| can be called to add marks
+/// redrawn buffer. |nvim_buf_set_extmark()| can be called to add marks
/// on a per-window or per-lines basis. Use the `ephemeral` key to only
/// use the mark for the current screen redraw (the callback will be called
/// again for the next redraw ).
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 867584dd71..ec1f19cf6a 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -147,7 +147,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
/// @param name Option name
/// @param value New option value
/// @param opts Optional parameters
-/// - scope: One of 'global' or 'local'. Analogous to
+/// - scope: One of "global" or "local". Analogous to
/// |:setglobal| and |:setlocal|, respectively.
/// - win: |window-ID|. Used for setting window local option.
/// - buf: Buffer number. Used for setting buffer local option.
@@ -202,7 +202,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error
/// 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|.
+/// dictionaries as detailed at |nvim_get_option_info()|.
///
/// @return dictionary of all options
Dictionary nvim_get_all_options_info(Error *err)
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index b888d09343..73b5489d5c 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -218,6 +218,8 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
+ bool watched = tv_dict_is_watched(dict);
+
if (del) {
// Delete the key
if (di == NULL) {
@@ -225,6 +227,10 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
api_set_error(err, kErrorTypeValidation, "Key not found: %s",
key.data);
} else {
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv);
+ }
// Return the old value
if (retval) {
rv = vim_to_object(&di->di_tv);
@@ -241,11 +247,16 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
return rv;
}
+ typval_T oldtv = TV_INITIAL_VALUE;
+
if (di == NULL) {
// Need to create an entry
di = tv_dict_item_alloc_len(key.data, key.size);
tv_dict_add(dict, di);
} else {
+ if (watched) {
+ tv_copy(&di->di_tv, &oldtv);
+ }
// Return the old value
if (retval) {
rv = vim_to_object(&di->di_tv);
@@ -255,6 +266,13 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
// Update the value
tv_copy(&tv, &di->di_tv);
+
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, &tv, &oldtv);
+ tv_clear(&oldtv);
+ }
+
// Clear the temporary variable
tv_clear(&tv);
}
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 45c20d07e1..e6d8cb2fdb 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -453,7 +453,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, I
}
}
-/// Tells Nvim the number of elements displaying in the popumenu, to decide
+/// Tells Nvim the number of elements displaying in the popupmenu, to decide
/// <PageUp> and <PageDown> movement.
///
/// @param channel_id
@@ -483,7 +483,7 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
ui->pum_nlines = (int)height;
}
-/// Tells Nvim the geometry of the popumenu, to align floating windows with an
+/// Tells Nvim the geometry of the popupmenu, to align floating windows with an
/// external popup menu.
///
/// Note that this method is not to be confused with |nvim_ui_pum_set_height()|,
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ad9ed72f43..d65127e406 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -160,8 +160,8 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err)
/// - nocombine: boolean
/// - link: name of another highlight group to link to, see |:hi-link|.
/// - default: Don't override existing definition |:hi-default|
-/// - ctermfg: Sets foreground of cterm color |highlight-ctermfg|
-/// - ctermbg: Sets background of cterm color |highlight-ctermbg|
+/// - ctermfg: Sets foreground of cterm color |ctermfg|
+/// - ctermbg: Sets background of cterm color |ctermbg|
/// - cterm: cterm attribute map, like |highlight-args|. If not set,
/// cterm attributes will match those from the attribute map
/// documented above.
@@ -185,7 +185,7 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
}
/// Set active namespace for highlights. This can be set for a single window,
-/// see |nvim_win_set_hl_ns|.
+/// see |nvim_win_set_hl_ns()|.
///
/// @param ns_id the namespace to use
/// @param[out] err Error details, if any
@@ -205,7 +205,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err)
/// Set active namespace for highlights while redrawing.
///
/// This function meant to be called while redrawing, primarily from
-/// |nvim_set_decoration_provider| on_win and on_line callbacks, which
+/// |nvim_set_decoration_provider()| on_win and on_line callbacks, which
/// are allowed to change the namespace during a redraw cycle.
///
/// @param ns_id the namespace to activate
@@ -523,7 +523,7 @@ Array nvim__runtime_inspect(void)
/// Find files in runtime directories
///
-/// 'name' can contain wildcards. For example
+/// "name" can contain wildcards. For example
/// nvim_get_runtime_file("colors/*.vim", true) will return all color
/// scheme files. Always use forward slashes (/) in the search pattern for
/// subdirectories regardless of platform.
@@ -964,7 +964,7 @@ fail:
/// mode. Note: keypresses are sent raw as they would be to the pty
/// master end. For instance, a carriage return is sent
/// as a "\r", not as a "\n". |textlock| applies. It is possible
-/// to call |nvim_chan_send| directly in the callback however.
+/// to call |nvim_chan_send()| directly in the callback however.
/// ["input", term, bufnr, data]
/// @param[out] err Error details, if any
/// @return Channel id, or 0 on error
@@ -1452,7 +1452,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// @param rhs Right-hand-side |{rhs}| of the mapping.
/// @param opts Optional parameters map: keys are |:map-arguments|, values are booleans (default
/// false). Accepts all |:map-arguments| as keys excluding |<buffer>| but including
-/// |noremap| and "desc". Unknown key is an error.
+/// |:noremap| and "desc". Unknown key is an error.
/// "desc" can be used to give a description to the mapping.
/// When called from Lua, also accepts a "callback" key that takes a Lua function to
/// call when the mapping is executed.
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 96c560efa1..636b9566ce 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -109,7 +109,7 @@
/// is changed to `auto` and 'colorcolumn' is cleared. The
/// end-of-buffer region is hidden by setting `eob` flag of
/// 'fillchars' to a space char, and clearing the
-/// |EndOfBuffer| region in 'winhighlight'.
+/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: Style of (optional) window border. This can either be a string
/// or an array. The string values are
/// - "none": No border (default).
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 5203003369..aaff00d640 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -340,7 +340,7 @@ Boolean nvim_win_is_valid(Window window)
///
/// Like |:hide| the buffer becomes hidden unless another window is editing it,
/// or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to |:close| or
-/// |nvim_win_close|, which will close the buffer.
+/// |nvim_win_close()|, which will close the buffer.
///
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
@@ -430,7 +430,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
/// Set highlight namespace for a window. This will use highlights defined in
/// this namespace, but fall back to global highlights (ns=0) when missing.
///
-/// This takes predecence over the 'winhighlight' option.
+/// This takes precedence over the 'winhighlight' option.
///
/// @param ns_id the namespace to use
/// @param[out] err Error details, if any
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index c18a8209cf..a8834b85aa 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -618,7 +618,7 @@ struct file_buffer {
bool b_u_synced; // entry lists are synced
long b_u_seq_last; // last used undo sequence number
long b_u_save_nr_last; // counter for last file write
- long b_u_seq_cur; // hu_seq of header below which we are now
+ long b_u_seq_cur; // uh_seq of header below which we are now
time_t b_u_time_cur; // uh_time of header below which we are now
long b_u_save_nr_cur; // file write nr after which we are now
diff --git a/src/nvim/change.c b/src/nvim/change.c
index ab550259c8..c9e57ab88f 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -999,7 +999,7 @@ int copy_indent(int size, char *src)
/// "second_line_indent": indent for after ^^D in Insert mode or if flag
/// OPENLINE_COM_LIST
/// "did_do_comment" is set to true when intentionally putting the comment
-/// leader in fromt of the new line.
+/// leader in front of the new line.
///
/// @param dir FORWARD or BACKWARD
///
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 0cc2189948..f5db03b0b4 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -650,7 +650,7 @@ static inline unsigned nr2hex(unsigned n)
///
/// @param b
///
-/// @reeturn Number of display cells.
+/// @return Number of display cells.
int byte2cells(int b)
FUNC_ATTR_PURE
{
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 8adeb19082..3e0cf82740 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -128,7 +128,7 @@ void do_debug(char *cmd)
ignore_script = true;
}
- // don't debug any function call, e.g. from an expresion mapping
+ // don't debug any function call, e.g. from an expression mapping
n = debug_break_level;
debug_break_level = -1;
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index c95f3f3550..fdf70a081c 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1965,7 +1965,8 @@ win_update_start:
if (mid_end >= row) {
lastline = MIN(lastline, mid_start);
}
- if (mod_bot > buf->b_ml.ml_line_count + 1) {
+ // if (mod_bot > buf->b_ml.ml_line_count + 1) {
+ if (mod_bot > buf->b_ml.ml_line_count) {
lastline = 0;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index c2a7b6bba5..6eaf3d1f5e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -3659,7 +3659,6 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate)
FUNC_ATTR_NONNULL_ARG(1)
{
- bool working = (**arg == '+'); // has("+option")
int opt_flags;
// Isolate the option name and find its value.
@@ -3704,10 +3703,6 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
rettv->v_type = VAR_STRING;
rettv->vval.v_string = stringval;
}
- } else if (working && (opt_type == gov_hidden_bool
- || opt_type == gov_hidden_number
- || opt_type == gov_hidden_string)) {
- ret = FAIL;
}
*option_end = c; // put back for error messages
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 9ba2ce2365..f2ef8e5cdd 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -1938,9 +1938,14 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xfree(exp);
}
} else if (*p == '&' || *p == '+') { // Option.
- n = (get_option_tv(&p, NULL, true) == OK);
- if (*skipwhite(p) != NUL) {
- n = false; // Trailing garbage.
+ bool working = (*p == '+'); // whether option needs to be working
+ int opt_flags;
+
+ if (find_option_end(&p, &opt_flags) != NULL) {
+ int opt_idx = findoption(p);
+ n = (opt_idx >= 0 && (!working || get_varp_scope(get_option(opt_idx), opt_flags) != NULL));
+ } else {
+ n = false;
}
} else if (*p == '*') { // Internal or user defined function.
n = function_exists(p + 1, false);
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index f9aed7a966..961c963170 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -1249,14 +1249,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
item_compare_func_ptr = item_compare_keeping_zero;
}
- int idx = 0;
for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l))
; li != NULL;) {
listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li);
if (item_compare_func_ptr(&prev_li, &li) == 0) {
li = tv_list_item_remove(l, li);
} else {
- idx++;
li = TV_LIST_ITEM_NEXT(l, li);
}
if (info.item_compare_func_err) { // -V547
@@ -1781,7 +1779,7 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T
tv_dict_add(argv[2].vval.v_dict, v);
}
- if (oldtv) {
+ if (oldtv && oldtv->v_type != VAR_UNKNOWN) {
dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old"));
tv_copy(oldtv, &v->di_tv);
tv_dict_add(argv[2].vval.v_dict, v);
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 1c07fc4d45..4d7214205d 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -1348,12 +1348,8 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
}
if (watched) {
- if (oldtv.v_type == VAR_UNKNOWN) {
- tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL);
- } else {
- tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv);
- tv_clear(&oldtv);
- }
+ tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv);
+ tv_clear(&oldtv);
}
if (is_const) {
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 085948f7b1..987fb439d7 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1339,6 +1339,20 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate)
|| ascii_iswhite(*p))) {
long n = getdigits_long(&eap->arg, false, -1);
eap->arg = skipwhite(eap->arg);
+
+ if (eap->args != NULL) {
+ assert(eap->argc > 0 && eap->arg >= eap->args[0]);
+ // If eap->arg is still pointing to the first argument, just make eap->args[0] point to the
+ // same location. This is needed for usecases like vim.cmd.sleep('10m'). If eap->arg is
+ // pointing outside the first argument, shift arguments by 1.
+ if (eap->arg < eap->args[0] + eap->arglens[0]) {
+ eap->arglens[0] -= (size_t)(eap->arg - eap->args[0]);
+ eap->args[0] = eap->arg;
+ } else {
+ shift_cmd_args(eap);
+ }
+ }
+
if (n <= 0 && (eap->argt & EX_ZEROR) == 0) {
if (errormsg != NULL) {
*errormsg = _(e_zerocount);
@@ -1512,6 +1526,30 @@ end:
return retval;
}
+// Shift Ex-command arguments to the right.
+static void shift_cmd_args(exarg_T *eap)
+{
+ assert(eap->args != NULL && eap->argc > 0);
+
+ char **oldargs = eap->args;
+ size_t *oldarglens = eap->arglens;
+
+ eap->argc--;
+ eap->args = eap->argc > 0 ? xcalloc(eap->argc, sizeof(char *)) : NULL;
+ eap->arglens = eap->argc > 0 ? xcalloc(eap->argc, sizeof(size_t)) : NULL;
+
+ for (size_t i = 0; i < eap->argc; i++) {
+ eap->args[i] = oldargs[i + 1];
+ eap->arglens[i] = oldarglens[i + 1];
+ }
+
+ // If there are no arguments, make eap->arg point to the end of string.
+ eap->arg = (eap->argc > 0 ? eap->args[0] : (oldargs[0] + oldarglens[0]));
+
+ xfree(oldargs);
+ xfree(oldarglens);
+}
+
static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
{
// If filename expansion is enabled, expand filenames
@@ -1551,15 +1589,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
eap->args[0] + eap->arglens[0],
(eap->argt & EX_BUFUNL) != 0, false, false);
eap->addr_count = 1;
- // Shift each argument by 1
- for (size_t i = 0; i < eap->argc - 1; i++) {
- eap->args[i] = eap->args[i + 1];
- }
- // Make the last argument point to the NUL terminator at the end of string
- eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1];
- eap->argc -= 1;
-
- eap->arg = eap->args[0];
+ shift_cmd_args(eap);
}
if (eap->line2 < 0) { // failed
return FAIL;
@@ -1658,6 +1688,11 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
(void)hasFolding(eap->line2, NULL, &eap->line2);
}
+ // Use first argument as count when possible
+ if (parse_count(eap, &errormsg, true) == FAIL) {
+ goto end;
+ }
+
// Execute the command
execute_cmd0(&retv, eap, &errormsg, preview);
@@ -3887,7 +3922,7 @@ static char *repl_cmdline(exarg_T *eap, char *src, size_t srclen, char *repl, ch
} else {
// Otherwise, argument gets shifted alongside the replaced text.
// The amount of the shift is equal to the difference of the old and new string length.
- eap->args[j] = new_cmdline + (eap->args[j] - *cmdlinep) + (len - srclen);
+ eap->args[j] = new_cmdline + ((eap->args[j] - *cmdlinep) + (ptrdiff_t)(len - srclen));
}
}
@@ -5867,7 +5902,7 @@ static void ex_undo(exarg_T *eap)
{
if (eap->addr_count != 1) {
if (eap->forceit) {
- u_undo_and_forget(1); // :undo!
+ u_undo_and_forget(1, true); // :undo!
} else {
u_undo(1); // :undo
}
@@ -5894,7 +5929,7 @@ static void ex_undo(exarg_T *eap)
emsg(_(e_undobang_cannot_redo_or_move_branch));
return;
}
- u_undo_and_forget(count);
+ u_undo_and_forget(count, true);
} else { // :undo 123
undo_time(step, false, false, true);
}
@@ -6088,7 +6123,7 @@ static void ex_redrawstatus(exarg_T *eap)
} else {
status_redraw_curbuf();
}
- if (msg_scrolled && (State & MODE_CMDLINE)) {
+ if (msg_scrolled && !msg_use_msgsep() && (State & MODE_CMDLINE)) {
return; // redraw later
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 2d39ced582..4b54b58ac1 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -136,6 +136,7 @@ typedef struct cmdpreview_win_info {
typedef struct cmdpreview_buf_info {
buf_T *buf;
+ bool save_b_u_synced;
time_t save_b_u_time_cur;
long save_b_u_seq_cur;
u_header_T *save_b_u_newhead;
@@ -773,11 +774,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
// Redraw the statusline in case it uses the current mode using the mode()
// function.
- if (!cmd_silent && msg_scrolled == 0) {
+ if (!cmd_silent && (msg_scrolled == 0 || msg_use_msgsep())) {
bool found_one = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (*p_stl != NUL || *wp->w_p_stl != NUL) {
+ if (*p_stl != NUL || *wp->w_p_stl != NUL || *p_wbr != NUL || *wp->w_p_wbr != NUL) {
wp->w_redr_status = true;
found_one = true;
}
@@ -2131,6 +2132,7 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
CpBufInfo cp_bufinfo;
cp_bufinfo.buf = buf;
+ cp_bufinfo.save_b_u_synced = buf->b_u_synced;
cp_bufinfo.save_b_u_time_cur = buf->b_u_time_cur;
cp_bufinfo.save_b_u_seq_cur = buf->b_u_seq_cur;
cp_bufinfo.save_b_u_newhead = buf->b_u_newhead;
@@ -2168,6 +2170,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
cmdmod.cmod_split = 0; // Disable :leftabove/botright modifiers
cmdmod.cmod_tab = 0; // Disable :tab modifier
cmdmod.cmod_flags |= CMOD_NOSWAPFILE; // Disable swap for preview buffer
+
+ u_sync(true);
}
// Restore the state of buffers and windows before command preview.
@@ -2190,7 +2194,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo)
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
// Undo invisibly. This also moves the cursor!
- if (!u_undo_and_forget(count)) {
+ if (!u_undo_and_forget(count, false)) {
abort();
}
aucmd_restbuf(&aco);
@@ -2200,6 +2204,11 @@ static void cmdpreview_restore_state(CpInfo *cpinfo)
buf->b_u_newhead = cp_bufinfo.save_b_u_newhead;
buf->b_u_time_cur = cp_bufinfo.save_b_u_time_cur;
}
+
+ if (buf->b_u_curhead == NULL) {
+ buf->b_u_synced = cp_bufinfo.save_b_u_synced;
+ }
+
if (cp_bufinfo.save_changedtick != buf_get_changedtick(buf)) {
buf_set_changedtick(buf, cp_bufinfo.save_changedtick);
}
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index fd0acce25f..ef66e2d355 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2104,7 +2104,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
} else {
keylen = 0;
}
- if (keylen == 0) { // no simplication has been done
+ if (keylen == 0) { // no simplification has been done
// If there was no mapping at all use the character from the
// typeahead buffer right here.
if (mp == NULL) {
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 3d0ab192b9..32d67621db 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -265,7 +265,7 @@ void hash_unlock(hashtab_T *ht)
hash_may_resize(ht, 0);
}
-/// Resize hastable (new size can be given or automatically computed).
+/// Resize hashtable (new size can be given or automatically computed).
///
/// @param minitems Minimum number of items the new table should hold.
/// If zero, new size will depend on currently used items:
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index fed39c6ed7..3508560e20 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -2034,7 +2034,7 @@ void highlight_changed(void)
}
}
- // sentinel value. used when no hightlight namespace is active
+ // sentinel value. used when no highlight namespace is active
highlight_attr[HLF_COUNT] = 0;
//
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index a23fa22da2..bc31d702f4 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -649,7 +649,7 @@ static char *cs_create_cmd(char *csoption, char *pattern)
return NULL;
}
- // Skip white space before the patter, except for text and pattern search,
+ // Skip white space before the pattern, except for text and pattern search,
// they may want to use the leading white space.
pat = pattern;
if (search != 4 && search != 6) {
diff --git a/src/nvim/input.c b/src/nvim/input.c
index 0aa9feaca3..681d9d5f9c 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -83,7 +83,6 @@ int get_keystroke(MultiQueue *events)
int len = 0;
int n;
int save_mapped_ctrl_c = mapped_ctrl_c;
- int waited = 0;
mapped_ctrl_c = 0; // mappings are not used here
for (;;) {
@@ -110,10 +109,8 @@ int get_keystroke(MultiQueue *events)
// Replace zero and K_SPECIAL by a special key code.
n = fix_input_buffer(buf + len, n);
len += n;
- waited = 0;
- } else if (len > 0) {
- waited++; // keep track of the waiting time
}
+
if (n > 0) { // found a termcode: adjust length
len = n;
}
diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c
index 9ec37fd564..61dc2ac035 100644
--- a/src/nvim/keycodes.c
+++ b/src/nvim/keycodes.c
@@ -861,10 +861,9 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
/// @param[in] from What characters to replace.
/// @param[in] from_len Length of the "from" argument.
/// @param[out] bufp Location where results were saved in case of success (allocated).
-/// if *bufp is non-NULL, it will be used directly. it is
-/// assumed to be 128 bytes long (enough for transcoding LHS
-/// of mapping)
-/// Will be set to NULL in case of failure.
+/// If `*bufp` is non-NULL, it will be used directly,
+/// and is assumed to be 128 bytes long (enough for transcoding LHS of mapping),
+/// and will be set to NULL in case of failure.
/// @param[in] flags REPTERM_FROM_PART see above
/// REPTERM_DO_LT also translate <lt>
/// REPTERM_NO_SPECIAL do not accept <key> notation
@@ -872,7 +871,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
/// @param[out] did_simplify set when some <C-H> code was simplied, unless it is NULL.
/// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS.
///
-/// @return Pointer to an allocated memory, which is also saved to "bufp".
+/// @return The same as what `*bufp` is set to.
char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp,
const int flags, bool *const did_simplify, const int cpo_flags)
FUNC_ATTR_NONNULL_ARG(1, 3)
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 6063414a02..f3821f149a 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -2036,7 +2036,8 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
}
lua_setfield(lstate, -2, "fargs");
- lua_pushstring(lstate, (const char *)&eap->regname);
+ char reg[2] = { (char)eap->regname, NUL };
+ lua_pushstring(lstate, reg);
lua_setfield(lstate, -2, "reg");
lua_pushinteger(lstate, eap->addr_count);
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index 9b1890403e..498f956ed9 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -369,12 +369,19 @@ int nlua_setvar(lua_State *lstate)
return 0;
}
+ bool watched = tv_dict_is_watched(dict);
+
if (del) {
// Delete the key
if (di == NULL) {
// Doesn't exist, nothing to do
return 0;
} else {
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv);
+ }
+
// Delete the entry
tv_dict_item_remove(dict, di);
}
@@ -388,17 +395,29 @@ int nlua_setvar(lua_State *lstate)
return luaL_error(lstate, "Couldn't convert lua value");
}
+ typval_T oldtv = TV_INITIAL_VALUE;
+
if (di == NULL) {
// Need to create an entry
di = tv_dict_item_alloc_len(key.data, key.size);
tv_dict_add(dict, di);
} else {
+ if (watched) {
+ tv_copy(&di->di_tv, &oldtv);
+ }
// Clear the old value
tv_clear(&di->di_tv);
}
// Update the value
tv_copy(&tv, &di->di_tv);
+
+ // Notify watchers
+ if (watched) {
+ tv_dict_watcher_notify(dict, key.data, &tv, &oldtv);
+ tv_clear(&oldtv);
+ }
+
// Clear the temporary variable
tv_clear(&tv);
}
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 64cace9ab4..79b11eca4a 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -1369,7 +1369,7 @@ static int query_inspect(lua_State *L)
lua_rawseti(L, -2, nextitem++); // [retval, patterns, pat, pred]
}
// last predicate should have ended with TypeDone
- lua_pop(L, 1); // [retval, patters, pat]
+ lua_pop(L, 1); // [retval, patterns, pat]
lua_rawseti(L, -2, (int)i + 1); // [retval, patterns]
}
lua_setfield(L, -2, "patterns"); // [retval]
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 6267e1c875..001bbf7e48 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -890,7 +890,7 @@ theend:
///
/// @param maptype MAPTYPE_MAP for |:map|
/// MAPTYPE_UNMAP for |:unmap|
-/// MAPTYPE_NOREMAP for |noremap|.
+/// MAPTYPE_NOREMAP for |:noremap|.
/// @param arg C-string containing the arguments of the map/abbrev
/// command, i.e. everything except the initial `:[X][nore]map`.
/// - Cannot be a read-only string; it will be modified.
diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h
index 182d1a48cb..156187b5d8 100644
--- a/src/nvim/mapping.h
+++ b/src/nvim/mapping.h
@@ -9,7 +9,7 @@
/// All possible |:map-arguments| usable in a |:map| command.
///
/// The <special> argument has no effect on mappings and is excluded from this
-/// struct declaration. |noremap| is included, since it behaves like a map
+/// struct declaration. |:noremap| is included, since it behaves like a map
/// argument when used in a mapping.
///
/// @see mapblock_T
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 0b9cbfe474..fd20d9dd81 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1399,12 +1399,15 @@ void msg_start(void)
msg_clr_eos();
}
+ // if cmdheight=0, we need to scroll in the first line of msg_grid upon the screen
+ if (p_ch == 0 && !ui_has(kUIMessages) && !msg_scrolled) {
+ msg_grid_validate();
+ msg_scroll_up(false, true);
+ msg_scrolled++;
+ cmdline_row = Rows - 1;
+ }
+
if (!msg_scroll && full_screen) { // overwrite last message
- if (cmdline_row >= Rows && !ui_has(kUIMessages)) {
- msg_scroll_up(false, true);
- msg_scrolled++;
- cmdline_row = Rows - 1;
- }
msg_row = cmdline_row;
msg_col = cmdmsg_rl ? Columns - 1 : 0;
} else if (msg_didout || (p_ch == 0 && !ui_has(kUIMessages))) { // start message on next line
@@ -2312,7 +2315,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse)
if (t_col > 0) {
t_puts(&t_col, t_s, s, attr);
}
- if (p_more && !recurse) {
+ if (p_more && !recurse && !(s == sb_str + 1 && *sb_str == '\n')) {
store_sb_text((char **)&sb_str, (char *)s, attr, &sb_col, false);
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 5b67f0e471..e7d0b171f6 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -106,30 +106,6 @@ static char e_number_required_after_equal[]
static char e_preview_window_already_exists[]
= N_("E590: A preview window already exists");
-// The options that are local to a window or buffer have "indir" set to one of
-// these values. Special values:
-// PV_NONE: global option.
-// PV_WIN is added: window-local option
-// PV_BUF is added: buffer-local option
-// PV_BOTH is added: global option which also has a local value.
-#define PV_BOTH 0x1000
-#define PV_WIN 0x2000
-#define PV_BUF 0x4000
-#define PV_MASK 0x0fff
-#define OPT_WIN(x) (idopt_T)(PV_WIN + (int)(x))
-#define OPT_BUF(x) (idopt_T)(PV_BUF + (int)(x))
-#define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x))
-
-// WV_ and BV_ values get typecasted to this for the "indir" field
-typedef enum {
- PV_NONE = 0,
- PV_MAXVAL = 0xffff, // to avoid warnings for value out of range
-} idopt_T;
-
-// Options local to a window have a value local to a buffer and global to all
-// buffers. Indicate this by setting "var" to VAR_WIN.
-#define VAR_WIN ((char_u *)-1)
-
static char *p_term = NULL;
static char *p_ttytype = NULL;
@@ -147,19 +123,6 @@ static long p_tw_nopaste;
static long p_wm_nopaste;
static char *p_vsts_nopaste;
-typedef struct vimoption {
- char *fullname; // full option name
- char *shortname; // permissible abbreviation
- uint32_t flags; // see below
- char_u *var; // global option: pointer to variable;
- // window-local option: VAR_WIN;
- // buffer-local option: global value
- idopt_T indir; // global option: PV_NONE;
- // local option: indirect option index
- char *def_val; // default values for variable (neovim!!)
- LastSet last_set; // script in which the option was last set
-} vimoption_T;
-
// options[] is initialized here.
// The order of the options MUST be alphabetic for ":set all" and findoption().
// All option names MUST start with a lowercase letter (for findoption()).
@@ -3047,47 +3010,10 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return rv;
}
-/// Return the flags for the option at 'opt_idx'.
-uint32_t get_option_flags(int opt_idx)
-{
- return options[opt_idx].flags;
-}
-
-/// Set a flag for the option at 'opt_idx'.
-void set_option_flag(int opt_idx, uint32_t flag)
-{
- options[opt_idx].flags |= flag;
-}
-
-/// Clear a flag for the option at 'opt_idx'.
-void clear_option_flag(int opt_idx, uint32_t flag)
-{
- options[opt_idx].flags &= ~flag;
-}
-
-/// Returns true if the option at 'opt_idx' is a global option
-bool is_global_option(int opt_idx)
-{
- return options[opt_idx].indir == PV_NONE;
-}
-
-/// Returns true if the option at 'opt_idx' is a global option which also has a
-/// local value.
-int is_global_local_option(int opt_idx)
+// Return information for option at 'opt_idx'
+vimoption_T *get_option(int opt_idx)
{
- return options[opt_idx].indir & PV_BOTH;
-}
-
-/// Returns true if the option at 'opt_idx' is a window-local option
-bool is_window_local_option(int opt_idx)
-{
- return options[opt_idx].var == VAR_WIN;
-}
-
-/// Returns true if the option at 'opt_idx' is a hidden option
-bool is_hidden_option(int opt_idx)
-{
- return options[opt_idx].var == NULL;
+ return &options[opt_idx];
}
/// Set the value of an option
@@ -3761,7 +3687,7 @@ void unset_global_local_option(char *name, void *from)
}
/// Get pointer to option variable, depending on local or global scope.
-static char *get_varp_scope(vimoption_T *p, int opt_flags)
+char *get_varp_scope(vimoption_T *p, int opt_flags)
{
if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
@@ -3833,13 +3759,6 @@ static char *get_varp_scope(vimoption_T *p, int opt_flags)
return (char *)get_varp(p);
}
-/// Get pointer to option variable at 'opt_idx', depending on local or global
-/// scope.
-char *get_option_varp_scope(int opt_idx, int opt_flags)
-{
- return get_varp_scope(&(options[opt_idx]), opt_flags);
-}
-
/// Get pointer to option variable.
static char_u *get_varp(vimoption_T *p)
{
@@ -4149,18 +4068,6 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_wm);
}
-/// Return a pointer to the variable for option at 'opt_idx'
-char_u *get_option_var(int opt_idx)
-{
- return options[opt_idx].var;
-}
-
-/// Return the full name of the option at 'opt_idx'
-char *get_option_fullname(int opt_idx)
-{
- return options[opt_idx].fullname;
-}
-
/// Get the value of 'equalprg', either the buffer-local one or the global one.
char_u *get_equalprg(void)
{
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index e8cf338cf1..e27607d7a8 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -990,4 +990,41 @@ typedef struct {
uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT.
} LastSet;
+// WV_ and BV_ values get typecasted to this for the "indir" field
+typedef enum {
+ PV_NONE = 0,
+ PV_MAXVAL = 0xffff, // to avoid warnings for value out of range
+} idopt_T;
+
+typedef struct vimoption {
+ char *fullname; // full option name
+ char *shortname; // permissible abbreviation
+ uint32_t flags; // see below
+ char_u *var; // global option: pointer to variable;
+ // window-local option: VAR_WIN;
+ // buffer-local option: global value
+ idopt_T indir; // global option: PV_NONE;
+ // local option: indirect option index
+ char *def_val; // default values for variable (neovim!!)
+ LastSet last_set; // script in which the option was last set
+} vimoption_T;
+
+// The options that are local to a window or buffer have "indir" set to one of
+// these values. Special values:
+// PV_NONE: global option.
+// PV_WIN is added: window-local option
+// PV_BUF is added: buffer-local option
+// PV_BOTH is added: global option which also has a local value.
+#define PV_BOTH 0x1000
+#define PV_WIN 0x2000
+#define PV_BUF 0x4000
+#define PV_MASK 0x0fff
+#define OPT_WIN(x) (idopt_T)(PV_WIN + (int)(x))
+#define OPT_BUF(x) (idopt_T)(PV_BUF + (int)(x))
+#define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x))
+
+// Options local to a window have a value local to a buffer and global to all
+// buffers. Indicate this by setting "var" to VAR_WIN.
+#define VAR_WIN ((char_u *)-1)
+
#endif // NVIM_OPTION_DEFS_H
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 7278b1a12d..aff88a755b 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -178,7 +178,7 @@ void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval, char *o
set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
}
- apply_autocmds(EVENT_OPTIONSET, get_option_fullname(opt_idx), NULL, false, NULL);
+ apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL);
reset_v_option_vars();
}
}
@@ -280,19 +280,19 @@ void check_string_option(char **pp)
/// Set global value for string option when it's a local option.
///
-/// @param opt_idx option index
+/// @param opt option
/// @param varp pointer to option variable
-static void set_string_option_global(int opt_idx, char **varp)
+static void set_string_option_global(vimoption_T *opt, char **varp)
{
char **p;
// the global value is always allocated
- if (is_window_local_option(opt_idx)) {
+ if (opt->var == VAR_WIN) {
p = (char **)GLOBAL_WO(varp);
} else {
- p = (char **)get_option_var(opt_idx);
+ p = (char **)opt->var;
}
- if (!is_global_option(opt_idx) && p != varp) {
+ if (opt->indir != PV_NONE && p != varp) {
char *s = xstrdup(*varp);
free_string_option(*p);
*p = s;
@@ -324,30 +324,32 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in
}
}
- if (is_hidden_option(idx)) { // can't set hidden option
+ vimoption_T *opt = get_option(idx);
+
+ if (opt->var == NULL) { // can't set hidden option
return;
}
- assert((void *)get_option_var(idx) != (void *)&p_shada);
+ assert((void *)opt->var != (void *)&p_shada);
s = xstrdup(val);
{
- varp = (char **)get_option_varp_scope(idx, both ? OPT_LOCAL : opt_flags);
- if ((opt_flags & OPT_FREE) && (get_option_flags(idx) & P_ALLOCED)) {
+ varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
+ if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) {
free_string_option(*varp);
}
*varp = s;
// For buffer/window local option may also set the global value.
if (both) {
- set_string_option_global(idx, varp);
+ set_string_option_global(opt, varp);
}
- set_option_flag(idx, P_ALLOCED);
+ opt->flags |= P_ALLOCED;
// When setting both values of a global option with a local value,
// make the local value empty, so that the global value is used.
- if (is_global_local_option(idx) && both) {
+ if ((opt->indir & PV_BOTH) && both) {
free_string_option(*varp);
*varp = empty_option;
}
@@ -393,24 +395,24 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c
char *set_string_option(const int opt_idx, const char *const value, const int opt_flags)
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (is_hidden_option(opt_idx)) { // don't set hidden option
+ vimoption_T *opt = get_option(opt_idx);
+
+ if (opt->var == NULL) { // don't set hidden option
return NULL;
}
char *const s = xstrdup(value);
char **const varp
- = (char **)get_option_varp_scope(opt_idx,
- (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
- ? (is_global_local_option(opt_idx)
- ? OPT_GLOBAL : OPT_LOCAL)
- : opt_flags);
+ = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
+ ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL)
+ : opt_flags));
char *const oldval = *varp;
char *oldval_l = NULL;
char *oldval_g = NULL;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
- oldval_l = *(char **)get_option_varp_scope(opt_idx, OPT_LOCAL);
- oldval_g = *(char **)get_option_varp_scope(opt_idx, OPT_GLOBAL);
+ oldval_l = *(char **)get_varp_scope(opt, OPT_LOCAL);
+ oldval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL);
}
*varp = s;
@@ -434,8 +436,8 @@ char *set_string_option(const int opt_idx, const char *const value, const int op
trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g,
saved_newval);
}
- if (get_option_flags(opt_idx) & P_UI_OPTION) {
- ui_call_option_set(cstr_as_string(get_option_fullname(opt_idx)),
+ if (opt->flags & P_UI_OPTION) {
+ ui_call_option_set(cstr_as_string(opt->fullname),
STRING_OBJ(cstr_as_string(saved_newval)));
}
}
@@ -638,20 +640,21 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
char *errmsg = NULL;
char *s, *p;
int did_chartab = false;
- bool free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
+ vimoption_T *opt = get_option(opt_idx);
+ bool free_oldval = (opt->flags & P_ALLOCED);
bool value_changed = false;
// Get the global option to compare with, otherwise we would have to check
// two values for all local options.
- char **gvarp = (char **)get_option_varp_scope(opt_idx, OPT_GLOBAL);
+ char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL);
// Disallow changing some options from secure mode
if ((secure || sandbox != 0)
- && (get_option_flags(opt_idx) & P_SECURE)) {
+ && (opt->flags & P_SECURE)) {
errmsg = e_secure;
- } else if (((get_option_flags(opt_idx) & P_NFNAME)
+ } else if (((opt->flags & P_NFNAME)
&& strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
- || ((get_option_flags(opt_idx) & P_NDNAME)
+ || ((opt->flags & P_NDNAME)
&& strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) {
// Check for a "normal" directory or file name in some options. Disallow a
// path separator (slash and/or backslash), wildcards and characters that
@@ -986,13 +989,14 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
} else if (varp == &p_shada) { // 'shada'
// TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
// option.
- opt_idx = ((get_option_fullname(opt_idx)[0] == 'v')
+ opt_idx = ((opt->fullname[0] == 'v')
? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
: opt_idx);
+ opt = get_option(opt_idx);
// Update free_oldval now that we have the opt_idx for 'shada', otherwise
// there would be a disconnect between the check for P_ALLOCED at the start
// of the function and the set of P_ALLOCED at the end of the function.
- free_oldval = (get_option_flags(opt_idx) & P_ALLOCED);
+ free_oldval = (opt->flags & P_ALLOCED);
for (s = p_shada; *s;) {
// Check it's a valid character
if (vim_strchr("!\"%'/:<@cfhnrs", *s) == NULL) {
@@ -1522,18 +1526,18 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
if (free_oldval) {
free_string_option(oldval);
}
- set_option_flag(opt_idx, P_ALLOCED);
+ opt->flags |= P_ALLOCED;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
- && is_global_local_option(opt_idx)) {
+ && (opt->indir & PV_BOTH)) {
// global option with local value set to use global value; free
// the local value and make it empty
- p = get_option_varp_scope(opt_idx, OPT_LOCAL);
+ p = get_varp_scope(opt, OPT_LOCAL);
free_string_option(*(char **)p);
*(char **)p = empty_option;
} else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) {
// May set global value for local option.
- set_string_option_global(opt_idx, varp);
+ set_string_option_global(opt, varp);
}
// Trigger the autocommand only after setting the flags.
@@ -1604,11 +1608,11 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
}
if (curwin->w_curswant != MAXCOL
- && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) {
+ && (opt->flags & (P_CURSWANT | P_RALL)) != 0) {
curwin->w_set_curswant = true;
}
- check_redraw(get_option_flags(opt_idx));
+ check_redraw(opt->flags);
return errmsg;
}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 9766c8f3d9..750d2f342f 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -805,7 +805,7 @@ done:
/// char *output = NULL;
/// size_t nread = 0;
/// char *argv[] = {"ls", "-la", NULL};
-/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread);
+/// int exitcode = os_system(argv, NULL, 0, &output, &nread);
///
/// @param argv The commandline arguments to be passed to the shell. `argv`
/// will be consumed.
diff --git a/src/nvim/path.c b/src/nvim/path.c
index d1a7e14c9f..9295905415 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -575,7 +575,7 @@ bool path_has_exp_wildcard(const char_u *p)
/// @param path The path to search.
/// @param flags Flags for regexp expansion.
/// - EW_ICASE: Ignore case.
-/// - EW_NOERROR: Silence error messeges.
+/// - EW_NOERROR: Silence error messages.
/// - EW_NOTWILD: Add matches literally.
/// @returns the number of matches found.
static size_t path_expand(garray_T *gap, const char_u *path, int flags)
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 6f13dd2f06..9c517098b9 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -724,7 +724,27 @@ static void sign_list_placed(buf_T *rbuf, char *sign_group)
}
}
-/// Adjust a placed sign for inserted/deleted lines.
+/// Adjust or delete a placed sign for inserted/deleted lines.
+///
+/// @return the new line number of the sign, or 0 if the sign is in deleted lines.
+static linenr_T sign_adjust_one(const linenr_T se_lnum, linenr_T line1, linenr_T line2,
+ linenr_T amount, linenr_T amount_after)
+{
+ if (se_lnum < line1) {
+ // Ignore changes to lines after the sign
+ return se_lnum;
+ }
+ if (se_lnum > line2) {
+ // Lines inserted or deleted before the sign
+ return se_lnum + amount_after;
+ }
+ if (amount == MAXLNUM) { // sign in deleted lines
+ return 0;
+ }
+ return se_lnum + amount;
+}
+
+/// Adjust placed signs for inserted/deleted lines.
void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after)
{
sign_entry_T *sign; // a sign in a b_signlist
@@ -735,9 +755,7 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T
int is_fixed = 0;
int signcol = win_signcol_configured(curwin, &is_fixed);
- bool delete = amount == MAXLNUM;
-
- if (delete) {
+ if (amount == MAXLNUM) { // deleting
buf_signcols_del_check(curbuf, line1, line2);
}
@@ -745,11 +763,10 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T
for (sign = curbuf->b_signlist; sign != NULL; sign = next) {
next = sign->se_next;
- new_lnum = sign->se_lnum;
- if (sign->se_lnum >= line1 && sign->se_lnum <= line2) {
- if (!delete) {
- new_lnum += amount;
- } else if (!is_fixed || signcol >= 2) {
+
+ new_lnum = sign_adjust_one(sign->se_lnum, line1, line2, amount, amount_after);
+ if (new_lnum == 0) { // sign in deleted lines
+ if (!is_fixed || signcol >= 2) {
*lastp = next;
if (next) {
next->se_prev = last;
@@ -757,19 +774,23 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T
xfree(sign);
continue;
}
- } else if (sign->se_lnum > line2) {
- new_lnum += amount_after;
- }
- // If the new sign line number is past the last line in the buffer,
- // then don't adjust the line number. Otherwise, it will always be past
- // the last line and will not be visible.
- if (sign->se_lnum >= line1 && new_lnum <= curbuf->b_ml.ml_line_count) {
- sign->se_lnum = new_lnum;
+ } else {
+ // If the new sign line number is past the last line in the buffer,
+ // then don't adjust the line number. Otherwise, it will always be past
+ // the last line and will not be visible.
+ if (new_lnum <= curbuf->b_ml.ml_line_count) {
+ sign->se_lnum = new_lnum;
+ }
}
last = sign;
lastp = &sign->se_next;
}
+
+ new_lnum = sign_adjust_one(curbuf->b_signcols.sentinel, line1, line2, amount, amount_after);
+ if (new_lnum != 0) {
+ curbuf->b_signcols.sentinel = new_lnum;
+ }
}
/// Find index of a ":sign" subcmd from its name.
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 53fa920358..7d2b58ff46 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1344,14 +1344,14 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
: p - buf) > wp->w_cursor.col)) {
col = (colnr_T)(p - buf);
- bool can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0;
+ bool can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error);
if (!can_spell) {
- can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error);
- }
-
- if (!can_spell && has_syntax) {
- (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
+ if (has_syntax) {
+ (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
+ } else {
+ can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0;
+ }
}
if (!can_spell) {
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 326c868be8..c52586fea2 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -759,6 +759,22 @@ static int get_rgb(VTermState *state, VTermColor color)
return RGB_(color.rgb.red, color.rgb.green, color.rgb.blue);
}
+static int get_underline_hl_flag(VTermScreenCellAttrs attrs)
+{
+ switch (attrs.underline) {
+ case VTERM_UNDERLINE_OFF:
+ return 0;
+ case VTERM_UNDERLINE_SINGLE:
+ return HL_UNDERLINE;
+ case VTERM_UNDERLINE_DOUBLE:
+ return HL_UNDERDOUBLE;
+ case VTERM_UNDERLINE_CURLY:
+ return HL_UNDERCURL;
+ default:
+ return HL_UNDERLINE;
+ }
+}
+
void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *term_attrs)
{
int height, width;
@@ -795,7 +811,7 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te
int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0)
| (cell.attrs.italic ? HL_ITALIC : 0)
| (cell.attrs.reverse ? HL_INVERSE : 0)
- | (cell.attrs.underline ? HL_UNDERLINE : 0)
+ | get_underline_hl_flag(cell.attrs)
| (cell.attrs.strike ? HL_STRIKETHROUGH: 0)
| ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0)
| ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0);
@@ -892,7 +908,6 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
case VTERM_PROP_TITLE: {
buf_T *buf = handle_get_buffer(term->buf_handle);
-#if VTERM_VERSION_MAJOR > 0 || (VTERM_VERSION_MAJOR == 0 && VTERM_VERSION_MINOR >= 2)
VTermStringFragment frag = val->string;
if (frag.initial && frag.final) {
@@ -917,9 +932,6 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
xfree(term->title);
term->title = NULL;
}
-#else
- buf_set_term_title(buf, val->string, strlen(val->string));
-#endif
break;
}
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 4755d39cd3..05aee9b31d 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -240,6 +240,7 @@ let s:filename_checks = {
\ 'grub': ['/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf', 'any/boot/grub/grub.conf', 'any/boot/grub/menu.lst', 'any/etc/grub.conf'],
\ 'gsp': ['file.gsp'],
\ 'gtkrc': ['.gtkrc', 'gtkrc', '.gtkrc-file', 'gtkrc-file'],
+ \ 'gyp': ['file.gyp', 'file.gypi'],
\ 'hack': ['file.hack', 'file.hackpartial'],
\ 'haml': ['file.haml'],
\ 'hamster': ['file.hsm'],
@@ -327,7 +328,7 @@ let s:filename_checks = {
\ 'lpc': ['file.lpc', 'file.ulpc'],
\ 'lsl': ['file.lsl'],
\ 'lss': ['file.lss'],
- \ 'lua': ['file.lua', 'file.rockspec', 'file.nse'],
+ \ 'lua': ['file.lua', 'file.rockspec', 'file.nse', '.luacheckrc'],
\ 'lynx': ['lynx.cfg'],
\ 'lyrics': ['file.lrc'],
\ 'm3build': ['m3makefile', 'm3overrides'],
@@ -412,7 +413,7 @@ let s:filename_checks = {
\ 'pccts': ['file.g'],
\ 'pcmk': ['file.pcmk'],
\ 'pdf': ['file.pdf'],
- \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'],
+ \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc', '.latexmkrc', 'latexmkrc'],
\ 'pf': ['pf.conf'],
\ 'pfmain': ['main.cf'],
\ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt', 'file.theme'],
@@ -582,6 +583,7 @@ let s:filename_checks = {
\ 'tssop': ['file.tssop'],
\ 'tsv': ['file.tsv'],
\ 'twig': ['file.twig'],
+ \ 'typescript': ['file.mts', 'file.cts'],
\ 'typescript.glimmer': ['file.gts'],
\ 'typescriptreact': ['file.tsx'],
\ 'uc': ['file.uc'],
diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim
index 2672fcb69d..42a1fdcfe2 100644
--- a/src/nvim/testdir/test_messages.vim
+++ b/src/nvim/testdir/test_messages.vim
@@ -316,6 +316,66 @@ func Test_message_more()
call StopVimInTerminal(buf)
endfunc
+" Test more-prompt scrollback
+func Test_message_more_scrollback()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ set t_ut=
+ hi Normal ctermfg=15 ctermbg=0
+ for i in range(100)
+ echo i
+ endfor
+ END
+ call writefile(lines, 'XmoreScrollback', 'D')
+ let buf = RunVimInTerminal('-S XmoreScrollback', {'rows': 10})
+ call VerifyScreenDump(buf, 'Test_more_scrollback_1', {})
+
+ call term_sendkeys(buf, 'f')
+ call TermWait(buf)
+ call term_sendkeys(buf, 'b')
+ call VerifyScreenDump(buf, 'Test_more_scrollback_2', {})
+
+ call term_sendkeys(buf, 'q')
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
+" Test verbose message before echo command
+func Test_echo_verbose_system()
+ CheckRunVimInTerminal
+ CheckUnix
+
+ let buf = RunVimInTerminal('', {'rows': 10})
+ call term_sendkeys(buf, ":4 verbose echo system('seq 20')\<CR>")
+ " Note that the screendump is filtered to remove the name of the temp file
+ call VerifyScreenDump(buf, 'Test_verbose_system_1', {})
+
+ " display a page and go back, results in exactly the same view
+ call term_sendkeys(buf, ' ')
+ call TermWait(buf)
+ call term_sendkeys(buf, 'b')
+ call VerifyScreenDump(buf, 'Test_verbose_system_1', {})
+
+ " do the same with 'cmdheight' set to 2
+ call term_sendkeys(buf, 'q')
+ call TermWait(buf)
+ call term_sendkeys(buf, ":set ch=2\<CR>")
+ call TermWait(buf)
+ call term_sendkeys(buf, ":4 verbose echo system('seq 20')\<CR>")
+ call VerifyScreenDump(buf, 'Test_verbose_system_2', {})
+
+ call term_sendkeys(buf, ' ')
+ call TermWait(buf)
+ call term_sendkeys(buf, 'b')
+ call VerifyScreenDump(buf, 'Test_verbose_system_2', {})
+
+ call term_sendkeys(buf, 'q')
+ call TermWait(buf)
+ call StopVimInTerminal(buf)
+endfunc
+
+
func Test_ask_yesno()
CheckRunVimInTerminal
let buf = RunVimInTerminal('', {'rows': 6})
@@ -357,15 +417,14 @@ func Test_quit_long_message()
let content =<< trim END
echom range(9999)->join("\x01")
END
- call writefile(content, 'Xtest_quit_message')
- let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 6, wait_for_ruler: 0})
- call WaitForAssert({-> assert_match('^-- More --', term_getline(buf, 6))})
+ call writefile(content, 'Xtest_quit_message', 'D')
+ let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 10, wait_for_ruler: 0})
+ call WaitForAssert({-> assert_match('^-- More --', term_getline(buf, 10))})
call term_sendkeys(buf, "q")
call VerifyScreenDump(buf, 'Test_quit_long_message', {})
" clean up
call StopVimInTerminal(buf)
- call delete('Xtest_quit_message')
endfunc
" this was missing a terminating NUL
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
index 621efa44cf..e6b330cbf1 100644
--- a/src/nvim/textobject.c
+++ b/src/nvim/textobject.c
@@ -1503,7 +1503,7 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
bool inside_quotes = false; // Looks like "i'" done before
bool selected_quote = false; // Has quote inside selection
int i;
- bool restore_vis_bef = false; // resotre VIsual on abort
+ bool restore_vis_bef = false; // restore VIsual on abort
// When 'selection' is "exclusive" move the cursor to where it would be
// with 'selection' "inclusive", so that the logic is the same for both.
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 998e8cfed0..fbeca26274 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -159,14 +159,10 @@ void tinput_init(TermInput *input, Loop *loop)
term = ""; // termkey_new_abstract assumes non-null (#2745)
}
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
input->tk = termkey_new_abstract(term,
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
termkey_start(input->tk);
-#else
- input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8);
-#endif
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 51df57938c..0b60394850 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -26,9 +26,7 @@ typedef struct term_input {
ExtkeysType extkeys_type;
long ttimeoutlen;
TermKey *tk;
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
-#endif
TimeWatcher timer_handle;
Loop *loop;
Stream read_stream;
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 4eabecb74a..b483ad3486 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -485,9 +485,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
// TODO(bfredl): zero hl is empty, send this explicitly?
kv_push(data->attrs, HLATTRS_INIT);
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
-#endif
tinput_init(&data->input, &tui_loop);
tui_terminal_start(ui);
@@ -2278,7 +2276,6 @@ static void flush_buf(UI *ui)
data->overflow = false;
}
-#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
/// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely
/// unreliable." (Vim, Bash, and tmux also do this.)
///
@@ -2287,14 +2284,14 @@ static void flush_buf(UI *ui)
static const char *tui_get_stty_erase(void)
{
static char stty_erase[2] = { 0 };
-# if defined(HAVE_TERMIOS_H)
+#if defined(HAVE_TERMIOS_H)
struct termios t;
if (tcgetattr(input_global_fd(), &t) != -1) {
stty_erase[0] = (char)t.c_cc[VERASE];
stty_erase[1] = '\0';
DLOG("stty/termios:erase=%s", stty_erase);
}
-# endif
+#endif
return stty_erase;
}
@@ -2328,4 +2325,3 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, void *d
return value;
}
-#endif
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index d67863f84f..1a9066d7f1 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1771,16 +1771,16 @@ void u_redo(int count)
/// Undo and remove the branch from the undo tree.
/// Also moves the cursor (as a "normal" undo would).
-bool u_undo_and_forget(int count)
+///
+/// @param do_buf_event If `true`, send the changedtick with the buffer updates
+bool u_undo_and_forget(int count, bool do_buf_event)
{
if (curbuf->b_u_synced == false) {
u_sync(true);
count = 1;
}
undo_undoes = true;
- u_doit(count, true,
- // Don't send nvim_buf_lines_event for u_undo_and_forget().
- false);
+ u_doit(count, true, do_buf_event);
if (curbuf->b_u_curhead == NULL) {
// nothing was undone.
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 22c1b77570..adcf9cdd56 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -737,7 +737,7 @@ void win_set_minimal_style(win_T *wp)
}
// TODO(bfredl): this could use a highlight namespace directly,
- // and avoid pecularities around window options
+ // and avoid peculiarities around window options
char_u *old = (char_u *)wp->w_p_winhl;
wp->w_p_winhl = ((*old == NUL)
? xstrdup("EndOfBuffer:")
@@ -2239,7 +2239,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
// Compute maximum number of windows vertically in this frame.
n = frame_minheight(topfr, NOWIN);
// add one for the bottom window if it doesn't have a statusline or separator
- if (row + height == cmdline_row && p_ls == 0) {
+ if (row + height >= cmdline_row && p_ls == 0) {
extra_sep = STATUS_HEIGHT;
} else if (global_stl_height() > 0) {
extra_sep = 1;