aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/autocmd.txt6
-rw-r--r--runtime/doc/diagnostic.txt24
-rw-r--r--runtime/doc/editing.txt29
-rw-r--r--runtime/doc/eval.txt25
-rw-r--r--runtime/doc/usr_22.txt24
-rw-r--r--runtime/doc/usr_41.txt3
-rw-r--r--runtime/doc/vim_diff.txt5
-rw-r--r--runtime/lua/vim/diagnostic.lua80
-rw-r--r--src/nvim/buffer.c33
-rw-r--r--src/nvim/buffer_defs.h5
-rw-r--r--src/nvim/eval.c6
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c64
-rw-r--r--src/nvim/eval/userfunc.c52
-rw-r--r--src/nvim/ex_cmds.c150
-rw-r--r--src/nvim/ex_cmds2.c80
-rw-r--r--src/nvim/ex_cmds2.h25
-rw-r--r--src/nvim/ex_docmd.c237
-rw-r--r--src/nvim/ex_eval.c120
-rw-r--r--src/nvim/ex_getln.c20
-rw-r--r--src/nvim/ex_session.c2
-rw-r--r--src/nvim/file_search.c45
-rw-r--r--src/nvim/fileio.c122
-rw-r--r--src/nvim/fold.c127
-rw-r--r--src/nvim/globals.h16
-rw-r--r--src/nvim/main.c6
-rw-r--r--src/nvim/mark.c33
-rw-r--r--src/nvim/mbyte.c30
-rw-r--r--src/nvim/memline.c52
-rw-r--r--src/nvim/menu.c8
-rw-r--r--src/nvim/normal.c91
-rw-r--r--src/nvim/ops.c79
-rw-r--r--src/nvim/option.c42
-rw-r--r--src/nvim/regexp.c12
-rw-r--r--src/nvim/regexp_nfa.c79
-rw-r--r--src/nvim/screen.c8
-rw-r--r--src/nvim/search.c87
-rw-r--r--src/nvim/spellfile.c2
-rw-r--r--src/nvim/syntax.c121
-rw-r--r--src/nvim/tag.c73
-rw-r--r--src/nvim/testdir/test_autochdir.vim10
-rw-r--r--src/nvim/testdir/test_autocmd.vim73
-rw-r--r--src/nvim/testdir/test_cd.vim138
-rw-r--r--src/nvim/testdir/test_find_complete.vim8
-rw-r--r--src/nvim/testdir/test_findfile.vim4
-rw-r--r--src/nvim/testdir/test_getcwd.vim2
-rw-r--r--src/nvim/undo.c76
-rw-r--r--src/nvim/window.c175
-rw-r--r--test/functional/api/vim_spec.lua45
-rw-r--r--test/functional/autocmd/dirchanged_spec.lua120
-rw-r--r--test/functional/ex_cmds/source_spec.lua20
-rw-r--r--test/functional/lua/diagnostic_spec.lua72
52 files changed, 1715 insertions, 1052 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 5923dada43..6c41dd3b10 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -519,11 +519,17 @@ DiffUpdated After diffs have been updated. Depending on
change or when doing |:diffupdate|.
*DirChanged*
DirChanged After the |current-directory| was changed.
+ The pattern can be:
+ "window" to trigger on `:lcd`
+ "tabpage" to trigger on `:tcd`
+ "global" to trigger on `:cd`
+ "auto" to trigger on 'autochdir'.
Sets these |v:event| keys:
cwd: current working directory
scope: "global", "tab", "window"
changed_window: v:true if we fired the event
switching window (or tab)
+ <afile> is set to the new directory name.
Non-recursive (event cannot trigger itself).
*FileAppendCmd*
FileAppendCmd Before appending to a file. Should do the
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 75c8a2ad6f..17d317522b 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -254,12 +254,31 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
Configure diagnostic options globally or for a specific
diagnostic namespace.
+ Configuration can be specified globally, per-namespace, or
+ ephemerally (i.e. only for a single call to
+ |vim.diagnostic.set()| or |vim.diagnostic.show()|). Ephemeral
+ configuration has highest priority, followed by namespace
+ configuration, and finally global configuration.
+
+ For example, if a user enables virtual text globally with >
+
+ vim.diagnostic.config({virt_text = true})
+<
+
+ and a diagnostic producer sets diagnostics with >
+
+ vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false})
+<
+
+ then virtual text will not be enabled for those diagnostics.
+
Note:
Each of the configuration options below accepts one of the
following:
• `false` : Disable this feature
• `true` : Enable this feature, use default settings.
- • `table` : Enable this feature with overrides.
+ • `table` : Enable this feature with overrides. Use an
+ empty table to use default values.
• `function` : Function with signature (namespace, bufnr)
that returns any of the above.
@@ -460,8 +479,9 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
For example, consider a line of output from a linter: >
WARNING filename:27:3: Variable 'foo' does not exist
+<
- < This can be parsed into a diagnostic |diagnostic-structure|
+ This can be parsed into a diagnostic |diagnostic-structure|
with: >
local s = "WARNING filename:27:3: Variable 'foo' does not exist"
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index f91e4f0627..efba9020f9 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1275,10 +1275,12 @@ exist, the next-higher scope in the hierarchy applies.
*:chd* *:chdir*
:chd[ir][!] [path] Same as |:cd|.
- *:tc* *:tcd* *E5000* *E5001* *E5002*
-:tc[d][!] {path} Like |:cd|, but set the current directory for the
- current tab and window. The current directory for
- other tabs and windows is not changed.
+ *:tc* *:tcd*
+:tc[d][!] {path} Like |:cd|, but only set the directory for the current
+ tab. The current window will also use this directory.
+ The current directory is not changed for windows in
+ other tabs and for windows in the current tab that
+ have their own window-local directory.
*:tcd-*
:tc[d][!] - Change to the previous current directory (before the
@@ -1302,9 +1304,24 @@ exist, the next-higher scope in the hierarchy applies.
*:pw* *:pwd* *E187*
:pw[d] Print the current directory name.
Also see |getcwd()|.
+ *:pwd-verbose*
+ When 'verbose' is non-zero, |:pwd| will also display
+ what scope the current directory was set. Example: >
-So long as no |:tcd| or |:lcd| command has been used, all windows share the
-same "current directory". Using a command to jump to another window doesn't
+ " Set by :cd
+ :verbose pwd
+ [global] /path/to/current
+
+ " Set by :lcd
+ :verbose pwd
+ [window] /path/to/current
+
+ " Set by :tcd
+ :verbose pwd
+ [tabpage] /path/to/current
+
+So long as no |:lcd| or |:tcd| command has been used, all windows share the
+same current directory. Using a command to jump to another window doesn't
change anything for the current directory.
When |:lcd| has been used for a window, the specified directory becomes the
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e956ccaa77..4467afaa16 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2316,6 +2316,7 @@ chansend({id}, {data}) Number Writes {data} to channel
char2nr({expr}[, {utf8}]) Number ASCII/UTF-8 value of first char in {expr}
charidx({string}, {idx} [, {countcc}])
Number char index of byte {idx} in {string}
+chdir({dir}) String change current working directory
cindent({lnum}) Number C indent for line {lnum}
clearmatches([{win}]) none clear all matches
col({expr}) Number column nr of cursor or mark
@@ -2461,6 +2462,7 @@ has({feature}) Number |TRUE| if feature {feature} supported
has_key({dict}, {key}) Number |TRUE| if {dict} has entry {key}
haslocaldir([{winnr} [, {tabnr}]])
Number |TRUE| if current window executed |:lcd|
+ or |:tcd|
hasmapto({what} [, {mode} [, {abbr}]])
Number |TRUE| if mapping to {what} exists
histadd({history}, {item}) String add an item to a history
@@ -3280,6 +3282,27 @@ charidx({string}, {idx} [, {countcc}])
echo charidx('áb́ć', 6, 1) returns 4
echo charidx('áb́ć', 16) returns -1
+chdir({dir}) *chdir()*
+ Change the current working directory to {dir}. The scope of
+ the directory change depends on the directory of the current
+ window:
+ - If the current window has a window-local directory
+ (|:lcd|), then changes the window local directory.
+ - Otherwise, if the current tabpage has a local
+ directory (|:tcd|) then changes the tabpage local
+ directory.
+ - Otherwise, changes the global directory.
+ If successful, returns the previous working directory. Pass
+ this to another chdir() to restore the directory.
+ On failure, returns an empty string.
+
+ Example: >
+ let save_dir = chdir(newdir)
+ if save_dir
+ " ... do some work
+ call chdir(save_dir)
+ endif
+<
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
indenting rules, as with 'cindent'.
@@ -4987,6 +5010,8 @@ getcwd([{winnr}[, {tabnr}]]) *getcwd()*
getcwd(0, 0)
< If {winnr} is -1 it is ignored, only the tab is resolved.
{winnr} can be the window number or the |window-ID|.
+ If both {winnr} and {tabnr} are -1 the global working
+ directory is returned.
Can also be used as a |method|: >
GetWinnr()->getcwd()
diff --git a/runtime/doc/usr_22.txt b/runtime/doc/usr_22.txt
index 56fe5ada2b..f53d578456 100644
--- a/runtime/doc/usr_22.txt
+++ b/runtime/doc/usr_22.txt
@@ -202,14 +202,28 @@ the other window. This is called a local directory. >
:pwd
/home/Bram/VeryLongFileName
-So long as no ":lcd" command has been used, all windows share the same current
-directory. Doing a ":cd" command in one window will also change the current
+So long as no `:lcd` command has been used, all windows share the same current
+directory. Doing a `:cd` command in one window will also change the current
directory of the other window.
- For a window where ":lcd" has been used a different current directory is
-remembered. Using ":cd" or ":lcd" in other windows will not change it.
- When using a ":cd" command in a window that uses a different current
+ For a window where `:lcd` has been used a different current directory is
+remembered. Using `:cd` or `:lcd` in other windows will not change it.
+ When using a `:cd` command in a window that uses a different current
directory, it will go back to using the shared directory.
+
+TAB LOCAL DIRECTORY
+
+When you open a new tab page, it uses the directory of the window in the
+previous tab page from which the new tab page was opened. You can change the
+directory of the current tab page using the `:tcd` command. All the windows in
+a tab page share this directory except for windows with a window-local
+directory. Any new windows opened in this tab page will use this directory as
+the current working directory. Using a `:cd` command in a tab page will not
+change the working directory of tab pages which have a tab local directory.
+When the global working directory is changed using the ":cd" command in a tab
+page, it will also change the current tab page working directory.
+
+
==============================================================================
*22.3* Finding a file
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index c575dd9fd8..6a9284dac9 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -785,9 +785,10 @@ System functions and manipulation of files:
isdirectory() check if a directory exists
getfsize() get the size of a file
getcwd() get the current working directory
- haslocaldir() check if current window used |:lcd|
+ haslocaldir() check if current window used |:lcd| or |:tcd|
tempname() get the name of a temporary file
mkdir() create a new directory
+ chdir() change current working directory
delete() delete a file
rename() rename a file
system() get the result of a shell command as a string
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 64824b2e3f..7e7bb7d62f 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -180,6 +180,7 @@ Commands:
|:match| can be invoked before highlight group is defined
Events:
+ |DirChanged| can be triggered when switching to another window
|Signal|
|TabNewEntered|
|TermClose|
@@ -196,6 +197,10 @@ Functions:
|stdpath()|
|system()|, |systemlist()| can run {cmd} directly (without 'shell')
|matchadd()| can be called before highlight group is defined
+ |getcwd()| and |haslocaldir()| may throw errors. *E5000* *E5001* *E5002*
+ |haslocaldir()|'s only possible return values are 0 and 1, it never returns 2.
+ `getcwd(-1)` is equivalent to `getcwd(-1, 0)` instead of returning the global
+ working directory. Use `getcwd(-1, -1)` to get the global working directory.
Highlight groups:
|highlight-blend| controls blend level for a highlight group
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index e8aba6b7a3..326932d982 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -93,28 +93,6 @@ local function reformat_diagnostics(format, diagnostics)
return formatted
end
----@private
-local function resolve_optional_value(option, namespace, bufnr)
- local enabled_val = {}
-
- if not option then
- return false
- elseif option == true then
- return enabled_val
- elseif type(option) == 'function' then
- local val = option(namespace, bufnr)
- if val == true then
- return enabled_val
- else
- return val
- end
- elseif type(option) == 'table' then
- return option
- else
- error("Unexpected option type: " .. vim.inspect(option))
- end
-end
-
local all_namespaces = {}
---@private
@@ -140,12 +118,46 @@ local function get_namespace(ns)
end
---@private
+local function enabled_value(option, namespace)
+ local ns = get_namespace(namespace)
+ if type(ns.opts[option]) == "table" then
+ return ns.opts[option]
+ end
+
+ if type(global_diagnostic_options[option]) == "table" then
+ return global_diagnostic_options[option]
+ end
+
+ return {}
+end
+
+---@private
+local function resolve_optional_value(option, value, namespace, bufnr)
+ if not value then
+ return false
+ elseif value == true then
+ return enabled_value(option, namespace)
+ elseif type(value) == 'function' then
+ local val = value(namespace, bufnr)
+ if val == true then
+ return enabled_value(option, namespace)
+ else
+ return val
+ end
+ elseif type(value) == 'table' then
+ return value
+ else
+ error("Unexpected option type: " .. vim.inspect(value))
+ end
+end
+
+---@private
local function get_resolved_options(opts, namespace, bufnr)
local ns = get_namespace(namespace)
local resolved = vim.tbl_extend('keep', opts or {}, ns.opts, global_diagnostic_options)
for k in pairs(global_diagnostic_options) do
if resolved[k] ~= nil then
- resolved[k] = resolve_optional_value(resolved[k], namespace, bufnr)
+ resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr)
end
end
return resolved
@@ -542,10 +554,27 @@ end
--- Configure diagnostic options globally or for a specific diagnostic
--- namespace.
---
+--- Configuration can be specified globally, per-namespace, or ephemerally
+--- (i.e. only for a single call to |vim.diagnostic.set()| or
+--- |vim.diagnostic.show()|). Ephemeral configuration has highest priority,
+--- followed by namespace configuration, and finally global configuration.
+---
+--- For example, if a user enables virtual text globally with
+--- <pre>
+--- vim.diagnostic.config({virt_text = true})
+--- </pre>
+---
+--- and a diagnostic producer sets diagnostics with
+--- <pre>
+--- vim.diagnostic.set(ns, 0, diagnostics, {virt_text = false})
+--- </pre>
+---
+--- then virtual text will not be enabled for those diagnostics.
+---
---@note Each of the configuration options below accepts one of the following:
--- - `false`: Disable this feature
--- - `true`: Enable this feature, use default settings.
---- - `table`: Enable this feature with overrides.
+--- - `table`: Enable this feature with overrides. Use an empty table to use default values.
--- - `function`: Function with signature (namespace, bufnr) that returns any of the above.
---
---@param opts table Configuration table with the following keys:
@@ -653,8 +682,6 @@ function M.set(namespace, bufnr, diagnostics, opts)
if vim.api.nvim_buf_is_loaded(bufnr) then
M.show(namespace, bufnr, diagnostics, opts)
- elseif opts then
- M.config(opts, namespace)
end
vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
@@ -1277,6 +1304,7 @@ end
--- <pre>
--- WARNING filename:27:3: Variable 'foo' does not exist
--- </pre>
+---
--- This can be parsed into a diagnostic |diagnostic-structure|
--- with:
--- <pre>
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 37cc854959..826a197454 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -526,8 +526,8 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
diff_buf_delete(buf); // Clear 'diff' for hidden buffer.
}
- /* Return when a window is displaying the buffer or when it's not
- * unloaded. */
+ // Return when a window is displaying the buffer or when it's not
+ // unloaded.
if (buf->b_nwindows > 0 || !unload_buf) {
return false;
}
@@ -593,9 +593,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
buf->b_nwindows--;
}
- // Change directories when the 'acd' option is set.
- do_autochdir();
-
// Disable buffer-updates for the current buffer.
// No need to check `unload_buf`: in that case the function returned above.
buf_updates_unload(buf, false);
@@ -1591,8 +1588,8 @@ void enter_buffer(buf_T *buf)
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, false, curbuf);
}
- /* If autocommands did not change the cursor position, restore cursor lnum
- * and possibly cursor col. */
+ // If autocommands did not change the cursor position, restore cursor lnum
+ // and possibly cursor col.
if (curwin->w_cursor.lnum == 1 && inindent(0)) {
buflist_getfpos();
}
@@ -1628,7 +1625,7 @@ void do_autochdir(void)
if (p_acd) {
if (starting == 0
&& curbuf->b_ffname != NULL
- && vim_chdirfile(curbuf->b_ffname) == OK) {
+ && vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) {
post_chdir(kCdScopeGlobal, false);
shorten_fnames(true);
}
@@ -1754,8 +1751,8 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl
if ((flags & BLN_CURBUF) && curbuf_reusable()) {
assert(curbuf != NULL);
buf = curbuf;
- /* It's like this buffer is deleted. Watch out for autocommands that
- * change curbuf! If that happens, allocate a new buffer anyway. */
+ // It's like this buffer is deleted. Watch out for autocommands that
+ // change curbuf! If that happens, allocate a new buffer anyway.
if (curbuf->b_p_bl) {
apply_autocmds(EVENT_BUFDELETE, NULL, NULL, false, curbuf);
}
@@ -2257,8 +2254,8 @@ int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlis
}
}
- /* Only search for unlisted buffers if there was no match with
- * a listed buffer. */
+ // Only search for unlisted buffers if there was no match with
+ // a listed buffer.
if (!unlisted || !find_listed || match != -1) {
break;
}
@@ -2893,8 +2890,8 @@ void buf_set_name(int fnum, char_u *name)
xfree(buf->b_ffname);
buf->b_ffname = vim_strsave(name);
buf->b_sfname = NULL;
- /* Allocate ffname and expand into full path. Also resolves .lnk
- * files on Win32. */
+ // Allocate ffname and expand into full path. Also resolves .lnk
+ // files on Win32.
fname_expand(buf, &buf->b_ffname, &buf->b_sfname);
buf->b_fname = buf->b_sfname;
}
@@ -3166,8 +3163,8 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate)
(void)append_arg_number(curwin, buffer, IOSIZE, !shortmess(SHM_FILE));
if (dont_truncate) {
- /* Temporarily set msg_scroll to avoid the message being truncated.
- * First call msg_start() to get the message in the right place. */
+ // Temporarily set msg_scroll to avoid the message being truncated.
+ // First call msg_start() to get the message in the right place.
msg_start();
n = msg_scroll;
msg_scroll = true;
@@ -5233,8 +5230,8 @@ void do_modelines(int flags)
return;
}
- /* Disallow recursive entry here. Can happen when executing a modeline
- * triggers an autocommand, which reloads modelines with a ":do". */
+ // Disallow recursive entry here. Can happen when executing a modeline
+ // triggers an autocommand, which reloads modelines with a ":do".
if (entered) {
return;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 2c411553b8..19b0a3c5c6 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -953,6 +953,7 @@ struct tabpage_S {
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
dict_T *tp_vars; ///< Internal variables, local to tab page.
char_u *tp_localdir; ///< Absolute path of local cwd or NULL.
+ char_u *tp_prevdir; ///< Previous directory.
};
/*
@@ -1381,8 +1382,8 @@ struct window_S {
// out of range!)
int w_arg_idx_invalid; // editing another file than w_arg_idx
- char_u *w_localdir; /* absolute path of local directory or
- NULL */
+ char_u *w_localdir; // absolute path of local directory or NULL
+ char_u *w_prevdir; // previous directory
// Options local to a window.
// They are local because they influence the layout of the window or
// depend on the window layout.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b19ea36bd5..e6a3901dcf 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -9191,8 +9191,12 @@ static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, cons
} else if (*name == 'l' && funccal != NULL) { // local variable
*d = &funccal->l_vars;
} else if (*name == 's' // script variable
- && current_sctx.sc_sid > 0
+ && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR)
&& current_sctx.sc_sid <= ga_scripts.ga_len) {
+ // For anonymous scripts without a script item, create one now so script vars can be used
+ if (current_sctx.sc_sid == SID_STR) {
+ new_script_item(NULL, &current_sctx.sc_sid);
+ }
*d = &SCRIPT_SV(current_sctx.sc_sid)->sv_dict;
}
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 70aa2bb1f8..dfc51d80af 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -72,6 +72,7 @@ return {
chansend={args=2},
char2nr={args={1, 2}, base=1},
charidx={args={2, 3}},
+ chdir={args=1, base=1},
cindent={args=1, base=1},
clearmatches={args={0, 1}, base=1},
col={args=1, base=1},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index da129c1170..5faf2b0b81 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -28,6 +28,7 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/globals.h"
#include "nvim/if_cscope.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -1062,6 +1063,45 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = len > 0 ? len - 1 : 0;
}
+// "chdir(dir)" function
+static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ char_u *cwd;
+ CdScope scope = kCdScopeGlobal;
+
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+
+ if (argvars[0].v_type != VAR_STRING) {
+ // Returning an empty string means it failed.
+ // No error message, for historic reasons.
+ return;
+ }
+
+ // Return the current directory
+ cwd = xmalloc(MAXPATHL);
+ if (cwd != NULL) {
+ if (os_dirname(cwd, MAXPATHL) != FAIL) {
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(cwd);
+#endif
+ rettv->vval.v_string = vim_strsave(cwd);
+ }
+ xfree(cwd);
+ }
+
+ if (curwin->w_localdir != NULL) {
+ scope = kCdScopeWindow;
+ } else if (curtab->tp_localdir != NULL) {
+ scope = kCdScopeTabpage;
+ }
+
+ if (!changedir_func(argvars[0].vval.v_string, scope)) {
+ // Directory change failed
+ XFREE_CLEAR(rettv->vval.v_string);
+ }
+}
+
/*
* "cindent(lnum)" function
*/
@@ -3405,8 +3445,8 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Numbers of the scope objects (window, tab) we want the working directory
// of. A `-1` means to skip this scope, a `0` means the current object.
int scope_number[] = {
- [kCdScopeWindow] = 0, // Number of window to look at.
- [kCdScopeTab ] = 0, // Number of tab to look at.
+ [kCdScopeWindow ] = 0, // Number of window to look at.
+ [kCdScopeTabpage] = 0, // Number of tab to look at.
};
char_u *cwd = NULL; // Current working directory to print
@@ -3449,8 +3489,8 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// Find the tabpage by number
- if (scope_number[kCdScopeTab] > 0) {
- tp = find_tabpage(scope_number[kCdScopeTab]);
+ if (scope_number[kCdScopeTabpage] > 0) {
+ tp = find_tabpage(scope_number[kCdScopeTabpage]);
if (!tp) {
EMSG(_("E5000: Cannot find tab number."));
return;
@@ -3459,7 +3499,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Find the window in `tp` by number, `NULL` if none.
if (scope_number[kCdScopeWindow] >= 0) {
- if (scope_number[kCdScopeTab] < 0) {
+ if (scope_number[kCdScopeTabpage] < 0) {
EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0."));
return;
}
@@ -3483,7 +3523,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
}
FALLTHROUGH;
- case kCdScopeTab:
+ case kCdScopeTabpage:
assert(tp);
from = tp->tp_localdir;
if (from) {
@@ -4612,8 +4652,8 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Numbers of the scope objects (window, tab) we want the working directory
// of. A `-1` means to skip this scope, a `0` means the current object.
int scope_number[] = {
- [kCdScopeWindow] = 0, // Number of window to look at.
- [kCdScopeTab ] = 0, // Number of tab to look at.
+ [kCdScopeWindow ] = 0, // Number of window to look at.
+ [kCdScopeTabpage] = 0, // Number of tab to look at.
};
tabpage_T *tp = curtab; // The tabpage to look at.
@@ -4651,8 +4691,8 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// Find the tabpage by number
- if (scope_number[kCdScopeTab] > 0) {
- tp = find_tabpage(scope_number[kCdScopeTab]);
+ if (scope_number[kCdScopeTabpage] > 0) {
+ tp = find_tabpage(scope_number[kCdScopeTabpage]);
if (!tp) {
EMSG(_("E5000: Cannot find tab number."));
return;
@@ -4661,7 +4701,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Find the window in `tp` by number, `NULL` if none.
if (scope_number[kCdScopeWindow] >= 0) {
- if (scope_number[kCdScopeTab] < 0) {
+ if (scope_number[kCdScopeTabpage] < 0) {
EMSG(_("E5001: Higher scope cannot be -1 if lower scope is >= 0."));
return;
}
@@ -4680,7 +4720,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
assert(win);
rettv->vval.v_number = win->w_localdir ? 1 : 0;
break;
- case kCdScopeTab:
+ case kCdScopeTabpage:
assert(tp);
rettv->vval.v_number = tp->tp_localdir ? 1 : 0;
break;
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 657777d7db..7958ff6e13 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -1709,8 +1709,8 @@ char_u *trans_function_name(char_u **pp, bool skip, // only
}
start = *pp;
- /* Check for hard coded <SNR>: already translated function ID (from a user
- * command). */
+ // Check for hard coded <SNR>: already translated function ID (from a user
+ // command).
if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
&& (*pp)[2] == (int)KE_SNR) {
*pp += 3;
@@ -2032,8 +2032,8 @@ void ex_function(exarg_T *eap)
}
}
- /* An error in a function call during evaluation of an expression in magic
- * braces should not cause the function not to be defined. */
+ // An error in a function call during evaluation of an expression in magic
+ // braces should not cause the function not to be defined.
saved_did_emsg = did_emsg;
did_emsg = FALSE;
@@ -2105,8 +2105,8 @@ void ex_function(exarg_T *eap)
ga_init(&newlines, (int)sizeof(char_u *), 3);
if (!eap->skip) {
- /* Check the name of the function. Unless it's a dictionary function
- * (that we are overwriting). */
+ // Check the name of the function. Unless it's a dictionary function
+ // (that we are overwriting).
if (name != NULL) {
arg = name;
} else {
@@ -2164,8 +2164,8 @@ void ex_function(exarg_T *eap)
}
}
- /* When there is a line break use what follows for the function body.
- * Makes 'exe "func Test()\n...\nendfunc"' work. */
+ // When there is a line break use what follows for the function body.
+ // Makes 'exe "func Test()\n...\nendfunc"' work.
if (*p == '\n') {
line_arg = p + 1;
} else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) {
@@ -2176,9 +2176,9 @@ void ex_function(exarg_T *eap)
* Read the body of the function, until ":endfunction" is found.
*/
if (KeyTyped) {
- /* Check if the function already exists, don't let the user type the
- * whole function before telling him it doesn't work! For a script we
- * need to skip the body to be able to find what follows. */
+ // Check if the function already exists, don't let the user type the
+ // whole function before telling him it doesn't work! For a script we
+ // need to skip the body to be able to find what follows.
if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
EMSG(_(e_funcdict));
@@ -2305,8 +2305,8 @@ void ex_function(exarg_T *eap)
break;
}
- /* Increase indent inside "if", "while", "for" and "try", decrease
- * at "end". */
+ // Increase indent inside "if", "while", "for" and "try", decrease
+ // at "end".
if (indent > 2 && STRNCMP(p, "end", 3) == 0) {
indent -= 2;
} else if (STRNCMP(p, "if", 2) == 0
@@ -2421,8 +2421,8 @@ void ex_function(exarg_T *eap)
}
}
- /* Don't define the function when skipping commands or when an error was
- * detected. */
+ // Don't define the function when skipping commands or when an error was
+ // detected.
if (eap->skip || did_emsg) {
goto erret;
}
@@ -2640,8 +2640,8 @@ bool function_exists(const char *const name, bool no_deref)
NULL);
nm = skipwhite(nm);
- /* Only accept "funcname", "funcname ", "funcname (..." and
- * "funcname(...", not "funcname!...". */
+ // Only accept "funcname", "funcname ", "funcname (..." and
+ // "funcname(...", not "funcname!...".
if (p != NULL && (*nm == NUL || *nm == '(')) {
n = translated_function_exists(p);
}
@@ -2903,9 +2903,9 @@ void ex_return(exarg_T *eap)
}
}
- /* When skipping or the return gets pending, advance to the next command
- * in this line (!returning). Otherwise, ignore the rest of the line.
- * Following lines will be ignored by get_func_line(). */
+ // When skipping or the return gets pending, advance to the next command
+ // in this line (!returning). Otherwise, ignore the rest of the line.
+ // Following lines will be ignored by get_func_line().
if (returning) {
eap->nextcmd = NULL;
} else if (eap->nextcmd == NULL) { // no argument
@@ -3098,9 +3098,9 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
}
if (reanimate) {
- /* The pending return value could be overwritten by a ":return"
- * without argument in a finally clause; reset the default
- * return value. */
+ // The pending return value could be overwritten by a ":return"
+ // without argument in a finally clause; reset the default
+ // return value.
current_funccal->rettv->v_type = VAR_NUMBER;
current_funccal->rettv->vval.v_number = 0;
}
@@ -3109,9 +3109,9 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
} else {
current_funccal->returned = TRUE;
- /* If the return is carried out now, store the return value. For
- * a return immediately after reanimation, the value is already
- * there. */
+ // If the return is carried out now, store the return value. For
+ // a return immediately after reanimation, the value is already
+ // there.
if (!reanimate && rettv != NULL) {
tv_clear(current_funccal->rettv);
*current_funccal->rettv = *(typval_T *)rettv;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5d43a14168..4a23f284cc 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -361,8 +361,8 @@ static int linelen(int *has_tab)
return len;
}
-/* Buffer for two lines used during sorting. They are allocated to
- * contain the longest line being sorted. */
+// Buffer for two lines used during sorting. They are allocated to
+// contain the longest line being sorted.
static char_u *sortbuf1;
static char_u *sortbuf2;
@@ -404,9 +404,9 @@ static int sort_compare(const void *s1, const void *s2)
sorti_T l2 = *(sorti_T *)s2;
int result = 0;
- /* If the user interrupts, there's no way to stop qsort() immediately, but
- * if we return 0 every time, qsort will assume it's done sorting and
- * exit. */
+ // If the user interrupts, there's no way to stop qsort() immediately, but
+ // if we return 0 every time, qsort will assume it's done sorting and
+ // exit.
if (sort_abort) {
return 0;
}
@@ -1733,8 +1733,8 @@ int rename_buffer(char_u *new_fname)
*/
void ex_file(exarg_T *eap)
{
- /* ":0file" removes the file name. Check for illegal uses ":3file",
- * "0file name", etc. */
+ // ":0file" removes the file name. Check for illegal uses ":3file",
+ // "0file name", etc.
if (eap->addr_count > 0
&& (*eap->arg != NUL
|| eap->line2 > 0
@@ -1888,11 +1888,11 @@ int do_write(exarg_T *eap)
retval = FAIL;
goto theend;
}
- /* Exchange the file names for the current and the alternate
- * buffer. This makes it look like we are now editing the buffer
- * under the new name. Must be done before buf_write(), because
- * if there is no file name and 'cpo' contains 'F', it will set
- * the file name. */
+ // Exchange the file names for the current and the alternate
+ // buffer. This makes it look like we are now editing the buffer
+ // under the new name. Must be done before buf_write(), because
+ // if there is no file name and 'cpo' contains 'F', it will set
+ // the file name.
fname = alt_buf->b_fname;
alt_buf->b_fname = curbuf->b_fname;
curbuf->b_fname = fname;
@@ -1923,8 +1923,8 @@ int do_write(exarg_T *eap)
do_modelines(0);
}
- /* Autocommands may have changed buffer names, esp. when
- * 'autochdir' is set. */
+ // Autocommands may have changed buffer names, esp. when
+ // 'autochdir' is set.
fname = curbuf->b_sfname;
}
@@ -2003,11 +2003,11 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int
char_u *p;
char_u *swapname;
- /* We only try the first entry in 'directory', without checking if
- * it's writable. If the "." directory is not writable the write
- * will probably fail anyway.
- * Use 'shortname' of the current buffer, since there is no buffer
- * for the written file. */
+ // We only try the first entry in 'directory', without checking if
+ // it's writable. If the "." directory is not writable the write
+ // will probably fail anyway.
+ // Use 'shortname' of the current buffer, since there is no buffer
+ // for the written file.
if (*p_dir == NUL) {
dir = xmalloc(5);
STRCPY(dir, ".");
@@ -2466,8 +2466,8 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
}
}
- /* May jump to last used line number for a loaded buffer or when asked
- * for explicitly */
+ // May jump to last used line number for a loaded buffer or when asked
+ // for explicitly
if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST) {
pos = buflist_findfpos(buf);
newlnum = pos->lnum;
@@ -2577,10 +2577,10 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
}
}
- /* May get the window options from the last time this buffer
- * was in this window (or another window). If not used
- * before, reset the local window options to the global
- * values. Also restores old folding stuff. */
+ // May get the window options from the last time this buffer
+ // was in this window (or another window). If not used
+ // before, reset the local window options to the global
+ // values. Also restores old folding stuff.
get_winopts(curbuf);
did_get_winopts = true;
}
@@ -2621,10 +2621,10 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
goto theend;
}
- /* Since we are starting to edit a file, consider the filetype to be
- * unset. Helps for when an autocommand changes files and expects syntax
- * highlighting to work in the other file. */
- did_filetype = FALSE;
+ // Since we are starting to edit a file, consider the filetype to be
+ // unset. Helps for when an autocommand changes files and expects syntax
+ // highlighting to work in the other file.
+ did_filetype = false;
/*
* other_file oldbuf
@@ -2828,8 +2828,8 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
&& !auto_buf) {
int msg_scroll_save = msg_scroll;
- /* Obey the 'O' flag in 'cpoptions': overwrite any previous file
- * message. */
+ // Obey the 'O' flag in 'cpoptions': overwrite any previous file
+ // message.
if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) {
msg_scroll = FALSE;
}
@@ -2953,8 +2953,8 @@ void ex_append(exarg_T *eap)
}
}
if (eap->getline == NULL) {
- /* No getline() function, use the lines that follow. This ends
- * when there is no more. */
+ // No getline() function, use the lines that follow. This ends
+ // when there is no more.
if (eap->nextcmd == NULL || *eap->nextcmd == NUL) {
break;
}
@@ -3750,8 +3750,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
sub_firstline = vim_strsave(ml_get(sub_firstlnum));
}
- /* Save the line number of the last change for the final
- * cursor position (just like Vi). */
+ // Save the line number of the last change for the final
+ // cursor position (just like Vi).
curwin->w_cursor.lnum = lnum;
do_again = FALSE;
@@ -3778,8 +3778,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
goto skip;
}
- /* Normally we continue searching for a match just after the
- * previous match. */
+ // Normally we continue searching for a match just after the
+ // previous match.
matchcol = regmatch.endpos[0].col;
prev_matchcol = matchcol;
@@ -3818,8 +3818,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
do_check_cursorbind();
}
- /* When 'cpoptions' contains "u" don't sync undo when
- * asking for confirmation. */
+ // When 'cpoptions' contains "u" don't sync undo when
+ // asking for confirmation.
if (vim_strchr(p_cpo, CPO_UNDO) != NULL) {
++no_u_sync;
}
@@ -3970,11 +3970,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
}
if (typed == 'n') {
- /* For a multi-line match, put matchcol at the NUL at
- * the end of the line and set nmatch to one, so that
- * we continue looking for a match on the next line.
- * Avoids that ":%s/\nB\@=//gc" and ":%s/\n/,\r/gc"
- * get stuck when pressing 'n'. */
+ // For a multi-line match, put matchcol at the NUL at
+ // the end of the line and set nmatch to one, so that
+ // we continue looking for a match on the next line.
+ // Avoids that ":%s/\nB\@=//gc" and ":%s/\n/,\r/gc"
+ // get stuck when pressing 'n'.
if (nmatch > 1) {
matchcol = (colnr_T)STRLEN(sub_firstline);
skip_match = true;
@@ -3986,8 +3986,8 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
}
}
- /* Move the cursor to the start of the match, so that we can
- * use "\=col("."). */
+ // Move the cursor to the start of the match, so that we can
+ // use "\=col(".").
curwin->w_cursor.col = regmatch.startpos[0].col;
// When the match included the "$" of the last line it may
@@ -4178,11 +4178,11 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
// But ":s/\n/#/" is OK.
skip:
- /* We already know that we did the last subst when we are at
- * the end of the line, except that a pattern like
- * "bar\|\nfoo" may match at the NUL. "lnum" can be below
- * "line2" when there is a \zs in the pattern after a line
- * break. */
+ // We already know that we did the last subst when we are at
+ // the end of the line, except that a pattern like
+ // "bar\|\nfoo" may match at the NUL. "lnum" can be below
+ // "line2" when there is a \zs in the pattern after a line
+ // break.
lastone = (skip_match
|| got_int
|| got_quit
@@ -4249,8 +4249,8 @@ skip:
nmatch_tl = 0;
}
- /* When asking, undo is saved each time, must also set
- * changed flag each time. */
+ // When asking, undo is saved each time, must also set
+ // changed flag each time.
if (subflags.do_ask) {
changed_bytes(lnum, 0);
} else {
@@ -4278,9 +4278,9 @@ skip:
* 5. break if there isn't another match in this line
*/
if (nmatch <= 0) {
- /* If the match found didn't start where we were
- * searching, do the next search in the line where we
- * found the match. */
+ // If the match found didn't start where we were
+ // searching, do the next search in the line where we
+ // found the match.
if (nmatch == -1) {
lnum -= regmatch.startpos[0].lnum;
}
@@ -4329,9 +4329,9 @@ skip:
curbuf->deleted_bytes2 = 0;
if (first_line != 0) {
- /* Need to subtract the number of added lines from "last_line" to get
- * the line number before the change (same as adding the number of
- * deleted lines). */
+ // Need to subtract the number of added lines from "last_line" to get
+ // the line number before the change (same as adding the number of
+ // deleted lines).
i = curbuf->b_ml.ml_line_count - old_line_count;
changed_lines(first_line, 0, last_line - i, i, false);
@@ -4842,9 +4842,9 @@ void ex_help(exarg_T *eap)
}
fclose(helpfd);
- /* Split off help window; put it at far top if no position
- * specified, the current window is vertically split and
- * narrow. */
+ // Split off help window; put it at far top if no position
+ // specified, the current window is vertically split and
+ // narrow.
n = WSP_HELP;
if (cmdmod.split == 0 && curwin->w_width != Columns
&& curwin->w_width < 80) {
@@ -4884,9 +4884,9 @@ void ex_help(exarg_T *eap)
do_tag(tag, DT_HELP, 1, FALSE, TRUE);
- /* Delete the empty buffer if we're not using it. Careful: autocommands
- * may have jumped to another window, check that the buffer is not in a
- * window. */
+ // Delete the empty buffer if we're not using it. Careful: autocommands
+ // may have jumped to another window, check that the buffer is not in a
+ // window.
if (empty_fnum != 0 && curbuf->b_fnum != empty_fnum) {
buf = buflist_findnr(empty_fnum);
if (buf != NULL && buf->b_nwindows == 0) {
@@ -5057,11 +5057,11 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
}
if (i < 0) { // no match in table
- /* Replace "\S" with "/\\S", etc. Otherwise every tag is matched.
- * Also replace "\%^" and "\%(", they match every tag too.
- * Also "\zs", "\z1", etc.
- * Also "\@<", "\@=", "\@<=", etc.
- * And also "\_$" and "\_^". */
+ // Replace "\S" with "/\\S", etc. Otherwise every tag is matched.
+ // Also replace "\%^" and "\%(", they match every tag too.
+ // Also "\zs", "\z1", etc.
+ // Also "\@<", "\@=", "\@<=", etc.
+ // And also "\_$" and "\_^".
if (arg[0] == '\\'
&& ((arg[1] != NUL && arg[2] == NUL)
|| (vim_strchr((char_u *)"%_z@", arg[1]) != NULL
@@ -5158,8 +5158,8 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
*d++ = '\\';
}
- /* "CTRL-\_" -> "CTRL-\\_" to avoid the special meaning of "\_" in
- * "CTRL-\_CTRL-N" */
+ // "CTRL-\_" -> "CTRL-\\_" to avoid the special meaning of "\_" in
+ // "CTRL-\_CTRL-N"
if (STRNICMP(s, "CTRL-\\_", 7) == 0) {
STRCPY(d, "CTRL-\\\\");
d += 7;
@@ -5213,9 +5213,9 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
}
if (find_tags(IObuff, num_matches, matches, flags, MAXCOL, NULL) == OK
&& *num_matches > 0) {
- /* Sort the matches found on the heuristic number that is after the
- * tag name. */
- qsort((void *)*matches, (size_t)*num_matches,
+ // Sort the matches found on the heuristic number that is after the
+ // tag name.
+ qsort((void *)(*matches), (size_t)(*num_matches),
sizeof(char_u *), help_compare);
// Delete more than TAG_MANY to reduce the size of the listing.
while (*num_matches > TAG_MANY) {
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 40a2960a85..5d40d7a16a 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -52,33 +52,7 @@
#include "nvim/version.h"
#include "nvim/window.h"
-
/// Growarray to store info about already sourced scripts.
-/// Also store the dev/ino, so that we don't have to stat() each
-/// script when going through the list.
-typedef struct scriptitem_S {
- char_u *sn_name;
- bool file_id_valid;
- FileID file_id;
- bool sn_prof_on; ///< true when script is/was profiled
- bool sn_pr_force; ///< forceit: profile functions in this script
- proftime_T sn_pr_child; ///< time set when going into first child
- int sn_pr_nest; ///< nesting for sn_pr_child
- // profiling the script as a whole
- int sn_pr_count; ///< nr of times sourced
- proftime_T sn_pr_total; ///< time spent in script + children
- proftime_T sn_pr_self; ///< time spent in script itself
- proftime_T sn_pr_start; ///< time at script start
- proftime_T sn_pr_children; ///< time in children after script start
- // profiling the script per line
- garray_T sn_prl_ga; ///< things stored for every line
- proftime_T sn_prl_start; ///< start time for current line
- proftime_T sn_prl_children; ///< time spent in children for this line
- proftime_T sn_prl_wait; ///< wait start time for current line
- linenr_T sn_prl_idx; ///< index of line being timed; -1 if none
- int sn_prl_execed; ///< line being timed was executed
-} scriptitem_T;
-
static garray_T script_items = { 0, 0, sizeof(scriptitem_T), 4, NULL };
#define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
@@ -1939,6 +1913,29 @@ static char_u *get_str_line(int c, void *cookie, int indent, bool do_concat)
return ga.ga_data;
}
+/// Create a new script item and allocate script-local vars. @see new_script_vars
+///
+/// @param name File name of the script. NULL for anonymous :source.
+/// @param[out] sid_out SID of the new item.
+/// @return pointer to the created script item.
+scriptitem_T *new_script_item(char_u *const name, scid_T *const sid_out)
+{
+ static scid_T last_current_SID = 0;
+ const scid_T sid = ++last_current_SID;
+ if (sid_out != NULL) {
+ *sid_out = sid;
+ }
+ ga_grow(&script_items, (int)(sid - script_items.ga_len));
+ while (script_items.ga_len < sid) {
+ script_items.ga_len++;
+ SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
+ SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
+ }
+ SCRIPT_ITEM(sid).sn_name = name;
+ new_script_vars(sid); // Allocate the local script variables to use for this script.
+ return &SCRIPT_ITEM(sid);
+}
+
static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name)
{
char_u *save_sourcing_name = sourcing_name;
@@ -2036,7 +2033,6 @@ int do_source(char *fname, int check_other, int is_vimrc)
char_u *fname_exp;
char_u *firstline = NULL;
int retval = FAIL;
- static scid_T last_current_SID = 0;
static int last_current_SID_seq = 0;
int save_debug_break_level = debug_break_level;
scriptitem_T *si = NULL;
@@ -2183,15 +2179,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
}
}
if (current_sctx.sc_sid == 0) {
- current_sctx.sc_sid = ++last_current_SID;
- ga_grow(&script_items, (int)(current_sctx.sc_sid - script_items.ga_len));
- while (script_items.ga_len < current_sctx.sc_sid) {
- script_items.ga_len++;
- SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
- SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
- }
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
- si->sn_name = fname_exp;
+ si = new_script_item(fname_exp, &current_sctx.sc_sid);
fname_exp = vim_strsave(si->sn_name); // used for autocmd
if (file_id_ok) {
si->file_id_valid = true;
@@ -2199,9 +2187,6 @@ int do_source(char *fname, int check_other, int is_vimrc)
} else {
si->file_id_valid = false;
}
-
- // Allocate the local script variables to use for this script.
- new_script_vars(current_sctx.sc_sid);
}
if (l_do_profiling == PROF_YES) {
@@ -2375,16 +2360,21 @@ char_u *get_scriptname(LastSet last_set, bool *should_free)
case SID_LUA:
return (char_u *)_("Lua");
case SID_API_CLIENT:
- vim_snprintf((char *)IObuff, IOSIZE,
- _("API client (channel id %" PRIu64 ")"),
- last_set.channel_id);
+ snprintf((char *)IObuff, IOSIZE, _("API client (channel id %" PRIu64 ")"), last_set.channel_id);
return IObuff;
case SID_STR:
return (char_u *)_("anonymous :source");
- default:
+ default: {
+ char_u *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name;
+ if (sname == NULL) {
+ snprintf((char *)IObuff, IOSIZE, _("anonymous :source (script id %d)"),
+ last_set.script_ctx.sc_sid);
+ return IObuff;
+ }
+
*should_free = true;
- return home_replace_save(NULL,
- SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name);
+ return home_replace_save(NULL, sname);
+ }
}
}
diff --git a/src/nvim/ex_cmds2.h b/src/nvim/ex_cmds2.h
index de4e1429b7..d426ff28f8 100644
--- a/src/nvim/ex_cmds2.h
+++ b/src/nvim/ex_cmds2.h
@@ -16,6 +16,31 @@
#define CCGD_ALLBUF 8 // may write all buffers
#define CCGD_EXCMD 16 // may suggest using !
+/// Also store the dev/ino, so that we don't have to stat() each
+/// script when going through the list.
+typedef struct scriptitem_S {
+ char_u *sn_name;
+ bool file_id_valid;
+ FileID file_id;
+ bool sn_prof_on; ///< true when script is/was profiled
+ bool sn_pr_force; ///< forceit: profile functions in this script
+ proftime_T sn_pr_child; ///< time set when going into first child
+ int sn_pr_nest; ///< nesting for sn_pr_child
+ // profiling the script as a whole
+ int sn_pr_count; ///< nr of times sourced
+ proftime_T sn_pr_total; ///< time spent in script + children
+ proftime_T sn_pr_self; ///< time spent in script itself
+ proftime_T sn_pr_start; ///< time at script start
+ proftime_T sn_pr_children; ///< time in children after script start
+ // profiling the script per line
+ garray_T sn_prl_ga; ///< things stored for every line
+ proftime_T sn_prl_start; ///< start time for current line
+ proftime_T sn_prl_children; ///< time spent in children for this line
+ proftime_T sn_prl_wait; ///< wait start time for current line
+ linenr_T sn_prl_idx; ///< index of line being timed; -1 if none
+ int sn_prl_execed; ///< line being timed was executed
+} scriptitem_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_cmds2.h.generated.h"
#endif
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 16a9b78c6a..f649266b9f 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -197,8 +197,8 @@ void do_exmode(void)
exmode_active = true;
State = NORMAL;
- /* When using ":global /pat/ visual" and then "Q" we return to continue
- * the :global command. */
+ // When using ":global /pat/ visual" and then "Q" we return to continue
+ // the :global command.
if (global_busy) {
return;
}
@@ -231,8 +231,8 @@ void do_exmode(void)
EMSG(_(e_emptybuf));
} else {
if (ex_pressedreturn) {
- /* go up one line, to overwrite the ":<CR>" line, so the
- * output doesn't contain empty lines. */
+ // go up one line, to overwrite the ":<CR>" line, so the
+ // output doesn't contain empty lines.
msg_row = prev_msg_row;
if (prev_msg_row == Rows - 1) {
msg_row--;
@@ -374,8 +374,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
++ex_nesting_level;
}
- /* Get the function or script name and the address where the next breakpoint
- * line and the debug tick for a function or script are stored. */
+ // Get the function or script name and the address where the next breakpoint
+ // line and the debug tick for a function or script are stored.
if (getline_is_func) {
fname = func_name(real_cookie);
breakpoint = func_breakpoint(real_cookie);
@@ -500,11 +500,11 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
}
if (cstack.cs_looplevel > 0) {
- /* Inside a while/for loop we need to store the lines and use them
- * again. Pass a different "fgetline" function to do_one_cmd()
- * below, so that it stores lines in or reads them from
- * "lines_ga". Makes it possible to define a function inside a
- * while/for loop. */
+ // Inside a while/for loop we need to store the lines and use them
+ // again. Pass a different "fgetline" function to do_one_cmd()
+ // below, so that it stores lines in or reads them from
+ // "lines_ga". Makes it possible to define a function inside a
+ // while/for loop.
cmd_getline = get_loop_line;
cmd_cookie = (void *)&cmd_loop_cookie;
cmd_loop_cookie.lines_gap = &lines_ga;
@@ -612,8 +612,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
}
if (cmd_cookie == (void *)&cmd_loop_cookie) {
- /* Use "current_line" from "cmd_loop_cookie", it may have been
- * incremented when defining a function. */
+ // Use "current_line" from "cmd_loop_cookie", it may have been
+ // incremented when defining a function.
current_line = cmd_loop_cookie.current_line;
}
@@ -671,8 +671,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
cstack.cs_lflags |= CSL_HAD_LOOP;
line_breakcheck(); // check if CTRL-C typed
- /* Check for the next breakpoint at or after the ":while"
- * or ":for". */
+ // Check for the next breakpoint at or after the ":while"
+ // or ":for".
if (breakpoint != NULL) {
*breakpoint = dbg_find_breakpoint(getline_equal(fgetline, cookie, getsourceline),
fname,
@@ -724,8 +724,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
cstack.cs_flags[cstack.cs_idx] |= CSF_ACTIVE | CSF_FINALLY;
}
- /* Update global "trylevel" for recursive calls to do_cmdline() from
- * within this loop. */
+ // Update global "trylevel" for recursive calls to do_cmdline() from
+ // within this loop.
trylevel = initial_trylevel + cstack.cs_trylevel;
// If the outermost try conditional (across function calls and sourced
@@ -806,9 +806,9 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
trylevel = initial_trylevel;
}
- /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory
- * lack was reported above and the error message is to be converted to an
- * exception, do this now after rewinding the cstack. */
+ // If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory
+ // lack was reported above and the error message is to be converted to an
+ // exception, do this now after rewinding the cstack.
do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line)
? (char_u *)"endfunction" : (char_u *)NULL);
@@ -1014,9 +1014,9 @@ int getline_equal(LineGetter fgetline, void *cookie, LineGetter func)
LineGetter gp;
struct loop_cookie *cp;
- /* When "fgetline" is "get_loop_line()" use the "cookie" to find the
- * function that's originally used to obtain the lines. This may be
- * nested several levels. */
+ // When "fgetline" is "get_loop_line()" use the "cookie" to find the
+ // function that's originally used to obtain the lines. This may be
+ // nested several levels.
gp = fgetline;
cp = (struct loop_cookie *)cookie;
while (gp == get_loop_line) {
@@ -1035,9 +1035,9 @@ void *getline_cookie(LineGetter fgetline, void *cookie)
LineGetter gp;
struct loop_cookie *cp;
- /* When "fgetline" is "get_loop_line()" use the "cookie" to find the
- * cookie that's originally used to obtain the lines. This may be nested
- * several levels. */
+ // When "fgetline" is "get_loop_line()" use the "cookie" to find the
+ // cookie that's originally used to obtain the lines. This may be nested
+ // several levels.
gp = fgetline;
cp = (struct loop_cookie *)cookie;
while (gp == get_loop_line) {
@@ -2625,9 +2625,9 @@ static char_u *find_command(exarg_T *eap, int *full)
}
len = (int)(p - eap->cmd);
if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) {
- /* Check for ":dl", ":dell", etc. to ":deletel": that's
- * :delete with the 'l' flag. Same for 'p'. */
- for (i = 0; i < len; ++i) {
+ // Check for ":dl", ":dell", etc. to ":deletel": that's
+ // :delete with the 'l' flag. Same for 'p'.
+ for (i = 0; i < len; i++) {
if (eap->cmd[i] != ((char_u *)"delete")[i]) {
break;
}
@@ -4435,8 +4435,8 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
continue;
}
- /* Wildcards won't be expanded below, the replacement is taken
- * literally. But do expand "~/file", "~user/file" and "$HOME/file". */
+ // Wildcards won't be expanded below, the replacement is taken
+ // literally. But do expand "~/file", "~user/file" and "$HOME/file".
if (vim_strchr(repl, '$') != NULL || vim_strchr(repl, '~') != NULL) {
char_u *l = repl;
@@ -4463,8 +4463,8 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& !(eap->argt & EX_NOSPC)) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
- /* Don't escape a backslash here, because rem_backslash() doesn't
- * remove it later. */
+ // Don't escape a backslash here, because rem_backslash() doesn't
+ // remove it later.
static char_u *nobslash = (char_u *)" \t\"|";
# define ESCAPE_CHARS nobslash
#else
@@ -7205,8 +7205,8 @@ void ex_splitview(exarg_T *eap)
}
} else if (win_split(eap->addr_count > 0 ? (int)eap->line2 : 0,
*eap->cmd == 'v' ? WSP_VERT : 0) != FAIL) {
- /* Reset 'scrollbind' when editing another file, but keep it when
- * doing ":split" without arguments. */
+ // Reset 'scrollbind' when editing another file, but keep it when
+ // doing ":split" without arguments.
if (*eap->arg != NUL
) {
RESET_BINDING(curwin);
@@ -7402,8 +7402,8 @@ static void ex_find(exarg_T *eap)
fname = find_file_in_path(eap->arg, STRLEN(eap->arg),
FNAME_MESS, TRUE, curbuf->b_ffname);
if (eap->addr_count > 0) {
- /* Repeat finding the file "count" times. This matters when it
- * appears several times in the path. */
+ // Repeat finding the file "count" times. This matters when it
+ // appears several times in the path.
count = eap->line2;
while (fname != NULL && --count > 0) {
xfree(fname);
@@ -7509,8 +7509,8 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
if (!need_hide || buf_hide(curbuf)) {
cleanup_T cs;
- /* Reset the error/interrupt/exception state here so that
- * aborting() returns FALSE when closing a window. */
+ // Reset the error/interrupt/exception state here so that
+ // aborting() returns FALSE when closing a window.
enter_cleanup(&cs);
win_close(curwin, !need_hide && !buf_hide(curbuf));
@@ -7675,8 +7675,8 @@ static void ex_read(exarg_T *eap)
}
} else {
if (empty && exmode_active) {
- /* Delete the empty line that remains. Historically ex does
- * this but vi doesn't. */
+ // Delete the empty line that remains. Historically ex does
+ // this but vi doesn't.
if (eap->line2 == 0) {
lnum = curbuf->b_ml.ml_line_count;
} else {
@@ -7707,6 +7707,21 @@ void free_cd_dir(void)
#endif
+// Get the previous directory for the given chdir scope.
+static char_u *get_prevdir(CdScope scope)
+{
+ switch (scope) {
+ case kCdScopeTabpage:
+ return curtab->tp_prevdir;
+ break;
+ case kCdScopeWindow:
+ return curwin->w_prevdir;
+ break;
+ default:
+ return prev_dir;
+ }
+}
+
/// Deal with the side effects of changing the current directory.
///
/// @param scope Scope of the function call (global, tab or window).
@@ -7716,14 +7731,15 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
XFREE_CLEAR(curwin->w_localdir);
// Overwrite the tab-local CWD for :cd, :tcd.
- if (scope >= kCdScopeTab) {
+ if (scope >= kCdScopeTabpage) {
XFREE_CLEAR(curtab->tp_localdir);
}
if (scope < kCdScopeGlobal) {
+ char_u *pdir = get_prevdir(scope);
// If still in global directory, set CWD as the global directory.
- if (globaldir == NULL && prev_dir != NULL) {
- globaldir = vim_strsave(prev_dir);
+ if (globaldir == NULL && pdir != NULL) {
+ globaldir = vim_strsave(pdir);
}
}
@@ -7736,7 +7752,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
// We are now in the global directory, no need to remember its name.
XFREE_CLEAR(globaldir);
break;
- case kCdScopeTab:
+ case kCdScopeTabpage:
curtab->tp_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeWindow:
@@ -7749,59 +7765,92 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
shorten_fnames(true);
if (trigger_dirchanged) {
- do_autocmd_dirchanged(cwd, scope, false);
+ do_autocmd_dirchanged(cwd, scope, kCdCauseManual);
}
}
-/// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`.
-void ex_cd(exarg_T *eap)
+/// Change directory function used by :cd/:tcd/:lcd Ex commands and the chdir() function.
+/// @param new_dir The directory to change to.
+/// @param scope Scope of the function call (global, tab or window).
+/// @return true if the directory is successfully changed.
+bool changedir_func(char_u *new_dir, CdScope scope)
{
- char_u *new_dir;
char_u *tofree;
+ char_u *pdir = NULL;
+ bool retval = false;
- new_dir = eap->arg;
-#if !defined(UNIX)
- // for non-UNIX ":cd" means: print current directory
- if (*new_dir == NUL) {
- ex_pwd(NULL);
- } else
-#endif
- {
- if (allbuf_locked()) {
- return;
- }
+ if (new_dir == NULL || allbuf_locked()) {
+ return false;
+ }
- // ":cd -": Change to previous directory
- if (STRCMP(new_dir, "-") == 0) {
- if (prev_dir == NULL) {
- EMSG(_("E186: No previous directory"));
- return;
- }
- new_dir = prev_dir;
+ // ":cd -": Change to previous directory
+ if (STRCMP(new_dir, "-") == 0) {
+ pdir = get_prevdir(scope);
+ if (pdir == NULL) {
+ EMSG(_("E186: No previous directory"));
+ return false;
}
+ new_dir = pdir;
+ }
- // Save current directory for next ":cd -"
- tofree = prev_dir;
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- prev_dir = vim_strsave(NameBuff);
- } else {
- prev_dir = NULL;
- }
+ // Free the previous directory
+ tofree = get_prevdir(scope);
+
+ if (os_dirname(NameBuff, MAXPATHL) == OK) {
+ pdir = vim_strsave(NameBuff);
+ } else {
+ pdir = NULL;
+ }
+
+ switch (scope) {
+ case kCdScopeTabpage:
+ curtab->tp_prevdir = pdir;
+ break;
+ case kCdScopeWindow:
+ curwin->w_prevdir = pdir;
+ break;
+ default:
+ prev_dir = pdir;
+ }
#if defined(UNIX)
- // On Unix ":cd" means: go to home directory.
- if (*new_dir == NUL) {
- // Use NameBuff for home directory name.
- expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
- new_dir = NameBuff;
- }
+ // On Unix ":cd" means: go to home directory.
+ if (*new_dir == NUL) {
+ // Use NameBuff for home directory name.
+ expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
+ new_dir = NameBuff;
+ }
#endif
- CdScope scope = kCdScopeGlobal; // Depends on command invoked
+ if (vim_chdir(new_dir) == 0) {
+ bool dir_differs = pdir == NULL || pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
+ post_chdir(scope, dir_differs);
+ retval = true;
+ } else {
+ EMSG(_(e_failed));
+ }
+ xfree(tofree);
+
+ return retval;
+}
+
+/// ":cd", ":tcd", ":lcd", ":chdir", "tchdir" and ":lchdir".
+void ex_cd(exarg_T *eap)
+{
+ char_u *new_dir;
+ new_dir = eap->arg;
+#if !defined(UNIX) && !defined(VMS)
+ // for non-UNIX ":cd" means: print current directory
+ if (*new_dir == NUL) {
+ ex_pwd(NULL);
+ } else
+#endif
+ {
+ CdScope scope = kCdScopeGlobal;
switch (eap->cmdidx) {
case CMD_tcd:
case CMD_tchdir:
- scope = kCdScopeTab;
+ scope = kCdScopeTabpage;
break;
case CMD_lcd:
case CMD_lchdir:
@@ -7810,18 +7859,12 @@ void ex_cd(exarg_T *eap)
default:
break;
}
-
- if (vim_chdir(new_dir)) {
- EMSG(_(e_failed));
- } else {
- post_chdir(scope, true);
+ if (changedir_func(new_dir, scope)) {
// Echo the new current directory if the command was typed.
if (KeyTyped || p_verbose >= 5) {
ex_pwd(eap);
}
}
-
- xfree(tofree);
}
}
@@ -7834,7 +7877,17 @@ static void ex_pwd(exarg_T *eap)
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(NameBuff);
#endif
- msg(NameBuff);
+ if (p_verbose > 0) {
+ char *context = "global";
+ if (curwin->w_localdir != NULL) {
+ context = "window";
+ } else if (curtab->tp_localdir != NULL) {
+ context = "tabpage";
+ }
+ smsg("[%s] %s", context, (char *)NameBuff);
+ } else {
+ msg(NameBuff);
+ }
} else {
EMSG(_("E187: Unknown"));
}
@@ -8298,8 +8351,8 @@ static void ex_redir(exarg_T *eap)
}
}
- /* Make sure redirection is not off. Can happen for cmdline completion
- * that indirectly invokes a command to catch its output. */
+ // Make sure redirection is not off. Can happen for cmdline completion
+ // that indirectly invokes a command to catch its output.
if (redir_fd != NULL
|| redir_reg || redir_vname) {
redir_off = false;
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 21ddf7399b..09a1350f17 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -135,8 +135,8 @@ int should_abort(int retcode)
*/
int aborted_in_try(void)
{
- /* This function is only called after an error. In this case, "force_abort"
- * determines whether searching for finally clauses is necessary. */
+ // This function is only called after an error. In this case, "force_abort"
+ // determines whether searching for finally clauses is necessary.
return force_abort;
}
@@ -321,8 +321,8 @@ void do_errthrow(cstack_T *cstack, char_u *cmdname)
force_abort = TRUE;
}
- /* If no exception is to be thrown or the conversion should be done after
- * returning to a previous invocation of do_one_cmd(), do nothing. */
+ // If no exception is to be thrown or the conversion should be done after
+ // returning to a previous invocation of do_one_cmd(), do nothing.
if (msg_list == NULL || *msg_list == NULL) {
return;
}
@@ -471,8 +471,8 @@ static int throw_exception(void *value, except_type_T type, char_u *cmdname)
excp = xmalloc(sizeof(except_T));
if (type == ET_ERROR) {
- /* Store the original message and prefix the exception value with
- * "Vim:" or, if a command name is given, "Vim(cmdname):". */
+ // Store the original message and prefix the exception value with
+ // "Vim:" or, if a command name is given, "Vim(cmdname):".
excp->messages = (struct msglist *)value;
}
@@ -940,11 +940,11 @@ void ex_else(exarg_T *eap)
if (eap->cmdidx == CMD_elseif) {
bool error;
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
- /* When throwing error exceptions, we want to throw always the first
- * of several errors in a row. This is what actually happens when
- * a conditional error was detected above and there is another failure
- * when parsing the expression. Since the skip flag is set in this
- * case, the parsing error will be ignored by emsg(). */
+ // When throwing error exceptions, we want to throw always the first
+ // of several errors in a row. This is what actually happens when
+ // a conditional error was detected above and there is another failure
+ // when parsing the expression. Since the skip flag is set in this
+ // case, the parsing error will be ignored by emsg().
if (!skip && !error) {
if (result) {
@@ -1000,8 +1000,8 @@ void ex_while(exarg_T *eap)
* ":for var in list-expr"
*/
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) {
- /* Jumping here from a ":continue" or ":endfor": use the
- * previously evaluated list. */
+ // Jumping here from a ":continue" or ":endfor": use the
+ // previously evaluated list.
fi = cstack->cs_forinfo[cstack->cs_idx];
error = FALSE;
} else {
@@ -1033,10 +1033,10 @@ void ex_while(exarg_T *eap)
cstack->cs_lflags ^= CSL_HAD_LOOP;
} else {
cstack->cs_lflags &= ~CSL_HAD_LOOP;
- /* If the ":while" evaluates to FALSE or ":for" is past the end of
- * the list, show the debug prompt at the ":endwhile"/":endfor" as
- * if there was a ":break" in a ":while"/":for" evaluating to
- * TRUE. */
+ // If the ":while" evaluates to FALSE or ":for" is past the end of
+ // the list, show the debug prompt at the ":endwhile"/":endfor" as
+ // if there was a ":break" in a ":while"/":for" evaluating to
+ // TRUE.
if (!skip && !error) {
cstack->cs_flags[cstack->cs_idx] |= CSF_TRUE;
}
@@ -1125,8 +1125,8 @@ void ex_endwhile(exarg_T *eap)
} else {
fl = cstack->cs_flags[cstack->cs_idx];
if (!(fl & csf)) {
- /* If we are in a ":while" or ":for" but used the wrong endloop
- * command, do not rewind to the next enclosing ":for"/":while". */
+ // If we are in a ":while" or ":for" but used the wrong endloop
+ // command, do not rewind to the next enclosing ":for"/":while".
if (fl & CSF_WHILE) {
eap->errmsg = (char_u *)_("E732: Using :endfor with :while");
} else if (fl & CSF_FOR) {
@@ -1143,8 +1143,8 @@ void ex_endwhile(exarg_T *eap)
for (idx = cstack->cs_idx; idx > 0; --idx) {
fl = cstack->cs_flags[idx];
if ((fl & CSF_TRY) && !(fl & CSF_FINALLY)) {
- /* Give up at a try conditional not in its finally clause.
- * Ignore the ":endwhile"/":endfor". */
+ // Give up at a try conditional not in its finally clause.
+ // Ignore the ":endwhile"/":endfor".
eap->errmsg = err;
return;
}
@@ -1258,9 +1258,9 @@ void do_throw(cstack_T *cstack)
if (cstack->cs_flags[idx] & CSF_ACTIVE) {
cstack->cs_flags[idx] |= CSF_THROWN;
} else {
- /* THROWN may have already been set for a catchable exception
- * that has been discarded. Ensure it is reset for the new
- * exception. */
+ // THROWN may have already been set for a catchable exception
+ // that has been discarded. Ensure it is reset for the new
+ // exception.
cstack->cs_flags[idx] &= ~CSF_THROWN;
}
}
@@ -1288,9 +1288,9 @@ void ex_try(exarg_T *eap)
skip = CHECK_SKIP;
if (!skip) {
- /* Set ACTIVE and TRUE. TRUE means that the corresponding ":catch"
- * commands should check for a match if an exception is thrown and
- * that the finally clause needs to be executed. */
+ // Set ACTIVE and TRUE. TRUE means that the corresponding ":catch"
+ // commands should check for a match if an exception is thrown and
+ // that the finally clause needs to be executed.
cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
/*
@@ -1343,8 +1343,8 @@ void ex_catch(exarg_T *eap)
give_up = TRUE;
} else {
if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
- /* Report what's missing if the matching ":try" is not in its
- * finally clause. */
+ // Report what's missing if the matching ":try" is not in its
+ // finally clause.
eap->errmsg = get_end_emsg(cstack);
skip = TRUE;
}
@@ -1497,9 +1497,9 @@ void ex_finally(exarg_T *eap)
break;
}
}
- /* Make this error pending, so that the commands in the following
- * finally clause can be executed. This overrules also a pending
- * ":continue", ":break", ":return", or ":finish". */
+ // Make this error pending, so that the commands in the following
+ // finally clause can be executed. This overrules also a pending
+ // ":continue", ":break", ":return", or ":finish".
pending = CSTP_ERROR;
} else {
idx = cstack->cs_idx;
@@ -1524,14 +1524,14 @@ void ex_finally(exarg_T *eap)
skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE);
if (!skip) {
- /* When debugging or a breakpoint was encountered, display the
- * debug prompt (if not already done). The user then knows that the
- * finally clause is executed. */
+ // When debugging or a breakpoint was encountered, display the
+ // debug prompt (if not already done). The user then knows that the
+ // finally clause is executed.
if (dbg_check_skipped(eap)) {
- /* Handle a ">quit" debug command as if an interrupt had
- * occurred before the ":finally". That is, discard the
- * original exception and replace it by an interrupt
- * exception. */
+ // Handle a ">quit" debug command as if an interrupt had
+ // occurred before the ":finally". That is, discard the
+ // original exception and replace it by an interrupt
+ // exception.
(void)do_intthrow(cstack);
}
@@ -1732,13 +1732,13 @@ void ex_endtry(exarg_T *eap)
case CSTP_NONE:
break;
- /* Reactivate a pending ":continue", ":break", ":return",
- * ":finish" from the try block or a catch clause of this try
- * conditional. This is skipped, if there was an error in an
- * (unskipped) conditional command or an interrupt afterwards
- * or if the finally clause is present and executed a new error,
- * interrupt, throw, ":continue", ":break", ":return", or
- * ":finish". */
+ // Reactivate a pending ":continue", ":break", ":return",
+ // ":finish" from the try block or a catch clause of this try
+ // conditional. This is skipped, if there was an error in an
+ // (unskipped) conditional command or an interrupt afterwards
+ // or if the finally clause is present and executed a new error,
+ // interrupt, throw, ":continue", ":break", ":return", or
+ // ":finish".
case CSTP_CONTINUE:
ex_continue(eap);
break;
@@ -1866,10 +1866,10 @@ void leave_cleanup(cleanup_T *csp)
return;
}
- /* If there was an aborting error, an interrupt, or an uncaught exception
- * after the corresponding call to enter_cleanup(), discard what has been
- * made pending by it. Report this to the user if required by the
- * 'verbose' option or when debugging. */
+ // If there was an aborting error, an interrupt, or an uncaught exception
+ // after the corresponding call to enter_cleanup(), discard what has been
+ // 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).
@@ -1878,8 +1878,8 @@ void leave_cleanup(cleanup_T *csp)
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. */
+ // If an error was about to be converted to an exception when
+ // enter_cleanup() was called, free the message list.
if (msg_list != NULL) {
free_global_msglist();
}
@@ -1999,10 +1999,10 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
&& (cstack->cs_flags[idx] & CSF_CAUGHT)) {
finish_exception((except_T *)cstack->cs_exception[idx]);
}
- /* Stop at this try conditional - except the try block never
- * got active (because of an inactive surrounding conditional
- * or when the ":try" appeared after an error or interrupt or
- * throw). */
+ // Stop at this try conditional - except the try block never
+ // got active (because of an inactive surrounding conditional
+ // or when the ":try" appeared after an error or interrupt or
+ // throw).
if (cstack->cs_flags[idx] & CSF_TRUE) {
if (searched_cond == 0 && !inclusive) {
break;
@@ -2012,10 +2012,10 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
}
}
- /* Stop on the searched conditional type (even when the surrounding
- * conditional is not active or something has been made pending).
- * If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT,
- * check first whether "emsg_silent" needs to be restored. */
+ // Stop on the searched conditional type (even when the surrounding
+ // conditional is not active or something has been made pending).
+ // If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT,
+ // check first whether "emsg_silent" needs to be restored.
if (cstack->cs_flags[idx] & searched_cond) {
if (!inclusive) {
break;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 4c4d3e89e4..62a4d48645 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2637,8 +2637,8 @@ static void realloc_cmdbuff(int len)
&& ccline.xpc->xp_context != EXPAND_UNSUCCESSFUL) {
int i = (int)(ccline.xpc->xp_pattern - p);
- /* If xp_pattern points inside the old cmdbuff it needs to be adjusted
- * to point into the newly allocated memory. */
+ // If xp_pattern points inside the old cmdbuff it needs to be adjusted
+ // to point into the newly allocated memory.
if (i >= 0 && i <= ccline.cmdlen) {
ccline.xpc->xp_pattern = ccline.cmdbuff + i;
}
@@ -3457,8 +3457,8 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
return FAIL;
}
- /* When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate
- * part of the word. */
+ // When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate
+ // part of the word.
p = arg;
if (p_is && regname == Ctrl_W) {
char_u *w;
@@ -5976,8 +5976,8 @@ int set_cmdline_pos(int pos)
return 1;
}
- /* The position is not set directly but after CTRL-\ e or CTRL-R = has
- * changed the command line. */
+ // The position is not set directly but after CTRL-\ e or CTRL-R = has
+ // changed the command line.
if (pos < 0) {
new_cmdpos = 0;
} else {
@@ -6471,8 +6471,8 @@ static int open_cmdwin(void)
exmode_active = save_exmode;
- /* Safety check: The old window or buffer was deleted: It's a bug when
- * this happens! */
+ // Safety check: The old window or buffer was deleted: It's a bug when
+ // this happens!
if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) {
cmdwin_result = Ctrl_C;
EMSG(_("E199: Active window or buffer deleted"));
@@ -6498,8 +6498,8 @@ static int open_cmdwin(void)
stuffcharReadbuff(CAR);
}
} else if (cmdwin_result == Ctrl_C) {
- /* :q or :close, don't execute any command
- * and don't modify the cmd window. */
+ // :q or :close, don't execute any command
+ // and don't modify the cmd window.
ccline.cmdbuff = NULL;
} else {
ccline.cmdbuff = vim_strsave(get_cursor_line_ptr());
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 1e1da6a9a3..0dfd7e1edd 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -963,7 +963,7 @@ void ex_mkrc(exarg_T *eap)
*dirnow = NUL;
}
if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) {
- if (vim_chdirfile((char_u *)fname) == OK) {
+ if (vim_chdirfile((char_u *)fname, kCdCauseOther) == OK) {
shorten_fnames(true);
}
} else if (*dirnow != NUL
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 5458d8acf2..9eab579243 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -54,6 +54,7 @@
#include "nvim/eval.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
+#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
@@ -1590,7 +1591,7 @@ theend:
return file_name;
}
-void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
+void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
{
static bool recursive = false;
@@ -1609,8 +1610,8 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
case kCdScopeGlobal:
snprintf(buf, sizeof(buf), "global");
break;
- case kCdScopeTab:
- snprintf(buf, sizeof(buf), "tab");
+ case kCdScopeTabpage:
+ snprintf(buf, sizeof(buf), "tabpage");
break;
case kCdScopeWindow:
snprintf(buf, sizeof(buf), "window");
@@ -1620,11 +1621,30 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
abort();
}
+#ifdef BACKSLASH_IN_FILENAME
+ char new_dir_buf[MAXPATHL];
+ STRCPY(new_dir_buf, new_dir);
+ slash_adjust(new_dir_buf);
+ new_dir = new_dir_buf;
+#endif
+
tv_dict_add_str(dict, S_LEN("scope"), buf); // -V614
- tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
- tv_dict_add_bool(dict, S_LEN("changed_window"), changed_window);
+ tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
+ tv_dict_add_bool(dict, S_LEN("changed_window"), cause == kCdCauseWindow);
tv_dict_set_keys_readonly(dict);
+ switch (cause) {
+ case kCdCauseManual:
+ case kCdCauseWindow:
+ break;
+ case kCdCauseAuto:
+ snprintf(buf, sizeof(buf), "auto");
+ break;
+ case kCdCauseOther:
+ // Should never happen.
+ abort();
+ }
+
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
curbuf);
@@ -1636,7 +1656,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
/// Change to a file's directory.
/// Caller must call shorten_fnames()!
/// @return OK or FAIL
-int vim_chdirfile(char_u *fname)
+int vim_chdirfile(char_u *fname, CdCause cause)
{
char dir[MAXPATHL];
@@ -1647,17 +1667,14 @@ int vim_chdirfile(char_u *fname)
NameBuff[0] = NUL;
}
- if (os_chdir(dir) != 0) {
+ if (os_chdir(dir) == 0) {
+ if (cause != kCdCauseOther && pathcmp(dir, (char *)NameBuff, -1) != 0) {
+ do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
+ }
+ } else {
return FAIL;
}
-#ifdef BACKSLASH_IN_FILENAME
- slash_adjust((char_u *)dir);
-#endif
- if (!strequal(dir, (char *)NameBuff)) {
- do_autocmd_dirchanged(dir, kCdScopeWindow, false);
- }
-
return OK;
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index f5a4efc371..bd78818ab2 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -269,10 +269,10 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski
}
}
- /* Remember the initial values of curbuf, curbuf->b_ffname and
- * curbuf->b_fname to detect whether they are altered as a result of
- * executing nasty autocommands. Also check if "fname" and "sfname"
- * point to one of these values. */
+ // Remember the initial values of curbuf, curbuf->b_ffname and
+ // curbuf->b_fname to detect whether they are altered as a result of
+ // executing nasty autocommands. Also check if "fname" and "sfname"
+ // point to one of these values.
old_curbuf = curbuf;
old_b_ffname = curbuf->b_ffname;
old_b_fname = curbuf->b_fname;
@@ -429,8 +429,8 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski
curbuf->b_orig_mode = 0;
}
- /* Reset the "new file" flag. It will be set again below when the
- * file doesn't exist. */
+ // Reset the "new file" flag. It will be set again below when the
+ // file doesn't exist.
curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
}
@@ -514,8 +514,8 @@ int readfile(char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_ski
}
if (set_options) {
- /* Don't change 'eol' if reading from buffer as it will already be
- * correctly set when reading stdin. */
+ // Don't change 'eol' if reading from buffer as it will already be
+ // correctly set when reading stdin.
if (!read_buffer) {
curbuf->b_p_eol = TRUE;
curbuf->b_start_eol = TRUE;
@@ -816,8 +816,8 @@ retry:
fio_flags = 0;
converted = need_conversion(fenc);
if (converted) {
- /* "ucs-bom" means we need to check the first bytes of the file
- * for a BOM. */
+ // "ucs-bom" means we need to check the first bytes of the file
+ // for a BOM.
if (STRCMP(fenc, ENC_UCSBOM) == 0) {
fio_flags = FIO_UCSBOM;
} else {
@@ -949,16 +949,16 @@ retry:
ptr = buffer + linerest;
line_start = buffer;
- /* May need room to translate into.
- * For iconv() we don't really know the required space, use a
- * factor ICONV_MULT.
- * latin1 to utf-8: 1 byte becomes up to 2 bytes
- * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
- * become up to 4 bytes, size must be multiple of 2
- * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
- * multiple of 2
- * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
- * multiple of 4 */
+ // May need room to translate into.
+ // For iconv() we don't really know the required space, use a
+ // factor ICONV_MULT.
+ // latin1 to utf-8: 1 byte becomes up to 2 bytes
+ // utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
+ // become up to 4 bytes, size must be multiple of 2
+ // ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
+ // multiple of 2
+ // ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
+ // multiple of 4
real_size = (int)size;
#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
@@ -1000,9 +1000,9 @@ retry:
p = ml_get(read_buf_lnum) + read_buf_col;
n = (int)STRLEN(p);
if ((int)tlen + n + 1 > size) {
- /* Filled up to "size", append partial line.
- * Change NL to NUL to reverse the effect done
- * below. */
+ // Filled up to "size", append partial line.
+ // Change NL to NUL to reverse the effect done
+ // below.
n = (int)(size - tlen);
for (ni = 0; ni < n; ++ni) {
if (p[ni] == NL) {
@@ -1026,8 +1026,8 @@ retry:
ptr[tlen++] = NL;
read_buf_col = 0;
if (++read_buf_lnum > from) {
- /* When the last line didn't have an
- * end-of-line don't add it now either. */
+ // When the last line didn't have an
+ // end-of-line don't add it now either.
if (!curbuf->b_p_eol) {
--tlen;
}
@@ -1279,8 +1279,8 @@ retry:
}
}
- /* If there is a trailing incomplete sequence move it to
- * conv_rest[]. */
+ // If there is a trailing incomplete sequence move it to
+ // conv_rest[].
if (tail != NULL) {
conv_restlen = (int)((ptr + size) - tail);
memmove(conv_rest, tail, conv_restlen);
@@ -1320,8 +1320,8 @@ retry:
}
}
- /* found second word of double-word, get the first
- * word and compute the resulting character */
+ // found second word of double-word, get the first
+ // word and compute the resulting character
if (fio_flags & FIO_ENDIAN_L) {
u16c = (*--p << 8);
u16c += *--p;
@@ -1369,9 +1369,9 @@ retry:
p -= len;
u8c = utf_ptr2char(p);
if (len == 0) {
- /* Not a valid UTF-8 character, retry with
- * another fenc when possible, otherwise just
- * report the error. */
+ // Not a valid UTF-8 character, retry with
+ // another fenc when possible, otherwise just
+ // report the error.
if (can_retry) {
goto rewind_retry;
}
@@ -1435,9 +1435,9 @@ retry:
}
}
if (l == 1 || l > todo) {
- /* Illegal byte. If we can try another encoding
- * do that, unless at EOF where a truncated
- * file is more likely than a conversion error. */
+ // Illegal byte. If we can try another encoding
+ // do that, unless at EOF where a truncated
+ // file is more likely than a conversion error.
if (can_retry && !incomplete_tail) {
break;
}
@@ -1909,8 +1909,8 @@ failed:
*/
curbuf->b_no_eol_lnum = read_no_eol_lnum;
- /* When reloading a buffer put the cursor at the first line that is
- * different. */
+ // When reloading a buffer put the cursor at the first line that is
+ // different.
if (flags & READ_KEEP_UNDO) {
u_find_first_changed();
}
@@ -1929,8 +1929,8 @@ failed:
int m = msg_scroll;
int n = msg_scrolled;
- /* Save the fileformat now, otherwise the buffer will be considered
- * modified if the format/encoding was automatically detected. */
+ // Save the fileformat now, otherwise the buffer will be considered
+ // modified if the format/encoding was automatically detected.
if (set_options) {
save_file_ff(curbuf);
}
@@ -4804,15 +4804,15 @@ int check_timestamps(int focus)
{
int didit = 0;
- /* Don't check timestamps while system() or another low-level function may
- * cause us to lose and gain focus. */
+ // Don't check timestamps while system() or another low-level function may
+ // cause us to lose and gain focus.
if (no_check_timestamps > 0) {
return FALSE;
}
- /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
- * event and we would keep on checking if the file is steadily growing.
- * Do check again after typing something. */
+ // Avoid doing a check twice. The OK/Reload dialog can cause a focus
+ // event and we would keep on checking if the file is steadily growing.
+ // Do check again after typing something.
if (focus && did_check_timestamps) {
need_check_timestamps = TRUE;
return FALSE;
@@ -5025,8 +5025,8 @@ int buf_check_timestamp(buf_T *buf)
mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
mesg2 = _("See \":help W16\" for more info.");
} else {
- /* Only timestamp changed, store it to avoid a warning
- * in check_mtime() later. */
+ // Only timestamp changed, store it to avoid a warning
+ // in check_mtime() later.
buf->b_mtime_read = buf->b_mtime;
}
}
@@ -5623,12 +5623,11 @@ char_u *file_pat_to_reg_pat(const char_u *pat, const char_u *pat_end, char *allo
}
#ifdef BACKSLASH_IN_FILENAME
if (!no_bslash) {
- /* translate:
- * "\x" to "\\x" e.g., "dir\file"
- * "\*" to "\\.*" e.g., "dir\*.c"
- * "\?" to "\\." e.g., "dir\??.c"
- * "\+" to "\+" e.g., "fileX\+.c"
- */
+ // translate:
+ // "\x" to "\\x" e.g., "dir\file"
+ // "\*" to "\\.*" e.g., "dir\*.c"
+ // "\?" to "\\." e.g., "dir\??.c"
+ // "\+" to "\+" e.g., "fileX\+.c"
if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
&& p[1] != '+') {
reg_pat[i++] = '[';
@@ -5642,16 +5641,15 @@ char_u *file_pat_to_reg_pat(const char_u *pat, const char_u *pat_end, char *allo
}
}
#endif
- /* Undo escaping from ExpandEscape():
- * foo\?bar -> foo?bar
- * foo\%bar -> foo%bar
- * foo\,bar -> foo,bar
- * foo\ bar -> foo bar
- * Don't unescape \, * and others that are also special in a
- * regexp.
- * An escaped { must be unescaped since we use magic not
- * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
- */
+ // Undo escaping from ExpandEscape():
+ // foo\?bar -> foo?bar
+ // foo\%bar -> foo%bar
+ // foo\,bar -> foo,bar
+ // foo\ bar -> foo bar
+ // Don't unescape \, * and others that are also special in a
+ // regexp.
+ // An escaped { must be unescaped since we use magic not
+ // verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
if (*++p == '?'
#ifdef BACKSLASH_IN_FILENAME
&& no_bslash
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 5a2ce74666..e141f9bb62 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -224,8 +224,8 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp
break;
}
- /* Fold found, but it's open: Check nested folds. Line number is
- * relative to containing fold. */
+ // Fold found, but it's open: Check nested folds. Line number is
+ // relative to containing fold.
gap = &fp->fd_nested;
lnum_rel -= fp->fd_top;
++level;
@@ -264,8 +264,8 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp
*/
int foldLevel(linenr_T lnum)
{
- /* While updating the folds lines between invalid_top and invalid_bot have
- * an undefined fold level. Otherwise update the folds first. */
+ // While updating the folds lines between invalid_top and invalid_bot have
+ // an undefined fold level. Otherwise update the folds first.
if (invalid_top == (linenr_T)0) {
checkupdate(curwin);
} else if (lnum == prev_lnum && prev_lnum_lvl >= 0) {
@@ -492,9 +492,9 @@ static void newFoldLevelWin(win_T *wp)
checkupdate(wp);
if (wp->w_fold_manual) {
- /* Set all flags for the first level of folds to FD_LEVEL. Following
- * manual open/close will then change the flags to FD_OPEN or
- * FD_CLOSED for those folds that don't use 'foldlevel'. */
+ // Set all flags for the first level of folds to FD_LEVEL. Following
+ // manual open/close will then change the flags to FD_OPEN or
+ // FD_CLOSED for those folds that don't use 'foldlevel'.
fp = (fold_T *)wp->w_folds.ga_data;
for (int i = 0; i < wp->w_folds.ga_len; ++i) {
fp[i].fd_flags = FD_LEVEL;
@@ -904,8 +904,8 @@ int foldMoveTo(const bool updown, const int dir, const long count)
break;
}
- /* When moving up, consider a fold above the cursor; when
- * moving down consider a fold below the cursor. */
+ // When moving up, consider a fold above the cursor; when
+ // moving down consider a fold below the cursor.
if (dir == FORWARD) {
if (fp - (fold_T *)gap->ga_data >= gap->ga_len) {
break;
@@ -1424,13 +1424,13 @@ void deleteFoldRecurse(buf_T *bp, garray_T *gap)
*/
void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after)
{
- /* If deleting marks from line1 to line2, but not deleting all those
- * lines, set line2 so that only deleted lines have their folds removed. */
+ // If deleting marks from line1 to line2, but not deleting all those
+ // lines, set line2 so that only deleted lines have their folds removed.
if (amount == MAXLNUM && line2 >= line1 && line2 - line1 >= -amount_after) {
line2 = line1 - amount_after - 1;
}
- /* If appending a line in Insert mode, it should be included in the fold
- * just above the line. */
+ // If appending a line in Insert mode, it should be included in the fold
+ // just above the line.
if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) {
line1--;
}
@@ -1449,8 +1449,8 @@ static void foldMarkAdjustRecurse(win_T *wp, garray_T *gap, linenr_T line1, line
return;
}
- /* In Insert mode an inserted line at the top of a fold is considered part
- * of the fold, otherwise it isn't. */
+ // In Insert mode an inserted line at the top of a fold is considered part
+ // of the fold, otherwise it isn't.
if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) {
top = line1 + 1;
} else {
@@ -1580,8 +1580,8 @@ static bool check_closed(win_T *const wp, fold_T *const fp, bool *const use_leve
{
bool closed = false;
- /* Check if this fold is closed. If the flag is FD_LEVEL this
- * fold and all folds it contains depend on 'foldlevel'. */
+ // Check if this fold is closed. If the flag is FD_LEVEL this
+ // fold and all folds it contains depend on 'foldlevel'.
if (*use_levelp || fp->fd_flags == FD_LEVEL) {
*use_levelp = true;
if (level >= wp->w_p_fdl) {
@@ -2035,8 +2035,8 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
// Init marker variables to speed up foldlevelMarker().
parseMarker(wp);
- /* Need to get the level of the line above top, it is used if there is
- * no marker at the top. */
+ // Need to get the level of the line above top, it is used if there is
+ // no marker at the top.
if (top > 1) {
// Get the fold level at top - 1.
const int level = foldLevelWin(wp, top - 1);
@@ -2046,9 +2046,9 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
fline.lvl = level;
getlevel(&fline);
- /* If a fold started here, we already had the level, if it stops
- * here, we need to use lvl_next. Could also start and end a fold
- * in the same line. */
+ // If a fold started here, we already had the level, if it stops
+ // here, we need to use lvl_next. Could also start and end a fold
+ // in the same line.
if (fline.lvl > level) {
fline.lvl = level - (fline.lvl - fline.lvl_next);
} else {
@@ -2061,8 +2061,8 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
fline.lnum = top;
if (foldmethodIsExpr(wp)) {
getlevel = foldlevelExpr;
- /* start one line back, because a "<1" may indicate the end of a
- * fold in the topline */
+ // start one line back, because a "<1" may indicate the end of a
+ // fold in the topline
if (top > 1) {
--fline.lnum;
}
@@ -2151,9 +2151,9 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
end = fp->fd_top + fp->fd_len - 1;
} else if (getlevel == foldlevelSyntax
&& foldLevelWin(wp, fline.lnum) != fline.lvl) {
- /* For "syntax" method: Compare the foldlevel that the syntax
- * tells us to the foldlevel from the existing folds. If they
- * don't match continue updating folds. */
+ // For "syntax" method: Compare the foldlevel that the syntax
+ // tells us to the foldlevel from the existing folds. If they
+ // don't match continue updating folds.
end = fline.lnum;
} else {
break;
@@ -2185,9 +2185,9 @@ static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
changed_window_setting_win(wp);
}
- /* If we updated folds past "bot", need to redraw more lines. Don't do
- * this in other situations, the changed lines will be redrawn anyway and
- * this method can cause the whole window to be updated. */
+ // If we updated folds past "bot", need to redraw more lines. Don't do
+ // this in other situations, the changed lines will be redrawn anyway and
+ // this method can cause the whole window to be updated.
if (end != bot) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > top) {
wp->w_redraw_top = top;
@@ -2272,10 +2272,10 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
// Updating folds can be slow, check for CTRL-C.
line_breakcheck();
- /* Set "lvl" to the level of line "flp->lnum". When flp->start is set
- * and after the first line of the fold, set the level to zero to
- * force the fold to end. Do the same when had_end is set: Previous
- * line was marked as end of a fold. */
+ // Set "lvl" to the level of line "flp->lnum". When flp->start is set
+ // and after the first line of the fold, set the level to zero to
+ // force the fold to end. Do the same when had_end is set: Previous
+ // line was marked as end of a fold.
lvl = flp->lvl;
if (lvl > MAX_LEVEL) {
lvl = MAX_LEVEL;
@@ -2286,12 +2286,11 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
if (flp->lnum > bot && !finish && fp != NULL) {
- /* For "marker" and "syntax" methods:
- * - If a change caused a nested fold to be removed, we need to
- * delete it and continue at least until where it ended.
- * - If a change caused a nested fold to be created, or this fold
- * to continue below its original end, need to finish this fold.
- */
+ // For "marker" and "syntax" methods:
+ // - If a change caused a nested fold to be removed, we need to
+ // delete it and continue at least until where it ended.
+ // - If a change caused a nested fold to be created, or this fold
+ // to continue below its original end, need to finish this fold.
if (getlevel != foldlevelMarker
&& getlevel != foldlevelExpr
&& getlevel != foldlevelSyntax) {
@@ -2300,9 +2299,9 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
i = 0;
fp2 = fp;
if (lvl >= level) {
- /* Compute how deep the folds currently are, if it's deeper
- * than "lvl" then some must be deleted, need to update
- * at least one nested fold. */
+ // Compute how deep the folds currently are, if it's deeper
+ // than "lvl" then some must be deleted, need to update
+ // at least one nested fold.
ll = flp->lnum - fp->fd_top;
while (foldFind(&fp2->fd_nested, ll, &fp2)) {
++i;
@@ -2321,9 +2320,9 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
}
- /* At the start of the first nested fold and at the end of the current
- * fold: check if existing folds at this level, before the current
- * one, need to be deleted or truncated. */
+ // At the start of the first nested fold and at the end of the current
+ // fold: check if existing folds at this level, before the current
+ // one, need to be deleted or truncated.
if (fp == NULL
&& (lvl != level
|| flp->lnum_save >= bot
@@ -2356,10 +2355,10 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
|| (lvl >= level
&& fp->fd_top <= flp->lnum_save))))) {
if (fp->fd_top + fp->fd_len + concat > firstlnum) {
- /* Use existing fold for the new fold. If it starts
- * before where we started looking, extend it. If it
- * starts at another line, update nested folds to keep
- * their position, compensating for the new fd_top. */
+ // Use existing fold for the new fold. If it starts
+ // before where we started looking, extend it. If it
+ // starts at another line, update nested folds to keep
+ // their position, compensating for the new fd_top.
if (fp->fd_top == firstlnum) {
// We have found a fold beginning exactly where we want one.
} else if (fp->fd_top >= startlnum) {
@@ -2503,8 +2502,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
bot = flp->lnum;
}
- /* Line numbers in the nested fold are relative to the start of
- * this fold. */
+ // Line numbers in the nested fold are relative to the start of
+ // this fold.
flp->lnum = flp->lnum_save - fp->fd_top;
flp->off += fp->fd_top;
i = (int)(fp - (fold_T *)gap->ga_data);
@@ -2547,8 +2546,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
break;
}
- /* leave flp->lnum_save to lnum of the line that was used to get
- * the level, flp->lnum to the lnum of the next line. */
+ // leave flp->lnum_save to lnum of the line that was used to get
+ // the level, flp->lnum to the lnum of the next line.
flp->lnum_save = flp->lnum;
flp->lnum = ll;
}
@@ -2633,8 +2632,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
deleteFoldEntry(flp->wp, gap, (int)(fp2 - (fold_T *)gap->ga_data), true);
}
- /* Need to redraw the lines we inspected, which might be further down than
- * was asked for. */
+ // Need to redraw the lines we inspected, which might be further down than
+ // was asked for.
if (bot < flp->lnum - 1) {
bot = flp->lnum - 1;
}
@@ -2947,8 +2946,8 @@ static void foldMerge(win_T *const wp, fold_T *fp1, garray_T *gap, fold_T *fp2)
garray_T *gap1 = &fp1->fd_nested;
garray_T *gap2 = &fp2->fd_nested;
- /* If the last nested fold in fp1 touches the first nested fold in fp2,
- * merge them recursively. */
+ // If the last nested fold in fp1 touches the first nested fold in fp2,
+ // merge them recursively.
if (foldFind(gap1, fp1->fd_len - 1L, &fp3) && foldFind(gap2, 0L, &fp4)) {
foldMerge(wp, fp3, gap2, fp4);
}
@@ -2985,8 +2984,8 @@ static void foldlevelIndent(fline_T *flp)
buf = flp->wp->w_buffer;
s = skipwhite(ml_get_buf(buf, lnum, false));
- /* empty line or lines starting with a character in 'foldignore': level
- * depends on surrounding lines */
+ // empty line or lines starting with a character in 'foldignore': level
+ // depends on surrounding lines
if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) {
// first and last line can't be undefined, use level 0
if (lnum == 1 || lnum == buf->b_ml.ml_line_count) {
@@ -3089,8 +3088,8 @@ static void foldlevelExpr(fline_T *flp)
// "-1", "0", "1", ..: set fold level
default:
if (n < 0) {
- /* Use the current level for the next line, so that "a1"
- * will work there. */
+ // Use the current level for the next line, so that "a1"
+ // will work there.
flp->lvl_next = flp->lvl;
} else {
flp->lvl_next = n;
@@ -3099,8 +3098,8 @@ static void foldlevelExpr(fline_T *flp)
break;
}
- /* If the level is unknown for the first or the last line in the file, use
- * level 0. */
+ // If the level is unknown for the first or the last line in the file, use
+ // level 0.
if (flp->lvl < 0) {
if (lnum <= 1) {
flp->lvl = 0;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 1d120bbe6b..73cfffb0fb 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -335,7 +335,7 @@ EXTERN int garbage_collect_at_exit INIT(= false);
#define SID_WINLAYOUT -7 // changing window size
#define SID_LUA -8 // for Lua scripts/chunks
#define SID_API_CLIENT -9 // for API clients
-#define SID_STR -10 // for sourcing a string
+#define SID_STR -10 // for sourcing a string with no script item
// Script CTX being sourced or was sourced to define the current function.
EXTERN sctx_T current_sctx INIT(= { 0 COMMA 0 COMMA 0 });
@@ -1034,14 +1034,22 @@ typedef enum {
/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead.
typedef enum {
kCdScopeInvalid = -1,
- kCdScopeWindow, ///< Affects one window.
- kCdScopeTab, ///< Affects one tab page.
- kCdScopeGlobal, ///< Affects the entire Nvim instance.
+ kCdScopeWindow, ///< Affects one window.
+ kCdScopeTabpage, ///< Affects one tab page.
+ kCdScopeGlobal, ///< Affects the entire Nvim instance.
} CdScope;
#define MIN_CD_SCOPE kCdScopeWindow
#define MAX_CD_SCOPE kCdScopeGlobal
+/// What caused the current directory to change.
+typedef enum {
+ kCdCauseOther = -1,
+ kCdCauseManual, ///< Using `:cd`, `:tcd`, `:lcd` or `chdir()`.
+ kCdCauseWindow, ///< Switching to another window.
+ kCdCauseAuto, ///< On 'autochdir'.
+} CdCause;
+
// Only filled for Win32.
EXTERN char windowsVersion[20] INIT(= { 0 });
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 9a82eccc6f..00a43c9c79 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -583,9 +583,9 @@ void getout(int exitval)
{
exiting = true;
- /* When running in Ex mode an error causes us to exit with a non-zero exit
- * code. POSIX requires this, although it's not 100% clear from the
- * standard. */
+ // When running in Ex mode an error causes us to exit with a non-zero exit
+ // code. POSIX requires this, although it's not 100% clear from the
+ // standard.
if (exmode_active) {
exitval += ex_exitval;
}
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 835c2adbe5..ea9acdf31a 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -121,8 +121,8 @@ int setmark_pos(int c, pos_T *pos, int fnum)
return OK;
}
- /* Allow setting '[ and '] for an autocommand that simulates reading a
- * file. */
+ // Allow setting '[ and '] for an autocommand that simulates reading a
+ // file.
if (c == '[') {
buf->b_op_start = *pos;
return OK;
@@ -338,8 +338,8 @@ pos_T *getmark_buf_fnum(buf_T *buf, int c, bool changefile, int *fnum)
posp = NULL;
- /* Check for special key, can't be a mark name and might cause islower()
- * to crash. */
+ // Check for special key, can't be a mark name and might cause islower()
+ // to crash.
if (c < 0) {
return posp;
}
@@ -434,8 +434,7 @@ pos_T *getmark_buf_fnum(buf_T *buf, int c, bool changefile, int *fnum)
}
pos_copy.lnum = -1; // can't get file
} else {
- pos_copy.lnum = 0; /* mark exists, but is not valid in
- current buffer */
+ pos_copy.lnum = 0; // mark exists, but is not valid in current buffer
}
}
}
@@ -457,10 +456,10 @@ pos_T *getnextmark(pos_T *startpos, int dir, int begin_line)
pos = *startpos;
- /* When searching backward and leaving the cursor on the first non-blank,
- * position must be in a previous line.
- * When searching forward and leaving the cursor on the first non-blank,
- * position must be in a next line. */
+ // When searching backward and leaving the cursor on the first non-blank,
+ // position must be in a previous line.
+ // When searching forward and leaving the cursor on the first non-blank,
+ // position must be in a next line.
if (dir == BACKWARD && begin_line) {
pos.col = 0;
} else if (dir == FORWARD && begin_line) {
@@ -569,8 +568,8 @@ int check_mark(pos_T *pos)
return FAIL;
}
if (pos->lnum <= 0) {
- /* lnum is negative if mark is in another file can can't get that
- * file, error message already give then. */
+ // lnum is negative if mark is in another file can can't get that
+ // file, error message already give then.
if (pos->lnum == 0) {
EMSG(_(e_marknotset));
}
@@ -1058,9 +1057,9 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount, lo
*/
FOR_ALL_TAB_WINDOWS(tab, win) {
if (!cmdmod.lockmarks) {
- /* Marks in the jumplist. When deleting lines, this may create
- * duplicate marks in the jumplist, they will be removed later. */
- for (i = 0; i < win->w_jumplistlen; ++i) {
+ // Marks in the jumplist. When deleting lines, this may create
+ // duplicate marks in the jumplist, they will be removed later.
+ for (i = 0; i < win->w_jumplistlen; i++) {
if (win->w_jumplist[i].fmark.fnum == fnum) {
one_adjust_nodel(&(win->w_jumplist[i].fmark.mark.lnum));
}
@@ -1083,8 +1082,8 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount, lo
one_adjust_nodel(&(win->w_old_visual_lnum));
}
- /* topline and cursor position for windows with the same buffer
- * other than the current window */
+ // topline and cursor position for windows with the same buffer
+ // other than the current window
if (win != curwin) {
if (win->w_topline >= line1 && win->w_topline <= line2) {
if (amount == MAXLNUM) { // topline is deleted
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 253ddfc253..62cc3b56ed 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -190,9 +190,9 @@ enc_canon_table[] =
#define IDX_BIG5 29
{ "big5", ENC_DBCS, DBCS_CHT },
- /* MS-DOS and MS-Windows codepages are included here, so that they can be
- * used on Unix too. Most of them are similar to ISO-8859 encodings, but
- * not exactly the same. */
+ // MS-DOS and MS-Windows codepages are included here, so that they can be
+ // used on Unix too. Most of them are similar to ISO-8859 encodings, but
+ // not exactly the same.
#define IDX_CP437 30
{ "cp437", ENC_8BIT, 437 }, // like iso-8859-1
#define IDX_CP737 31
@@ -1066,8 +1066,8 @@ bool utf_printable(int c)
*/
return iswprint(c);
#else
- /* Sorted list of non-overlapping intervals.
- * 0xd800-0xdfff is reserved for UTF-16, actually illegal. */
+ // Sorted list of non-overlapping intervals.
+ // 0xd800-0xdfff is reserved for UTF-16, actually illegal.
static struct interval nonprint[] =
{
{ 0x070f, 0x070f }, { 0x180b, 0x180e }, { 0x200b, 0x200f }, { 0x202a, 0x202e },
@@ -1354,12 +1354,12 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, size_t n2
return c1 == 0 ? -1 : 1;
}
- /* Continue with bytewise comparison to produce some result that
- * would make comparison operations involving this function transitive.
- *
- * If only one string had an error, comparison should be made with
- * folded version of the other string. In this case it is enough
- * to fold just one character to determine the result of comparison. */
+ // Continue with bytewise comparison to produce some result that
+ // would make comparison operations involving this function transitive.
+ //
+ // If only one string had an error, comparison should be made with
+ // folded version of the other string. In this case it is enough
+ // to fold just one character to determine the result of comparison.
if (c1 != -1 && c2 == -1) {
n1 = utf_char2bytes(utf_fold(c1), buffer);
@@ -1637,8 +1637,8 @@ int utf_head_off(const char_u *base, const char_u *p)
while (q > base && (*q & 0xc0) == 0x80) {
--q;
}
- /* Check for illegal sequence. Do allow an illegal byte after where we
- * started. */
+ // Check for illegal sequence. Do allow an illegal byte after where we
+ // started.
len = utf8len_tab[*q];
if (len != (int)(s - q + 1) && len != (int)(p - q + 1)) {
return 0;
@@ -2335,8 +2335,8 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen
fromlen = slen;
for (;; ) {
if (len == 0 || ICONV_ERRNO == ICONV_E2BIG) {
- /* Allocate enough room for most conversions. When re-allocating
- * increase the buffer size. */
+ // Allocate enough room for most conversions. When re-allocating
+ // increase the buffer size.
len = len + fromlen * 2 + 40;
p = xmalloc(len);
if (done > 0) {
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 20ae5a4042..0874af5ee1 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -200,17 +200,17 @@ struct block0 {
*/
#define b0_flags b0_fname[B0_FNAME_SIZE_ORG - 2]
-/* The lowest two bits contain the fileformat. Zero means it's not set
- * (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or
- * EOL_MAC + 1. */
+// The lowest two bits contain the fileformat. Zero means it's not set
+// (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or
+// EOL_MAC + 1.
#define B0_FF_MASK 3
-/* Swap file is in directory of edited file. Used to find the file from
- * different mount points. */
+// Swap file is in directory of edited file. Used to find the file from
+// different mount points.
#define B0_SAME_DIR 4
-/* The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it.
- * When empty there is only the NUL. */
+// The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it.
+// When empty there is only the NUL.
#define B0_HAS_FENC 8
#define STACK_INCR 5 // nr of entries added to ml_stack at a time
@@ -524,9 +524,9 @@ void ml_open_file(buf_T *buf)
// Flush block zero, so others can read it
if (mf_sync(mfp, MFS_ZERO) == OK) {
- /* Mark all blocks that should be in the swapfile as dirty.
- * Needed for when the 'swapfile' option was reset, so that
- * the swap file was deleted, and then on again. */
+ // Mark all blocks that should be in the swapfile as dirty.
+ // Needed for when the 'swapfile' option was reset, so that
+ // the swap file was deleted, and then on again.
mf_set_dirty(mfp);
break;
}
@@ -580,8 +580,8 @@ void ml_close(buf_T *buf, int del_file)
XFREE_CLEAR(buf->b_ml.ml_chunksize);
buf->b_ml.ml_mfp = NULL;
- /* Reset the "recovered" flag, give the ATTENTION prompt the next time
- * this buffer is loaded. */
+ // Reset the "recovered" flag, give the ATTENTION prompt the next time
+ // this buffer is loaded.
buf->b_flags &= ~BF_RECOVERED;
}
@@ -860,8 +860,8 @@ void ml_recover(bool checkext)
/*
* open the memfile from the old swap file
*/
- p = vim_strsave(fname_used); /* save "fname_used" for the message:
- mf_open() will consume "fname_used"! */
+ p = vim_strsave(fname_used); // save "fname_used" for the message:
+ // mf_open() will consume "fname_used"!
mfp = mf_open(fname_used, O_RDONLY);
fname_used = p;
if (mfp == NULL || mfp->mf_fd < 0) {
@@ -1199,8 +1199,8 @@ void ml_recover(bool checkext)
* Line ml_line_count + 1 in the dummy empty line.
*/
if (orig_file_status != OK || curbuf->b_ml.ml_line_count != lnum * 2 + 1) {
- /* Recovering an empty file results in two lines and the first line is
- * empty. Don't set the modified flag then. */
+ // Recovering an empty file results in two lines and the first line is
+ // empty. Don't set the modified flag then.
if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) {
changed_internal();
buf_inc_changedtick(curbuf);
@@ -1305,8 +1305,8 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
if (fname != NULL) {
#ifdef HAVE_READLINK
- /* Expand symlink in the file name, because the swap file is created
- * with the actual file instead of with the symlink. */
+ // Expand symlink in the file name, because the swap file is created
+ // with the actual file instead of with the symlink.
if (resolve_symlink(fname, fname_buf) == OK) {
fname_res = fname_buf;
} else
@@ -1761,9 +1761,9 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync)
return;
}
- /* We only want to stop when interrupted here, not when interrupted
- * before. */
- got_int = FALSE;
+ // We only want to stop when interrupted here, not when interrupted
+ // before.
+ got_int = false;
ml_flush_line(buf); // flush buffered line
(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); // flush locked block
@@ -3222,9 +3222,9 @@ int resolve_symlink(const char_u *fname, char_u *buf)
ret = readlink((char *)tmp, (char *)buf, MAXPATHL - 1);
if (ret <= 0) {
if (errno == EINVAL || errno == ENOENT) {
- /* Found non-symlink or not existing file, stop here.
- * When at the first level use the unmodified name, skip the
- * call to vim_FullName(). */
+ // Found non-symlink or not existing file, stop here.
+ // When at the first level use the unmodified name, skip the
+ // call to vim_FullName().
if (depth == 1) {
return FAIL;
}
@@ -4200,8 +4200,8 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
size += lnum - 1;
}
- /* Don't count the last line break if 'noeol' and ('bin' or
- * 'nofixeol'). */
+ // Don't count the last line break if 'noeol' and ('bin' or
+ // 'nofixeol').
if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol
&& lnum > buf->b_ml.ml_line_count) {
size -= ffdos + 1;
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 85e062009a..d89f58163f 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -343,8 +343,8 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg,
}
menup = &menu->next;
- /* Count menus, to find where this one needs to be inserted.
- * Ignore menus that are not in the menubar (PopUp and Toolbar) */
+ // Count menus, to find where this one needs to be inserted.
+ // Ignore menus that are not in the menubar (PopUp and Toolbar)
if (parent != NULL || menu_is_menubar(menu->name)) {
if (menu->priority <= pri_tab[pri_idx]) {
lower_pri = menup;
@@ -596,8 +596,8 @@ static int remove_menu(vimmenu_T **menup, char_u *name, int modes, bool silent)
break;
}
- /* Remove the menu item for the given mode[s]. If the menu item
- * is no longer valid in ANY mode, delete it */
+ // Remove the menu item for the given mode[s]. If the menu item
+ // is no longer valid in ANY mode, delete it
menu->modes &= ~modes;
if (modes & MENU_TIP_MODE) {
free_menu_string(menu, MENU_INDEX_TIP);
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 493c704f42..732e5ffc1f 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -349,8 +349,8 @@ static const struct nv_cmd {
// Sorted index of commands in nv_cmds[].
static short nv_cmd_idx[NV_CMDS_SIZE];
-/* The highest index for which
- * nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] */
+// The highest index for which
+// nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char]
static int nv_max_linear;
/*
@@ -3623,8 +3623,8 @@ void do_check_scrollbind(bool check)
static colnr_T old_leftcol = 0;
if (check && curwin->w_p_scb) {
- /* If a ":syncbind" command was just used, don't scroll, only reset
- * the values. */
+ // If a ":syncbind" command was just used, don't scroll, only reset
+ // the values.
if (did_syncbind) {
did_syncbind = false;
} else if (curwin == old_curwin) {
@@ -4264,8 +4264,8 @@ void scroll_redraw(int up, long count)
break;
}
}
- /* Mark w_topline as valid, otherwise the screen jumps back at the
- * end of the file. */
+ // Mark w_topline as valid, otherwise the screen jumps back at the
+ // end of the file.
check_cursor_moved(curwin);
curwin->w_valid |= VALID_TOPLINE;
}
@@ -4712,9 +4712,9 @@ dozet:
if (ptr == NULL) {
pos_T pos = curwin->w_cursor;
- /* Find bad word under the cursor. When 'spell' is
- * off this fails and find_ident_under_cursor() is
- * used below. */
+ // Find bad word under the cursor. When 'spell' is
+ // off this fails and find_ident_under_cursor() is
+ // used below.
emsg_off++;
len = spell_move_to(curwin, FORWARD, true, true, NULL);
emsg_off--;
@@ -4833,10 +4833,8 @@ static void nv_colon(cmdarg_T *cap)
&& (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
|| cap->oap->start.col >
(colnr_T)STRLEN(ml_get(cap->oap->start.lnum))
- || did_emsg
- )) {
- /* The start of the operator has become invalid by the Ex command.
- */
+ || did_emsg)) {
+ // The start of the operator has become invalid by the Ex command.
clearopbeep(cap->oap);
}
}
@@ -5667,8 +5665,8 @@ static int normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt, int *wrap
}
}
- /* "/$" will put the cursor after the end of the line, may need to
- * correct that here */
+ // "/$" will put the cursor after the end of the line, may need to
+ // correct that here
check_cursor();
return i;
}
@@ -5848,16 +5846,15 @@ static void nv_brackets(cmdarg_T *cap)
}
c = gchar_cursor();
if (c == '{' || c == '}') {
- /* Must have found end/start of class: use it.
- * Or found the place to be at. */
+ // Must have found end/start of class: use it.
+ // Or found the place to be at.
if ((c == findc && norm) || (n == 1 && !norm)) {
new_pos = curwin->w_cursor;
pos = &new_pos;
n = 0;
- }
- /* if no match found at all, we started outside of the
- * class and we're inside now. Just go on. */
- else if (new_pos.lnum == 0) {
+ } else if (new_pos.lnum == 0) {
+ // if no match found at all, we started outside of the
+ // class and we're inside now. Just go on.
new_pos = curwin->w_cursor;
pos = &new_pos;
}
@@ -6306,8 +6303,8 @@ static void v_swap_corners(int cmdchar)
curwin->w_cursor.lnum = old_cursor.lnum;
curwin->w_curswant = right;
- /* 'selection "exclusive" and cursor at right-bottom corner: move it
- * right one column */
+ // 'selection "exclusive" and cursor at right-bottom corner: move it
+ // right one column
if (old_cursor.lnum >= VIsual.lnum && *p_sel == 'e') {
++curwin->w_curswant;
}
@@ -6479,8 +6476,8 @@ static void v_visop(cmdarg_T *cap)
{
static char_u trans[] = "YyDdCcxdXdAAIIrr";
- /* Uppercase means linewise, except in block mode, then "D" deletes till
- * the end of the line, and "C" replaces till EOL */
+ // Uppercase means linewise, except in block mode, then "D" deletes till
+ // the end of the line, and "C" replaces till EOL
if (isupper(cap->cmdchar)) {
if (VIsual_mode != Ctrl_V) {
VIsual_mode_orig = VIsual_mode;
@@ -6912,8 +6909,8 @@ static void nv_g_cmd(cmdarg_T *cap)
VIsual_active = true;
VIsual_reselect = true;
- /* Set Visual to the start and w_cursor to the end of the Visual
- * area. Make sure they are on an existing character. */
+ // Set Visual to the start and w_cursor to the end of the Visual
+ // area. Make sure they are on an existing character.
check_cursor();
VIsual = curwin->w_cursor;
curwin->w_cursor = tpos;
@@ -6956,10 +6953,9 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_visual(cap);
break;
- /* "gn", "gN" visually select next/previous search match
- * "gn" selects next match
- * "gN" selects previous match
- */
+ // "gn", "gN" visually select next/previous search match
+ // "gn" selects next match
+ // "gN" selects previous match
case 'N':
case 'n':
if (!current_search(cap->count1, cap->nchar == 'n')) {
@@ -7033,9 +7029,9 @@ static void nv_g_cmd(cmdarg_T *cap)
} else {
i = curwin->w_leftcol;
}
- /* Go to the middle of the screen line. When 'number' or
- * 'relativenumber' is on and lines are wrapping the middle can be more
- * to the left. */
+ // Go to the middle of the screen line. When 'number' or
+ // 'relativenumber' is on and lines are wrapping the middle can be more
+ // to the left.
if (cap->nchar == 'm') {
i += (curwin->w_width_inner - curwin_col_off()
+ ((curwin->w_p_wrap && i > 0)
@@ -7683,11 +7679,10 @@ static void nv_wordcmd(cmdarg_T *cap)
*/
static void adjust_cursor(oparg_T *oap)
{
- /* The cursor cannot remain on the NUL when:
- * - the column is > 0
- * - not in Visual mode or 'selection' is "o"
- * - 'virtualedit' is not "all" and not "onemore".
- */
+ // The cursor cannot remain on the NUL when:
+ // - the column is > 0
+ // - not in Visual mode or 'selection' is "o"
+ // - 'virtualedit' is not "all" and not "onemore".
if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL
&& (!VIsual_active || *p_sel == 'o')
&& !virtual_active() &&
@@ -7956,8 +7951,8 @@ static void nv_edit(cmdarg_T *cap)
if (curwin->w_cursor.coladd && cap->cmdchar != 'A') {
int save_State = State;
- /* Pretend Insert mode here to allow the cursor on the
- * character past the end of the line */
+ // Pretend Insert mode here to allow the cursor on the
+ // character past the end of the line
State = INSERT;
coladvance(getviscol());
State = save_State;
@@ -7974,9 +7969,9 @@ static void invoke_edit(cmdarg_T *cap, int repl, int cmd, int startln)
{
int restart_edit_save = 0;
- /* Complicated: When the user types "a<C-O>a" we don't want to do Insert
- * mode recursively. But when doing "a<C-O>." or "a<C-O>rx" we do allow
- * it. */
+ // Complicated: When the user types "a<C-O>a" we don't want to do Insert
+ // mode recursively. But when doing "a<C-O>." or "a<C-O>rx" we do allow
+ // it.
if (repl || !stuff_empty()) {
restart_edit_save = restart_edit;
} else {
@@ -8260,8 +8255,8 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
&& curwin->w_cursor.col < curbuf->b_op_start.col)
|| (VIsual_mode == 'V'
&& curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) {
- /* cursor is at the end of the line or end of file, put
- * forward. */
+ // cursor is at the end of the line or end of file, put
+ // forward.
dir = FORWARD;
}
// May have been reset in do_put().
@@ -8275,8 +8270,8 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
xfree(savereg);
}
- /* What to reselect with "gv"? Selecting the just put text seems to
- * be the most useful, since the original text was removed. */
+ // What to reselect with "gv"? Selecting the just put text seems to
+ // be the most useful, since the original text was removed.
if (was_visual) {
curbuf->b_visual.vi_start = curbuf->b_op_start;
curbuf->b_visual.vi_end = curbuf->b_op_end;
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 8bc2b3781a..55c34586cb 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -435,9 +435,9 @@ static void shift_block(oparg_T *oap, int amount)
* non-whitespace character.
*/
- /* If "bd.startspaces" is set, "bd.textstart" points to the character,
- * the part of which is displayed at the block's beginning. Let's start
- * searching from the next character. */
+ // If "bd.startspaces" is set, "bd.textstart" points to the character,
+ // the part of which is displayed at the block's beginning. Let's start
+ // searching from the next character.
if (bd.startspaces) {
MB_PTR_ADV(non_white);
}
@@ -614,8 +614,8 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
skipped, offset-startcol, kExtmarkUndo);
if (lnum == oap->end.lnum) {
- /* Set "']" mark to the end of the block instead of the end of
- * the insert in the first line. */
+ // Set "']" mark to the end of the block instead of the end of
+ // the insert in the first line.
curbuf->b_op_end.lnum = oap->end.lnum;
curbuf->b_op_end.col = offset;
}
@@ -1846,8 +1846,8 @@ int op_replace(oparg_T *oap, int c)
numc -= (oap->end_vcol - bd.end_vcol) + 1;
}
- /* A double-wide character can be replaced only up to half the
- * times. */
+ // A double-wide character can be replaced only up to half the
+ // times.
if ((*mb_char2cells)(c) > 1) {
if ((numc & 1) && !bd.is_short) {
++bd.endspaces;
@@ -1938,8 +1938,8 @@ int op_replace(oparg_T *oap, int c)
n = gchar_cursor();
if (n != NUL) {
if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1) {
- /* This is slow, but it handles replacing a single-byte
- * with a multi-byte and the other way around. */
+ // This is slow, but it handles replacing a single-byte
+ // with a multi-byte and the other way around.
if (curwin->w_cursor.lnum == oap->end.lnum) {
oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n);
}
@@ -1949,8 +1949,8 @@ int op_replace(oparg_T *oap, int c)
int end_vcol = 0;
if (curwin->w_cursor.lnum == oap->end.lnum) {
- /* oap->end has to be recalculated when
- * the tab breaks */
+ // oap->end has to be recalculated when
+ // the tab breaks
end_vcol = getviscol2(oap->end.col,
oap->end.coladd);
}
@@ -1969,9 +1969,9 @@ int op_replace(oparg_T *oap, int c)
virtcols -= oap->start.coladd;
}
- /* oap->end has been trimmed so it's effectively inclusive;
- * as a result an extra +1 must be counted so we don't
- * trample the NUL byte. */
+ // oap->end has been trimmed so it's effectively inclusive;
+ // as a result an extra +1 must be counted so we don't
+ // trample the NUL byte.
coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1);
curwin->w_cursor.col -= (virtcols + 1);
for (; virtcols >= 0; virtcols--) {
@@ -2228,8 +2228,8 @@ void op_insert(oparg_T *oap, long count1)
++curwin->w_cursor.col;
}
if (bd.is_short && !bd.is_MAX) {
- /* First line was too short, make it longer and adjust the
- * values in "bd". */
+ // First line was too short, make it longer and adjust the
+ // values in "bd".
if (u_save_cursor() == FAIL) {
return;
}
@@ -2386,8 +2386,8 @@ int op_change(oparg_T *oap)
}
}
- /* First delete the text in the region. In an empty buffer only need to
- * save for undo */
+ // First delete the text in the region. In an empty buffer only need to
+ // save for undo
if (curbuf->b_ml.ml_flags & ML_EMPTY) {
if (u_save_cursor() == FAIL) {
return FALSE;
@@ -3872,10 +3872,9 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
++comment_flags;
}
- /* If we found a colon, it means that we are not processing a line
- * starting with a closing part of a three-part comment. That's good,
- * because we don't want to remove those as this would be annoying.
- */
+ // If we found a colon, it means that we are not processing a line
+ // starting with a closing part of a three-part comment. That's good,
+ // because we don't want to remove those as this would be annoying.
if (*comment_flags == ':' || *comment_flags == NUL) {
line += lead_len;
}
@@ -4054,8 +4053,8 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
curwin->w_buffer->b_op_end.col = sumsize;
}
- /* Only report the change in the first line here, del_lines() will report
- * the deleted line. */
+ // Only report the change in the first line here, del_lines() will report
+ // the deleted line.
changed_lines(curwin->w_cursor.lnum, currsize,
curwin->w_cursor.lnum + 1, 0L, true);
@@ -4172,8 +4171,8 @@ void op_format(oparg_T *oap, int keep_cursor)
{
long old_line_count = curbuf->b_ml.ml_line_count;
- /* Place the cursor where the "gq" or "gw" command was given, so that "u"
- * can put it back there. */
+ // Place the cursor where the "gq" or "gw" command was given, so that "u"
+ // can put it back there.
curwin->w_cursor = oap->cursor_start;
if (u_save((linenr_T)(oap->start.lnum - 1),
@@ -4190,8 +4189,8 @@ void op_format(oparg_T *oap, int keep_cursor)
// Set '[ mark at the start of the formatted area
curbuf->b_op_start = oap->start;
- /* For "gw" remember the cursor position and put it back below (adjusted
- * for joined and split lines). */
+ // For "gw" remember the cursor position and put it back below (adjusted
+ // for joined and split lines).
if (keep_cursor) {
saved_cursor = oap->cursor_start;
}
@@ -4221,8 +4220,8 @@ void op_format(oparg_T *oap, int keep_cursor)
if (oap->is_VIsual) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_old_cursor_lnum != 0) {
- /* When lines have been inserted or deleted, adjust the end of
- * the Visual area to be redrawn. */
+ // When lines have been inserted or deleted, adjust the end of
+ // the Visual area to be redrawn.
if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum) {
wp->w_old_cursor_lnum += old_line_count;
} else {
@@ -4244,9 +4243,9 @@ void op_formatexpr(oparg_T *oap)
}
if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0) {
- /* As documented: when 'formatexpr' returns non-zero fall back to
- * internal formatting. */
- op_format(oap, FALSE);
+ // As documented: when 'formatexpr' returns non-zero fall back to
+ // internal formatting.
+ op_format(oap, false);
}
}
@@ -4424,8 +4423,8 @@ void format_lines(linenr_T line_count, int avoid_fex)
*/
if (is_end_par || force_format) {
if (need_set_indent) {
- /* replace indent in first line with minimal number of
- * tabs and spaces, according to current options */
+ // replace indent in first line with minimal number of
+ // tabs and spaces, according to current options
(void)set_indent(get_indent(), SIN_CHANGED);
}
@@ -4451,8 +4450,8 @@ void format_lines(linenr_T line_count, int avoid_fex)
// at end of par.: need to set indent of next par.
need_set_indent = is_end_par;
if (is_end_par) {
- /* When called with a negative line count, break at the
- * end of the paragraph. */
+ // When called with a negative line count, break at the
+ // end of the paragraph.
if (line_count < 0) {
break;
}
@@ -4674,9 +4673,9 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
} else {
bdp->startspaces = oap->end_vcol - oap->start_vcol + 1;
if (is_del && oap->op_type != OP_LSHIFT) {
- /* just putting the sum of those two into
- * bdp->startspaces doesn't work for Visual replace,
- * so we have to split the tab in two */
+ // just putting the sum of those two into
+ // bdp->startspaces doesn't work for Visual replace,
+ // so we have to split the tab in two
bdp->startspaces = bdp->start_char_vcols
- (bdp->start_vcol - oap->start_vcol);
bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 659e16268b..9466e841ce 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -615,8 +615,8 @@ static void set_option_default(int opt_idx, int opt_flags)
uint32_t flags = options[opt_idx].flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
- /* Use set_string_option_direct() for local options to handle
- * freeing and allocating the value. */
+ // Use set_string_option_direct() for local options to handle
+ // freeing and allocating the value.
if (options[opt_idx].indir != PV_NONE) {
set_string_option_direct(NULL, opt_idx,
options[opt_idx].def_val, opt_flags, 0);
@@ -1094,8 +1094,8 @@ int do_set(char_u *arg, int opt_flags)
flags = P_STRING;
}
- /* Skip all options that are not window-local (used when showing
- * an already loaded buffer in a window). */
+ // Skip all options that are not window-local (used when showing
+ // an already loaded buffer in a window).
if ((opt_flags & OPT_WINONLY)
&& (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
goto skip;
@@ -1514,8 +1514,8 @@ int do_set(char_u *arg, int opt_flags)
}
}
- /* concatenate the two strings; add a ',' if
- * needed */
+ // concatenate the two strings; add a ',' if
+ // needed
if (adding || prepending) {
comma = ((flags & P_COMMA) && *origval != NUL
&& *newval != NUL);
@@ -1540,8 +1540,8 @@ int do_set(char_u *arg, int opt_flags)
}
}
- /* Remove newval[] from origval[]. (Note: "i" has
- * been set above and is used here). */
+ // Remove newval[] from origval[]. (Note: "i" has
+ // been set above and is used here).
if (removing) {
STRCPY(newval, origval);
if (*s) {
@@ -4044,8 +4044,8 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
}
}
- /* Arabic requires a utf-8 encoding, inform the user if its not
- * set. */
+ // Arabic requires a utf-8 encoding, inform the user if its not
+ // set.
if (STRCMP(p_enc, "utf-8") != 0) {
static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
@@ -4070,12 +4070,12 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
changed_window_setting();
}
- /* 'arabicshape' isn't reset, it is a global option and
- * another window may still need it "on". */
+ // 'arabicshape' isn't reset, it is a global option and
+ // another window may still need it "on".
}
- /* 'delcombine' isn't reset, it is a global option and another
- * window may still want it "on". */
+ // 'delcombine' isn't reset, it is a global option and another
+ // window may still want it "on".
// Revert to the default keymap
curbuf->b_p_iminsert = B_IMODE_NONE;
@@ -5218,8 +5218,8 @@ int makeset(FILE *fd, int opt_flags, int local_only)
continue;
}
- /* Do not store options like 'bufhidden' and 'syntax' in a vimrc
- * file, they are always buffer-specific. */
+ // Do not store options like 'bufhidden' and 'syntax' in a vimrc
+ // file, they are always buffer-specific.
if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB)) {
continue;
}
@@ -5339,9 +5339,9 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, uint6
return FAIL;
}
if (*valuep != NULL) {
- /* Output 'pastetoggle' as key names. For other
- * options some characters have to be escaped with
- * CTRL-V or backslash */
+ // Output 'pastetoggle' as key names. For other
+ // options some characters have to be escaped with
+ // CTRL-V or backslash
if (valuep == &p_pt) {
s = *valuep;
while (*s != NUL) {
@@ -6605,8 +6605,8 @@ void ExpandOldSetting(int *num_file, char_u ***file)
char_u *buf = vim_strsave_escaped(var, escape_chars);
#ifdef BACKSLASH_IN_FILENAME
- /* For MS-Windows et al. we don't double backslashes at the start and
- * before a file name character. */
+ // For MS-Windows et al. we don't double backslashes at the start and
+ // before a file name character.
for (var = buf; *var != NUL; MB_PTR_ADV(var)) {
if (var[0] == '\\' && var[1] == '\\'
&& expand_option_idx >= 0
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index ea4f2ecaf1..24dc86e034 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -3005,8 +3005,8 @@ static void ungetchr(void)
at_start = prev_at_start;
prev_at_start = false;
- /* Backup regparse, so that it's at the same position as before the
- * getchr(). */
+ // Backup regparse, so that it's at the same position as before the
+ // getchr().
regparse -= prevchr_len;
}
@@ -6414,8 +6414,8 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
int c1, c2, c11, c12;
int junk;
- /* we have to handle the strcmp ourselves, since it is necessary to
- * deal with the composing characters by ignoring them: */
+ // we have to handle the strcmp ourselves, since it is necessary to
+ // deal with the composing characters by ignoring them:
str1 = s1;
str2 = s2;
c1 = c2 = 0;
@@ -7186,8 +7186,8 @@ static regengine_T nfa_regengine =
(char_u *)""
};
-/* Which regexp engine to use? Needed for vim_regcomp().
- * Must match with 'regexpengine'. */
+// Which regexp engine to use? Needed for vim_regcomp().
+// Must match with 'regexpengine'.
static int regexp_engine = 0;
#ifdef REGEXP_DEBUG
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index ec213d0adf..c8b7190b4a 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -374,8 +374,8 @@ nfa_regcomp_start (
/* A reasonable estimation for maximum size */
nstate_max = (STRLEN(expr) + 1) * 25;
- /* Some items blow up in size, such as [A-z]. Add more space for that.
- * When it is still not enough realloc_post_list() will be used. */
+ // Some items blow up in size, such as [A-z]. Add more space for that.
+ // When it is still not enough realloc_post_list() will be used.
nstate_max += 1000;
/* Size for postfix representation of expr. */
@@ -1426,8 +1426,8 @@ static int nfa_regatom(void)
}
break;
- /* Catch \%^ and \%$ regardless of where they appear in the
- * pattern -- regardless of whether or not it makes sense. */
+ // Catch \%^ and \%$ regardless of where they appear in the
+ // pattern -- regardless of whether or not it makes sense.
case '^':
EMIT(NFA_BOF);
break;
@@ -1468,13 +1468,13 @@ static int nfa_regatom(void)
EMIT(NFA_OPT_CHARS);
EMIT(n);
- /* Emit as "\%(\%[abc]\)" to be able to handle
- * "\%[abc]*" which would cause the empty string to be
- * matched an unlimited number of times. NFA_NOPEN is
- * added only once at a position, while NFA_SPLIT is
- * added multiple times. This is more efficient than
- * not allowing NFA_SPLIT multiple times, it is used
- * a lot. */
+ // Emit as "\%(\%[abc]\)" to be able to handle
+ // "\%[abc]*" which would cause the empty string to be
+ // matched an unlimited number of times. NFA_NOPEN is
+ // added only once at a position, while NFA_SPLIT is
+ // added multiple times. This is more efficient than
+ // not allowing NFA_SPLIT multiple times, it is used
+ // a lot.
EMIT(NFA_NOPEN);
break;
}
@@ -1884,8 +1884,8 @@ static int nfa_regpiece(void)
int my_post_start;
int quest;
- /* Save the current parse state, so that we can use it if <atom>{m,n} is
- * next. */
+ // Save the current parse state, so that we can use it if <atom>{m,n} is
+ // next.
save_parse_state(&old_state);
/* store current pos in the postfix form, for \{m,n} involving 0s */
@@ -1969,12 +1969,11 @@ static int nfa_regpiece(void)
break;
case Magic('{'):
- /* a{2,5} will expand to 'aaa?a?a?'
- * a{-1,3} will expand to 'aa??a??', where ?? is the nongreedy
- * version of '?'
- * \v(ab){2,3} will expand to '(ab)(ab)(ab)?', where all the
- * parenthesis have the same id
- */
+ // a{2,5} will expand to 'aaa?a?a?'
+ // a{-1,3} will expand to 'aa??a??', where ?? is the nongreedy
+ // version of '?'
+ // \v(ab){2,3} will expand to '(ab)(ab)(ab)?', where all the
+ // parenthesis have the same id
greedy = true;
c2 = peekchr();
@@ -1985,8 +1984,8 @@ static int nfa_regpiece(void)
if (!read_limits(&minval, &maxval))
EMSG_RET_FAIL(_("E870: (NFA regexp) Error reading repetition limits"));
- /* <atom>{0,inf}, <atom>{0,} and <atom>{} are equivalent to
- * <atom>* */
+ // <atom>{0,inf}, <atom>{0,} and <atom>{} are equivalent to
+ // <atom>*
if (minval == 0 && maxval == MAX_LIMIT) {
if (greedy)
/* \{}, \{0,} */
@@ -3329,10 +3328,10 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size)
break;
}
- /* Allow "NFA_MOPEN" as a valid postfix representation for
- * the empty regexp "". In this case, the NFA will be
- * NFA_MOPEN -> NFA_MCLOSE. Note that this also allows
- * empty groups of parenthesis, and empty mbyte chars */
+ // Allow "NFA_MOPEN" as a valid postfix representation for
+ // the empty regexp "". In this case, the NFA will be
+ // NFA_MOPEN -> NFA_MCLOSE. Note that this also allows
+ // empty groups of parenthesis, and empty mbyte chars
if (stackp == stack) {
s = alloc_state(mopen, NULL, NULL);
if (s == NULL)
@@ -3345,8 +3344,8 @@ static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size)
break;
}
- /* At least one node was emitted before NFA_MOPEN, so
- * at least one node will be between NFA_MOPEN and NFA_MCLOSE */
+ // At least one node was emitted before NFA_MOPEN, so
+ // at least one node will be between NFA_MOPEN and NFA_MCLOSE
e = POP();
s = alloc_state(mopen, e.start, NULL); /* `(' */
if (s == NULL)
@@ -3503,14 +3502,14 @@ static void nfa_postprocess(nfa_regprog_T *prog)
int ch_invisible = failure_chance(prog->state[i].out, 0);
int ch_follows = failure_chance(prog->state[i].out1->out, 0);
- /* Postpone when the invisible match is expensive or has a
- * lower chance of failing. */
+ // Postpone when the invisible match is expensive or has a
+ // lower chance of failing.
if (c == NFA_START_INVISIBLE_BEFORE
|| c == NFA_START_INVISIBLE_BEFORE_NEG) {
- /* "before" matches are very expensive when
- * unbounded, always prefer what follows then,
- * unless what follows will always match.
- * Otherwise strongly prefer what follows. */
+ // "before" matches are very expensive when
+ // unbounded, always prefer what follows then,
+ // unless what follows will always match.
+ // Otherwise strongly prefer what follows.
if (prog->state[i].val <= 0 && ch_follows > 0) {
directly = false;
} else {
@@ -3529,9 +3528,9 @@ static void nfa_postprocess(nfa_regprog_T *prog)
}
}
-/****************************************************************
-* NFA execution code.
-****************************************************************/
+/////////////////////////////////////////////////////////////////
+// NFA execution code.
+/////////////////////////////////////////////////////////////////
/* Values for done in nfa_pim_T. */
#define NFA_PIM_UNUSED 0 /* pim not used */
@@ -4197,8 +4196,8 @@ skip_add:
save_ptr = NULL;
memset(&save_multipos, 0, sizeof(save_multipos));
- /* Set the position (with "off" added) in the subexpression. Save
- * and restore it when it was in use. Otherwise fill any gap. */
+ // Set the position (with "off" added) in the subexpression. Save
+ // and restore it when it was in use. Otherwise fill any gap.
if (REG_MULTI) {
if (subidx < sub->in_use) {
save_multipos = sub->list.multi[subidx];
@@ -4297,8 +4296,8 @@ skip_add:
sub = &subs->norm;
}
- /* We don't fill in gaps here, there must have been an MOPEN that
- * has done that. */
+ // We don't fill in gaps here, there must have been an MOPEN that
+ // has done that.
save_in_use = sub->in_use;
if (sub->in_use <= subidx)
sub->in_use = subidx + 1;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 0bd9dbe0d5..63f3267d8a 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -5164,8 +5164,8 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in
if (row >= 0) {
if (wild_menu_showing == 0 || wild_menu_showing == WM_LIST) {
if (msg_scrolled > 0) {
- /* Put the wildmenu just above the command line. If there is
- * no room, scroll the screen one line up. */
+ // Put the wildmenu just above the command line. If there is
+ // no room, scroll the screen one line up.
if (cmdline_row == Rows - 1) {
msg_scroll_up(false);
msg_scrolled++;
@@ -7031,8 +7031,8 @@ int showmode(void)
if (VIsual_active) {
char *p;
- /* Don't concatenate separate words to avoid translation
- * problems. */
+ // Don't concatenate separate words to avoid translation
+ // problems.
switch ((VIsual_select ? 4 : 0)
+ (VIsual_mode == Ctrl_V) * 2
+ (VIsual_mode == 'V')) {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 3d30932d69..1b54d12042 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -839,14 +839,14 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
}
}
- /* With the SEARCH_END option move to the last character
- * of the match. Don't do it for an empty match, end
- * should be same as start then. */
+ // With the SEARCH_END option move to the last character
+ // of the match. Don't do it for an empty match, end
+ // should be same as start then.
if ((options & SEARCH_END) && !(options & SEARCH_NOOF)
&& !(matchpos.lnum == endpos.lnum
&& matchpos.col == endpos.col)) {
- /* For a match in the first column, set the position
- * on the NUL in the previous line. */
+ // For a match in the first column, set the position
+ // on the NUL in the previous line.
pos->lnum = lnum + endpos.lnum;
pos->col = endpos.col;
if (endpos.col == 0) {
@@ -1498,8 +1498,8 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
p = skipwhite(ptr);
pos->col = (colnr_T)(p - ptr);
- /* when adding lines the matching line may be empty but it is not
- * ignored because we are interested in the next line -- Acevedo */
+ // when adding lines the matching line may be empty but it is not
+ // ignored because we are interested in the next line -- Acevedo
if ((compl_cont_status & CONT_ADDING)
&& !(compl_cont_status & CONT_SOL)) {
if (mb_strcmp_ic((bool)p_ic, (const char *)p, (const char *)pat) == 0) {
@@ -1566,9 +1566,9 @@ int searchc(cmdarg_T *cap, int t_cmd)
c = *lastc;
// For multi-byte re-use last lastc_bytes[] and lastc_bytelen.
- /* Force a move of at least one char, so ";" and "," will move the
- * cursor, even if the cursor is right in front of char we are looking
- * at. */
+ // Force a move of at least one char, so ";" and "," will move the
+ // cursor, even if the cursor is right in front of char we are looking
+ // at.
if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd) {
stop = false;
}
@@ -2084,10 +2084,10 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
if (linep[pos.col - 1] == 'R'
&& linep[pos.col] == '"'
&& vim_strchr(linep + pos.col + 1, '(') != NULL) {
- /* Possible start of raw string. Now that we have the
- * delimiter we can check if it ends before where we
- * started searching, or before the previously found
- * raw string start. */
+ // Possible start of raw string. Now that we have the
+ // delimiter we can check if it ends before where we
+ // started searching, or before the previously found
+ // raw string start.
if (!find_rawstring_end(linep, &pos,
count > 0 ? &match_pos : &curwin->w_cursor)) {
count++;
@@ -2208,8 +2208,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
break;
case '"':
- /* a quote that is preceded with an odd number of backslashes is
- * ignored */
+ // a quote that is preceded with an odd number of backslashes is
+ // ignored
if (do_quotes) {
int col;
@@ -2282,8 +2282,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
bslcnt++;
}
}
- /* Only accept a match when 'M' is in 'cpo' or when escaping
- * is what we expect. */
+ // Only accept a match when 'M' is in 'cpo' or when escaping
+ // is what we expect.
if (cpo_bsl || (bslcnt & 1) == match_escaped) {
if (c == initc) {
count++;
@@ -3505,8 +3505,8 @@ int current_block(oparg_T *oap, long count, int include, int what, int other)
// Include the character under the cursor.
oap->inclusive = true;
} else {
- /* End is before the start (no text in between <>, [], etc.): don't
- * operate on any text. */
+ // End is before the start (no text in between <>, [], etc.): don't
+ // operate on any text.
curwin->w_cursor = start_pos;
}
}
@@ -4044,8 +4044,8 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
}
if (!vis_empty) {
- /* Check if the existing selection exactly spans the text inside
- * quotes. */
+ // Check if the existing selection exactly spans the text inside
+ // quotes.
if (vis_bef_curs) {
inside_quotes = VIsual.col > 0
&& line[VIsual.col - 1] == quotechar
@@ -4072,11 +4072,11 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
}
if (!vis_empty && line[col_start] == quotechar) {
- /* Already selecting something and on a quote character. Find the
- * next quoted string. */
+ // Already selecting something and on a quote character. Find the
+ // next quoted string.
if (vis_bef_curs) {
- /* Assume we are on a closing quote: move to after the next
- * opening quote. */
+ // Assume we are on a closing quote: move to after the next
+ // opening quote.
col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
if (col_start < 0) {
goto abort_search;
@@ -4800,8 +4800,8 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
file_line = xmalloc(LSIZE);
if (type != CHECK_PATH && type != FIND_DEFINE
- /* when CONT_SOL is set compare "ptr" with the beginning of the line
- * is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo */
+ // when CONT_SOL is set compare "ptr" with the beginning of the line
+ // is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
&& !(compl_cont_status & CONT_SOL)) {
pat = xmalloc(len + 5);
assert(len <= INT_MAX);
@@ -4946,10 +4946,9 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
// Nothing found, use the rest of the line.
p = incl_regmatch.endp[0];
i = (int)STRLEN(p);
- }
- /* Avoid checking before the start of the line, can
- * happen if \zs appears in the regexp. */
- else if (p > line) {
+ } else if (p > line) {
+ // Avoid checking before the start of the line, can
+ // happen if \zs appears in the regexp.
if (p[-1] == '"' || p[-1] == '<') {
--p;
++i;
@@ -5129,9 +5128,9 @@ search_line:
// IOSIZE > compl_length, so the STRNCPY works
STRNCPY(IObuff, aux, i);
- /* Get the next line: when "depth" < 0 from the current
- * buffer, otherwise from the included file. Jump to
- * exit_matched when past the last line. */
+ // Get the next line: when "depth" < 0 from the current
+ // buffer, otherwise from the included file. Jump to
+ // exit_matched when past the last line.
if (depth < 0) {
if (lnum >= end_lnum) {
goto exit_matched;
@@ -5142,9 +5141,9 @@ search_line:
goto exit_matched;
}
- /* we read a line, set "already" to check this "line" later
- * if depth >= 0 we'll increase files[depth].lnum far
- * bellow -- Acevedo */
+ // we read a line, set "already" to check this "line" later
+ // if depth >= 0 we'll increase files[depth].lnum far
+ // bellow -- Acevedo
already = aux = p = skipwhite(line);
p = find_word_start(p);
p = find_word_end(p);
@@ -5195,8 +5194,8 @@ search_line:
if (did_show) {
msg_putchar('\n'); // cursor below last one
}
- if (!got_int) { /* don't display if 'q' typed
- at "--more--" message */
+ if (!got_int) { // don't display if 'q' typed
+ // at "--more--" message
msg_home_replace_hl(curr_fname);
}
prev_fname = curr_fname;
@@ -5209,10 +5208,10 @@ search_line:
match_count++);
}
- /* Set matched flag for this file and all the ones that
- * include it */
- for (i = 0; i <= depth; ++i) {
- files[i].matched = TRUE;
+ // Set matched flag for this file and all the ones that
+ // include it
+ for (i = 0; i <= depth; i++) {
+ files[i].matched = true;
}
} else if (--count <= 0) {
found = true;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 2a501f4714..e3a6236ae4 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -2602,7 +2602,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
upp = vim_strsave(items[1]);
} else if (is_aff_rule(items, itemcnt, "REP", 2)
|| is_aff_rule(items, itemcnt, "REPSAL", 2)) {
- /* Ignore REP/REPSAL count */;
+ // Ignore REP/REPSAL count
if (!isdigit(*items[1])) {
smsg(_("Expected REP(SAL) count in %s line %d"),
fname, lnum);
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index ac4c81f6b3..3afc2aff52 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -230,11 +230,10 @@ struct name_list {
static char *(spo_name_tab[SPO_COUNT]) =
{ "ms=", "me=", "hs=", "he=", "rs=", "re=", "lc=" };
-/* The sp_off_flags are computed like this:
- * offset from the start of the matched text: (1 << SPO_XX_OFF)
- * offset from the end of the matched text: (1 << (SPO_XX_OFF + SPO_COUNT))
- * When both are present, only one is used.
- */
+// The sp_off_flags are computed like this:
+// offset from the start of the matched text: (1 << SPO_XX_OFF)
+// offset from the end of the matched text: (1 << (SPO_XX_OFF + SPO_COUNT))
+// When both are present, only one is used.
#define SPTYPE_MATCH 1 // match keyword with this group ID
#define SPTYPE_START 2 // match a regexp, start of item
@@ -345,7 +344,7 @@ static int next_seqnr = 1; // value to use for si_seqnr
*/
static int next_match_col; // column for start of next match
static lpos_T next_match_m_endpos; // position for end of next match
-static lpos_T next_match_h_startpos; // pos. for highl. start of next match
+static lpos_T next_match_h_startpos; // pos. for highl. start of next match
static lpos_T next_match_h_endpos; // pos. for highl. end of next match
static int next_match_idx; // index of matched item
static long next_match_flags; // flags for next match
@@ -492,8 +491,8 @@ void syntax_start(win_T *wp, linenr_T lnum)
// First line is always valid, no matter "minlines".
first_stored = 1;
} else {
- /* Need to parse "minlines" lines before state can be considered
- * valid to store. */
+ // Need to parse "minlines" lines before state can be considered
+ // valid to store.
first_stored = current_lnum + syn_block->b_syn_sync_minlines;
}
} else {
@@ -514,12 +513,12 @@ void syntax_start(win_T *wp, linenr_T lnum)
(void)syn_finish_line(false);
current_lnum++;
- /* If we parsed at least "minlines" lines or started at a valid
- * state, the current state is considered valid. */
+ // If we parsed at least "minlines" lines or started at a valid
+ // state, the current state is considered valid.
if (current_lnum >= first_stored) {
- /* Check if the saved state entry is for the current line and is
- * equal to the current state. If so, then validate all saved
- * states that depended on a change before the parsed line. */
+ // Check if the saved state entry is for the current line and is
+ // equal to the current state. If so, then validate all saved
+ // states that depended on a change before the parsed line.
if (prev == NULL) {
prev = syn_stack_find_entry(current_lnum - 1);
}
@@ -548,19 +547,18 @@ void syntax_start(win_T *wp, linenr_T lnum)
sp = sp->sst_next;
}
load_current_state(prev);
- }
- /* Store the state at this line when it's the first one, the line
- * where we start parsing, or some distance from the previously
- * saved state. But only when parsed at least 'minlines'. */
- else if (prev == NULL
- || current_lnum == lnum
- || current_lnum >= prev->sst_lnum + dist) {
+ } else if (prev == NULL
+ // Store the state at this line when it's the first one, the line
+ // where we start parsing, or some distance from the previously
+ // saved state. But only when parsed at least 'minlines'.
+ || current_lnum == lnum
+ || current_lnum >= prev->sst_lnum + dist) {
prev = store_current_state();
}
}
- /* This can take a long time: break when CTRL-C pressed. The current
- * state will be wrong then. */
+ // This can take a long time: break when CTRL-C pressed. The current
+ // state will be wrong then.
line_breakcheck();
if (got_int) {
current_lnum = lnum;
@@ -664,8 +662,8 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
* 1. Search backwards for the end of a C-style comment.
*/
if (syn_block->b_syn_sync_flags & SF_CCOMMENT) {
- /* Need to make syn_buf the current buffer for a moment, to be able to
- * use find_start_comment(). */
+ // Need to make syn_buf the current buffer for a moment, to be able to
+ // use find_start_comment().
curwin_save = curwin;
curwin = wp;
curbuf_save = curbuf;
@@ -793,9 +791,9 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
++current_col;
}
- /* syn_current_attr() will have skipped the check for
- * an item that ends here, need to do that now. Be
- * careful not to go past the NUL. */
+ // syn_current_attr() will have skipped the check for
+ // an item that ends here, need to do that now. Be
+ // careful not to go past the NUL.
prev_current_col = current_col;
if (syn_getcurline()[current_col] != NUL) {
++current_col;
@@ -987,9 +985,8 @@ static void syn_update_ends(bool startofline)
check_keepend();
}
-/****************************************
- * Handling of the state stack cache.
- */
+/////////////////////////////////////////
+// Handling of the state stack cache.
/*
* EXPLANATION OF THE SYNTAX STATE STACK CACHE
@@ -1081,8 +1078,8 @@ static void syn_stack_alloc(void)
}
if (syn_block->b_sst_array != NULL) {
- /* When shrinking the array, cleanup the existing stack.
- * Make sure that all valid entries fit in the new array. */
+ // When shrinking the array, cleanup the existing stack.
+ // Make sure that all valid entries fit in the new array.
while (syn_block->b_sst_len - syn_block->b_sst_freecount + 2 > len
&& syn_stack_cleanup()) {
;
@@ -1165,9 +1162,9 @@ static void syn_stack_apply_changes_block(synblock_T *block, buf_T *buf)
p = np;
continue;
}
- /* This state is below the changed area. Remember the line
- * that needs to be parsed before this entry can be made valid
- * again. */
+ // This state is below the changed area. Remember the line
+ // that needs to be parsed before this entry can be made valid
+ // again.
if (p->sst_change_lnum != 0 && p->sst_change_lnum > buf->b_mod_top) {
if (p->sst_change_lnum + buf->b_mod_xlines > buf->b_mod_top) {
p->sst_change_lnum += buf->b_mod_xlines;
@@ -1638,8 +1635,8 @@ int get_syntax_attr(const colnr_T col, bool *const can_spell, const bool keep_st
int attr = 0;
if (can_spell != NULL) {
- /* Default: Only do spelling when there is no @Spell cluster or when
- * ":syn spell toplevel" was used. */
+ // Default: Only do spelling when there is no @Spell cluster or when
+ // ":syn spell toplevel" was used.
*can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT
? (syn_block->b_spell_cluster_id == 0)
: (syn_block->b_syn_spell == SYNSPL_TOP);
@@ -1901,15 +1898,15 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
syn_add_start_off(&pos, &regmatch,
spp, SPO_MS_OFF, -1);
if (pos.lnum > current_lnum) {
- /* must have used end of match in a next line,
- * we can't handle that */
+ // must have used end of match in a next line,
+ // we can't handle that
spp->sp_startcol = MAXCOL;
continue;
}
startcol = pos.col;
- /* remember the next column where this pattern
- * matches in the current line */
+ // remember the next column where this pattern
+ // matches in the current line
spp->sp_startcol = startcol;
/*
@@ -1999,8 +1996,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
/*
* keep the best match so far in next_match_*
*/
- /* Highlighting must start after startpos and end
- * before endpos. */
+ // Highlighting must start after startpos and end
+ // before endpos.
if (hl_startpos.lnum == current_lnum
&& (int)hl_startpos.col < startcol) {
hl_startpos.col = startcol;
@@ -2029,8 +2026,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
if (next_match_idx >= 0 && next_match_col == (int)current_col) {
synpat_T *lspp;
- /* When a zero-width item matched which has a nextgroup,
- * don't push the item but set nextgroup. */
+ // When a zero-width item matched which has a nextgroup,
+ // don't push the item but set nextgroup.
lspp = &(SYN_ITEMS(syn_block)[next_match_idx]);
if (next_match_m_endpos.lnum == current_lnum
&& next_match_m_endpos.col == current_col
@@ -2127,8 +2124,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
* done in the current item.
*/
if (syn_block->b_spell_cluster_id == 0) {
- /* There is no @Spell cluster: Do spelling for items without
- * @NoSpell cluster. */
+ // There is no @Spell cluster: Do spelling for items without
+ // @NoSpell cluster.
if (syn_block->b_nospell_cluster_id == 0
|| current_trans_id == 0) {
*can_spell = (syn_block->b_syn_spell != SYNSPL_NOTOP);
@@ -2180,8 +2177,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
} else if (can_spell != NULL) {
- /* Default: Only do spelling when there is no @Spell cluster or when
- * ":syn spell toplevel" was used. */
+ // Default: Only do spelling when there is no @Spell cluster or when
+ // ":syn spell toplevel" was used.
*can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT
? (syn_block->b_spell_cluster_id == 0)
: (syn_block->b_syn_spell == SYNSPL_TOP);
@@ -2365,8 +2362,8 @@ static void check_state_ends(void)
current_next_list = NULL;
}
- /* When the ended item has "extend", another item with
- * "keepend" now needs to check for its end. */
+ // When the ended item has "extend", another item with
+ // "keepend" now needs to check for its end.
had_extend = (cur_si->si_flags & HL_EXTEND);
pop_current_state();
@@ -2541,9 +2538,9 @@ static void update_si_end(stateitem_T *sip, int startcol, bool force)
return;
}
- /* Don't update when it's already done. Can be a match of an end pattern
- * that started in a previous line. Watch out: can also be a "keepend"
- * from a containing item. */
+ // Don't update when it's already done. Can be a match of an end pattern
+ // that started in a previous line. Watch out: can also be a "keepend"
+ // from a containing item.
if (!force && sip->si_m_endpos.lnum >= current_lnum) {
return;
}
@@ -2822,8 +2819,8 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
}
limit_pos(hl_endpos, m_endpos);
- /* now the match ends where the highlighting ends, it is turned
- * into the matchgroup for the end */
+ // now the match ends where the highlighting ends, it is turned
+ // into the matchgroup for the end
*m_endpos = *hl_endpos;
} else {
*end_idx = 0;
@@ -5570,8 +5567,8 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
// If ssp has a "containedin" list and "cur_si" is in it, return TRUE.
if (cur_si != NULL && ssp->cont_in_list != NULL
&& !(cur_si->si_flags & HL_MATCH)) {
- /* Ignore transparent items without a contains argument. Double check
- * that we don't go back past the first one. */
+ // Ignore transparent items without a contains argument. Double check
+ // that we don't go back past the first one.
while ((cur_si->si_flags & HL_TRANS_CONT)
&& cur_si > (stateitem_T *)(current_state.ga_data)) {
--cur_si;
@@ -5635,8 +5632,8 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
}
if (item >= SYNID_CLUSTER) {
scl_list = SYN_CLSTR(syn_block)[item - SYNID_CLUSTER].scl_list;
- /* restrict recursiveness to 30 to avoid an endless loop for a
- * cluster that includes itself (indirectly) */
+ // restrict recursiveness to 30 to avoid an endless loop for a
+ // cluster that includes itself (indirectly)
if (scl_list != NULL && depth < 30) {
++depth;
r = in_id_list(NULL, scl_list, ssp, contained);
@@ -5931,8 +5928,8 @@ int syn_get_sub_char(void)
int syn_get_stack_item(int i)
{
if (i >= current_state.ga_len) {
- /* Need to invalidate the state, because we didn't properly finish it
- * for the last character, "keep_state" was TRUE. */
+ // Need to invalidate the state, because we didn't properly finish it
+ // for the last character, "keep_state" was TRUE.
invalidate_current_state();
current_col = MAXCOL;
return -1;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index ee92a2c642..83b06e2f6d 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -230,8 +230,8 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose)
if (g_do_tagpreview != 0) {
if (ptag_entry.tagname != NULL
&& STRCMP(ptag_entry.tagname, tag) == 0) {
- /* Jumping to same tag: keep the current match, so that
- * the CursorHold autocommand example works. */
+ // Jumping to same tag: keep the current match, so that
+ // the CursorHold autocommand example works.
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
} else {
@@ -407,9 +407,9 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose)
tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
}
- /* Curwin will change in the call to jumpto_tag() if ":stag" was
- * used or an autocommand jumps to another window; store value of
- * tagstackidx now. */
+ // Curwin will change in the call to jumpto_tag() if ":stag" was
+ // used or an autocommand jumps to another window; store value of
+ // tagstackidx now.
curwin->w_tagstackidx = tagstackidx;
if (type != DT_SELECT && type != DT_JUMP) {
curwin->w_tagstack[tagstackidx].cur_match = cur_match;
@@ -418,9 +418,9 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose)
}
}
- /* When not using the current buffer get the name of buffer "cur_fnum".
- * Makes sure that the tag order doesn't change when using a remembered
- * position for "cur_match". */
+ // When not using the current buffer get the name of buffer "cur_fnum".
+ // Makes sure that the tag order doesn't change when using a remembered
+ // position for "cur_match".
if (cur_fnum != curbuf->b_fnum) {
buf_T *buf = buflist_findnr(cur_fnum);
@@ -1101,8 +1101,8 @@ static void prepare_pats(pat_T *pats, int has_re)
pats->head = pats->pat;
pats->headlen = pats->len;
if (has_re) {
- /* When the pattern starts with '^' or "\\<", binary searching can be
- * used (much faster). */
+ // When the pattern starts with '^' or "\\<", binary searching can be
+ // used (much faster).
if (pats->pat[0] == '^') {
pats->head = pats->pat + 1;
} else if (pats->pat[0] == '\\' && pats->pat[1] == '<') {
@@ -1500,8 +1500,8 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int
orgpat.len = (int)STRLEN(pat);
if (curbuf->b_help) {
- /* When "@ab" is specified use only the "ab" language, otherwise
- * search all languages. */
+ // When "@ab" is specified use only the "ab" language, otherwise
+ // search all languages.
if (orgpat.len > 3 && pat[orgpat.len - 3] == '@'
&& ASCII_ISALPHA(pat[orgpat.len - 2])
&& ASCII_ISALPHA(pat[orgpat.len - 1])) {
@@ -1613,9 +1613,9 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int
}
}
if (s == NULL || *s == NUL) {
- /* Language not in 'helplang': use last, prefer English,
- * unless found already. */
- ++help_pri;
+ // Language not in 'helplang': use last, prefer English,
+ // unless found already.
+ help_pri++;
if (STRICMP(help_lang, "en") != 0) {
++help_pri;
}
@@ -1654,8 +1654,8 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int
stop_searching = true;
break;
}
- /* When mincount is TAG_MANY, stop when enough matches have been
- * found (for completion). */
+ // When mincount is TAG_MANY, stop when enough matches have been
+ // found (for completion).
if (mincount == TAG_MANY && match_count >= TAG_MANY) {
stop_searching = true;
retval = OK;
@@ -1695,8 +1695,8 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int
vim_fseek(fp, search_info.curr_offset, SEEK_SET);
eof = vim_fgets(lbuf, lbuf_size, fp);
if (!eof && search_info.curr_offset != 0) {
- /* The explicit cast is to work around a bug in gcc 3.4.2
- * (repeated below). */
+ // The explicit cast is to work around a bug in gcc 3.4.2
+ // (repeated below).
search_info.curr_offset = vim_ftell(fp);
if (search_info.curr_offset == search_info.high_offset) {
// oops, gone a bit too far; try from low offset
@@ -1739,9 +1739,9 @@ line_read_in:
char_u *conv_line;
int len;
- /* Convert every line. Converting the pattern from 'enc' to
- * the tags file encoding doesn't work, because characters are
- * not recognized. */
+ // Convert every line. Converting the pattern from 'enc' to
+ // the tags file encoding doesn't work, because characters are
+ // not recognized.
conv_line = string_convert(&vimconv, lbuf, NULL);
if (conv_line != NULL) {
// Copy or swap lbuf and conv_line.
@@ -1764,13 +1764,12 @@ line_read_in:
* format, and for "not sorted" flag.
*/
if (state == TS_START) {
- /* The header ends when the line sorts below "!_TAG_". When
- * case is folded lower case letters sort before "_". */
+ // The header ends when the line sorts below "!_TAG_". When
+ // case is folded lower case letters sort before "_".
if (STRNCMP(lbuf, "!_TAG_", 6) <= 0
|| (lbuf[0] == '!' && ASCII_ISLOWER(lbuf[1]))) {
if (STRNCMP(lbuf, "!_TAG_", 6) != 0) {
- /* Non-header item before the header, e.g. "!" itself.
- */
+ // Non-header item before the header, e.g. "!" itself.
goto parse_line;
}
@@ -1781,10 +1780,9 @@ line_read_in:
tag_file_sorted = lbuf[18];
}
if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) {
- /* Prepare to convert every line from the specified
- * encoding to 'encoding'. */
- for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) {
- ;
+ // Prepare to convert every line from the specified
+ // encoding to 'encoding'.
+ for (p = lbuf + 20; *p > ' ' && *p < 127; p++) {
}
*p = NUL;
convert_setup(&vimconv, lbuf + 20, p_enc);
@@ -1820,9 +1818,9 @@ line_read_in:
}
if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) {
- /* Binary search won't work for ignoring case, use linear
- * search. */
- linear = TRUE;
+ // Binary search won't work for ignoring case, use linear
+ // search.
+ linear = true;
state = TS_LINEAR;
}
@@ -1927,9 +1925,8 @@ parse_line:
}
if (tagcmp == 0) {
- /* We've located the tag, now skip back and search
- * forward until the first matching tag is found.
- */
+ // We've located the tag, now skip back and search
+ // forward until the first matching tag is found.
state = TS_SKIP_BACK;
search_info.match_offset = search_info.curr_offset;
continue;
@@ -1966,8 +1963,8 @@ parse_line:
if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
state = TS_STEP_FORWARD;
} else {
- /* Have to skip back more. Restore the curr_offset
- * used, otherwise we get stuck at a long line. */
+ // Have to skip back more. Restore the curr_offset
+ // used, otherwise we get stuck at a long line.
search_info.curr_offset = search_info.curr_offset_used;
}
continue;
diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim
index d071f4b325..0b76828dd7 100644
--- a/src/nvim/testdir/test_autochdir.vim
+++ b/src/nvim/testdir/test_autochdir.vim
@@ -8,13 +8,21 @@ func Test_set_filename()
let cwd = getcwd()
call test_autochdir()
set acd
+
+ let s:li = []
+ autocmd DirChanged auto call add(s:li, "autocd")
+ autocmd DirChanged auto call add(s:li, expand("<afile>"))
+
new
w samples/Xtest
call assert_equal("Xtest", expand('%'))
call assert_equal("samples", substitute(getcwd(), '.*/\(\k*\)', '\1', ''))
+ call assert_equal(["autocd", getcwd()], s:li)
+
bwipe!
+ au! DirChanged
set noacd
- exe 'cd ' . cwd
+ call chdir(cwd)
call delete('samples/Xtest')
endfunc
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 015979e1be..c350a17236 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -42,9 +42,7 @@ if has('timers')
endfunc
func Test_cursorhold_insert_with_timer_interrupt()
- if !has('job')
- return
- endif
+ CheckFeature job
" Need to move the cursor.
call feedkeys("ggG", "xt")
@@ -551,9 +549,7 @@ endfunc
func Test_OptionSet()
CheckFunction test_override
- if !has("eval") || !exists("+autochdir")
- return
- endif
+ CheckOption autochdir
call test_override('starting', 1)
set nocp
@@ -1328,6 +1324,71 @@ func Test_autocommand_all_events()
call assert_fails('au * x bwipe', 'E1155:')
endfunc
+function s:Before_test_dirchanged()
+ augroup test_dirchanged
+ autocmd!
+ augroup END
+ let s:li = []
+ let s:dir_this = getcwd()
+ let s:dir_foo = s:dir_this . '/Xfoo'
+ call mkdir(s:dir_foo)
+ let s:dir_bar = s:dir_this . '/Xbar'
+ call mkdir(s:dir_bar)
+endfunc
+
+function s:After_test_dirchanged()
+ call chdir(s:dir_this)
+ call delete(s:dir_foo, 'd')
+ call delete(s:dir_bar, 'd')
+ augroup test_dirchanged
+ autocmd!
+ augroup END
+endfunc
+
+function Test_dirchanged_global()
+ call s:Before_test_dirchanged()
+ autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
+ autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
+ call chdir(s:dir_foo)
+ call assert_equal(["cd:", s:dir_foo], s:li)
+ call chdir(s:dir_foo)
+ call assert_equal(["cd:", s:dir_foo], s:li)
+ exe 'lcd ' .. fnameescape(s:dir_bar)
+ call assert_equal(["cd:", s:dir_foo], s:li)
+ call s:After_test_dirchanged()
+endfunc
+
+function Test_dirchanged_local()
+ call s:Before_test_dirchanged()
+ autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
+ autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
+ call chdir(s:dir_foo)
+ call assert_equal([], s:li)
+ exe 'lcd ' .. fnameescape(s:dir_bar)
+ call assert_equal(["lcd:", s:dir_bar], s:li)
+ exe 'lcd ' .. fnameescape(s:dir_bar)
+ call assert_equal(["lcd:", s:dir_bar], s:li)
+ call s:After_test_dirchanged()
+endfunc
+
+function Test_dirchanged_auto()
+ CheckFunction test_autochdir
+ CheckOption autochdir
+ call s:Before_test_dirchanged()
+ call test_autochdir()
+ autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
+ autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
+ set acd
+ cd ..
+ call assert_equal([], s:li)
+ exe 'edit ' . s:dir_foo . '/Xfile'
+ call assert_equal(s:dir_foo, getcwd())
+ call assert_equal(["auto:", s:dir_foo], s:li)
+ set noacd
+ bwipe!
+ call s:After_test_dirchanged()
+endfunc
+
" Test TextChangedI and TextChangedP
" See test/functional/viml/completion_spec.lua'
func Test_ChangedP()
diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim
index 02a23bf82f..0bba321ee2 100644
--- a/src/nvim/testdir/test_cd.vim
+++ b/src/nvim/testdir/test_cd.vim
@@ -12,7 +12,7 @@ func Test_cd_up_and_down()
let path = getcwd()
cd ..
call assert_notequal(path, getcwd())
- exe 'cd ' . path
+ exe 'cd ' .. fnameescape(path)
call assert_equal(path, getcwd())
endfunc
@@ -23,7 +23,7 @@ func Test_cd_no_arg()
cd
call assert_equal($HOME, getcwd())
call assert_notequal(path, getcwd())
- exe 'cd ' . path
+ exe 'cd ' .. fnameescape(path)
call assert_equal(path, getcwd())
else
" Test that cd without argument echoes cwd on non-Unix systems.
@@ -43,6 +43,20 @@ func Test_cd_minus()
call assert_equal(path_dotdot, getcwd())
cd -
call assert_equal(path, getcwd())
+
+ " Test for :cd - without a previous directory
+ let lines =<< trim [SCRIPT]
+ call assert_fails('cd -', 'E186:')
+ call assert_fails('call chdir("-")', 'E186:')
+ call writefile(v:errors, 'Xresult')
+ qall!
+ [SCRIPT]
+ call writefile(lines, 'Xscript')
+ if RunVim([], [], '--clean -S Xscript')
+ call assert_equal([], readfile('Xresult'))
+ endif
+ call delete('Xscript')
+ call delete('Xresult')
endfunc
func Test_cd_with_cpo_chdir()
@@ -61,7 +75,7 @@ func Test_cd_with_cpo_chdir()
" :cd should succeed when buffer has been written.
w!
- exe 'cd ' . path
+ exe 'cd ' .. fnameescape(path)
call assert_equal(path, getcwd())
call delete('Xfoo')
@@ -69,6 +83,124 @@ func Test_cd_with_cpo_chdir()
bw!
endfunc
+" Test for chdir()
+func Test_chdir_func()
+ let topdir = getcwd()
+ call mkdir('Xdir/y/z', 'p')
+
+ " Create a few tabpages and windows with different directories
+ new
+ cd Xdir
+ tabnew
+ tcd y
+ below new
+ below new
+ lcd z
+
+ tabfirst
+ call assert_match('^\[global\] .*/Xdir$', trim(execute('verbose pwd')))
+ call chdir('..')
+ call assert_equal('y', fnamemodify(getcwd(1, 2), ':t'))
+ call assert_equal('z', fnamemodify(getcwd(3, 2), ':t'))
+ tabnext | wincmd t
+ call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd')))
+ call chdir('..')
+ call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t'))
+ call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t'))
+ call assert_equal('z', fnamemodify(getcwd(3, 2), ':t'))
+ call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t'))
+ 3wincmd w
+ call assert_match('^\[window\] .*/z$', trim(execute('verbose pwd')))
+ call chdir('..')
+ call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t'))
+ call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t'))
+ call assert_equal('y', fnamemodify(getcwd(3, 2), ':t'))
+ call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t'))
+
+ " Error case
+ call assert_fails("call chdir('dir-abcd')", 'E472:')
+ silent! let d = chdir("dir_abcd")
+ call assert_equal("", d)
+ " Should not crash
+ call chdir(d)
+
+ only | tabonly
+ call chdir(topdir)
+ call delete('Xdir', 'rf')
+endfunc
+
+" Test for changing to the previous directory '-'
+func Test_prev_dir()
+ let topdir = getcwd()
+ call mkdir('Xdir/a/b/c', 'p')
+
+ " Create a few tabpages and windows with different directories
+ new | only
+ tabnew | new
+ tabnew
+ tabfirst
+ cd Xdir
+ tabnext | wincmd t
+ tcd a
+ wincmd w
+ lcd b
+ tabnext
+ tcd a/b/c
+
+ " Change to the previous directory twice in all the windows.
+ tabfirst
+ cd - | cd -
+ tabnext | wincmd t
+ tcd - | tcd -
+ wincmd w
+ lcd - | lcd -
+ tabnext
+ tcd - | tcd -
+
+ " Check the directory of all the windows
+ tabfirst
+ call assert_equal('Xdir', fnamemodify(getcwd(), ':t'))
+ tabnext | wincmd t
+ call assert_equal('a', fnamemodify(getcwd(), ':t'))
+ wincmd w
+ call assert_equal('b', fnamemodify(getcwd(), ':t'))
+ tabnext
+ call assert_equal('c', fnamemodify(getcwd(), ':t'))
+
+ " Change to the previous directory using chdir()
+ tabfirst
+ call chdir("-") | call chdir("-")
+ tabnext | wincmd t
+ call chdir("-") | call chdir("-")
+ wincmd w
+ call chdir("-") | call chdir("-")
+ tabnext
+ call chdir("-") | call chdir("-")
+
+ " Check the directory of all the windows
+ tabfirst
+ call assert_equal('Xdir', fnamemodify(getcwd(), ':t'))
+ tabnext | wincmd t
+ call assert_equal('a', fnamemodify(getcwd(), ':t'))
+ wincmd w
+ call assert_equal('b', fnamemodify(getcwd(), ':t'))
+ tabnext
+ call assert_equal('c', fnamemodify(getcwd(), ':t'))
+
+ only | tabonly
+ call chdir(topdir)
+ call delete('Xdir', 'rf')
+endfunc
+
+func Test_lcd_split()
+ let curdir = getcwd()
+ lcd ..
+ split
+ lcd -
+ call assert_equal(curdir, getcwd())
+ quit!
+endfunc
+
func Test_cd_from_non_existing_dir()
CheckNotMSWindows
diff --git a/src/nvim/testdir/test_find_complete.vim b/src/nvim/testdir/test_find_complete.vim
index 0a00d9432f..32ca9672ef 100644
--- a/src/nvim/testdir/test_find_complete.vim
+++ b/src/nvim/testdir/test_find_complete.vim
@@ -36,7 +36,7 @@ func Test_find_complete()
" We shouldn't find any file till this point
call mkdir('in/path', 'p')
- exe 'cd ' . cwd
+ call chdir(cwd)
call writefile(['Holy Grail'], 'Xfind/file.txt')
call writefile(['Jimmy Hoffa'], 'Xfind/in/file.txt')
call writefile(['Another Holy Grail'], 'Xfind/in/stuff.txt')
@@ -133,12 +133,12 @@ func Test_find_complete()
call assert_equal('Voyager 2', getline(1))
" Check for correct handling of shorten_fname()'s behavior on windows
- exec "cd " . cwd . "/Xfind/in"
+ call chdir(cwd .. "/Xfind/in")
call feedkeys(":find file\t\n", "xt")
call assert_equal('Jimmy Hoffa', getline(1))
" Test for relative to current buffer 'path' item
- exec "cd " . cwd . "/Xfind/"
+ call chdir(cwd . "/Xfind/")
set path=./path
" Open the file where Jimmy Hoffa is found
e in/file.txt
@@ -157,7 +157,7 @@ func Test_find_complete()
call assert_equal('Another Holy Grail', getline(1))
enew | only
- exe 'cd ' . cwd
+ call chdir(cwd)
call delete('Xfind', 'rf')
set path&
endfunc
diff --git a/src/nvim/testdir/test_findfile.vim b/src/nvim/testdir/test_findfile.vim
index d92706dbe5..5a20475d3d 100644
--- a/src/nvim/testdir/test_findfile.vim
+++ b/src/nvim/testdir/test_findfile.vim
@@ -113,7 +113,7 @@ func Test_findfile()
call assert_match('.*/Xdir1/bar', findfile('bar', '**;', 2))
bwipe!
- exe 'cd ' . save_dir
+ call chdir(save_dir)
call CleanFiles()
let &path = save_path
let &shellslash = save_shellslash
@@ -171,7 +171,7 @@ func Test_finddir()
call assert_match('.*/Xdir1/Xdir2', finddir('Xdir2', '**;', 2))
call assert_equal('Xdir3', finddir('Xdir3', '**;', 1))
- exe 'cd ' . save_dir
+ call chdir(save_dir)
call CleanFiles()
let &path = save_path
let &shellslash = save_shellslash
diff --git a/src/nvim/testdir/test_getcwd.vim b/src/nvim/testdir/test_getcwd.vim
index 2ff396b641..a75583cd2c 100644
--- a/src/nvim/testdir/test_getcwd.vim
+++ b/src/nvim/testdir/test_getcwd.vim
@@ -46,7 +46,7 @@ endfunction
let g:cwd=getcwd()
function TearDown()
q
- exec "cd " . g:cwd
+ call chdir(g:cwd)
call delete("Xtopdir", "rf")
endfunction
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 64d618c38f..43e6325aa5 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -69,8 +69,8 @@
* All data is allocated and will all be freed when the buffer is unloaded.
*/
-/* Uncomment the next line for including the u_check() function. This warns
- * for errors in the debug information. */
+// Uncomment the next line for including the u_check() function. This warns
+// for errors in the debug information.
// #define U_DEBUG 1
#define UH_MAGIC 0x18dade // value for uh_magic when in use
#define UE_MAGIC 0xabc123 // value for ue_magic when in use
@@ -291,8 +291,8 @@ bool undo_allowed(buf_T *buf)
return false;
}
- /* Don't allow changes in the buffer while editing the cmdline. The
- * caller of getcmdline() may get confused. */
+ // Don't allow changes in the buffer while editing the cmdline. The
+ // caller of getcmdline() may get confused.
if (textlock != 0) {
EMSG(_(e_secure));
return false;
@@ -1921,8 +1921,8 @@ static void u_doit(int startcount, bool quiet, bool do_buf_event)
u_undoredo(false, do_buf_event);
- /* Advance for next redo. Set "newhead" when at the end of the
- * redoable changes. */
+ // Advance for next redo. Set "newhead" when at the end of the
+ // redoable changes.
if (curbuf->b_u_curhead->uh_prev.ptr == NULL) {
curbuf->b_u_newhead = curbuf->b_u_curhead;
}
@@ -1967,8 +1967,8 @@ void undo_time(long step, bool sec, bool file, bool absolute)
u_oldcount = -1;
}
- /* "target" is the node below which we want to be.
- * Init "closest" to a value we can't reach. */
+ // "target" is the node below which we want to be.
+ // Init "closest" to a value we can't reach.
if (absolute) {
target = step;
closest = -1;
@@ -1977,9 +1977,9 @@ void undo_time(long step, bool sec, bool file, bool absolute)
target = (long)(curbuf->b_u_time_cur) + step;
} else if (dofile) {
if (step < 0) {
- /* Going back to a previous write. If there were changes after
- * the last write, count that as moving one file-write, so
- * that ":earlier 1f" undoes all changes since the last save. */
+ // Going back to a previous write. If there were changes after
+ // the last write, count that as moving one file-write, so
+ // that ":earlier 1f" undoes all changes since the last save.
uhp = curbuf->b_u_curhead;
if (uhp != NULL) {
uhp = uhp->uh_next.ptr;
@@ -2003,8 +2003,8 @@ void undo_time(long step, bool sec, bool file, bool absolute)
// Moving forward to a newer write.
target = curbuf->b_u_save_nr_cur + step;
if (target > curbuf->b_u_save_nr_last) {
- /* Go to after last write: after the latest change. Use
- * the sequence number for that. */
+ // Go to after last write: after the latest change. Use
+ // the sequence number for that.
target = curbuf->b_u_seq_last + 1;
dofile = false;
}
@@ -2072,10 +2072,10 @@ void undo_time(long step, bool sec, bool file, bool absolute)
}
if (round == 1 && !(dofile && val == 0)) {
- /* Remember the header that is closest to the target.
- * It must be at least in the right direction (checked with
- * "b_u_seq_cur"). When the timestamp is equal find the
- * highest/lowest sequence number. */
+ // Remember the header that is closest to the target.
+ // It must be at least in the right direction (checked with
+ // "b_u_seq_cur"). When the timestamp is equal find the
+ // highest/lowest sequence number.
if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur
: uhp->uh_seq > curbuf->b_u_seq_cur)
&& ((dosec && val == closest)
@@ -2095,8 +2095,8 @@ void undo_time(long step, bool sec, bool file, bool absolute)
}
}
- /* Quit searching when we found a match. But when searching for a
- * time we need to continue looking for the best uh_seq. */
+ // Quit searching when we found a match. But when searching for a
+ // time we need to continue looking for the best uh_seq.
if (target == val && !dosec) {
target = uhp->uh_seq;
break;
@@ -2112,12 +2112,11 @@ void undo_time(long step, bool sec, bool file, bool absolute)
&& uhp->uh_alt_next.ptr->uh_walk != nomark
&& uhp->uh_alt_next.ptr->uh_walk != mark) {
uhp = uhp->uh_alt_next.ptr;
- }
- /* go up in the tree if we haven't been there and we are at the
- * start of alternate branches */
- else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
- && uhp->uh_next.ptr->uh_walk != nomark
- && uhp->uh_next.ptr->uh_walk != mark) {
+ } else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
+ // go up in the tree if we haven't been there and we are at the
+ // start of alternate branches
+ && uhp->uh_next.ptr->uh_walk != nomark
+ && uhp->uh_next.ptr->uh_walk != mark) {
// If still at the start we don't go through this change.
if (uhp == curbuf->b_u_curhead) {
uhp->uh_walk = nomark;
@@ -2297,8 +2296,8 @@ static void u_undoredo(int undo, bool do_buf_event)
bool empty_buffer; // buffer became empty
u_header_T *curhead = curbuf->b_u_curhead;
- /* Don't want autocommands using the undo structures here, they are
- * invalid till the end. */
+ // Don't want autocommands using the undo structures here, they are
+ // invalid till the end.
block_autocmds();
#ifdef U_DEBUG
@@ -2549,8 +2548,8 @@ static void u_undoredo(int undo, bool do_buf_event)
}
}
- /* The timestamp can be the same for multiple changes, just use the one of
- * the undone/redone change. */
+ // The timestamp can be the same for multiple changes, just use the one of
+ // the undone/redone change.
curbuf->b_u_time_cur = curhead->uh_time;
unblock_autocmds();
@@ -2709,12 +2708,11 @@ void ex_undolist(exarg_T *eap)
&& uhp->uh_alt_next.ptr->uh_walk != nomark
&& uhp->uh_alt_next.ptr->uh_walk != mark) {
uhp = uhp->uh_alt_next.ptr;
- }
- /* go up in the tree if we haven't been there and we are at the
- * start of alternate branches */
- else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
- && uhp->uh_next.ptr->uh_walk != nomark
- && uhp->uh_next.ptr->uh_walk != mark) {
+ } else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
+ // go up in the tree if we haven't been there and we are at the
+ // start of alternate branches
+ && uhp->uh_next.ptr->uh_walk != nomark
+ && uhp->uh_next.ptr->uh_walk != mark) {
uhp = uhp->uh_next.ptr;
--changes;
} else {
@@ -2906,8 +2904,8 @@ static void u_freeheader(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
{
u_header_T *uhap;
- /* When there is an alternate redo list free that branch completely,
- * because we can never go there. */
+ // When there is an alternate redo list free that branch completely,
+ // because we can never go there.
if (uhp->uh_alt_next.ptr != NULL) {
u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp);
}
@@ -2942,8 +2940,8 @@ static void u_freebranch(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
{
u_header_T *tofree, *next;
- /* If this is the top branch we may need to use u_freeheader() to update
- * all the pointers. */
+ // If this is the top branch we may need to use u_freeheader() to update
+ // all the pointers.
if (uhp == buf->b_u_oldhead) {
while (buf->b_u_oldhead != NULL) {
u_freeheader(buf, buf->b_u_oldhead, uhpp);
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 1fe4aa1add..dfe1ffdbd4 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -23,6 +23,7 @@
#include "nvim/fold.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
+#include "nvim/globals.h"
#include "nvim/hashtab.h"
#include "nvim/main.h"
#include "nvim/mark.h"
@@ -298,8 +299,8 @@ newwindow:
tabpage_T *oldtab = curtab;
tabpage_T *newtab;
- /* First create a new tab with the window, then go back to
- * the old tab and close the window there. */
+ // First create a new tab with the window, then go back to
+ // the old tab and close the window there.
wp = curwin;
if (win_new_tabpage((int)Prenum, NULL) == OK
&& valid_tabpage(oldtab)) {
@@ -519,8 +520,8 @@ wingotofile:
postponed_split = -1;
}
- /* Execute the command right here, required when
- * "wincmd g}" was used in a function. */
+ // Execute the command right here, required when
+ // "wincmd g}" was used in a function.
do_nv_ident('g', xchar);
break;
@@ -922,8 +923,8 @@ int win_split(int size, int flags)
return FAIL;
}
- /* When creating the help window make a snapshot of the window layout.
- * Otherwise clear the snapshot, it's now invalid. */
+ // When creating the help window make a snapshot of the window layout.
+ // Otherwise clear the snapshot, it's now invalid.
if (flags & WSP_HELP) {
make_snapshot(SNAP_HELP_IDX);
} else {
@@ -1260,8 +1261,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_append(curfrp, frp);
}
- /* Set w_fraction now so that the cursor keeps the same relative
- * vertical position. */
+ // Set w_fraction now so that the cursor keeps the same relative
+ // vertical position.
if (!did_set_fraction) {
set_fraction(oldwin);
}
@@ -1287,8 +1288,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
frp->fr_height = curfrp->fr_height;
- /* "new_size" of the current window goes to the new window, use
- * one column for the vertical separator */
+ // "new_size" of the current window goes to the new window, use
+ // one column for the vertical separator
win_new_width(wp, new_size);
if (before) {
wp->w_vsep_width = 1;
@@ -1328,8 +1329,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
frp->fr_width = curfrp->fr_width;
- /* "new_size" of the current window goes to the new window, use
- * one row for the status line */
+ // "new_size" of the current window goes to the new window, use
+ // one row for the status line
win_new_height(wp, new_size);
if (flags & (WSP_TOP | WSP_BOT)) {
int new_fr_height = curfrp->fr_height - new_size;
@@ -1388,8 +1389,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
'v');
}
- /* Don't change the window height/width to 'winheight' / 'winwidth' if a
- * size was given. */
+ // Don't change the window height/width to 'winheight' / 'winwidth' if a
+ // size was given.
if (flags & WSP_VERT) {
i = p_wiw;
if (size != 0) {
@@ -1462,6 +1463,8 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
}
newp->w_localdir = (oldp->w_localdir == NULL)
? NULL : vim_strsave(oldp->w_localdir);
+ newp->w_prevdir = (oldp->w_prevdir == NULL)
+ ? NULL : vim_strsave(oldp->w_prevdir);
// copy tagstack and folds
for (i = 0; i < oldp->w_tagstacklen; i++) {
@@ -1589,8 +1592,8 @@ int make_windows(int count, bool vertical)
int todo;
if (vertical) {
- /* Each windows needs at least 'winminwidth' lines and a separator
- * column. */
+ // Each windows needs at least 'winminwidth' lines and a separator
+ // column.
maxcount = (curwin->w_width + curwin->w_vsep_width
- (p_wiw - p_wmw)) / (p_wmw + 1);
} else {
@@ -1679,8 +1682,8 @@ static void win_exchange(long Prenum)
frp = curwin->w_frame->fr_prev;
}
- /* We can only exchange a window with another window, not with a frame
- * containing windows. */
+ // We can only exchange a window with another window, not with a frame
+ // containing windows.
if (frp == NULL || frp->fr_win == NULL || frp->fr_win == curwin) {
return;
}
@@ -1890,8 +1893,8 @@ void win_move_after(win_T *win1, win_T *win2)
win1->w_status_height = win2->w_status_height;
win2->w_status_height = height;
if (win1->w_vsep_width == 1) {
- /* Remove the vertical separator from win1, add it to the last
- * window, win2. Adjust the frame widths. */
+ // Remove the vertical separator from win1, add it to the last
+ // window, win2. Adjust the frame widths.
win2->w_vsep_width = 1;
win2->w_frame->fr_width += 1;
win1->w_vsep_width = 0;
@@ -1955,8 +1958,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
bool hnc;
if (topfr->fr_layout == FR_LEAF) {
- /* Set the width/height of this frame.
- * Redraw when size or position changes */
+ // Set the width/height of this frame.
+ // Redraw when size or position changes
if (topfr->fr_height != height || topfr->fr_win->w_winrow != row
|| topfr->fr_width != width ||
topfr->fr_win->w_wincol != col) {
@@ -2028,8 +2031,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else if (totwincount > 1
&& (room + (totwincount - 2))
/ (totwincount - 1) > p_wiw) {
- /* Can make all windows wider than 'winwidth', spread
- * the room equally. */
+ // Can make all windows wider than 'winwidth', spread
+ // the room equally.
next_curwin_size = (room + p_wiw
+ (totwincount - 1) * p_wmw
+ (totwincount - 1)) / totwincount;
@@ -2084,8 +2087,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
new_size += n;
}
- /* Skip frame that is full width when splitting or closing a
- * window, unless equalizing all frames. */
+ // Skip frame that is full width when splitting or closing a
+ // window, unless equalizing all frames.
if (!current || dir != 'v' || topfr->fr_parent != NULL
|| (new_size != fr->fr_width)
|| frame_has_win(fr, next_curwin)) {
@@ -2120,8 +2123,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
m = frame_minheight(topfr, next_curwin);
room = height - m;
if (room < 0) {
- /* The room is less then 'winheight', use all space for the
- * current window. */
+ // The room is less then 'winheight', use all space for the
+ // current window.
next_curwin_size = p_wh + room;
room = 0;
} else {
@@ -2159,8 +2162,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else if (totwincount > 1
&& (room + (totwincount - 2))
/ (totwincount - 1) > p_wh) {
- /* can make all windows higher than 'winheight',
- * spread the room equally. */
+ // can make all windows higher than 'winheight',
+ // spread the room equally.
next_curwin_size = (room + p_wh
+ (totwincount - 1) * p_wmh
+ (totwincount - 1)) / totwincount;
@@ -2214,8 +2217,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
new_size += n;
}
- /* Skip frame that is full width when splitting or closing a
- * window, unless equalizing all frames. */
+ // Skip frame that is full width when splitting or closing a
+ // window, unless equalizing all frames.
if (!current || dir != 'h' || topfr->fr_parent != NULL
|| (new_size != fr->fr_height)
|| frame_has_win(fr, next_curwin)) {
@@ -2263,8 +2266,8 @@ void close_windows(buf_T *buf, int keep_curwin)
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)) {
win_close_othertab(wp, false, tp);
- /* Start all over, the tab page may be closed and
- * autocommands may change the window layout. */
+ // Start all over, the tab page may be closed and
+ // autocommands may change the window layout.
nexttp = first_tabpage;
break;
}
@@ -2630,8 +2633,8 @@ int win_close(win_T *win, bool free_buf)
*/
last_status(false);
- /* After closing the help window, try restoring the window layout from
- * before it was opened. */
+ // After closing the help window, try restoring the window layout from
+ // before it was opened.
if (help_window) {
restore_snapshot(SNAP_HELP_IDX, close_curwin);
}
@@ -2703,8 +2706,8 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false);
}
- /* Careful: Autocommands may have closed the tab page or made it the
- * current tab page. */
+ // Careful: Autocommands may have closed the tab page or made it the
+ // current tab page.
for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) {
;
}
@@ -2863,9 +2866,9 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
frame_remove(frp_close);
if (frp_close->fr_parent->fr_layout == FR_COL) {
- /* When 'winfixheight' is set, try to find another frame in the column
- * (as close to the closed frame as possible) to distribute the height
- * to. */
+ // When 'winfixheight' is set, try to find another frame in the column
+ // (as close to the closed frame as possible) to distribute the height
+ // to.
if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfh) {
frp = frp_close->fr_prev;
frp3 = frp_close->fr_next;
@@ -2922,8 +2925,8 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
*dirp = 'h';
}
- /* If rows/columns go to a window below/right its positions need to be
- * updated. Can only be done after the sizes have been updated. */
+ // If rows/columns go to a window below/right its positions need to be
+ // updated. Can only be done after the sizes have been updated.
if (frp2 == frp_close->fr_next) {
int row = win->w_winrow;
int col = win->w_wincol;
@@ -2932,8 +2935,8 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
}
if (frp2->fr_next == NULL && frp2->fr_prev == NULL) {
- /* There is no other frame in this list, move its info to the parent
- * and remove it. */
+ // There is no other frame in this list, move its info to the parent
+ // and remove it.
frp2->fr_parent->fr_layout = frp2->fr_layout;
frp2->fr_parent->fr_child = frp2->fr_child;
FOR_ALL_FRAMES(frp, frp2->fr_child) {
@@ -2951,8 +2954,8 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
frp2 = frp->fr_parent;
if (frp2 != NULL && frp2->fr_layout == frp->fr_layout) {
- /* The frame above the parent has the same layout, have to merge
- * the frames into this list. */
+ // The frame above the parent has the same layout, have to merge
+ // the frames into this list.
if (frp2->fr_child == frp) {
frp2->fr_child = frp->fr_child;
}
@@ -3641,8 +3644,8 @@ static int win_alloc_firstwin(win_T *oldwin)
{
curwin = win_alloc(NULL, false);
if (oldwin == NULL) {
- /* Very first window, need to create an empty buffer for it and
- * initialize from scratch. */
+ // Very first window, need to create an empty buffer for it and
+ // initialize from scratch.
curbuf = buflist_new(NULL, NULL, 1L, BLN_LISTED);
if (curbuf == NULL) {
return FAIL;
@@ -3732,6 +3735,7 @@ void free_tabpage(tabpage_T *tp)
}
xfree(tp->tp_localdir);
+ xfree(tp->tp_prevdir);
xfree(tp);
}
@@ -4014,10 +4018,10 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
const int row = win_comp_pos(); // recompute w_winrow for all windows
diff_need_scrollbind = true;
- /* The tabpage line may have appeared or disappeared, may need to resize
- * the frames for that. When the Vim window was resized need to update
- * frame sizes too. Use the stored value of p_ch, so that it can be
- * different for each tab page. */
+ // The tabpage line may have appeared or disappeared, may need to resize
+ // the frames for that. When the Vim window was resized need to update
+ // frame sizes too. Use the stored value of p_ch, so that it can be
+ // different for each tab page.
if (p_ch != curtab->tp_ch_used) {
clear_cmdline = true;
}
@@ -4112,8 +4116,8 @@ void goto_tabpage(int n)
tp = curtab->tp_next;
}
} else if (n < 0) {
- /* "gT": go to previous tab page, wrap around end. "N gT" repeats
- * this N times. */
+ // "gT": go to previous tab page, wrap around end. "N gT" repeats
+ // this N times.
ttp = curtab;
for (i = n; i < 0; ++i) {
for (tp = first_tabpage; tp->tp_next != ttp && tp->tp_next != NULL;
@@ -4540,9 +4544,9 @@ static void win_enter_ext(win_T *const wp, const int flags)
}
}
if (os_chdir(new_dir) == 0) {
- if (!p_acd && !strequal(new_dir, cwd)) {
+ if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) {
do_autocmd_dirchanged(new_dir, curwin->w_localdir
- ? kCdScopeWindow : kCdScopeTab, true);
+ ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow);
}
shorten_fnames(true);
}
@@ -4550,8 +4554,8 @@ static void win_enter_ext(win_T *const wp, const int flags)
// Window doesn't have a local directory and we are not in the global
// directory: Change to the global directory.
if (os_chdir((char *)globaldir) == 0) {
- if (!p_acd && !strequal((char *)globaldir, cwd)) {
- do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, true);
+ if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) {
+ do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow);
}
}
XFREE_CLEAR(globaldir);
@@ -4677,9 +4681,9 @@ static win_T *win_alloc(win_T *after, bool hidden)
new_wp->w_vars = tv_dict_alloc();
init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
- /* Don't execute autocommands while the window is not properly
- * initialized yet. gui_create_scrollbar() may trigger a FocusGained
- * event. */
+ // Don't execute autocommands while the window is not properly
+ // initialized yet. gui_create_scrollbar() may trigger a FocusGained
+ // event.
block_autocmds();
/*
* link the window in the window list
@@ -4742,8 +4746,8 @@ static void win_free(win_T *wp, tabpage_T *tp)
// reduce the reference count to the argument list.
alist_unlink(wp->w_alist);
- /* Don't execute autocommands while the window is halfway being deleted.
- * gui_mch_destroy_scrollbar() may trigger a FocusGained event. */
+ // Don't execute autocommands while the window is halfway being deleted.
+ // gui_mch_destroy_scrollbar() may trigger a FocusGained event.
block_autocmds();
clear_winopt(&wp->w_onebuf_opt);
@@ -4770,6 +4774,7 @@ static void win_free(win_T *wp, tabpage_T *tp)
}
xfree(wp->w_localdir);
+ xfree(wp->w_prevdir);
/* Remove the window from the b_wininfo lists, it may happen that the
* freed memory is re-used for another window. */
@@ -5200,8 +5205,8 @@ static void frame_setheight(frame_T *curfrp, int height)
frame_new_height(curfrp, height, false, false);
}
} else if (curfrp->fr_parent->fr_layout == FR_ROW) {
- /* Row of frames: Also need to resize frames left and right of this
- * one. First check for the minimal height of these. */
+ // Row of frames: Also need to resize frames left and right of this
+ // one. First check for the minimal height of these.
h = frame_minheight(curfrp->fr_parent, NULL);
if (height < h) {
height = h;
@@ -5261,13 +5266,13 @@ static void frame_setheight(frame_T *curfrp, int height)
*/
take = height - curfrp->fr_height;
- /* If there is not enough room, also reduce the height of a window
- * with 'winfixheight' set. */
+ // If there is not enough room, also reduce the height of a window
+ // with 'winfixheight' set.
if (height > room + room_cmdline - room_reserved) {
room_reserved = room + room_cmdline - height;
}
- /* If there is only a 'winfixheight' window and making the
- * window smaller, need to make the other window taller. */
+ // If there is only a 'winfixheight' window and making the
+ // window smaller, need to make the other window taller.
if (take < 0 && room - curfrp->fr_height < room_reserved) {
room_reserved = 0;
}
@@ -5342,8 +5347,8 @@ void win_setwidth(int width)
void win_setwidth_win(int width, win_T *wp)
{
- /* Always keep current window at least one column wide, even when
- * 'winminwidth' is zero. */
+ // Always keep current window at least one column wide, even when
+ // 'winminwidth' is zero.
if (wp == curwin) {
if (width < p_wmw) {
width = p_wmw;
@@ -5394,8 +5399,8 @@ static void frame_setwidth(frame_T *curfrp, int width)
}
if (curfrp->fr_parent->fr_layout == FR_COL) {
- /* Column of frames: Also need to resize frames above and below of
- * this one. First check for the minimal width of these. */
+ // Column of frames: Also need to resize frames above and below of
+ // this one. First check for the minimal width of these.
w = frame_minwidth(curfrp->fr_parent, NULL);
if (width < w) {
width = w;
@@ -5442,13 +5447,13 @@ static void frame_setwidth(frame_T *curfrp, int width)
*/
take = width - curfrp->fr_width;
- /* If there is not enough room, also reduce the width of a window
- * with 'winfixwidth' set. */
+ // If there is not enough room, also reduce the width of a window
+ // with 'winfixwidth' set.
if (width > room - room_reserved) {
room_reserved = room - width;
}
- /* If there is only a 'winfixwidth' window and making the
- * window smaller, need to make the other window narrower. */
+ // If there is only a 'winfixwidth' window and making the
+ // window smaller, need to make the other window narrower.
if (take < 0 && room - curfrp->fr_width < room_reserved) {
room_reserved = 0;
}
@@ -5557,8 +5562,8 @@ void win_drag_status_line(win_T *dragwin, int offset)
curfr = fr;
if (fr != topframe) { // more than one window
fr = fr->fr_parent;
- /* When the parent frame is not a column of frames, its parent should
- * be. */
+ // When the parent frame is not a column of frames, its parent should
+ // be.
if (fr->fr_layout != FR_COL) {
curfr = fr;
if (fr != topframe) { // only a row of windows, may drag statusline
@@ -6009,9 +6014,9 @@ void command_height(void)
frame_T *frp;
int old_p_ch = curtab->tp_ch_used;
- /* Use the value of p_ch that we remembered. This is needed for when the
- * GUI starts up, we can't be sure in what order things happen. And when
- * p_ch was changed in another tab page. */
+ // Use the value of p_ch that we remembered. This is needed for when the
+ // GUI starts up, we can't be sure in what order things happen. And when
+ // p_ch was changed in another tab page.
curtab->tp_ch_used = p_ch;
// Find bottom frame with width of screen.
@@ -6270,8 +6275,8 @@ static void last_status_rec(frame_T *fr, bool statusline)
EMSG(_(e_noroom));
return;
}
- /* In a column of frames: go to frame above. If already at
- * the top or in a row of frames: go to parent. */
+ // In a column of frames: go to frame above. If already at
+ // the top or in a row of frames: go to parent.
if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL) {
fp = fp->fr_prev;
} else {
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 6b644ed519..d8914a3ab7 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -91,6 +91,14 @@ describe('API', function()
nvim('exec', 'set nowrap', false)
eq('nowrap\n\tLast set from anonymous :source',
nvim('exec', 'verbose set wrap?', true))
+
+ -- Using script var to force creation of a script item
+ nvim('exec', [[
+ let s:a = 1
+ set nowrap
+ ]], false)
+ eq('nowrap\n\tLast set from anonymous :source (script id 1)',
+ nvim('exec', 'verbose set wrap?', true))
end)
it('multiline input', function()
@@ -132,6 +140,43 @@ describe('API', function()
-- try no spaces before continuations to catch off-by-one error
nvim('exec', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', false)
eq({a = 98}, request('nvim_eval', 'g:ab'))
+
+ -- Script scope (s:)
+ eq('ahoy! script-scoped varrrrr', nvim('exec', [[
+ let s:pirate = 'script-scoped varrrrr'
+ function! s:avast_ye_hades(s) abort
+ return a:s .. ' ' .. s:pirate
+ endfunction
+ echo <sid>avast_ye_hades('ahoy!')
+ ]], true))
+
+ eq('ahoy! script-scoped varrrrr', nvim('exec', [[
+ let s:pirate = 'script-scoped varrrrr'
+ function! Avast_ye_hades(s) abort
+ return a:s .. ' ' .. s:pirate
+ endfunction
+ echo nvim_exec('echo Avast_ye_hades(''ahoy!'')', 1)
+ ]], true))
+
+ eq('Vim(call):E5555: API call: Vim(echo):E121: Undefined variable: s:pirate',
+ pcall_err(request, 'nvim_exec', [[
+ let s:pirate = 'script-scoped varrrrr'
+ call nvim_exec('echo s:pirate', 1)
+ ]], false))
+
+ -- Script items are created only on script var access
+ eq('1\n0', nvim('exec', [[
+ echo expand("<SID>")->empty()
+ let s:a = 123
+ echo expand("<SID>")->empty()
+ ]], true))
+
+ eq('1\n0', nvim('exec', [[
+ echo expand("<SID>")->empty()
+ function s:a() abort
+ endfunction
+ echo expand("<SID>")->empty()
+ ]], true))
end)
it('non-ASCII input', function()
diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua
index 6f2da24cf2..f4a1642ebf 100644
--- a/test/functional/autocmd/dirchanged_spec.lua
+++ b/test/functional/autocmd/dirchanged_spec.lua
@@ -6,6 +6,7 @@ local command = h.command
local eq = h.eq
local eval = h.eval
local request = h.request
+local iswin = h.iswin
describe('autocmd DirChanged', function()
local curdir = string.gsub(lfs.currentdir(), '\\', '/')
@@ -14,6 +15,11 @@ describe('autocmd DirChanged', function()
curdir .. '/Xtest-functional-autocmd-dirchanged.dir2',
curdir .. '/Xtest-functional-autocmd-dirchanged.dir3',
}
+ local win_dirs = {
+ curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR1',
+ curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR2',
+ curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3',
+ }
setup(function() for _, dir in pairs(dirs) do h.mkdir(dir) end end)
teardown(function() for _, dir in pairs(dirs) do h.rmdir(dir) end end)
@@ -27,17 +33,20 @@ describe('autocmd DirChanged', function()
command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
end)
- it('sets v:event', function()
+ it('sets v:event and <amatch>', function()
command('lcd '..dirs[1])
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatch'))
eq(1, eval('g:cdcount'))
command('tcd '..dirs[2])
- eq({cwd=dirs[2], scope='tab', changed_window=false}, eval('g:ev'))
+ eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatch'))
eq(2, eval('g:cdcount'))
command('cd '..dirs[3])
eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ eq('global', eval('g:amatch'))
eq(3, eval('g:cdcount'))
end)
@@ -63,17 +72,6 @@ describe('autocmd DirChanged', function()
eq(dirs[3], eval('getcwd()'))
end)
- it('sets <amatch> to CWD "scope"', function()
- command('lcd '..dirs[1])
- eq('window', eval('g:amatch'))
-
- command('tcd '..dirs[2])
- eq('tab', eval('g:amatch'))
-
- command('cd '..dirs[3])
- eq('global', eval('g:amatch'))
- end)
-
it('does not trigger if :cd fails', function()
command('let g:ev = {}')
@@ -106,13 +104,79 @@ describe('autocmd DirChanged', function()
command('split '..dirs[1]..'/foo')
eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatch'))
command('split '..dirs[2]..'/bar')
eq({cwd=dirs[2], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatch'))
eq(2, eval('g:cdcount'))
end)
+ it('does not trigger if directory has not changed', function()
+ command('lcd '..dirs[1])
+ eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('window', eval('g:amatch'))
+ eq(1, eval('g:cdcount'))
+ command('let g:ev = {}')
+ command('lcd '..dirs[1])
+ eq({}, eval('g:ev'))
+ eq(1, eval('g:cdcount'))
+
+ if iswin() then
+ command('lcd '..win_dirs[1])
+ eq({}, eval('g:ev'))
+ eq(1, eval('g:cdcount'))
+ end
+
+ command('tcd '..dirs[2])
+ eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ eq('tabpage', eval('g:amatch'))
+ eq(2, eval('g:cdcount'))
+ command('let g:ev = {}')
+ command('tcd '..dirs[2])
+ eq({}, eval('g:ev'))
+ eq(2, eval('g:cdcount'))
+
+ if iswin() then
+ command('tcd '..win_dirs[2])
+ eq({}, eval('g:ev'))
+ eq(2, eval('g:cdcount'))
+ end
+
+ command('cd '..dirs[3])
+ eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ eq('global', eval('g:amatch'))
+ eq(3, eval('g:cdcount'))
+ command('let g:ev = {}')
+ command('cd '..dirs[3])
+ eq({}, eval('g:ev'))
+ eq(3, eval('g:cdcount'))
+
+ if iswin() then
+ command('cd '..win_dirs[3])
+ eq({}, eval('g:ev'))
+ eq(3, eval('g:cdcount'))
+ end
+
+ command('set autochdir')
+
+ command('split '..dirs[1]..'/foo')
+ eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ eq('auto', eval('g:amatch'))
+ eq(4, eval('g:cdcount'))
+ command('let g:ev = {}')
+ command('split '..dirs[1]..'/bar')
+ eq({}, eval('g:ev'))
+ eq(4, eval('g:cdcount'))
+
+ if iswin() then
+ command('split '..win_dirs[1]..'/baz')
+ eq({}, eval('g:ev'))
+ eq(4, eval('g:cdcount'))
+ end
+ end)
+
it("is triggered by switching to win/tab with different CWD #6054", function()
command('lcd '..dirs[3]) -- window 3
command('split '..dirs[2]..'/foo') -- window 2
@@ -122,6 +186,7 @@ describe('autocmd DirChanged', function()
command('2wincmd w') -- window 2
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatch'))
eq(4, eval('g:cdcount'))
command('tabnew') -- tab 2 (tab-local CWD)
@@ -129,8 +194,10 @@ describe('autocmd DirChanged', function()
command('tcd '..dirs[3])
command('tabnext') -- tab 1 (no tab-local CWD)
eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ eq('window', eval('g:amatch'))
command('tabnext') -- tab 2
- eq({cwd=dirs[3], scope='tab', changed_window=true}, eval('g:ev'))
+ eq({cwd=dirs[3], scope='tabpage', changed_window=true}, eval('g:ev'))
+ eq('tabpage', eval('g:amatch'))
eq(7, eval('g:cdcount'))
command('tabnext') -- tab 1
@@ -138,6 +205,31 @@ describe('autocmd DirChanged', function()
eq(9, eval('g:cdcount'))
command('tabnext') -- tab 2 (has the *same* CWD)
eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+
+ if iswin() then
+ command('tabnew') -- tab 3
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tcd '..win_dirs[3])
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 1
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 3
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 2
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 1
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('lcd '..win_dirs[3]) -- window 3
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 2
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 3
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 1
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 3
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ end
end)
it('is triggered by nvim_set_current_dir()', function()
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index bdf6ae76d1..fa650d611b 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -25,12 +25,19 @@ describe(':source', function()
let b = #{
\ k: "v"
"\ (o_o)
- \ }]])
+ \ }
+ let c = expand("<SID>")->empty()
+ let s:s = 0zbeef.cafe
+ let d = s:s]])
command('source')
eq('2', meths.exec('echo a', true))
eq("{'k': 'v'}", meths.exec('echo b', true))
+ -- Script items are created only on script var access
+ eq("1", meths.exec('echo c', true))
+ eq("0zBEEFCAFE", meths.exec('echo d', true))
+
exec('set cpoptions+=C')
eq('Vim(let):E15: Invalid expression: #{', exc_exec('source'))
end)
@@ -43,7 +50,11 @@ describe(':source', function()
let b = #{
"\ (>_<)
\ K: "V"
- \ }]])
+ \ }
+ function! s:C() abort
+ return expand("<SID>") .. "C()"
+ endfunction
+ let D = {-> s:C()}]])
-- Source the 2nd line only
feed('ggjV')
@@ -55,6 +66,11 @@ describe(':source', function()
feed_command(':source')
eq('4', meths.exec('echo a', true))
eq("{'K': 'V'}", meths.exec('echo b', true))
+ eq("<SNR>1_C()", meths.exec('echo D()', true))
+
+ -- Source last line only
+ feed_command(':$source')
+ eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()'))
exec('set cpoptions+=C')
eq('Vim(let):E15: Invalid expression: #{', exc_exec("'<,'>source"))
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index a08c8d8681..33469597a1 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -473,6 +473,78 @@ describe('vim.diagnostic', function()
end)
describe('config()', function()
+ it('works with global, namespace, and ephemeral options', function()
+ eq(1, exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = false,
+ })
+
+ vim.diagnostic.config({
+ virtual_text = true,
+ underline = false,
+ }, diagnostic_ns)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Some Error', 4, 4, 4, 4),
+ })
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(1, exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = false,
+ })
+
+ vim.diagnostic.config({
+ virtual_text = false,
+ underline = false,
+ }, diagnostic_ns)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Some Error', 4, 4, 4, 4),
+ }, {virtual_text = true})
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(0, exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = false,
+ })
+
+ vim.diagnostic.config({
+ virtual_text = {severity=vim.diagnostic.severity.ERROR},
+ underline = false,
+ }, diagnostic_ns)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Some Warning', 4, 4, 4, 4),
+ }, {virtual_text = true})
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+
+ eq(1, exec_lua [[
+ vim.diagnostic.config({
+ virtual_text = false,
+ })
+
+ vim.diagnostic.config({
+ virtual_text = {severity=vim.diagnostic.severity.ERROR},
+ underline = false,
+ }, diagnostic_ns)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning('Some Warning', 4, 4, 4, 4),
+ }, {
+ virtual_text = {} -- An empty table uses default values
+ })
+
+ return count_extmarks(diagnostic_bufnr, diagnostic_ns)
+ ]])
+ end)
+
it('can use functions for config values', function()
exec_lua [[
vim.diagnostic.config({