aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/file_search.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/file_search.c')
-rw-r--r--src/nvim/file_search.c189
1 files changed, 94 insertions, 95 deletions
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index b2cd5c510b..ca276b8a40 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -146,7 +146,6 @@ typedef struct ff_visited_list_hdr {
ff_visited_T *ffvl_visited_list;
} ff_visited_list_hdr_T;
-
/*
* '**' can be expanded to several directory levels.
* Set the default maximum depth.
@@ -298,7 +297,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
&& (vim_ispathsep(path[1]) || path[1] == NUL)
&& (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
&& rel_fname != NULL) {
- size_t len = (size_t)(path_tail(rel_fname) - rel_fname);
+ size_t len = (size_t)((char_u *)path_tail((char *)rel_fname) - rel_fname);
if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) {
// Make the start dir an absolute path name.
@@ -371,23 +370,23 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
ptr = xrealloc(search_ctx->ffsc_stopdirs_v,
(dircount + 1) * sizeof(char_u *));
search_ctx->ffsc_stopdirs_v = ptr;
- walker = vim_strchr(walker, ';');
+ walker = (char_u *)vim_strchr((char *)walker, ';');
if (walker) {
assert(walker - helper >= 0);
- search_ctx->ffsc_stopdirs_v[dircount-1] =
+ search_ctx->ffsc_stopdirs_v[dircount - 1] =
vim_strnsave(helper, (size_t)(walker - helper));
walker++;
} else {
/* this might be "", which means ascent till top
* of directory tree.
*/
- search_ctx->ffsc_stopdirs_v[dircount-1] =
+ search_ctx->ffsc_stopdirs_v[dircount - 1] =
vim_strsave(helper);
}
dircount++;
} while (walker != NULL);
- search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = NULL;
}
search_ctx->ffsc_level = level;
@@ -396,7 +395,7 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
* -fix path
* -wildcard_stuff (might be NULL)
*/
- wc_part = vim_strchr(path, '*');
+ wc_part = (char_u *)vim_strchr((char *)path, '*');
if (wc_part != NULL) {
int64_t llevel;
int len;
@@ -477,14 +476,20 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path);
add_pathsep((char *)ff_expand_buffer);
} else {
- char_u *p = path_tail(search_ctx->ffsc_fix_path);
+ char_u *p = (char_u *)path_tail((char *)search_ctx->ffsc_fix_path);
char_u *wc_path = NULL;
char_u *temp = NULL;
int len = 0;
if (p > search_ctx->ffsc_fix_path) {
+ // do not add '..' to the path and start upwards searching
len = (int)(p - search_ctx->ffsc_fix_path) - 1;
- STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len);
+ if ((len >= 2 && STRNCMP(search_ctx->ffsc_fix_path, "..", 2) == 0)
+ && (len == 2 || search_ctx->ffsc_fix_path[2] == PATHSEP)) {
+ xfree(buf);
+ goto error_return;
+ }
+ STRLCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1);
add_pathsep((char *)ff_expand_buffer);
} else {
len = (int)STRLEN(search_ctx->ffsc_fix_path);
@@ -523,9 +528,7 @@ error_return:
return NULL;
}
-/*
- * Get the stopdir string. Check that ';' is not escaped.
- */
+/// @return the stopdir string. Check that ';' is not escaped.
char_u *vim_findfile_stopdir(char_u *buf)
{
char_u *r_ptr = buf;
@@ -548,9 +551,7 @@ char_u *vim_findfile_stopdir(char_u *buf)
return r_ptr;
}
-/*
- * Clean up the given search context. Can handle a NULL pointer.
- */
+/// Clean up the given search context. Can handle a NULL pointer.
void vim_findfile_cleanup(void *ctx)
{
if (ctx == NULL) {
@@ -562,18 +563,19 @@ void vim_findfile_cleanup(void *ctx)
xfree(ctx);
}
-/*
- * Find a file in a search context.
- * The search context was created with vim_findfile_init() above.
- * Return a pointer to an allocated file name or NULL if nothing found.
- * To get all matching files call this function until you get NULL.
- *
- * If the passed search_context is NULL, NULL is returned.
- *
- * The search algorithm is depth first. To change this replace the
- * stack with a list (don't forget to leave partly searched directories on the
- * top of the list).
- */
+/// Find a file in a search context.
+/// The search context was created with vim_findfile_init() above.
+///
+/// To get all matching files call this function until you get NULL.
+///
+/// If the passed search_context is NULL, NULL is returned.
+///
+/// The search algorithm is depth first. To change this replace the
+/// stack with a list (don't forget to leave partly searched directories on the
+/// top of the list).
+///
+/// @return a pointer to an allocated file name or,
+/// NULL if nothing found.
char_u *vim_findfile(void *search_ctx_arg)
{
char_u *file_path;
@@ -891,8 +893,7 @@ char_u *vim_findfile(void *search_ctx_arg)
break;
}
assert(MAXPATHL >= len);
- copy_option_part(&suf, file_path + len,
- MAXPATHL - len, ",");
+ copy_option_part((char **)&suf, (char *)file_path + len, MAXPATHL - len, ",");
}
}
} else {
@@ -921,8 +922,8 @@ char_u *vim_findfile(void *search_ctx_arg)
*/
if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) {
for (int i = stackp->ffs_filearray_cur;
- i < stackp->ffs_filearray_size; ++i) {
- if (fnamecmp(stackp->ffs_filearray[i],
+ i < stackp->ffs_filearray_size; i++) {
+ if (FNAMECMP(stackp->ffs_filearray[i],
stackp->ffs_fix_path) == 0) {
continue; // don't repush same directory
}
@@ -993,10 +994,8 @@ fail:
return NULL;
}
-/*
- * Free the list of lists of visited files and directories
- * Can handle it if the passed search_context is NULL;
- */
+/// Free the list of lists of visited files and directories
+/// Can handle it if the passed search_context is NULL;
void vim_findfile_free_visited(void *search_ctx_arg)
{
ff_search_ctx_T *search_ctx;
@@ -1038,10 +1037,8 @@ static void ff_free_visited_list(ff_visited_T *vl)
vl = NULL;
}
-/*
- * Returns the already visited list for the given filename. If none is found it
- * allocates a new one.
- */
+/// @return the already visited list for the given filename. If none is found it
+/// allocates a new one.
static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
ff_visited_list_hdr_T **list_headp)
{
@@ -1051,7 +1048,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
if (*list_headp != NULL) {
retptr = *list_headp;
while (retptr != NULL) {
- if (fnamecmp(filename, retptr->ffvl_filename) == 0) {
+ if (FNAMECMP(filename, retptr->ffvl_filename) == 0) {
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
@@ -1088,13 +1085,13 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
return retptr;
}
-// Check if two wildcard paths are equal.
-// They are equal if:
-// - both paths are NULL
-// - they have the same length
-// - char by char comparison is OK
-// - the only differences are in the counters behind a '**', so
-// '**\20' is equal to '**\24'
+/// Check if two wildcard paths are equal.
+/// They are equal if:
+/// - both paths are NULL
+/// - they have the same length
+/// - char by char comparison is OK
+/// - the only differences are in the counters behind a '**', so
+/// '**\20' is equal to '**\24'
static bool ff_wc_equal(char_u *s1, char_u *s2)
{
int i, j;
@@ -1112,8 +1109,8 @@ static bool ff_wc_equal(char_u *s1, char_u *s2)
}
for (i = 0, j = 0; s1[i] != NUL && s2[j] != NUL;) {
- c1 = utf_ptr2char(s1 + i);
- c2 = utf_ptr2char(s2 + j);
+ c1 = utf_ptr2char((char *)s1 + i);
+ c2 = utf_ptr2char((char *)s2 + j);
if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2)
&& (prev1 != '*' || prev2 != '*')) {
@@ -1122,17 +1119,16 @@ static bool ff_wc_equal(char_u *s1, char_u *s2)
prev2 = prev1;
prev1 = c1;
- i += utfc_ptr2len(s1 + i);
- j += utfc_ptr2len(s2 + j);
+ i += utfc_ptr2len((char *)s1 + i);
+ j += utfc_ptr2len((char *)s2 + j);
}
return s1[i] == s2[j];
}
-/*
- * maintains the list of already visited files and dirs
- * returns FAIL if the given file/dir is already in the list
- * returns OK if it is newly added
- */
+/// maintains the list of already visited files and dirs
+///
+/// @return FAIL if the given file/dir is already in the list or,
+/// OK if it is newly added
static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *wc_path)
{
ff_visited_T *vp;
@@ -1153,7 +1149,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
// check against list of already visited files
for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) {
- if ((url && fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0)
+ if ((url && FNAMECMP(vp->ffv_fname, ff_expand_buffer) == 0)
|| (!url && vp->file_id_valid
&& os_fileid_equal(&(vp->file_id), &file_id))) {
// are the wildcard parts equal
@@ -1190,9 +1186,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
return OK;
}
-/*
- * create stack element from given path pieces
- */
+/// create stack element from given path pieces
static ff_stack_T *ff_create_stack_element(char_u *fix_part, char_u *wc_part, int level,
int star_star_empty)
{
@@ -1220,9 +1214,7 @@ static ff_stack_T *ff_create_stack_element(char_u *fix_part, char_u *wc_part, in
return new;
}
-/*
- * Push a dir on the directory stack.
- */
+/// Push a dir on the directory stack.
static void ff_push(ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)
{
/* check for NULL pointer, not to return an error to the user, but
@@ -1233,10 +1225,9 @@ static void ff_push(ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)
}
}
-/*
- * Pop a dir from the directory stack.
- * Returns NULL if stack is empty.
- */
+/// Pop a dir from the directory stack.
+///
+/// @return NULL if stack is empty.
static ff_stack_T *ff_pop(ff_search_ctx_T *search_ctx)
{
ff_stack_T *sptr;
@@ -1249,9 +1240,7 @@ static ff_stack_T *ff_pop(ff_search_ctx_T *search_ctx)
return sptr;
}
-/*
- * free the given stack element
- */
+/// free the given stack element
static void ff_free_stack_element(ff_stack_T *const stack_ptr)
{
if (stack_ptr == NULL) {
@@ -1269,9 +1258,7 @@ static void ff_free_stack_element(ff_stack_T *const stack_ptr)
xfree(stack_ptr);
}
-/*
- * Clear the search context, but NOT the visited list.
- */
+/// Clear the search context, but NOT the visited list.
static void ff_clear(ff_search_ctx_T *search_ctx)
{
ff_stack_T *sptr;
@@ -1305,10 +1292,9 @@ static void ff_clear(ff_search_ctx_T *search_ctx)
search_ctx->ffsc_level = 0;
}
-/*
- * check if the given path is in the stopdirs
- * returns TRUE if yes else FALSE
- */
+/// check if the given path is in the stopdirs
+///
+/// @return TRUE if yes else FALSE
static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
{
int i = 0;
@@ -1329,13 +1315,13 @@ static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
* '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
* '/home/r' would also match '/home/rks'
*/
- if (fnamencmp(stopdirs_v[i], path, path_len) == 0
+ if (FNAMENCMP(stopdirs_v[i], path, path_len) == 0
&& vim_ispathsep(stopdirs_v[i][path_len])) {
return TRUE;
}
} else {
- if (fnamecmp(stopdirs_v[i], path) == 0) {
- return TRUE;
+ if (FNAMECMP(stopdirs_v[i], path) == 0) {
+ return true;
}
}
}
@@ -1433,7 +1419,11 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
rel_fname = NULL;
}
- if (first == TRUE) {
+ if (first == true) {
+ if (len == 0) {
+ return NULL;
+ }
+
// copy file name into NameBuff, expanding environment variables
save_char = ptr[len];
ptr[len] = NUL;
@@ -1489,7 +1479,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
&& rel_fname != NULL
&& STRLEN(rel_fname) + l < MAXPATHL) {
STRCPY(NameBuff, rel_fname);
- STRCPY(path_tail(NameBuff), ff_file_to_find);
+ STRCPY(path_tail((char *)NameBuff), ff_file_to_find);
l = STRLEN(NameBuff);
} else {
STRCPY(NameBuff, ff_file_to_find);
@@ -1512,7 +1502,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
break;
}
assert(MAXPATHL >= l);
- copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
+ copy_option_part((char **)&buf, (char *)NameBuff + l, MAXPATHL - l, ",");
}
}
}
@@ -1552,7 +1542,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
// copy next path
buf[0] = 0;
- copy_option_part(&dir, buf, MAXPATHL, " ,");
+ copy_option_part((char **)&dir, (char *)buf, MAXPATHL, " ,");
// get the stopdir string
r_ptr = vim_findfile_stopdir(buf);
@@ -1590,11 +1580,13 @@ theend:
return file_name;
}
-void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
+void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre)
{
static bool recursive = false;
- if (recursive || !has_event(EVENT_DIRCHANGED)) {
+ event_T event = pre ? EVENT_DIRCHANGEDPRE : EVENT_DIRCHANGED;
+
+ if (recursive || !has_event(event)) {
// No autocommand was defined or we changed
// the directory from this autocommand.
return;
@@ -1628,8 +1620,12 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
new_dir = new_dir_buf;
#endif
+ if (pre) {
+ tv_dict_add_str(dict, S_LEN("directory"), new_dir);
+ } else {
+ tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
+ }
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"), cause == kCdCauseWindow);
tv_dict_set_keys_readonly(dict);
@@ -1645,8 +1641,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
abort();
}
- apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
- curbuf);
+ apply_autocmds(event, buf, new_dir, false, curbuf);
restore_v_event(dict, &save_v_event);
@@ -1655,13 +1650,14 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
/// Change to a file's directory.
/// Caller must call shorten_fnames()!
-/// @return OK or FAIL
-int vim_chdirfile(char_u *fname, CdCause cause)
+///
+/// @return OK or FAIL
+int vim_chdirfile(char *fname, CdCause cause)
{
char dir[MAXPATHL];
STRLCPY(dir, fname, MAXPATHL);
- *path_tail_with_sep((char_u *)dir) = NUL;
+ *path_tail_with_sep(dir) = NUL;
if (os_dirname(NameBuff, sizeof(NameBuff)) != OK) {
NameBuff[0] = NUL;
@@ -1672,12 +1668,16 @@ int vim_chdirfile(char_u *fname, CdCause cause)
return OK;
}
+ if (cause != kCdCauseOther) {
+ do_autocmd_dirchanged(dir, kCdScopeWindow, cause, true);
+ }
+
if (os_chdir(dir) != 0) {
return FAIL;
}
if (cause != kCdCauseOther) {
- do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
+ do_autocmd_dirchanged(dir, kCdScopeWindow, cause, false);
}
return OK;
@@ -1687,7 +1687,7 @@ int vim_chdirfile(char_u *fname, CdCause cause)
int vim_chdir(char_u *new_dir)
{
char *dir_name = (char *)find_directory_in_path(new_dir, STRLEN(new_dir),
- FNAME_MESS, curbuf->b_ffname);
+ FNAME_MESS, (char_u *)curbuf->b_ffname);
if (dir_name == NULL) {
return -1;
}
@@ -1696,4 +1696,3 @@ int vim_chdir(char_u *new_dir)
xfree(dir_name);
return r;
}
-