aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/ui.c7
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/api/vim.c8
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/misc1.c3
-rw-r--r--src/nvim/option.c7
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/regexp.c17
-rw-r--r--src/nvim/regexp_nfa.c5
-rw-r--r--src/nvim/screen.c3
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_cmdline.vim4
-rw-r--r--src/nvim/testdir/test_functions.vim415
-rw-r--r--src/nvim/testdir/test_listlbr_utf8.vim15
-rw-r--r--src/nvim/testdir/test_regexp_utf8.vim23
-rw-r--r--src/nvim/testdir/test_scroll_opt.vim36
-rw-r--r--src/nvim/testdir/test_smartindent.vim27
-rw-r--r--src/nvim/testdir/test_syntax.vim59
-rw-r--r--src/nvim/tui/tui.c6
-rw-r--r--src/nvim/ui.c16
-rw-r--r--src/nvim/ui.h1
-rw-r--r--src/nvim/ui_bridge.c25
-rw-r--r--src/nvim/version.c120
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,