Move apply_autocmd_dirchanged() to vim_chdir()

This commit is contained in:
Marco Hinz 2017-01-12 19:26:53 +01:00
parent a2f8adad4c
commit a05779aa1c
No known key found for this signature in database
GPG Key ID: 1C980A1B657B4A4F
6 changed files with 85 additions and 67 deletions

View File

@ -315,7 +315,7 @@ void nvim_set_current_dir(String dir, Error *err)
try_start(); try_start();
if (vim_chdir((char_u *)string)) { if (vim_chdir((char_u *)string, kCdScopeGlobal)) {
if (!try_end(err)) { if (!try_end(err)) {
api_set_error(err, Exception, _("Failed to change directory")); api_set_error(err, Exception, _("Failed to change directory"));
} }

View File

@ -6949,35 +6949,6 @@ void free_cd_dir(void)
#endif #endif
void apply_autocmd_dirchanged(char_u *new_dir, CdScope scope)
{
dict_T *dict = get_vim_var_dict(VV_EVENT);
char buf[8];
switch (scope) {
case kCdScopeGlobal:
snprintf(buf, sizeof(buf), "global");
break;
case kCdScopeTab:
snprintf(buf, sizeof(buf), "tab");
break;
case kCdScopeWindow:
snprintf(buf, sizeof(buf), "window");
break;
case kCdScopeInvalid:
// Should never happen.
assert(false);
}
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
dict_add_nr_str(dict, "cwd", 0L, new_dir);
dict_set_keys_readonly(dict);
apply_autocmds(EVENT_DIRCHANGED, NULL, new_dir, false, NULL);
dict_clear(dict);
}
/// Deal with the side effects of changing the current directory. /// Deal with the side effects of changing the current directory.
/// ///
/// @param scope Scope of the function call (global, tab or window). /// @param scope Scope of the function call (global, tab or window).
@ -7001,8 +6972,6 @@ void post_chdir(CdScope scope)
} }
} }
apply_autocmd_dirchanged(new_dir, scope);
switch (scope) { switch (scope) {
case kCdScopeGlobal: case kCdScopeGlobal:
// We are now in the global directory, no need to remember its name. // We are now in the global directory, no need to remember its name.
@ -7070,9 +7039,6 @@ void ex_cd(exarg_T *eap)
new_dir = NameBuff; new_dir = NameBuff;
} }
#endif #endif
if (vim_chdir(new_dir)) {
EMSG(_(e_failed));
} else {
CdScope scope = kCdScopeGlobal; // Depends on command invoked CdScope scope = kCdScopeGlobal; // Depends on command invoked
switch (eap->cmdidx) { switch (eap->cmdidx) {
@ -7088,12 +7054,16 @@ void ex_cd(exarg_T *eap)
break; break;
} }
if (vim_chdir(new_dir, scope)) {
EMSG(_(e_failed));
} else {
post_chdir(scope); post_chdir(scope);
// Echo the new current directory if the command was typed. // Echo the new current directory if the command was typed.
if (KeyTyped || p_verbose >= 5) { if (KeyTyped || p_verbose >= 5) {
ex_pwd(eap); ex_pwd(eap);
} }
}
xfree(tofree); xfree(tofree);
} }
} }

View File

@ -19,21 +19,6 @@
#define EXMODE_NORMAL 1 #define EXMODE_NORMAL 1
#define EXMODE_VIM 2 #define EXMODE_VIM 2
/// The scope of a working-directory command like `:cd`.
///
/// Scopes are enumerated from lowest to highest. When adding a scope make sure
/// to update all functions using scopes as well, such as the implementation of
/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes
/// 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 instance of Neovim.
} CdScope;
#define MIN_CD_SCOPE kCdScopeWindow
#define MAX_CD_SCOPE kCdScopeGlobal
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_docmd.h.generated.h" # include "ex_docmd.h.generated.h"
#endif #endif

View File

@ -48,10 +48,10 @@
#include <limits.h> #include <limits.h>
#include "nvim/vim.h" #include "nvim/vim.h"
#include "nvim/eval.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/file_search.h" #include "nvim/file_search.h"
#include "nvim/charset.h" #include "nvim/charset.h"
#include "nvim/ex_docmd.h"
#include "nvim/fileio.h" #include "nvim/fileio.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/message.h" #include "nvim/message.h"
@ -1523,6 +1523,47 @@ theend:
return file_name; return file_name;
} }
static void do_autocmd_dirchanged(char_u *new_dir, CdScope scope)
{
static bool recursive = false;
if (recursive || !has_event(EVENT_DIRCHANGED)) {
// No autocommand was defined or we changed
// the directory from this autocommand.
return;
}
recursive = true;
dict_T *dict = get_vim_var_dict(VV_EVENT);
char buf[8];
switch (scope) {
case kCdScopeGlobal:
snprintf(buf, sizeof(buf), "global");
break;
case kCdScopeTab:
snprintf(buf, sizeof(buf), "tab");
break;
case kCdScopeWindow:
snprintf(buf, sizeof(buf), "window");
break;
case kCdScopeInvalid:
// Should never happen.
assert(false);
}
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
dict_add_nr_str(dict, "cwd", 0L, new_dir);
dict_set_keys_readonly(dict);
apply_autocmds(EVENT_DIRCHANGED, NULL, new_dir, false, NULL);
dict_clear(dict);
recursive = false;
}
/// 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
@ -1535,20 +1576,25 @@ int vim_chdirfile(char_u *fname)
if (os_chdir((char *)dir) != 0) { if (os_chdir((char *)dir) != 0) {
return FAIL; return FAIL;
} }
apply_autocmd_dirchanged(dir, kCdScopeWindow); do_autocmd_dirchanged(dir, kCdScopeWindow);
return OK; return OK;
} }
/// Change directory to "new_dir". Search 'cdpath' for relative directory names. /// Change directory to "new_dir". Search 'cdpath' for relative directory names.
int vim_chdir(char_u *new_dir) int vim_chdir(char_u *new_dir, CdScope scope)
{ {
char_u *dir_name = find_directory_in_path(new_dir, STRLEN(new_dir), char_u *dir_name = find_directory_in_path(new_dir, STRLEN(new_dir),
FNAME_MESS, curbuf->b_ffname); FNAME_MESS, curbuf->b_ffname);
if (dir_name == NULL) { if (dir_name == NULL) {
return -1; return -1;
} }
int r = os_chdir((char *)dir_name); int r = os_chdir((char *)dir_name);
if (r == 0) {
do_autocmd_dirchanged(dir_name, scope);
}
xfree(dir_name); xfree(dir_name);
return r; return r;
} }

View File

@ -1249,4 +1249,20 @@ typedef enum {
kBroken kBroken
} WorkingStatus; } WorkingStatus;
/// The scope of a working-directory command like `:cd`.
///
/// Scopes are enumerated from lowest to highest. When adding a scope make sure
/// to update all functions using scopes as well, such as the implementation of
/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes
/// 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 instance of Neovim.
} CdScope;
#define MIN_CD_SCOPE kCdScopeWindow
#define MAX_CD_SCOPE kCdScopeGlobal
#endif /* NVIM_GLOBALS_H */ #endif /* NVIM_GLOBALS_H */

View File

@ -14,4 +14,5 @@ typedef unsigned char char_u;
typedef uint32_t u8char_T; typedef uint32_t u8char_T;
typedef struct expand expand_T; typedef struct expand expand_T;
#endif // NVIM_TYPES_H #endif // NVIM_TYPES_H