diff options
62 files changed, 631 insertions, 474 deletions
diff --git a/man/nvim.1 b/man/nvim.1 index 9e7da629f7..305551c7d4 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -113,9 +113,6 @@ associated with a file. To overwrite a file, add an exclamation mark to the relevant Ex command, such as .Ic :w! . .Ic ":help 'readonly'" -.It Fl Z -Restricted mode. -Disable commands that make use of an external shell. .It Fl m Resets the 'write' option, to disable file modifications. Writing to a file is disabled, but buffers can still be modified. diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim index dab88fde23..5008b8cfaf 100644 --- a/runtime/autoload/man.vim +++ b/runtime/autoload/man.vim @@ -13,8 +13,6 @@ function! man#init() abort try " Check for -l support. call s:get_page(s:get_path('', 'man')) - catch /E145:/ - " Ignore the error in restricted mode catch /command error .*/ let s:localfile_arg = v:false endtry diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index 20eaa47b26..2a972483ff 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -20,8 +20,7 @@ additionally sets up for viewing the differences between the arguments. > nvim -d file1 file2 [file3 [file4]] -In addition to the |-d| argument, |-R| may be used for readonly mode -respectively. +In addition to the |-d| argument, |-R| may be used for readonly mode. The second and following arguments may also be a directory name. Vim will then append the file name of the first argument to the directory name to find diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index ac24f22bc6..0f15aefd17 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -416,8 +416,8 @@ Aliases: gvimdiff (GUI) rgview (GUI) rgvim (GUI) - rview (alias for "nvim -RZ") - rvim (alias for "nvim -Z") + rview + rvim view (alias for "nvim -R") vimdiff (alias for "nvim -d" |diff-mode|) @@ -496,6 +496,7 @@ Startup: --literal (file args are always literal; to expand wildcards on Windows, use |:n| e.g. `nvim +"n *"`) Easy mode: eview, evim, nvim -y + Restricted mode: rview, rvim, nvim -Z Vi mode: nvim -v Test functions: diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 4e617052a9..4e54bcaefd 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -692,12 +692,21 @@ au BufNewFile,BufRead .gtkrc,gtkrc setf gtkrc au BufNewFile,BufRead *.haml setf haml " Hamster Classic | Playground files -au BufNewFile,BufRead *.hsc,*.hsm setf hamster +au BufNewFile,BufRead *.hsm setf hamster +au BufNewFile,BufRead *.hsc + \ if match(join(getline(1,10), "\n"), '\%(^\|\n\)\s*\%({-#\_s*LANGUAGE\>\|\<module\>\)') != -1 | + \ setf haskell | + \ else | + \ setf hamster | + \ endif " Haskell au BufNewFile,BufRead *.hs,*.hs-boot setf haskell au BufNewFile,BufRead *.lhs setf lhaskell au BufNewFile,BufRead *.chs setf chaskell +au BufNewFile,BufRead cabal.project setf cabalproject +au BufNewFile,BufRead $HOME/.cabal/config setf cabalconfig +au BufNewFile,BufRead cabal.config setf cabalconfig " Haste au BufNewFile,BufRead *.ht setf haste @@ -2042,12 +2051,14 @@ au BufNewFile,BufRead bzr_log.* setf bzr " Bazel build file if !has("fname_case") - au BufNewFile,BufRead *.BUILD,BUILD setf bzl + au BufNewFile,BufRead *.BUILD,BUILD setf bzl endif " BIND zone au BufNewFile,BufRead */named/db.*,*/bind/db.* call s:StarSetf('bindzone') +au BufNewFile,BufRead cabal.project.* call s:StarSetf('cabalproject') + " Calendar au BufNewFile,BufRead */.calendar/*, \*/share/calendar/*/calendar.*,*/share/calendar/calendar.* diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index cf822782d8..710885d295 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -212,6 +212,9 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err) /// @param ns_id number of namespace for this highlight /// @param name highlight group name, like ErrorMsg /// @param val highlight definiton map, like |nvim_get_hl_by_name|. +/// in addition the following keys are also recognized: +/// `default`: don't override existing definition, +/// like `hi default` /// @param[out] err Error details, if any /// /// TODO: ns_id = 0, should modify :highlight namespace @@ -249,7 +252,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err) // event path for redraws caused by "fast" events. This could tie in with // better throttling of async events causing redraws, such as non-batched // nvim_buf_set_extmark calls from async contexts. - if (!updating_screen && !ns_hl_changed) { + if (!provider_active && !ns_hl_changed) { multiqueue_put(main_loop.events, on_redraw_event, 0); } ns_hl_changed = true; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 93fe37b585..dba02a67e8 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1132,12 +1132,6 @@ struct VimMenu { vimmenu_T *next; ///< Next item in menu }; -typedef struct { - int wb_startcol; - int wb_endcol; - vimmenu_T *wb_menu; -} winbar_item_T; - /// Structure which contains all information that belongs to a window. /// /// All row numbers are relative to the start of the window, except w_winrow. @@ -1354,10 +1348,6 @@ struct window_S { char_u *w_localdir; /* absolute path of local directory or NULL */ - vimmenu_T *w_winbar; // The root of the WinBar menu hierarchy. - winbar_item_T *w_winbar_items; // list of items in the WinBar - int w_winbar_height; // 1 if there is a window toolbar - // Options local to a window. // They are local because they influence the layout of the window or // depend on the window layout. diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index 90fdc3dc43..c5941ae2fe 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -58,6 +58,7 @@ typedef struct { EXTERN kvec_t(DecorProvider) decor_providers INIT(= KV_INITIAL_VALUE); EXTERN DecorState decor_state INIT(= { 0 }); +EXTERN bool provider_active INIT(= false); #define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ { ns_id, false, LUA_NOREF, LUA_NOREF, \ diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 45d2bf7a91..402211080b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1971,7 +1971,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, typval_T var2; int empty1 = FALSE; listitem_T *ni; - hashtab_T *ht; + hashtab_T *ht = NULL; int quiet = flags & GLV_QUIET; // Clear everything in "lp". @@ -2441,7 +2441,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, tv_copy(rettv, lp->ll_tv); } else { *lp->ll_tv = *rettv; - lp->ll_tv->v_lock = 0; + lp->ll_tv->v_lock = VAR_UNLOCKED; tv_init(rettv); } @@ -5458,7 +5458,7 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, } item = tv_dict_item_alloc((const char *)key); item->di_tv = tv; - item->di_tv.v_lock = 0; + item->di_tv.v_lock = VAR_UNLOCKED; if (tv_dict_add(d, item) == FAIL) { tv_dict_item_free(item); } @@ -6128,7 +6128,7 @@ static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) if (map) { // map(): replace the list item value. tv_clear(tv); - rettv.v_lock = 0; + rettv.v_lock = VAR_UNLOCKED; *tv = rettv; } else { bool error = false; @@ -6433,7 +6433,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow + 1); tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline); tv_dict_add_nr(dict, S_LEN("botline"), wp->w_botline - 1); - tv_dict_add_nr(dict, S_LEN("winbar"), wp->w_winbar_height); + tv_dict_add_nr(dict, S_LEN("winbar"), 0); tv_dict_add_nr(dict, S_LEN("width"), wp->w_width); tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1); @@ -9078,7 +9078,7 @@ static void set_var_const(const char *name, const size_t name_len, tv_copy(tv, &v->di_tv); } else { v->di_tv = *tv; - v->di_tv.v_lock = 0; + v->di_tv.v_lock = VAR_UNLOCKED; tv_init(tv); } @@ -9275,7 +9275,7 @@ int var_item_copy(const vimconv_T *const conv, tv_copy(from, to); } else { to->v_type = VAR_STRING; - to->v_lock = 0; + to->v_lock = VAR_UNLOCKED; if ((to->vval.v_string = string_convert((vimconv_T *)conv, from->vval.v_string, NULL)) @@ -9286,7 +9286,7 @@ int var_item_copy(const vimconv_T *const conv, break; case VAR_LIST: to->v_type = VAR_LIST; - to->v_lock = 0; + to->v_lock = VAR_UNLOCKED; if (from->vval.v_list == NULL) { to->vval.v_list = NULL; } else if (copyID != 0 && tv_list_copyid(from->vval.v_list) == copyID) { @@ -9302,7 +9302,7 @@ int var_item_copy(const vimconv_T *const conv, break; case VAR_DICT: to->v_type = VAR_DICT; - to->v_lock = 0; + to->v_lock = VAR_UNLOCKED; if (from->vval.v_dict == NULL) { to->vval.v_dict = NULL; } else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID) { @@ -10466,9 +10466,10 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, provider_call_nesting++; typval_T argvars[3] = { - {.v_type = VAR_STRING, .vval.v_string = (uint8_t *)method, .v_lock = 0}, - {.v_type = VAR_LIST, .vval.v_list = arguments, .v_lock = 0}, - {.v_type = VAR_UNKNOWN} + { .v_type = VAR_STRING, .vval.v_string = (char_u *)method, + .v_lock = VAR_UNLOCKED }, + { .v_type = VAR_LIST, .vval.v_list = arguments, .v_lock = VAR_UNLOCKED }, + { .v_type = VAR_UNKNOWN } }; typval_T rettv = { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED }; tv_list_ref(arguments); diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index eee40965e0..62a8022734 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2987,11 +2987,12 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) // illegal argument or getchar(0) and no char avail: return zero n = 0; } else { - // getchar(0) and char avail: return char + // getchar(0) and char avail() != NUL: get a character. + // Note that vpeekc_any() returns K_SPECIAL for K_IGNORE. n = safe_vgetc(); } - if (n == K_IGNORE) { + if (n == K_IGNORE || n == K_VER_SCROLLBAR || n == K_HOR_SCROLLBAR) { continue; } break; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ada6f78f10..b62820fecc 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -725,7 +725,7 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) list_T *l; tv->v_type = VAR_LIST; - + tv->v_lock = VAR_UNLOCKED; if (l1 == NULL && l2 == NULL) { l = NULL; } else if (l1 == NULL) { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index dc94bc698d..8daef00985 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -851,7 +851,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; tv_dict_add(&fc->l_vars, v); v->di_tv.v_type = VAR_DICT; - v->di_tv.v_lock = 0; + v->di_tv.v_lock = VAR_UNLOCKED; v->di_tv.vval.v_dict = selfdict; ++selfdict->dv_refcount; } diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 898ff4ebfe..b01cdde236 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -149,22 +149,22 @@ int hl_get_syn_attr(int ns_id, int idx, HlAttrs at_en) } } -static ColorKey colored_key(NS ns_id, int syn_id) -{ - return (ColorKey){ .ns_id = (int)ns_id, .syn_id = syn_id }; -} - void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id) { DecorProvider *p = get_provider(ns_id, true); + if ((attrs.rgb_ae_attr & HL_DEFAULT) + && map_has(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id))) { + return; + } int attr_id = link_id > 0 ? -1 : hl_get_syn_attr(ns_id, hl_id, attrs); ColorItem it = { .attr_id = attr_id, .link_id = link_id, - .version = p->hl_valid }; - map_put(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id), it); + .version = p->hl_valid, + .is_default = (attrs.rgb_ae_attr & HL_DEFAULT) }; + map_put(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id), it); } -int ns_get_hl(NS ns_id, int hl_id, bool link) +int ns_get_hl(NS ns_id, int hl_id, bool link, bool nodefault) { static int recursive = 0; @@ -176,7 +176,7 @@ int ns_get_hl(NS ns_id, int hl_id, bool link) } DecorProvider *p = get_provider(ns_id, true); - ColorItem it = map_get(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id)); + ColorItem it = map_get(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id)); // TODO(bfredl): map_ref true even this? bool valid_cache = it.version >= p->hl_valid; @@ -218,11 +218,16 @@ int ns_get_hl(NS ns_id, int hl_id, bool link) it.attr_id = fallback ? -1 : hl_get_syn_attr((int)ns_id, hl_id, attrs); it.version = p->hl_valid-tmp; - map_put(ColorKey, ColorItem)(ns_hl, colored_key(ns_id, hl_id), it); + it.is_default = attrs.rgb_ae_attr & HL_DEFAULT; + map_put(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id), it); + } + + if (it.is_default && nodefault) { + return -1; } if (link) { - return it.attr_id >= 0 ? -1 : it.link_id; + return it.attr_id >= 0 ? 0 : it.link_id; } else { return it.attr_id; } @@ -307,7 +312,7 @@ void update_window_hl(win_T *wp, bool invalid) // // haha, theme engine go brrr int normality = syn_check_group((const char_u *)S_LEN("Normal")); - int ns_attr = ns_get_hl(-1, normality, false); + int ns_attr = ns_get_hl(-1, normality, false, false); if (ns_attr > 0) { // TODO(bfredl): hantera NormalNC and so on wp->w_hl_attr_normal = ns_attr; @@ -793,6 +798,8 @@ HlAttrs dict2hlattrs(Dictionary dict, bool use_rgb, int *link_id, Error *err) { "undercurl", HL_UNDERCURL }, { "italic", HL_ITALIC }, { "reverse", HL_INVERSE }, + { "default", HL_DEFAULT }, + { "global", HL_GLOBAL }, { NULL, 0 }, }; diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h index 6a5c593ab1..2bda094d8e 100644 --- a/src/nvim/highlight_defs.h +++ b/src/nvim/highlight_defs.h @@ -22,6 +22,8 @@ typedef enum { HL_NOCOMBINE = 0x80, HL_BG_INDEXED = 0x0100, HL_FG_INDEXED = 0x0200, + HL_DEFAULT = 0x0400, + HL_GLOBAL = 0x0800, } HlAttrFlags; /// Stores a complete highlighting entry, including colors and attributes @@ -188,13 +190,16 @@ typedef struct { int ns_id; int syn_id; } ColorKey; +#define ColorKey(n, s) (ColorKey) { .ns_id = (int)(n), .syn_id = (s) } typedef struct { int attr_id; int link_id; int version; + bool is_default; } ColorItem; -#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1 } +#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, \ + .version = -1, .is_default = false } #endif // NVIM_HIGHLIGHT_DEFS_H diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 4ba2e36656..7094d3be90 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -55,16 +55,10 @@ static bool menu_is_winbar(const char_u *const name) return (STRNCMP(name, "WinBar", 6) == 0); } -int winbar_height(const win_T *const wp) - FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL -{ - return wp->w_winbar != NULL && wp->w_winbar->children != NULL ? 1 : 0; -} - static vimmenu_T **get_root_menu(const char_u *const name) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - return menu_is_winbar(name) ? &curwin->w_winbar : &root_menu; + return &root_menu; } /// Do the :menu command and relatives. @@ -191,10 +185,6 @@ ex_menu(exarg_T *eap) } vimmenu_T **root_menu_ptr = get_root_menu(menu_path); - if (root_menu_ptr == &curwin->w_winbar) { - // Assume the window toolbar menu will change. - redraw_later(curwin, NOT_VALID); - } if (enable != kNone) { // Change sensitivity of the menu. @@ -270,19 +260,6 @@ ex_menu(exarg_T *eap) xfree(map_buf); } - if (root_menu_ptr == &curwin->w_winbar) { - const int h = winbar_height(curwin); - - if (h != curwin->w_winbar_height) { - if (h == 0) { - curwin->w_height++; - } else if (curwin->w_height > 0) { - curwin->w_height--; - } - curwin->w_winbar_height = h; - } - } - ui_call_update_menu(); theend: @@ -661,14 +638,6 @@ remove_menu ( return OK; } -// Remove the WinBar menu from window "wp". -void remove_winbar(win_T *wp) - FUNC_ATTR_NONNULL_ALL -{ - remove_menu(&wp->w_winbar, (char_u *)"", MENU_ALL_MODES, true); - xfree(wp->w_winbar_items); -} - /* * Free the given menu structure and remove it from the linked list. */ @@ -937,7 +906,6 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) * Used when expanding menu names. */ static vimmenu_T *expand_menu = NULL; -static vimmenu_T *expand_menu_alt = NULL; static int expand_modes = 0x0; static int expand_emenu; /* TRUE for ":emenu" command */ @@ -992,8 +960,6 @@ char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forc return NULL; // TODO(vim): check for next command? } if (*p == NUL) { // Complete the menu name - bool try_alt_menu = true; - // With :unmenu, you only want to match menus for the appropriate mode. // With :menu though you might want to add a menu with the same name as // one in another mode, so match menus from other modes too. @@ -1025,10 +991,6 @@ char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forc break; } menu = menu->next; - if (menu == NULL && try_alt_menu) { - menu = curwin->w_winbar; - try_alt_menu = false; - } } if (menu == NULL) { /* No menu found with the name we were looking for */ @@ -1037,18 +999,12 @@ char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forc } name = p; menu = menu->children; - try_alt_menu = false; } xfree(path_name); xp->xp_context = expand_menus ? EXPAND_MENUNAMES : EXPAND_MENUS; xp->xp_pattern = after_dot; expand_menu = menu; - if (expand_menu == root_menu) { - expand_menu_alt = curwin->w_winbar; - } else { - expand_menu_alt = NULL; - } } else { // We're in the mapping part xp->xp_context = EXPAND_NOTHING; } @@ -1062,13 +1018,11 @@ char_u *set_context_in_menu_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forc char_u *get_menu_name(expand_T *xp, int idx) { static vimmenu_T *menu = NULL; - static bool did_alt_menu = false; char_u *str; static int should_advance = FALSE; if (idx == 0) { /* first call: start at first item */ menu = expand_menu; - did_alt_menu = false; should_advance = false; } @@ -1077,10 +1031,6 @@ char_u *get_menu_name(expand_T *xp, int idx) || menu_is_separator(menu->dname) || menu->children == NULL)) { menu = menu->next; - if (menu == NULL && !did_alt_menu) { - menu = expand_menu_alt; - did_alt_menu = true; - } } if (menu == NULL) /* at end of linked list */ @@ -1100,10 +1050,6 @@ char_u *get_menu_name(expand_T *xp, int idx) if (should_advance) { // Advance to next menu entry. menu = menu->next; - if (menu == NULL && !did_alt_menu) { - menu = expand_menu_alt; - did_alt_menu = true; - } } should_advance = !should_advance; @@ -1118,7 +1064,6 @@ char_u *get_menu_name(expand_T *xp, int idx) char_u *get_menu_names(expand_T *xp, int idx) { static vimmenu_T *menu = NULL; - static bool did_alt_menu = false; #define TBUFFER_LEN 256 static char_u tbuffer[TBUFFER_LEN]; /*hack*/ char_u *str; @@ -1126,7 +1071,6 @@ char_u *get_menu_names(expand_T *xp, int idx) if (idx == 0) { /* first call: start at first item */ menu = expand_menu; - did_alt_menu = false; should_advance = false; } @@ -1136,10 +1080,6 @@ char_u *get_menu_names(expand_T *xp, int idx) || (expand_emenu && menu_is_separator(menu->dname)) || menu->dname[STRLEN(menu->dname) - 1] == '.')) { menu = menu->next; - if (menu == NULL && !did_alt_menu) { - menu = expand_menu_alt; - did_alt_menu = true; - } } if (menu == NULL) /* at end of linked list */ @@ -1173,10 +1113,6 @@ char_u *get_menu_names(expand_T *xp, int idx) if (should_advance) { // Advance to next menu entry. menu = menu->next; - if (menu == NULL && !did_alt_menu) { - menu = expand_menu_alt; - did_alt_menu = true; - } } should_advance = !should_advance; @@ -1470,7 +1406,6 @@ static void execute_menu(const exarg_T *eap, vimmenu_T *menu) } } - // For the WinBar menu always use the Normal mode menu. if (idx == -1 || eap == NULL) { mode = (char_u *)"Normal"; idx = MENU_INDEX_NORMAL; @@ -1540,53 +1475,6 @@ void ex_emenu(exarg_T *eap) execute_menu(eap, menu); } -// Handle a click in the window toolbar of "wp" at column "col". -void winbar_click(win_T *wp, int col) - FUNC_ATTR_NONNULL_ALL -{ - if (wp->w_winbar_items == NULL) { - return; - } - for (int idx = 0; wp->w_winbar_items[idx].wb_menu != NULL; idx++) { - winbar_item_T *item = &wp->w_winbar_items[idx]; - - if (col >= item->wb_startcol && col <= item->wb_endcol) { - win_T *save_curwin = NULL; - const pos_T save_visual = VIsual; - const int save_visual_active = VIsual_active; - const int save_visual_select = VIsual_select; - const int save_visual_reselect = VIsual_reselect; - const int save_visual_mode = VIsual_mode; - - if (wp != curwin) { - // Clicking in the window toolbar of a not-current window. - // Make that window the current one and save Visual mode. - save_curwin = curwin; - VIsual_active = false; - curwin = wp; - curbuf = curwin->w_buffer; - check_cursor(); - } - - // Note: the command might close the current window. - execute_menu(NULL, item->wb_menu); - - if (save_curwin != NULL && win_valid(save_curwin)) { - curwin = save_curwin; - curbuf = curwin->w_buffer; - VIsual = save_visual; - VIsual_active = save_visual_active; - VIsual_select = save_visual_select; - VIsual_reselect = save_visual_reselect; - VIsual_mode = save_visual_mode; - } - if (!win_valid(wp)) { - break; - } - } - } -} - /* * Translation of menu names. Just a simple lookup table. */ diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index cff88de00b..f05dade73f 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -60,7 +60,6 @@ int jump_to_mouse(int flags, { static int on_status_line = 0; // #lines below bottom of window static int on_sep_line = 0; // on separator right of window - static bool in_winbar = false; static int prev_row = -1; static int prev_col = -1; static win_T *dragwin = NULL; // window being dragged @@ -101,18 +100,6 @@ retnomove: if (on_sep_line) { return IN_SEP_LINE; } - if (in_winbar) { - // A quick second click may arrive as a double-click, but we use it - // as a second click in the WinBar. - if ((mod_mask & MOD_MASK_MULTI_CLICK) && !(flags & MOUSE_RELEASED)) { - wp = mouse_find_win(&grid, &row, &col); - if (wp == NULL) { - return IN_UNKNOWN; - } - winbar_click(wp, col); - } - return IN_OTHER_WIN | MOUSE_WINBAR; - } if (flags & MOUSE_MAY_STOP_VIS) { end_visual_mode(); redraw_curbuf_later(INVERTED); // delete the inversion @@ -142,13 +129,8 @@ retnomove: dragwin = NULL; if (row == -1) { - // A click in the window toolbar does not enter another window or - // change Visual highlighting. - winbar_click(wp, col); - in_winbar = true; - return IN_OTHER_WIN | MOUSE_WINBAR; + return IN_OTHER_WIN; } - in_winbar = false; // winpos and height may change in win_enter()! if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) { @@ -239,9 +221,6 @@ retnomove: did_drag |= count; } return IN_SEP_LINE; // Cursor didn't move - } else if (in_winbar) { - // After a click on the window toolbar don't start Visual mode. - return IN_OTHER_WIN | MOUSE_WINBAR; } else { // keep_window_focus must be true // before moving the cursor for a left click, stop Visual mode @@ -503,7 +482,6 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp) // exist. FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp == fp->fr_win) { - *rowp -= wp->w_winbar_height; return wp; } } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 4b26ae259e..0293bb4a73 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1847,13 +1847,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) CancelRedo(); } else { (void)op_delete(oap); - if (oap->motion_type == kMTLineWise && has_format_option(FO_AUTO)) { - // cursor line wasn't saved yet - if (u_save_cursor() == FAIL) { - break; - } + // save cursor line for undo if it wasn't saved yet + if (oap->motion_type == kMTLineWise + && has_format_option(FO_AUTO) + && u_save_cursor() == OK) { + auto_format(false, true); } - auto_format(false, true); } break; @@ -2601,11 +2600,6 @@ do_mouse ( oap == NULL ? NULL : &(oap->inclusive), which_button); - // A click in the window toolbar has no side effects. - if (jump_flags & MOUSE_WINBAR) { - return false; - } - moved = (jump_flags & CURSOR_MOVED); in_status_line = (jump_flags & IN_STATUS_LINE); in_sep_line = (jump_flags & IN_SEP_LINE); diff --git a/src/nvim/option.c b/src/nvim/option.c index 0a91687352..146bce8cc0 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7173,46 +7173,6 @@ int get_sts_value(void) return (int)result; } -/// Check matchpairs option for "*initc". -/// If there is a match set "*initc" to the matching character and "*findc" to -/// the opposite character. Set "*backwards" to the direction. -/// When "switchit" is true swap the direction. -void find_mps_values(int *initc, int *findc, int *backwards, int switchit) -{ - char_u *ptr = curbuf->b_p_mps; - - while (*ptr != NUL) { - if (utf_ptr2char(ptr) == *initc) { - if (switchit) { - *findc = *initc; - *initc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); - *backwards = true; - } else { - *findc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); - *backwards = false; - } - return; - } - char_u *prev = ptr; - ptr += utfc_ptr2len(ptr) + 1; - if (utf_ptr2char(ptr) == *initc) { - if (switchit) { - *findc = *initc; - *initc = utf_ptr2char(prev); - *backwards = false; - } else { - *findc = utf_ptr2char(prev); - *backwards = true; - } - return; - } - ptr += utfc_ptr2len(ptr); - if (*ptr == ',') { - ptr++; - } - } -} - /// This is called when 'breakindentopt' is changed and when a window is /// initialized static bool briopt_check(win_T *wp) diff --git a/src/nvim/po/af.po b/src/nvim/po/af.po index 79048eac39..fa6674469c 100644 --- a/src/nvim/po/af.po +++ b/src/nvim/po/af.po @@ -1348,10 +1348,6 @@ msgstr "E143: Outobevele het nuwe buffer %s onverwags geskrap" msgid "E144: non-numeric argument to :z" msgstr "E144: nie-numeriese parameter vir :z" -#, fuzzy -#~ msgid "E145: Shell commands not allowed in restricted mode" -#~ msgstr "E145: Dop bevele nie toegelaat in rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Patrone kan nie deur letters afgebaken word nie" diff --git a/src/nvim/po/ca.po b/src/nvim/po/ca.po index 7e83cb08ed..be4206f36e 100644 --- a/src/nvim/po/ca.po +++ b/src/nvim/po/ca.po @@ -1234,10 +1234,6 @@ msgstr "E143: Una auto-ordre ha eliminat el buffer nou %s inesperadament" msgid "E144: non-numeric argument to :z" msgstr "E144: Argument no numèric per a :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Les ordres shell no estan permeses en l'rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Les expressions regulars no poden estar delimitades per lletres" diff --git a/src/nvim/po/cs.cp1250.po b/src/nvim/po/cs.cp1250.po index 26bdbe8c45..5b9f3d3a58 100644 --- a/src/nvim/po/cs.cp1250.po +++ b/src/nvim/po/cs.cp1250.po @@ -1249,10 +1249,6 @@ msgstr "E143: Automatické pøíkazy neoèekávanì smazaly nový buffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: neèíselný argument pro :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim nepovoluje použití pøíkazù shellu" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulární výrazy nesmí být oddìleny písmeny" diff --git a/src/nvim/po/cs.po b/src/nvim/po/cs.po index 986d6753a8..31a90dc514 100644 --- a/src/nvim/po/cs.po +++ b/src/nvim/po/cs.po @@ -1249,10 +1249,6 @@ msgstr "E143: Automatické pøíkazy neoèekávanì smazaly nový buffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: neèíselný argument pro :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim nepovoluje pou¾ití pøíkazù shellu" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulární výrazy nesmí být oddìleny písmeny" diff --git a/src/nvim/po/da.po b/src/nvim/po/da.po index 58cd19210b..f35272810b 100644 --- a/src/nvim/po/da.po +++ b/src/nvim/po/da.po @@ -980,9 +980,6 @@ msgstr "E143: Autokommandoer slettede uventede ny buffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: ikke-numerisk argument til :z" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Skalkommandoer er ikke tilladt i rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulære udtryk kan ikke afgrænses af bogstaver" diff --git a/src/nvim/po/de.po b/src/nvim/po/de.po index a6ba8476d8..a2e04965e5 100644 --- a/src/nvim/po/de.po +++ b/src/nvim/po/de.po @@ -3,7 +3,7 @@ # Do ":help uganda" in Vim to read copying and usage conditions. # Do ":help credits" in Vim to see a list of people who contributed. # -# Previous-Translator(s): +# Previous-Translator(s): # Johannes Zellner <johannes@zellner.org> # Gerfried Fuchs <alfie@ist.org> msgid "" @@ -659,10 +659,6 @@ msgstr "E143: Autokommandos löschten unerwartet neuen Puffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: Nicht-numerisches Argument für :z" -#: ../ex_cmds.c:3398 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Shell-Befehle sind in rvim nicht erlaubt" - #: ../ex_cmds.c:3492 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Reguläre Ausdrücke können nicht durch Buchstaben begrenzt werden" diff --git a/src/nvim/po/en_GB.po b/src/nvim/po/en_GB.po index 00a05195b4..7919fc8946 100644 --- a/src/nvim/po/en_GB.po +++ b/src/nvim/po/en_GB.po @@ -1194,10 +1194,6 @@ msgstr "" msgid "E144: non-numeric argument to :z" msgstr "" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regular expressions cannot be delimited by letters" diff --git a/src/nvim/po/eo.po b/src/nvim/po/eo.po index d1ce47d97c..99c46c7275 100644 --- a/src/nvim/po/eo.po +++ b/src/nvim/po/eo.po @@ -969,9 +969,6 @@ msgstr "E143: AÅtokomandoj neatendite forviÅis novan bufron %s" msgid "E144: non-numeric argument to :z" msgstr "E144: nenumera argumento de :z" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Åœelkomandoj nepermeseblaj en rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Ne eblas limigi regulesprimon per literoj" diff --git a/src/nvim/po/es.po b/src/nvim/po/es.po index f30e8780f9..eeea27610d 100644 --- a/src/nvim/po/es.po +++ b/src/nvim/po/es.po @@ -1234,10 +1234,6 @@ msgstr "E143: Las auto-órdenes han eliminado al nuevo búfer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: Argumento no numérico para \":z\"" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: No se permiten órdenes de consola en rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Las expresiones regulares no se pueden delimitar con letras" diff --git a/src/nvim/po/fi.po b/src/nvim/po/fi.po index f568a34b3c..4489139cfb 100644 --- a/src/nvim/po/fi.po +++ b/src/nvim/po/fi.po @@ -1515,10 +1515,6 @@ msgstr "E143: Autocommand poisti uuden puskurin odotuksen vastaisesti %s" msgid "E144: non-numeric argument to :z" msgstr "E144: :z:n argumentti ei ole numero" -#, fuzzy -#~ msgid "E145: Shell commands not allowed in restricted mode" -#~ msgstr "E145: Kuoren komennot eivät toimi rvimissä" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Säännöllistä ilmausta ei voi rajata kirjaimilla" diff --git a/src/nvim/po/fr.po b/src/nvim/po/fr.po index ea6fe302fe..bb60649c91 100644 --- a/src/nvim/po/fr.po +++ b/src/nvim/po/fr.po @@ -1117,12 +1117,6 @@ msgstr "E143: Une autocommande a effacé le nouveau tampon %s" msgid "E144: non-numeric argument to :z" msgstr "E144: L'argument de :z n'est pas numérique" -# AB - La version française fera peut-être mieux passer l'amère pilule. -# La consultation de l'aide donnera l'explication complète à ceux qui -# ne comprendraient pas à quoi ce message est dû. -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Les commandes externes sont indisponibles dans rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Les expressions régulières ne peuvent pas être délimitées par des " diff --git a/src/nvim/po/ga.po b/src/nvim/po/ga.po index 617b805eb8..1104b31c32 100644 --- a/src/nvim/po/ga.po +++ b/src/nvim/po/ga.po @@ -967,9 +967,6 @@ msgstr "E143: Scrios na huathorduithe maolán nua %s go tobann" msgid "E144: non-numeric argument to :z" msgstr "E144: argóint neamhuimhriúil chun :z" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Ní cheadaítear orduithe blaoisce i rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "" "E146: Ní cheadaítear litreacha mar theormharcóirí ar shloinn ionadaíochta" diff --git a/src/nvim/po/it.po b/src/nvim/po/it.po index 9d5709e1ab..511f910b71 100644 --- a/src/nvim/po/it.po +++ b/src/nvim/po/it.po @@ -1220,10 +1220,6 @@ msgstr "" msgid "E144: non-numeric argument to :z" msgstr "E144: argomento non-numerico a :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Comandi Shell non permessi in rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Le espressioni regolari non possono essere delimitate da lettere" diff --git a/src/nvim/po/ja.euc-jp.po b/src/nvim/po/ja.euc-jp.po index dc3c4368ab..523e9ca4e3 100644 --- a/src/nvim/po/ja.euc-jp.po +++ b/src/nvim/po/ja.euc-jp.po @@ -987,9 +987,6 @@ msgstr "E143: autocommand¤¬Í½´ü¤»¤º¿·¤·¤¤¥Ð¥Ã¥Õ¥¡ %s ¤òºï½ü¤·¤Þ¤·¤¿" msgid "E144: non-numeric argument to :z" msgstr "E144: ¿ô¤Ç¤Ï¤Ê¤¤°ú¿ô¤¬ :z ¤ËÅϤµ¤ì¤Þ¤·¤¿" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim¤Ç¤Ï¥·¥§¥ë¥³¥Þ¥ó¥É¤ò»È¤¨¤Þ¤»¤ó" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Àµµ¬É½¸½¤Ïʸ»ú¤Ç¶èÀڤ뤳¤È¤¬¤Ç¤¤Þ¤»¤ó" diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po index 4c5661464a..5a69d0c5bf 100644 --- a/src/nvim/po/ja.po +++ b/src/nvim/po/ja.po @@ -987,9 +987,6 @@ msgstr "E143: autocommandãŒäºˆæœŸã›ãšæ–°ã—ã„ãƒãƒƒãƒ•ã‚¡ %s を削除ã—ã¾ msgid "E144: non-numeric argument to :z" msgstr "E144: æ•°ã§ã¯ãªã„引数㌠:z ã«æ¸¡ã•れã¾ã—ãŸ" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvimã§ã¯ã‚·ã‚§ãƒ«ã‚³ãƒžãƒ³ãƒ‰ã‚’使ãˆã¾ã›ã‚“" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: æ£è¦è¡¨ç¾ã¯æ–‡å—ã§åŒºåˆ‡ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" diff --git a/src/nvim/po/ko.UTF-8.po b/src/nvim/po/ko.UTF-8.po index e90081bcfd..128b238f8b 100644 --- a/src/nvim/po/ko.UTF-8.po +++ b/src/nvim/po/ko.UTF-8.po @@ -1215,10 +1215,6 @@ msgstr "E143: Autocommandê°€ 뜻 ë°–ì— ìƒˆ ë²„í¼ %sì„(를) ì§€ì› ìŠµë‹ˆë‹¤" msgid "E144: non-numeric argument to :z" msgstr "E144: 숫ìžê°€ 아닌 ì¸ìžê°€ :zì— ì£¼ì–´ì¡ŒìŠµë‹ˆë‹¤" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvimì—서는 쉘 ëª…ë ¹ì„ ì‚¬ìš©í• ìˆ˜ 없습니다" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: ì •ê·œí‘œí˜„ì‹ì€ 글ìžë¡œ 구분ë 수 없습니다" diff --git a/src/nvim/po/nb.po b/src/nvim/po/nb.po index b99e8ce465..34617ccf18 100644 --- a/src/nvim/po/nb.po +++ b/src/nvim/po/nb.po @@ -1231,10 +1231,6 @@ msgstr "E143: Autokommandoer slettet uventet den nye bufferen %s" msgid "E144: non-numeric argument to :z" msgstr "E144: Ikke-numerisk parameter til :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Skallkommandoer er ikke tillatt i rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulære uttrykk kan ikke bli adskilt av bokstaver" diff --git a/src/nvim/po/nl.po b/src/nvim/po/nl.po index 56bcd94e79..30f34508f5 100644 --- a/src/nvim/po/nl.po +++ b/src/nvim/po/nl.po @@ -1217,10 +1217,6 @@ msgstr "E143: 'Autocommands' hebben het nieuwe buffer %s onverwacht verwijderd" msgid "E144: non-numeric argument to :z" msgstr "E144: niet-numeriek argument voor :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: in rvim zijn shell-opdrachten zijn niet toegestaan" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: reguliere expressies kunnen niet begrensd worden door letters" diff --git a/src/nvim/po/no.po b/src/nvim/po/no.po index b99e8ce465..34617ccf18 100644 --- a/src/nvim/po/no.po +++ b/src/nvim/po/no.po @@ -1231,10 +1231,6 @@ msgstr "E143: Autokommandoer slettet uventet den nye bufferen %s" msgid "E144: non-numeric argument to :z" msgstr "E144: Ikke-numerisk parameter til :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Skallkommandoer er ikke tillatt i rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulære uttrykk kan ikke bli adskilt av bokstaver" diff --git a/src/nvim/po/pl.UTF-8.po b/src/nvim/po/pl.UTF-8.po index a348bf6203..f5c452e924 100644 --- a/src/nvim/po/pl.UTF-8.po +++ b/src/nvim/po/pl.UTF-8.po @@ -1201,10 +1201,6 @@ msgstr "E143: Autokomendy nieoczekiwanie skasowaÅ‚y nowy bufor %s" msgid "E144: non-numeric argument to :z" msgstr "E144: nienumeryczny argument dla :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Komendy powÅ‚oki sÄ… niedozwolone w rvim" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Wzorce regularne nie mogÄ… być rozgraniczane literami" diff --git a/src/nvim/po/pt_BR.po b/src/nvim/po/pt_BR.po index 543f0bce27..4f39cb5bdb 100644 --- a/src/nvim/po/pt_BR.po +++ b/src/nvim/po/pt_BR.po @@ -4210,10 +4210,6 @@ msgstr "" msgid "E144: non-numeric argument to :z" msgstr "E144: argumento não-numérico passado a :z" -#: ../ex_cmds.c:3398 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Comandos do shell não são permitidos no rvim" - #: ../ex_cmds.c:3492 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Expressões regulares não podem ser delimitadas por letras" diff --git a/src/nvim/po/ru.po b/src/nvim/po/ru.po index e5be489d72..62f892d257 100644 --- a/src/nvim/po/ru.po +++ b/src/nvim/po/ru.po @@ -1205,10 +1205,6 @@ msgstr "E143: Ðвтокоманды неожиданно убили новый msgid "E144: non-numeric argument to :z" msgstr "E144: Параметр команды :z должен быть чиÑлом" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: ИÑпользование команд оболочки не допуÑкаетÑÑ Ð² rvim." - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: РегулÑрные Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ могут разделÑтьÑÑ Ð±ÑƒÐºÐ²Ð°Ð¼Ð¸" diff --git a/src/nvim/po/sk.cp1250.po b/src/nvim/po/sk.cp1250.po index 74b8e1039c..ced343bf6b 100644 --- a/src/nvim/po/sk.cp1250.po +++ b/src/nvim/po/sk.cp1250.po @@ -1219,10 +1219,6 @@ msgstr "E143: Automatické príkazy neoèakávane zmazali nový buffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: neèíselný argument pre :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim nepovo¾uje použitie príkazov shellu" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulárne výrazy nesmú by oddelené písmenami" diff --git a/src/nvim/po/sk.po b/src/nvim/po/sk.po index d3f954f6d8..66b3d5abb1 100644 --- a/src/nvim/po/sk.po +++ b/src/nvim/po/sk.po @@ -1219,10 +1219,6 @@ msgstr "E143: Automatické príkazy neoèakávane zmazali nový buffer %s" msgid "E144: non-numeric argument to :z" msgstr "E144: neèíselný argument pre :z" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim nepovoµuje pou¾itie príkazov shellu" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regulárne výrazy nesmú by» oddelené písmenami" diff --git a/src/nvim/po/sr.po b/src/nvim/po/sr.po index 88c5d18866..4c157658e5 100644 --- a/src/nvim/po/sr.po +++ b/src/nvim/po/sr.po @@ -424,7 +424,7 @@ msgstr "Опција 'dictionary' је празна" msgid "'thesaurus' option is empty" msgstr "Опција 'thesaurus' је празна" -#, c-format +#, c-format msgid "Scanning dictionary: %s" msgstr "Скенирање речника: %s" @@ -702,7 +702,7 @@ msgstr "E785: complete() може да Ñе кориÑти Ñамо у режиРmsgid "&Ok" msgstr "&Ок" -#, c-format +#, c-format msgid "+-%s%3ld line: " msgid_plural "+-%s%3ld lines: " msgstr[0] "+-%s%3ld линија: " @@ -810,7 +810,7 @@ msgstr "E677: Грешка при упиÑу temp датотеке" msgid "E921: Invalid callback argument" msgstr "E921: ÐеиÑправан callback аргумент" -#, c-format +#, c-format msgid "<%s>%s%s %d, Hex %02x, Oct %03o, Digr %s" msgstr "<%s>%s%s %d, Ð¥ÐµÐºÑ %02x, Окт %03o, Дигр %s" @@ -818,11 +818,11 @@ msgstr "<%s>%s%s %d, Ð¥ÐµÐºÑ %02x, Окт %03o, Дигр %s" msgid "<%s>%s%s %d, Hex %02x, Octal %03o" msgstr "<%s>%s%s %d, Ð¥ÐµÐºÑ %02x, Октално %03o" -#, c-format +#, c-format msgid "> %d, Hex %04x, Oct %o, Digr %s" msgstr "> %d, Ð¥ÐµÐºÑ %04x, Окт %o, Дигр %s" -#, c-format +#, c-format msgid "> %d, Hex %08x, Oct %o, Digr %s" msgstr "> %d, Ð¥ÐµÐºÑ %08x, Окт %o, Дигр %s" @@ -981,9 +981,6 @@ msgstr "E143: Ðутокоманде Ñу неочекивано обриÑалРmsgid "E144: non-numeric argument to :z" msgstr "E144: ненумерички аргумент за :z" -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Shell команде ниÑу дозвољене у rvim" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Регуларни изрази не могу да Ñе раздвајају Ñловима" diff --git a/src/nvim/po/sv.po b/src/nvim/po/sv.po index 4770db15de..db7bada888 100644 --- a/src/nvim/po/sv.po +++ b/src/nvim/po/sv.po @@ -2622,10 +2622,6 @@ msgstr "E143: Autokommandon tog oväntat bort ny buffert %s" msgid "E144: non-numeric argument to :z" msgstr "E144: ickenumeriskt argument till :z" -#: ../ex_cmds.c:3398 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Skalkommandon inte tillåtna i rvim" - #: ../ex_cmds.c:3492 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Reguljära uttryck kan inte vara åtskilda av bokstäver" diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po index f2179f4f1b..604e425bd0 100644 --- a/src/nvim/po/uk.po +++ b/src/nvim/po/uk.po @@ -1459,10 +1459,6 @@ msgstr "E143: Ðвтокоманди неÑподівано знищили ноРmsgid "E144: non-numeric argument to :z" msgstr "E144: нечиÑловий аргумент Ð´Ð»Ñ :z" -msgid "" -"E145: Shell commands and some functionality not allowed in restricted mode" -msgstr "E145: У обмеженому режимі не дозволені команди оболонки Ñ– деÑка функіональніÑть" - msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: РегулÑрні вирази не можна розділÑти літерами" diff --git a/src/nvim/po/vi.po b/src/nvim/po/vi.po index 7dbf19c263..a954ea6e34 100644 --- a/src/nvim/po/vi.po +++ b/src/nvim/po/vi.po @@ -1229,10 +1229,6 @@ msgstr "E143: Các lệnh tá»± động xóa bá»™ đệm má»›i ngoà i ý muốn % msgid "E144: non-numeric argument to :z" msgstr "E144: Tham số cá»§a lệnh :z phải là số" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: Không cho phép sá» dụng lệnh shell trong rvim." - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Không thể phân cách biểu thức chÃnh quy bằng chữ cái" diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po index 76204a43a8..542157002a 100644 --- a/src/nvim/po/zh_CN.UTF-8.po +++ b/src/nvim/po/zh_CN.UTF-8.po @@ -1222,10 +1222,6 @@ msgstr "E143: 自动命令æ„å¤–åœ°åˆ é™¤äº†æ–°ç¼“å†²åŒº %s" msgid "E144: non-numeric argument to :z" msgstr "E144: :z 䏿ޥå—éžæ•°å—çš„å‚æ•°" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim ä¸ç¦æ¢ä½¿ç”¨ shell 命令" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: æ£åˆ™è¡¨è¾¾å¼ä¸èƒ½ç”¨å—æ¯ä½œåˆ†ç•Œ" diff --git a/src/nvim/po/zh_TW.UTF-8.po b/src/nvim/po/zh_TW.UTF-8.po index 3c1dd463b7..6a11b5e669 100644 --- a/src/nvim/po/zh_TW.UTF-8.po +++ b/src/nvim/po/zh_TW.UTF-8.po @@ -32,8 +32,8 @@ # So please change [行"] to [行 "] # # Q. How to use UTF8 mode on Win32? -# A. A simple configuration: -# set encoding=utf-8; let $LANG='zh_TW.UTF-8'; +# A. A simple configuration: +# set encoding=utf-8; let $LANG='zh_TW.UTF-8'; # (set langmenu=none or ..) # set fileencodings=ucs-bom,utf-8,japan,taiwan,prc # set fileencoding=taiwan (or utf-8) @@ -1262,10 +1262,6 @@ msgstr "E143: Autocommands æ„外地刪除新緩è¡å€ %s" msgid "E144: non-numeric argument to :z" msgstr "E144: :z 䏿ޥå—éžæ•¸å—çš„åƒæ•¸" -#: ../ex_cmds.c:3404 -msgid "E145: Shell commands not allowed in rvim" -msgstr "E145: rvim ä¸ç¦æ¢ä½¿ç”¨ shell 命令" - #: ../ex_cmds.c:3498 msgid "E146: Regular expressions can't be delimited by letters" msgstr "E146: Regular expression ç„¡æ³•ç”¨å—æ¯åˆ†éš” (?)" diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 8998f9037e..5f09912116 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -173,7 +173,9 @@ static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, Error err = ERROR_INIT; textlock++; + provider_active = true; Object ret = nlua_call_ref(ref, name, args, true, &err); + provider_active = false; textlock--; if (!ERROR_SET(&err) diff --git a/src/nvim/search.c b/src/nvim/search.c index f979889540..90e1e25de2 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1658,6 +1658,48 @@ static bool find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos) return found; } +/// Check matchpairs option for "*initc". +/// If there is a match set "*initc" to the matching character and "*findc" to +/// the opposite character. Set "*backwards" to the direction. +/// When "switchit" is true swap the direction. +static void find_mps_values(int *initc, int *findc, bool *backwards, + bool switchit) + FUNC_ATTR_NONNULL_ALL +{ + char_u *ptr = curbuf->b_p_mps; + + while (*ptr != NUL) { + if (utf_ptr2char(ptr) == *initc) { + if (switchit) { + *findc = *initc; + *initc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); + *backwards = true; + } else { + *findc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); + *backwards = false; + } + return; + } + char_u *prev = ptr; + ptr += utfc_ptr2len(ptr) + 1; + if (utf_ptr2char(ptr) == *initc) { + if (switchit) { + *findc = *initc; + *initc = utf_ptr2char(prev); + *backwards = false; + } else { + *findc = utf_ptr2char(prev); + *backwards = true; + } + return; + } + ptr += utfc_ptr2len(ptr); + if (*ptr == ',') { + ptr++; + } + } +} + /* * findmatchlimit -- find the matching paren or brace, if it exists within * maxtravel lines of the cursor. A maxtravel of 0 means search until falling @@ -1684,7 +1726,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) static pos_T pos; // current search position int findc = 0; // matching brace int count = 0; // cumulative number of braces - int backwards = false; // init for gcc + bool backwards = false; // init for gcc bool raw_string = false; // search for raw string bool inquote = false; // true when inside quotes char_u *ptr; @@ -1729,9 +1771,10 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) raw_string = (initc == 'R'); initc = NUL; } else if (initc != '#' && initc != NUL) { - find_mps_values(&initc, &findc, &backwards, TRUE); - if (findc == NUL) + find_mps_values(&initc, &findc, &backwards, true); + if (findc == NUL) { return NULL; + } } else { /* * Either initc is '#', or no initc was given and we need to look @@ -1759,20 +1802,20 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) else if (linep[pos.col] == '/') { if (linep[pos.col + 1] == '*') { comment_dir = FORWARD; - backwards = FALSE; + backwards = false; pos.col++; } else if (pos.col > 0 && linep[pos.col - 1] == '*') { comment_dir = BACKWARD; - backwards = TRUE; + backwards = true; pos.col--; } } else if (linep[pos.col] == '*') { if (linep[pos.col + 1] == '/') { comment_dir = BACKWARD; - backwards = TRUE; + backwards = true; } else if (pos.col > 0 && linep[pos.col - 1] == '/') { comment_dir = FORWARD; - backwards = FALSE; + backwards = false; } } } @@ -1794,9 +1837,10 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) if (initc == NUL) break; - find_mps_values(&initc, &findc, &backwards, FALSE); - if (findc) + find_mps_values(&initc, &findc, &backwards, false); + if (findc) { break; + } pos.col += utfc_ptr2len(linep + pos.col); } if (!findc) { diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 5e54354ea8..e91d560284 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -7563,14 +7563,13 @@ static void syn_unadd_group(void) /// @see syn_attr2entry int syn_id2attr(int hl_id) { - struct hl_group *sgp; - hl_id = syn_get_final_id(hl_id); - int attr = ns_get_hl(-1, hl_id, false); + struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one + + int attr = ns_get_hl(-1, hl_id, false, sgp->sg_set); if (attr >= 0) { return attr; } - sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one return sgp->sg_attr; } @@ -7583,7 +7582,6 @@ int syn_id2attr(int hl_id) int syn_get_final_id(int hl_id) { int count; - struct hl_group *sgp; if (hl_id > highlight_ga.ga_len || hl_id < 1) return 0; /* Can be called from eval!! */ @@ -7593,19 +7591,20 @@ int syn_get_final_id(int hl_id) * Look out for loops! Break after 100 links. */ for (count = 100; --count >= 0; ) { + struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one + // ACHTUNG: when using "tmp" attribute (no link) the function might be // called twice. it needs be smart enough to remember attr only to // syn_id2attr time - int check = ns_get_hl(-1, hl_id, true); + int check = ns_get_hl(-1, hl_id, true, sgp->sg_set); if (check == 0) { - return 0; // how dare! it broke the link! + return hl_id; // how dare! it broke the link! } else if (check > 0) { hl_id = check; continue; } - sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) { break; } diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index af8482bdbe..ed75bda7a5 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -86,6 +86,8 @@ let s:filename_checks = { \ 'bzr': ['bzr_log.any'], \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c'], \ 'cabal': ['file.cabal'], + \ 'cabalconfig': ['cabal.config'], + \ 'cabalproject': ['cabal.project', 'cabal.project.local'], \ 'calendar': ['calendar'], \ 'catalog': ['catalog', 'sgml.catalogfile'], \ 'cdl': ['file.cdl'], diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 12bec745a8..7fe0168356 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -2,6 +2,8 @@ source shared.vim source screendump.vim +source term_util.vim +source check.vim " Check that loading startup.vim works. func Test_startup_script() @@ -278,6 +280,68 @@ func Test_V_arg() " call assert_match("sourcing \"$VIMRUNTIME[\\/]defaults\.vim\"\r\nline 1: \" The default vimrc file\..* verbose=15\n", out) endfunc +" Test the '-q [errorfile]' argument. +func Test_q_arg() + CheckFeature quickfix + + let lines =<< trim END + /* some file with an error */ + main() { + functionCall(arg; arg, arg); + return 666 + } + END + call writefile(lines, 'Xbadfile.c') + + let after =<< trim [CODE] + call writefile([&errorfile, string(getpos("."))], "Xtestout") + copen + w >> Xtestout + qall + [CODE] + + " Test with default argument '-q'. + call assert_equal('errors.err', &errorfile) + call writefile(["Xbadfile.c:4:12: error: expected ';' before '}' token"], 'errors.err') + if RunVim([], after, '-q') + let lines = readfile('Xtestout') + call assert_equal(['errors.err', + \ '[0, 4, 12, 0]', + \ "Xbadfile.c|4 col 12| error: expected ';' before '}' token"], + \ lines) + endif + call delete('Xtestout') + call delete('errors.err') + + " Test with explicit argument '-q Xerrors' (with space). + call writefile(["Xbadfile.c:4:12: error: expected ';' before '}' token"], 'Xerrors') + if RunVim([], after, '-q Xerrors') + let lines = readfile('Xtestout') + call assert_equal(['Xerrors', + \ '[0, 4, 12, 0]', + \ "Xbadfile.c|4 col 12| error: expected ';' before '}' token"], + \ lines) + endif + call delete('Xtestout') + + " Test with explicit argument '-qXerrors' (without space). + if RunVim([], after, '-qXerrors') + let lines = readfile('Xtestout') + call assert_equal(['Xerrors', + \ '[0, 4, 12, 0]', + \ "Xbadfile.c|4 col 12| error: expected ';' before '}' token"], + \ lines) + endif + + " Test with a non-existing error file (exits with value 3) + let out = system(GetVimCommand() .. ' -q xyz.err') + call assert_equal(3, v:shell_error) + + call delete('Xbadfile.c') + call delete('Xtestout') + call delete('Xerrors') +endfunc + " Test the -V[N]{filename} argument to set the 'verbose' option to N " and set 'verbosefile' to filename. func Test_V_file_arg() @@ -408,13 +472,15 @@ func Test_invalid_args() let out = split(system(GetVimCommand() .. ' - xxx -cq'), "\n") call assert_equal(0, v:shell_error) - " Detect invalid repeated arguments '-t foo -t foo", '-q foo -q foo'. - for opt in ['-t', '-q'] - let out = split(system(GetVimCommand() .. repeat(' ' .. opt .. ' foo', 2)), "\n") - call assert_equal(1, v:shell_error) - call assert_equal('nvim: Too many edit arguments: "' .. opt .. '"', out[0]) - call assert_equal('More info with "nvim -h"', out[1]) - endfor + if has('quickfix') + " Detect invalid repeated arguments '-t foo -t foo", '-q foo -q foo'. + for opt in ['-t', '-q'] + let out = split(system(GetVimCommand() .. repeat(' ' .. opt .. ' foo', 2)), "\n") + call assert_equal(1, v:shell_error) + call assert_equal('nvim: Too many edit arguments: "' .. opt .. '"', out[0]) + call assert_equal('More info with "nvim -h"', out[1]) + endfor + endif for opt in [' -cq', ' --cmd q', ' +', ' -S foo'] let out = split(system(GetVimCommand() .. repeat(opt, 11)), "\n") diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 94c326a5eb..124f96e039 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -22,6 +22,14 @@ #define KEY_BUFFER_SIZE 0xfff +#ifndef UNIT_TESTING +typedef enum { + kIncomplete = -1, + kNotApplicable = 0, + kComplete = 1, +} HandleState; +#endif + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/input.c.generated.h" #endif @@ -339,8 +347,14 @@ static void tk_getkeys(TermInput *input, bool force) static void tinput_timer_cb(TimeWatcher *watcher, void *data) { - tk_getkeys(data, true); - tinput_flush(data, true); + TermInput *input = (TermInput *)data; + // If the raw buffer is not empty, process the raw buffer first because it is + // processing an incomplete bracketed paster sequence. + if (rbuffer_size(input->read_stream.buffer)) { + handle_raw_buffer(input, true); + } + tk_getkeys(input, true); + tinput_flush(input, true); } /// Handle focus events. @@ -365,19 +379,22 @@ static bool handle_focus_event(TermInput *input) return false; } -static bool handle_bracketed_paste(TermInput *input) +#define START_PASTE "\x1b[200~" +#define END_PASTE "\x1b[201~" +static HandleState handle_bracketed_paste(TermInput *input) { - if (rbuffer_size(input->read_stream.buffer) > 5 - && (!rbuffer_cmp(input->read_stream.buffer, "\x1b[200~", 6) - || !rbuffer_cmp(input->read_stream.buffer, "\x1b[201~", 6))) { + size_t buf_size = rbuffer_size(input->read_stream.buffer); + if (buf_size > 5 + && (!rbuffer_cmp(input->read_stream.buffer, START_PASTE, 6) + || !rbuffer_cmp(input->read_stream.buffer, END_PASTE, 6))) { bool enable = *rbuffer_get(input->read_stream.buffer, 4) == '0'; if (input->paste && enable) { - return false; // Pasting "start paste" code literally. + return kNotApplicable; // Pasting "start paste" code literally. } // Advance past the sequence rbuffer_consumed(input->read_stream.buffer, 6); if (!!input->paste == enable) { - return true; // Spurious "disable paste" code. + return kComplete; // Spurious "disable paste" code. } if (enable) { @@ -392,9 +409,15 @@ static bool handle_bracketed_paste(TermInput *input) // Paste phase: "disabled". input->paste = 0; } - return true; + return kComplete; + } else if (buf_size < 6 + && (!rbuffer_cmp(input->read_stream.buffer, START_PASTE, buf_size) + || !rbuffer_cmp(input->read_stream.buffer, + END_PASTE, buf_size))) { + // Wait for further input, as the sequence may be split. + return kIncomplete; } - return false; + return kNotApplicable; } // ESC NUL => <Esc> @@ -441,39 +464,47 @@ static void set_bg_deferred(void **argv) // ignored in the calculations. // // [1] https://en.wikipedia.org/wiki/Luma_%28video%29 -static bool handle_background_color(TermInput *input) +static HandleState handle_background_color(TermInput *input) { if (input->waiting_for_bg_response <= 0) { - return false; + return kNotApplicable; } size_t count = 0; size_t component = 0; size_t header_size = 0; size_t num_components = 0; + size_t buf_size = rbuffer_size(input->read_stream.buffer); uint16_t rgb[] = { 0, 0, 0 }; uint16_t rgb_max[] = { 0, 0, 0 }; bool eat_backslash = false; bool done = false; bool bad = false; - if (rbuffer_size(input->read_stream.buffer) >= 9 + if (buf_size >= 9 && !rbuffer_cmp(input->read_stream.buffer, "\x1b]11;rgb:", 9)) { header_size = 9; num_components = 3; - } else if (rbuffer_size(input->read_stream.buffer) >= 10 + } else if (buf_size >= 10 && !rbuffer_cmp(input->read_stream.buffer, "\x1b]11;rgba:", 10)) { header_size = 10; num_components = 4; + } else if (buf_size < 10 + && !rbuffer_cmp(input->read_stream.buffer, + "\x1b]11;rgba", buf_size)) { + // An incomplete sequence was found, waiting for the next input. + return kIncomplete; } else { input->waiting_for_bg_response--; if (input->waiting_for_bg_response == 0) { DLOG("did not get a response for terminal background query"); } - return false; + return kNotApplicable; } - input->waiting_for_bg_response = 0; - rbuffer_consumed(input->read_stream.buffer, header_size); RBUFFER_EACH(input->read_stream.buffer, c, i) { count = i + 1; + // Skip the header. + if (i < header_size) { + continue; + } if (eat_backslash) { done = true; break; @@ -495,8 +526,8 @@ static bool handle_background_color(TermInput *input) bad = true; } } - rbuffer_consumed(input->read_stream.buffer, count); if (done && !bad && rgb_max[0] && rgb_max[1] && rgb_max[2]) { + rbuffer_consumed(input->read_stream.buffer, count); double r = (double)rgb[0] / (double)rgb_max[0]; double g = (double)rgb[1] / (double)rgb_max[1]; double b = (double)rgb[2] / (double)rgb_max[2]; @@ -505,34 +536,41 @@ static bool handle_background_color(TermInput *input) DLOG("bg response: %s", bgvalue); loop_schedule_deferred(&main_loop, event_create(set_bg_deferred, 1, bgvalue)); + input->waiting_for_bg_response = 0; + } else if (!done && !bad) { + // An incomplete sequence was found, waiting for the next input. + return kIncomplete; } else { + input->waiting_for_bg_response = 0; + rbuffer_consumed(input->read_stream.buffer, count); DLOG("failed to parse bg response"); - return false; + return kNotApplicable; } - return true; + return kComplete; } #ifdef UNIT_TESTING -bool ut_handle_background_color(TermInput *input) +HandleState ut_handle_background_color(TermInput *input) { return handle_background_color(input); } #endif -static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, - void *data, bool eof) +static void handle_raw_buffer(TermInput *input, bool force) { - TermInput *input = data; - - if (eof) { - loop_schedule_fast(&main_loop, event_create(tinput_done_event, 0)); - return; - } + HandleState is_paste; + HandleState is_bc; do { - if (handle_focus_event(input) - || handle_bracketed_paste(input) - || handle_forced_escape(input) - || handle_background_color(input)) { + if (!force + && (handle_focus_event(input) + || (is_paste = handle_bracketed_paste(input)) != kNotApplicable + || handle_forced_escape(input) + || (is_bc = handle_background_color(input)) != kNotApplicable)) { + if (is_paste == kIncomplete || is_bc == kIncomplete) { + // Wait for the next input, leaving it in the raw buffer due to an + // incomplete sequence. + return; + } continue; } @@ -578,7 +616,34 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, } } } while (rbuffer_size(input->read_stream.buffer)); +} + +static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, + void *data, bool eof) +{ + TermInput *input = data; + + if (eof) { + loop_schedule_fast(&main_loop, event_create(tinput_done_event, 0)); + return; + } + + handle_raw_buffer(input, false); tinput_flush(input, true); + + // An incomplete sequence was found. Leave it in the raw buffer and wait for + // the next input. + if (rbuffer_size(input->read_stream.buffer)) { + // If 'ttimeout' is not set, start the timer with a timeout of 0 to process + // the next input. + long ms = input->ttimeout ? + (input->ttimeoutlen >= 0 ? input->ttimeoutlen : 0) : 0; + // Stop the current timer if already running + time_watcher_stop(&input->timer_handle); + time_watcher_start(&input->timer_handle, tinput_timer_cb, (uint32_t)ms, 0); + return; + } + // Make sure the next input escape sequence fits into the ring buffer without // wraparound, else it could be misinterpreted (because rbuffer_read_ptr() // exposes the underlying buffer to callers unaware of the wraparound). diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index b30546c815..ed76455189 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -32,7 +32,13 @@ typedef struct term_input { #endif #ifdef UNIT_TESTING -bool ut_handle_background_color(TermInput *input); +typedef enum { + kIncomplete = -1, + kNotApplicable = 0, + kComplete = 1, +} HandleState; + +HandleState ut_handle_background_color(TermInput *input); #endif #endif // NVIM_TUI_INPUT_H diff --git a/src/nvim/types.h b/src/nvim/types.h index 17f7e16740..2dbeecbf6d 100644 --- a/src/nvim/types.h +++ b/src/nvim/types.h @@ -2,6 +2,7 @@ #define NVIM_TYPES_H #include <stdint.h> +#include <stdbool.h> // dummy to pass an ACL to a function typedef void *vim_acl_T; diff --git a/src/nvim/window.c b/src/nvim/window.c index 17d9b8f483..72ee400e40 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1112,8 +1112,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // add a status line when p_ls == 1 and splitting the first window if (one_nonfloat() && p_ls == 1 && oldwin->w_status_height == 0) { - if ((oldwin->w_height + oldwin->w_winbar_height) <= p_wmh - && new_in_layout) { + if (oldwin->w_height <= p_wmh && new_in_layout) { EMSG(_(e_noroom)); return FAIL; } @@ -1210,7 +1209,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) * height. */ // Current window requires at least 1 space. - wmh1 = (p_wmh == 0 ? 1 : p_wmh) + curwin->w_winbar_height; + wmh1 = p_wmh == 0 ? 1 : p_wmh; needed = wmh1 + STATUS_HEIGHT; if (flags & WSP_ROOM) { needed += p_wh - wmh1; @@ -1408,12 +1407,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) if (flags & (WSP_TOP | WSP_BOT)) { /* set height and row of new window to full height */ wp->w_winrow = tabline_height(); - win_new_height(wp, curfrp->fr_height - (p_ls > 0) - wp->w_winbar_height); + win_new_height(wp, curfrp->fr_height - (p_ls > 0)); wp->w_status_height = (p_ls > 0); } else { /* height and row of new window is same as current window */ wp->w_winrow = oldwin->w_winrow; - win_new_height(wp, oldwin->w_height + oldwin->w_winbar_height); + win_new_height(wp, oldwin->w_height); wp->w_status_height = oldwin->w_status_height; } frp->fr_height = curfrp->fr_height; @@ -1460,7 +1459,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) * one row for the status line */ win_new_height(wp, new_size); if (flags & (WSP_TOP | WSP_BOT)) { - int new_fr_height = curfrp->fr_height - new_size + wp->w_winbar_height; + int new_fr_height = curfrp->fr_height - new_size; if (!((flags & WSP_BOT) && p_ls == 0)) { new_fr_height -= STATUS_HEIGHT; @@ -1474,8 +1473,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) wp->w_status_height = STATUS_HEIGHT; oldwin->w_winrow += wp->w_height + STATUS_HEIGHT; } else { // new window below current one - wp->w_winrow = oldwin->w_winrow + oldwin->w_height - + STATUS_HEIGHT + oldwin->w_winbar_height; + wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT; wp->w_status_height = oldwin->w_status_height; if (!(flags & WSP_BOT)) { oldwin->w_status_height = STATUS_HEIGHT; @@ -1690,7 +1688,7 @@ make_windows ( - (p_wiw - p_wmw)) / (p_wmw + 1); } else { // Each window needs at least 'winminheight' lines and a status line. - maxcount = (curwin->w_height + curwin->w_winbar_height + maxcount = (curwin->w_height + curwin->w_status_height - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT); } @@ -3155,9 +3153,7 @@ frame_new_height ( if (topfrp->fr_win != NULL) { // Simple case: just one window. win_new_height(topfrp->fr_win, - height - - topfrp->fr_win->w_status_height - - topfrp->fr_win->w_winbar_height); + height - topfrp->fr_win->w_status_height); } else if (topfrp->fr_layout == FR_ROW) { do { // All frames in this row get the same new height. @@ -3464,8 +3460,7 @@ static void frame_fix_width(win_T *wp) static void frame_fix_height(win_T *wp) FUNC_ATTR_NONNULL_ALL { - wp->w_frame->fr_height = - wp->w_height + wp->w_status_height + wp->w_winbar_height; + wp->w_frame->fr_height = wp->w_height + wp->w_status_height; } /* @@ -3488,11 +3483,10 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin) // window: minimal height of the window plus status line m = p_wmh + topfrp->fr_win->w_status_height; if (topfrp->fr_win == curwin && next_curwin == NULL) { - // Current window is minimal one line high and WinBar is visible. + // Current window is minimal one line high. if (p_wmh == 0) { m++; } - m += curwin->w_winbar_height; } } } else if (topfrp->fr_layout == FR_ROW) { @@ -4804,8 +4798,6 @@ win_free ( qf_free_all(wp); - remove_winbar(wp); - xfree(wp->w_p_cc_cols); win_free_grid(wp, false); @@ -5092,8 +5084,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col) wp->w_redr_status = true; wp->w_pos_changed = true; } - // WinBar will not show if the window height is zero - const int h = wp->w_height + wp->w_winbar_height + wp->w_status_height; + const int h = wp->w_height + wp->w_status_height; *row += h > topfrp->fr_height ? topfrp->fr_height : h; *col += wp->w_width + wp->w_vsep_width; } else { @@ -5135,7 +5126,6 @@ void win_setheight_win(int height, win_T *win) if (height == 0) { height = 1; } - height += curwin->w_winbar_height; } if (win->w_floating) { @@ -5231,9 +5221,8 @@ static void frame_setheight(frame_T *curfrp, int height) room_cmdline = 0; } else { win_T *wp = lastwin_nofloating(); - room_cmdline = Rows - p_ch - (wp->w_winrow - + wp->w_height + wp->w_winbar_height + - wp->w_status_height); + room_cmdline = Rows - p_ch + - (wp->w_winrow + wp->w_height + wp->w_status_height); if (room_cmdline < 0) { room_cmdline = 0; } diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 5948ab3a64..3ef41fde1d 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -727,6 +727,38 @@ describe('TUI', function() ]]) end) + it('paste: split "start paste" code', function() + feed_data('i') + -- Send split "start paste" sequence. + feed_data('\027[2') + feed_data('00~pasted from terminal\027[201~') + screen:expect([[ + pasted from terminal{1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + end) + + it('paste: split "stop paste" code', function() + feed_data('i') + -- Send split "stop paste" sequence. + feed_data('\027[200~pasted from terminal\027[20') + feed_data('1~') + screen:expect([[ + pasted from terminal{1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] [+] }| + {3:-- INSERT --} | + {3:-- TERMINAL --} | + ]]) + end) + it('allows termguicolors to be set at runtime', function() screen:set_option('rgb', true) screen:set_default_attr_ids({ @@ -1452,15 +1484,108 @@ describe("TUI", function() end) -it('TUI bg color triggers OptionSet event on terminal-response', function() - -- Only single integration test. - -- See test/unit/tui_spec.lua for unit tests. - clear() - local screen = thelpers.screen_setup(0, '["'..nvim_prog - ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile", ' - ..'"-c", "autocmd OptionSet background echo \\"did OptionSet, yay!\\""]') +describe('TUI bg color', function() + local screen + + local function setup() + -- Only single integration test. + -- See test/unit/tui_spec.lua for unit tests. + clear() + screen = thelpers.screen_setup(0, '["'..nvim_prog + ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile", ' + ..'"-c", "autocmd OptionSet background echo \\"did OptionSet, yay!\\""]') + end + + before_each(setup) + + it('triggers OptionSet event on unsplit terminal-response', function() + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027]11;rgb:ffff/ffff/ffff\007') + screen:expect{any='did OptionSet, yay!'} + + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=light'} + + setup() + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027]11;rgba:ffff/ffff/ffff/8000\027\\') + screen:expect{any='did OptionSet, yay!'} + + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=light'} + end) + + it('triggers OptionSet event with split terminal-response', function() + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + -- Send a background response with the OSC command part split. + feed_data('\027]11;rgb') + feed_data(':ffff/ffff/ffff\027\\') + screen:expect{any='did OptionSet, yay!'} + + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=light'} + + setup() + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + -- Send a background response with the Pt portion split. + feed_data('\027]11;rgba:ffff/fff') + feed_data('f/ffff/8000\007') + screen:expect{any='did OptionSet, yay!'} + + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=light'} + end) + + it('not triggers OptionSet event with invalid terminal-response', function() + screen:expect([[ + {1: } | + {4:~ }| + {4:~ }| + {4:~ }| + {5:[No Name] 0,0-1 All}| + | + {3:-- TERMINAL --} | + ]]) + feed_data('\027]11;rgb:ffff/ffff/ffff/8000\027\\') + screen:expect_unchanged() + + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=dark'} - screen:expect([[ + setup() + screen:expect([[ {1: } | {4:~ }| {4:~ }| @@ -1468,10 +1593,11 @@ it('TUI bg color triggers OptionSet event on terminal-response', function() {5:[No Name] 0,0-1 All}| | {3:-- TERMINAL --} | - ]]) - feed_data('\027]11;rgb:ffff/ffff/ffff\007') - screen:expect{any='did OptionSet, yay!'} + ]]) + feed_data('\027]11;rgba:ffff/foo/ffff/8000\007') + screen:expect_unchanged() - feed_data(':echo "new_bg=".&background\n') - screen:expect{any='new_bg=light'} + feed_data(':echo "new_bg=".&background\n') + screen:expect{any='new_bg=dark'} + end) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 4182090732..781fdf7203 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -27,6 +27,7 @@ describe('decorations providers', function() [9] = {reverse = true}; [10] = {italic = true, background = Screen.colors.Magenta}; [11] = {foreground = Screen.colors.Red, background = tonumber('0x005028')}; + [12] = {foreground = tonumber('0x990000')}; } end) @@ -227,4 +228,77 @@ describe('decorations providers', function() ]]} end) + + it('can break an existing link', function() + insert(mulholland) + local ns1 = setup_provider() + + exec [[ + highlight OriginalGroup guifg='#990000' + highlight link LinkGroup OriginalGroup + ]] + + meths.buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {}) + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); {12:- not red} | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false); | + restore_buffer(&save_buf);^ | + | + ]]} + + meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue'}) + meths.set_hl_ns(ns1) + + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); {4:- not red} | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false); | + restore_buffer(&save_buf);^ | + | + ]]} + end) + + it("with 'default': do not break an existing link", function() + insert(mulholland) + local ns1 = setup_provider() + + exec [[ + highlight OriginalGroup guifg='#990000' + highlight link LinkGroup OriginalGroup + ]] + + meths.buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {}) + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); {12:- not red} | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false); | + restore_buffer(&save_buf);^ | + | + ]]} + + meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue', default=true}) + meths.set_hl_ns(ns1) + feed 'k' + + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); {12:- not red} | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false^); | + restore_buffer(&save_buf); | + | + ]]} + end) end) diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index d7dde6345f..3826707743 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -232,20 +232,53 @@ describe("shell command :!", function() if has_powershell() then it('powershell supports literal strings', function() set_shell_powershell() - local screen = Screen.new(30, 4) + local screen = Screen.new(45, 4) screen:attach() feed_command([[!'Write-Output $a']]) - screen:expect{any='\nWrite%-Output %$a', timeout=10000} + screen:expect([[ + :!'Write-Output $a' | + Write-Output $a | + | + Press ENTER or type command to continue^ | + ]]) feed_command([[!$a = 1; Write-Output '$a']]) - screen:expect{any='\n%$a', timeout=10000} + screen:expect([[ + :!$a = 1; Write-Output '$a' | + $a | + | + Press ENTER or type command to continue^ | + ]]) feed_command([[!"Write-Output $a"]]) - screen:expect{any='\nWrite%-Output', timeout=10000} + screen:expect([[ + :!"Write-Output $a" | + Write-Output | + | + Press ENTER or type command to continue^ | + ]]) feed_command([[!$a = 1; Write-Output "$a"]]) - screen:expect{any='\n1', timeout=10000} - feed_command(iswin() - and [[!& 'C:\\Windows\\system32\\cmd.exe' /c 'echo $a']] - or [[!& '/bin/sh' -c 'echo ''$a''']]) - screen:expect{any='\n%$a', timeout=10000} + screen:expect([[ + :!$a = 1; Write-Output "$a" | + 1 | + | + Press ENTER or type command to continue^ | + ]]) + if iswin() then + feed_command([[!& 'cmd.exe' /c 'echo $a']]) + screen:expect([[ + :!& 'cmd.exe' /c 'echo $a' | + $a | + | + Press ENTER or type command to continue^ | + ]]) + else + feed_command([[!& '/bin/sh' -c 'echo ''$a''']]) + screen:expect([[ + :!& '/bin/sh' -c 'echo ''$a''' | + $a | + | + Press ENTER or type command to continue^ | + ]]) + end end) end end) diff --git a/test/helpers.lua b/test/helpers.lua index 84148dc1a8..8dbd82cb8c 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -777,11 +777,12 @@ end function module.isCI(name) local any = (name == nil) - assert(any or name == 'appveyor' or name == 'travis' or name == 'sourcehut') + assert(any or name == 'appveyor' or name == 'travis' or name == 'sourcehut' or name == 'github') local av = ((any or name == 'appveyor') and nil ~= os.getenv('APPVEYOR')) local tr = ((any or name == 'travis') and nil ~= os.getenv('TRAVIS')) local sh = ((any or name == 'sourcehut') and nil ~= os.getenv('SOURCEHUT')) - return tr or av or sh + local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS')) + return tr or av or sh or gh end diff --git a/test/unit/tui_spec.lua b/test/unit/tui_spec.lua index e6b5c889d7..36ce4a1493 100644 --- a/test/unit/tui_spec.lua +++ b/test/unit/tui_spec.lua @@ -14,10 +14,13 @@ itp('handle_background_color', function() local handle_background_color = cinput.ut_handle_background_color local term_input = ffi.new('TermInput', {}) local events = globals.main_loop.thread_events + local kIncomplete = cinput.kIncomplete + local kNotApplicable = cinput.kNotApplicable + local kComplete = cinput.kComplete -- Short-circuit when not waiting for response. term_input.waiting_for_bg_response = 0 - eq(false, handle_background_color(term_input)) + eq(kNotApplicable, handle_background_color(term_input)) local capacity = 100 local rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free) @@ -28,7 +31,7 @@ itp('handle_background_color', function() rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) term_input.waiting_for_bg_response = 1 - eq(true, handle_background_color(term_input)) + eq(kComplete, handle_background_color(term_input)) eq(0, term_input.waiting_for_bg_response) eq(1, multiqueue.multiqueue_size(events)) @@ -97,14 +100,42 @@ itp('handle_background_color', function() assert_bg('rgba', 'f/f/f/f', 'light') - -- Incomplete sequence: not necessarily correct behavior, but tests it. + -- Incomplete sequence: necessarily correct behavior. local term_response = '\027]11;rgba:f/f/f/f' -- missing '\007 rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) term_input.waiting_for_bg_response = 1 - eq(false, handle_background_color(term_input)) + eq(kIncomplete, handle_background_color(term_input)) + eq(1, term_input.waiting_for_bg_response) + eq(#term_response, rbuf.size) + + term_response = '\007' + rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) + eq(kComplete, handle_background_color(term_input)) + eq(0, term_input.waiting_for_bg_response) + + local event = multiqueue.multiqueue_get(events) + local bg_event = ffi.cast("Event*", event.argv[1]) + eq('light', ffi.string(bg_event.argv[0])) + eq(0, multiqueue.multiqueue_size(events)) + eq(0, rbuf.size) + + term_response = '\027]11;rg' + rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) + + term_input.waiting_for_bg_response = 1 + eq(kIncomplete, handle_background_color(term_input)) + eq(1, term_input.waiting_for_bg_response) + eq(#term_response, rbuf.size) + + term_response = 'ba:f/f/f/f\007' + rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) + eq(kComplete, handle_background_color(term_input)) eq(0, term_input.waiting_for_bg_response) + event = multiqueue.multiqueue_get(events) + bg_event = ffi.cast("Event*", event.argv[1]) + eq('light', ffi.string(bg_event.argv[0])) eq(0, multiqueue.multiqueue_size(events)) eq(0, rbuf.size) @@ -114,7 +145,7 @@ itp('handle_background_color', function() rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) term_input.waiting_for_bg_response = 3 - eq(false, handle_background_color(term_input)) + eq(kNotApplicable, handle_background_color(term_input)) eq(2, term_input.waiting_for_bg_response) eq(0, multiqueue.multiqueue_size(events)) @@ -127,7 +158,7 @@ itp('handle_background_color', function() rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response) term_input.waiting_for_bg_response = 1 - eq(true, handle_background_color(term_input)) + eq(kComplete, handle_background_color(term_input)) eq(0, term_input.waiting_for_bg_response) eq(1, multiqueue.multiqueue_size(events)) |