diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui.c | 7 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 2 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 2 | ||||
-rw-r--r-- | src/nvim/misc1.c | 3 | ||||
-rw-r--r-- | src/nvim/option.c | 7 | ||||
-rw-r--r-- | src/nvim/options.lua | 2 | ||||
-rw-r--r-- | src/nvim/regexp.c | 17 | ||||
-rw-r--r-- | src/nvim/regexp_nfa.c | 5 | ||||
-rw-r--r-- | src/nvim/screen.c | 3 | ||||
-rw-r--r-- | src/nvim/testdir/test_alot.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 415 | ||||
-rw-r--r-- | src/nvim/testdir/test_listlbr_utf8.vim | 15 | ||||
-rw-r--r-- | src/nvim/testdir/test_regexp_utf8.vim | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_scroll_opt.vim | 36 | ||||
-rw-r--r-- | src/nvim/testdir/test_smartindent.vim | 27 | ||||
-rw-r--r-- | src/nvim/testdir/test_syntax.vim | 59 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 6 | ||||
-rw-r--r-- | src/nvim/ui.c | 16 | ||||
-rw-r--r-- | src/nvim/ui.h | 1 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 25 | ||||
-rw-r--r-- | src/nvim/version.c | 120 |
23 files changed, 711 insertions, 93 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 4cd2657561..b6e0b9a566 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -97,6 +97,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, ui->set_icon = remote_ui_set_icon; ui->option_set = remote_ui_option_set; ui->event = remote_ui_event; + ui->inspect = remote_ui_inspect; memset(ui->ui_ext, 0, sizeof(ui->ui_ext)); @@ -275,3 +276,9 @@ static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed) } push_call(ui, name, my_args); } + +static void remote_ui_inspect(UI *ui, Dictionary *info) +{ + UIData *data = ui->data; + PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id)); +} diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 96d494460b..3ef16a7ac3 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -62,7 +62,7 @@ void set_title(String title) void set_icon(String icon) FUNC_API_SINCE(3); void option_set(String name, Object value) - FUNC_API_SINCE(4); + FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL; void popupmenu_show(Array items, Integer selected, Integer row, Integer col) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index f587948cf0..b73ecc2d03 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1747,6 +1747,14 @@ Dictionary nvim__stats(void) /// Gets a list of dictionaries representing attached UIs. /// /// @return Array of UI dictionaries +/// +/// Each dictionary has the following keys: +/// - "height" requested height of the UI +/// - "width" requested width of the UI +/// - "rgb" whether the UI uses rgb colors (false implies cterm colors) +/// - "ext_..." Requested UI extensions, see |ui-options| +/// - "chan" Channel id of remote UI (not present for TUI) +/// Array nvim_list_uis(void) FUNC_API_SINCE(4) { diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index ce02808ad3..4e46c5ce45 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -698,7 +698,7 @@ return { }, { command='delfunction', - flags=bit.bor(NEEDARG, WORD1, CMDWIN), + flags=bit.bor(BANG, NEEDARG, WORD1, CMDWIN), addr_type=ADDR_LINES, func='ex_delfunction', }, diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 28455f0ba9..dc59aa1281 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -106,7 +106,8 @@ open_line ( char_u *p; char_u saved_char = NUL; // init for GCC pos_T *pos; - bool do_si = (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin); + bool do_si = (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin + && *curbuf->b_p_inde == NUL); bool no_si = false; // reset did_si afterwards int first_char = NUL; // init for GCC int vreplace_mode; diff --git a/src/nvim/option.c b/src/nvim/option.c index 88c458b597..26fc164c6c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -939,11 +939,8 @@ void set_init_2(bool headless) { int idx; - /* - * 'scroll' defaults to half the window height. Note that this default is - * wrong when the window height changes. - */ - set_number_default("scroll", Rows / 2); + // 'scroll' defaults to half the window height. The stored default is zero, + // which results in the actual value computed from the window height. idx = findoption("scroll"); if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) { set_option_default(idx, OPT_LOCAL, p_cp); diff --git a/src/nvim/options.lua b/src/nvim/options.lua index f1f559fff0..47c9f5aa78 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1922,7 +1922,7 @@ return { no_mkrc=true, vi_def=true, pv_name='p_scroll', - defaults={if_true={vi=12}} + defaults={if_true={vi=0}} }, { full_name='scrollback', abbreviation='scbk', diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index ee7d6d8500..c4af7d9e4a 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -479,6 +479,8 @@ static char_u *regprop(char_u *); #endif static char_u e_missingbracket[] = N_("E769: Missing ] after %s["); +static char_u e_reverse_range[] = N_("E944: Reverse range in character class"); +static char_u e_large_class[] = N_("E945: Range too large in character class"); static char_u e_unmatchedpp[] = N_("E53: Unmatched %s%%("); static char_u e_unmatchedp[] = N_("E54: Unmatched %s("); static char_u e_unmatchedpar[] = N_("E55: Unmatched %s)"); @@ -2232,15 +2234,18 @@ collection: if (endc == '\\' && !reg_cpo_lit) endc = coll_get_char(); - if (startc > endc) - EMSG_RET_NULL(_(e_invrange)); + if (startc > endc) { + EMSG_RET_NULL(_(e_reverse_range)); + } if (has_mbyte && ((*mb_char2len)(startc) > 1 || (*mb_char2len)(endc) > 1)) { - /* Limit to a range of 256 chars */ - if (endc > startc + 256) - EMSG_RET_NULL(_(e_invrange)); - while (++startc <= endc) + // Limit to a range of 256 chars + if (endc > startc + 256) { + EMSG_RET_NULL(_(e_large_class)); + } + while (++startc <= endc) { regmbc(startc); + } } else { while (++startc <= endc) regc(startc); diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 0b8e979ca2..334539b228 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -1711,8 +1711,9 @@ collection: if (emit_range) { endc = startc; startc = oldstartc; - if (startc > endc) - EMSG_RET_FAIL(_(e_invrange)); + if (startc > endc) { + EMSG_RET_FAIL(_(e_reverse_range)); + } if (endc > startc + 2) { /* Emit a range instead of the sequence of diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 4299002084..b0bf3a7d5f 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -4061,7 +4061,8 @@ win_line ( * Also highlight the 'colorcolumn' if it is different than * 'cursorcolumn' */ vcol_save_attr = -1; - if (draw_state == WL_LINE && !lnum_in_visual_area) { + if (draw_state == WL_LINE && !lnum_in_visual_area + && search_attr == 0 && area_attr == 0) { if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { vcol_save_attr = char_attr; diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index b4baf7a8d7..c4b4a43ad4 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -27,6 +27,7 @@ source test_popup.vim source test_put.vim source test_recover.vim source test_regexp_utf8.vim +source test_scroll_opt.vim source test_source_utf8.vim source test_sha256.vim source test_statusline.vim diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index be68e9ff9d..8139f00f0e 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -64,6 +64,10 @@ func Test_highlight_completion() hi Aardig ctermfg=green call feedkeys(":hi \<Tab>\<Home>\"\<CR>", 'xt') call assert_equal('"hi Aardig', getreg(':')) + call feedkeys(":hi default \<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi default Aardig', getreg(':')) + call feedkeys(":hi clear Aa\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi clear Aardig', getreg(':')) call feedkeys(":hi li\<S-Tab>\<Home>\"\<CR>", 'xt') call assert_equal('"hi link', getreg(':')) call feedkeys(":hi d\<S-Tab>\<Home>\"\<CR>", 'xt') diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 398e9ab331..8a82493ab6 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1,5 +1,101 @@ " Tests for various functions. +" Must be done first, since the alternate buffer must be unset. +func Test_00_bufexists() + call assert_equal(0, bufexists('does_not_exist')) + call assert_equal(1, bufexists(bufnr('%'))) + call assert_equal(0, bufexists(0)) + new Xfoo + let bn = bufnr('%') + call assert_equal(1, bufexists(bn)) + call assert_equal(1, bufexists('Xfoo')) + call assert_equal(1, bufexists(getcwd() . '/Xfoo')) + call assert_equal(1, bufexists(0)) + bw + call assert_equal(0, bufexists(bn)) + call assert_equal(0, bufexists('Xfoo')) +endfunc + +func Test_empty() + call assert_equal(1, empty('')) + call assert_equal(0, empty('a')) + + call assert_equal(1, empty(0)) + call assert_equal(1, empty(-0)) + call assert_equal(0, empty(1)) + call assert_equal(0, empty(-1)) + + call assert_equal(1, empty(0.0)) + call assert_equal(1, empty(-0.0)) + call assert_equal(0, empty(1.0)) + call assert_equal(0, empty(-1.0)) + call assert_equal(0, empty(1.0/0.0)) + call assert_equal(0, empty(0.0/0.0)) + + call assert_equal(1, empty([])) + call assert_equal(0, empty(['a'])) + + call assert_equal(1, empty({})) + call assert_equal(0, empty({'a':1})) + + call assert_equal(1, empty(v:null)) + " call assert_equal(1, empty(v:none)) + call assert_equal(1, empty(v:false)) + call assert_equal(0, empty(v:true)) + + if has('channel') + call assert_equal(1, empty(test_null_channel())) + endif + if has('job') + call assert_equal(1, empty(test_null_job())) + endif + + call assert_equal(0, empty(function('Test_empty'))) +endfunc + +func Test_len() + call assert_equal(1, len(0)) + call assert_equal(2, len(12)) + + call assert_equal(0, len('')) + call assert_equal(2, len('ab')) + + call assert_equal(0, len([])) + call assert_equal(2, len([2, 1])) + + call assert_equal(0, len({})) + call assert_equal(2, len({'a': 1, 'b': 2})) + + " call assert_fails('call len(v:none)', 'E701:') + call assert_fails('call len({-> 0})', 'E701:') +endfunc + +func Test_max() + call assert_equal(0, max([])) + call assert_equal(2, max([2])) + call assert_equal(2, max([1, 2])) + call assert_equal(2, max([1, 2, v:null])) + + call assert_equal(0, max({})) + call assert_equal(2, max({'a':1, 'b':2})) + + call assert_fails('call max(1)', 'E712:') + " call assert_fails('call max(v:none)', 'E712:') +endfunc + +func Test_min() + call assert_equal(0, min([])) + call assert_equal(2, min([2])) + call assert_equal(1, min([1, 2])) + call assert_equal(0, min([1, 2, v:null])) + + call assert_equal(0, min({})) + call assert_equal(1, min({'a':1, 'b':2})) + + call assert_fails('call min(1)', 'E712:') + " call assert_fails('call min(v:none)', 'E712:') +endfunc + func Test_str2nr() call assert_equal(0, str2nr('')) call assert_equal(1, str2nr('1')) @@ -15,6 +111,77 @@ func Test_str2nr() call assert_equal(123456789, str2nr('123456789')) call assert_equal(-123456789, str2nr('-123456789')) + + call assert_equal(5, str2nr('101', 2)) + call assert_equal(5, str2nr('0b101', 2)) + call assert_equal(5, str2nr('0B101', 2)) + call assert_equal(-5, str2nr('-101', 2)) + call assert_equal(-5, str2nr('-0b101', 2)) + call assert_equal(-5, str2nr('-0B101', 2)) + + call assert_equal(65, str2nr('101', 8)) + call assert_equal(65, str2nr('0101', 8)) + call assert_equal(-65, str2nr('-101', 8)) + call assert_equal(-65, str2nr('-0101', 8)) + + call assert_equal(11259375, str2nr('abcdef', 16)) + call assert_equal(11259375, str2nr('ABCDEF', 16)) + call assert_equal(-11259375, str2nr('-ABCDEF', 16)) + call assert_equal(11259375, str2nr('0xabcdef', 16)) + call assert_equal(11259375, str2nr('0Xabcdef', 16)) + call assert_equal(11259375, str2nr('0XABCDEF', 16)) + call assert_equal(-11259375, str2nr('-0xABCDEF', 16)) + + call assert_equal(0, str2nr('0x10')) + call assert_equal(0, str2nr('0b10')) + call assert_equal(1, str2nr('12', 2)) + call assert_equal(1, str2nr('18', 8)) + call assert_equal(1, str2nr('1g', 16)) + + call assert_equal(0, str2nr(v:null)) + " call assert_equal(0, str2nr(v:none)) + + call assert_fails('call str2nr([])', 'E730:') + call assert_fails('call str2nr({->2})', 'E729:') + call assert_fails('call str2nr(1.2)', 'E806:') + call assert_fails('call str2nr(10, [])', 'E474:') +endfunc + +func Test_strftime() + if !exists('*strftime') + return + endif + " Format of strftime() depends on system. We assume + " that basic formats tested here are available and + " identical on all systems which support strftime(). + " + " The 2nd parameter of strftime() is a local time, so the output day + " of strftime() can be 17 or 18, depending on timezone. + call assert_match('^2017-01-1[78]$', strftime('%Y-%m-%d', 1484695512)) + " + call assert_match('^\d\d\d\d-\(0\d\|1[012]\)-\([012]\d\|3[01]\) \([01]\d\|2[0-3]\):[0-5]\d:\([0-5]\d\|60\)$', strftime('%Y-%m-%d %H:%M:%S')) + + call assert_fails('call strftime([])', 'E730:') + call assert_fails('call strftime("%Y", [])', 'E745:') +endfunc + +func Test_simplify() + call assert_equal('', simplify('')) + call assert_equal('/', simplify('/')) + call assert_equal('/', simplify('/.')) + call assert_equal('/', simplify('/..')) + call assert_equal('/...', simplify('/...')) + call assert_equal('./dir/file', simplify('./dir/file')) + call assert_equal('./dir/file', simplify('.///dir//file')) + call assert_equal('./dir/file', simplify('./dir/./file')) + call assert_equal('./file', simplify('./dir/../file')) + call assert_equal('../dir/file', simplify('dir/../../dir/file')) + call assert_equal('./file', simplify('dir/.././file')) + + call assert_fails('call simplify({->0})', 'E729:') + call assert_fails('call simplify([])', 'E730:') + call assert_fails('call simplify({})', 'E731:') + call assert_fails('call simplify(1.2)', 'E806:') endfunc func Test_setbufvar_options() @@ -48,6 +215,19 @@ func Test_setbufvar_options() bwipe! endfunc +func Test_strpart() + call assert_equal('de', strpart('abcdefg', 3, 2)) + call assert_equal('ab', strpart('abcdefg', -2, 4)) + call assert_equal('abcdefg', strpart('abcdefg', -2)) + call assert_equal('fg', strpart('abcdefg', 5, 4)) + call assert_equal('defg', strpart('abcdefg', 3)) + + if has('multi_byte') + call assert_equal('lép', strpart('éléphant', 2, 4)) + call assert_equal('léphant', strpart('éléphant', 2)) + endif +endfunc + func Test_tolower() call assert_equal("", tolower("")) @@ -188,7 +368,7 @@ func Test_toupper() call assert_equal("YÝŶŸẎỲỶỸ", toupper("YÝŶŸẎỲỶỸ")) call assert_equal("ZŹŻŽƵẐẔ", toupper("ZŹŻŽƵẐẔ")) - call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) + call assert_equal("Ⱥ Ⱦ", toupper("ⱥ ⱦ")) endfunc " Tests for the mode() function @@ -353,3 +533,236 @@ func Test_getbufvar() set fileformats& endfunc + +func Test_last_buffer_nr() + call assert_equal(bufnr('$'), last_buffer_nr()) +endfunc + +func Test_stridx() + call assert_equal(-1, stridx('', 'l')) + call assert_equal(0, stridx('', '')) + call assert_equal(0, stridx('hello', '')) + call assert_equal(-1, stridx('hello', 'L')) + call assert_equal(2, stridx('hello', 'l', -1)) + call assert_equal(2, stridx('hello', 'l', 0)) + call assert_equal(2, stridx('hello', 'l', 1)) + call assert_equal(3, stridx('hello', 'l', 3)) + call assert_equal(-1, stridx('hello', 'l', 4)) + call assert_equal(-1, stridx('hello', 'l', 10)) + call assert_equal(2, stridx('hello', 'll')) + call assert_equal(-1, stridx('hello', 'hello world')) +endfunc + +func Test_strridx() + call assert_equal(-1, strridx('', 'l')) + call assert_equal(0, strridx('', '')) + call assert_equal(5, strridx('hello', '')) + call assert_equal(-1, strridx('hello', 'L')) + call assert_equal(3, strridx('hello', 'l')) + call assert_equal(3, strridx('hello', 'l', 10)) + call assert_equal(3, strridx('hello', 'l', 3)) + call assert_equal(2, strridx('hello', 'l', 2)) + call assert_equal(-1, strridx('hello', 'l', 1)) + call assert_equal(-1, strridx('hello', 'l', 0)) + call assert_equal(-1, strridx('hello', 'l', -1)) + call assert_equal(2, strridx('hello', 'll')) + call assert_equal(-1, strridx('hello', 'hello world')) +endfunc + +func Test_matchend() + call assert_equal(7, matchend('testing', 'ing')) + call assert_equal(7, matchend('testing', 'ing', 2)) + call assert_equal(-1, matchend('testing', 'ing', 5)) +endfunc + +func Test_nextnonblank_prevnonblank() + new +insert +This + + +is + +a +Test +. + call assert_equal(0, nextnonblank(-1)) + call assert_equal(0, nextnonblank(0)) + call assert_equal(1, nextnonblank(1)) + call assert_equal(4, nextnonblank(2)) + call assert_equal(4, nextnonblank(3)) + call assert_equal(4, nextnonblank(4)) + call assert_equal(6, nextnonblank(5)) + call assert_equal(6, nextnonblank(6)) + call assert_equal(7, nextnonblank(7)) + call assert_equal(0, nextnonblank(8)) + + call assert_equal(0, prevnonblank(-1)) + call assert_equal(0, prevnonblank(0)) + call assert_equal(1, prevnonblank(1)) + call assert_equal(1, prevnonblank(2)) + call assert_equal(1, prevnonblank(3)) + call assert_equal(4, prevnonblank(4)) + call assert_equal(4, prevnonblank(5)) + call assert_equal(6, prevnonblank(6)) + call assert_equal(7, prevnonblank(7)) + call assert_equal(0, prevnonblank(8)) + bw! +endfunc + +func Test_byte2line_line2byte() + new + call setline(1, ['a', 'bc', 'd']) + + set fileformat=unix + call assert_equal([-1, -1, 1, 1, 2, 2, 2, 3, 3, -1], + \ map(range(-1, 8), 'byte2line(v:val)')) + call assert_equal([-1, -1, 1, 3, 6, 8, -1], + \ map(range(-1, 5), 'line2byte(v:val)')) + + set fileformat=mac + call assert_equal([-1, -1, 1, 1, 2, 2, 2, 3, 3, -1], + \ map(range(-1, 8), 'byte2line(v:val)')) + call assert_equal([-1, -1, 1, 3, 6, 8, -1], + \ map(range(-1, 5), 'line2byte(v:val)')) + + set fileformat=dos + call assert_equal([-1, -1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, -1], + \ map(range(-1, 11), 'byte2line(v:val)')) + call assert_equal([-1, -1, 1, 4, 8, 11, -1], + \ map(range(-1, 5), 'line2byte(v:val)')) + + set fileformat& + bw! +endfunc + +func Test_count() + let l = ['a', 'a', 'A', 'b'] + call assert_equal(2, count(l, 'a')) + call assert_equal(1, count(l, 'A')) + call assert_equal(1, count(l, 'b')) + call assert_equal(0, count(l, 'B')) + + call assert_equal(2, count(l, 'a', 0)) + call assert_equal(1, count(l, 'A', 0)) + call assert_equal(1, count(l, 'b', 0)) + call assert_equal(0, count(l, 'B', 0)) + + call assert_equal(3, count(l, 'a', 1)) + call assert_equal(3, count(l, 'A', 1)) + call assert_equal(1, count(l, 'b', 1)) + call assert_equal(1, count(l, 'B', 1)) + call assert_equal(0, count(l, 'c', 1)) + + call assert_equal(1, count(l, 'a', 0, 1)) + call assert_equal(2, count(l, 'a', 1, 1)) + call assert_fails('call count(l, "a", 0, 10)', 'E684:') + + let d = {1: 'a', 2: 'a', 3: 'A', 4: 'b'} + call assert_equal(2, count(d, 'a')) + call assert_equal(1, count(d, 'A')) + call assert_equal(1, count(d, 'b')) + call assert_equal(0, count(d, 'B')) + + call assert_equal(2, count(d, 'a', 0)) + call assert_equal(1, count(d, 'A', 0)) + call assert_equal(1, count(d, 'b', 0)) + call assert_equal(0, count(d, 'B', 0)) + + call assert_equal(3, count(d, 'a', 1)) + call assert_equal(3, count(d, 'A', 1)) + call assert_equal(1, count(d, 'b', 1)) + call assert_equal(1, count(d, 'B', 1)) + call assert_equal(0, count(d, 'c', 1)) + + call assert_fails('call count(d, "a", 0, 1)', 'E474:') + call assert_fails('call count("a", "a")', 'E712:') +endfunc + +func Test_changenr() + new Xchangenr + call assert_equal(0, changenr()) + norm ifoo + call assert_equal(1, changenr()) + set undolevels=10 + norm Sbar + call assert_equal(2, changenr()) + undo + call assert_equal(1, changenr()) + redo + call assert_equal(2, changenr()) + bw! + set undolevels& +endfunc + +func Test_filewritable() + new Xfilewritable + write! + call assert_equal(1, filewritable('Xfilewritable')) + + call assert_notequal(0, setfperm('Xfilewritable', 'r--r-----')) + call assert_equal(0, filewritable('Xfilewritable')) + + call assert_notequal(0, setfperm('Xfilewritable', 'rw-r-----')) + call assert_equal(1, filewritable('Xfilewritable')) + + call assert_equal(0, filewritable('doesnotexist')) + + call delete('Xfilewritable') + bw! +endfunc + +func Test_hostname() + let hostname_vim = hostname() + if has('unix') + let hostname_system = systemlist('uname -n')[0] + call assert_equal(hostname_vim, hostname_system) + endif +endfunc + +func Test_getpid() + " getpid() always returns the same value within a vim instance. + call assert_equal(getpid(), getpid()) + if has('unix') + call assert_equal(systemlist('echo $PPID')[0], string(getpid())) + endif +endfunc + +func Test_hlexists() + call assert_equal(0, hlexists('does_not_exist')) + " call assert_equal(0, hlexists('Number')) + call assert_equal(0, highlight_exists('does_not_exist')) + " call assert_equal(0, highlight_exists('Number')) + syntax on + call assert_equal(0, hlexists('does_not_exist')) + " call assert_equal(1, hlexists('Number')) + call assert_equal(0, highlight_exists('does_not_exist')) + " call assert_equal(1, highlight_exists('Number')) + syntax off +endfunc + +func Test_col() + new + call setline(1, 'abcdef') + norm gg4|mx6|mY2| + call assert_equal(2, col('.')) + call assert_equal(7, col('$')) + call assert_equal(4, col("'x")) + call assert_equal(6, col("'Y")) + call assert_equal(2, col([1, 2])) + call assert_equal(7, col([1, '$'])) + + call assert_equal(0, col('')) + call assert_equal(0, col('x')) + call assert_equal(0, col([2, '$'])) + call assert_equal(0, col([1, 100])) + call assert_equal(0, col([1])) + bw! +endfunc + +func Test_balloon_show() + if has('balloon_eval') + " This won't do anything but must not crash either. + call balloon_show('hi!') + endif +endfunc diff --git a/src/nvim/testdir/test_listlbr_utf8.vim b/src/nvim/testdir/test_listlbr_utf8.vim index 56a4cc9b31..b648a3361b 100644 --- a/src/nvim/testdir/test_listlbr_utf8.vim +++ b/src/nvim/testdir/test_listlbr_utf8.vim @@ -194,6 +194,21 @@ func Test_multibyte_sign_and_colorcolumn() call s:close_windows() endfunc +func Test_colorcolumn_priority() + call s:test_windows('setl cc=4 cuc hls') + call setline(1, ["xxyy", ""]) + norm! gg + exe "normal! /xxyy\<CR>" + norm! G + redraw! + let line_attr = s:screen_attr(1, [1, &cc]) + " Search wins over CursorColumn + call assert_equal(line_attr[1], line_attr[0]) + " Search wins over Colorcolumn + call assert_equal(line_attr[2], line_attr[3]) + call s:close_windows('setl hls&vim') +endfunc + func Test_illegal_byte_and_breakat() call s:test_windows("setl sbr= brk+=<") vert resize 18 diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim index ecd686743e..97638e9aac 100644 --- a/src/nvim/testdir/test_regexp_utf8.vim +++ b/src/nvim/testdir/test_regexp_utf8.vim @@ -109,12 +109,10 @@ func s:classes_test() call assert_equal('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', alnumchars) call assert_equal("\b", backspacechar) call assert_equal("\t ", blankchars) - " Commented out: it succeeds on Linux and Windows, but fails on macOs in Travis. - " call assert_equal("\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0b\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f\x7f", cntrlchars) + call assert_equal("\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0b\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f\x7f", cntrlchars) call assert_equal("0123456789", digitchars) call assert_equal("\<Esc>", escapechar) - " Commented out: it succeeds on Linux and Windows, but fails on macOs in Travis. - " call assert_equal('!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', graphchars) + call assert_equal('!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~', graphchars) call assert_equal('abcdefghijklmnopqrstuvwxyzµßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ', lowerchars) call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', printchars) call assert_equal('!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~', punctchars) @@ -168,3 +166,20 @@ func Test_eow_with_optional() call assert_equal(expected, actual) endfor endfunc + +func Test_reversed_range() + for re in range(0, 2) + exe 'set re=' . re + call assert_fails('call match("abc def", "[c-a]")', 'E944:') + endfor + set re=0 +endfunc + +func Test_large_class() + set re=1 + call assert_fails('call match("abc def", "[\u3000-\u4000]")', 'E945:') + set re=2 + call assert_equal(0, 'abc def' =~# '[\u3000-\u4000]') + call assert_equal(1, "\u3042" =~# '[\u3000-\u4000]') + set re=0 +endfunc diff --git a/src/nvim/testdir/test_scroll_opt.vim b/src/nvim/testdir/test_scroll_opt.vim new file mode 100644 index 0000000000..77920eb8b0 --- /dev/null +++ b/src/nvim/testdir/test_scroll_opt.vim @@ -0,0 +1,36 @@ +" Test for reset 'scroll' +" + +func Test_reset_scroll() + let scr = &l:scroll + + setlocal scroll=1 + setlocal scroll& + call assert_equal(scr, &l:scroll) + + setlocal scroll=1 + setlocal scroll=0 + call assert_equal(scr, &l:scroll) + + try + execute 'setlocal scroll=' . (winheight(0) + 1) + " not reached + call assert_false(1) + catch + call assert_exception('E49:') + endtry + + split + + let scr = &l:scroll + + setlocal scroll=1 + setlocal scroll& + call assert_equal(scr, &l:scroll) + + setlocal scroll=1 + setlocal scroll=0 + call assert_equal(scr, &l:scroll) + + quit! +endfunc diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim index d00eac9798..9e93a55eb0 100644 --- a/src/nvim/testdir/test_smartindent.vim +++ b/src/nvim/testdir/test_smartindent.vim @@ -1,3 +1,4 @@ +" Tests for smartindent " Tests for not doing smart indenting when it isn't set. function! Test_nosmartindent() @@ -12,3 +13,29 @@ function! Test_nosmartindent() call assert_equal(" #test", getline(1)) enew! | close endfunction + +function MyIndent() +endfunction + +" When 'indentexpr' is set, setting 'si' has no effect. +function Test_smartindent_has_no_effect() + new + exe "normal! i\<Tab>one\<Esc>" + set noautoindent + set smartindent + set indentexpr= + exe "normal! Gotwo\<Esc>" + call assert_equal("\ttwo", getline("$")) + + set indentexpr=MyIndent + exe "normal! Gothree\<Esc>" + call assert_equal("three", getline("$")) + + delfunction! MyIndent + set autoindent& + set smartindent& + set indentexpr& + bwipe! +endfunction + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim index 8465fe7d45..ebdfc250aa 100644 --- a/src/nvim/testdir/test_syntax.vim +++ b/src/nvim/testdir/test_syntax.vim @@ -301,11 +301,19 @@ func Test_syntax_arg_skipped() syn clear endfunc - -func Test_invalid_arg() + +func Test_syntax_invalid_arg() call assert_fails('syntax case asdf', 'E390:') - call assert_fails('syntax conceal asdf', 'E390:') + if has('conceal') + call assert_fails('syntax conceal asdf', 'E390:') + endif call assert_fails('syntax spell asdf', 'E390:') + call assert_fails('syntax clear @ABCD', 'E391:') + call assert_fails('syntax include @Xxx', 'E397:') + call assert_fails('syntax region X start="{"', 'E399:') + call assert_fails('syntax sync x', 'E404:') + call assert_fails('syntax keyword Abc a[', 'E789:') + call assert_fails('syntax keyword Abc a[bc]d', 'E890:') endfunc func Test_syn_sync() @@ -346,6 +354,50 @@ func Test_invalid_name() hi clear @Wrong endfunc +func Test_ownsyntax() + new Xfoo + call setline(1, '#define FOO') + syntax on + set filetype=c + ownsyntax perl + call assert_equal('perlComment', synIDattr(synID(line('.'), col('.'), 1), 'name')) + call assert_equal('c', b:current_syntax) + call assert_equal('perl', w:current_syntax) + + " A new split window should have the original syntax. + split + call assert_equal('cDefine', synIDattr(synID(line('.'), col('.'), 1), 'name')) + call assert_equal('c', b:current_syntax) + call assert_equal(0, exists('w:current_syntax')) + + wincmd x + call assert_equal('perlComment', synIDattr(synID(line("."), col("."), 1), "name")) + + syntax off + set filetype& + %bw! +endfunc + +func Test_ownsyntax_completion() + call feedkeys(":ownsyntax java\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"ownsyntax java javacc javascript', @:) +endfunc + +func Test_highlight_invalid_arg() + if has('gui_running') + call assert_fails('hi XXX guifg=xxx', 'E254:') + endif + call assert_fails('hi DoesNotExist', 'E411:') + call assert_fails('hi link', 'E412:') + call assert_fails('hi link a', 'E412:') + call assert_fails('hi link a b c', 'E413:') + call assert_fails('hi XXX =', 'E415:') + call assert_fails('hi XXX cterm', 'E416:') + call assert_fails('hi XXX cterm=', 'E417:') + call assert_fails('hi XXX cterm=DoesNotExist', 'E418:') + call assert_fails('hi XXX ctermfg=DoesNotExist', 'E421:') + call assert_fails('hi XXX xxx=White', 'E423:') +endfunc func Test_conceal() if !has('conceal') @@ -382,3 +434,4 @@ func Test_conceal() set conceallevel& bw! endfunc + diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 65957626cb..25c39587f4 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -405,6 +405,10 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data) { got_winch = true; UI *ui = data; + if (tui_is_stopped(ui)) { + return; + } + update_size(ui); ui_schedule_refresh(); } @@ -845,7 +849,7 @@ CursorShape tui_cursor_decode_shape(const char *shape_str) static cursorentry_T decode_cursor_entry(Dictionary args) { - cursorentry_T r; + cursorentry_T r = shape_table[0]; for (size_t i = 0; i < args.size; i++) { char *key = args.items[i].key.data; diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 42366fdb76..21dd6ec0dd 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -535,14 +535,18 @@ Array ui_array(void) { Array all_uis = ARRAY_DICT_INIT; for (size_t i = 0; i < ui_count; i++) { - Dictionary dic = ARRAY_DICT_INIT; - PUT(dic, "width", INTEGER_OBJ(uis[i]->width)); - PUT(dic, "height", INTEGER_OBJ(uis[i]->height)); - PUT(dic, "rgb", BOOLEAN_OBJ(uis[i]->rgb)); + UI *ui = uis[i]; + Dictionary info = ARRAY_DICT_INIT; + PUT(info, "width", INTEGER_OBJ(ui->width)); + PUT(info, "height", INTEGER_OBJ(ui->height)); + PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb)); for (UIExtension j = 0; j < kUIExtCount; j++) { - PUT(dic, ui_ext_names[j], BOOLEAN_OBJ(uis[i]->ui_ext[j])); + PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j])); + } + if (ui->inspect) { + ui->inspect(ui, &info); } - ADD(all_uis, DICTIONARY_OBJ(dic)); + ADD(all_uis, DICTIONARY_OBJ(info)); } return all_uis; } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 48896a6a3f..6b04e9c67a 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -36,6 +36,7 @@ struct ui_t { #endif void (*event)(UI *ui, char *name, Array args, bool *args_consumed); void (*stop)(UI *ui); + void (*inspect)(UI *ui, Dictionary *info); }; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index a8bbeea035..56db124a46 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -163,3 +163,28 @@ static void ui_bridge_suspend_event(void **argv) UI *ui = UI(argv[0]); ui->suspend(ui); } + +static void ui_bridge_option_set(UI *ui, String name, Object value) +{ + String copy_name = copy_string(name); + Object *copy_value = xmalloc(sizeof(Object)); + *copy_value = copy_object(value); + UI_BRIDGE_CALL(ui, option_set, 4, ui, copy_name.data, + INT2PTR(copy_name.size), copy_value); + // TODO(bfredl): when/if TUI/bridge teardown is refactored to use events, the + // commit that introduced this special case can be reverted. + // For now this is needed for nvim_list_uis(). + if (strequal(name.data, "termguicolors")) { + ui->rgb = value.data.boolean; + } +} +static void ui_bridge_option_set_event(void **argv) +{ + UI *ui = UI(argv[0]); + String name = (String){ .data = argv[1], .size = (size_t)argv[2] }; + Object value = *(Object *)argv[3]; + ui->option_set(ui, name, value); + api_free_string(name); + api_free_object(value); + xfree(argv[3]); +} diff --git a/src/nvim/version.c b/src/nvim/version.c index 17f89a25d2..be160e678e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -145,7 +145,7 @@ static const int included_patches[] = { // 1497, // 1496, // 1495, - // 1494, + 1494, 1493, // 1492, // 1491, @@ -167,7 +167,7 @@ static const int included_patches[] = { 1475, // 1474, // 1473, - // 1472, + 1472, // 1471, // 1470, // 1469, @@ -328,7 +328,7 @@ static const int included_patches[] = { // 1314, // 1313, // 1312, - // 1311, + 1311, // 1310, // 1309, // 1308, @@ -405,9 +405,9 @@ static const int included_patches[] = { // 1237, // 1236, // 1235, - // 1234, + 1234, // 1233, - // 1232, + 1232, // 1231, 1230, 1229, @@ -442,13 +442,13 @@ static const int included_patches[] = { 1200, // 1199, // 1198, - // 1197, + 1197, // 1196, // 1195, // 1194, // 1193, // 1192, - // 1191, + 1191, // 1190, 1189, 1188, @@ -458,8 +458,8 @@ static const int included_patches[] = { // 1184, // 1183, // 1182, - // 1181, - // 1180, + 1181, + 1180, // 1179, // 1178, // 1177, @@ -489,7 +489,7 @@ static const int included_patches[] = { // 1153, // 1152, // 1151, - // 1150, + 1150, // 1149, // 1148, // 1147, @@ -498,7 +498,7 @@ static const int included_patches[] = { // 1144, // 1143, // 1142, - // 1141, + 1141, // 1140, // 1139, // 1138, @@ -518,7 +518,7 @@ static const int included_patches[] = { // 1124, // 1123, // 1122, - // 1121, + 1121, // 1120, // 1119, // 1118, @@ -714,7 +714,7 @@ static const int included_patches[] = { // 928, // 927, // 926, - // 925, + 925, // 924, // 923, // 922, @@ -758,7 +758,7 @@ static const int included_patches[] = { // 884, // 883, // 882, - // 881, + 881, // 880, // 879, // 878, @@ -1077,11 +1077,11 @@ static const int included_patches[] = { 565, 564, // 563, - // 562, + 562, 561, // 560, - // 559, - // 558, + 559, + 558, // 557, // 556, 555, @@ -1120,30 +1120,30 @@ static const int included_patches[] = { // 522, // 521, // 520, - // 519, + 519, 518, 517, - // 516, - // 515, + 516, + 515, // 514, 513, // 512, - // 511, + 511, // 510, // 509, // 508, - // 507, + 507, // 506, - // 505, + 505, // 504, - // 503, + 503, 502, // 501, 500, 499, 498, - // 497, - // 496, + 497, + 496, 495, // 494, // 493, @@ -1175,36 +1175,36 @@ static const int included_patches[] = { // 467, // 466, 465, - // 464, - // 463, + 464, + 463, // 462, 461, - // 460, + 460, 459, 458, 457, - // 456, + 456, // 455, - // 454, + 454, 453, // 452, // 451, - // 450, + 450, // 449, 448, - // 447, + 447, 446, // 445, 444, 443, 442, - // 441, + 441, 440, 439, - // 438, + 438, 437, // 436, - // 435, + 435, 434, 433, // 432, @@ -1220,23 +1220,23 @@ static const int included_patches[] = { // 422, 421, 420, - // 419, + 419, // 418, 417, - // 416, - // 415, + 416, + 415, // 414, // 413, // 412, // 411, // 410, - // 409, + 409, 408, 407, 406, 405, 404, - // 403, + 403, 402, // 401, 400, @@ -1255,20 +1255,20 @@ static const int included_patches[] = { 387, // 386, 385, - // 384, - // 383, - // 382, + 384, + 383, + 382, 381, 380, 379, 378, 377, 376, - // 375, + 375, 374, // 373, // 372, - // 371, + 371, // 370, // 369, // 368, @@ -1277,27 +1277,27 @@ static const int included_patches[] = { // 365, 364, // 363, - // 362, + 362, // 361, 360, 359, 358, 357, - // 356, + 356, // 355, - // 354, + 354, 353, 352, 351, // 350, // 349, - // 348, + 348, 347, // 346, 345, 344, 343, - // 342, + 342, 341, // 340, 339, @@ -1307,10 +1307,10 @@ static const int included_patches[] = { 335, 334, 333, - // 332, + 332, 331, 330, - // 329, + 329, 328, 327, 326, @@ -1318,16 +1318,16 @@ static const int included_patches[] = { 324, 323, 322, - // 321, + 321, 320, 319, - // 318, - // 317, + 318, + 317, 316, 315, 314, - // 313, - // 312, + 313, + 312, 311, 310, 309, @@ -1335,7 +1335,7 @@ static const int included_patches[] = { 307, 306, 305, - // 304, + 304, // 303, 302, 301, @@ -1378,7 +1378,7 @@ static const int included_patches[] = { // 264, 263, 262, - // 261, + 261, 260, 259, 258, |