0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 9.0.1515: reverse() does not work for a String

Problem:    reverse() does not work for a String.
Solution:   Implement reverse() for a String. (Yegappan Lakshmanan,
            closes #12179)
This commit is contained in:
Yegappan Lakshmanan
2023-05-06 14:08:21 +01:00
committed by Bram Moolenaar
parent 45fcb7928a
commit 03ff1c2dde
8 changed files with 76 additions and 8 deletions

View File

@@ -484,7 +484,8 @@ rename({from}, {to}) Number rename (move) file from {from} to {to}
repeat({expr}, {count}) List/Blob/String repeat({expr}, {count}) List/Blob/String
repeat {expr} {count} times repeat {expr} {count} times
resolve({filename}) String get filename a shortcut points to resolve({filename}) String get filename a shortcut points to
reverse({list}) List reverse {list} in-place reverse({obj}) List/Blob/String
reverse {obj}
round({expr}) Float round off {expr} round({expr}) Float round off {expr}
rubyeval({expr}) any evaluate |Ruby| expression rubyeval({expr}) any evaluate |Ruby| expression
screenattr({row}, {col}) Number attribute at screen position screenattr({row}, {col}) Number attribute at screen position
@@ -7404,11 +7405,13 @@ resolve({filename}) *resolve()* *E655*
GetName()->resolve() GetName()->resolve()
reverse({object}) *reverse()* reverse({object}) *reverse()*
Reverse the order of items in {object} in-place. Reverse the order of items in {object}. {object} can be a
{object} can be a |List| or a |Blob|. |List|, a |Blob| or a |String|. For a List and a Blob the
Returns {object}. items are reversed in-place and {object} is returned.
Returns zero if {object} is not a List or a Blob. For a String a new String is returned.
If you want an object to remain unmodified make a copy first: > Returns zero if {object} is not a List, Blob or a String.
If you want a List or Blob to remain unmodified make a copy
first: >
:let revlist = reverse(copy(mylist)) :let revlist = reverse(copy(mylist))
< Can also be used as a |method|: > < Can also be used as a |method|: >
mylist->reverse() mylist->reverse()

View File

@@ -759,6 +759,7 @@ String manipulation: *string-functions*
strdisplaywidth() size of string when displayed, deals with tabs strdisplaywidth() size of string when displayed, deals with tabs
setcellwidths() set character cell width overrides setcellwidths() set character cell width overrides
getcellwidths() get character cell width overrides getcellwidths() get character cell width overrides
reverse() reverse the order of characters in a string
substitute() substitute a pattern match with a string substitute() substitute a pattern match with a string
submatch() get a specific match in ":s" and substitute() submatch() get a specific match in ":s" and substitute()
strpart() get part of a string using byte index strpart() get part of a string using byte index
@@ -797,7 +798,7 @@ List manipulation: *list-functions*
reduce() reduce a List to a value reduce() reduce a List to a value
slice() take a slice of a List slice() take a slice of a List
sort() sort a List sort() sort a List
reverse() reverse the order of a List or Blob reverse() reverse the order of items in a List
uniq() remove copies of repeated adjacent items uniq() remove copies of repeated adjacent items
split() split a String into a List split() split a String into a List
join() join List items into a String join() join List items into a String
@@ -864,6 +865,7 @@ Floating point computation: *float-functions*
Blob manipulation: *blob-functions* Blob manipulation: *blob-functions*
blob2list() get a list of numbers from a blob blob2list() get a list of numbers from a blob
list2blob() get a blob from a list of numbers list2blob() get a blob from a list of numbers
reverse() reverse the order of numbers in a blob
Other computation: *bitwise-function* Other computation: *bitwise-function*
and() bitwise AND and() bitwise AND

View File

@@ -2999,6 +2999,8 @@ f_reverse(typval_T *argvars, typval_T *rettv)
if (argvars[0].v_type == VAR_BLOB) if (argvars[0].v_type == VAR_BLOB)
blob_reverse(argvars[0].vval.v_blob, rettv); blob_reverse(argvars[0].vval.v_blob, rettv);
else if (argvars[0].v_type == VAR_STRING)
string_reverse(argvars[0].vval.v_string, rettv);
else if (argvars[0].v_type != VAR_LIST) else if (argvars[0].v_type != VAR_LIST)
semsg(_(e_argument_of_str_must_be_list_or_blob), "reverse()"); semsg(_(e_argument_of_str_must_be_list_or_blob), "reverse()");
else else

View File

@@ -23,6 +23,7 @@ int has_non_ascii(char_u *s);
char_u *concat_str(char_u *str1, char_u *str2); char_u *concat_str(char_u *str1, char_u *str2);
char_u *string_quote(char_u *str, int function); char_u *string_quote(char_u *str, int function);
long string_count(char_u *haystack, char_u *needle, int ic); long string_count(char_u *haystack, char_u *needle, int ic);
void string_reverse(char_u *str, typval_T *rettv);
void string_filter_map(char_u *str, filtermap_T filtermap, typval_T *expr, typval_T *rettv); void string_filter_map(char_u *str, filtermap_T filtermap, typval_T *expr, typval_T *rettv);
void string_reduce(typval_T *argvars, typval_T *expr, typval_T *rettv); void string_reduce(typval_T *argvars, typval_T *expr, typval_T *rettv);
void f_byteidx(typval_T *argvars, typval_T *rettv); void f_byteidx(typval_T *argvars, typval_T *rettv);

View File

@@ -854,6 +854,47 @@ string_count(char_u *haystack, char_u *needle, int ic)
return n; return n;
} }
/*
* Reverse the string in 'str' and set the result in 'rettv'.
*/
void
string_reverse(char_u *str, typval_T *rettv)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
if (str == NULL)
return;
char_u *rstr = vim_strsave(str);
rettv->vval.v_string = rstr;
if (rstr == NULL || *str == NUL)
return;
size_t len = STRLEN(rstr);
if (has_mbyte)
{
char_u *src = str;
char_u *dest = rstr + len;
while (src < str + len)
{
int clen = mb_ptr2len(src);
dest -= clen;
mch_memmove(dest, src, (size_t)clen);
src += clen;
}
}
else
{
for (size_t i = 0; i < len / 2; i++)
{
char tmp = rstr[len - i - 1];
rstr[len - i - 1] = rstr[i];
rstr[i] = tmp;
}
}
}
/* /*
* Make a typval_T of the first character of "input" and store it in "output". * Make a typval_T of the first character of "input" and store it in "output".
* Return OK or FAIL. * Return OK or FAIL.

View File

@@ -3469,4 +3469,21 @@ func Test_delfunc_while_listing()
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
endfunc endfunc
" Test for the reverse() function with a string
func Test_string_reverse()
call assert_equal('', reverse(test_null_string()))
for [s1, s2] in [['', ''], ['a', 'a'], ['ab', 'ba'], ['abc', 'cba'],
\ ['abcd', 'dcba'], ['«-«-»-»', '»-»-«-«'],
\ ['🇦', '🇦'], ['🇦🇧', '🇧🇦'], ['🇦🇧🇨', '🇨🇧🇦'],
\ ['🇦«🇧-🇨»🇩', '🇩»🇨-🇧«🇦']]
call assert_equal(s2, reverse(s1))
endfor
" test in latin1 encoding
let save_enc = &encoding
set encoding=latin1
call assert_equal('dcba', reverse('abcd'))
let &encoding = save_enc
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -981,7 +981,7 @@ func Test_reverse_sort_uniq()
END END
call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Success(lines)
call assert_fails('call reverse("")', 'E899:') call assert_fails('call reverse({})', 'E899:')
call assert_fails('call uniq([1, 2], {x, y -> []})', 'E745:') call assert_fails('call uniq([1, 2], {x, y -> []})', 'E745:')
call assert_fails("call sort([1, 2], function('min'), 1)", "E1206:") call assert_fails("call sort([1, 2], function('min'), 1)", "E1206:")
call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:") call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:")

View File

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