From bd8025727cc1ca4389af8fc690b467e2e25a3903 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Wed, 11 Jan 2017 00:51:31 +0100 Subject: New event: DirChanged --- src/nvim/auevents.lua | 2 ++ src/nvim/ex_docmd.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 8d891effae..6c62748aae 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -28,6 +28,7 @@ return { 'CursorHoldI', -- idem, in Insert mode 'CursorMoved', -- cursor was moved 'CursorMovedI', -- cursor was moved in Insert mode + 'DirChanged', -- directory changed 'EncodingChanged', -- after changing the 'encoding' option 'FileAppendCmd', -- append to a file using command 'FileAppendPost', -- after appending to a file @@ -101,6 +102,7 @@ return { -- List of neovim-specific events or aliases for the purpose of generating -- syntax file neovim_specific = { + DirChanged=true, TabClosed=true, TabNew=true, TabNewEntered=true, diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 5ff79bcfef..e5c05a2498 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6949,6 +6949,35 @@ void free_cd_dir(void) #endif +static 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. /// /// @param scope Scope of the function call (global, tab or window). @@ -6972,6 +7001,8 @@ void post_chdir(CdScope scope) } } + apply_autocmd_dirchanged(new_dir, scope); + switch (scope) { case kCdScopeGlobal: // We are now in the global directory, no need to remember its name. @@ -6998,8 +7029,6 @@ void post_chdir(CdScope scope) shorten_fnames(TRUE); } - - /// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`. void ex_cd(exarg_T *eap) { @@ -7061,8 +7090,8 @@ void ex_cd(exarg_T *eap) post_chdir(scope); - /* Echo the new current directory if the command was typed. */ - if (KeyTyped || p_verbose >= 5) + // Echo the new current directory if the command was typed. + if (KeyTyped || p_verbose >= 5) { ex_pwd(eap); } xfree(tofree); -- cgit From 30f775f8a6061697c3a3619f26c21d237ad92027 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Wed, 11 Jan 2017 14:16:43 +0100 Subject: Don't expand filenames during autocmd --- src/nvim/fileio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 6f95ced147..3f5152aea3 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6716,8 +6716,9 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, fname = vim_strsave(fname); /* make a copy, so we can change it */ } else { sfname = vim_strsave(fname); - // don't try expanding the following events + // Don't try expanding the following events. if (event == EVENT_COLORSCHEME + || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED || event == EVENT_OPTIONSET @@ -6726,10 +6727,11 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX - || event == EVENT_TABCLOSED) + || event == EVENT_TABCLOSED) { fname = vim_strsave(fname); - else - fname = (char_u *)FullName_save((char *)fname, FALSE); + } else { + fname = (char_u *)FullName_save((char *)fname, false); + } } if (fname == NULL) { /* out of memory */ xfree(sfname); -- cgit From 197f50bf9ab5c1c8ba4925e3e556830a9b7fd826 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Thu, 12 Jan 2017 14:25:11 +0100 Subject: Trigger DirChanged on 'autochdir' --- src/nvim/ex_docmd.c | 2 +- src/nvim/file_search.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e5c05a2498..86f387d9a5 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6949,7 +6949,7 @@ void free_cd_dir(void) #endif -static void apply_autocmd_dirchanged(char_u *new_dir, CdScope scope) +void apply_autocmd_dirchanged(char_u *new_dir, CdScope scope) { dict_T *dict = get_vim_var_dict(VV_EVENT); char buf[8]; diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 2ac8e27047..56c0cb73a6 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -51,6 +51,7 @@ #include "nvim/ascii.h" #include "nvim/file_search.h" #include "nvim/charset.h" +#include "nvim/ex_docmd.h" #include "nvim/fileio.h" #include "nvim/memory.h" #include "nvim/message.h" @@ -1531,7 +1532,12 @@ int vim_chdirfile(char_u *fname) STRLCPY(dir, fname, MAXPATHL); *path_tail_with_sep(dir) = NUL; - return os_chdir((char *)dir) == 0 ? OK : FAIL; + if (os_chdir((char *)dir) != 0) { + return FAIL; + } + apply_autocmd_dirchanged(dir, kCdScopeWindow); + + return OK; } /// Change directory to "new_dir". Search 'cdpath' for relative directory names. -- cgit From a05779aa1c13149c26678419890653f15fd00127 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Thu, 12 Jan 2017 19:26:53 +0100 Subject: Move apply_autocmd_dirchanged() to vim_chdir() --- src/nvim/api/vim.c | 2 +- src/nvim/ex_docmd.c | 66 ++++++++++++++------------------------------------ src/nvim/ex_docmd.h | 15 ------------ src/nvim/file_search.c | 52 ++++++++++++++++++++++++++++++++++++--- src/nvim/globals.h | 16 ++++++++++++ src/nvim/types.h | 1 + 6 files changed, 85 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b17b59f7a6..f37e996f06 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -315,7 +315,7 @@ void nvim_set_current_dir(String dir, Error *err) try_start(); - if (vim_chdir((char_u *)string)) { + if (vim_chdir((char_u *)string, kCdScopeGlobal)) { if (!try_end(err)) { api_set_error(err, Exception, _("Failed to change directory")); } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 86f387d9a5..e205901635 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6949,35 +6949,6 @@ void free_cd_dir(void) #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. /// /// @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) { case kCdScopeGlobal: // We are now in the global directory, no need to remember its name. @@ -7070,30 +7039,31 @@ void ex_cd(exarg_T *eap) new_dir = NameBuff; } #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) { - case CMD_tcd: - case CMD_tchdir: - scope = kCdScopeTab; - break; - case CMD_lcd: - case CMD_lchdir: - scope = kCdScopeWindow; - break; - default: - break; - } + switch (eap->cmdidx) { + case CMD_tcd: + case CMD_tchdir: + scope = kCdScopeTab; + break; + case CMD_lcd: + case CMD_lchdir: + scope = kCdScopeWindow; + break; + default: + break; + } + if (vim_chdir(new_dir, scope)) { + EMSG(_(e_failed)); + } else { post_chdir(scope); - // Echo the new current directory if the command was typed. if (KeyTyped || p_verbose >= 5) { ex_pwd(eap); + } } + xfree(tofree); } } diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index fb6aac223f..4def4cbbae 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -19,21 +19,6 @@ #define EXMODE_NORMAL 1 #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 # include "ex_docmd.h.generated.h" #endif diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 56c0cb73a6..eb93921bb0 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -48,10 +48,10 @@ #include #include "nvim/vim.h" +#include "nvim/eval.h" #include "nvim/ascii.h" #include "nvim/file_search.h" #include "nvim/charset.h" -#include "nvim/ex_docmd.h" #include "nvim/fileio.h" #include "nvim/memory.h" #include "nvim/message.h" @@ -1523,6 +1523,47 @@ theend: 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. /// Caller must call shorten_fnames()! /// @return OK or FAIL @@ -1535,20 +1576,25 @@ int vim_chdirfile(char_u *fname) if (os_chdir((char *)dir) != 0) { return FAIL; } - apply_autocmd_dirchanged(dir, kCdScopeWindow); + do_autocmd_dirchanged(dir, kCdScopeWindow); return OK; } /// 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), FNAME_MESS, curbuf->b_ffname); if (dir_name == NULL) { return -1; } + 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/globals.h b/src/nvim/globals.h index 463f4fcd8d..e3c84cb852 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1249,4 +1249,20 @@ typedef enum { kBroken } 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 */ diff --git a/src/nvim/types.h b/src/nvim/types.h index 35a5d1e2bd..317bead3bb 100644 --- a/src/nvim/types.h +++ b/src/nvim/types.h @@ -14,4 +14,5 @@ typedef unsigned char char_u; typedef uint32_t u8char_T; typedef struct expand expand_T; + #endif // NVIM_TYPES_H -- cgit From 1f7a119f5efc13fbce6446bf268c2e0f9d753147 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Fri, 13 Jan 2017 03:06:20 +0100 Subject: Rename yank_do_autocmd() to do_autocmd_textyankpost() --- src/nvim/ops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 907353c271..10d6be85f8 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1404,7 +1404,7 @@ int op_delete(oparg_T *oap) if (oap->regname == 0) { set_clipboard(0, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); } } @@ -2315,7 +2315,7 @@ bool op_yank(oparg_T *oap, bool message) yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK); op_yank_reg(oap, message, reg, is_append_register(oap->regname)); set_clipboard(oap->regname, reg); - yank_do_autocmd(oap, reg); + do_autocmd_textyankpost(oap, reg); return true; } @@ -2538,7 +2538,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx) /// /// @param oap Operator arguments. /// @param reg The yank register used. -static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) +static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) FUNC_ATTR_NONNULL_ALL { static bool recursive = false; -- cgit