aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/ex_docmd.c29
-rw-r--r--src/nvim/file_search.c30
-rw-r--r--src/nvim/if_cscope.c11
-rw-r--r--src/nvim/memory.c7
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/option_defs.h7
-rw-r--r--src/nvim/quickfix.c38
-rw-r--r--src/nvim/terminal.c1
-rw-r--r--src/nvim/testdir/test_quickfix.vim17
-rw-r--r--src/nvim/version.c2
-rw-r--r--src/nvim/window.c41
13 files changed, 118 insertions, 78 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index a1b5633c32..3e9767adde 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -825,8 +825,7 @@ struct tabpage_S {
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
dict_T *tp_vars; ///< internal variables, local to tab page
- char_u *localdir; ///< Absolute path of local directory or
- ///< NULL
+ char_u *tp_localdir; ///< Absolute path of local CWD or NULL
};
/*
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6dc7e5606e..78f470b10a 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -10901,7 +10901,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
case kCdScopeTab: // FALLTHROUGH
assert(tp);
- from = tp->localdir;
+ from = tp->tp_localdir;
if (from) {
break;
}
@@ -12015,7 +12015,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
case kCdScopeTab:
assert(tp);
- rettv->vval.v_number = tp->localdir ? 1 : 0;
+ rettv->vval.v_number = tp->tp_localdir ? 1 : 0;
break;
case kCdScopeGlobal:
// The global scope never has a local directory
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 87b6959101..774380b2f0 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6943,24 +6943,27 @@ void free_cd_dir(void)
/// @param scope Scope of the function call (global, tab or window).
void post_chdir(CdScope scope)
{
- // The local directory of the current window is always overwritten.
+ // Always overwrite the window-local CWD.
xfree(curwin->w_localdir);
curwin->w_localdir = NULL;
- // Overwrite the local directory of the current tab page for `cd` and `tcd`
+ // Overwrite the tab-local CWD for :cd, :tcd.
if (scope >= kCdScopeTab) {
- xfree(curtab->localdir);
- curtab->localdir = NULL;
+ xfree(curtab->tp_localdir);
+ curtab->tp_localdir = NULL;
}
if (scope < kCdScopeGlobal) {
- // If still in global directory, need to remember current directory as
- // global directory.
+ // If still in global directory, set CWD as the global directory.
if (globaldir == NULL && prev_dir != NULL) {
globaldir = vim_strsave(prev_dir);
}
}
+ char cwd[MAXPATHL];
+ if (os_dirname((char_u *)cwd, MAXPATHL) != OK) {
+ return;
+ }
switch (scope) {
case kCdScopeGlobal:
// We are now in the global directory, no need to remember its name.
@@ -6968,23 +6971,17 @@ void post_chdir(CdScope scope)
globaldir = NULL;
break;
case kCdScopeTab:
- // Remember this local directory for the tab page.
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- curtab->localdir = vim_strsave(NameBuff);
- }
+ curtab->tp_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeWindow:
- // Remember this local directory for the window.
- if (os_dirname(NameBuff, MAXPATHL) == OK) {
- curwin->w_localdir = vim_strsave(NameBuff);
- }
+ curwin->w_localdir = (char_u *)xstrdup(cwd);
break;
case kCdScopeInvalid:
- // We should never get here
assert(false);
}
- shorten_fnames(TRUE);
+ shorten_fnames(true);
+ do_autocmd_dirchanged(cwd, scope);
}
/// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`.
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 79a39c6503..b73d9944ce 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1519,7 +1519,7 @@ theend:
return file_name;
}
-static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
+void do_autocmd_dirchanged(char *new_dir, CdScope scope)
{
static bool recursive = false;
@@ -1550,10 +1550,11 @@ static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
}
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
- dict_add_nr_str(dict, "cwd", 0L, new_dir);
+ dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir);
dict_set_keys_readonly(dict);
- apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, new_dir, false, NULL);
+ apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
+ NULL);
dict_clear(dict);
@@ -1565,14 +1566,25 @@ static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
/// @return OK or FAIL
int vim_chdirfile(char_u *fname)
{
- char_u dir[MAXPATHL];
+ char dir[MAXPATHL];
STRLCPY(dir, fname, MAXPATHL);
- *path_tail_with_sep(dir) = NUL;
- if (os_chdir((char *)dir) != 0) {
+ *path_tail_with_sep((char_u *)dir) = NUL;
+
+ if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) {
+ NameBuff[0] = NUL;
+ }
+
+ if (os_chdir(dir) != 0) {
return FAIL;
}
- do_autocmd_dirchanged(dir, kCdScopeWindow);
+
+#ifdef BACKSLASH_IN_FILENAME
+ slash_adjust(dir);
+#endif
+ if (!strequal(dir, (char *)NameBuff)) {
+ do_autocmd_dirchanged(dir, kCdScopeWindow);
+ }
return OK;
}
@@ -1587,10 +1599,6 @@ int vim_chdir(char_u *new_dir, CdScope scope)
}
int r = os_chdir((char *)dir_name);
- if (r == 0) {
- do_autocmd_dirchanged(dir_name, scope);
- }
-
xfree(dir_name);
return r;
}
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index a05ac5f877..550d256de5 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -994,11 +994,12 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
return FALSE;
}
- if (*qfpos != '0') {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope",
- curbuf->b_fname, TRUE, curbuf);
- if (did_throw || force_abort)
- return FALSE;
+ if (*qfpos != '0'
+ && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)"cscope",
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
+ return false;
+ }
}
}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index b593936d7b..58c01fbe7a 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -475,6 +475,13 @@ void *xmemdup(const void *data, size_t len)
return memcpy(xmalloc(len), data, len);
}
+/// Returns true if strings `a` and `b` are equal. Arguments may be NULL.
+bool strequal(const char *a, const char *b)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0);
+}
+
/*
* Avoid repeating the error message many times (they take 1 second each).
* Did_outofmem_msg is reset when a character is read.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 92b1cf2d55..d010b4b3a7 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -7193,8 +7193,10 @@ static void nv_wordcmd(cmdarg_T *cap)
// Another strangeness: When standing on the end of a word "ce" will
// change until the end of the next word, but "cw" will change only one
// character! This is done by setting "flag".
- cap->oap->inclusive = true;
- word_end = true;
+ if (vim_strchr(p_cpo, CPO_CHANGEW) != NULL) {
+ cap->oap->inclusive = true;
+ word_end = true;
+ }
flag = true;
}
}
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 9c6393e014..1fd6dc9c91 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -129,9 +129,10 @@
#define CPO_REGAPPEND '>' /* insert NL when appending to a register */
#define CPO_SCOLON ';' /* using "," and ";" will skip over char if
* cursor would not move */
-/* default values for Vim and Vi */
-#define CPO_VIM "aABceFs"
-#define CPO_VI "aAbBcCdDeEfFiIJkKlLmMnoOpPqrRsStuvWxXyZ$!%+<>;"
+#define CPO_CHANGEW '_' // "cw" special-case
+// default values for Vim and Vi
+#define CPO_VIM "aABceFs_"
+#define CPO_VI "aAbBcCdDeEfFiIJkKlLmMnoOpPqrRsStuvWxXyZ$!%+<>;_"
/* characters for p_ww option: */
#define WW_ALL "bshl<>[],~"
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index c4b8d266cf..40a8066f75 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -3023,11 +3023,11 @@ void ex_make(exarg_T *eap)
case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break;
default: break;
}
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
- curbuf->b_fname, TRUE, curbuf);
- if (did_throw || force_abort)
+ if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
return;
+ }
}
if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep
@@ -3487,11 +3487,11 @@ void ex_vimgrep(exarg_T *eap)
case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break;
default: break;
}
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
- curbuf->b_fname, TRUE, curbuf);
- if (did_throw || force_abort)
+ if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
return;
+ }
}
if (eap->cmdidx == CMD_lgrep
@@ -4310,10 +4310,9 @@ void ex_cbuffer(exarg_T *eap)
break;
}
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name,
- curbuf->b_fname, true, curbuf);
- if (did_throw || force_abort) {
+ if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name,
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
return;
}
}
@@ -4396,10 +4395,9 @@ void ex_cexpr(exarg_T *eap)
default:
break;
}
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name,
- curbuf->b_fname, true, curbuf);
- if (did_throw || force_abort) {
+ if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, (char_u *)au_name,
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
return;
}
}
@@ -4455,11 +4453,11 @@ void ex_helpgrep(exarg_T *eap)
case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break;
default: break;
}
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
- curbuf->b_fname, TRUE, curbuf);
- if (did_throw || force_abort)
+ if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
+ curbuf->b_fname, true, curbuf)) {
+ if (aborting()) {
return;
+ }
}
/* Make 'cpoptions' empty, the 'l' flag should not be used here. */
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index cec7fc84a5..bd925a8106 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -238,6 +238,7 @@ Terminal *terminal_open(TerminalOptions opts)
set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL);
set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL);
+ set_option_value((uint8_t *)"list", false, NULL, OPT_LOCAL);
buf_set_term_title(curbuf, (char *)curbuf->b_ffname);
RESET_BINDING(curwin);
// Reset cursor in current window.
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 50fe6ce977..044c288ce0 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1560,3 +1560,20 @@ function Test_Autocmd()
\ 'postcaddbuffer']
call assert_equal(l, g:acmds)
endfunction
+
+function! Test_Autocmd_Exception()
+ set efm=%m
+ lgetexpr '?'
+
+ try
+ call DoesNotExit()
+ catch
+ lgetexpr '1'
+ finally
+ lgetexpr '1'
+ endtry
+
+ call assert_equal('1', getloclist(0)[0].text)
+
+ set efm&vim
+endfunction
diff --git a/src/nvim/version.c b/src/nvim/version.c
index ef865a3c71..c4d31c4abe 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -360,7 +360,7 @@ static int included_patches[] = {
// 2083,
2082,
2081,
- // 2080,
+ // 2080 NA
// 2079 NA
// 2078 NA
2077,
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 73a60b2e04..7c7d73fdfb 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2998,8 +2998,7 @@ void free_tabpage(tabpage_T *tp)
hash_init(&tp->tp_vars->dv_hashtab);
unref_var_dict(tp->tp_vars);
-
- xfree(tp->localdir); // Free tab-local working directory
+ xfree(tp->tp_localdir);
xfree(tp);
}
@@ -3025,7 +3024,7 @@ int win_new_tabpage(int after, char_u *filename)
return FAIL;
}
- newtp->localdir = tp->localdir ? vim_strsave(tp->localdir) : NULL;
+ newtp->tp_localdir = tp->tp_localdir ? vim_strsave(tp->tp_localdir) : NULL;
curtab = newtp;
@@ -3617,28 +3616,38 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
curwin->w_cursor.coladd = 0;
changed_line_abv_curs(); /* assume cursor position needs updating */
- // The new directory is either the local directory of the window, of the tab
- // or NULL.
- char_u *new_dir = curwin->w_localdir ? curwin->w_localdir : curtab->localdir;
+ // New directory is either the local directory of the window, tab or NULL.
+ char *new_dir = (char *)(curwin->w_localdir
+ ? curwin->w_localdir : curtab->tp_localdir);
+
+ char cwd[MAXPATHL];
+ if (os_dirname((char_u *)cwd, MAXPATHL) != OK) {
+ cwd[0] = NUL;
+ }
if (new_dir) {
// Window/tab has a local directory: Save current directory as global
- // directory (unless that was done already) and change to the local
- // directory.
+ // (unless that was done already) and change to the local directory.
if (globaldir == NULL) {
- char_u cwd[MAXPATHL];
-
- if (os_dirname(cwd, MAXPATHL) == OK) {
- globaldir = vim_strsave(cwd);
+ if (cwd[0] != NUL) {
+ globaldir = (char_u *)xstrdup(cwd);
}
}
- if (os_chdir((char *)new_dir) == 0) {
+ if (os_chdir(new_dir) == 0) {
+ if (!p_acd && !strequal(new_dir, cwd)) {
+ do_autocmd_dirchanged(new_dir, curwin->w_localdir
+ ? kCdScopeWindow : kCdScopeTab);
+ }
shorten_fnames(true);
}
} else if (globaldir != NULL) {
- /* Window doesn't have a local directory and we are not in the global
- * directory: Change to the global directory. */
- ignored = os_chdir((char *)globaldir);
+ // 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);
+ }
+ }
xfree(globaldir);
globaldir = NULL;
shorten_fnames(TRUE);