diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.lua | 2 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 41 | ||||
-rw-r--r-- | src/nvim/screen.c | 19 | ||||
-rw-r--r-- | src/nvim/testdir/test_listchars.vim | 20 | ||||
-rw-r--r-- | src/nvim/testdir/test_utf8.vim | 43 |
5 files changed, 119 insertions, 6 deletions
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 17d9cc56aa..4654f8cef6 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -214,6 +214,7 @@ return { line={args=1}, line2byte={args=1}, lispindent={args=1}, + list2str={args={1, 2}}, localtime={}, log={args=1, func="float_op_wrapper", data="&log"}, log10={args=1, func="float_op_wrapper", data="&log10"}, @@ -321,6 +322,7 @@ return { sqrt={args=1, func="float_op_wrapper", data="&sqrt"}, stdpath={args=1}, str2float={args=1}, + str2list={args={1, 2}}, str2nr={args={1, 2}}, strcharpart={args={2, 3}}, strchars={args={1,2}}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 36782e4223..bd57cec794 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5246,6 +5246,36 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "list2str()" function +static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + garray_T ga; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + if (argvars[0].v_type != VAR_LIST) { + EMSG(_(e_invarg)); + return; + } + + list_T *const l = argvars[0].vval.v_list; + if (l == NULL) { + return; // empty list results in empty string + } + + ga_init(&ga, 1, 80); + char_u buf[MB_MAXBYTES + 1]; + + TV_LIST_ITER_CONST(l, li, { + buf[utf_char2bytes(tv_get_number(TV_LIST_ITEM_TV(li)), buf)] = NUL; + ga_concat(&ga, buf); + }); + ga_append(&ga, NUL); + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = ga.ga_data; +} + /* * "localtime()" function */ @@ -9353,6 +9383,17 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_FLOAT; } +// "str2list()" function +static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tv_list_alloc_ret(rettv, kListLenUnknown); + const char_u *p = (const char_u *)tv_get_string(&argvars[0]); + + for (; *p != NUL; p += utf_ptr2len(p)) { + tv_list_append_number(rettv->vval.v_list, utf_ptr2char(p)); + } +} + // "str2nr()" function static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 5df279c0a7..b6da02d9c3 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -3647,8 +3647,9 @@ win_line ( tab_len += n_extra - tab_len; } - /* if n_extra > 0, it gives the number of chars to use for - * a tab, else we need to calculate the width for a tab */ + // if n_extra > 0, it gives the number of chars + // to use for a tab, else we need to calculate the width + // for a tab int len = (tab_len * mb_char2len(wp->w_p_lcs_chars.tab2)); if (n_extra > 0) { len += n_extra - tab_len; @@ -3660,10 +3661,16 @@ win_line ( xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { - utf_char2bytes(wp->w_p_lcs_chars.tab2, p); - p += mb_char2len(wp->w_p_lcs_chars.tab2); - n_extra += mb_char2len(wp->w_p_lcs_chars.tab2) - - (saved_nextra > 0 ? 1: 0); + int lcs = wp->w_p_lcs_chars.tab2; + + // if tab3 is given, need to change the char + // for tab + if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) { + lcs = wp->w_p_lcs_chars.tab3; + } + utf_char2bytes(lcs, p); + p += mb_char2len(lcs); + n_extra += mb_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); } p_extra = p_extra_free; diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim index 57cfaa298e..dcc588120c 100644 --- a/src/nvim/testdir/test_listchars.vim +++ b/src/nvim/testdir/test_listchars.vim @@ -58,6 +58,26 @@ func Test_listchars() call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) endfor + " tab with 3rd character and linebreak set + set listchars-=tab:<=> + set listchars+=tab:<·> + set linebreak + let expected = [ + \ '<······>aa<····>$', + \ '..bb<··>--$', + \ '...cccc>-$', + \ 'dd........ee--<>$', + \ '-$' + \ ] + redraw! + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + set nolinebreak + set listchars-=tab:<·> + set listchars+=tab:<=> + set listchars-=trail:- let expected = [ \ '<======>aa<====>$', diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim index b1f33f56dd..1b4ce4c4af 100644 --- a/src/nvim/testdir/test_utf8.vim +++ b/src/nvim/testdir/test_utf8.vim @@ -60,3 +60,46 @@ func Test_getvcol() call assert_equal(2, virtcol("'[")) call assert_equal(2, virtcol("']")) endfunc + +func Test_list2str_str2list_utf8() + " One Unicode codepoint + let s = "\u3042\u3044" + let l = [0x3042, 0x3044] + call assert_equal(l, str2list(s, 1)) + call assert_equal(s, list2str(l, 1)) + if &enc ==# 'utf-8' + call assert_equal(str2list(s), str2list(s, 1)) + call assert_equal(list2str(l), list2str(l, 1)) + endif + + " With composing characters + let s = "\u304b\u3099\u3044" + let l = [0x304b, 0x3099, 0x3044] + call assert_equal(l, str2list(s, 1)) + call assert_equal(s, list2str(l, 1)) + if &enc ==# 'utf-8' + call assert_equal(str2list(s), str2list(s, 1)) + call assert_equal(list2str(l), list2str(l, 1)) + endif + + " Null list is the same as an empty list + call assert_equal('', list2str([])) + " call assert_equal('', list2str(test_null_list())) +endfunc + +func Test_list2str_str2list_latin1() + " When 'encoding' is not multi-byte can still get utf-8 string. + " But we need to create the utf-8 string while 'encoding' is utf-8. + let s = "\u3042\u3044" + let l = [0x3042, 0x3044] + + let save_encoding = &encoding + " set encoding=latin1 + + let lres = str2list(s, 1) + let sres = list2str(l, 1) + + let &encoding = save_encoding + call assert_equal(l, lres) + call assert_equal(s, sres) +endfunc |