0
0
mirror of https://github.com/vim/vim.git synced 2025-08-30 20:43:35 -04:00

patch 8.2.0988: getting directory contents is always case sorted

Problem:    Getting directory contents is always case sorted.
Solution:   Add sort options and v:collate. (Christian Brabandt, closes #6229)
This commit is contained in:
Bram Moolenaar 2020-06-16 20:03:43 +02:00
parent 9af78769ee
commit 84cf6bd81b
17 changed files with 272 additions and 32 deletions

View File

@ -1745,6 +1745,14 @@ v:cmdbang Set like v:cmdarg for a file read/write command. When a "!"
was used the value is 1, otherwise it is 0. Note that this
can only be used in autocommands. For user commands |<bang>|
can be used.
*v:collate* *collate-variable*
v:collate The current locale setting for collation order of the runtime
environment. This allows Vim scripts to be aware of the
current locale encoding. Technical: it's the value of
LC_COLLATE. When not using a locale the value is "C".
This variable can not be set directly, use the |:language|
command.
See |multi-lang|.
*v:completed_item* *completed_item-variable*
v:completed_item
@ -2683,8 +2691,10 @@ pyxeval({expr}) any evaluate |python_x| expression
rand([{expr}]) Number get pseudo-random number
range({expr} [, {max} [, {stride}]])
List items from {expr} to {max}
readdir({dir} [, {expr}]) List file names in {dir} selected by {expr}
readdirex({dir} [, {expr}]) List file info in {dir} selected by {expr}
readdir({dir} [, {expr} [, {dict}]])
List file names in {dir} selected by {expr}
readdirex({dir} [, {expr} [, {dict}]])
List file info in {dir} selected by {expr}
readfile({fname} [, {type} [, {max}]])
List get list of lines from file {fname}
reduce({object}, {func} [, {initial}])
@ -7904,11 +7914,12 @@ rand([{expr}]) *rand()* *random*
:echo rand(seed)
:echo rand(seed) % 16 " random number 0 - 15
<
readdir({directory} [, {expr}]) *readdir()*
readdir({directory} [, {expr} [, {dict}]]) *readdir()*
Return a list with file and directory names in {directory}.
You can also use |glob()| if you don't need to do complicated
things, such as limiting the number of matches.
The list will be sorted (case sensitive).
The list will be sorted (case sensitive), see the {dict}
argument below for changing the sort order.
When {expr} is omitted all entries are included.
When {expr} is given, it is evaluated to check what to do:
@ -7926,18 +7937,38 @@ readdir({directory} [, {expr}]) *readdir()*
< To skip hidden and backup files: >
readdir(dirname, {n -> n !~ '^\.\|\~$'})
< The optional {dict} argument allows for further custom
values. Currently this is used to specify if and how sorting
should be performed. The dict can have the following members:
sort How to sort the result returned from the system.
Valid values are:
"none" do not sort (fastest method)
"case" sort case sensitive (byte value of
each character, technically, using
strcmp()) (default)
"icase" sort case insensitive (technically
using strcasecmp())
"collate" sort using the collation order
of the "POSIX" or "C" |locale|
(technically using strcoll())
Other values are silently ignored.
For example, to get a list of all files in the current
directory without sorting the individual entries: >
readdir('.', '1', #{sort: 'none'})
< If you want to get a directory tree: >
function! s:tree(dir)
return {a:dir : map(readdir(a:dir),
function! s:tree(dir)
return {a:dir : map(readdir(a:dir),
\ {_, x -> isdirectory(x) ?
\ {x : s:tree(a:dir . '/' . x)} : x})}
endfunction
echo s:tree(".")
\ {x : s:tree(a:dir . '/' . x)} : x})}
endfunction
echo s:tree(".")
<
Can also be used as a |method|: >
GetDirName()->readdir()
<
readdirex({directory} [, {expr}]) *readdirex()*
readdirex({directory} [, {expr} [, {dict}]]) *readdirex()*
Extended version of |readdir()|.
Return a list of Dictionaries with file and directory
information in {directory}.
@ -7946,7 +7977,9 @@ readdirex({directory} [, {expr}]) *readdirex()*
This is much faster than calling |readdir()| then calling
|getfperm()|, |getfsize()|, |getftime()| and |getftype()| for
each file and directory especially on MS-Windows.
The list will be sorted by name (case sensitive).
The list will by default be sorted by name (case sensitive),
the sorting can be changed by using the optional {dict}
argument, see |readdir()|.
The Dictionary for file and directory information has the
following items:
@ -7986,6 +8019,11 @@ readdirex({directory} [, {expr}]) *readdirex()*
When {expr} is a function the entry is passed as the argument.
For example, to get a list of files ending in ".txt": >
readdirex(dirname, {e -> e.name =~ '.txt$'})
<
For example, to get a list of all files in the current
directory without sorting the individual entries: >
readdirex(dirname, '1', #{sort: 'none'})
<
Can also be used as a |method|: >
GetDirName()->readdirex()

View File

@ -37,6 +37,7 @@ use of "-" and "_".
:lan[guage] mes[sages]
:lan[guage] cty[pe]
:lan[guage] tim[e]
:lan[guage] col[late]
Print the current language (aka locale).
With the "messages" argument the language used for
messages is printed. Technical: LC_MESSAGES.
@ -44,15 +45,19 @@ use of "-" and "_".
character encoding is printed. Technical: LC_CTYPE.
With the "time" argument the language used for
strftime() is printed. Technical: LC_TIME.
With the "collate" argument the language used for
collation order is printed. Technical: LC_COLLATE.
Without argument all parts of the locale are printed
(this is system dependent).
The current language can also be obtained with the
|v:lang|, |v:ctype| and |v:lc_time| variables.
|v:lang|, |v:ctype|, |v:collate| and |v:lc_time|
variables.
:lan[guage] {name}
:lan[guage] mes[sages] {name}
:lan[guage] cty[pe] {name}
:lan[guage] tim[e] {name}
:lan[guage] col[late] {name}
Set the current language (aka locale) to {name}.
The locale {name} must be a valid locale on your
system. Some systems accept aliases like "en" or
@ -72,7 +77,10 @@ use of "-" and "_".
With the "time" argument the language used for time
and date messages is set. This affects strftime().
This sets $LC_TIME.
Without an argument both are set, and additionally
With the "collate" argument the language used for the
collation order is set. This affects sorting of
characters. This sets $LC_COLLATE.
Without an argument all are set, and additionally
$LANG is set.
When compiled with the |+float| feature the LC_NUMERIC
value will always be set to "C", so that floating

2
src/auto/configure vendored
View File

@ -12618,7 +12618,7 @@ for ac_func in fchdir fchown fchmod fsync getcwd getpseudotty \
getpwent getpwnam getpwuid getrlimit gettimeofday localtime_r lstat \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
sigprocmask sigvec strcasecmp strcoll strerror strftime stricmp strncasecmp \
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt
do :

View File

@ -1728,7 +1728,8 @@ set_one_cmd_context(
{
if ( STRNCMP(arg, "messages", p - arg) == 0
|| STRNCMP(arg, "ctype", p - arg) == 0
|| STRNCMP(arg, "time", p - arg) == 0)
|| STRNCMP(arg, "time", p - arg) == 0
|| STRNCMP(arg, "collate", p - arg) == 0)
{
xp->xp_context = EXPAND_LOCALES;
xp->xp_pattern = skipwhite(p);

View File

@ -198,6 +198,7 @@
#undef HAVE_SIGVEC
#undef HAVE_SMACK
#undef HAVE_STRCASECMP
#undef HAVE_STRCOLL
#undef HAVE_STRERROR
#undef HAVE_STRFTIME
#undef HAVE_STRICMP

View File

@ -3739,7 +3739,7 @@ AC_CHECK_FUNCS(fchdir fchown fchmod fsync getcwd getpseudotty \
getpwent getpwnam getpwuid getrlimit gettimeofday localtime_r lstat \
memset mkdtemp nanosleep opendir putenv qsort readlink select setenv \
getpgid setpgid setsid sigaltstack sigstack sigset sigsetjmp sigaction \
sigprocmask sigvec strcasecmp strerror strftime stricmp strncasecmp \
sigprocmask sigvec strcasecmp strcoll strerror strftime stricmp strncasecmp \
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt)
AC_FUNC_SELECT_ARGTYPES

View File

@ -769,8 +769,8 @@ static funcentry_T global_functions[] =
},
{"rand", 0, 1, FEARG_1, ret_number, f_rand},
{"range", 1, 3, FEARG_1, ret_list_number, f_range},
{"readdir", 1, 2, FEARG_1, ret_list_string, f_readdir},
{"readdirex", 1, 2, FEARG_1, ret_list_dict_any, f_readdirex},
{"readdir", 1, 3, FEARG_1, ret_list_string, f_readdir},
{"readdirex", 1, 3, FEARG_1, ret_list_dict_any, f_readdirex},
{"readfile", 1, 3, FEARG_1, ret_any, f_readfile},
{"reduce", 2, 3, FEARG_1, ret_any, f_reduce},
{"reg_executing", 0, 0, 0, ret_string, f_reg_executing},

View File

@ -145,6 +145,7 @@ static struct vimvar
{VV_NAME("versionlong", VAR_NUMBER), VV_RO},
{VV_NAME("echospace", VAR_NUMBER), VV_RO},
{VV_NAME("argv", VAR_LIST), VV_RO},
{VV_NAME("collate", VAR_STRING), VV_RO},
};
// shorthand

View File

@ -1185,6 +1185,14 @@ set_lang_var(void)
loc = get_locale_val(LC_TIME);
# endif
set_vim_var_string(VV_LC_TIME, loc, -1);
# ifdef HAVE_GET_LOCALE_VAL
loc = get_locale_val(LC_COLLATE);
# else
// setlocale() not supported: use the default value
loc = (char_u *)"C";
# endif
set_vim_var_string(VV_COLLATE, loc, -1);
}
#endif
@ -1232,6 +1240,12 @@ ex_language(exarg_T *eap)
name = skipwhite(p);
whatstr = "time ";
}
else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0)
{
what = LC_COLLATE;
name = skipwhite(p);
whatstr = "collate ";
}
}
if (*name == NUL)
@ -1274,7 +1288,7 @@ ex_language(exarg_T *eap)
// Reset $LC_ALL, otherwise it would overrule everything.
vim_setenv((char_u *)"LC_ALL", (char_u *)"");
if (what != LC_TIME)
if (what != LC_TIME && what != LC_COLLATE)
{
// Tell gettext() what to translate to. It apparently doesn't
// use the currently effective locale. Also do this when
@ -1309,7 +1323,7 @@ ex_language(exarg_T *eap)
}
# ifdef FEAT_EVAL
// Set v:lang, v:lc_time and v:ctype to the final result.
// Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
set_lang_var();
# endif
# ifdef FEAT_TITLE
@ -1462,11 +1476,13 @@ get_lang_arg(expand_T *xp UNUSED, int idx)
return (char_u *)"ctype";
if (idx == 2)
return (char_u *)"time";
if (idx == 3)
return (char_u *)"collate";
init_locales();
if (locales == NULL)
return NULL;
return locales[idx - 3];
return locales[idx - 4];
}
/*

View File

@ -35,6 +35,10 @@ static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp);
static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags);
static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
#ifdef FEAT_EVAL
static int readdirex_sort;
#endif
void
filemess(
buf_T *buf,
@ -4645,7 +4649,23 @@ compare_readdirex_item(const void *p1, const void *p2)
name1 = dict_get_string(*(dict_T**)p1, (char_u*)"name", FALSE);
name2 = dict_get_string(*(dict_T**)p2, (char_u*)"name", FALSE);
return STRCMP(name1, name2);
if (readdirex_sort == READDIR_SORT_BYTE)
return STRCMP(name1, name2);
else if (readdirex_sort == READDIR_SORT_IC)
return STRICMP(name1, name2);
else
return STRCOLL(name1, name2);
}
static int
compare_readdir_item(const void *s1, const void *s2)
{
if (readdirex_sort == READDIR_SORT_BYTE)
return STRCMP(*(char **)s1, *(char **)s2);
else if (readdirex_sort == READDIR_SORT_IC)
return STRICMP(*(char **)s1, *(char **)s2);
else
return STRCOLL(*(char **)s1, *(char **)s2);
}
#endif
@ -4663,7 +4683,8 @@ readdir_core(
char_u *path,
int withattr UNUSED,
void *context,
int (*checkitem)(void *context, void *item))
int (*checkitem)(void *context, void *item),
int sort)
{
int failed = FALSE;
char_u *p;
@ -4687,6 +4708,8 @@ readdir_core(
else \
vim_free(item); \
} while (0)
readdirex_sort = READDIR_SORT_BYTE;
# else
# define FREE_ITEM(item) vim_free(item)
# endif
@ -4844,15 +4867,19 @@ readdir_core(
# undef FREE_ITEM
if (!failed && gap->ga_len > 0)
if (!failed && gap->ga_len > 0 && sort > READDIR_SORT_NONE)
{
# ifdef FEAT_EVAL
readdirex_sort = sort;
if (withattr)
qsort((void*)gap->ga_data, (size_t)gap->ga_len, sizeof(dict_T*),
compare_readdirex_item);
else
# endif
qsort((void*)gap->ga_data, (size_t)gap->ga_len, sizeof(char_u *),
compare_readdir_item);
# else
sort_strings((char_u **)gap->ga_data, gap->ga_len);
# endif
}
return failed ? FAIL : OK;
@ -4883,7 +4910,7 @@ delete_recursive(char_u *name)
exp = vim_strsave(name);
if (exp == NULL)
return -1;
if (readdir_core(&ga, exp, FALSE, NULL, NULL) == OK)
if (readdir_core(&ga, exp, FALSE, NULL, NULL, READDIR_SORT_NONE) == OK)
{
for (i = 0; i < ga.ga_len; ++i)
{

View File

@ -1405,6 +1405,36 @@ theend:
return retval;
}
static int
readdirex_dict_arg(typval_T *tv, int *cmp)
{
char_u *compare;
if (tv->v_type != VAR_DICT)
{
emsg(_(e_dictreq));
return FAIL;
}
if (dict_find(tv->vval.v_dict, (char_u *)"sort", -1) != NULL)
compare = dict_get_string(tv->vval.v_dict, (char_u *)"sort", FALSE);
else
{
semsg(_(e_no_dict_key), "sort");
return FAIL;
}
if (STRCMP(compare, (char_u *) "none") == 0)
*cmp = READDIR_SORT_NONE;
else if (STRCMP(compare, (char_u *) "case") == 0)
*cmp = READDIR_SORT_BYTE;
else if (STRCMP(compare, (char_u *) "icase") == 0)
*cmp = READDIR_SORT_IC;
else if (STRCMP(compare, (char_u *) "collate") == 0)
*cmp = READDIR_SORT_COLLATE;
return OK;
}
/*
* "readdir()" function
*/
@ -1417,14 +1447,19 @@ f_readdir(typval_T *argvars, typval_T *rettv)
char_u *p;
garray_T ga;
int i;
int sort = READDIR_SORT_BYTE;
if (rettv_list_alloc(rettv) == FAIL)
return;
path = tv_get_string(&argvars[0]);
expr = &argvars[1];
if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN &&
readdirex_dict_arg(&argvars[2], &sort) == FAIL)
return;
ret = readdir_core(&ga, path, FALSE, (void *)expr,
(expr->v_type == VAR_UNKNOWN) ? NULL : readdir_checkitem);
(expr->v_type == VAR_UNKNOWN) ? NULL : readdir_checkitem, sort);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)
@ -1480,14 +1515,19 @@ f_readdirex(typval_T *argvars, typval_T *rettv)
char_u *path;
garray_T ga;
int i;
int sort = READDIR_SORT_BYTE;
if (rettv_list_alloc(rettv) == FAIL)
return;
path = tv_get_string(&argvars[0]);
expr = &argvars[1];
if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN &&
readdirex_dict_arg(&argvars[2], &sort) == FAIL)
return;
ret = readdir_core(&ga, path, TRUE, (void *)expr,
(expr->v_type == VAR_UNKNOWN) ? NULL : readdirex_checkitem);
(expr->v_type == VAR_UNKNOWN) ? NULL : readdirex_checkitem, sort);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)

View File

@ -1699,6 +1699,8 @@ EXTERN char e_const_option[] INIT(= N_("E996: Cannot lock an option"));
EXTERN char e_unknown_option[] INIT(= N_("E113: Unknown option: %s"));
EXTERN char e_letunexp[] INIT(= N_("E18: Unexpected characters in :let"));
EXTERN char e_reduceempty[] INIT(= N_("E998: Reduce of an empty %s with no initial value"));
// TODO: Change Error Number
EXTERN char e_no_dict_key[] INIT(= N_("E999: Dictionary with key \"%s\" required"));
#endif
#ifdef FEAT_QUICKFIX
EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile"));

View File

@ -31,7 +31,7 @@ int buf_check_timestamp(buf_T *buf, int focus);
void buf_reload(buf_T *buf, int orig_mode);
void buf_store_time(buf_T *buf, stat_T *st, char_u *fname);
void write_lnum_adjust(linenr_T offset);
int readdir_core(garray_T *gap, char_u *path, int withattr, void *context, int (*checkitem)(void *context, void *item));
int readdir_core(garray_T *gap, char_u *path, int withattr, void *context, int (*checkitem)(void *context, void *item), int sort);
int delete_recursive(char_u *name);
void vim_deltempdir(void);
char_u *vim_tempname(int extra_char, int keep);

View File

@ -604,10 +604,20 @@ func Test_cmdline_complete_bang()
endfunc
func Test_cmdline_complete_languages()
let lang = substitute(execute('language time'), '.*"\(.*\)"$', '\1', '')
call assert_equal(lang, v:lc_time)
let lang = substitute(execute('language ctype'), '.*"\(.*\)"$', '\1', '')
call assert_equal(lang, v:ctype)
let lang = substitute(execute('language collate'), '.*"\(.*\)"$', '\1', '')
call assert_equal(lang, v:collate)
let lang = substitute(execute('language messages'), '.*"\(.*\)"$', '\1', '')
call assert_equal(lang, v:lang)
call feedkeys(":language \<c-a>\<c-b>\"\<cr>", 'tx')
call assert_match('^"language .*\<ctype\>.*\<messages\>.*\<time\>', @:)
call assert_match('^"language .*\<collate\>.*\<ctype\>.*\<messages\>.*\<time\>', @:)
call assert_match('^"language .*\<' . lang . '\>', @:)
@ -619,6 +629,9 @@ func Test_cmdline_complete_languages()
call feedkeys(":language time \<c-a>\<c-b>\"\<cr>", 'tx')
call assert_match('^"language .*\<' . lang . '\>', @:)
call feedkeys(":language collate \<c-a>\<c-b>\"\<cr>", 'tx')
call assert_match('^"language .*\<' . lang . '\>', @:)
endfunc
func Test_cmdline_complete_env_variable()

View File

@ -1937,6 +1937,85 @@ func Test_readdirex()
eval 'Xdir'->delete('rf')
endfunc
func Test_readdirex_sort()
CheckUnix
" Skip tests on Mac OS X and Cygwin (does not allow several files with different casing)
if has("osxdarwin") || has("osx") || has("macunix") || has("win32unix")
throw 'Skipped: Test_readdirex_sort on systems that do not allow this using the default filesystem'
endif
let _collate = v:collate
call mkdir('Xdir2')
call writefile(['1'], 'Xdir2/README.txt')
call writefile(['2'], 'Xdir2/Readme.txt')
call writefile(['3'], 'Xdir2/readme.txt')
" 1) default
let files = readdirex('Xdir2')->map({-> v:val.name})
let default = copy(files)
call assert_equal(['README.txt', 'Readme.txt', 'readme.txt'], files, 'sort using default')
" 2) no sorting
let files = readdirex('Xdir2', 1, #{sort: 'none'})->map({-> v:val.name})
let unsorted = copy(files)
call assert_equal(['README.txt', 'Readme.txt', 'readme.txt'], sort(files), 'unsorted')
" 3) sort by case (same as default)
let files = readdirex('Xdir2', 1, #{sort: 'case'})->map({-> v:val.name})
call assert_equal(default, files, 'sort by case')
" 4) sort by ignoring case
let files = readdirex('Xdir2', 1, #{sort: 'icase'})->map({-> v:val.name})
call assert_equal(unsorted->sort('i'), files, 'sort by icase')
" 5) Default Collation
let collate = v:collate
lang collate C
let files = readdirex('Xdir2', 1, #{sort: 'collate'})->map({-> v:val.name})
call assert_equal(['README.txt', 'Readme.txt', 'readme.txt'], files, 'sort by C collation')
" 6) Collation de_DE
" Switch locale, this may not work on the CI system, if the locale isn't
" available
try
lang collate de_DE
let files = readdirex('Xdir2', 1, #{sort: 'collate'})->map({-> v:val.name})
call assert_equal(['readme.txt', 'Readme.txt', 'README.txt'], files, 'sort by de_DE collation')
catch
throw 'Skipped: de_DE collation is not available'
finally
exe 'lang collate' collate
eval 'Xdir2'->delete('rf')
endtry
endfunc
func Test_readdir_sort()
" some more cases for testing sorting for readdirex
let dir = 'Xdir3'
call mkdir(dir)
call writefile(['1'], dir .. '/README.txt')
call writefile(['2'], dir .. '/Readm.txt')
call writefile(['3'], dir .. '/read.txt')
call writefile(['4'], dir .. '/Z.txt')
call writefile(['5'], dir .. '/a.txt')
call writefile(['6'], dir .. '/b.txt')
" 1) default
let files = readdir(dir)
let default = copy(files)
call assert_equal(default->sort(), files, 'sort using default')
" 2) sort by case (same as default)
let files = readdir(dir, '1', #{sort: 'case'})
call assert_equal(default, files, 'sort using default')
" 3) sort by ignoring case
let files = readdir(dir, '1', #{sort: 'icase'})
call assert_equal(default->sort('i'), files, 'sort by ignoring case')
eval dir->delete('rf')
endfunc
func Test_delete_rf()
call mkdir('Xdir')
call writefile([], 'Xdir/foo.txt')

View File

@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
988,
/**/
987,
/**/

View File

@ -1599,6 +1599,11 @@ void *vim_memset(void *, int, size_t);
# define STRICMP(d, s) vim_stricmp((char *)(d), (char *)(s))
# endif
#endif
#ifdef HAVE_STRCOLL
# define STRCOLL(d, s) strcoll((char *)(d), (char *)(s))
#else
# define STRCOLL(d, s) strcmp((char *)(d), (char *)(s))
#endif
// Like strcpy() but allows overlapped source and destination.
#define STRMOVE(d, s) mch_memmove((d), (s), STRLEN(s) + 1)
@ -1896,7 +1901,7 @@ typedef int sock_T;
#define VALID_PATH 1
#define VALID_HEAD 2
// Defines for Vim variables. These must match vimvars[] in eval.c!
// Defines for Vim variables. These must match vimvars[] in evalvars.c!
#define VV_COUNT 0
#define VV_COUNT1 1
#define VV_PREVCOUNT 2
@ -1992,7 +1997,8 @@ typedef int sock_T;
#define VV_VERSIONLONG 92
#define VV_ECHOSPACE 93
#define VV_ARGV 94
#define VV_LEN 95 // number of v: vars
#define VV_COLLATE 95
#define VV_LEN 96 // number of v: vars
// used for v_number in VAR_BOOL and VAR_SPECIAL
#define VVAL_FALSE 0L // VAR_BOOL
@ -2669,4 +2675,10 @@ long elapsed(DWORD start_tick);
#define FSK_IN_STRING 0x04 // TRUE in string, double quote is escaped
#define FSK_SIMPLIFY 0x08 // simplify <C-H> and <A-x>
// Flags for the readdirex function, how to sort the result
#define READDIR_SORT_NONE 0 // do not sort
#define READDIR_SORT_BYTE 1 // sort by byte order (strcmp), default
#define READDIR_SORT_IC 2 // sort ignoring case (strcasecmp)
#define READDIR_SORT_COLLATE 3 // sort according to collation (strcoll)
#endif // VIM__H