mirror of
https://github.com/neovim/neovim.git
synced 2025-09-11 13:58:18 +00:00
vim-patch:8.1.1120: cannot easily get directory entry matches #12222
Problem: Cannot easily get directory entry matches.
Solution: Add the readdir() function. (Yasuhiro Matsumoto, closes vim/vim#2439)
543c9b1921
closes #12212
This commit is contained in:

committed by
GitHub

parent
48c2198297
commit
d2766b06c8
@@ -6316,6 +6316,99 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate "expr" for readdir().
|
||||
static varnumber_T readdir_checkitem(typval_T *expr, const char *name)
|
||||
{
|
||||
typval_T save_val;
|
||||
typval_T rettv;
|
||||
typval_T argv[2];
|
||||
varnumber_T retval = 0;
|
||||
bool error = false;
|
||||
|
||||
prepare_vimvar(VV_VAL, &save_val);
|
||||
set_vim_var_string(VV_VAL, name, -1);
|
||||
argv[0].v_type = VAR_STRING;
|
||||
argv[0].vval.v_string = (char_u *)name;
|
||||
|
||||
if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) {
|
||||
goto theend;
|
||||
}
|
||||
|
||||
retval = tv_get_number_chk(&rettv, &error);
|
||||
if (error) {
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
tv_clear(&rettv);
|
||||
|
||||
theend:
|
||||
set_vim_var_string(VV_VAL, NULL, 0);
|
||||
restore_vimvar(VV_VAL, &save_val);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// "readdir()" function
|
||||
static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
typval_T *expr;
|
||||
const char *path;
|
||||
garray_T ga;
|
||||
Directory dir;
|
||||
|
||||
tv_list_alloc_ret(rettv, kListLenUnknown);
|
||||
path = tv_get_string(&argvars[0]);
|
||||
expr = &argvars[1];
|
||||
ga_init(&ga, (int)sizeof(char *), 20);
|
||||
|
||||
if (!os_scandir(&dir, path)) {
|
||||
smsg(_(e_notopen), path);
|
||||
} else {
|
||||
for (;;) {
|
||||
bool ignore;
|
||||
|
||||
path = os_scandir_next(&dir);
|
||||
if (path == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
ignore = (path[0] == '.'
|
||||
&& (path[1] == NUL || (path[1] == '.' && path[2] == NUL)));
|
||||
if (!ignore && expr->v_type != VAR_UNKNOWN) {
|
||||
varnumber_T r = readdir_checkitem(expr, path);
|
||||
|
||||
if (r < 0) {
|
||||
break;
|
||||
}
|
||||
if (r == 0) {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore) {
|
||||
ga_grow(&ga, 1);
|
||||
((char **)ga.ga_data)[ga.ga_len++] = xstrdup(path);
|
||||
}
|
||||
}
|
||||
|
||||
os_closedir(&dir);
|
||||
}
|
||||
|
||||
rettv->vval.v_list = tv_list_alloc(kListLenShouldKnow);
|
||||
if (rettv->vval.v_list != NULL) {
|
||||
tv_list_ref(rettv->vval.v_list);
|
||||
sort_strings((char_u **)ga.ga_data, ga.ga_len);
|
||||
for (int i = 0; i < ga.ga_len; i++) {
|
||||
path = ((const char **)ga.ga_data)[i];
|
||||
tv_list_append_string(rettv->vval.v_list, path, -1);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ga.ga_len; i++) {
|
||||
xfree(((uint8_t **)ga.ga_data)[i]);
|
||||
}
|
||||
|
||||
ga_clear(&ga);
|
||||
}
|
||||
|
||||
/*
|
||||
* "readfile()" function
|
||||
*/
|
||||
|
Reference in New Issue
Block a user