diff options
-rw-r--r-- | runtime/autoload/dist/ft.vim | 11 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 10 | ||||
-rw-r--r-- | runtime/filetype.vim | 16 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 2 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 55 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 31 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 33 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 8 | ||||
-rw-r--r-- | src/nvim/path.c | 48 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 10 | ||||
-rw-r--r-- | src/nvim/screen.c | 19 | ||||
-rw-r--r-- | src/nvim/testdir/test_filetype.vim | 42 | ||||
-rw-r--r-- | src/nvim/testdir/test_let.vim | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 62 | ||||
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 11 | ||||
-rw-r--r-- | test/functional/ui/tabline_spec.lua | 43 | ||||
-rw-r--r-- | test/unit/eval/typval_spec.lua | 2 |
18 files changed, 341 insertions, 75 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index 1ac74b5785..ac80659113 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -172,6 +172,17 @@ func dist#ft#FTent() setf dtd endfunc +func dist#ft#ExCheck() + let lines = getline(1, min([line("$"), 100])) + if exists('g:filetype_euphoria') + exe 'setf ' . g:filetype_euphoria + elseif match(lines, '^--\|^ifdef\>\|^include\>') > -1 + setf euphoria3 + else + setf elixir + endif +endfunc + func dist#ft#EuphoriaCheck() if exists('g:filetype_euphoria') exe 'setf ' . g:filetype_euphoria diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index b385cab36f..e7be14e732 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -631,11 +631,13 @@ Tabline Events *ui-tabline* Activated by the `ext_tabline` |ui-option|. -["tabline_update", curtab, tabs] +["tabline_update", curtab, tabs, curbuf, buffers] Tabline was updated. UIs should present this data in a custom tabline - widget. - curtab: Current Tabpage - tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...] + widget. Note: options `curbuf` + `buffers` were added in API7. + curtab: Current Tabpage + tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...] + curbuf: Current buffer handle. + buffers: List of Dicts [{ "buffer": buffer handle, "name": String}, ...] ============================================================================== Cmdline Events *ui-cmdline* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 09a1d1d0e6..2617d8ffc0 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -389,7 +389,7 @@ au BufNewFile,BufRead *.cfm,*.cfi,*.cfc setf cf " Configure scripts au BufNewFile,BufRead configure.in,configure.ac setf config -" CUDA Cumpute Unified Device Architecture +" CUDA Compute Unified Device Architecture au BufNewFile,BufRead *.cu,*.cuh setf cuda " Dockerfilb; Podman uses the same syntax with name Containerfile @@ -404,8 +404,15 @@ au BufNewFile,BufRead *enlightenment/*.cfg setf c " Eterm au BufNewFile,BufRead *Eterm/*.cfg setf eterm +" Elixir or Euphoria +au BufNewFile,BufRead *.ex call dist#ft#ExCheck() + +" Elixir +au BufRead,BufNewFile mix.lock,*.exs setf elixir +au BufRead,BufNewFile *.eex,*.leex setf eelixir + " Euphoria 3 or 4 -au BufNewFile,BufRead *.eu,*.ew,*.ex,*.exu,*.exw call dist#ft#EuphoriaCheck() +au BufNewFile,BufRead *.eu,*.ew,*.exu,*.exw call dist#ft#EuphoriaCheck() if has("fname_case") au BufNewFile,BufRead *.EU,*.EW,*.EX,*.EXU,*.EXW call dist#ft#EuphoriaCheck() endif @@ -851,6 +858,9 @@ au BufNewFile,BufRead *.jov,*.j73,*.jovial setf jovial " JSON au BufNewFile,BufRead *.json,*.jsonp,*.webmanifest setf json +" JSON Patch (RFC 6902) +au BufNewFile,BufRead *.json-patch setf json + " Jupyter Notebook is also json au BufNewFile,BufRead *.ipynb setf json @@ -1495,7 +1505,7 @@ au BufNewFile,BufRead *.sass setf sass au BufNewFile,BufRead *.sa setf sather " Scala -au BufNewFile,BufRead *.scala setf scala +au BufNewFile,BufRead *.scala,*.sc setf scala " SBT - Scala Build Tool au BufNewFile,BufRead *.sbt setf sbt diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 08437063a3..195e3a0e65 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1153,7 +1153,7 @@ function M.stylize_markdown(bufnr, contents, opts) table.insert(highlights, { ft = match.ft; start = start + 1; - finish = #stripped + 1 - 1; + finish = #stripped; }) else table.insert(stripped, line) diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 11e21a88ea..35d39a34d7 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -130,7 +130,8 @@ void popupmenu_hide(void) void popupmenu_select(Integer selected) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; -void tabline_update(Tabpage current, Array tabs) +void tabline_update(Tabpage current, Array tabs, + Buffer current_buffer, Array buffers) FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; void cmdline_show(Array content, Integer pos, String firstc, String prompt, diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 1b78147ec2..ff019d1e07 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2340,10 +2340,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name), &tv, &di, true, false) == OK) { if ((di == NULL - || (!var_check_ro(di->di_flags, (const char *)lp->ll_name, - TV_CSTRING) - && !tv_check_lock(di->di_tv.v_lock, (const char *)lp->ll_name, - TV_CSTRING))) + || (!var_check_ro(di->di_flags, lp->ll_name, TV_CSTRING) + && !tv_check_lock(&di->di_tv, lp->ll_name, TV_CSTRING))) && eexe_mod_op(&tv, rettv, op) == OK) { set_var(lp->ll_name, lp->ll_name_len, &tv, false); } @@ -2353,10 +2351,10 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, set_var_const(lp->ll_name, lp->ll_name_len, rettv, copy, is_const); } *endp = cc; - } else if (tv_check_lock(lp->ll_newkey == NULL - ? lp->ll_tv->v_lock - : lp->ll_tv->vval.v_dict->dv_lock, - (const char *)lp->ll_name, TV_CSTRING)) { + } else if (var_check_lock(lp->ll_newkey == NULL + ? lp->ll_tv->v_lock + : lp->ll_tv->vval.v_dict->dv_lock, + lp->ll_name, TV_CSTRING)) { } else if (lp->ll_range) { listitem_T *ll_li = lp->ll_li; int ll_n1 = lp->ll_n1; @@ -2369,9 +2367,8 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, // Check whether any of the list items is locked for (ri = tv_list_first(rettv->vval.v_list); ri != NULL && ll_li != NULL; ) { - if (tv_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, - (const char *)lp->ll_name, - TV_CSTRING)) { + if (var_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name, + TV_CSTRING)) { return; } ri = TV_LIST_ITEM_NEXT(rettv->vval.v_list, ri); @@ -2795,13 +2792,13 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, } else if ((lp->ll_list != NULL // ll_list is not NULL when lvalue is not in a list, NULL lists // yield E689. - && tv_check_lock(tv_list_locked(lp->ll_list), - (const char *)lp->ll_name, - lp->ll_name_len)) + && var_check_lock(tv_list_locked(lp->ll_list), + lp->ll_name, + lp->ll_name_len)) || (lp->ll_dict != NULL - && tv_check_lock(lp->ll_dict->dv_lock, - (const char *)lp->ll_name, - lp->ll_name_len))) { + && var_check_lock(lp->ll_dict->dv_lock, + lp->ll_name, + lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { assert(lp->ll_list != NULL); @@ -2810,9 +2807,9 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, listitem_T *last_li = first_li; for (;;) { listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li); - if (tv_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, - (const char *)lp->ll_name, - lp->ll_name_len)) { + if (var_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, + lp->ll_name, + lp->ll_name_len)) { return false; } lp->ll_li = li; @@ -2897,11 +2894,11 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit) dictitem_T *const di = TV_DICT_HI2DI(hi); if (var_check_fixed(di->di_flags, (const char *)name, TV_CSTRING) || var_check_ro(di->di_flags, (const char *)name, TV_CSTRING) - || tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { + || var_check_lock(d->dv_lock, name, TV_CSTRING)) { return FAIL; } - if (tv_check_lock(d->dv_lock, (const char *)name, TV_CSTRING)) { + if (var_check_lock(d->dv_lock, name, TV_CSTRING)) { return FAIL; } @@ -5962,14 +5959,14 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) if (argvars[0].v_type == VAR_LIST) { tv_copy(&argvars[0], rettv); if ((l = argvars[0].vval.v_list) == NULL - || (!map && tv_check_lock(tv_list_locked(l), arg_errmsg, - TV_TRANSLATE))) { + || (!map + && var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) { return; } } else if (argvars[0].v_type == VAR_DICT) { tv_copy(&argvars[0], rettv); if ((d = argvars[0].vval.v_dict) == NULL - || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) { + || (!map && var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) { return; } } else { @@ -6002,7 +5999,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) di = TV_DICT_HI2DI(hi); if (map - && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE) + && (var_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE) || var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) { break; } @@ -6029,8 +6026,8 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) for (listitem_T *li = tv_list_first(l); li != NULL;) { if (map - && tv_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg, - TV_TRANSLATE)) { + && var_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg, + TV_TRANSLATE)) { break; } vimvars[VV_KEY].vv_nr = idx; @@ -8947,7 +8944,7 @@ static void set_var_const(const char *name, const size_t name_len, // existing variable, need to clear the value if (var_check_ro(v->di_flags, name, name_len) - || tv_check_lock(v->di_tv.v_lock, name, name_len)) { + || var_check_lock(v->di_tv.v_lock, name, name_len)) { return; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4f9a9fcd68..1ba31bfe68 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -268,7 +268,8 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; // Default: failed. if (argvars[0].v_type == VAR_LIST) { list_T *const l = argvars[0].vval.v_list; - if (!tv_check_lock(tv_list_locked(l), N_("add() argument"), TV_TRANSLATE)) { + if (!var_check_lock(tv_list_locked(l), N_("add() argument"), + TV_TRANSLATE)) { tv_list_append_tv(l, &argvars[1]); tv_copy(&argvars[0], rettv); } @@ -2277,9 +2278,9 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) list = argvars[0].vval.v_list; if (list != NULL - && !tv_check_lock(tv_list_locked(list), - N_("flatten() argument"), - TV_TRANSLATE) + && !var_check_lock(tv_list_locked(list), + N_("flatten() argument"), + TV_TRANSLATE) && tv_list_flatten(list, maxdepth) == OK) { tv_copy(&argvars[0], rettv); } @@ -2299,7 +2300,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) list_T *const l1 = argvars[0].vval.v_list; list_T *const l2 = argvars[1].vval.v_list; - if (!tv_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (!var_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { before = (long)tv_get_number_chk(&argvars[2], &error); @@ -2328,13 +2329,13 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) dict_T *const d1 = argvars[0].vval.v_dict; dict_T *const d2 = argvars[1].vval.v_dict; if (d1 == NULL) { - const bool locked = tv_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + const bool locked = var_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); (void)locked; assert(locked == true); } else if (d2 == NULL) { // Do nothing tv_copy(&argvars[0], rettv); - } else if (!tv_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + } else if (!var_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { const char *action = "force"; // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { @@ -4845,8 +4846,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "insert()"); - } else if (!tv_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - N_("insert() argument"), TV_TRANSLATE)) { + } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), + N_("insert() argument"), TV_TRANSLATE)) { long before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); @@ -7079,7 +7080,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { EMSG2(_(e_toomanyarg), "remove()"); } else if ((d = argvars[0].vval.v_dict) != NULL - && !tv_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { + && !var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { const char *key = tv_get_string_chk(&argvars[1]); if (key != NULL) { di = tv_dict_find(d, key, -1); @@ -7098,8 +7099,8 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listdictarg), "remove()"); - } else if (!tv_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - arg_errmsg, TV_TRANSLATE)) { + } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), + arg_errmsg, TV_TRANSLATE)) { bool error = false; idx = tv_get_number_chk(&argvars[1], &error); @@ -7374,8 +7375,8 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) list_T *l; if (argvars[0].v_type != VAR_LIST) { EMSG2(_(e_listarg), "reverse()"); - } else if (!tv_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - N_("reverse() argument"), TV_TRANSLATE)) { + } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), + N_("reverse() argument"), TV_TRANSLATE)) { tv_list_reverse(l); tv_list_set_ret(rettv, l); } @@ -9462,7 +9463,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); } else { list_T *const l = argvars[0].vval.v_list; - if (tv_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { + if (var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { goto theend; } tv_list_set_ret(rettv, l); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 4275ff7c61..7221dc8bc9 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1994,7 +1994,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, } else if (*action == 'f' && di2 != di1) { typval_T oldtv; - if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) + if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { break; } @@ -2625,7 +2625,7 @@ bool tv_islocked(const typval_T *const tv) /// /// Also gives an error message when typval is locked. /// -/// @param[in] lock Lock status. +/// @param[in] tv Typval. /// @param[in] name Variable name, used in the error message. /// @param[in] name_len Variable name length. Use #TV_TRANSLATE to translate /// variable name and compute the length. Use #TV_CSTRING @@ -2639,10 +2639,37 @@ bool tv_islocked(const typval_T *const tv) /// gettext. /// /// @return true if variable is locked, false otherwise. -bool tv_check_lock(const VarLockStatus lock, const char *name, +bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len) FUNC_ATTR_WARN_UNUSED_RESULT { + VarLockStatus lock = VAR_UNLOCKED; + + switch (tv->v_type) { + // case VAR_BLOB: + // if (tv->vval.v_blob != NULL) + // lock = tv->vval.v_blob->bv_lock; + // break; + case VAR_LIST: + if (tv->vval.v_list != NULL) { + lock = tv->vval.v_list->lv_lock; + } + break; + case VAR_DICT: + if (tv->vval.v_dict != NULL) { + lock = tv->vval.v_dict->dv_lock; + } + break; + default: + break; + } + return var_check_lock(tv->v_lock, name, name_len) + || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len)); +} + +/// @return true if variable "name" is locked (immutable) +bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len) +{ const char *error_message = NULL; switch (lock) { case VAR_UNLOCKED: { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f5d1b1e870..5ffc06ec44 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2455,13 +2455,13 @@ void ex_function(exarg_T *eap) goto erret; } if (fudi.fd_di == NULL) { - if (tv_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, - TV_CSTRING)) { + if (var_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't add a function to a locked dictionary goto erret; } - } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, - TV_CSTRING)) { + } else if (var_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't change an existing function if it is locked goto erret; } diff --git a/src/nvim/path.c b/src/nvim/path.c index fe50be5ea1..6ac24182cc 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -180,6 +180,34 @@ const char *path_next_component(const char *fname) return fname; } +/// Returns the length of the path head on the current platform. +/// @return +/// - 3 on windows +/// - 1 otherwise +int path_head_length(void) +{ +#ifdef WIN32 + return 3; +#else + return 1; +#endif +} + +/// Returns true if path begins with characters denoting the head of a path +/// (e.g. '/' on linux and 'D:' on windows). +/// @param path The path to be checked. +/// @return +/// - True if path begins with a path head +/// - False otherwise +bool is_path_head(const char_u *path) +{ +#ifdef WIN32 + return isalpha(path[0]) && path[1] == ':'; +#else + return vim_ispathsep(*path); +#endif +} + /// Get a pointer to one character past the head of a path name. /// Unix: after "/"; Win: after "c:\" /// If there is no head, path is returned. @@ -189,7 +217,7 @@ char_u *get_past_head(const char_u *path) #ifdef WIN32 // May skip "c:" - if (isalpha(path[0]) && path[1] == ':') { + if (is_path_head(path)) { retval = path + 2; } #endif @@ -1991,10 +2019,24 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name) assert(dir_name != NULL); size_t len = strlen((char *)dir_name); + + // If dir_name is a path head, full_path can always be made relative. + if (len == (size_t)path_head_length() && is_path_head(dir_name)) { + return full_path + len; + } + + // If full_path and dir_name do not match, it's impossible to make one + // relative to the other. + if (fnamencmp(dir_name, full_path, len) != 0) { + return NULL; + } + char_u *p = full_path + len; - if (fnamencmp(dir_name, full_path, len) != 0 - || !vim_ispathsep(*p)) { + // If *p is not pointing to a path separator, this means that full_path's + // last directory name is longer than *dir_name's last directory, so they + // don't actually match. + if (!vim_ispathsep(*p)) { return NULL; } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3e8d623ed4..71624baaf4 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3925,7 +3925,15 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) int qf_winid = 0; if (IS_LL_STACK(qi)) { - qf_winid = curwin->handle; + if (curwin->w_llist == qi) { + win = curwin; + } else { + win = qf_find_win_with_loclist(qi); + if (win == NULL) { + return; + } + } + qf_winid = (int)win->handle; } if (old_last == NULL) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 04157a0154..3446a944cd 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -7211,7 +7211,24 @@ void ui_ext_tabline_update(void) ADD(tabs, DICTIONARY_OBJ(tab_info)); } - ui_call_tabline_update(curtab->handle, tabs); + + Array buffers = ARRAY_DICT_INIT; + FOR_ALL_BUFFERS(buf) { + // Do not include unlisted buffers + if (!buf->b_p_bl) { + continue; + } + + Dictionary buffer_info = ARRAY_DICT_INIT; + PUT(buffer_info, "buffer", BUFFER_OBJ(buf->handle)); + + get_trans_bufname(buf); + PUT(buffer_info, "name", STRING_OBJ(cstr_to_string((char *)NameBuff))); + + ADD(buffers, DICTIONARY_OBJ(buffer_info)); + } + + ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers); } /* diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 71a7a2cce5..eb6151fbe1 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -161,6 +161,8 @@ let s:filename_checks = { \ 'ecd': ['file.ecd'], \ 'edif': ['file.edf', 'file.edif', 'file.edo'], \ 'elinks': ['elinks.conf'], + \ 'elixir': ['file.ex', 'file.exs', 'mix.lock'], + \ 'eelixir': ['file.eex', 'file.leex'], \ 'elm': ['file.elm'], \ 'elmfilt': ['filter-rules'], \ 'epuppet': ['file.epp'], @@ -257,7 +259,7 @@ let s:filename_checks = { \ 'jgraph': ['file.jgr'], \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'], - \ 'json': ['file.json', 'file.jsonp', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb'], + \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb'], \ 'jsp': ['file.jsp'], \ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'], \ 'kivy': ['file.kv'], @@ -422,7 +424,7 @@ let s:filename_checks = { \ 'sass': ['file.sass'], \ 'sather': ['file.sa'], \ 'sbt': ['file.sbt'], - \ 'scala': ['file.scala'], + \ 'scala': ['file.scala', 'file.sc'], \ 'scheme': ['file.scm', 'file.ss', 'file.rkt'], \ 'scilab': ['file.sci', 'file.sce'], \ 'screen': ['.screenrc', 'screenrc'], @@ -765,5 +767,41 @@ func Test_pp_file() filetype off endfunc +func Test_ex_file() + filetype on + + call writefile(['arbitrary content'], 'Xfile.ex') + split Xfile.ex + call assert_equal('elixir', &filetype) + bwipe! + let g:filetype_euphoria = 'euphoria4' + split Xfile.ex + call assert_equal('euphoria4', &filetype) + bwipe! + unlet g:filetype_euphoria + + call writefile(['-- filetype euphoria comment'], 'Xfile.ex') + split Xfile.ex + call assert_equal('euphoria3', &filetype) + bwipe! + + call writefile(['--filetype euphoria comment'], 'Xfile.ex') + split Xfile.ex + call assert_equal('euphoria3', &filetype) + bwipe! + + call writefile(['ifdef '], 'Xfile.ex') + split Xfile.ex + call assert_equal('euphoria3', &filetype) + bwipe! + + call writefile(['include '], 'Xfile.ex') + split Xfile.ex + call assert_equal('euphoria3', &filetype) + bwipe! + + call delete('Xfile.ex') + filetype off +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_let.vim b/src/nvim/testdir/test_let.vim index a5cbd8f6a6..6cb736a38a 100644 --- a/src/nvim/testdir/test_let.vim +++ b/src/nvim/testdir/test_let.vim @@ -126,11 +126,16 @@ endfunction func s:set_varg7(...) abort let b = a:000 - call add(b, 1) + let b += [1] endfunction func s:set_varg8(...) abort let b = a:000 + call add(b, 1) +endfunction + +func s:set_varg9(...) abort + let b = a:000 let b[0][0] = 1 endfunction @@ -142,7 +147,8 @@ func Test_let_varg_fail() call s:set_varg5([0]) call assert_fails('call s:set_varg6(1)', 'E742:') call assert_fails('call s:set_varg7(1)', 'E742:') - call s:set_varg8([0]) + call assert_fails('call s:set_varg8(1)', 'E742:') + call s:set_varg9([0]) endfunction func Test_let_utf8_environment() diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index c63613ab1b..6bd64caa6c 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -891,7 +891,7 @@ func Test_efm1() Xtestfile:9: parse error before `asd' make: *** [vim] Error 1 in file "Xtestfile" linenr 10: there is an error - + 2 returned "Xtestfile", line 11 col 1; this is an error "Xtestfile", line 12 col 2; this is another error @@ -914,7 +914,7 @@ func Test_efm1() x should be a dot xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 ^ - + Does anyone know what is the problem and how to correction it? "Xtestfile", line 21 col 9: What is the title of the quickfix window? "Xtestfile", line 22 col 9: What is the title of the quickfix window? @@ -5138,4 +5138,62 @@ func Test_qftextfunc() call Xtest_qftextfunc('l') endfunc +" Test for updating a location list for some other window and check that +" 'qftextfunc' uses the correct location list. +func Test_qftextfunc_other_loclist() + %bw! + call setloclist(0, [], 'f') + + " create a window and a location list for it and open the location list + " window + lexpr ['F1:10:12:one', 'F1:20:14:two'] + let w1_id = win_getid() + call setloclist(0, [], ' ', + \ {'lines': ['F1:10:12:one', 'F1:20:14:two'], + \ 'quickfixtextfunc': + \ {d -> map(getloclist(d.winid, {'id' : d.id, + \ 'items' : 1}).items[d.start_idx-1:d.end_idx-1], + \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}}) + lwindow + let w2_id = win_getid() + + " create another window and a location list for it and open the location + " list window + topleft new + let w3_id = win_getid() + call setloclist(0, [], ' ', + \ {'lines': ['F2:30:32:eleven', 'F2:40:34:twelve'], + \ 'quickfixtextfunc': + \ {d -> map(getloclist(d.winid, {'id' : d.id, + \ 'items' : 1}).items[d.start_idx-1:d.end_idx-1], + \ "'Ligne ' .. v:val.lnum .. ', Colonne ' .. v:val.col")}}) + lwindow + let w4_id = win_getid() + + topleft new + lexpr ['F3:50:52:green', 'F3:60:54:blue'] + let w5_id = win_getid() + + " change the location list for some other window + call setloclist(0, [], 'r', {'lines': ['F3:55:56:aaa', 'F3:57:58:bbb']}) + call setloclist(w1_id, [], 'r', {'lines': ['F1:62:63:bbb', 'F1:64:65:ccc']}) + call setloclist(w3_id, [], 'r', {'lines': ['F2:76:77:ddd', 'F2:78:79:eee']}) + call assert_equal(['Line 62, Col 63', 'Line 64, Col 65'], + \ getbufline(winbufnr(w2_id), 1, '$')) + call assert_equal(['Ligne 76, Colonne 77', 'Ligne 78, Colonne 79'], + \ getbufline(winbufnr(w4_id), 1, '$')) + call setloclist(w2_id, [], 'r', {'lines': ['F1:32:33:fff', 'F1:34:35:ggg']}) + call setloclist(w4_id, [], 'r', {'lines': ['F2:46:47:hhh', 'F2:48:49:jjj']}) + call assert_equal(['Line 32, Col 33', 'Line 34, Col 35'], + \ getbufline(winbufnr(w2_id), 1, '$')) + call assert_equal(['Ligne 46, Colonne 47', 'Ligne 48, Colonne 49'], + \ getbufline(winbufnr(w4_id), 1, '$')) + + call win_gotoid(w5_id) + lwindow + call assert_equal(['F3|55 col 56| aaa', 'F3|57 col 58| bbb'], + \ getline(1, '$')) + %bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index e62d3bb66b..93d71a9e45 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -101,6 +101,17 @@ describe('autocmd', function() }, eval('g:evs')) end) + it('WinClosed from root directory', function() + command('cd /') + command('let g:evs = []') + command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("<afile>")])') + command('new') + command('close') + eq({ + {'WinClosed', '1001'}, + }, eval('g:evs')) + end) + it('v:vim_did_enter is 1 after VimEnter', function() eq(1, eval('v:vim_did_enter')) end) diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua index 23aae81745..ab8d63cda1 100644 --- a/test/functional/ui/tabline_spec.lua +++ b/test/functional/ui/tabline_spec.lua @@ -4,14 +4,17 @@ local clear, command, eq = helpers.clear, helpers.command, helpers.eq describe('ui/ext_tabline', function() local screen - local event_tabs, event_curtab + local event_tabs, event_curtab, event_curbuf, event_buffers before_each(function() clear() screen = Screen.new(25, 5) screen:attach({rgb=true, ext_tabline=true}) - function screen:_handle_tabline_update(curtab, tabs) - event_curtab, event_tabs = curtab, tabs + function screen:_handle_tabline_update(curtab, tabs, curbuf, buffers) + event_curtab = curtab + event_tabs = tabs + event_curbuf = curbuf + event_buffers = buffers end end) @@ -45,4 +48,38 @@ describe('ui/ext_tabline', function() eq(expected_tabs, event_tabs) end} end) + + it('buffer UI events', function() + local expected_buffers_initial= { + {buffer = { id = 1 }, name = '[No Name]'}, + } + + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + | + ]], condition=function() + eq({ id = 1}, event_curbuf) + eq(expected_buffers_initial, event_buffers) + end} + + command("badd another-buffer") + command("bnext") + + local expected_buffers = { + {buffer = { id = 2 }, name = 'another-buffer'}, + } + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + | + ]], condition=function() + eq({ id = 2 }, event_curbuf) + eq(expected_buffers, event_buffers) + end} + end) end) diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index 7c03005529..d81e272877 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -2623,7 +2623,7 @@ describe('typval.c', function() describe('check_lock()', function() local function tv_check_lock(lock, name, name_len, emsg) return check_emsg(function() - return lib.tv_check_lock(lock, name, name_len) + return lib.var_check_lock(lock, name, name_len) end, emsg) end itp('works', function() |