From d6e27f90b9ce19852d14e74c9e8a883f6c2207d7 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 13:41:51 -0700 Subject: vim-patch:7.4.1730 Problem: It is not easy to get a character out of a string. Solution: Add strgetchar() and strcharpart(). https://github.com/vim/vim/commit/58de0e2dcc1f2d251b74892a06d71a14973f3187 --- src/nvim/eval.c | 85 ++++++++++++++++++++++++++++++++++++++++++ src/nvim/eval.lua | 2 + src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_expr.vim | 48 ++++++++++++++++++++++++ src/nvim/version.c | 2 +- 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 src/nvim/testdir/test_expr.vim (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 76f33e7d8c..2826627215 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15612,6 +15612,39 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "strgetchar()" function +static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char_u *str; + int len; + int error = false; + int charidx; + + rettv->vval.v_number = -1; + str = get_tv_string_chk(&argvars[0]); + if (str == NULL) { + return; + } + len = (int)STRLEN(str); + charidx = get_tv_number_chk(&argvars[1], &error); + if (error) { + return; + } + + { + int byteidx = 0; + + while (charidx >= 0 && byteidx < len) { + if (charidx == 0) { + rettv->vval.v_number = mb_ptr2char(str + byteidx); + break; + } + charidx--; + byteidx += mb_char2len(str[byteidx]); + } + } +} + /* * "stridx()" function */ @@ -15712,6 +15745,58 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (varnumber_T) mb_string2cells(s); } +// "strcharpart()" function +static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + char_u *p; + int nchar; + int nbyte = 0; + int charlen; + int len = 0; + int slen; + int error = false; + + p = get_tv_string(&argvars[0]); + slen = (int)STRLEN(p); + + nchar = get_tv_number_chk(&argvars[1], &error); + if (!error) { + if (nchar > 0) { + while (nchar > 0 && nbyte < slen) { + nbyte += mb_char2len(p[nbyte]); + nchar--; + } + } else { + nbyte = nchar; + } + } + if (argvars[2].v_type != VAR_UNKNOWN) { + charlen = get_tv_number(&argvars[2]); + while (charlen > 0 && nbyte + len < slen) { + len += mb_char2len(p[nbyte + len]); + charlen--; + } + } else { + len = slen - nbyte; // default: all bytes that are available. + } + + // Only return the overlap between the specified part and the actual + // string. + if (nbyte < 0) { + len += nbyte; + nbyte = 0; + } else if (nbyte > slen) { + nbyte = slen; + } + if (len < 0) { + len = 0; + } else if (nbyte + len > slen) { + len = slen - nbyte; + } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strnsave(p + nbyte, len); +} + /* * "strpart()" function */ diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index eaaee81533..633a4b1061 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -268,9 +268,11 @@ return { sqrt={args=1, func="float_op_wrapper", data="&sqrt"}, str2float={args=1}, str2nr={args={1, 2}}, + strcharpart={args={2, 3}}, strchars={args={1,2}}, strdisplaywidth={args={1, 2}}, strftime={args={1, 2}}, + strgetchar={args={2,2}}, stridx={args={2, 3}}, string={args=1}, strlen={args=1}, diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 036a4c0470..90194fefce 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -4,6 +4,7 @@ source test_assign.vim source test_cursor_func.vim source test_ex_undo.vim +source test_expr.vim source test_feedkeys.vim source test_cmdline.vim source test_menu.vim diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim new file mode 100644 index 0000000000..5c70dcb25e --- /dev/null +++ b/src/nvim/testdir/test_expr.vim @@ -0,0 +1,48 @@ +" Tests for expressions. + +func Test_strgetchar() + call assert_equal(char2nr('a'), strgetchar('axb', 0)) + call assert_equal(char2nr('x'), strgetchar('axb', 1)) + call assert_equal(char2nr('b'), strgetchar('axb', 2)) + + call assert_equal(-1, strgetchar('axb', -1)) + call assert_equal(-1, strgetchar('axb', 3)) + call assert_equal(-1, strgetchar('', 0)) + + if !has('multi_byte') + return + endif + + call assert_equal(char2nr('á'), strgetchar('áxb', 0)) + call assert_equal(char2nr('x'), strgetchar('áxb', 1)) + + call assert_equal(char2nr('a'), strgetchar('àxb', 0)) + call assert_equal(char2nr(''), strgetchar('àxb', 1)) + call assert_equal(char2nr('x'), strgetchar('àxb', 2)) +endfunc + +func Test_strcharpart() + call assert_equal('a', strcharpart('axb', 0, 1)) + call assert_equal('x', strcharpart('axb', 1, 1)) + call assert_equal('b', strcharpart('axb', 2, 1)) + call assert_equal('xb', strcharpart('axb', 1)) + + call assert_equal('', strcharpart('axb', 1, 0)) + call assert_equal('', strcharpart('axb', 1, -1)) + call assert_equal('', strcharpart('axb', -1, 1)) + call assert_equal('', strcharpart('axb', -2, 2)) + + call assert_equal('a', strcharpart('axb', -1, 2)) + + if !has('multi_byte') + return + endif + + call assert_equal('áxb', strcharpart('áxb', 0)) + call assert_equal('á', strcharpart('áxb', 0, 1)) + call assert_equal('x', strcharpart('áxb', 1, 1)) + + call assert_equal('a', strcharpart('àxb', 0, 1)) + call assert_equal('', strcharpart('àxb', 1, 1)) + call assert_equal('x', strcharpart('àxb', 2, 1)) +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 2dfe5d3248..74e9289a3e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -713,7 +713,7 @@ static int included_patches[] = { // 1733 NA 1732, // 1731, - // 1730, + 1730, // 1729 NA 1728, // 1727, -- cgit From 763422b0365cd9270dc495f31e75e75913516088 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 16:59:24 -0700 Subject: vim-patch:7.4.1734 Problem: Test fails when not using utf-8. Solution: Split test in regularand utf-8 part. https://github.com/vim/vim/commit/0f518a8f4d4be4cac10389680f6bd5e3781f94b0 --- src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_expr.vim | 23 ----------------------- src/nvim/testdir/test_expr_utf8.vim | 33 +++++++++++++++++++++++++++++++++ src/nvim/version.c | 2 +- 4 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 src/nvim/testdir/test_expr_utf8.vim (limited to 'src') diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 90194fefce..87c1cd2c58 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -5,6 +5,7 @@ source test_assign.vim source test_cursor_func.vim source test_ex_undo.vim source test_expr.vim +source test_expr_utf8.vim source test_feedkeys.vim source test_cmdline.vim source test_menu.vim diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 5c70dcb25e..7ea4ebc7df 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -8,17 +8,6 @@ func Test_strgetchar() call assert_equal(-1, strgetchar('axb', -1)) call assert_equal(-1, strgetchar('axb', 3)) call assert_equal(-1, strgetchar('', 0)) - - if !has('multi_byte') - return - endif - - call assert_equal(char2nr('á'), strgetchar('áxb', 0)) - call assert_equal(char2nr('x'), strgetchar('áxb', 1)) - - call assert_equal(char2nr('a'), strgetchar('àxb', 0)) - call assert_equal(char2nr(''), strgetchar('àxb', 1)) - call assert_equal(char2nr('x'), strgetchar('àxb', 2)) endfunc func Test_strcharpart() @@ -33,16 +22,4 @@ func Test_strcharpart() call assert_equal('', strcharpart('axb', -2, 2)) call assert_equal('a', strcharpart('axb', -1, 2)) - - if !has('multi_byte') - return - endif - - call assert_equal('áxb', strcharpart('áxb', 0)) - call assert_equal('á', strcharpart('áxb', 0, 1)) - call assert_equal('x', strcharpart('áxb', 1, 1)) - - call assert_equal('a', strcharpart('àxb', 0, 1)) - call assert_equal('', strcharpart('àxb', 1, 1)) - call assert_equal('x', strcharpart('àxb', 2, 1)) endfunc diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim new file mode 100644 index 0000000000..85cddbb13a --- /dev/null +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -0,0 +1,33 @@ +" Tests for expressions using utf-8. +if !has('multi_byte') + finish +endif +scriptencoding utf-8 + +func Test_strgetchar() + call assert_equal(char2nr('a'), strgetchar('axb', 0)) + call assert_equal(char2nr('x'), strgetchar('axb', 1)) + call assert_equal(char2nr('b'), strgetchar('axb', 2)) + + call assert_equal(-1, strgetchar('axb', -1)) + call assert_equal(-1, strgetchar('axb', 3)) + call assert_equal(-1, strgetchar('', 0)) + + call assert_equal(char2nr('a'), strgetchar('àxb', 0)) + call assert_equal(char2nr('̀'), strgetchar('àxb', 1)) + call assert_equal(char2nr('x'), strgetchar('àxb', 2)) + + call assert_equal(char2nr('あ'), strgetchar('あaい', 0)) + call assert_equal(char2nr('a'), strgetchar('あaい', 1)) + call assert_equal(char2nr('い'), strgetchar('あaい', 2)) +endfunc + +func Test_strcharpart() + call assert_equal('áxb', strcharpart('áxb', 0)) + call assert_equal('á', strcharpart('áxb', 0, 1)) + call assert_equal('x', strcharpart('áxb', 1, 1)) + + call assert_equal('a', strcharpart('àxb', 0, 1)) + call assert_equal('̀', strcharpart('àxb', 1, 1)) + call assert_equal('x', strcharpart('àxb', 2, 1)) +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 74e9289a3e..cdbc0a34fe 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -709,7 +709,7 @@ static int included_patches[] = { // 1737 NA // 1736 NA // 1735, - // 1734, + 1734, // 1733 NA 1732, // 1731, -- cgit From 9e5dca84902eb620d856b1e9bd994218f4423708 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 17:04:26 -0700 Subject: vim-patch:7.4.1741 Problem: Not testing utf-8 characters. Solution: Move the right asserts to the test_expr_utf8 test. https://github.com/vim/vim/commit/b22bd46b9681d73d095f2eadff8163d3a6cf416b --- src/nvim/testdir/test_expr_utf8.vim | 5 ++--- src/nvim/version.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim index 85cddbb13a..00d5d9a63a 100644 --- a/src/nvim/testdir/test_expr_utf8.vim +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -5,9 +5,8 @@ endif scriptencoding utf-8 func Test_strgetchar() - call assert_equal(char2nr('a'), strgetchar('axb', 0)) - call assert_equal(char2nr('x'), strgetchar('axb', 1)) - call assert_equal(char2nr('b'), strgetchar('axb', 2)) + call assert_equal(char2nr('á'), strgetchar('áxb', 0)) + call assert_equal(char2nr('x'), strgetchar('áxb', 1)) call assert_equal(-1, strgetchar('axb', -1)) call assert_equal(-1, strgetchar('axb', 3)) diff --git a/src/nvim/version.c b/src/nvim/version.c index cdbc0a34fe..2b6dffd38d 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -702,7 +702,7 @@ static int included_patches[] = { // 1744 NA // 1743 NA // 1742, - // 1741, + 1741, 1740, // 1739, // 1738, -- cgit From b5dfdf0669c4ee1293d558543d7d96a374ac2e1d Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 17:07:36 -0700 Subject: vim-patch:7.4.1742 Problem: strgetchar() does not work correctly. Solution: use mb_cptr2len(). Add a test. (Naruhiko Nishino) https://github.com/vim/vim/commit/5d18e0eca59ffbba22c7f7c91c9f99d672095728 --- src/nvim/eval.c | 2 +- src/nvim/version.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 2826627215..9fc5256a7e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15640,7 +15640,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } charidx--; - byteidx += mb_char2len(str[byteidx]); + byteidx += mb_cptr2len(str + byteidx); } } } diff --git a/src/nvim/version.c b/src/nvim/version.c index 2b6dffd38d..389e89b466 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -701,7 +701,7 @@ static int included_patches[] = { // 1745 NA // 1744 NA // 1743 NA - // 1742, + 1742, 1741, 1740, // 1739, -- cgit From 6bc0d9b8c75b5bef61a951e56deb2b28f50182d8 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 17:38:28 -0700 Subject: vim-patch:7.4.1779 Problem: Using negative index in strcharpart(). (Yegappan Lakshmanan) Solution: Assume single byte when using a negative iindex. https://github.com/vim/vim/commit/73dfe917ba6357413aaf98a021c91add5ac6e9bc --- src/nvim/eval.c | 10 ++++++++-- src/nvim/testdir/test_expr_utf8.vim | 26 ++++++++++++++++---------- src/nvim/version.c | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9fc5256a7e..a9079c5519 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15772,8 +15772,14 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[2].v_type != VAR_UNKNOWN) { charlen = get_tv_number(&argvars[2]); while (charlen > 0 && nbyte + len < slen) { - len += mb_char2len(p[nbyte + len]); - charlen--; + int off = nbyte + len; + + if (off < 0) { + len += 1; + } else { + len += mb_char2len(p[off]); + charlen--; + } } } else { len = slen - nbyte; // default: all bytes that are available. diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim index 00d5d9a63a..7bdcb4f65f 100644 --- a/src/nvim/testdir/test_expr_utf8.vim +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -4,29 +4,35 @@ if !has('multi_byte') endif scriptencoding utf-8 -func Test_strgetchar() +func Test_strgetchar_utf8() call assert_equal(char2nr('á'), strgetchar('áxb', 0)) call assert_equal(char2nr('x'), strgetchar('áxb', 1)) - call assert_equal(-1, strgetchar('axb', -1)) - call assert_equal(-1, strgetchar('axb', 3)) - call assert_equal(-1, strgetchar('', 0)) - - call assert_equal(char2nr('a'), strgetchar('àxb', 0)) + call assert_equal(char2nr('a'), strgetchar('àxb', 0)) call assert_equal(char2nr('̀'), strgetchar('àxb', 1)) - call assert_equal(char2nr('x'), strgetchar('àxb', 2)) + call assert_equal(char2nr('x'), strgetchar('àxb', 2)) call assert_equal(char2nr('あ'), strgetchar('あaい', 0)) call assert_equal(char2nr('a'), strgetchar('あaい', 1)) call assert_equal(char2nr('い'), strgetchar('あaい', 2)) endfunc -func Test_strcharpart() +func Test_strcharpart_utf8() call assert_equal('áxb', strcharpart('áxb', 0)) call assert_equal('á', strcharpart('áxb', 0, 1)) call assert_equal('x', strcharpart('áxb', 1, 1)) - call assert_equal('a', strcharpart('àxb', 0, 1)) + call assert_equal('いうeお', strcharpart('あいうeお', 1)) + call assert_equal('い', strcharpart('あいうeお', 1, 1)) + call assert_equal('いう', strcharpart('あいうeお', 1, 2)) + call assert_equal('いうe', strcharpart('あいうeお', 1, 3)) + call assert_equal('いうeお', strcharpart('あいうeお', 1, 4)) + call assert_equal('eお', strcharpart('あいうeお', 3)) + call assert_equal('e', strcharpart('あいうeお', 3, 1)) + + call assert_equal('あ', strcharpart('あいうeお', -3, 4)) + + call assert_equal('a', strcharpart('àxb', 0, 1)) call assert_equal('̀', strcharpart('àxb', 1, 1)) - call assert_equal('x', strcharpart('àxb', 2, 1)) + call assert_equal('x', strcharpart('àxb', 2, 1)) endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 389e89b466..53435e4650 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -663,7 +663,7 @@ static int included_patches[] = { // 1782, // 1781, // 1780, - // 1779, + 1779, // 1778 NA // 1777 NA // 1776 NA -- cgit From f6f77272b3233ea2926e2d7fb2c007e381a85ea1 Mon Sep 17 00:00:00 2001 From: Michael Ennen Date: Sun, 23 Oct 2016 17:10:14 -0700 Subject: vim-patch:7.4.1782 Problem: strcharpart() does not work properly with some multi-byte characters. Solution: Use mb_cptr2len() instead of mb_char2len(). (Hirohito Higashi) https://github.com/vim/vim/commit/fca66003053f8c0da5161d1fe4b75b3a389934b5 --- src/nvim/eval.c | 6 +++--- src/nvim/eval.lua | 2 +- src/nvim/version.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a9079c5519..4eb3b36464 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15762,7 +15762,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (!error) { if (nchar > 0) { while (nchar > 0 && nbyte < slen) { - nbyte += mb_char2len(p[nbyte]); + nbyte += mb_cptr2len(p + nbyte); nchar--; } } else { @@ -15777,9 +15777,9 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (off < 0) { len += 1; } else { - len += mb_char2len(p[off]); - charlen--; + len += mb_cptr2len(p + off); } + charlen--; } } else { len = slen - nbyte; // default: all bytes that are available. diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 633a4b1061..bea25b36f3 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -272,7 +272,7 @@ return { strchars={args={1,2}}, strdisplaywidth={args={1, 2}}, strftime={args={1, 2}}, - strgetchar={args={2,2}}, + strgetchar={args={2, 2}}, stridx={args={2, 3}}, string={args=1}, strlen={args=1}, diff --git a/src/nvim/version.c b/src/nvim/version.c index 53435e4650..153b7fb5fd 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -660,7 +660,7 @@ static int included_patches[] = { // 1785, // 1784 NA // 1783, - // 1782, + 1782, // 1781, // 1780, 1779, -- cgit