# HG changeset patch # User Christian Brabandt # Date 1487346305 -3600 # Node ID 5780bd3a5a7e37c388e4832e0429a6a3bb509dc1 # Parent 46008b393de11a4631ba04ebe35eb3a43a531fdd patch 8.0.0334: can't access b:changedtick from a dict reference commit https://github.com/vim/vim/commit/79518e2ace5fce7b9c49060e462a6e935dba0a84 Author: Bram Moolenaar Date: Fri Feb 17 16:31:35 2017 +0100 patch 8.0.0334: can't access b:changedtick from a dict reference Problem: Can't access b:changedtick from a dict reference. Solution: Make changedtick a member of the b: dict. (inspired by neovim #6112) diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -2099,6 +2099,7 @@ test_arglist \ test_cdo \ test_channel \ test_charsearch \ + test_changedtick \ test_cmdline \ test_command_count \ test_crypt \ diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -832,6 +832,7 @@ free_buffer(buf_T *buf) free_buffer_stuff(buf, TRUE); #ifdef FEAT_EVAL unref_var_dict(buf->b_vars); + buf->b_changedtick = &buf->b_ct_val; #endif #ifdef FEAT_LUA lua_buffer_free(buf); @@ -873,6 +874,29 @@ free_buffer(buf_T *buf) } /* + * Initializes buf->b_changedtick. + */ + static void +init_changedtick(buf_T *buf) +{ +#ifdef FEAT_EVAL + dictitem_T *di = dictitem_alloc((char_u *)"changedtick"); + + if (di != NULL) + { + di->di_flags |= DI_FLAGS_LOCK | DI_FLAGS_FIX | DI_FLAGS_RO; + di->di_tv.v_type = VAR_NUMBER; + di->di_tv.v_lock = VAR_FIXED; + di->di_tv.vval.v_number = 0; + dict_add(buf->b_vars, di); + buf->b_changedtick = &di->di_tv.vval.v_number; + } + else +#endif + buf->b_changedtick = &buf->b_ct_val; +} + +/* * Free stuff in the buffer for ":bdel" and when wiping out the buffer. */ static void @@ -889,8 +913,14 @@ free_buffer_stuff( #endif } #ifdef FEAT_EVAL - vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */ - hash_init(&buf->b_vars->dv_hashtab); + { + varnumber_T tick = *buf->b_changedtick; + + vars_clear(&buf->b_vars->dv_hashtab); /* free all buffer variables */ + hash_init(&buf->b_vars->dv_hashtab); + init_changedtick(buf); + *buf->b_changedtick = tick; + } #endif #ifdef FEAT_USR_CMDS uc_clear(&buf->b_ucmds); /* clear local user commands */ @@ -1979,6 +2009,7 @@ buflist_new( } init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); #endif + init_changedtick(buf); } if (ffname != NULL) diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -1668,7 +1668,7 @@ ins_redraw( #ifdef FEAT_AUTOCMD /* Trigger TextChangedI if b_changedtick differs. */ if (ready && has_textchangedI() - && last_changedtick != curbuf->b_changedtick + && last_changedtick != *curbuf->b_changedtick # ifdef FEAT_INS_EXPAND && !pum_visible() # endif @@ -1677,7 +1677,7 @@ ins_redraw( if (last_changedtick_buf == curbuf) apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); last_changedtick_buf = curbuf; - last_changedtick = curbuf->b_changedtick; + last_changedtick = *curbuf->b_changedtick; } #endif diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -1451,14 +1451,8 @@ list_glob_vars(int *first) static void list_buf_vars(int *first) { - char_u numbuf[NUMBUFLEN]; - list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:", TRUE, first); - - sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick); - list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, - numbuf, first); } /* @@ -1806,20 +1800,6 @@ ex_let_one( } /* - * If "arg" is equal to "b:changedtick" give an error and return TRUE. - */ - int -check_changedtick(char_u *arg) -{ - if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13])) - { - EMSG2(_(e_readonlyvar), arg); - return TRUE; - } - return FALSE; -} - -/* * Get an lval: variable, Dict item or List item that can be assigned a value * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", * "name.key", "name.key[expr]" etc. @@ -2208,32 +2188,29 @@ set_var_lval( if (lp->ll_tv == NULL) { - if (!check_changedtick(lp->ll_name)) - { - cc = *endp; - *endp = NUL; - if (op != NULL && *op != '=') - { - typval_T tv; - - /* handle +=, -= and .= */ - di = NULL; - if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), - &tv, &di, TRUE, FALSE) == OK) - { - if ((di == NULL - || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) - && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, - FALSE))) - && tv_op(&tv, rettv, op) == OK) - set_var(lp->ll_name, &tv, FALSE); - clear_tv(&tv); - } - } - else - set_var(lp->ll_name, rettv, copy); - *endp = cc; - } + cc = *endp; + *endp = NUL; + if (op != NULL && *op != '=') + { + typval_T tv; + + /* handle +=, -= and .= */ + di = NULL; + if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), + &tv, &di, TRUE, FALSE) == OK) + { + if ((di == NULL + || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) + && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, + FALSE))) + && tv_op(&tv, rettv, op) == OK) + set_var(lp->ll_name, &tv, FALSE); + clear_tv(&tv); + } + } + else + set_var(lp->ll_name, rettv, copy); + *endp = cc; } else if (tv_check_lock(lp->ll_newkey == NULL ? lp->ll_tv->v_lock @@ -2776,9 +2753,7 @@ do_unlet_var( *name_end = NUL; /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) - ret = FAIL; - else if (do_unlet(lp->ll_name, forceit) == FAIL) + if (do_unlet(lp->ll_name, forceit) == FAIL) ret = FAIL; *name_end = cc; } @@ -2904,21 +2879,16 @@ do_lock_var( *name_end = NUL; /* Normal name or expanded name. */ - if (check_changedtick(lp->ll_name)) + di = find_var(lp->ll_name, NULL, TRUE); + if (di == NULL) ret = FAIL; else { - di = find_var(lp->ll_name, NULL, TRUE); - if (di == NULL) - ret = FAIL; + if (lock) + di->di_flags |= DI_FLAGS_LOCK; else - { - if (lock) - di->di_flags |= DI_FLAGS_LOCK; - else - di->di_flags &= ~DI_FLAGS_LOCK; - item_lock(&di->di_tv, deep, lock); - } + di->di_flags &= ~DI_FLAGS_LOCK; + item_lock(&di->di_tv, deep, lock); } *name_end = cc; } @@ -3139,11 +3109,6 @@ get_user_var_name(expand_T *xp, int idx) ++hi; return cat_prefix_varname('b', hi->hi_key); } - if (bdone == ht->ht_used) - { - ++bdone; - return (char_u *)"b:changedtick"; - } /* w: variables */ ht = &curwin->w_vars->dv_hashtab; @@ -6815,7 +6780,6 @@ get_var_tv( { int ret = OK; typval_T *tv = NULL; - typval_T atv; dictitem_T *v; int cc; @@ -6824,27 +6788,14 @@ get_var_tv( name[len] = NUL; /* - * Check for "b:changedtick". - */ - if (STRCMP(name, "b:changedtick") == 0) - { - atv.v_type = VAR_NUMBER; - atv.vval.v_number = curbuf->b_changedtick; - tv = &atv; - } - - /* * Check for user-defined variables. */ - else - { - v = find_var(name, NULL, no_autoload); - if (v != NULL) - { - tv = &v->di_tv; - if (dip != NULL) - *dip = v; - } + v = find_var(name, NULL, no_autoload); + if (v != NULL) + { + tv = &v->di_tv; + if (dip != NULL) + *dip = v; } if (tv == NULL) diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2539,7 +2539,7 @@ f_diff_hlID(typval_T *argvars UNUSED, ty #ifdef FEAT_DIFF linenr_T lnum = get_tv_lnum(argvars); static linenr_T prev_lnum = 0; - static int changedtick = 0; + static varnumber_T changedtick = 0; static int fnum = 0; static int change_start = 0; static int change_end = 0; @@ -2550,7 +2550,7 @@ f_diff_hlID(typval_T *argvars UNUSED, ty if (lnum < 0) /* ignore type error in {lnum} arg */ lnum = 0; if (lnum != prev_lnum - || changedtick != curbuf->b_changedtick + || changedtick != *curbuf->b_changedtick || fnum != curbuf->b_fnum) { /* New line, buffer, change: need to get the values. */ @@ -2572,7 +2572,7 @@ f_diff_hlID(typval_T *argvars UNUSED, ty else hlID = (hlf_T)0; prev_lnum = lnum; - changedtick = curbuf->b_changedtick; + changedtick = *curbuf->b_changedtick; fnum = curbuf->b_fnum; } @@ -3957,7 +3957,7 @@ get_buffer_info(buf_T *buf) dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL); dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL); dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL); - dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL); + dict_add_nr_str(dict, "changedtick", *buf->b_changedtick, NULL); dict_add_nr_str(dict, "hidden", buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, NULL); @@ -4190,12 +4190,6 @@ f_getbufvar(typval_T *argvars, typval_T /* buffer-local-option */ done = TRUE; } - else if (STRCMP(varname, "changedtick") == 0) - { - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = curbuf->b_changedtick; - done = TRUE; - } else { /* Look up the variable. */ @@ -6576,21 +6570,16 @@ f_islocked(typval_T *argvars, typval_T * { if (lv.ll_tv == NULL) { - if (check_changedtick(lv.ll_name)) - rettv->vval.v_number = 1; /* always locked */ - else + di = find_var(lv.ll_name, NULL, TRUE); + if (di != NULL) { - di = find_var(lv.ll_name, NULL, TRUE); - if (di != NULL) - { - /* Consider a variable locked when: - * 1. the variable itself is locked - * 2. the value of the variable is locked. - * 3. the List or Dict value is locked. - */ - rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) - || tv_islocked(&di->di_tv)); - } + /* Consider a variable locked when: + * 1. the variable itself is locked + * 2. the value of the variable is locked. + * 3. the List or Dict value is locked. + */ + rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) + || tv_islocked(&di->di_tv)); } } else if (lv.ll_range) @@ -11551,8 +11540,8 @@ f_submatch(typval_T *argvars, typval_T * return; if (no < 0 || no >= NSUBEXP) { - EMSGN(_("E935: invalid submatch number: %d"), no); - return; + EMSGN(_("E935: invalid submatch number: %d"), no); + return; } if (argvars[1].v_type != VAR_UNKNOWN) retList = (int)get_tv_number_chk(&argvars[1], &error); diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -626,7 +626,7 @@ do_exmode( int save_msg_scroll; int prev_msg_row; linenr_T prev_line; - int changedtick; + varnumber_T changedtick; if (improved) exmode_active = EXMODE_VIM; @@ -660,7 +660,7 @@ do_exmode( need_wait_return = FALSE; ex_pressedreturn = FALSE; ex_no_reprint = FALSE; - changedtick = curbuf->b_changedtick; + changedtick = *curbuf->b_changedtick; prev_msg_row = msg_row; prev_line = curwin->w_cursor.lnum; if (improved) @@ -673,7 +673,7 @@ do_exmode( lines_left = Rows - 1; if ((prev_line != curwin->w_cursor.lnum - || changedtick != curbuf->b_changedtick) && !ex_no_reprint) + || changedtick != *curbuf->b_changedtick) && !ex_no_reprint) { if (curbuf->b_ml.ml_flags & ML_EMPTY) EMSG(_(e_emptybuf)); diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -4926,9 +4926,9 @@ restore_backup: #ifdef FEAT_AUTOCMD /* buf->b_changedtick is always incremented in unchanged() but that * should not trigger a TextChanged event. */ - if (last_changedtick + 1 == buf->b_changedtick + if (last_changedtick + 1 == *buf->b_changedtick && last_changedtick_buf == buf) - last_changedtick = buf->b_changedtick; + last_changedtick = *buf->b_changedtick; #endif u_unchanged(buf); u_update_save_nr(buf); diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -1088,7 +1088,7 @@ EXTERN pos_T last_cursormoved /* f = INIT_POS_T(0, 0, 0) # endif ; -EXTERN int last_changedtick INIT(= 0); /* for TextChanged event */ +EXTERN varnumber_T last_changedtick INIT(= 0); /* for TextChanged event */ EXTERN buf_T *last_changedtick_buf INIT(= NULL); #endif diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -1164,13 +1164,13 @@ main_loop( #ifdef FEAT_AUTOCMD /* Trigger TextChanged if b_changedtick differs. */ if (!finish_op && has_textchanged() - && last_changedtick != curbuf->b_changedtick) + && last_changedtick != *curbuf->b_changedtick) { if (last_changedtick_buf == curbuf) apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf); last_changedtick_buf = curbuf; - last_changedtick = curbuf->b_changedtick; + last_changedtick = *curbuf->b_changedtick; } #endif @@ -1388,11 +1388,11 @@ getout(int exitval) /* Autocmd must have close the buffer already, skip. */ continue; buf = wp->w_buffer; - if (buf->b_changedtick != -1) + if (buf->b_ct_val != -1) { apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf); - buf->b_changedtick = -1; /* note that we did it already */ + buf->b_ct_val = -1; /* note that we did it already */ /* start all over, autocommands may mess up the lists */ next_tp = first_tabpage; break; diff --git a/src/memline.c b/src/memline.c --- a/src/memline.c +++ b/src/memline.c @@ -1148,11 +1148,11 @@ ml_recover(void) len = (int)STRLEN(fname); if (len >= 4 && #if defined(VMS) - STRNICMP(fname + len - 4, "_s" , 2) + STRNICMP(fname + len - 4, "_s", 2) #else - STRNICMP(fname + len - 4, ".s" , 2) + STRNICMP(fname + len - 4, ".s", 2) #endif - == 0 + == 0 && vim_strchr((char_u *)"UVWuvw", fname[len - 2]) != NULL && ASCII_ISALPHA(fname[len - 1])) { @@ -1649,7 +1649,7 @@ ml_recover(void) if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) { changed_int(); - ++curbuf->b_changedtick; + ++*curbuf->b_changedtick; } } else @@ -1663,7 +1663,7 @@ ml_recover(void) if (i != 0) { changed_int(); - ++curbuf->b_changedtick; + ++*curbuf->b_changedtick; break; } } diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -492,7 +492,7 @@ get_breakindent_win( static int prev_indent = 0; /* cached indent value */ static long prev_ts = 0L; /* cached tabstop value */ static char_u *prev_line = NULL; /* cached pointer to line */ - static int prev_tick = 0; /* changedtick of cached value */ + static varnumber_T prev_tick = 0; /* changedtick of cached value */ int bri = 0; /* window width minus window margin space, i.e. what rests for text */ const int eff_wwidth = W_WIDTH(wp) @@ -502,11 +502,11 @@ get_breakindent_win( /* used cached indent, unless pointer or 'tabstop' changed */ if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts - || prev_tick != wp->w_buffer->b_changedtick) + || prev_tick != *wp->w_buffer->b_changedtick) { prev_line = line; prev_ts = wp->w_buffer->b_p_ts; - prev_tick = wp->w_buffer->b_changedtick; + prev_tick = *wp->w_buffer->b_changedtick; prev_indent = get_indent_str(line, (int)wp->w_buffer->b_p_ts, wp->w_p_list); } @@ -2768,7 +2768,7 @@ changed(void) } changed_int(); } - ++curbuf->b_changedtick; + ++*curbuf->b_changedtick; } /* @@ -3195,7 +3195,7 @@ unchanged( need_maketitle = TRUE; /* set window title later */ #endif } - ++buf->b_changedtick; + ++*buf->b_changedtick; #ifdef FEAT_NETBEANS_INTG netbeans_unmodified(buf); #endif diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -25,7 +25,6 @@ void *call_func_retlist(char_u *func, in int eval_foldexpr(char_u *arg, int *cp); void ex_let(exarg_T *eap); void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first); -int check_changedtick(char_u *arg); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); void clear_lval(lval_T *lp); void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1916,7 +1916,9 @@ struct file_buffer int b_changed; /* 'modified': Set to TRUE if something in the file has been changed and not written out. */ - int b_changedtick; /* incremented for each change, also for undo */ + varnumber_T *b_changedtick; /* points into b:changedtick or b_ct_val; + incremented for each change, also for undo */ + varnumber_T b_ct_val; /* fallback for b:changedtick */ int b_saving; /* Set to TRUE if we are in the middle of saving the buffer. */ diff --git a/src/syntax.c b/src/syntax.c --- a/src/syntax.c +++ b/src/syntax.c @@ -503,7 +503,7 @@ syntax_start(win_T *wp, linenr_T lnum) linenr_T parsed_lnum; linenr_T first_stored; int dist; - static int changedtick = 0; /* remember the last change ID */ + static varnumber_T changedtick = 0; /* remember the last change ID */ #ifdef FEAT_CONCEAL current_sub_char = NUL; @@ -516,13 +516,13 @@ syntax_start(win_T *wp, linenr_T lnum) */ if (syn_block != wp->w_s || syn_buf != wp->w_buffer - || changedtick != syn_buf->b_changedtick) + || changedtick != *syn_buf->b_changedtick) { invalidate_current_state(); syn_buf = wp->w_buffer; syn_block = wp->w_s; } - changedtick = syn_buf->b_changedtick; + changedtick = *syn_buf->b_changedtick; syn_win = wp; /* diff --git a/src/testdir/test91.in b/src/testdir/test91.in --- a/src/testdir/test91.in +++ b/src/testdir/test91.in @@ -1,4 +1,4 @@ -Tests for getbufvar(), getwinvar(), gettabvar() and gettabwinvar(). +Tests for getwinvar(), gettabvar() and gettabwinvar(). vim: set ft=vim : STARTTEST @@ -10,34 +10,7 @@ STARTTEST :let t:testvar='abcd' :$put =string(gettabvar(1,'testvar')) :$put =string(gettabvar(1,'testvar')) -:" Test for getbufvar() -:let b:var_num = '1234' -:let def_num = '5678' -:$put =string(getbufvar(1, 'var_num')) -:$put =string(getbufvar(1, 'var_num', def_num)) -:$put =string(getbufvar(1, '')) -:$put =string(getbufvar(1, '', def_num)) -:unlet b:var_num -:$put =string(getbufvar(1, 'var_num', def_num)) -:$put =string(getbufvar(1, '')) -:$put =string(getbufvar(1, '', def_num)) -:$put =string(getbufvar(9, '')) -:$put =string(getbufvar(9, '', def_num)) -:unlet def_num -:$put =string(getbufvar(1, '&autoindent')) -:$put =string(getbufvar(1, '&autoindent', 1)) :" -:" Open new window with forced option values -:set fileformats=unix,dos -:new ++ff=dos ++bin ++enc=iso-8859-2 -:let otherff = getbufvar(bufnr('%'), '&fileformat') -:let otherbin = getbufvar(bufnr('%'), '&bin') -:let otherfenc = getbufvar(bufnr('%'), '&fenc') -:close -:$put =otherff -:$put =string(otherbin) -:$put =otherfenc -:unlet otherff otherbin otherfenc :" test for getwinvar() :let w:var_str = "Dance" :let def_str = "Chance" diff --git a/src/testdir/test91.ok b/src/testdir/test91.ok --- a/src/testdir/test91.ok +++ b/src/testdir/test91.ok @@ -1,20 +1,6 @@ start: 'abcd' 'abcd' -'1234' -'1234' -{'var_num': '1234'} -{'var_num': '1234'} -'5678' -{} -{} -'' -'5678' -0 -0 -dos -1 -iso-8859-2 'Dance' 'Dance' {'var_str': 'Dance'} diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -3,10 +3,11 @@ source test_assign.vim source test_autocmd.vim +source test_changedtick.vim source test_cursor_func.vim source test_delete.vim +source test_ex_undo.vim source test_execute_func.vim -source test_ex_undo.vim source test_expand.vim source test_expr.vim source test_expand_dllpath.vim diff --git a/src/testdir/test_changedtick.vim b/src/testdir/test_changedtick.vim new file mode 100644 --- /dev/null +++ b/src/testdir/test_changedtick.vim @@ -0,0 +1,45 @@ +" Tests for b:changedtick + +func Test_changedtick_increments() + new + " New buffer has an empty line, tick starts at 2. + let expected = 2 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + call setline(1, 'hello') + let expected += 1 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + undo + " Somehow undo counts as two changes. + let expected += 2 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + bwipe! +endfunc + +func Test_changedtick_dict_entry() + let d = b: + call assert_equal(b:changedtick, d['changedtick']) +endfunc + +func Test_changedtick_bdel() + new + let bnr = bufnr('%') + let v = b:changedtick + bdel + " Delete counts as a change too. + call assert_equal(v + 1, getbufvar(bnr, 'changedtick')) +endfunc + +func Test_changedtick_fixed() + call assert_fails('let b:changedtick = 4', 'E46') + call assert_fails('let b:["changedtick"] = 4', 'E46') + + call assert_fails('unlet b:changedtick', 'E795') + call assert_fails('unlet b:["changedtick"]', 'E46') + + let d = b: + call assert_fails('unlet d["changedtick"]', 'E46') + +endfunc diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -424,3 +424,45 @@ func! Test_mode() bwipe! iunmap endfunc + +func Test_getbufvar() + let bnr = bufnr('%') + let b:var_num = '1234' + let def_num = '5678' + call assert_equal('1234', getbufvar(bnr, 'var_num')) + call assert_equal('1234', getbufvar(bnr, 'var_num', def_num)) + + let bd = getbufvar(bnr, '') + call assert_equal('1234', bd['var_num']) + call assert_true(exists("bd['changedtick']")) + call assert_equal(2, len(bd)) + + let bd2 = getbufvar(bnr, '', def_num) + call assert_equal(bd, bd2) + + unlet b:var_num + call assert_equal(def_num, getbufvar(bnr, 'var_num', def_num)) + call assert_equal('', getbufvar(bnr, 'var_num')) + + let bd = getbufvar(bnr, '') + call assert_equal(1, len(bd)) + let bd = getbufvar(bnr, '',def_num) + call assert_equal(1, len(bd)) + + call assert_equal('', getbufvar(9, '')) + call assert_equal(def_num, getbufvar(9, '', def_num)) + unlet def_num + + call assert_equal(0, getbufvar(1, '&autoindent')) + call assert_equal(0, getbufvar(1, '&autoindent', 1)) + + " Open new window with forced option values + set fileformats=unix,dos + new ++ff=dos ++bin ++enc=iso-8859-2 + call assert_equal('dos', getbufvar(bufnr('%'), '&fileformat')) + call assert_equal(1, getbufvar(bufnr('%'), '&bin')) + call assert_equal('iso-8859-2', getbufvar(bufnr('%'), '&fenc')) + close + + set fileformats& +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 334, +/**/ 333, /**/ 332,