Patch 8.2.0988
Problem: Getting directory contents is always case sorted.
Solution: Add sort options and v:collate. (Christian Brabandt, closes #6229)
Files: runtime/doc/eval.txt, runtime/doc/mlang.txt, src/auto/configure,
src/cmdexpand.c, src/config.h.in, src/configure.ac,
src/evalfunc.c, src/evalvars.c, src/ex_cmds2.c, src/fileio.c,
src/filepath.c, src/globals.h, src/proto/fileio.pro,
src/testdir/test_cmdline.vim, src/testdir/test_functions.vim
src/vim.h
*** ../vim-8.2.0987/runtime/doc/eval.txt 2020-06-13 15:47:21.074282253
+0200
--- runtime/doc/eval.txt 2020-06-16 19:59:43.652250328 +0200
***************
*** 1740,1745 ****
--- 1745,1758 ----
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
***************
*** 2674,2681 ****
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}
readfile({fname} [, {type} [, {max}]])
List get list of lines from file {fname}
reduce({object}, {func} [, {initial}])
--- 2691,2700 ----
rand([{expr}]) Number get pseudo-random number
range({expr} [, {max} [, {stride}]])
List items from {expr} to {max}
! 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}])
***************
*** 7885,7895 ****
:echo rand(seed)
:echo rand(seed) % 16 " random number 0 - 15
<
! readdir({directory} [, {expr}]) *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).
When {expr} is omitted all entries are included.
When {expr} is given, it is evaluated to check what to do:
--- 7914,7925 ----
:echo rand(seed)
:echo rand(seed) % 16 " random number 0 - 15
<
! 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), 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:
***************
*** 7907,7924 ****
< To skip hidden and backup files: >
readdir(dirname, {n -> n !~ '^\.\|\~$'})
< If you want to get a directory tree: >
! 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(".")
<
Can also be used as a |method|: >
GetDirName()->readdir()
<
! readdirex({directory} [, {expr}]) *readdirex()*
Extended version of |readdir()|.
Return a list of Dictionaries with file and directory
information in {directory}.
--- 7937,7974 ----
< 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),
\ {_, x -> isdirectory(x) ?
! \ {x : s:tree(a:dir . '/' . x)} : x})}
! endfunction
! echo s:tree(".")
<
Can also be used as a |method|: >
GetDirName()->readdir()
<
! readdirex({directory} [, {expr} [, {dict}]]) *readdirex()*
Extended version of |readdir()|.
Return a list of Dictionaries with file and directory
information in {directory}.
***************
*** 7927,7933 ****
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 Dictionary for file and directory information has the
following items:
--- 7977,7985 ----
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 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:
***************
*** 7968,7973 ****
--- 8020,8030 ----
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()
<
*** ../vim-8.2.0987/runtime/doc/mlang.txt 2019-12-12 12:49:06.000000000
+0100
--- runtime/doc/mlang.txt 2020-06-16 20:00:21.944103819 +0200
***************
*** 37,42 ****
--- 37,43 ----
: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,58 ****
character encoding is printed. Technical: LC_CTYPE.
With the "time" argument the language used for
strftime() is printed. Technical: LC_TIME.
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.
:lan[guage] {name}
:lan[guage] mes[sages] {name}
:lan[guage] cty[pe] {name}
:lan[guage] tim[e] {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
--- 45,63 ----
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|, |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,78 ****
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
$LANG is set.
When compiled with the |+float| feature the LC_NUMERIC
value will always be set to "C", so that floating
--- 77,86 ----
With the "time" argument the language used for time
and date messages is set. This affects strftime().
This sets $LC_TIME.
! 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
*** ../vim-8.2.0987/src/auto/configure 2020-06-05 23:16:25.621415440 +0200
--- src/auto/configure 2020-06-16 19:42:20.672234619 +0200
***************
*** 12618,12624 ****
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 \
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt
do :
--- 12618,12624 ----
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 strcoll strerror strftime stricmp
strncasecmp \
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt
do :
*** ../vim-8.2.0987/src/cmdexpand.c 2020-06-12 19:35:29.338583023 +0200
--- src/cmdexpand.c 2020-06-16 19:40:39.140621851 +0200
***************
*** 1728,1734 ****
{
if ( STRNCMP(arg, "messages", p - arg) == 0
|| STRNCMP(arg, "ctype", p - arg) == 0
! || STRNCMP(arg, "time", p - arg) == 0)
{
xp->xp_context = EXPAND_LOCALES;
xp->xp_pattern = skipwhite(p);
--- 1728,1735 ----
{
if ( STRNCMP(arg, "messages", p - arg) == 0
|| STRNCMP(arg, "ctype", 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);
*** ../vim-8.2.0987/src/config.h.in 2020-06-05 23:16:25.621415440 +0200
--- src/config.h.in 2020-06-16 19:40:39.144621835 +0200
***************
*** 198,203 ****
--- 198,204 ----
#undef HAVE_SIGVEC
#undef HAVE_SMACK
#undef HAVE_STRCASECMP
+ #undef HAVE_STRCOLL
#undef HAVE_STRERROR
#undef HAVE_STRFTIME
#undef HAVE_STRICMP
*** ../vim-8.2.0987/src/configure.ac 2020-06-05 23:16:25.621415440 +0200
--- src/configure.ac 2020-06-16 19:40:39.144621835 +0200
***************
*** 3739,3745 ****
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 \
strnicmp strpbrk strptime strtol tgetent towlower towupper iswupper \
tzset usleep utime utimes mblen ftruncate unsetenv posix_openpt)
AC_FUNC_SELECT_ARGTYPES
--- 3739,3745 ----
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 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
*** ../vim-8.2.0987/src/evalfunc.c 2020-06-13 15:47:21.070282268 +0200
--- src/evalfunc.c 2020-06-16 19:40:39.144621835 +0200
***************
*** 769,776 ****
},
{"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},
{"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},
--- 769,776 ----
},
{"rand", 0, 1, FEARG_1, ret_number, f_rand},
{"range", 1, 3, FEARG_1, ret_list_number, f_range},
! {"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},
*** ../vim-8.2.0987/src/evalvars.c 2020-06-14 23:05:06.368915209 +0200
--- src/evalvars.c 2020-06-16 19:40:39.144621835 +0200
***************
*** 145,150 ****
--- 145,151 ----
{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
*** ../vim-8.2.0987/src/ex_cmds2.c 2020-06-12 19:35:29.338583023 +0200
--- src/ex_cmds2.c 2020-06-16 19:40:39.144621835 +0200
***************
*** 1185,1190 ****
--- 1185,1198 ----
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,1237 ****
--- 1240,1251 ----
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,1280 ****
// Reset $LC_ALL, otherwise it would overrule everything.
vim_setenv((char_u *)"LC_ALL", (char_u *)"");
! if (what != LC_TIME)
{
// Tell gettext() what to translate to. It apparently doesn't
// use the currently effective locale. Also do this when
--- 1288,1294 ----
// Reset $LC_ALL, otherwise it would overrule everything.
vim_setenv((char_u *)"LC_ALL", (char_u *)"");
! 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,1315 ****
}
# ifdef FEAT_EVAL
! // Set v:lang, v:lc_time and v:ctype to the final result.
set_lang_var();
# endif
# ifdef FEAT_TITLE
--- 1323,1329 ----
}
# ifdef FEAT_EVAL
! // Set v:lang, v:lc_time, v:collate and v:ctype to the final result.
set_lang_var();
# endif
# ifdef FEAT_TITLE
***************
*** 1462,1472 ****
return (char_u *)"ctype";
if (idx == 2)
return (char_u *)"time";
init_locales();
if (locales == NULL)
return NULL;
! return locales[idx - 3];
}
/*
--- 1476,1488 ----
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 - 4];
}
/*
*** ../vim-8.2.0987/src/fileio.c 2020-06-12 22:59:07.262097216 +0200
--- src/fileio.c 2020-06-16 19:40:39.144621835 +0200
***************
*** 35,40 ****
--- 35,44 ----
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,4651 ****
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);
}
#endif
--- 4649,4671 ----
name1 = dict_get_string(*(dict_T**)p1, (char_u*)"name", FALSE);
name2 = dict_get_string(*(dict_T**)p2, (char_u*)"name", FALSE);
! 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,4669 ****
char_u *path,
int withattr UNUSED,
void *context,
! int (*checkitem)(void *context, void *item))
{
int failed = FALSE;
char_u *p;
--- 4683,4690 ----
char_u *path,
int withattr UNUSED,
void *context,
! int (*checkitem)(void *context, void *item),
! int sort)
{
int failed = FALSE;
char_u *p;
***************
*** 4687,4692 ****
--- 4708,4715 ----
else \
vim_free(item); \
} while (0)
+
+ readdirex_sort = READDIR_SORT_BYTE;
# else
# define FREE_ITEM(item) vim_free(item)
# endif
***************
*** 4844,4858 ****
# undef FREE_ITEM
! if (!failed && gap->ga_len > 0)
{
# ifdef FEAT_EVAL
if (withattr)
qsort((void*)gap->ga_data, (size_t)gap->ga_len, sizeof(dict_T*),
compare_readdirex_item);
else
! # endif
sort_strings((char_u **)gap->ga_data, gap->ga_len);
}
return failed ? FAIL : OK;
--- 4867,4885 ----
# undef FREE_ITEM
! 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
! 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,4889 ****
exp = vim_strsave(name);
if (exp == NULL)
return -1;
! if (readdir_core(&ga, exp, FALSE, NULL, NULL) == OK)
{
for (i = 0; i < ga.ga_len; ++i)
{
--- 4910,4916 ----
exp = vim_strsave(name);
if (exp == NULL)
return -1;
! if (readdir_core(&ga, exp, FALSE, NULL, NULL, READDIR_SORT_NONE) == OK)
{
for (i = 0; i < ga.ga_len; ++i)
{
*** ../vim-8.2.0987/src/filepath.c 2020-06-12 22:59:07.262097216 +0200
--- src/filepath.c 2020-06-16 19:40:39.144621835 +0200
***************
*** 1405,1410 ****
--- 1405,1440 ----
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,1430 ****
char_u *p;
garray_T ga;
int i;
if (rettv_list_alloc(rettv) == FAIL)
return;
path = tv_get_string(&argvars[0]);
expr = &argvars[1];
ret = readdir_core(&ga, path, FALSE, (void *)expr,
! (expr->v_type == VAR_UNKNOWN) ? NULL : readdir_checkitem);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)
--- 1447,1465 ----
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, sort);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)
***************
*** 1480,1493 ****
char_u *path;
garray_T ga;
int i;
if (rettv_list_alloc(rettv) == FAIL)
return;
path = tv_get_string(&argvars[0]);
expr = &argvars[1];
ret = readdir_core(&ga, path, TRUE, (void *)expr,
! (expr->v_type == VAR_UNKNOWN) ? NULL : readdirex_checkitem);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)
--- 1515,1533 ----
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, sort);
if (ret == OK)
{
for (i = 0; i < ga.ga_len; i++)
*** ../vim-8.2.0987/src/globals.h 2020-06-15 19:51:52.633404482 +0200
--- src/globals.h 2020-06-16 19:40:39.144621835 +0200
***************
*** 1699,1704 ****
--- 1699,1706 ----
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"));
*** ../vim-8.2.0987/src/proto/fileio.pro 2020-06-01 16:09:30.266292734
+0200
--- src/proto/fileio.pro 2020-06-16 19:40:39.148621821 +0200
***************
*** 31,37 ****
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 delete_recursive(char_u *name);
void vim_deltempdir(void);
char_u *vim_tempname(int extra_char, int keep);
--- 31,37 ----
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 sort);
int delete_recursive(char_u *name);
void vim_deltempdir(void);
char_u *vim_tempname(int extra_char, int keep);
*** ../vim-8.2.0987/src/testdir/test_cmdline.vim 2020-06-12
19:35:29.338583023 +0200
--- src/testdir/test_cmdline.vim 2020-06-16 19:40:39.148621821 +0200
***************
*** 604,613 ****
endfunc
func Test_cmdline_complete_languages()
let lang = substitute(execute('language messages'), '.*"\(.*\)"$', '\1', '')
call feedkeys(":language \<c-a>\<c-b>\"\<cr>", 'tx')
! call assert_match('^"language .*\<ctype\>.*\<messages\>.*\<time\>', @:)
call assert_match('^"language .*\<' . lang . '\>', @:)
--- 604,623 ----
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
.*\<collate\>.*\<ctype\>.*\<messages\>.*\<time\>', @:)
call assert_match('^"language .*\<' . lang . '\>', @:)
***************
*** 619,624 ****
--- 629,637 ----
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()
*** ../vim-8.2.0987/src/testdir/test_functions.vim 2020-06-15
23:18:08.924482716 +0200
--- src/testdir/test_functions.vim 2020-06-16 19:40:39.148621821 +0200
***************
*** 1937,1942 ****
--- 1937,2021 ----
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')
*** ../vim-8.2.0987/src/vim.h 2020-06-10 20:56:55.021354582 +0200
--- src/vim.h 2020-06-16 19:40:39.148621821 +0200
***************
*** 1599,1604 ****
--- 1599,1609 ----
# 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,1902 ****
#define VALID_PATH 1
#define VALID_HEAD 2
! // Defines for Vim variables. These must match vimvars[] in eval.c!
#define VV_COUNT 0
#define VV_COUNT1 1
#define VV_PREVCOUNT 2
--- 1901,1907 ----
#define VALID_PATH 1
#define VALID_HEAD 2
! // Defines for Vim variables. These must match vimvars[] in evalvars.c!
#define VV_COUNT 0
#define VV_COUNT1 1
#define VV_PREVCOUNT 2
***************
*** 1992,1998 ****
#define VV_VERSIONLONG 92
#define VV_ECHOSPACE 93
#define VV_ARGV 94
! #define VV_LEN 95 // number of v: vars
// used for v_number in VAR_BOOL and VAR_SPECIAL
#define VVAL_FALSE 0L // VAR_BOOL
--- 1997,2004 ----
#define VV_VERSIONLONG 92
#define VV_ECHOSPACE 93
#define VV_ARGV 94
! #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,2672 ****
--- 2675,2684 ----
#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
*** ../vim-8.2.0987/src/version.c 2020-06-16 11:34:38.318223430 +0200
--- src/version.c 2020-06-16 19:42:15.904252802 +0200
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 988,
/**/
--
BLACK KNIGHT: I move for no man.
ARTHUR: So be it!
[hah] [parry thrust]
[ARTHUR chops the BLACK KNIGHT's left arm off]
ARTHUR: Now stand aside, worthy adversary.
BLACK KNIGHT: 'Tis but a scratch.
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202006161804.05GI4HHF1411307%40masaka.moolenaar.net.