mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.0.1459: cannot handle change of directory
Problem: Cannot handle change of directory. Solution: Add the DirChanged autocommand event. (Andy Massimino, closes vim/vim#888) Avoid changing directory for 'autochdir' too often.b7407d3fc9
Only add "auto" pattern. "window" and "global" are already implemented. Skip `Test_dirchanged_auto` using `CheckFunction test_autochdir`. Part of PR #15952. More information can be found there. N/A patches for version.c: vim-patch:8.0.1460: missing file in patch Problem: Missing file in patch. Solution: Add changes to missing file.b5cb65ba2b
vim-patch:8.0.1461: missing another file in patch Problem: Missing another file in patch. Solution: Add changes to missing file.15833239a4
This commit is contained in:
parent
30af69509d
commit
920473d2f2
@ -519,11 +519,17 @@ DiffUpdated After diffs have been updated. Depending on
|
|||||||
change or when doing |:diffupdate|.
|
change or when doing |:diffupdate|.
|
||||||
*DirChanged*
|
*DirChanged*
|
||||||
DirChanged After the |current-directory| was changed.
|
DirChanged After the |current-directory| was changed.
|
||||||
|
The pattern can be:
|
||||||
|
"window" to trigger on `:lcd`
|
||||||
|
"tab" to trigger on `:tcd`
|
||||||
|
"global" to trigger on `:cd`
|
||||||
|
"auto" to trigger on 'autochdir'.
|
||||||
Sets these |v:event| keys:
|
Sets these |v:event| keys:
|
||||||
cwd: current working directory
|
cwd: current working directory
|
||||||
scope: "global", "tab", "window"
|
scope: "global", "tab", "window"
|
||||||
changed_window: v:true if we fired the event
|
changed_window: v:true if we fired the event
|
||||||
switching window (or tab)
|
switching window (or tab)
|
||||||
|
<afile> is set to the new directory name.
|
||||||
Non-recursive (event cannot trigger itself).
|
Non-recursive (event cannot trigger itself).
|
||||||
*FileAppendCmd*
|
*FileAppendCmd*
|
||||||
FileAppendCmd Before appending to a file. Should do the
|
FileAppendCmd Before appending to a file. Should do the
|
||||||
|
@ -180,6 +180,7 @@ Commands:
|
|||||||
|:match| can be invoked before highlight group is defined
|
|:match| can be invoked before highlight group is defined
|
||||||
|
|
||||||
Events:
|
Events:
|
||||||
|
|DirChanged| can be triggered when switching to another window
|
||||||
|Signal|
|
|Signal|
|
||||||
|TabNewEntered|
|
|TabNewEntered|
|
||||||
|TermClose|
|
|TermClose|
|
||||||
|
@ -593,9 +593,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
|
|||||||
buf->b_nwindows--;
|
buf->b_nwindows--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change directories when the 'acd' option is set.
|
|
||||||
do_autochdir();
|
|
||||||
|
|
||||||
// Disable buffer-updates for the current buffer.
|
// Disable buffer-updates for the current buffer.
|
||||||
// No need to check `unload_buf`: in that case the function returned above.
|
// No need to check `unload_buf`: in that case the function returned above.
|
||||||
buf_updates_unload(buf, false);
|
buf_updates_unload(buf, false);
|
||||||
@ -1628,7 +1625,7 @@ void do_autochdir(void)
|
|||||||
if (p_acd) {
|
if (p_acd) {
|
||||||
if (starting == 0
|
if (starting == 0
|
||||||
&& curbuf->b_ffname != NULL
|
&& curbuf->b_ffname != NULL
|
||||||
&& vim_chdirfile(curbuf->b_ffname) == OK) {
|
&& vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) {
|
||||||
post_chdir(kCdScopeGlobal, false);
|
post_chdir(kCdScopeGlobal, false);
|
||||||
shorten_fnames(true);
|
shorten_fnames(true);
|
||||||
}
|
}
|
||||||
|
@ -7749,7 +7749,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
|
|||||||
shorten_fnames(true);
|
shorten_fnames(true);
|
||||||
|
|
||||||
if (trigger_dirchanged) {
|
if (trigger_dirchanged) {
|
||||||
do_autocmd_dirchanged(cwd, scope, false);
|
do_autocmd_dirchanged(cwd, scope, kCdCauseManual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +963,7 @@ void ex_mkrc(exarg_T *eap)
|
|||||||
*dirnow = NUL;
|
*dirnow = NUL;
|
||||||
}
|
}
|
||||||
if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) {
|
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);
|
shorten_fnames(true);
|
||||||
}
|
}
|
||||||
} else if (*dirnow != NUL
|
} else if (*dirnow != NUL
|
||||||
|
@ -1590,7 +1590,7 @@ theend:
|
|||||||
return file_name;
|
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;
|
static bool recursive = false;
|
||||||
|
|
||||||
@ -1621,10 +1621,22 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tv_dict_add_str(dict, S_LEN("scope"), buf); // -V614
|
tv_dict_add_str(dict, S_LEN("scope"), buf); // -V614
|
||||||
tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
|
tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
|
||||||
tv_dict_add_bool(dict, S_LEN("changed_window"), changed_window);
|
tv_dict_add_bool(dict, S_LEN("changed_window"), cause == kCdCauseWindow);
|
||||||
tv_dict_set_keys_readonly(dict);
|
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,
|
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
|
||||||
curbuf);
|
curbuf);
|
||||||
|
|
||||||
@ -1636,7 +1648,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window)
|
|||||||
/// Change to a file's directory.
|
/// Change to a file's directory.
|
||||||
/// Caller must call shorten_fnames()!
|
/// Caller must call shorten_fnames()!
|
||||||
/// @return OK or FAIL
|
/// @return OK or FAIL
|
||||||
int vim_chdirfile(char_u *fname)
|
int vim_chdirfile(char_u *fname, CdCause cause)
|
||||||
{
|
{
|
||||||
char dir[MAXPATHL];
|
char dir[MAXPATHL];
|
||||||
|
|
||||||
@ -1654,8 +1666,8 @@ int vim_chdirfile(char_u *fname)
|
|||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
slash_adjust((char_u *)dir);
|
slash_adjust((char_u *)dir);
|
||||||
#endif
|
#endif
|
||||||
if (!strequal(dir, (char *)NameBuff)) {
|
if (cause != kCdCauseOther && !strequal(dir, (char *)NameBuff)) {
|
||||||
do_autocmd_dirchanged(dir, kCdScopeWindow, false);
|
do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -1042,6 +1042,14 @@ typedef enum {
|
|||||||
#define MIN_CD_SCOPE kCdScopeWindow
|
#define MIN_CD_SCOPE kCdScopeWindow
|
||||||
#define MAX_CD_SCOPE kCdScopeGlobal
|
#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.
|
// Only filled for Win32.
|
||||||
EXTERN char windowsVersion[20] INIT(= { 0 });
|
EXTERN char windowsVersion[20] INIT(= { 0 });
|
||||||
|
|
||||||
|
@ -1328,6 +1328,62 @@ func Test_autocommand_all_events()
|
|||||||
call assert_fails('au * x bwipe', 'E1155:')
|
call assert_fails('au * x bwipe', 'E1155:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
function s:Before_test_dirchanged()
|
||||||
|
augroup test_dirchanged
|
||||||
|
autocmd!
|
||||||
|
augroup END
|
||||||
|
let s:li = []
|
||||||
|
let s:dir_this = getcwd()
|
||||||
|
let s:dir_other = s:dir_this . '/foo'
|
||||||
|
call mkdir(s:dir_other)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
function s:After_test_dirchanged()
|
||||||
|
exe 'cd' s:dir_this
|
||||||
|
call delete(s:dir_other, '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>"))
|
||||||
|
exe 'cd' s:dir_other
|
||||||
|
call assert_equal(["cd:", s:dir_other], s:li)
|
||||||
|
exe 'lcd' s:dir_other
|
||||||
|
call assert_equal(["cd:", s:dir_other], 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>"))
|
||||||
|
exe 'cd' s:dir_other
|
||||||
|
call assert_equal([], s:li)
|
||||||
|
exe 'lcd' s:dir_other
|
||||||
|
call assert_equal(["lcd:", s:dir_other], s:li)
|
||||||
|
call s:After_test_dirchanged()
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
function Test_dirchanged_auto()
|
||||||
|
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
|
||||||
|
exe 'cd ..'
|
||||||
|
call assert_equal([], s:li)
|
||||||
|
exe 'edit ' . s:dir_other . '/Xfile'
|
||||||
|
call assert_equal(s:dir_other, getcwd())
|
||||||
|
call assert_equal(["auto:", s:dir_other], s:li)
|
||||||
|
set noacd
|
||||||
|
bwipe!
|
||||||
|
call s:After_test_dirchanged()
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test TextChangedI and TextChangedP
|
" Test TextChangedI and TextChangedP
|
||||||
" See test/functional/viml/completion_spec.lua'
|
" See test/functional/viml/completion_spec.lua'
|
||||||
func Test_ChangedP()
|
func Test_ChangedP()
|
||||||
|
@ -4542,7 +4542,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
|||||||
if (os_chdir(new_dir) == 0) {
|
if (os_chdir(new_dir) == 0) {
|
||||||
if (!p_acd && !strequal(new_dir, cwd)) {
|
if (!p_acd && !strequal(new_dir, cwd)) {
|
||||||
do_autocmd_dirchanged(new_dir, curwin->w_localdir
|
do_autocmd_dirchanged(new_dir, curwin->w_localdir
|
||||||
? kCdScopeWindow : kCdScopeTab, true);
|
? kCdScopeWindow : kCdScopeTab, kCdCauseWindow);
|
||||||
}
|
}
|
||||||
shorten_fnames(true);
|
shorten_fnames(true);
|
||||||
}
|
}
|
||||||
@ -4551,7 +4551,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
|
|||||||
// directory: Change to the global directory.
|
// directory: Change to the global directory.
|
||||||
if (os_chdir((char *)globaldir) == 0) {
|
if (os_chdir((char *)globaldir) == 0) {
|
||||||
if (!p_acd && !strequal((char *)globaldir, cwd)) {
|
if (!p_acd && !strequal((char *)globaldir, cwd)) {
|
||||||
do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, true);
|
do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XFREE_CLEAR(globaldir);
|
XFREE_CLEAR(globaldir);
|
||||||
|
Loading…
Reference in New Issue
Block a user