From 9c8540edfd52c77678eac84e48beb56171487b3f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 21 Mar 2017 19:16:26 +0100 Subject: vim-patch:8.0.0159 References #5406 Problem: Using a NULL pointer when using feedkeys() to trigger drawing a tabline. Solution: Skip drawing a tabline if TabPageIdxs is NULL. (Dominique Pelle) Also fix recursing into getcmdline() from the cmd window. https://github.com/vim/vim/commit/c695cec4698b41d7b9555efdd47dda9b1945d3ae --- src/nvim/ex_getln.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index d99c8d02f7..d6e003a82f 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -698,7 +698,9 @@ static int command_line_execute(VimState *state, int key) if (s->c == cedit_key || s->c == K_CMDWIN) { if (ex_normal_busy == 0 && got_int == false) { // Open a window to edit the command line (and history). + save_cmdline(&s->save_ccline); s->c = ex_window(); + restore_cmdline(&s->save_ccline); s->some_key_typed = true; } } else { -- cgit From 01bf78971cea43938e01439ae6d4687bc97196ea Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 21 Mar 2017 23:17:10 +0100 Subject: vim-patch:8.0.0172 Problem: The command selected in the command line window is not executed. (Andrey Starodubtsev) Solution: Save and restore the command line at a lower level. (closes vim/vim#1370) https://github.com/vim/vim/commit/1d669c233c97486555a34f7d3f069068d9ebdb63 --- src/nvim/ex_getln.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index d6e003a82f..2600f484dc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -698,9 +698,7 @@ static int command_line_execute(VimState *state, int key) if (s->c == cedit_key || s->c == K_CMDWIN) { if (ex_normal_busy == 0 && got_int == false) { // Open a window to edit the command line (and history). - save_cmdline(&s->save_ccline); s->c = ex_window(); - restore_cmdline(&s->save_ccline); s->some_key_typed = true; } } else { @@ -5229,10 +5227,8 @@ static int ex_window(void) invalidate_botline(); redraw_later(SOME_VALID); - /* Save the command line info, can be used recursively. */ - save_ccline = ccline; - ccline.cmdbuff = NULL; - ccline.cmdprompt = NULL; + // Save the command line info, can be used recursively. + save_cmdline(&save_ccline); /* No Ex mode here! */ exmode_active = 0; @@ -5266,8 +5262,8 @@ static int ex_window(void) /* Restore KeyTyped in case it is modified by autocommands */ KeyTyped = save_KeyTyped; - /* Restore the command line info. */ - ccline = save_ccline; + // Restore the command line info. + restore_cmdline(&save_ccline); cmdwin_type = 0; exmode_active = save_exmode; -- cgit From 098e91400eb06d29c31264ba973ea8a563703059 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Sat, 25 Mar 2017 14:43:19 +0000 Subject: refactor: Remove allow_keys global (#6346) * The allow_keys global is unused in nvim, remove it * clint --- src/nvim/ex_getln.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2600f484dc..58979c0e43 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -621,11 +621,9 @@ static int command_line_execute(VimState *state, int key) // CTRL-\ CTRL-N goes to Normal mode, CTRL-\ CTRL-G goes to Insert // mode when 'insertmode' is set, CTRL-\ e prompts for an expression. if (s->c == Ctrl_BSL) { - ++no_mapping; - ++allow_keys; + no_mapping++; s->c = plain_vgetc(); - --no_mapping; - --allow_keys; + no_mapping--; // CTRL-\ e doesn't work when obtaining an expression, unless it // is in a mapping. if (s->c != Ctrl_N && s->c != Ctrl_G && (s->c != 'e' @@ -1887,8 +1885,7 @@ getexmodeline ( msg_putchar(' '); } } - ++no_mapping; - ++allow_keys; + no_mapping++; /* * Get the line, one character at a time. @@ -2078,8 +2075,7 @@ redraw: } } - --no_mapping; - --allow_keys; + no_mapping--; /* make following messages go to the next line */ msg_didout = FALSE; -- cgit From 3d48c35d6bfa83ba3ae621fa9ec3f512da199f59 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 29 Jan 2017 03:36:47 +0300 Subject: ex_getln: Refactor script_get() 1. Use `char *` for strings. 2. Add `const` qualifiers. 3. Add attributes and documentation. 4. Handle skipping *inside*. 5. Handle non-heredoc argument also inside: deferring this to the caller is pointless because all callers need the same thing. Though new ex_lua caller may live without allocations in this case, allocating nevertheless produces cleaner code. 6. Note that all callers call script_get with `eap` and `eap->arg`. Thus second argument is useless in practice: it is one and the same always and can be reached through the first argument. --- src/nvim/ex_getln.c | 68 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 58979c0e43..f7e10f3787 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5343,47 +5343,61 @@ static int ex_window(void) return cmdwin_result; } -/* - * Used for commands that either take a simple command string argument, or: - * cmd << endmarker - * {script} - * endmarker - * Returns a pointer to allocated memory with {script} or NULL. - */ -char_u *script_get(exarg_T *eap, char_u *cmd) +/// Get script string +/// +/// Used for commands which accept either `:command script` or +/// +/// :command << endmarker +/// script +/// endmarker +/// +/// @param eap Command being run. +/// @param[out] lenp Location where length of resulting string is saved. Will +/// be set to zero when skipping. +/// +/// @return [allocated] NULL or script. Does not show any error messages. +/// NULL is returned when skipping and on error. +char *script_get(exarg_T *const eap, size_t *const lenp) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *theline; - char *end_pattern = NULL; - char dot[] = "."; - garray_T ga; + const char *const cmd = (const char *)eap->arg; - if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) - return NULL; - - ga_init(&ga, 1, 0x400); + if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) { + *lenp = STRLEN(eap->arg); + return xmemdupz(eap->arg, *lenp); + } - if (cmd[2] != NUL) - end_pattern = (char *)skipwhite(cmd + 2); - else - end_pattern = dot; + garray_T ga = { .ga_data = NULL, .ga_len = 0 }; + if (!eap->skip) { + ga_init(&ga, 1, 0x400); + } - for (;; ) { - theline = eap->getline( + const char *const end_pattern = ( + cmd[2] != NUL + ? (const char *)skipwhite((const char_u *)cmd + 2) + : "."); + for (;;) { + char *const theline = (char *)eap->getline( eap->cstack->cs_looplevel > 0 ? -1 : NUL, eap->cookie, 0); - if (theline == NULL || STRCMP(end_pattern, theline) == 0) { + if (theline == NULL || strcmp(end_pattern, theline) == 0) { xfree(theline); break; } - ga_concat(&ga, theline); - ga_append(&ga, '\n'); + if (!eap->skip) { + ga_concat(&ga, (const char_u *)theline); + ga_append(&ga, '\n'); + } xfree(theline); } - ga_append(&ga, NUL); + *lenp = (size_t)ga.ga_len; // Set length without trailing NUL. + if (!eap->skip) { + ga_append(&ga, NUL); + } - return (char_u *)ga.ga_data; + return (char *)ga.ga_data; } /// Iterate over history items -- cgit From edc80f6b46f51ea1137289301914c0f90db19295 Mon Sep 17 00:00:00 2001 From: raichoo Date: Sun, 26 Mar 2017 23:15:53 +0200 Subject: vim-patch:7.4.2357 (#6354) Problem: Attempt to read history entry while not initialized. Solution: Skip when the index is negative. https://github.com/vim/vim/commit/46643713dc6bb04b4e84986b1763ef309e960161 --- src/nvim/ex_getln.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 58979c0e43..8758a63bce 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4677,8 +4677,8 @@ add_to_history ( * down, only lines that were added. */ if (histype == HIST_SEARCH && in_map) { - if (maptick == last_maptick) { - /* Current line is from the same mapping, remove it */ + if (maptick == last_maptick && hisidx[HIST_SEARCH] >= 0) { + // Current line is from the same mapping, remove it hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]]; hist_free_entry(hisptr); --hisnum[histype]; -- cgit From fb146e80aa1ead96518f38b9684e39249bc83485 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 26 Jul 2016 23:16:23 +0300 Subject: eval: Split eval.c into smaller files --- src/nvim/ex_getln.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8758a63bce..9851ed5396 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4249,7 +4249,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string)); } - list_unref(retlist); + tv_list_unref(retlist); *file = ga.ga_data; *num_file = ga.ga_len; @@ -4545,7 +4545,7 @@ static inline void hist_free_entry(histentry_T *hisptr) FUNC_ATTR_NONNULL_ALL { xfree(hisptr->hisstr); - list_unref(hisptr->additional_elements); + tv_list_unref(hisptr->additional_elements); clear_hist_entry(hisptr); } @@ -4601,7 +4601,7 @@ in_history ( history[type][last_i] = history[type][i]; last_i = i; } - list_unref(list); + tv_list_unref(list); history[type][i].hisnum = ++hisnum[type]; history[type][i].hisstr = str; history[type][i].timestamp = os_time(); -- cgit From e18a5783080f7c94f408ec5f53dedffdb69789e1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 20 Aug 2016 22:24:34 +0300 Subject: *: Move some dictionary functions to typval.h and use char* Also fixes buffer reusage in setmatches() and complete(). --- src/nvim/ex_getln.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9851ed5396..872b7fe365 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5173,7 +5173,7 @@ static int ex_window(void) // Create empty command-line buffer. buf_open_scratch(0, "[Command Line]"); // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); + set_option_value("bh", 0L, "wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; @@ -5191,7 +5191,7 @@ static int ex_window(void) add_map((char_u *)" ", INSERT); add_map((char_u *)" a", NORMAL); } - set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL); + set_option_value("ft", 0L, "vim", OPT_LOCAL); } /* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin -- cgit From 28dafe3ff0b0dc082fb62b2251fd64a167ce7188 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 21 Aug 2016 08:16:47 +0300 Subject: eval,*: Move get_tv_string to typval.c Function was renamed and changed to return `const char *`. --- src/nvim/ex_getln.c | 69 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 28 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 872b7fe365..3bd8d580ab 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -8,6 +8,7 @@ #include #include +#include "nvim/assert.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -960,7 +961,7 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); case Ctrl_HAT: - if (map_to_exists_mode((char_u *)"", LANGMAP, false)) { + if (map_to_exists_mode("", LANGMAP, false)) { // ":lmap" mappings exists, toggle use of mappings. State ^= LANGMAP; if (s->b_im_ptr != NULL) { @@ -3120,9 +3121,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o #endif } #ifdef BACKSLASH_IN_FILENAME - p = vim_strsave_fnameescape(files[i], FALSE); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false); #else - p = vim_strsave_fnameescape(files[i], xp->xp_shell); + p = (char_u *)vim_strsave_fnameescape((const char *)files[i], + xp->xp_shell); #endif xfree(files[i]); files[i] = p; @@ -3152,42 +3154,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o } } -/* - * Escape special characters in "fname" for when used as a file name argument - * after a Vim command, or, when "shell" is non-zero, a shell command. - * Returns the result in allocated memory. - */ -char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET +/// Escape special characters in a file name for use as a command argument +/// +/// @param[in] fname File name to escape. +/// @param[in] shell What to escape for: if false, escapes for VimL command, +/// if true then it escapes for a shell command. +/// +/// @return [allocated] escaped file name. +char *vim_strsave_fnameescape(const char *const fname, const bool shell) + FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL { - char_u *p; #ifdef BACKSLASH_IN_FILENAME -#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") - char_u buf[20]; +#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<" + char_u buf[sizeof(PATH_ESC_CHARS)]; int j = 0; - /* Don't escape '[', '{' and '!' if they are in 'isfname'. */ - for (p = PATH_ESC_CHARS; *p != NUL; ++p) - if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) - buf[j++] = *p; + // Don't escape '[', '{' and '!' if they are in 'isfname'. + for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) { + if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) { + buf[j++] = *s; + } + } buf[j] = NUL; - p = vim_strsave_escaped(fname, buf); + char *p = (char *)vim_strsave_escaped((const char_u *)fname, + (const char_u *)buf); #else #define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") #define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") - p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); + char *p = (char *)vim_strsave_escaped( + (const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS)); if (shell && csh_like_shell()) { - /* For csh and similar shells need to put two backslashes before '!'. - * One is taken by Vim, one by the shell. */ - char_u *s = vim_strsave_escaped(p, (char_u *)"!"); + // For csh and similar shells need to put two backslashes before '!'. + // One is taken by Vim, one by the shell. + char *s = (char *)vim_strsave_escaped((const char_u *)p, + (const char_u *)"!"); xfree(p); p = s; } #endif - /* '>' and '+' are special at the start of some commands, e.g. ":edit" and - * ":write". "cd -" has a special meaning. */ + // '>' and '+' are special at the start of some commands, e.g. ":edit" and + // ":write". "cd -" has a special meaning. if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) { - escape_fname(&p); + escape_fname((char_u **)&p); } return p; @@ -4197,9 +4206,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u keep; garray_T ga; - retstr = call_user_expand_func(call_func_retstr, xp, num_file, file); - if (retstr == NULL) + retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, + num_file, file); + if (retstr == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); for (s = retstr; *s != NUL; s = e) { @@ -4237,9 +4248,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) listitem_T *li; garray_T ga; - retlist = call_user_expand_func(call_func_retlist, xp, num_file, file); - if (retlist == NULL) + retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp, + num_file, file); + if (retlist == NULL) { return FAIL; + } ga_init(&ga, (int)sizeof(char *), 3); /* Loop over the items in the list. */ -- cgit From c8e63a8db84e9d9f7bd855085a87d93631504fc7 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 4 Sep 2016 02:25:24 +0300 Subject: eval: Move remaining get_tv_string* functions to eval/typval.c --- src/nvim/ex_getln.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 3bd8d580ab..a0981a42ce 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2554,19 +2554,22 @@ void cmdline_paste_str(char_u *s, int literally) else while (*s != NUL) { cv = *s; - if (cv == Ctrl_V && s[1]) - ++s; - if (has_mbyte) - c = mb_cptr2char_adv(&s); - else + if (cv == Ctrl_V && s[1]) { + s++; + } + if (has_mbyte) { + c = mb_cptr2char_adv((const char_u **)&s); + } else { c = *s++; + } if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL || c == Ctrl_L #ifdef UNIX || c == intr_char #endif - || (c == Ctrl_BSL && *s == Ctrl_N)) + || (c == Ctrl_BSL && *s == Ctrl_N)) { stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(c); } } @@ -4636,7 +4639,7 @@ in_history ( /// /// @return Any value from HistoryType enum, including HIST_INVALID. May not /// return HIST_DEFAULT unless return_default is true. -HistoryType get_histtype(const char_u *const name, const size_t len, +HistoryType get_histtype(const char *const name, const size_t len, const bool return_default) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { @@ -5029,7 +5032,7 @@ void ex_history(exarg_T *eap) while (ASCII_ISALPHA(*end) || vim_strchr((char_u *)":=@>/?", *end) != NULL) end++; - histype1 = get_histtype(arg, end - arg, false); + histype1 = get_histtype((const char *)arg, end - arg, false); if (histype1 == HIST_INVALID) { if (STRNICMP(arg, "all", end - arg) == 0) { histype1 = 0; @@ -5288,18 +5291,18 @@ static int ex_window(void) cmdwin_result = Ctrl_C; /* Set the new command line from the cmdline buffer. */ xfree(ccline.cmdbuff); - if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */ - char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; + if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed + const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; if (histtype == HIST_CMD) { - /* Execute the command directly. */ - ccline.cmdbuff = vim_strsave((char_u *)p); + // Execute the command directly. + ccline.cmdbuff = (char_u *)xstrdup(p); cmdwin_result = CAR; } else { - /* First need to cancel what we were doing. */ + // First need to cancel what we were doing. ccline.cmdbuff = NULL; stuffcharReadbuff(':'); - stuffReadbuff((char_u *)p); + stuffReadbuff(p); stuffcharReadbuff(CAR); } } else if (cmdwin_result == K_XF2) { /* :qa typed */ -- cgit From 4bcee963471abd939bb9edd1709418e30be7290f Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 5 Nov 2016 01:03:44 +0300 Subject: *: Fix some Windows-specific warnings Also fixed an error in path_fnamecmp(). --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a0981a42ce..e140dfa886 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -579,7 +579,7 @@ static int command_line_execute(VimState *state, int key) } if (vim_ispathsep(ccline.cmdbuff[s->j]) #ifdef BACKSLASH_IN_FILENAME - && vim_strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1]) + && strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1]) == NULL #endif ) { -- cgit From a1d590a08bd9d40d0e20a9907381573c2d069738 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 28 Mar 2017 02:17:51 +0300 Subject: *: Use const char * in set_one_cmd_context Also renames functions added in master and renamed here. --- src/nvim/ex_getln.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e140dfa886..8810204c03 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3636,7 +3636,6 @@ set_cmd_context ( ) { int old_char = NUL; - char_u *nextcomm; /* * Avoid a UMR warning from Purify, only save the character if it has been @@ -3645,7 +3644,7 @@ set_cmd_context ( if (col < len) old_char = str[col]; str[col] = NUL; - nextcomm = str; + const char *nextcomm = (const char *)str; if (use_ccline && ccline.cmdfirstc == '=') { // pass CMD_SIZE because there is no real command @@ -3654,9 +3653,11 @@ set_cmd_context ( xp->xp_context = ccline.xp_context; xp->xp_pattern = ccline.cmdbuff; xp->xp_arg = ccline.xp_arg; - } else - while (nextcomm != NULL) + } else { + while (nextcomm != NULL) { nextcomm = set_one_cmd_context(xp, nextcomm); + } + } /* Store the string here so that call_user_expand_func() can get to them * easily. */ -- cgit From db9ef6263ec5b7885782ccf0a93e06b0c71f6944 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 8 Apr 2017 16:45:38 +0200 Subject: mbyte: replace vim_tolower with mb_tolower handling locale correctly --- src/nvim/ex_getln.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8810204c03..9d74f554ba 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1231,7 +1231,7 @@ static int command_line_handle_key(CommandLineState *s) // command line has no uppercase characters, convert // the character to lowercase if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) { - s->c = vim_tolower(s->c); + s->c = mb_tolower(s->c); } if (s->c != NUL) { @@ -3018,7 +3018,7 @@ ExpandOne ( || xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_BUFFERS)) { - if (vim_tolower(c0) != vim_tolower(ci)) { + if (mb_tolower(c0) != mb_tolower(ci)) { break; } } else if (c0 != ci) { -- cgit From 2d72d85b23761383ac7838faed2f7b53bdce8817 Mon Sep 17 00:00:00 2001 From: Felipe Oliveira Carvalho Date: Tue, 11 Apr 2017 22:44:48 +0200 Subject: refactor: pos_T macros to functions (#6496) --- src/nvim/ex_getln.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9d74f554ba..0b6036ace9 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -30,6 +30,7 @@ #include "nvim/if_cscope.h" #include "nvim/indent.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/menu.h" -- cgit From c2f3e361c52ec4e7149ea1d8c6a1202e0873da8e Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 19 Apr 2017 19:11:50 +0300 Subject: *: Add comment to all C files --- src/nvim/ex_getln.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0b6036ace9..1affdb2fe7 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * ex_getln.c: Functions for entering and editing an Ex command line. */ -- cgit From 9cdbbd49825561d642705990a2704b2241cf0584 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 17 Apr 2017 11:32:14 +0200 Subject: ui: support more cursor shape modes throttle unneccessary cursor shape events --- src/nvim/ex_getln.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0b6036ace9..5d228e7492 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -351,6 +351,7 @@ static int command_line_check(VimState *state) quit_more = false; // reset after CTRL-D which had a more-prompt cursorcmd(); // set the cursor on the right spot + ui_cursor_shape(); return 1; } @@ -2092,6 +2093,18 @@ redraw: return (char_u *)line_ga.ga_data; } +bool cmdline_overstrike(void) +{ + return ccline.overstrike; +} + + +/// Return true if the cursor is at the end of the cmdline. +bool cmdline_at_end(void) +{ + return (ccline.cmdpos >= ccline.cmdlen); +} + /* * Allocate a new command line buffer. * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. @@ -2262,6 +2275,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2281,6 +2295,7 @@ void unputcmdline(void) draw_cmdline(ccline.cmdpos, 1); msg_no_more = FALSE; cursorcmd(); + ui_cursor_shape(); } /* @@ -2598,6 +2613,7 @@ void redrawcmdline(void) compute_cmdrow(); redrawcmd(); cursorcmd(); + ui_cursor_shape(); } static void redrawcmdprompt(void) -- cgit From de50c003d5b1097f93690a0d9dc5fb03a2818024 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 3 May 2017 04:12:38 -0400 Subject: Use vim_strchr(s, c) when c may be NUL (#6656) As part of the refactoring in #5119, some vim_strchr() were changed to strchr(). However, vim_strchr() behaves differently than strchr() when c is NUL, returning NULL instead of a pointer to the NUL. Revert the strchr() calls where it isn't known whether c is NUL, since this causes a semantic change the surrounding code doesn't expect. In the case of #6650, this led to a heap overrun. Closes #6650 --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index eed4bf6066..ff68de7670 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -584,7 +584,7 @@ static int command_line_execute(VimState *state, int key) } if (vim_ispathsep(ccline.cmdbuff[s->j]) #ifdef BACKSLASH_IN_FILENAME - && strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1]) + && vim_strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1]) == NULL #endif ) { -- cgit From 0ff959329bb8a8ae22856a65b5289b41bdae433a Mon Sep 17 00:00:00 2001 From: James McCoy Date: Thu, 20 Apr 2017 01:17:42 -0400 Subject: *: Comment intentional fallthroughs Falling through a switch case should be commented so it's clear that behavior is intentional. --- src/nvim/ex_getln.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index fe45ba4568..8945f807da 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1268,6 +1268,7 @@ static int command_line_handle_key(CommandLineState *s) } return command_line_changed(s); } + // fallthrough case K_UP: case K_DOWN: -- cgit From 50398e10fef8462a56266f2cedffd34d1b59d9bb Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 12 May 2017 20:05:24 +0300 Subject: ex_getln: Fix :lang code execution when skipping Fixes #6727 --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index fe45ba4568..f74086e45a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5401,7 +5401,7 @@ char *script_get(exarg_T *const eap, size_t *const lenp) if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) { *lenp = STRLEN(eap->arg); - return xmemdupz(eap->arg, *lenp); + return eap->skip ? NULL : xmemdupz(eap->arg, *lenp); } garray_T ga = { .ga_data = NULL, .ga_len = 0 }; -- cgit From 3f553ac0b9b3866f1254e669eb0c1c019c789a60 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 2 Jun 2017 15:42:37 +0200 Subject: lint: fix indentation of FUNC_ATTR lines --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0c14bf4255..2b4997928e 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4073,7 +4073,7 @@ void ExpandGeneric( /// @param flagsarg is a combination of EW_* flags. static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ALL { char_u *pat; int i; -- cgit From 81be7358be00d3d75453659bcdc7efc69207ca8e Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 16 Nov 2016 11:09:04 -0500 Subject: vim-patch:7.4.1976 Problem: Number variables are not 64 bits while they could be. Solution: Add the num64 feature. (Ken Takata) https://github.com/vim/vim/commit/22fcfad29276bd5f317faf516637dcd491b96a12 --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2b4997928e..b27d778140 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5004,7 +5004,7 @@ int get_list_range(char_u **str, int *num1, int *num2) { int len; int first = false; - long num; + varnumber_T num; *str = skipwhite(*str); if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range -- cgit From cb8efa4fefd845e6cf42c9d14384bd291327cfe8 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 5 Jun 2017 23:05:28 -0400 Subject: vim-patch:8.0.0360 Problem: Sometimes VimL is used, which is confusing. Solution: Consistently use "Vim script". (Hirohito Higashi) https://github.com/vim/vim/commit/b544f3c81f1e6a50322855681ac266ffaa8e313c --- src/nvim/ex_getln.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2b4997928e..36b6bac9c3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4174,10 +4174,8 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, } } -/* - * Call "user_expand_func()" to invoke a user defined VimL function and return - * the result (either a string or a List). - */ +/// Call "user_expand_func()" to invoke a user defined Vim script function and +/// return the result (either a string or a List). static void * call_user_expand_func(user_expand_func_T user_expand_func, expand_T *xp, int *num_file, char_u ***file) { -- cgit From 7955cf35158f56a207ece32127adece23fd0fba1 Mon Sep 17 00:00:00 2001 From: raichoo Date: Sat, 25 Mar 2017 14:09:31 +0100 Subject: vim-patch:7.4.2259 Problem: With 'incsearch' can only see the next match. Solution: Make CTRL-N/CTRL-P move to the previous/next match. (Christian Brabandt) https://github.com/vim/vim/commit/4d6f32cbfbaf324ac4a25c0206a5db0e9f7a48f7 --- src/nvim/ex_getln.c | 140 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 26 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 858374c68e..efa8cd24bc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -106,6 +106,9 @@ typedef struct command_line_state { linenr_T old_topline; int old_topfill; linenr_T old_botline; + pos_T cursor_start; + pos_T match_start; + pos_T match_end; int did_incsearch; int incsearch_postponed; int did_wild_list; // did wild_list() recently @@ -167,6 +170,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_State = State; s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; + s->match_start = curwin->w_cursor; if (s->firstc == -1) { s->firstc = NUL; @@ -179,7 +183,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) } ccline.overstrike = false; // always start in insert mode + clearpos(&s->match_end); s->old_cursor = curwin->w_cursor; // needs to be restored later + s->cursor_start = s->old_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -283,6 +289,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) if (s->did_incsearch) { curwin->w_cursor = s->old_cursor; + if (s->gotesc) { + curwin->w_cursor = s->cursor_start; + } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; @@ -929,6 +938,12 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->old_cursor = s->cursor_start; + } else { + s->old_cursor = s->match_start; + decl(&s->old_cursor); + } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W && ccline.cmdprompt == NULL && s->indent == 0) { @@ -1001,6 +1016,9 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; + if (ccline.cmdlen == 0) { + s->old_cursor = s->cursor_start; + } redrawcmd(); return command_line_changed(s); @@ -1230,24 +1248,27 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_L: if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { // Add a character from under the cursor for 'incsearch' - if (s->did_incsearch && !equalpos(curwin->w_cursor, s->old_cursor)) { - s->c = gchar_cursor(); - // If 'ignorecase' and 'smartcase' are set and the - // command line has no uppercase characters, convert - // the character to lowercase - if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) { - s->c = mb_tolower(s->c); - } - - if (s->c != NUL) { - if (s->c == s->firstc - || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) - != NULL) { - // put a backslash before special characters - stuffcharReadbuff(s->c); - s->c = '\\'; + if (s->did_incsearch) { + curwin->w_cursor = s->match_end; + if (!equalpos(curwin->w_cursor, s->old_cursor)) { + s->c = gchar_cursor(); + // If 'ignorecase' and 'smartcase' are set and the + // command line has no uppercase characters, convert + // the character to lowercase + if (p_ic && p_scs + && !pat_has_uppercase(ccline.cmdbuff)) { + s->c = mb_tolower(s->c); + } + if (s->c != NUL) { + if (s->c == s->firstc + || vim_strchr((char_u *)(p_magic ? "\\^$.*[" : "\\^$"), s->c) + != NULL) { + // put a backslash before special characters + stuffcharReadbuff(s->c); + s->c = '\\'; + } + break; } - break; } } return command_line_not_changed(s); @@ -1261,7 +1282,67 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_N: // next match case Ctrl_P: // previous match - if (s->xpc.xp_numfiles > 0) { + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + + if (char_avail()) { + return 1; + } + ui_busy_start(); + ui_flush(); + if (s->c == Ctrl_N) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + s->c == Ctrl_N ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->old_cursor = s->match_start; + s->match_end = t; + s->match_start = t; + if (s->c == Ctrl_P && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->old_cursor = t; + (void)decl(&s->old_cursor); + } + if (lt(t, s->old_cursor) && s->c == Ctrl_N) { + // wrap around + s->old_cursor = t; + if (s->firstc == '?') { + (void)incl(&s->old_cursor); + } else { + (void)decl(&s->old_cursor); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return command_line_not_changed(s); + } else if (s->xpc.xp_numfiles > 0) { if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 0, s->firstc != '@') == FAIL) { break; @@ -1566,16 +1647,11 @@ static int command_line_changed(CommandLineState *s) if (s->i != 0) { pos_T save_pos = curwin->w_cursor; - // First move cursor to end of match, then to the start. This - // moves the whole match onto the screen when 'nowrap' is set. - curwin->w_cursor.lnum += search_match_lines; - curwin->w_cursor.col = search_match_endcol; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - coladvance((colnr_T)MAXCOL); - } + s->match_start = curwin->w_cursor; + set_search_match(&curwin->w_cursor); validate_cursor(); end_pos = curwin->w_cursor; + s->match_end = end_pos; curwin->w_cursor = save_pos; } else { end_pos = curwin->w_cursor; // shutup gcc 4 @@ -5519,3 +5595,15 @@ histentry_T *hist_get_array(const uint8_t history_type, int **const new_hisidx, *new_hisnum = &(hisnum[history_type]); return history[history_type]; } + +static void set_search_match(pos_T *t) +{ + // First move cursor to end of match, then to the start. This + // moves the whole match onto the screen when 'nowrap' is set. + t->lnum += search_match_lines; + t->col = search_match_endcol; + if (t->lnum > curbuf->b_ml.ml_line_count) { + t->lnum = curbuf->b_ml.ml_line_count; + coladvance((colnr_T)MAXCOL); + } +} -- cgit From 90f62cc749da78afc9891bb03a195b79d0bedcff Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 26 Mar 2017 01:34:13 +0300 Subject: ex_getln: Clean up draw_cmdline a bit --- src/nvim/ex_getln.c | 70 +++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 37 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 858374c68e..013f936137 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2174,69 +2174,64 @@ void free_cmdline_buf(void) */ static void draw_cmdline(int start, int len) { - int i; - - if (cmdline_star > 0) - for (i = 0; i < len; ++i) { + if (cmdline_star > 0) { + for (int i = 0; i < len; i++) { msg_putchar('*'); - if (has_mbyte) + if (has_mbyte) { i += (*mb_ptr2len)(ccline.cmdbuff + start + i) - 1; + } } - else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { + } else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { static int buflen = 0; - char_u *p; - int j; - int newlen = 0; - int mb_l; - int pc, pc1 = 0; - int prev_c = 0; - int prev_c1 = 0; - int u8c; - int u8cc[MAX_MCO]; - int nc = 0; - /* - * Do arabic shaping into a temporary buffer. This is very - * inefficient! - */ + // Do arabic shaping into a temporary buffer. This is very + // inefficient! if (len * 2 + 2 > buflen) { - /* Re-allocate the buffer. We keep it around to avoid a lot of - * alloc()/free() calls. */ + // Re-allocate the buffer. We keep it around to avoid a lot of + // alloc()/free() calls. xfree(arshape_buf); buflen = len * 2 + 2; arshape_buf = xmalloc(buflen); } + int newlen = 0; if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) { - /* Prepend a space to draw the leading composing char on. */ + // Prepend a space to draw the leading composing char on. arshape_buf[0] = ' '; newlen = 1; } - for (j = start; j < start + len; j += mb_l) { - p = ccline.cmdbuff + j; - u8c = utfc_ptr2char_len(p, u8cc, start + len - j); - mb_l = utfc_ptr2len_len(p, start + len - j); + int mb_l; + int prev_c = 0; + int prev_c1 = 0; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); if (arabic_char(u8c)) { - /* Do Arabic shaping. */ + int pc; + int pc1 = 0; + int nc = 0; + // Do Arabic shaping. if (cmdmsg_rl) { - /* displaying from right to left */ + // Displaying from right to left. pc = prev_c; pc1 = prev_c1; prev_c1 = u8cc[0]; - if (j + mb_l >= start + len) + if (i + mb_l >= start + len) { nc = NUL; - else + } else { nc = utf_ptr2char(p + mb_l); + } } else { - /* displaying from left to right */ - if (j + mb_l >= start + len) + // Displaying from left to right. + if (i + mb_l >= start + len) { pc = NUL; - else { + } else { int pcc[MAX_MCO]; - pc = utfc_ptr2char_len(p + mb_l, pcc, - start + len - j - mb_l); + pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l); pc1 = pcc[0]; } nc = prev_c; @@ -2260,8 +2255,9 @@ static void draw_cmdline(int start, int len) } msg_outtrans_len(arshape_buf, newlen); - } else + } else { msg_outtrans_len(ccline.cmdbuff + start, len); + } } /* -- cgit From 7db2f658e87278885a137ac2b0b88df6a1b546cb Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 26 Mar 2017 01:38:43 +0300 Subject: ex_getln: Do not do arabic shaping unless needed Should speed up execution without arabic characters a bit, slowing down with arabic characters. More necessary, this allows coloring prompt without caring about arabic shaping at the first iteration. --- src/nvim/ex_getln.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 013f936137..632f125b45 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2182,6 +2182,22 @@ static void draw_cmdline(int start, int len) } } } else if (p_arshape && !p_tbidi && enc_utf8 && len > 0) { + bool do_arabicshape = false; + int mb_l; + for (int i = start; i < start + len; i += mb_l) { + char_u *p = ccline.cmdbuff + i; + int u8cc[MAX_MCO]; + int u8c = utfc_ptr2char_len(p, u8cc, start + len - i); + mb_l = utfc_ptr2len_len(p, start + len - i); + if (arabic_char(u8c)) { + do_arabicshape = true; + break; + } + } + if (!do_arabicshape) { + goto draw_cmdline_no_arabicshape; + } + static int buflen = 0; // Do arabic shaping into a temporary buffer. This is very @@ -2201,7 +2217,6 @@ static void draw_cmdline(int start, int len) newlen = 1; } - int mb_l; int prev_c = 0; int prev_c1 = 0; for (int i = start; i < start + len; i += mb_l) { @@ -2256,6 +2271,7 @@ static void draw_cmdline(int start, int len) msg_outtrans_len(arshape_buf, newlen); } else { +draw_cmdline_no_arabicshape: msg_outtrans_len(ccline.cmdbuff + start, len); } } -- cgit From c1d21e9dd67cdea5e133bb1b79fc1765d20c191b Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 26 Mar 2017 03:40:59 +0300 Subject: ex_getln: Add basic support for coloring command-line prompt --- src/nvim/ex_getln.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 632f125b45..b08407233f 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -62,6 +62,7 @@ #include "nvim/os/os.h" #include "nvim/event/loop.h" #include "nvim/os/time.h" +#include "nvim/lib/kvec.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -127,6 +128,15 @@ typedef struct command_line_state { struct cmdline_info save_ccline; } CommandLineState; +/// Command-line colors +typedef struct { + int start; ///< Colored chunk start. + int end; ///< Colored chunk end (exclusive, > start). + int attr; ///< Highlight attr. +} ColoredCmdlineChunk; + +kvec_t(ColoredCmdlineChunk) ccline_colors; + /* The current cmdline_info. It is initialized in getcmdline() and after that * used by other functions. When invoking getcmdline() recursively it needs * to be saved with save_cmdline() and restored with restore_cmdline(). @@ -2168,6 +2178,139 @@ void free_cmdline_buf(void) # endif +/// Color command-line +/// +/// Should use built-in command parser or user-specified one. Currently only the +/// latter is supported. +/// +/// Operates on ccline, saving results to ccline_colors. +/// +/// Always colors the whole cmdline. +static void color_cmdline(void) +{ + kv_size(ccline_colors) = 0; + if (ccline.cmdfirstc != ':') { + return; + } + static Callback prev_cb = { .type = kCallbackNone }; + static int prev_cb_errors = 0; + Callback color_cb; + if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb)) { + return; + } + if (color_cb.type == kCallbackNone) { + return; + } + if (prev_cb_errors == 5 && tv_callback_equal(&prev_cb, &color_cb)) { + return; + } + callback_free(&prev_cb); + prev_cb = color_cb; + bool arg_allocated; + typval_T arg = { + .v_type = VAR_STRING, + }; + if (ccline.cmdbuff[ccline.cmdlen] == NUL) { + arg_allocated = false; + arg.vval.v_string = ccline.cmdbuff; + } else { + arg_allocated = true; + arg.vval.v_string = xmemdupz((const char *)ccline.cmdbuff, + (size_t)ccline.cmdlen); + } + typval_T tv; + msg_silent++; + if (!callback_call(&color_cb, 1, &arg, &tv)) { + msg_silent--; + goto color_cmdline_end; + } + msg_silent--; + if (tv.v_type != VAR_LIST || tv.vval.v_list == NULL) { + emsgf(_("E5400: Callback should return list")); + goto color_cmdline_error; + } + varnumber_T prev_end = 0; + int i = 0; + for (const listitem_T *li = tv.vval.v_list->lv_first; + li != NULL; li = li->li_next, i++) { + if (li->li_tv.v_type != VAR_LIST) { + emsgf(_("E5401: List item %i is not a List"), i); + goto color_cmdline_error; + } + const list_T *const l = li->li_tv.vval.v_list; + if (tv_list_len(l) != 3) { + emsgf(_("E5402: List item %i has incorrect length: %li /= 3"), + i, tv_list_len(l)); + goto color_cmdline_error; + } + bool error = false; + const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); + if (error) { + goto color_cmdline_error; + } else if (!(prev_end <= start && start <= ccline.cmdlen)) { + emsgf(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " + "[%" PRIdVARNUMBER ", %i]"), + i, start, prev_end, ccline.cmdlen); + goto color_cmdline_error; + } + if (start != prev_end) { + kv_push(ccline_colors, ((ColoredCmdlineChunk) { + .start = prev_end, + .end = start, + .attr = 0, + })); + } + const varnumber_T end = tv_get_number_chk(&l->lv_first->li_next->li_tv, + &error); + if (error) { + goto color_cmdline_error; + } else if (!(start < end && end <= ccline.cmdlen)) { + emsgf(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " + "(%" PRIdVARNUMBER ", %i]"), + i, end, start, ccline.cmdlen); + goto color_cmdline_error; + } + prev_end = end; + const char *const group = tv_get_string_chk(&l->lv_last->li_tv); + if (group == NULL) { + goto color_cmdline_error; + } + const int id = syn_name2id((char_u *)group); + const int attr = (id == 0 ? 0 : syn_id2attr(id)); + kv_push(ccline_colors, ((ColoredCmdlineChunk) { + .start = start, + .end = end, + .attr = attr, + })); + } + if (prev_end < ccline.cmdlen) { + kv_push(ccline_colors, ((ColoredCmdlineChunk) { + .start = prev_end, + .end = ccline.cmdlen, + .attr = 0, + })); + } + prev_cb_errors = 0; +color_cmdline_end: + if (arg_allocated) { + tv_clear(&arg); + } + tv_clear(&tv); + return; +color_cmdline_error: + prev_cb_errors++; + did_emsg = false; + if (did_throw) { + discard_current_exception(); + } + if (msg_list != NULL && *msg_list != NULL) { + free_global_msglist(); + } + kv_size(ccline_colors) = 0; + goto color_cmdline_end; +} + /* * Draw part of the cmdline at the current cursor position. But draw stars * when cmdline_star is TRUE. @@ -2272,7 +2415,21 @@ static void draw_cmdline(int start, int len) msg_outtrans_len(arshape_buf, newlen); } else { draw_cmdline_no_arabicshape: - msg_outtrans_len(ccline.cmdbuff + start, len); + color_cmdline(); + if (kv_size(ccline_colors)) { + for (size_t i = 0; i < kv_size(ccline_colors); i++) { + ColoredCmdlineChunk chunk = kv_A(ccline_colors, i); + if (chunk.end <= start) { + continue; + } + const int chunk_start = MAX(chunk.start, start); + msg_outtrans_len_attr(ccline.cmdbuff + chunk_start, + chunk.end - chunk_start, + chunk.attr); + } + } else { + msg_outtrans_len(ccline.cmdbuff + start, len); + } } } -- cgit From d82741f8c04d003bb9925d9c46d7e07179810ed4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 26 Mar 2017 17:25:03 +0300 Subject: ex_getln: Add some more tests, fix some found errors --- src/nvim/ex_getln.c | 92 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 21 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index b08407233f..e4914d6ebc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2178,6 +2178,8 @@ void free_cmdline_buf(void) # endif +enum { MAX_CB_ERRORS = 5 }; + /// Color command-line /// /// Should use built-in command parser or user-specified one. Currently only the @@ -2186,50 +2188,77 @@ void free_cmdline_buf(void) /// Operates on ccline, saving results to ccline_colors. /// /// Always colors the whole cmdline. -static void color_cmdline(void) +/// +/// @return true if draw_cmdline may proceed, false if it does not need anything +/// to do. +static bool color_cmdline(void) { + bool ret = true; kv_size(ccline_colors) = 0; if (ccline.cmdfirstc != ':') { - return; + return ret; } + + const int saved_force_abort = force_abort; + force_abort = true; + bool arg_allocated = false; + typval_T arg = { + .v_type = VAR_STRING, + .vval.v_string = ccline.cmdbuff, + }; + typval_T tv = { .v_type = VAR_UNKNOWN }; + static Callback prev_cb = { .type = kCallbackNone }; static int prev_cb_errors = 0; Callback color_cb; if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), &color_cb)) { - return; + goto color_cmdline_error; } if (color_cb.type == kCallbackNone) { - return; + goto color_cmdline_end; } - if (prev_cb_errors == 5 && tv_callback_equal(&prev_cb, &color_cb)) { - return; + if (!tv_callback_equal(&prev_cb, &color_cb)) { + prev_cb_errors = 0; + } else if (prev_cb_errors >= MAX_CB_ERRORS) { + callback_free(&color_cb); + goto color_cmdline_end; } callback_free(&prev_cb); prev_cb = color_cb; - bool arg_allocated; - typval_T arg = { - .v_type = VAR_STRING, - }; - if (ccline.cmdbuff[ccline.cmdlen] == NUL) { - arg_allocated = false; - arg.vval.v_string = ccline.cmdbuff; - } else { + if (ccline.cmdbuff[ccline.cmdlen] != NUL) { arg_allocated = true; arg.vval.v_string = xmemdupz((const char *)ccline.cmdbuff, (size_t)ccline.cmdlen); } - typval_T tv; + // msg_start() called by e.g. :echo may shift command-line to the first column + // even though msg_silent is here. Two ways to workaround this problem without + // altering message.c: use full_screen or save and restore msg_col. + // + // Saving and restoring full_screen does not work well with :redraw!. Saving + // and restoring msg_col is neither ideal, but while with full_screen it + // appears shifted one character to the right and cursor position is no longer + // correct, with msg_col it just misses leading `:`. Since `redraw!` in + // callback lags this is least of the user problems. + const int saved_msg_col = msg_col; msg_silent++; if (!callback_call(&color_cb, 1, &arg, &tv)) { msg_silent--; - goto color_cmdline_end; + msg_col = saved_msg_col; + goto color_cmdline_error; } msg_silent--; - if (tv.v_type != VAR_LIST || tv.vval.v_list == NULL) { + msg_col = saved_msg_col; + if (got_int || did_emsg) { + goto color_cmdline_error; + } + if (tv.v_type != VAR_LIST) { emsgf(_("E5400: Callback should return list")); goto color_cmdline_error; } + if (tv.vval.v_list == NULL) { + goto color_cmdline_end; + } varnumber_T prev_end = 0; int i = 0; for (const listitem_T *li = tv.vval.v_list->lv_first; @@ -2248,11 +2277,15 @@ static void color_cmdline(void) const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); if (error) { goto color_cmdline_error; - } else if (!(prev_end <= start && start <= ccline.cmdlen)) { + } else if (!(prev_end <= start && start < ccline.cmdlen)) { emsgf(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " - "[%" PRIdVARNUMBER ", %i]"), + "[%" PRIdVARNUMBER ", %i)"), i, start, prev_end, ccline.cmdlen); goto color_cmdline_error; + } else if (utf8len_tab_zero[(uint8_t)ccline.cmdbuff[start]] == 0) { + emsgf(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits multibyte " + "character"), i, start); + goto color_cmdline_error; } if (start != prev_end) { kv_push(ccline_colors, ((ColoredCmdlineChunk) { @@ -2270,6 +2303,11 @@ static void color_cmdline(void) "(%" PRIdVARNUMBER ", %i]"), i, end, start, ccline.cmdlen); goto color_cmdline_error; + } else if (end < ccline.cmdlen + && utf8len_tab_zero[(uint8_t)ccline.cmdbuff[end]] == 0) { + emsgf(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " + "character"), i, end); + goto color_cmdline_error; } prev_end = end; const char *const group = tv_get_string_chk(&l->lv_last->li_tv); @@ -2293,13 +2331,16 @@ static void color_cmdline(void) } prev_cb_errors = 0; color_cmdline_end: + force_abort = saved_force_abort; if (arg_allocated) { tv_clear(&arg); } tv_clear(&tv); - return; + return ret; color_cmdline_error: prev_cb_errors++; + const bool do_redraw = (did_emsg || got_int); + got_int = false; did_emsg = false; if (did_throw) { discard_current_exception(); @@ -2308,6 +2349,12 @@ color_cmdline_error: free_global_msglist(); } kv_size(ccline_colors) = 0; + if (do_redraw) { + prev_cb_errors += MAX_CB_ERRORS; + redrawcmdline(); + prev_cb_errors -= MAX_CB_ERRORS; + ret = false; + } goto color_cmdline_end; } @@ -2317,6 +2364,10 @@ color_cmdline_error: */ static void draw_cmdline(int start, int len) { + if (!color_cmdline()) { + return; + } + if (cmdline_star > 0) { for (int i = 0; i < len; i++) { msg_putchar('*'); @@ -2415,7 +2466,6 @@ static void draw_cmdline(int start, int len) msg_outtrans_len(arshape_buf, newlen); } else { draw_cmdline_no_arabicshape: - color_cmdline(); if (kv_size(ccline_colors)) { for (size_t i = 0; i < kv_size(ccline_colors); i++) { ColoredCmdlineChunk chunk = kv_A(ccline_colors, i); -- cgit From 407abb3a6c5c1c706bf8797a1431e57e97a6b797 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 2 Apr 2017 01:00:40 +0300 Subject: eval,ex_getln: Add support for coloring input() prompts --- src/nvim/ex_getln.c | 88 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 36 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e4914d6ebc..a2cc6d2b65 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -70,23 +70,26 @@ * structure. */ struct cmdline_info { - char_u *cmdbuff; /* pointer to command line buffer */ - int cmdbufflen; /* length of cmdbuff */ - int cmdlen; /* number of chars in command line */ - int cmdpos; /* current cursor position */ - int cmdspos; /* cursor column on screen */ - int cmdfirstc; /* ':', '/', '?', '=', '>' or NUL */ - int cmdindent; /* number of spaces before cmdline */ - char_u *cmdprompt; /* message in front of cmdline */ - int cmdattr; /* attributes for prompt */ - int overstrike; /* Typing mode on the command line. Shared by - getcmdline() and put_on_cmdline(). */ - expand_T *xpc; /* struct being used for expansion, xp_pattern - may point into cmdbuff */ - int xp_context; /* type of expansion */ - char_u *xp_arg; /* user-defined expansion arg */ - int input_fn; /* when TRUE Invoked for input() function */ + char_u *cmdbuff; // pointer to command line buffer + int cmdbufflen; // length of cmdbuff + int cmdlen; // number of chars in command line + int cmdpos; // current cursor position + int cmdspos; // cursor column on screen + int cmdfirstc; // ':', '/', '?', '=', '>' or NUL + int cmdindent; // number of spaces before cmdline + char_u *cmdprompt; // message in front of cmdline + int cmdattr; // attributes for prompt + int overstrike; // Typing mode on the command line. Shared by + // getcmdline() and put_on_cmdline(). + expand_T *xpc; // struct being used for expansion, xp_pattern + // may point into cmdbuff + int xp_context; // type of expansion + char_u *xp_arg; // user-defined expansion arg + int input_fn; // when TRUE Invoked for input() function + unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. }; +/// Last value of prompt_id, incremented when doing new prompt +static unsigned last_prompt_id = 0; typedef struct command_line_state { VimState state; @@ -135,6 +138,9 @@ typedef struct { int attr; ///< Highlight attr. } ColoredCmdlineChunk; +/// Callback used for coloring input() prompts +Callback getln_input_callback = { .type = kCallbackNone }; + kvec_t(ColoredCmdlineChunk) ccline_colors; /* The current cmdline_info. It is initialized in getcmdline() and after that @@ -188,6 +194,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) cmd_hkmap = 0; } + ccline.prompt_id = last_prompt_id++; ccline.overstrike = false; // always start in insert mode s->old_cursor = curwin->w_cursor; // needs to be restored later s->old_curswant = curwin->w_curswant; @@ -1703,6 +1710,7 @@ getcmdline_prompt ( int msg_col_save = msg_col; save_cmdline(&save_ccline); + ccline.prompt_id = last_prompt_id++; ccline.cmdprompt = prompt; ccline.cmdattr = attr; ccline.xp_context = xp_context; @@ -2178,7 +2186,7 @@ void free_cmdline_buf(void) # endif -enum { MAX_CB_ERRORS = 5 }; +enum { MAX_CB_ERRORS = 1 }; /// Color command-line /// @@ -2195,9 +2203,6 @@ static bool color_cmdline(void) { bool ret = true; kv_size(ccline_colors) = 0; - if (ccline.cmdfirstc != ':') { - return ret; - } const int saved_force_abort = force_abort; force_abort = true; @@ -2208,24 +2213,32 @@ static bool color_cmdline(void) }; typval_T tv = { .v_type = VAR_UNKNOWN }; - static Callback prev_cb = { .type = kCallbackNone }; - static int prev_cb_errors = 0; - Callback color_cb; - if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), - &color_cb)) { - goto color_cmdline_error; + static unsigned prev_prompt_id = UINT_MAX; + static int prev_prompt_errors = 0; + Callback color_cb = { .type = kCallbackNone }; + bool can_free_cb = false; + + if (ccline.input_fn) { + color_cb = getln_input_callback; + } else if (ccline.cmdfirstc == ':') { + if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb)) { + goto color_cmdline_error; + } + can_free_cb = true; + } else { + goto color_cmdline_end; } + if (color_cb.type == kCallbackNone) { goto color_cmdline_end; } - if (!tv_callback_equal(&prev_cb, &color_cb)) { - prev_cb_errors = 0; - } else if (prev_cb_errors >= MAX_CB_ERRORS) { - callback_free(&color_cb); + if (ccline.prompt_id != prev_prompt_id) { + prev_prompt_errors = 0; + prev_prompt_id = ccline.prompt_id; + } else if (prev_prompt_errors >= MAX_CB_ERRORS) { goto color_cmdline_end; } - callback_free(&prev_cb); - prev_cb = color_cb; if (ccline.cmdbuff[ccline.cmdlen] != NUL) { arg_allocated = true; arg.vval.v_string = xmemdupz((const char *)ccline.cmdbuff, @@ -2329,8 +2342,11 @@ static bool color_cmdline(void) .attr = 0, })); } - prev_cb_errors = 0; + prev_prompt_errors = 0; color_cmdline_end: + if (can_free_cb) { + callback_free(&color_cb); + } force_abort = saved_force_abort; if (arg_allocated) { tv_clear(&arg); @@ -2338,7 +2354,7 @@ color_cmdline_end: tv_clear(&tv); return ret; color_cmdline_error: - prev_cb_errors++; + prev_prompt_errors++; const bool do_redraw = (did_emsg || got_int); got_int = false; did_emsg = false; @@ -2350,9 +2366,9 @@ color_cmdline_error: } kv_size(ccline_colors) = 0; if (do_redraw) { - prev_cb_errors += MAX_CB_ERRORS; + prev_prompt_errors += MAX_CB_ERRORS; redrawcmdline(); - prev_cb_errors -= MAX_CB_ERRORS; + prev_prompt_errors -= MAX_CB_ERRORS; ret = false; } goto color_cmdline_end; -- cgit From 072a853fa212bdce88f756ac170fb915a4972625 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 22 May 2017 22:44:08 +0300 Subject: ex_getln: Enable coloring for expression mode --- src/nvim/ex_getln.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a2cc6d2b65..f9b2d6cda8 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2226,6 +2226,12 @@ static bool color_cmdline(void) goto color_cmdline_error; } can_free_cb = true; + } else if (ccline.cmdfirstc == '=') { + if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), + &color_cb)) { + goto color_cmdline_error; + } + can_free_cb = true; } else { goto color_cmdline_end; } -- cgit From 0dd64556590633b2cab7cd846b28bbf5f7ef35d4 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 11:01:16 -0400 Subject: vim-patch:7.4.2268 Problem: Using CTRL-N and CTRL-P for incsearch shadows completion keys. Solution: Use CTRL-T and CTRL-G instead. https://github.com/vim/vim/commit/1195669f9e434fa9ab8b57ee9470bf951e4990b8 --- src/nvim/ex_getln.c | 128 +++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 62 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index efa8cd24bc..62f802fb8f 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1282,72 +1282,12 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_N: // next match case Ctrl_P: // previous match - if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { - pos_T t; - int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; - - if (char_avail()) { - return 1; - } - ui_busy_start(); - ui_flush(); - if (s->c == Ctrl_N) { - t = s->match_end; - search_flags += SEARCH_COL; - } else { - t = s->match_start; - } - emsg_off++; - s->i = searchit(curwin, curbuf, &t, - s->c == Ctrl_N ? FORWARD : BACKWARD, - ccline.cmdbuff, s->count, search_flags, - RE_SEARCH, 0, NULL); - emsg_off--; - ui_busy_stop(); - if (s->i) { - s->old_cursor = s->match_start; - s->match_end = t; - s->match_start = t; - if (s->c == Ctrl_P && s->firstc == '/') { - // move just before the current match, so that - // when nv_search finishes the cursor will be - // put back on the match - s->old_cursor = t; - (void)decl(&s->old_cursor); - } - if (lt(t, s->old_cursor) && s->c == Ctrl_N) { - // wrap around - s->old_cursor = t; - if (s->firstc == '?') { - (void)incl(&s->old_cursor); - } else { - (void)decl(&s->old_cursor); - } - } - - set_search_match(&s->match_end); - curwin->w_cursor = s->match_start; - changed_cline_bef_curs(); - update_topline(); - validate_cursor(); - highlight_match = true; - s->old_curswant = curwin->w_curswant; - s->old_leftcol = curwin->w_leftcol; - s->old_topline = curwin->w_topline; - s->old_topfill = curwin->w_topfill; - s->old_botline = curwin->w_botline; - update_screen(NOT_VALID); - redrawcmdline(); - } else { - vim_beep(BO_ERROR); - } - return command_line_not_changed(s); - } else if (s->xpc.xp_numfiles > 0) { + if (s->xpc.xp_numfiles > 0) { if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT, 0, s->firstc != '@') == FAIL) { break; } - return command_line_changed(s); + return command_line_not_changed(s); } // fallthrough @@ -1488,6 +1428,70 @@ static int command_line_handle_key(CommandLineState *s) beep_flush(); return command_line_not_changed(s); + case Ctrl_G: // next match + case Ctrl_T: // previous match + if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + + if (char_avail()) { + return 1; + } + ui_busy_start(); + ui_flush(); + if (s->c == Ctrl_G) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + s->c == Ctrl_G ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->old_cursor = s->match_start; + s->match_end = t; + s->match_start = t; + if (s->c == Ctrl_T && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->old_cursor = t; + (void)decl(&s->old_cursor); + } + if (lt(t, s->old_cursor) && s->c == Ctrl_G) { + // wrap around + s->old_cursor = t; + if (s->firstc == '?') { + (void)incl(&s->old_cursor); + } else { + (void)decl(&s->old_cursor); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + } + return command_line_not_changed(s); + case Ctrl_V: case Ctrl_Q: s->ignore_drag_release = true; -- cgit From 3679752dbd9191f4067a43143da637478cc389f1 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 12:11:22 -0400 Subject: vim-patch:7.4.2318 Problem: When 'incsearch' is not set CTRL-T and CTRL-G are not inserted as before. Solution: Move vim/vim#ifdef and don't use goto. https://github.com/vim/vim/commit/349e7d94e6bbb253bb87adad9039f095128ab543 --- src/nvim/ex_getln.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 62f802fb8f..45fff4f9d7 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1489,8 +1489,9 @@ static int command_line_handle_key(CommandLineState *s) } else { vim_beep(BO_ERROR); } + return command_line_not_changed(s); } - return command_line_not_changed(s); + break; case Ctrl_V: case Ctrl_Q: -- cgit From 54d5e90a2b87736a3248300ed423374e88ce8e79 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sun, 25 Jun 2017 12:15:58 -0400 Subject: vim-patch:7.4.2320 Problem: Redraw problem when using 'incsearch'. Solution: Save the current view when deleting characters. (Christian Brabandt) Fix that the '" mark is set in the wrong position. Don't change the search start when using BS. https://github.com/vim/vim/commit/dda933d06c06c2792bd686d059f6ad19191ad30b --- src/nvim/ex_getln.c | 63 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 21 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 45fff4f9d7..e8f9d9bf47 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -100,13 +100,18 @@ typedef struct command_line_state { char_u *lookfor; // string to match int hiscnt; // current history line in use int histype; // history type to be used - pos_T old_cursor; + pos_T search_start; // where 'incsearch' starts searching + pos_T save_cursor; colnr_T old_curswant; + colnr_T init_curswant; colnr_T old_leftcol; + colnr_T init_leftcol; linenr_T old_topline; + linenr_T init_topline; int old_topfill; + int init_topfill; linenr_T old_botline; - pos_T cursor_start; + linenr_T init_botline; pos_T match_start; pos_T match_end; int did_incsearch; @@ -171,6 +176,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) s->save_p_icm = vim_strsave(p_icm); s->ignore_drag_release = true; s->match_start = curwin->w_cursor; + s->init_curswant = curwin->w_curswant; + s->init_leftcol = curwin->w_leftcol; + s->init_topline = curwin->w_topline; + s->init_topfill = curwin->w_topfill; + s->init_botline = curwin->w_botline; if (s->firstc == -1) { s->firstc = NUL; @@ -184,8 +194,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.overstrike = false; // always start in insert mode clearpos(&s->match_end); - s->old_cursor = curwin->w_cursor; // needs to be restored later - s->cursor_start = s->old_cursor; + s->save_cursor = curwin->w_cursor; // may be restored later + s->search_start = curwin->w_cursor; s->old_curswant = curwin->w_curswant; s->old_leftcol = curwin->w_leftcol; s->old_topline = curwin->w_topline; @@ -288,9 +298,15 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.xpc = NULL; if (s->did_incsearch) { - curwin->w_cursor = s->old_cursor; if (s->gotesc) { - curwin->w_cursor = s->cursor_start; + curwin->w_cursor = s->save_cursor; + } else { + if (!equalpos(s->save_cursor, s->search_start)) { + // put the '" mark at the original position + curwin->w_cursor = s->save_cursor; + setpcmark(); + } + curwin->w_cursor = s->search_start; } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; @@ -939,10 +955,14 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; if (ccline.cmdlen == 0) { - s->old_cursor = s->cursor_start; - } else { - s->old_cursor = s->match_start; - decl(&s->old_cursor); + s->search_start = s->save_cursor; + // save view settings, so that the screen won't be restored at the + // wrong position + s->old_curswant = s->init_curswant; + s->old_leftcol = s->init_leftcol; + s->old_topline = s->init_topline; + s->old_topfill = s->init_topfill; + s->old_botline = s->init_botline; } redrawcmd(); } else if (ccline.cmdlen == 0 && s->c != Ctrl_W @@ -962,6 +982,7 @@ static int command_line_handle_key(CommandLineState *s) } msg_putchar(' '); // delete ':' } + s->search_start = s->save_cursor; redraw_cmdline = true; return 0; // back to cmd mode } @@ -1017,7 +1038,7 @@ static int command_line_handle_key(CommandLineState *s) // Truncate at the end, required for multi-byte chars. ccline.cmdbuff[ccline.cmdlen] = NUL; if (ccline.cmdlen == 0) { - s->old_cursor = s->cursor_start; + s->search_start = s->save_cursor; } redrawcmd(); return command_line_changed(s); @@ -1250,7 +1271,7 @@ static int command_line_handle_key(CommandLineState *s) // Add a character from under the cursor for 'incsearch' if (s->did_incsearch) { curwin->w_cursor = s->match_end; - if (!equalpos(curwin->w_cursor, s->old_cursor)) { + if (!equalpos(curwin->w_cursor, s->search_start)) { s->c = gchar_cursor(); // If 'ignorecase' and 'smartcase' are set and the // command line has no uppercase characters, convert @@ -1453,23 +1474,23 @@ static int command_line_handle_key(CommandLineState *s) emsg_off--; ui_busy_stop(); if (s->i) { - s->old_cursor = s->match_start; + s->search_start = s->match_start; s->match_end = t; s->match_start = t; if (s->c == Ctrl_T && s->firstc == '/') { // move just before the current match, so that // when nv_search finishes the cursor will be // put back on the match - s->old_cursor = t; - (void)decl(&s->old_cursor); + s->search_start = t; + (void)decl(&s->search_start); } - if (lt(t, s->old_cursor) && s->c == Ctrl_G) { + if (lt(t, s->search_start) && s->c == Ctrl_G) { // wrap around - s->old_cursor = t; + s->search_start = t; if (s->firstc == '?') { - (void)incl(&s->old_cursor); + (void)incl(&s->search_start); } else { - (void)decl(&s->old_cursor); + (void)decl(&s->search_start); } } @@ -1607,7 +1628,7 @@ static int command_line_changed(CommandLineState *s) return 1; } s->incsearch_postponed = false; - curwin->w_cursor = s->old_cursor; // start at old position + curwin->w_cursor = s->search_start; // start at old position // If there is no command line, don't do anything if (ccline.cmdlen == 0) { @@ -1698,7 +1719,7 @@ static int command_line_changed(CommandLineState *s) emsg_silent--; // Unblock error reporting // Restore the window "view". - curwin->w_cursor = s->old_cursor; + curwin->w_cursor = s->save_cursor; curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; curwin->w_topline = s->old_topline; -- cgit From 6a842132bcecb0d255fabf937694d1abfde1c86d Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 26 Jun 2017 19:12:06 -0400 Subject: ex_getln: Lint command_line_handle_key readability/fn_size Create new functions to handle moving to the next incsearch match or matching history index. --- src/nvim/ex_getln.c | 220 +++++++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 104 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e8f9d9bf47..7793081957 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -882,6 +882,118 @@ static int command_line_execute(VimState *state, int key) return command_line_handle_key(s); } +static void command_line_next_incsearch(CommandLineState *s, bool next_match) +{ + ui_busy_start(); + ui_flush(); + + pos_T t; + int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; + if (next_match) { + t = s->match_end; + search_flags += SEARCH_COL; + } else { + t = s->match_start; + } + emsg_off++; + s->i = searchit(curwin, curbuf, &t, + next_match ? FORWARD : BACKWARD, + ccline.cmdbuff, s->count, search_flags, + RE_SEARCH, 0, NULL); + emsg_off--; + ui_busy_stop(); + if (s->i) { + s->search_start = s->match_start; + s->match_end = t; + s->match_start = t; + if (!next_match && s->firstc == '/') { + // move just before the current match, so that + // when nv_search finishes the cursor will be + // put back on the match + s->search_start = t; + (void)decl(&s->search_start); + } + if (lt(t, s->search_start) && next_match) { + // wrap around + s->search_start = t; + if (s->firstc == '?') { + (void)incl(&s->search_start); + } else { + (void)decl(&s->search_start); + } + } + + set_search_match(&s->match_end); + curwin->w_cursor = s->match_start; + changed_cline_bef_curs(); + update_topline(); + validate_cursor(); + highlight_match = true; + s->old_curswant = curwin->w_curswant; + s->old_leftcol = curwin->w_leftcol; + s->old_topline = curwin->w_topline; + s->old_topfill = curwin->w_topfill; + s->old_botline = curwin->w_botline; + update_screen(NOT_VALID); + redrawcmdline(); + } else { + vim_beep(BO_ERROR); + } + return; +} + +static void command_line_next_histidx(CommandLineState *s, bool next_match) +{ + s->j = (int)STRLEN(s->lookfor); + for (;; ) { + // one step backwards + if (!next_match) { + if (s->hiscnt == hislen) { + // first time + s->hiscnt = hisidx[s->histype]; + } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { + s->hiscnt = hislen - 1; + } else if (s->hiscnt != hisidx[s->histype] + 1) { + s->hiscnt--; + } else { + // at top of list + s->hiscnt = s->i; + break; + } + } else { // one step forwards + // on last entry, clear the line + if (s->hiscnt == hisidx[s->histype]) { + s->hiscnt = hislen; + break; + } + + // not on a history line, nothing to do + if (s->hiscnt == hislen) { + break; + } + + if (s->hiscnt == hislen - 1) { + // wrap around + s->hiscnt = 0; + } else { + s->hiscnt++; + } + } + + if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { + s->hiscnt = s->i; + break; + } + + if ((s->c != K_UP && s->c != K_DOWN) + || s->hiscnt == s->i + || STRNCMP(history[s->histype][s->hiscnt].hisstr, + s->lookfor, (size_t)s->j) == 0) { + break; + } + } +} + static int command_line_handle_key(CommandLineState *s) { // Big switch for a typed command line character. @@ -1333,55 +1445,9 @@ static int command_line_handle_key(CommandLineState *s) s->lookfor[ccline.cmdpos] = NUL; } - s->j = (int)STRLEN(s->lookfor); - for (;; ) { - // one step backwards - if (s->c == K_UP|| s->c == K_S_UP || s->c == Ctrl_P - || s->c == K_PAGEUP || s->c == K_KPAGEUP) { - if (s->hiscnt == hislen) { - // first time - s->hiscnt = hisidx[s->histype]; - } else if (s->hiscnt == 0 && hisidx[s->histype] != hislen - 1) { - s->hiscnt = hislen - 1; - } else if (s->hiscnt != hisidx[s->histype] + 1) { - --s->hiscnt; - } else { - // at top of list - s->hiscnt = s->i; - break; - } - } else { // one step forwards - // on last entry, clear the line - if (s->hiscnt == hisidx[s->histype]) { - s->hiscnt = hislen; - break; - } - - // not on a history line, nothing to do - if (s->hiscnt == hislen) { - break; - } - - if (s->hiscnt == hislen - 1) { - // wrap around - s->hiscnt = 0; - } else { - ++s->hiscnt; - } - } - - if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) { - s->hiscnt = s->i; - break; - } - - if ((s->c != K_UP && s->c != K_DOWN) - || s->hiscnt == s->i - || STRNCMP(history[s->histype][s->hiscnt].hisstr, - s->lookfor, (size_t)s->j) == 0) { - break; - } - } + bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N + || s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN); + command_line_next_histidx(s, next_match); if (s->hiscnt != s->i) { // jumped to other entry @@ -1452,64 +1518,10 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_G: // next match case Ctrl_T: // previous match if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) { - pos_T t; - int search_flags = SEARCH_KEEP + SEARCH_NOOF + SEARCH_PEEK; - if (char_avail()) { return 1; } - ui_busy_start(); - ui_flush(); - if (s->c == Ctrl_G) { - t = s->match_end; - search_flags += SEARCH_COL; - } else { - t = s->match_start; - } - emsg_off++; - s->i = searchit(curwin, curbuf, &t, - s->c == Ctrl_G ? FORWARD : BACKWARD, - ccline.cmdbuff, s->count, search_flags, - RE_SEARCH, 0, NULL); - emsg_off--; - ui_busy_stop(); - if (s->i) { - s->search_start = s->match_start; - s->match_end = t; - s->match_start = t; - if (s->c == Ctrl_T && s->firstc == '/') { - // move just before the current match, so that - // when nv_search finishes the cursor will be - // put back on the match - s->search_start = t; - (void)decl(&s->search_start); - } - if (lt(t, s->search_start) && s->c == Ctrl_G) { - // wrap around - s->search_start = t; - if (s->firstc == '?') { - (void)incl(&s->search_start); - } else { - (void)decl(&s->search_start); - } - } - - set_search_match(&s->match_end); - curwin->w_cursor = s->match_start; - changed_cline_bef_curs(); - update_topline(); - validate_cursor(); - highlight_match = true; - s->old_curswant = curwin->w_curswant; - s->old_leftcol = curwin->w_leftcol; - s->old_topline = curwin->w_topline; - s->old_topfill = curwin->w_topfill; - s->old_botline = curwin->w_botline; - update_screen(NOT_VALID); - redrawcmdline(); - } else { - vim_beep(BO_ERROR); - } + command_line_next_incsearch(s, s->c == Ctrl_G); return command_line_not_changed(s); } break; -- cgit From 0ed95423de714edac11ccff177b8aee6b7987bac Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 28 Jun 2017 14:26:23 +0300 Subject: ex_getln: Call highlight callback inside :try --- src/nvim/ex_getln.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index f9b2d6cda8..9c494a2640 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -63,6 +63,7 @@ #include "nvim/event/loop.h" #include "nvim/os/time.h" #include "nvim/lib/kvec.h" +#include "nvim/api/private/helpers.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -2217,6 +2218,7 @@ static bool color_cmdline(void) static int prev_prompt_errors = 0; Callback color_cb = { .type = kCallbackNone }; bool can_free_cb = false; + Error err = ERROR_INIT; if (ccline.input_fn) { color_cb = getln_input_callback; @@ -2259,16 +2261,16 @@ static bool color_cmdline(void) // appears shifted one character to the right and cursor position is no longer // correct, with msg_col it just misses leading `:`. Since `redraw!` in // callback lags this is least of the user problems. + // + // Also using try_start() because error messages may overwrite typed + // command-line which is not expected. + try_start(); const int saved_msg_col = msg_col; msg_silent++; - if (!callback_call(&color_cb, 1, &arg, &tv)) { - msg_silent--; - msg_col = saved_msg_col; - goto color_cmdline_error; - } + const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); msg_silent--; msg_col = saved_msg_col; - if (got_int || did_emsg) { + if (try_end(&err) || !cbcall_ret) { goto color_cmdline_error; } if (tv.v_type != VAR_LIST) { @@ -2350,6 +2352,7 @@ static bool color_cmdline(void) } prev_prompt_errors = 0; color_cmdline_end: + assert(!ERROR_SET(&err)); if (can_free_cb) { callback_free(&color_cb); } @@ -2360,18 +2363,14 @@ color_cmdline_end: tv_clear(&tv); return ret; color_cmdline_error: - prev_prompt_errors++; - const bool do_redraw = (did_emsg || got_int); - got_int = false; - did_emsg = false; - if (did_throw) { - discard_current_exception(); - } - if (msg_list != NULL && *msg_list != NULL) { - free_global_msglist(); + if (ERROR_SET(&err)) { + emsgf(_("E5407: Callback has thrown an exception: %s"), err.msg); + api_clear_error(&err); } + prev_prompt_errors++; kv_size(ccline_colors) = 0; - if (do_redraw) { + if (did_emsg) { + did_emsg = false; prev_prompt_errors += MAX_CB_ERRORS; redrawcmdline(); prev_prompt_errors -= MAX_CB_ERRORS; -- cgit From 3da49cd68e7d5c968cc99a926819038ff57f488f Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 28 Jun 2017 22:09:10 +0300 Subject: ex_getln: Fix “echoerr msg not shown” problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also attempted to fix problem with cancelling input() on error by avoiding standard error printing facilities (assumed thrown error message is the problem), but with no luck so far. --- src/nvim/ex_getln.c | 52 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9c494a2640..444a3e5b11 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -64,6 +64,7 @@ #include "nvim/os/time.h" #include "nvim/lib/kvec.h" #include "nvim/api/private/helpers.h" +#include "nvim/highlight_defs.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -2202,6 +2203,13 @@ enum { MAX_CB_ERRORS = 1 }; /// to do. static bool color_cmdline(void) { + bool printed_errmsg = false; +#define PRINT_ERRMSG(...) \ + do { \ + msg_putchar('\n'); \ + msg_printf_attr(hl_attr(HLF_E)|MSG_HIST, __VA_ARGS__); \ + printed_errmsg = true; \ + } while (0) bool ret = true; kv_size(ccline_colors) = 0; @@ -2274,7 +2282,7 @@ static bool color_cmdline(void) goto color_cmdline_error; } if (tv.v_type != VAR_LIST) { - emsgf(_("E5400: Callback should return list")); + PRINT_ERRMSG(_("E5400: Callback should return list")); goto color_cmdline_error; } if (tv.vval.v_list == NULL) { @@ -2285,13 +2293,13 @@ static bool color_cmdline(void) for (const listitem_T *li = tv.vval.v_list->lv_first; li != NULL; li = li->li_next, i++) { if (li->li_tv.v_type != VAR_LIST) { - emsgf(_("E5401: List item %i is not a List"), i); + PRINT_ERRMSG(_("E5401: List item %i is not a List"), i); goto color_cmdline_error; } const list_T *const l = li->li_tv.vval.v_list; if (tv_list_len(l) != 3) { - emsgf(_("E5402: List item %i has incorrect length: %li /= 3"), - i, tv_list_len(l)); + PRINT_ERRMSG(_("E5402: List item %i has incorrect length: %li /= 3"), + i, tv_list_len(l)); goto color_cmdline_error; } bool error = false; @@ -2299,13 +2307,13 @@ static bool color_cmdline(void) if (error) { goto color_cmdline_error; } else if (!(prev_end <= start && start < ccline.cmdlen)) { - emsgf(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " - "[%" PRIdVARNUMBER ", %i)"), - i, start, prev_end, ccline.cmdlen); + PRINT_ERRMSG(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " + "[%" PRIdVARNUMBER ", %i)"), + i, start, prev_end, ccline.cmdlen); goto color_cmdline_error; } else if (utf8len_tab_zero[(uint8_t)ccline.cmdbuff[start]] == 0) { - emsgf(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits multibyte " - "character"), i, start); + PRINT_ERRMSG(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits " + "multibyte character"), i, start); goto color_cmdline_error; } if (start != prev_end) { @@ -2320,14 +2328,14 @@ static bool color_cmdline(void) if (error) { goto color_cmdline_error; } else if (!(start < end && end <= ccline.cmdlen)) { - emsgf(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " - "(%" PRIdVARNUMBER ", %i]"), - i, end, start, ccline.cmdlen); + PRINT_ERRMSG(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " + "(%" PRIdVARNUMBER ", %i]"), + i, end, start, ccline.cmdlen); goto color_cmdline_error; } else if (end < ccline.cmdlen && utf8len_tab_zero[(uint8_t)ccline.cmdbuff[end]] == 0) { - emsgf(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " - "character"), i, end); + PRINT_ERRMSG(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " + "character"), i, end); goto color_cmdline_error; } prev_end = end; @@ -2364,19 +2372,19 @@ color_cmdline_end: return ret; color_cmdline_error: if (ERROR_SET(&err)) { - emsgf(_("E5407: Callback has thrown an exception: %s"), err.msg); + PRINT_ERRMSG(_("E5407: Callback has thrown an exception: %s"), err.msg); api_clear_error(&err); } + assert(printed_errmsg); + prev_prompt_errors++; kv_size(ccline_colors) = 0; - if (did_emsg) { - did_emsg = false; - prev_prompt_errors += MAX_CB_ERRORS; - redrawcmdline(); - prev_prompt_errors -= MAX_CB_ERRORS; - ret = false; - } + prev_prompt_errors += MAX_CB_ERRORS; + redrawcmdline(); + prev_prompt_errors -= MAX_CB_ERRORS; + ret = false; goto color_cmdline_end; +#undef PRINT_ERRMSG } /* -- cgit From 99079a164db6ebea6d62f349e0c69894c6b9f799 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 28 Jun 2017 22:20:47 +0300 Subject: ex_getln: Make sure standard error reporting facility is not used --- src/nvim/ex_getln.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 444a3e5b11..7330bebe62 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2227,24 +2227,30 @@ static bool color_cmdline(void) Callback color_cb = { .type = kCallbackNone }; bool can_free_cb = false; Error err = ERROR_INIT; + const char *err_errmsg = (const char *)e_intern2; + bool dgc_ret = true; + try_start(); if (ccline.input_fn) { color_cb = getln_input_callback; } else if (ccline.cmdfirstc == ':') { - if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), - &color_cb)) { - goto color_cmdline_error; - } + err_errmsg = N_( + "E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), + &color_cb); can_free_cb = true; } else if (ccline.cmdfirstc == '=') { - if (!tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), - &color_cb)) { - goto color_cmdline_error; - } + err_errmsg = N_( + "E5409: Unable to get Nvim_color_expr callback from g:: %s"); + dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), + &color_cb); can_free_cb = true; } else { goto color_cmdline_end; } + if (try_end(&err) || !dgc_ret) { + goto color_cmdline_error; + } if (color_cb.type == kCallbackNone) { goto color_cmdline_end; @@ -2273,6 +2279,7 @@ static bool color_cmdline(void) // Also using try_start() because error messages may overwrite typed // command-line which is not expected. try_start(); + err_errmsg = N_("E5407: Callback has thrown an exception: %s"); const int saved_msg_col = msg_col; msg_silent++; const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); @@ -2372,7 +2379,7 @@ color_cmdline_end: return ret; color_cmdline_error: if (ERROR_SET(&err)) { - PRINT_ERRMSG(_("E5407: Callback has thrown an exception: %s"), err.msg); + PRINT_ERRMSG(_(err_errmsg), err.msg); api_clear_error(&err); } assert(printed_errmsg); -- cgit From 564d5f921c837e278f7e1aefeb7d832d08a63e97 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 28 Jun 2017 22:21:37 +0300 Subject: ex_getln: Fix indent --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7330bebe62..e10a485f76 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2232,7 +2232,7 @@ static bool color_cmdline(void) try_start(); if (ccline.input_fn) { - color_cb = getln_input_callback; + color_cb = getln_input_callback; } else if (ccline.cmdfirstc == ':') { err_errmsg = N_( "E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); -- cgit From ea75966e4232dc4a3693cbc4a572f2116c49b138 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 28 Jun 2017 22:54:13 +0300 Subject: ex_getln: Do not make interrupt input() after interrupting hl cb --- src/nvim/ex_getln.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e10a485f76..c23d6089a3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -166,6 +166,12 @@ static int hisnum[HIST_COUNT] = {0, 0, 0, 0, 0}; /* identifying (unique) number of newest history entry */ static int hislen = 0; /* actual length of history tables */ +/// Flag for command_line_handle_key to ignore +/// +/// Used if it was received while processing highlight function in order for +/// user interrupting highlight function to not interrupt command-line. +static bool getln_interrupted_highlight = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_getln.c.generated.h" @@ -1026,8 +1032,11 @@ static int command_line_handle_key(CommandLineState *s) case ESC: // get here if p_wc != ESC or when ESC typed twice case Ctrl_C: // In exmode it doesn't make sense to return. Except when - // ":normal" runs out of characters. - if (exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) { + // ":normal" runs out of characters. Also when highlight callback is active + // should interrupt only it. + if ((exmode_active && (ex_normal_busy == 0 || typebuf.tb_len > 0)) + || (getln_interrupted_highlight && s->c == Ctrl_C)) { + getln_interrupted_highlight = false; return command_line_not_changed(s); } @@ -2278,6 +2287,7 @@ static bool color_cmdline(void) // // Also using try_start() because error messages may overwrite typed // command-line which is not expected. + getln_interrupted_highlight = false; try_start(); err_errmsg = N_("E5407: Callback has thrown an exception: %s"); const int saved_msg_col = msg_col; @@ -2285,6 +2295,9 @@ static bool color_cmdline(void) const bool cbcall_ret = callback_call(&color_cb, 1, &arg, &tv); msg_silent--; msg_col = saved_msg_col; + if (got_int) { + getln_interrupted_highlight = true; + } if (try_end(&err) || !cbcall_ret) { goto color_cmdline_error; } -- cgit From 7ab152aaa58f493e54d03a15960b8a288196e588 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 1 Jul 2017 15:34:25 +0300 Subject: ex_getln: Save and restore try state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: when processing cycle such as :for pat in [' \ze*', ' \zs*'] : try : let l = matchlist('x x', pat) : $put ='E888 NOT detected for ' . pat : catch : $put ='E888 detected for ' . pat : endtry :endfor `:let l = …` throwing an error causes this error to be caught after color_cmdline attempts to get callback for highlighting next line (the one with `$put = 'E888 NOT…`). Saving/restoring state prevents this from happening. --- src/nvim/ex_getln.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index c23d6089a3..e6cd7398ab 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2222,6 +2222,11 @@ static bool color_cmdline(void) bool ret = true; kv_size(ccline_colors) = 0; + if (ccline.cmdbuff == NULL || *ccline.cmdbuff == NUL) { + // Nothing to do, exiting. + return ret; + } + const int saved_force_abort = force_abort; force_abort = true; bool arg_allocated = false; @@ -2235,11 +2240,12 @@ static bool color_cmdline(void) static int prev_prompt_errors = 0; Callback color_cb = { .type = kCallbackNone }; bool can_free_cb = false; + TryState tstate; Error err = ERROR_INIT; const char *err_errmsg = (const char *)e_intern2; bool dgc_ret = true; - try_start(); + try_enter(&tstate); if (ccline.input_fn) { color_cb = getln_input_callback; } else if (ccline.cmdfirstc == ':') { @@ -2257,7 +2263,7 @@ static bool color_cmdline(void) } else { goto color_cmdline_end; } - if (try_end(&err) || !dgc_ret) { + if (!try_leave(&tstate, &err) || !dgc_ret) { goto color_cmdline_error; } @@ -2285,10 +2291,10 @@ static bool color_cmdline(void) // correct, with msg_col it just misses leading `:`. Since `redraw!` in // callback lags this is least of the user problems. // - // Also using try_start() because error messages may overwrite typed + // Also using try_enter() because error messages may overwrite typed // command-line which is not expected. getln_interrupted_highlight = false; - try_start(); + try_enter(&tstate); err_errmsg = N_("E5407: Callback has thrown an exception: %s"); const int saved_msg_col = msg_col; msg_silent++; @@ -2298,7 +2304,7 @@ static bool color_cmdline(void) if (got_int) { getln_interrupted_highlight = true; } - if (try_end(&err) || !cbcall_ret) { + if (!try_leave(&tstate, &err) || !cbcall_ret) { goto color_cmdline_error; } if (tv.v_type != VAR_LIST) { -- cgit From 1f05ec95c04f7fd300ce3696b40f09e057d4fb06 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 4 Jul 2017 16:24:48 +0300 Subject: ex_getln: Silent V519: value is assigned twice successively MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is usual “passing data via global” false positive. --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7793081957..0ba6c79a71 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -306,7 +306,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) curwin->w_cursor = s->save_cursor; setpcmark(); } - curwin->w_cursor = s->search_start; + curwin->w_cursor = s->search_start; // -V519 } curwin->w_curswant = s->old_curswant; curwin->w_leftcol = s->old_leftcol; -- cgit From 2a6423eba732b005e277bac393f2246308dcc378 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 16 Jul 2017 22:03:31 +0300 Subject: api helpers: Save/restore more values in try_enter/try_leave This fixes memory leak reported by ASAN. This also somehow fixes test40, though I have no idea why except that that test yields memory leak report. --- src/nvim/ex_getln.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6c61e30f3d..275e1b7fdd 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2341,8 +2341,6 @@ static bool color_cmdline(void) return ret; } - const int saved_force_abort = force_abort; - force_abort = true; bool arg_allocated = false; typval_T arg = { .v_type = VAR_STRING, @@ -2504,7 +2502,6 @@ color_cmdline_end: if (can_free_cb) { callback_free(&color_cb); } - force_abort = saved_force_abort; if (arg_allocated) { tv_clear(&arg); } -- cgit From f4744e18219726d2eaa57b26198166ea255c62a4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 17 Jul 2017 01:55:10 +0300 Subject: ex_getln: Do not goto color_cmdline_end without first cleaning up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue with debug mode was actually not cleaning up after `try_enter`: location `&tstate` was pointing to got invalidated and received some “garbage” (actually, values that got stored on the stack afterwards). But pointer to that garbage was still stored in `msg_list`, so next attempt to check it resulted in a crash. --- src/nvim/ex_getln.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 275e1b7fdd..1052053ddf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2372,8 +2372,6 @@ static bool color_cmdline(void) dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), &color_cb); can_free_cb = true; - } else { - goto color_cmdline_end; } if (!try_leave(&tstate, &err) || !dgc_ret) { goto color_cmdline_error; -- cgit From dc0a496d41ed23106632d12bbc33679997281c73 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 17 Jul 2017 01:57:27 +0300 Subject: ex_getln: Do not do useless try_enter/try_leave calls These are actually needed for two modes only. And even for these modes they should eventually go away. --- src/nvim/ex_getln.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1052053ddf..9bcabeee72 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2356,24 +2356,28 @@ static bool color_cmdline(void) Error err = ERROR_INIT; const char *err_errmsg = (const char *)e_intern2; bool dgc_ret = true; + bool tl_ret = true; - try_enter(&tstate); if (ccline.input_fn) { color_cb = getln_input_callback; } else if (ccline.cmdfirstc == ':') { + try_enter(&tstate); err_errmsg = N_( "E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), &color_cb); + tl_ret = try_leave(&tstate, &err); can_free_cb = true; } else if (ccline.cmdfirstc == '=') { + try_enter(&tstate); err_errmsg = N_( "E5409: Unable to get Nvim_color_expr callback from g:: %s"); dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), &color_cb); + tl_ret = try_leave(&tstate, &err); can_free_cb = true; } - if (!try_leave(&tstate, &err) || !dgc_ret) { + if (!tl_ret || !dgc_ret) { goto color_cmdline_error; } -- cgit From 3a923ad2db87b2bece89616b28a14ab9826d569a Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 17 Jul 2017 02:33:18 +0300 Subject: ex_getln: Replace global with entry in save_ccline --- src/nvim/ex_getln.c | 70 +++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9bcabeee72..13bae4dadc 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -89,6 +89,7 @@ struct cmdline_info { char_u *xp_arg; // user-defined expansion arg int input_fn; // when TRUE Invoked for input() function unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. + Callback highlight_callback; ///< Callback used for coloring user input. }; /// Last value of prompt_id, incremented when doing new prompt static unsigned last_prompt_id = 0; @@ -148,9 +149,6 @@ typedef struct { int attr; ///< Highlight attr. } ColoredCmdlineChunk; -/// Callback used for coloring input() prompts -Callback getln_input_callback = { .type = kCallbackNone }; - kvec_t(ColoredCmdlineChunk) ccline_colors; /* The current cmdline_info. It is initialized in getcmdline() and after that @@ -1815,42 +1813,50 @@ getcmdline ( return command_line_enter(firstc, count, indent); } -/* - * Get a command line with a prompt. - * This is prepared to be called recursively from getcmdline() (e.g. by - * f_input() when evaluating an expression from CTRL-R =). - * Returns the command line in allocated memory, or NULL. - */ -char_u * -getcmdline_prompt ( - int firstc, - char_u *prompt, /* command line prompt */ - int attr, /* attributes for prompt */ - int xp_context, /* type of expansion */ - char_u *xp_arg /* user-defined expansion argument */ -) +/// Get a command line with a prompt +/// +/// This is prepared to be called recursively from getcmdline() (e.g. by +/// f_input() when evaluating an expression from `=`). +/// +/// @param[in] firstc Prompt type: e.g. '@' for input(), '>' for debug. +/// @param[in] prompt Prompt string: what is displayed before the user text. +/// @param[in] attr Prompt highlighting. +/// @param[in] xp_context Type of expansion. +/// @param[in] xp_arg User-defined expansion argument. +/// @param[in] highlight_callback Callback used for highlighting user input. +/// +/// @return [allocated] Command line or NULL. +char *getcmdline_prompt(const char firstc, const char *const prompt, + const int attr, const int xp_context, + const char *const xp_arg, + const Callback highlight_callback) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { - char_u *s; - struct cmdline_info save_ccline; - int msg_col_save = msg_col; + const int msg_col_save = msg_col; + struct cmdline_info save_ccline; save_cmdline(&save_ccline); + ccline.prompt_id = last_prompt_id++; - ccline.cmdprompt = prompt; + ccline.cmdprompt = (char_u *)prompt; ccline.cmdattr = attr; ccline.xp_context = xp_context; - ccline.xp_arg = xp_arg; + ccline.xp_arg = (char_u *)xp_arg; ccline.input_fn = (firstc == '@'); - s = getcmdline(firstc, 1L, 0); + ccline.highlight_callback = highlight_callback; + + char *const ret = (char *)getcmdline(firstc, 1L, 0); + restore_cmdline(&save_ccline); - /* Restore msg_col, the prompt from input() may have changed it. - * But only if called recursively and the commandline is therefore being - * restored to an old one; if not, the input() prompt stays on the screen, - * so we need its modified msg_col left intact. */ - if (ccline.cmdbuff != NULL) + // Restore msg_col, the prompt from input() may have changed it. + // But only if called recursively and the commandline is therefore being + // restored to an old one; if not, the input() prompt stays on the screen, + // so we need its modified msg_col left intact. + if (ccline.cmdbuff != NULL) { msg_col = msg_col_save; + } - return s; + return ret; } /* @@ -2358,8 +2364,10 @@ static bool color_cmdline(void) bool dgc_ret = true; bool tl_ret = true; - if (ccline.input_fn) { - color_cb = getln_input_callback; + if (ccline.highlight_callback.type != kCallbackNone) { + // Currently this should only happen while processing input() prompts. + assert(ccline.input_fn); + color_cb = ccline.highlight_callback; } else if (ccline.cmdfirstc == ':') { try_enter(&tstate); err_errmsg = N_( -- cgit From 8a581b918b339b84b5abd80919416a84932eb13f Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 18 Jul 2017 00:20:21 +0300 Subject: ex_getln: Check prev_prompt_errors before running redrawcmdline Otherwise there will be infinite recursion and shortly a crash. Running redrawcmdline recursively occurs under color_cmdline_error label. --- src/nvim/ex_getln.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 13bae4dadc..4be0dd0e0d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2364,6 +2364,12 @@ static bool color_cmdline(void) bool dgc_ret = true; bool tl_ret = true; + if (ccline.prompt_id != prev_prompt_id) { + prev_prompt_errors = 0; + prev_prompt_id = ccline.prompt_id; + } else if (prev_prompt_errors >= MAX_CB_ERRORS) { + goto color_cmdline_end; + } if (ccline.highlight_callback.type != kCallbackNone) { // Currently this should only happen while processing input() prompts. assert(ccline.input_fn); @@ -2392,12 +2398,6 @@ static bool color_cmdline(void) if (color_cb.type == kCallbackNone) { goto color_cmdline_end; } - if (ccline.prompt_id != prev_prompt_id) { - prev_prompt_errors = 0; - prev_prompt_id = ccline.prompt_id; - } else if (prev_prompt_errors >= MAX_CB_ERRORS) { - goto color_cmdline_end; - } if (ccline.cmdbuff[ccline.cmdlen] != NUL) { arg_allocated = true; arg.vval.v_string = xmemdupz((const char *)ccline.cmdbuff, -- cgit From 25c6ac1af63c0d68b7993910e94d3b0f1b8bbfd7 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 18 Jul 2017 01:21:23 +0300 Subject: *: Fix clint errors --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4be0dd0e0d..6ac0d062ac 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2321,7 +2321,7 @@ enum { MAX_CB_ERRORS = 1 }; /// Color command-line /// -/// Should use built-in command parser or user-specified one. Currently only the +/// Should use built-in command parser or user-specified one. Currently only the /// latter is supported. /// /// Operates on ccline, saving results to ccline_colors. -- cgit From 740dcaef0d6a7dda08e025fba678b763994128af Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 18 Jul 2017 01:25:55 +0300 Subject: ex_getln: Avoid GCC “unused variable” warning from QB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 17:25:45,363 WARN - /home/quickbuild/buildagent/workspace/root/neovim/pull-requests-automated/src/nvim/ex_getln.c: In function ‘color_cmdline’: 17:25:45,363 WARN - /home/quickbuild/buildagent/workspace/root/neovim/pull-requests-automated/src/nvim/ex_getln.c:2335:8: error: variable ‘printed_errmsg’ set but not used [-Werror=unused-but-set-variable] 17:25:45,363 WARN - bool printed_errmsg = false; 17:25:45,363 WARN - ^ 17:25:45,399 WARN - cc1: all warnings being treated as errors --- src/nvim/ex_getln.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6ac0d062ac..6115ebf2cb 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2523,6 +2523,7 @@ color_cmdline_error: api_clear_error(&err); } assert(printed_errmsg); + (void)printed_errmsg; prev_prompt_errors++; kv_size(ccline_colors) = 0; -- cgit From 811c45163c5613981c8e5abdca40e28c1b61d076 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 25 Jul 2017 18:30:28 +0200 Subject: vim-patch:8.0.0034 Problem: No completion for ":messages". Solution: Complete "clear" argument. (Hirohito Higashi) https://github.com/vim/vim/commit/9e507ca8a3e1535e62de4bd86374b0fcd18ef5b8 --- src/nvim/ex_getln.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0ba6c79a71..1d81a39dfe 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4050,6 +4050,7 @@ ExpandFromContext ( } tab[] = { { EXPAND_COMMANDS, get_command_name, false, true }, { EXPAND_BEHAVE, get_behave_arg, true, true }, + { EXPAND_MESSAGES, get_messages_arg, true, true }, { EXPAND_HISTORY, get_history_arg, true, true }, { EXPAND_USER_COMMANDS, get_user_commands, false, true }, { EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true }, -- cgit From c5857e3f3807d305598d7639949793d44b380e23 Mon Sep 17 00:00:00 2001 From: ZyX Date: Wed, 26 Jul 2017 22:56:48 +0300 Subject: ex_getln: Cache highlight callback calling results --- src/nvim/ex_getln.c | 121 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 38 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6115ebf2cb..6eb975fea3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -142,14 +142,37 @@ typedef struct command_line_state { struct cmdline_info save_ccline; } CommandLineState; -/// Command-line colors +/// Command-line colors: one chunk +/// +/// Defines a region which has the same highlighting. typedef struct { int start; ///< Colored chunk start. int end; ///< Colored chunk end (exclusive, > start). int attr; ///< Highlight attr. -} ColoredCmdlineChunk; +} CmdlineColorChunk; + +/// Command-line colors +/// +/// Holds data about all colors. +typedef kvec_t(CmdlineColorChunk) CmdlineColors; + +/// Command-line coloring +/// +/// Holds both what are the colors and what have been colored. Latter is used to +/// suppress unnecessary calls to coloring callbacks. +typedef struct { + unsigned prompt_id; ///< ID of the prompt which was colored last. + char *cmdbuff; ///< What exactly was colored last time or NULL. + CmdlineColors colors; ///< Last colors. +} ColoredCmdline; + +/// Last command-line colors. +ColoredCmdline last_ccline_colors = { + .cmdbuff = NULL, + .colors = KV_INITIAL_VALUE +}; -kvec_t(ColoredCmdlineChunk) ccline_colors; +typedef struct cmdline_info CmdlineInfo; /* The current cmdline_info. It is initialized in getcmdline() and after that * used by other functions. When invoking getcmdline() recursively it needs @@ -2324,13 +2347,20 @@ enum { MAX_CB_ERRORS = 1 }; /// Should use built-in command parser or user-specified one. Currently only the /// latter is supported. /// -/// Operates on ccline, saving results to ccline_colors. +/// @param[in] colored_ccline Command-line to color. +/// @param[out] ret_ccline_colors What should be colored. Also holds a cache: +/// if ->prompt_id and ->cmdbuff values happen +/// to be equal to those from colored_cmdline it +/// will just do nothing, assuming that ->colors +/// already contains needed data. /// /// Always colors the whole cmdline. /// /// @return true if draw_cmdline may proceed, false if it does not need anything /// to do. -static bool color_cmdline(void) +static bool color_cmdline(const CmdlineInfo *const colored_ccline, + ColoredCmdline *const ret_ccline_colors) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { bool printed_errmsg = false; #define PRINT_ERRMSG(...) \ @@ -2340,17 +2370,27 @@ static bool color_cmdline(void) printed_errmsg = true; \ } while (0) bool ret = true; - kv_size(ccline_colors) = 0; - if (ccline.cmdbuff == NULL || *ccline.cmdbuff == NUL) { + // Check whether result of the previous call is still valid. + if (ret_ccline_colors->prompt_id == colored_ccline->prompt_id + && ret_ccline_colors->cmdbuff != NULL + && STRCMP(ret_ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { + return ret; + } + + kv_size(ret_ccline_colors->colors) = 0; + + if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) { // Nothing to do, exiting. + xfree(ret_ccline_colors->cmdbuff); + ret_ccline_colors->cmdbuff = NULL; return ret; } bool arg_allocated = false; typval_T arg = { .v_type = VAR_STRING, - .vval.v_string = ccline.cmdbuff, + .vval.v_string = colored_ccline->cmdbuff, }; typval_T tv = { .v_type = VAR_UNKNOWN }; @@ -2364,17 +2404,17 @@ static bool color_cmdline(void) bool dgc_ret = true; bool tl_ret = true; - if (ccline.prompt_id != prev_prompt_id) { + if (colored_ccline->prompt_id != prev_prompt_id) { prev_prompt_errors = 0; - prev_prompt_id = ccline.prompt_id; + prev_prompt_id = colored_ccline->prompt_id; } else if (prev_prompt_errors >= MAX_CB_ERRORS) { goto color_cmdline_end; } - if (ccline.highlight_callback.type != kCallbackNone) { + if (colored_ccline->highlight_callback.type != kCallbackNone) { // Currently this should only happen while processing input() prompts. - assert(ccline.input_fn); - color_cb = ccline.highlight_callback; - } else if (ccline.cmdfirstc == ':') { + assert(colored_ccline->input_fn); + color_cb = colored_ccline->highlight_callback; + } else if (colored_ccline->cmdfirstc == ':') { try_enter(&tstate); err_errmsg = N_( "E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); @@ -2382,7 +2422,7 @@ static bool color_cmdline(void) &color_cb); tl_ret = try_leave(&tstate, &err); can_free_cb = true; - } else if (ccline.cmdfirstc == '=') { + } else if (colored_ccline->cmdfirstc == '=') { try_enter(&tstate); err_errmsg = N_( "E5409: Unable to get Nvim_color_expr callback from g:: %s"); @@ -2398,10 +2438,10 @@ static bool color_cmdline(void) if (color_cb.type == kCallbackNone) { goto color_cmdline_end; } - if (ccline.cmdbuff[ccline.cmdlen] != NUL) { + if (colored_ccline->cmdbuff[colored_ccline->cmdlen] != NUL) { arg_allocated = true; - arg.vval.v_string = xmemdupz((const char *)ccline.cmdbuff, - (size_t)ccline.cmdlen); + arg.vval.v_string = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); } // msg_start() called by e.g. :echo may shift command-line to the first column // even though msg_silent is here. Two ways to workaround this problem without @@ -2454,18 +2494,18 @@ static bool color_cmdline(void) const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); if (error) { goto color_cmdline_error; - } else if (!(prev_end <= start && start < ccline.cmdlen)) { + } else if (!(prev_end <= start && start < colored_ccline->cmdlen)) { PRINT_ERRMSG(_("E5403: Chunk %i start %" PRIdVARNUMBER " not in range " "[%" PRIdVARNUMBER ", %i)"), - i, start, prev_end, ccline.cmdlen); + i, start, prev_end, colored_ccline->cmdlen); goto color_cmdline_error; - } else if (utf8len_tab_zero[(uint8_t)ccline.cmdbuff[start]] == 0) { + } else if (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[start]] == 0) { PRINT_ERRMSG(_("E5405: Chunk %i start %" PRIdVARNUMBER " splits " "multibyte character"), i, start); goto color_cmdline_error; } if (start != prev_end) { - kv_push(ccline_colors, ((ColoredCmdlineChunk) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { .start = prev_end, .end = start, .attr = 0, @@ -2475,13 +2515,14 @@ static bool color_cmdline(void) &error); if (error) { goto color_cmdline_error; - } else if (!(start < end && end <= ccline.cmdlen)) { + } else if (!(start < end && end <= colored_ccline->cmdlen)) { PRINT_ERRMSG(_("E5404: Chunk %i end %" PRIdVARNUMBER " not in range " "(%" PRIdVARNUMBER ", %i]"), - i, end, start, ccline.cmdlen); + i, end, start, colored_ccline->cmdlen); goto color_cmdline_error; - } else if (end < ccline.cmdlen - && utf8len_tab_zero[(uint8_t)ccline.cmdbuff[end]] == 0) { + } else if (end < colored_ccline->cmdlen + && (utf8len_tab_zero[(uint8_t)colored_ccline->cmdbuff[end]] + == 0)) { PRINT_ERRMSG(_("E5406: Chunk %i end %" PRIdVARNUMBER " splits multibyte " "character"), i, end); goto color_cmdline_error; @@ -2493,16 +2534,16 @@ static bool color_cmdline(void) } const int id = syn_name2id((char_u *)group); const int attr = (id == 0 ? 0 : syn_id2attr(id)); - kv_push(ccline_colors, ((ColoredCmdlineChunk) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { .start = start, .end = end, .attr = attr, })); } - if (prev_end < ccline.cmdlen) { - kv_push(ccline_colors, ((ColoredCmdlineChunk) { + if (prev_end < colored_ccline->cmdlen) { + kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { .start = prev_end, - .end = ccline.cmdlen, + .end = colored_ccline->cmdlen, .attr = 0, })); } @@ -2512,8 +2553,14 @@ color_cmdline_end: if (can_free_cb) { callback_free(&color_cb); } + xfree(ret_ccline_colors->cmdbuff); + // Note: errors “output” is cached just as well as regular results. + ret_ccline_colors->prompt_id = colored_ccline->prompt_id; if (arg_allocated) { - tv_clear(&arg); + ret_ccline_colors->cmdbuff = (char *)arg.vval.v_string; + } else { + ret_ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); } tv_clear(&tv); return ret; @@ -2526,10 +2573,8 @@ color_cmdline_error: (void)printed_errmsg; prev_prompt_errors++; - kv_size(ccline_colors) = 0; - prev_prompt_errors += MAX_CB_ERRORS; + kv_size(ret_ccline_colors->colors) = 0; redrawcmdline(); - prev_prompt_errors -= MAX_CB_ERRORS; ret = false; goto color_cmdline_end; #undef PRINT_ERRMSG @@ -2541,7 +2586,7 @@ color_cmdline_error: */ static void draw_cmdline(int start, int len) { - if (!color_cmdline()) { + if (!color_cmdline(&ccline, &last_ccline_colors)) { return; } @@ -2643,9 +2688,9 @@ static void draw_cmdline(int start, int len) msg_outtrans_len(arshape_buf, newlen); } else { draw_cmdline_no_arabicshape: - if (kv_size(ccline_colors)) { - for (size_t i = 0; i < kv_size(ccline_colors); i++) { - ColoredCmdlineChunk chunk = kv_A(ccline_colors, i); + if (kv_size(last_ccline_colors.colors)) { + for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); if (chunk.end <= start) { continue; } -- cgit From a31482db4dcaa479b09e2683037fee3d6ee56408 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 5 Aug 2017 03:34:38 +0200 Subject: terminal: block redraw during c_CTRL-D Unlike the normal wildmenu, the CTRL-D wild-list is not restored by statusline redraw. (Semantics: ^D is controlled by 'wildoptions' option, so it's in the "wild..." family.) TODO: externalize the c_CTRL-D wild-list. --- src/nvim/ex_getln.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1d81a39dfe..a41e78d44a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -12,6 +12,7 @@ #include #include "nvim/assert.h" +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -472,11 +473,12 @@ static int command_line_execute(VimState *state, int key) } // free expanded names when finished walking through matches - if (s->xpc.xp_numfiles != -1 - && !(s->c == p_wc && KeyTyped) && s->c != p_wcm + if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A && s->c != Ctrl_L) { - (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + if (s->xpc.xp_numfiles != -1) { + (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); + } s->did_wild_list = false; if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) { s->xpc.xp_context = EXPAND_NOTHING; @@ -1222,6 +1224,7 @@ static int command_line_handle_key(CommandLineState *s) break; // Use ^D as normal char instead } + wild_menu_showing = WM_LIST; redrawcmd(); return 1; // don't do incremental search now -- cgit From 50c8f19d614d4752ac1d2d19b5bc7c05f6d354f9 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 5 Aug 2017 21:53:03 +0200 Subject: build: silence maybe-uninitialized warning False positive. From C:\msys64\mingw64\bin\gcc.exe (appveyor CI) --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a41e78d44a..ecd5c81822 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1455,7 +1455,7 @@ static int command_line_handle_key(CommandLineState *s) if (s->hiscnt != s->i) { // jumped to other entry char_u *p; - int len; + int len = 0; int old_firstc; xfree(ccline.cmdbuff); -- cgit From 19a28352a925b0a8502d57ec4f42b1412639aa6c Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 14 Aug 2017 01:56:48 +0300 Subject: ex_getln: Make error messages look better --- src/nvim/ex_getln.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6d839f0aa4..5e216925df 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2420,7 +2420,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, } else if (colored_ccline->cmdfirstc == ':') { try_enter(&tstate); err_errmsg = N_( - "E5408: Unable to get Nvim_color_cmdline callback from g:: %s"); + "E5408: Unable to get g:Nvim_color_cmdline callback: %s"); dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_cmdline"), &color_cb); tl_ret = try_leave(&tstate, &err); @@ -2428,7 +2428,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, } else if (colored_ccline->cmdfirstc == '=') { try_enter(&tstate); err_errmsg = N_( - "E5409: Unable to get Nvim_color_expr callback from g:: %s"); + "E5409: Unable to get g:Nvim_color_expr callback: %s"); dgc_ret = tv_dict_get_callback(&globvardict, S_LEN("Nvim_color_expr"), &color_cb); tl_ret = try_leave(&tstate, &err); -- cgit From b6b6e4a96f37ba6a54d194ecbc042d5ef7d595e6 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 28 Aug 2017 01:27:57 +0200 Subject: eventloop: FocusGained: schedule event instead of pseudokey closes #4840 closes #6164 --- src/nvim/ex_getln.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 5e216925df..fd7ad7a4b5 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1620,14 +1620,6 @@ static int command_line_handle_key(CommandLineState *s) } return command_line_not_changed(s); - case K_FOCUSGAINED: // Neovim has been given focus - apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf); - return command_line_not_changed(s); - - case K_FOCUSLOST: // Neovim has lost focus - apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf); - return command_line_not_changed(s); - default: // Normal character with no special meaning. Just set mod_mask // to 0x0 so that typing Shift-Space in the GUI doesn't enter -- cgit From d47b538f39e3e9700a18f1cd72e561086f62d7f3 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 2 Sep 2017 11:35:44 +0200 Subject: eventloop: do not redraw in cmdline K_EVENT handler If :echo is done by an timer or event (such as FocusGained/FocusLost), redrawcmdline() clobbers it. --- src/nvim/ex_getln.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index fd7ad7a4b5..9bfa9e22df 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -441,8 +441,7 @@ static int command_line_execute(VimState *state, int key) if (s->c == K_EVENT) { multiqueue_process_events(main_loop.events); - redrawcmdline(); - return 1; + return command_line_not_changed(s); } if (KeyTyped) { -- cgit From 6c53c3ee55991d9b1ea61a8dc443038b478ca92a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 2 Sep 2017 11:35:48 +0200 Subject: eventloop: restore redraw in cmdline K_EVENT handler Restores behavior from commit: 02e86ef04cc1 --- src/nvim/ex_getln.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9bfa9e22df..fd7ad7a4b5 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -441,7 +441,8 @@ static int command_line_execute(VimState *state, int key) if (s->c == K_EVENT) { multiqueue_process_events(main_loop.events); - return command_line_not_changed(s); + redrawcmdline(); + return 1; } if (KeyTyped) { -- cgit From dc513f761897f0ea09a511d19254f5c10b68e7fa Mon Sep 17 00:00:00 2001 From: James McCoy Date: Thu, 12 Oct 2017 00:49:47 -0400 Subject: getcmdline_prompt: Temporarily disable msg_silent so prompt is displayed vim-patch:7.4.1636 Closes #7378 --- src/nvim/ex_getln.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index fd7ad7a4b5..80f9b47340 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1863,9 +1863,13 @@ char *getcmdline_prompt(const char firstc, const char *const prompt, ccline.input_fn = (firstc == '@'); ccline.highlight_callback = highlight_callback; + int msg_silent_saved = msg_silent; + msg_silent = 0; + char *const ret = (char *)getcmdline(firstc, 1L, 0); restore_cmdline(&save_ccline); + msg_silent = msg_silent_saved; // Restore msg_col, the prompt from input() may have changed it. // But only if called recursively and the commandline is therefore being // restored to an old one; if not, the input() prompt stays on the screen, -- cgit From 4b3e51d4ee3018cf59d81578e2320b79fb614652 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 10 Oct 2017 18:42:01 +0200 Subject: ops: save and restore clipboard batch status when entering cmdline window --- src/nvim/ex_getln.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 80f9b47340..54e5bcb9ff 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5718,6 +5718,7 @@ static int ex_window(void) i = RedrawingDisabled; RedrawingDisabled = 0; + int save_count = save_batch_count(); /* * Call the main loop until or CTRL-C is typed. @@ -5726,6 +5727,7 @@ static int ex_window(void) normal_enter(true, false); RedrawingDisabled = i; + restore_batch_count(save_count); int save_KeyTyped = KeyTyped; -- cgit From 439c39a2cfb0712eb68ad76354b1fd7e92bb71fe Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 23 Feb 2017 05:33:14 +0000 Subject: ext_cmdline: allow external ui to draw cmdline --- src/nvim/ex_getln.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 9 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 54e5bcb9ff..87bf46d4d0 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -185,6 +185,8 @@ static int cmd_showtail; /* Only show path tail in lists ? */ static int new_cmdpos; /* position set by set_cmdline_pos() */ +static bool cmdline_external = false; + /* * Type used by call_user_expand_func */ @@ -281,7 +283,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) if (!cmd_silent) { s->i = msg_scrolled; msg_scrolled = 0; // avoid wait_return message - gotocmdline(true); + if (!cmdline_external) { + gotocmdline(true); + } msg_scrolled += s->i; redrawcmdprompt(); // draw prompt or indent set_cmdspos(); @@ -1828,7 +1832,16 @@ getcmdline ( int indent // indent for inside conditionals ) { - return command_line_enter(firstc, count, indent); + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ui_event("cmdline_enter", args); + } + char_u *p = command_line_enter(firstc, count, indent); + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ui_event("cmdline_leave", args); + } + return p; } /// Get a command line with a prompt @@ -2589,6 +2602,14 @@ static void draw_cmdline(int start, int len) return; } + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(args, INTEGER_OBJ(ccline.cmdpos)); + ui_event("cmdline", args); + return; + } + if (cmdline_star > 0) { for (int i = 0; i < len; i++) { msg_putchar('*'); @@ -2713,11 +2734,28 @@ void putcmdline(int c, int shift) { if (cmd_silent) return; - msg_no_more = TRUE; - msg_putchar(c); - if (shift) - draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); - msg_no_more = FALSE; + if (!cmdline_external) { + msg_no_more = TRUE; + msg_putchar(c); + if (shift) + draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); + msg_no_more = FALSE; + } else { + char_u *p; + if (ccline.cmdpos == ccline.cmdlen || shift) { + p = vim_strnsave(ccline.cmdbuff, ccline.cmdlen + 1); + } else { + p = vim_strsave(ccline.cmdbuff); + } + p[ccline.cmdpos] = c; + if (shift) + STRCPY(p + ccline.cmdpos + 1, ccline.cmdbuff + ccline.cmdpos); + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(p)))); + ADD(args, INTEGER_OBJ(ccline.cmdpos)); + ui_event("cmdline", args); + xfree(p); + } cursorcmd(); ui_cursor_shape(); } @@ -3066,8 +3104,15 @@ static void redrawcmdprompt(void) if (cmd_silent) return; - if (ccline.cmdfirstc != NUL) - msg_putchar(ccline.cmdfirstc); + if (ccline.cmdfirstc != NUL) { + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(&ccline.cmdfirstc)))); + ui_event("cmdline_firstc", args); + } else { + msg_putchar(ccline.cmdfirstc); + } + } if (ccline.cmdprompt != NULL) { msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; @@ -3087,6 +3132,11 @@ void redrawcmd(void) if (cmd_silent) return; + if (cmdline_external) { + draw_cmdline(0, ccline.cmdlen); + return; + } + /* when 'incsearch' is set there may be no command line while redrawing */ if (ccline.cmdbuff == NULL) { ui_cursor_goto(cmdline_row, 0); @@ -3130,6 +3180,13 @@ static void cursorcmd(void) if (cmd_silent) return; + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ADD(args, INTEGER_OBJ(ccline.cmdpos)); + ui_event("cmdline_pos", args); + return; + } + if (cmdmsg_rl) { msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1)); msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1; @@ -5974,3 +6031,8 @@ static void set_search_match(pos_T *t) coladvance((colnr_T)MAXCOL); } } + +void cmdline_set_external(bool external) +{ + cmdline_external = external; +} -- cgit From 6e90bc7200c87f0af448a8cf0998715db9175f15 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 23 Feb 2017 09:53:12 +0000 Subject: ext_cmdline: Added cmdline prompt --- src/nvim/ex_getln.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 87bf46d4d0..a05331d13a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3114,11 +3114,17 @@ static void redrawcmdprompt(void) } } if (ccline.cmdprompt != NULL) { - msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); - ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; - /* do the reverse of set_cmdspos() */ - if (ccline.cmdfirstc != NUL) - --ccline.cmdindent; + if (cmdline_external) { + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); + ui_event("cmdline_prompt", args); + } else { + msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); + ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; + /* do the reverse of set_cmdspos() */ + if (ccline.cmdfirstc != NUL) + --ccline.cmdindent; + } } else for (i = ccline.cmdindent; i > 0; --i) msg_putchar(' '); @@ -6036,3 +6042,8 @@ void cmdline_set_external(bool external) { cmdline_external = external; } + +bool cmdline_get_external(void) +{ + return cmdline_external; +} -- cgit From 26fd70bd18283701a2ade11407694485cd0f7e35 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Fri, 24 Feb 2017 07:26:39 +0000 Subject: ext_cmdline: add tests --- src/nvim/ex_getln.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a05331d13a..18d6b26595 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -283,9 +283,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) if (!cmd_silent) { s->i = msg_scrolled; msg_scrolled = 0; // avoid wait_return message - if (!cmdline_external) { - gotocmdline(true); - } + gotocmdline(true); msg_scrolled += s->i; redrawcmdprompt(); // draw prompt or indent set_cmdspos(); @@ -808,7 +806,9 @@ static int command_line_execute(VimState *state, int key) } if (!cmd_silent) { - ui_cursor_goto(msg_row, 0); + if (!cmdline_external) { + ui_cursor_goto(msg_row, 0); + } ui_flush(); } return 0; @@ -3210,6 +3210,9 @@ static void cursorcmd(void) void gotocmdline(int clr) { + if (cmdline_external) { + return; + } msg_start(); if (cmdmsg_rl) msg_col = Columns - 1; -- cgit From b7a8a76f6e3b2de1cfdf32e3ccc66d87ab8e5cad Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Mon, 27 Feb 2017 02:56:38 +0000 Subject: ext_cmdline: lint --- src/nvim/ex_getln.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 18d6b26595..0fae6c9810 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3121,13 +3121,16 @@ static void redrawcmdprompt(void) } else { msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; - /* do the reverse of set_cmdspos() */ - if (ccline.cmdfirstc != NUL) - --ccline.cmdindent; + // do the reverse of set_cmdspos() + if (ccline.cmdfirstc != NUL) { + ccline.cmdindent--; + } } - } else - for (i = ccline.cmdindent; i > 0; --i) + } else { + for (i = ccline.cmdindent; i > 0; i--) { msg_putchar(' '); + } + } } /* -- cgit From 550651c130c014e6c668644273db31dd96be475e Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Fri, 28 Apr 2017 06:51:16 +0100 Subject: ext_cmdline: use standard external ui functions --- src/nvim/ex_getln.c | 104 ++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 56 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0fae6c9810..8c9e081c89 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -185,8 +185,6 @@ static int cmd_showtail; /* Only show path tail in lists ? */ static int new_cmdpos; /* position set by set_cmdline_pos() */ -static bool cmdline_external = false; - /* * Type used by call_user_expand_func */ @@ -806,7 +804,7 @@ static int command_line_execute(VimState *state, int key) } if (!cmd_silent) { - if (!cmdline_external) { + if (!ui_is_external(kUICmdline)) { ui_cursor_goto(msg_row, 0); } ui_flush(); @@ -1832,12 +1830,12 @@ getcmdline ( int indent // indent for inside conditionals ) { - if (cmdline_external) { + if (ui_is_external(kUICmdline)) { Array args = ARRAY_DICT_INIT; ui_event("cmdline_enter", args); } char_u *p = command_line_enter(firstc, count, indent); - if (cmdline_external) { + if (ui_is_external(kUICmdline)) { Array args = ARRAY_DICT_INIT; ui_event("cmdline_leave", args); } @@ -2602,11 +2600,8 @@ static void draw_cmdline(int start, int len) return; } - if (cmdline_external) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); - ADD(args, INTEGER_OBJ(ccline.cmdpos)); - ui_event("cmdline", args); + if (ui_is_external(kUICmdline)) { + ui_ext_cmdline_show(); return; } @@ -2725,6 +2720,32 @@ draw_cmdline_no_arabicshape: } } +void ui_ext_cmdline_char(int c, int shift) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(&c)))); + ADD(args, INTEGER_OBJ(shift)); + ui_event("cmdline_char", args); +} + +void ui_ext_cmdline_show(void) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(args, INTEGER_OBJ(ccline.cmdpos)); + if (ccline.cmdfirstc != NUL) { + ADD(args, STRING_OBJ(cstr_to_string((char *)(&ccline.cmdfirstc)))); + } else { + ADD(args, STRING_OBJ(cstr_to_string(""))); + } + if (ccline.cmdprompt != NULL) { + ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); + } else { + ADD(args, STRING_OBJ(cstr_to_string(""))); + } + ui_event("cmdline_show", args); +} + /* * Put a character on the command line. Shifts the following text to the * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc. @@ -2732,29 +2753,17 @@ draw_cmdline_no_arabicshape: */ void putcmdline(int c, int shift) { - if (cmd_silent) + if (cmd_silent) { return; - if (!cmdline_external) { + } + if (!ui_is_external(kUICmdline)) { msg_no_more = TRUE; msg_putchar(c); if (shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; } else { - char_u *p; - if (ccline.cmdpos == ccline.cmdlen || shift) { - p = vim_strnsave(ccline.cmdbuff, ccline.cmdlen + 1); - } else { - p = vim_strsave(ccline.cmdbuff); - } - p[ccline.cmdpos] = c; - if (shift) - STRCPY(p + ccline.cmdpos + 1, ccline.cmdbuff + ccline.cmdpos); - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(p)))); - ADD(args, INTEGER_OBJ(ccline.cmdpos)); - ui_event("cmdline", args); - xfree(p); + ui_ext_cmdline_char(c, shift); } cursorcmd(); ui_cursor_shape(); @@ -3104,27 +3113,19 @@ static void redrawcmdprompt(void) if (cmd_silent) return; + if (ui_is_external(kUICmdline)) { + ui_ext_cmdline_show(); + return; + } if (ccline.cmdfirstc != NUL) { - if (cmdline_external) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(&ccline.cmdfirstc)))); - ui_event("cmdline_firstc", args); - } else { - msg_putchar(ccline.cmdfirstc); - } + msg_putchar(ccline.cmdfirstc); } if (ccline.cmdprompt != NULL) { - if (cmdline_external) { - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); - ui_event("cmdline_prompt", args); - } else { - msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); - ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; - // do the reverse of set_cmdspos() - if (ccline.cmdfirstc != NUL) { - ccline.cmdindent--; - } + msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); + ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; + // do the reverse of set_cmdspos() + if (ccline.cmdfirstc != NUL) { + ccline.cmdindent--; } } else { for (i = ccline.cmdindent; i > 0; i--) { @@ -3141,7 +3142,7 @@ void redrawcmd(void) if (cmd_silent) return; - if (cmdline_external) { + if (ui_is_external(kUICmdline)) { draw_cmdline(0, ccline.cmdlen); return; } @@ -3189,7 +3190,7 @@ static void cursorcmd(void) if (cmd_silent) return; - if (cmdline_external) { + if (ui_is_external(kUICmdline)) { Array args = ARRAY_DICT_INIT; ADD(args, INTEGER_OBJ(ccline.cmdpos)); ui_event("cmdline_pos", args); @@ -3213,7 +3214,7 @@ static void cursorcmd(void) void gotocmdline(int clr) { - if (cmdline_external) { + if (ui_is_external(kUICmdline)) { return; } msg_start(); @@ -6044,12 +6045,3 @@ static void set_search_match(pos_T *t) } } -void cmdline_set_external(bool external) -{ - cmdline_external = external; -} - -bool cmdline_get_external(void) -{ - return cmdline_external; -} -- cgit From daec81ab5179c7ce8e3813af556b1e2f05fc59c6 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Fri, 28 Apr 2017 07:49:45 +0100 Subject: ext_cmdline: change the content format --- src/nvim/ex_getln.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8c9e081c89..12f3f53c81 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2731,7 +2731,12 @@ void ui_ext_cmdline_char(int c, int shift) void ui_ext_cmdline_show(void) { Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + Array content = ARRAY_DICT_INIT; + Array text = ARRAY_DICT_INIT; + ADD(text, STRING_OBJ(cstr_to_string("Normal"))); + ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(content, ARRAY_OBJ(text)); + ADD(args, ARRAY_OBJ(content)); ADD(args, INTEGER_OBJ(ccline.cmdpos)); if (ccline.cmdfirstc != NUL) { ADD(args, STRING_OBJ(cstr_to_string((char *)(&ccline.cmdfirstc)))); -- cgit From e164ba41c8460d4e5b2e7e2b929d8479a0310738 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 11 May 2017 04:48:59 +0100 Subject: ext_cmdline: fix firstc, change cmdline_leave to cmdline_hide --- src/nvim/ex_getln.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 12f3f53c81..34547c59c9 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1837,7 +1837,7 @@ getcmdline ( char_u *p = command_line_enter(firstc, count, indent); if (ui_is_external(kUICmdline)) { Array args = ARRAY_DICT_INIT; - ui_event("cmdline_leave", args); + ui_event("cmdline_hide", args); } return p; } @@ -2738,16 +2738,13 @@ void ui_ext_cmdline_show(void) ADD(content, ARRAY_OBJ(text)); ADD(args, ARRAY_OBJ(content)); ADD(args, INTEGER_OBJ(ccline.cmdpos)); - if (ccline.cmdfirstc != NUL) { - ADD(args, STRING_OBJ(cstr_to_string((char *)(&ccline.cmdfirstc)))); - } else { - ADD(args, STRING_OBJ(cstr_to_string(""))); - } - if (ccline.cmdprompt != NULL) { - ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); - } else { - ADD(args, STRING_OBJ(cstr_to_string(""))); - } + char *firstc = (char []) { (char)ccline.cmdfirstc }; + String str = (String) { + .data = xmemdupz(firstc, 1), + .size = 1 + }; + ADD(args, STRING_OBJ(str)); + ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); ui_event("cmdline_show", args); } -- cgit From ab85999eb7c53e9d2b5bca5f8896ea11cb1df13e Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 11 May 2017 07:11:21 +0100 Subject: ext_cmdline: change to use ui_call --- src/nvim/ex_getln.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 34547c59c9..0223d9e936 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1831,13 +1831,11 @@ getcmdline ( ) { if (ui_is_external(kUICmdline)) { - Array args = ARRAY_DICT_INIT; - ui_event("cmdline_enter", args); + ui_call_cmdline_enter(); } char_u *p = command_line_enter(firstc, count, indent); if (ui_is_external(kUICmdline)) { - Array args = ARRAY_DICT_INIT; - ui_event("cmdline_hide", args); + ui_call_cmdline_hide(); } return p; } @@ -2720,32 +2718,19 @@ draw_cmdline_no_arabicshape: } } -void ui_ext_cmdline_char(int c, int shift) -{ - Array args = ARRAY_DICT_INIT; - ADD(args, STRING_OBJ(cstr_to_string((char *)(&c)))); - ADD(args, INTEGER_OBJ(shift)); - ui_event("cmdline_char", args); -} - void ui_ext_cmdline_show(void) { - Array args = ARRAY_DICT_INIT; Array content = ARRAY_DICT_INIT; Array text = ARRAY_DICT_INIT; ADD(text, STRING_OBJ(cstr_to_string("Normal"))); ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); ADD(content, ARRAY_OBJ(text)); - ADD(args, ARRAY_OBJ(content)); - ADD(args, INTEGER_OBJ(ccline.cmdpos)); char *firstc = (char []) { (char)ccline.cmdfirstc }; String str = (String) { .data = xmemdupz(firstc, 1), .size = 1 }; - ADD(args, STRING_OBJ(str)); - ADD(args, STRING_OBJ(cstr_to_string((char *)(ccline.cmdprompt)))); - ui_event("cmdline_show", args); + ui_call_cmdline_show(content, ccline.cmdpos, str, cstr_to_string((char *)(ccline.cmdprompt))); } /* @@ -2765,7 +2750,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; } else { - ui_ext_cmdline_char(c, shift); + ui_call_cmdline_char(cstr_to_string((char *)(&c)), shift); } cursorcmd(); ui_cursor_shape(); @@ -3193,9 +3178,7 @@ static void cursorcmd(void) return; if (ui_is_external(kUICmdline)) { - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(ccline.cmdpos)); - ui_event("cmdline_pos", args); + ui_call_cmdline_pos(ccline.cmdpos); return; } -- cgit From 866dadaf753ba3733feb8c22d7da47af757bd35c Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Thu, 11 May 2017 07:51:10 +0100 Subject: ext_cmdline: added cmdline level add cchar_to_string --- src/nvim/ex_getln.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0223d9e936..548459a8ce 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -91,6 +91,7 @@ struct cmdline_info { int input_fn; // when TRUE Invoked for input() function unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. Callback highlight_callback; ///< Callback used for coloring user input. + int level; // current cmdline level }; /// Last value of prompt_id, incremented when doing new prompt static unsigned last_prompt_id = 0; @@ -238,7 +239,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) cmd_hkmap = 0; } + // TODO(bfredl): can these be combined? ccline.prompt_id = last_prompt_id++; + ccline.level++; ccline.overstrike = false; // always start in insert mode clearpos(&s->match_end); s->save_cursor = curwin->w_cursor; // may be restored later @@ -414,6 +417,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) // Make ccline empty, getcmdline() may try to use it. ccline.cmdbuff = NULL; + + if (ui_is_external(kUICmdline)) { + ui_call_cmdline_hide(ccline.level); + } + ccline.level--; return p; } } @@ -1830,14 +1838,7 @@ getcmdline ( int indent // indent for inside conditionals ) { - if (ui_is_external(kUICmdline)) { - ui_call_cmdline_enter(); - } - char_u *p = command_line_enter(firstc, count, indent); - if (ui_is_external(kUICmdline)) { - ui_call_cmdline_hide(); - } - return p; + return command_line_enter(firstc, count, indent); } /// Get a command line with a prompt @@ -2720,17 +2721,12 @@ draw_cmdline_no_arabicshape: void ui_ext_cmdline_show(void) { - Array content = ARRAY_DICT_INIT; - Array text = ARRAY_DICT_INIT; - ADD(text, STRING_OBJ(cstr_to_string("Normal"))); - ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); - ADD(content, ARRAY_OBJ(text)); - char *firstc = (char []) { (char)ccline.cmdfirstc }; - String str = (String) { - .data = xmemdupz(firstc, 1), - .size = 1 - }; - ui_call_cmdline_show(content, ccline.cmdpos, str, cstr_to_string((char *)(ccline.cmdprompt))); + Array content = ARRAY_DICT_INIT; + Array text = ARRAY_DICT_INIT; + ADD(text, STRING_OBJ(cstr_to_string("Normal"))); + ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(content, ARRAY_OBJ(text)); + ui_call_cmdline_show(content, ccline.cmdpos, cchar_to_string((char)ccline.cmdfirstc), cstr_to_string((char *)(ccline.cmdprompt)), ccline.level); } /* @@ -2750,7 +2746,7 @@ void putcmdline(int c, int shift) draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); msg_no_more = FALSE; } else { - ui_call_cmdline_char(cstr_to_string((char *)(&c)), shift); + ui_call_cmdline_char(cchar_to_string((char)(c)), shift, ccline.level); } cursorcmd(); ui_cursor_shape(); @@ -3178,7 +3174,7 @@ static void cursorcmd(void) return; if (ui_is_external(kUICmdline)) { - ui_call_cmdline_pos(ccline.cmdpos); + ui_call_cmdline_pos(ccline.cmdpos, ccline.level); return; } @@ -3200,7 +3196,7 @@ static void cursorcmd(void) void gotocmdline(int clr) { if (ui_is_external(kUICmdline)) { - return; + return; } msg_start(); if (cmdmsg_rl) -- cgit From fb389a6b4b1e6fedb559dc2e5845dd138e8ff264 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Mon, 26 Jun 2017 15:27:49 +0100 Subject: ext_cmdline: added indent --- src/nvim/ex_getln.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 548459a8ce..6f941e66ef 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2726,7 +2726,11 @@ void ui_ext_cmdline_show(void) ADD(text, STRING_OBJ(cstr_to_string("Normal"))); ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); ADD(content, ARRAY_OBJ(text)); - ui_call_cmdline_show(content, ccline.cmdpos, cchar_to_string((char)ccline.cmdfirstc), cstr_to_string((char *)(ccline.cmdprompt)), ccline.level); + ui_call_cmdline_show(content, ccline.cmdpos, + cchar_to_string((char)ccline.cmdfirstc), + cstr_to_string((char *)(ccline.cmdprompt)), + ccline.cmdindent, + ccline.level); } /* -- cgit From 5ad591ef2d0ef184f78c728b1774c2a55fe2e581 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Tue, 27 Jun 2017 02:20:27 +0100 Subject: ext_cmdline: lint --- src/nvim/ex_getln.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6f941e66ef..93c060b4b7 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2744,11 +2744,12 @@ void putcmdline(int c, int shift) return; } if (!ui_is_external(kUICmdline)) { - msg_no_more = TRUE; + msg_no_more = true; msg_putchar(c); - if (shift) + if (shift) { draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); - msg_no_more = FALSE; + } + msg_no_more = false; } else { ui_call_cmdline_char(cchar_to_string((char)(c)), shift, ccline.level); } -- cgit From 22402fb99d05191cf140293cfb5f67902e78a8a8 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 12:19:29 +0200 Subject: ext_cmdline: add support for highlighting --- src/nvim/ex_getln.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 93c060b4b7..624a108bd4 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2372,6 +2372,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { bool printed_errmsg = false; + #define PRINT_ERRMSG(...) \ do { \ msg_putchar('\n'); \ @@ -2405,7 +2406,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, static unsigned prev_prompt_id = UINT_MAX; static int prev_prompt_errors = 0; - Callback color_cb = { .type = kCallbackNone }; + Callback color_cb = CALLBACK_NONE; bool can_free_cb = false; TryState tstate; Error err = ERROR_INIT; @@ -2722,10 +2723,30 @@ draw_cmdline_no_arabicshape: void ui_ext_cmdline_show(void) { Array content = ARRAY_DICT_INIT; - Array text = ARRAY_DICT_INIT; - ADD(text, STRING_OBJ(cstr_to_string("Normal"))); - ADD(text, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); - ADD(content, ARRAY_OBJ(text)); + if (kv_size(last_ccline_colors.colors)) { + for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); + Array item = ARRAY_DICT_INIT; + + if (chunk.attr) { + attrentry_T *aep = syn_cterm_attr2entry(chunk.attr); + // TODO(bfredl): this desicion could be delayed by making attr_code a + // recognized type + HlAttrs rgb_attrs = attrentry2hlattrs(aep, true); + ADD(item, DICTIONARY_OBJ(hlattrs2dict(rgb_attrs))); + } else { + ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); + } + ADD(item, STRING_OBJ(cbuf_to_string((char *)ccline.cmdbuff + chunk.start, + chunk.end-chunk.start))); + ADD(content, ARRAY_OBJ(item)); + } + } else { + Array item = ARRAY_DICT_INIT; + ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); + ADD(item, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(content, ARRAY_OBJ(item)); + } ui_call_cmdline_show(content, ccline.cmdpos, cchar_to_string((char)ccline.cmdfirstc), cstr_to_string((char *)(ccline.cmdprompt)), -- cgit From ddfc077da468450d1fab81fe3b3f594bb6ebf6dd Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 13:36:02 +0200 Subject: ext_cmdline: disable some redraws --- src/nvim/ex_getln.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 624a108bd4..0e620e59d8 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1144,7 +1144,7 @@ static int command_line_handle_key(CommandLineState *s) xfree(ccline.cmdbuff); // no commandline to return ccline.cmdbuff = NULL; - if (!cmd_silent) { + if (!cmd_silent && !ui_is_external(kUICmdline)) { if (cmdmsg_rl) { msg_col = Columns; } else { @@ -1596,9 +1596,14 @@ static int command_line_handle_key(CommandLineState *s) s->do_abbr = false; // don't do abbreviation now // may need to remove ^ when composing char was typed if (enc_utf8 && utf_iscomposing(s->c) && !cmd_silent) { - draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); - msg_putchar(' '); - cursorcmd(); + if (ui_is_external(kUICmdline)) { + // TODO(bfredl): why not make unputcmdline also work with true? + unputcmdline(); + } else { + draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); + msg_putchar(' '); + cursorcmd(); + } } break; @@ -2778,22 +2783,19 @@ void putcmdline(int c, int shift) ui_cursor_shape(); } -/* - * Undo a putcmdline(c, FALSE). - */ +/// Undo a putcmdline(c, FALSE). void unputcmdline(void) { - if (cmd_silent) + if (cmd_silent) { return; - msg_no_more = TRUE; - if (ccline.cmdlen == ccline.cmdpos) + } + msg_no_more = true; + if (ccline.cmdlen == ccline.cmdpos && !ui_is_external(kUICmdline)) { msg_putchar(' '); - else if (has_mbyte) - draw_cmdline(ccline.cmdpos, - (*mb_ptr2len)(ccline.cmdbuff + ccline.cmdpos)); - else - draw_cmdline(ccline.cmdpos, 1); - msg_no_more = FALSE; + } else { + draw_cmdline(ccline.cmdpos, mb_ptr2len(ccline.cmdbuff + ccline.cmdpos)); + } + msg_no_more = false; cursorcmd(); ui_cursor_shape(); } -- cgit From a68817f56517a31943806bd0b5a0030cdd35e182 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 13:57:58 +0200 Subject: ext_cmdline: extend "function" to generic "block" mechanism --- src/nvim/ex_getln.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0e620e59d8..50cccc8d10 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -186,6 +186,8 @@ static int cmd_showtail; /* Only show path tail in lists ? */ static int new_cmdpos; /* position set by set_cmdline_pos() */ +static Array cmdline_block; ///< currently displayed block of context + /* * Type used by call_user_expand_func */ @@ -2759,6 +2761,32 @@ void ui_ext_cmdline_show(void) ccline.level); } +void ui_ext_cmdline_block_append(int indent, const char *line) +{ + char *buf = xmallocz(indent + strlen(line)); + memset(buf, ' ', indent); + memcpy(buf+indent, line, strlen(line)); + + Array item = ARRAY_DICT_INIT; + ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); + ADD(item, STRING_OBJ(cstr_as_string(buf))); + Array content = ARRAY_DICT_INIT; + ADD(content, ARRAY_OBJ(item)); + ADD(cmdline_block, ARRAY_OBJ(content)); + if (cmdline_block.size > 1) { + ui_call_cmdline_block_append(copy_array(content)); + } else { + ui_call_cmdline_block_show(copy_array(cmdline_block)); + } +} + +void ui_ext_cmdline_block_leave(void) +{ + api_free_array(cmdline_block); + ui_call_cmdline_block_hide(); +} + + /* * Put a character on the command line. Shifts the following text to the * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc. -- cgit From f2aaa4ae8b84f74666b4379b391f333f34868a45 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 16 Aug 2017 15:38:12 +0200 Subject: ext_cmdline: rename cmdline_char to cmdline_special_char --- src/nvim/ex_getln.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 50cccc8d10..b9cf7b977c 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2805,7 +2805,8 @@ void putcmdline(int c, int shift) } msg_no_more = false; } else { - ui_call_cmdline_char(cchar_to_string((char)(c)), shift, ccline.level); + ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift, + ccline.level); } cursorcmd(); ui_cursor_shape(); -- cgit From 2050e6604632e190a04d52829f4469f1ef7f7018 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 20 Aug 2017 16:30:09 +0200 Subject: ext_cmdline: turn nested cmdlines into a linked list --- src/nvim/ex_getln.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index b9cf7b977c..2ac9ecdc2b 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -92,6 +92,7 @@ struct cmdline_info { unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. Callback highlight_callback; ///< Callback used for coloring user input. int level; // current cmdline level + struct cmdline_info *prev_ccline; ///< pointer to saved cmdline state }; /// Last value of prompt_id, incremented when doing new prompt static unsigned last_prompt_id = 0; @@ -2958,9 +2959,6 @@ void put_on_cmdline(char_u *str, int len, int redraw) msg_check(); } -static struct cmdline_info prev_ccline; -static int prev_ccline_used = FALSE; - /* * Save ccline, because obtaining the "=" register may execute "normal :cmd" * and overwrite it. But get_cmdline_str() may need it, thus make it @@ -2968,12 +2966,8 @@ static int prev_ccline_used = FALSE; */ static void save_cmdline(struct cmdline_info *ccp) { - if (!prev_ccline_used) { - memset(&prev_ccline, 0, sizeof(struct cmdline_info)); - prev_ccline_used = TRUE; - } - *ccp = prev_ccline; - prev_ccline = ccline; + *ccp = ccline; + ccline.prev_ccline = ccp; ccline.cmdbuff = NULL; ccline.cmdprompt = NULL; ccline.xpc = NULL; @@ -2984,8 +2978,7 @@ static void save_cmdline(struct cmdline_info *ccp) */ static void restore_cmdline(struct cmdline_info *ccp) { - ccline = prev_ccline; - prev_ccline = *ccp; + ccline = *ccp; } /* @@ -5312,13 +5305,15 @@ int get_history_idx(int histype) */ static struct cmdline_info *get_ccline_ptr(void) { - if ((State & CMDLINE) == 0) + if ((State & CMDLINE) == 0) { return NULL; - if (ccline.cmdbuff != NULL) + } else if (ccline.cmdbuff != NULL) { return &ccline; - if (prev_ccline_used && prev_ccline.cmdbuff != NULL) - return &prev_ccline; - return NULL; + } else if (ccline.prev_ccline && ccline.prev_ccline->cmdbuff != NULL) { + return ccline.prev_ccline; + } else { + return NULL; + } } /* -- cgit From bed0a3a8428027af32602ccb169e81767c55e257 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 20 Aug 2017 17:47:42 +0200 Subject: ext_cmdline: implement redraw! --- src/nvim/ex_getln.c | 166 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 67 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2ac9ecdc2b..933aea7b93 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -67,6 +67,30 @@ #include "nvim/api/private/helpers.h" #include "nvim/highlight_defs.h" +/// Command-line colors: one chunk +/// +/// Defines a region which has the same highlighting. +typedef struct { + int start; ///< Colored chunk start. + int end; ///< Colored chunk end (exclusive, > start). + int attr; ///< Highlight attr. +} CmdlineColorChunk; + +/// Command-line colors +/// +/// Holds data about all colors. +typedef kvec_t(CmdlineColorChunk) CmdlineColors; + +/// Command-line coloring +/// +/// Holds both what are the colors and what have been colored. Latter is used to +/// suppress unnecessary calls to coloring callbacks. +typedef struct { + unsigned prompt_id; ///< ID of the prompt which was colored last. + char *cmdbuff; ///< What exactly was colored last time or NULL. + CmdlineColors colors; ///< Last colors. +} ColoredCmdline; + /* * Variables shared between getcmdline(), redrawcmdline() and others. * These need to be saved when using CTRL-R |, that's why they are in a @@ -91,8 +115,11 @@ struct cmdline_info { int input_fn; // when TRUE Invoked for input() function unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. Callback highlight_callback; ///< Callback used for coloring user input. + ColoredCmdline last_colors; ///< Last cmdline colors int level; // current cmdline level struct cmdline_info *prev_ccline; ///< pointer to saved cmdline state + char special_char; ///< last putcmdline char (used for redraws) + bool special_shift; ///< shift of last putcmdline char }; /// Last value of prompt_id, incremented when doing new prompt static unsigned last_prompt_id = 0; @@ -145,36 +172,6 @@ typedef struct command_line_state { struct cmdline_info save_ccline; } CommandLineState; -/// Command-line colors: one chunk -/// -/// Defines a region which has the same highlighting. -typedef struct { - int start; ///< Colored chunk start. - int end; ///< Colored chunk end (exclusive, > start). - int attr; ///< Highlight attr. -} CmdlineColorChunk; - -/// Command-line colors -/// -/// Holds data about all colors. -typedef kvec_t(CmdlineColorChunk) CmdlineColors; - -/// Command-line coloring -/// -/// Holds both what are the colors and what have been colored. Latter is used to -/// suppress unnecessary calls to coloring callbacks. -typedef struct { - unsigned prompt_id; ///< ID of the prompt which was colored last. - char *cmdbuff; ///< What exactly was colored last time or NULL. - CmdlineColors colors; ///< Last colors. -} ColoredCmdline; - -/// Last command-line colors. -ColoredCmdline last_ccline_colors = { - .cmdbuff = NULL, - .colors = KV_INITIAL_VALUE -}; - typedef struct cmdline_info CmdlineInfo; /* The current cmdline_info. It is initialized in getcmdline() and after that @@ -242,7 +239,6 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) cmd_hkmap = 0; } - // TODO(bfredl): can these be combined? ccline.prompt_id = last_prompt_id++; ccline.level++; ccline.overstrike = false; // always start in insert mode @@ -264,6 +260,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.cmdlen = ccline.cmdpos = 0; ccline.cmdbuff[0] = NUL; + ccline.last_colors = (ColoredCmdline){ .cmdbuff = NULL, + .colors = KV_INITIAL_VALUE }; + // autoindent for :insert and :append if (s->firstc <= 0) { memset(ccline.cmdbuff, ' ', s->indent); @@ -414,6 +413,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) setmouse(); ui_cursor_shape(); // may show different cursor shape xfree(s->save_p_icm); + xfree(ccline.last_colors.cmdbuff); + kv_destroy(ccline.last_colors.colors); { char_u *p = ccline.cmdbuff; @@ -2364,8 +2365,7 @@ enum { MAX_CB_ERRORS = 1 }; /// Should use built-in command parser or user-specified one. Currently only the /// latter is supported. /// -/// @param[in] colored_ccline Command-line to color. -/// @param[out] ret_ccline_colors What should be colored. Also holds a cache: +/// @param[in,out] colored_ccline Command-line to color. Also holds a cache: /// if ->prompt_id and ->cmdbuff values happen /// to be equal to those from colored_cmdline it /// will just do nothing, assuming that ->colors @@ -2375,8 +2375,7 @@ enum { MAX_CB_ERRORS = 1 }; /// /// @return true if draw_cmdline may proceed, false if it does not need anything /// to do. -static bool color_cmdline(const CmdlineInfo *const colored_ccline, - ColoredCmdline *const ret_ccline_colors) +static bool color_cmdline(CmdlineInfo *colored_ccline) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { bool printed_errmsg = false; @@ -2389,19 +2388,21 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, } while (0) bool ret = true; + ColoredCmdline *ccline_colors = &colored_ccline->last_colors; + // Check whether result of the previous call is still valid. - if (ret_ccline_colors->prompt_id == colored_ccline->prompt_id - && ret_ccline_colors->cmdbuff != NULL - && STRCMP(ret_ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { + if (ccline_colors->prompt_id == colored_ccline->prompt_id + && ccline_colors->cmdbuff != NULL + && STRCMP(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { return ret; } - kv_size(ret_ccline_colors->colors) = 0; + kv_size(ccline_colors->colors) = 0; if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) { // Nothing to do, exiting. - xfree(ret_ccline_colors->cmdbuff); - ret_ccline_colors->cmdbuff = NULL; + xfree(ccline_colors->cmdbuff); + ccline_colors->cmdbuff = NULL; return ret; } @@ -2523,7 +2524,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, goto color_cmdline_error; } if (start != prev_end) { - kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + kv_push(ccline_colors->colors, ((CmdlineColorChunk) { .start = prev_end, .end = start, .attr = 0, @@ -2552,14 +2553,14 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline, } const int id = syn_name2id((char_u *)group); const int attr = (id == 0 ? 0 : syn_id2attr(id)); - kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + kv_push(ccline_colors->colors, ((CmdlineColorChunk) { .start = start, .end = end, .attr = attr, })); } if (prev_end < colored_ccline->cmdlen) { - kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { + kv_push(ccline_colors->colors, ((CmdlineColorChunk) { .start = prev_end, .end = colored_ccline->cmdlen, .attr = 0, @@ -2571,14 +2572,14 @@ color_cmdline_end: if (can_free_cb) { callback_free(&color_cb); } - xfree(ret_ccline_colors->cmdbuff); + xfree(ccline_colors->cmdbuff); // Note: errors “output” is cached just as well as regular results. - ret_ccline_colors->prompt_id = colored_ccline->prompt_id; + ccline_colors->prompt_id = colored_ccline->prompt_id; if (arg_allocated) { - ret_ccline_colors->cmdbuff = (char *)arg.vval.v_string; + ccline_colors->cmdbuff = (char *)arg.vval.v_string; } else { - ret_ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, - (size_t)colored_ccline->cmdlen); + ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, + (size_t)colored_ccline->cmdlen); } tv_clear(&tv); return ret; @@ -2591,7 +2592,7 @@ color_cmdline_error: (void)printed_errmsg; prev_prompt_errors++; - kv_size(ret_ccline_colors->colors) = 0; + kv_size(ccline_colors->colors) = 0; redrawcmdline(); ret = false; goto color_cmdline_end; @@ -2604,12 +2605,13 @@ color_cmdline_error: */ static void draw_cmdline(int start, int len) { - if (!color_cmdline(&ccline, &last_ccline_colors)) { + if (!color_cmdline(&ccline)) { return; } if (ui_is_external(kUICmdline)) { - ui_ext_cmdline_show(); + ccline.special_char = NUL; + ui_ext_cmdline_show(&ccline); return; } @@ -2711,9 +2713,9 @@ static void draw_cmdline(int start, int len) msg_outtrans_len(arshape_buf, newlen); } else { draw_cmdline_no_arabicshape: - if (kv_size(last_ccline_colors.colors)) { - for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { - CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); + if (kv_size(ccline.last_colors.colors)) { + for (size_t i = 0; i < kv_size(ccline.last_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(ccline.last_colors.colors, i); if (chunk.end <= start) { continue; } @@ -2728,12 +2730,12 @@ draw_cmdline_no_arabicshape: } } -void ui_ext_cmdline_show(void) +static void ui_ext_cmdline_show(CmdlineInfo *line) { Array content = ARRAY_DICT_INIT; - if (kv_size(last_ccline_colors.colors)) { - for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { - CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); + if (kv_size(line->last_colors.colors)) { + for (size_t i = 0; i < kv_size(line->last_colors.colors); i++) { + CmdlineColorChunk chunk = kv_A(line->last_colors.colors, i); Array item = ARRAY_DICT_INIT; if (chunk.attr) { @@ -2745,21 +2747,26 @@ void ui_ext_cmdline_show(void) } else { ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); } - ADD(item, STRING_OBJ(cbuf_to_string((char *)ccline.cmdbuff + chunk.start, + ADD(item, STRING_OBJ(cbuf_to_string((char *)line->cmdbuff + chunk.start, chunk.end-chunk.start))); ADD(content, ARRAY_OBJ(item)); } } else { Array item = ARRAY_DICT_INIT; ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); - ADD(item, STRING_OBJ(cstr_to_string((char *)(ccline.cmdbuff)))); + ADD(item, STRING_OBJ(cstr_to_string((char *)(line->cmdbuff)))); ADD(content, ARRAY_OBJ(item)); } - ui_call_cmdline_show(content, ccline.cmdpos, - cchar_to_string((char)ccline.cmdfirstc), - cstr_to_string((char *)(ccline.cmdprompt)), - ccline.cmdindent, - ccline.level); + ui_call_cmdline_show(content, line->cmdpos, + cchar_to_string((char)line->cmdfirstc), + cstr_to_string((char *)(line->cmdprompt)), + line->cmdindent, + line->level); + if (line->special_char) { + ui_call_cmdline_special_char(cchar_to_string((char)(line->special_char)), + line->special_shift, + line->level); + } } void ui_ext_cmdline_block_append(int indent, const char *line) @@ -2787,6 +2794,28 @@ void ui_ext_cmdline_block_leave(void) ui_call_cmdline_block_hide(); } +/// Extra redrawing needed for redraw! and on ui_attach +/// assumes "redrawcmdline()" will already be invoked +void cmdline_screen_cleared(void) +{ + if (!ui_is_external(kUICmdline)) { + return; + } + + if (cmdline_block.size) { + ui_call_cmdline_block_show(copy_array(cmdline_block)); + } + + int prev_level = ccline.level-1; + CmdlineInfo *prev_ccline = ccline.prev_ccline; + while (prev_level > 0 && prev_ccline) { + if (prev_ccline->level == prev_level) { + ui_ext_cmdline_show(prev_ccline); + prev_level--; + } + prev_ccline = prev_ccline->prev_ccline; + } +} /* * Put a character on the command line. Shifts the following text to the @@ -2806,6 +2835,8 @@ void putcmdline(int c, int shift) } msg_no_more = false; } else { + ccline.special_char = c; + ccline.special_shift = shift; ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift, ccline.level); } @@ -2971,6 +3002,7 @@ static void save_cmdline(struct cmdline_info *ccp) ccline.cmdbuff = NULL; ccline.cmdprompt = NULL; ccline.xpc = NULL; + ccline.special_char = NUL; } /* @@ -3147,7 +3179,7 @@ static void redrawcmdprompt(void) if (cmd_silent) return; if (ui_is_external(kUICmdline)) { - ui_ext_cmdline_show(); + ui_ext_cmdline_show(&ccline); return; } if (ccline.cmdfirstc != NUL) { -- cgit From 91d8e26bc7471378b8005b8843182dc1af90d81a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 27 Aug 2017 09:57:30 +0200 Subject: ext_cmdline: interact with cmdline window --- src/nvim/ex_getln.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 933aea7b93..bcc8d598db 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2810,7 +2810,10 @@ void cmdline_screen_cleared(void) CmdlineInfo *prev_ccline = ccline.prev_ccline; while (prev_level > 0 && prev_ccline) { if (prev_ccline->level == prev_level) { - ui_ext_cmdline_show(prev_ccline); + // don't redraw a cmdline already shown in the cmdline window + if (prev_level != cmdwin_level) { + ui_ext_cmdline_show(prev_ccline); + } prev_level--; } prev_ccline = prev_ccline->prev_ccline; @@ -5781,6 +5784,7 @@ static int ex_window(void) return K_IGNORE; } cmdwin_type = get_cmdline_type(); + cmdwin_level = ccline.level; // Create empty command-line buffer. buf_open_scratch(0, "[Command Line]"); @@ -5833,6 +5837,9 @@ static int ex_window(void) curwin->w_cursor.col = ccline.cmdpos; changed_line_abv_curs(); invalidate_botline(); + if (ui_is_external(kUICmdline)) { + ui_call_cmdline_hide(ccline.level); + } redraw_later(SOME_VALID); // Save the command line info, can be used recursively. @@ -5875,6 +5882,7 @@ static int ex_window(void) // Restore the command line info. restore_cmdline(&save_ccline); cmdwin_type = 0; + cmdwin_level = 0; exmode_active = save_exmode; -- cgit From 445f25998c66ee7e4dc5bbfeed4108818e439b92 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 30 Aug 2017 08:51:39 +0200 Subject: ext_cmdline: fix inputsecret() --- src/nvim/ex_getln.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index bcc8d598db..e79476ab53 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2733,7 +2733,18 @@ draw_cmdline_no_arabicshape: static void ui_ext_cmdline_show(CmdlineInfo *line) { Array content = ARRAY_DICT_INIT; - if (kv_size(line->last_colors.colors)) { + if (cmdline_star) { + size_t len = 0; + for (char_u *p = ccline.cmdbuff; *p; mb_ptr_adv(p)) { + len++; + } + char *buf = xmallocz(len); + memset(buf, '*', len); + Array item = ARRAY_DICT_INIT; + ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); + ADD(item, STRING_OBJ(((String) { .data = buf, .size = len }))); + ADD(content, ARRAY_OBJ(item)); + } else if (kv_size(line->last_colors.colors)) { for (size_t i = 0; i < kv_size(line->last_colors.colors); i++) { CmdlineColorChunk chunk = kv_A(line->last_colors.colors, i); Array item = ARRAY_DICT_INIT; -- cgit From 39e83fa7cb4486d30f788c3b27594d106d5e76ab Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Fri, 24 Feb 2017 06:12:34 +0000 Subject: ui: allow external ui to draw wildmenu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Björn Linse Updated docs and tests. --- src/nvim/ex_getln.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e79476ab53..3d5e1a5476 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -534,6 +534,9 @@ static int command_line_execute(VimState *state, int key) if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A && s->c != Ctrl_L) { + if (ui_is_external(kUIWildmenu)) { + ui_call_wildmenu_hide(); + } if (s->xpc.xp_numfiles != -1) { (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE); } @@ -3515,11 +3518,17 @@ ExpandOne ( else findex = -1; } - if (p_wmnu) - win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, - findex, cmd_showtail); - if (findex == -1) + if (p_wmnu) { + if (ui_is_external(kUIWildmenu)) { + ui_call_wildmenu_select(findex); + } else { + win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files, + findex, cmd_showtail); + } + } + if (findex == -1) { return vim_strsave(orig_save); + } return vim_strsave(xp->xp_files[findex]); } else return NULL; @@ -3876,6 +3885,15 @@ static int showmatches(expand_T *xp, int wildmenu) showtail = cmd_showtail; } + if (ui_is_external(kUIWildmenu)) { + Array args = ARRAY_DICT_INIT; + for (i = 0; i < num_files; i++) { + ADD(args, STRING_OBJ(cstr_to_string((char *)files_found[i]))); + } + ui_call_wildmenu_show(args); + return EXPAND_OK; + } + if (!wildmenu) { msg_didany = FALSE; /* lines_left will be set */ msg_start(); /* prepare for paging */ @@ -6128,4 +6146,3 @@ static void set_search_match(pos_T *t) coladvance((colnr_T)MAXCOL); } } - -- cgit From 241fe704a52092aad7eff8c1cbf25262bfcf0195 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 30 Oct 2017 23:29:47 +0100 Subject: pvs/V575: false positive (#7462) ./src/nvim/ex_getln.c:2787:1: error: V575 The 'memcpy' function doesn't copy the whole string. Use 'strcpy / strcpy_s' function to preserve terminal null. We could instead "trick" PVS like this: diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e79476ab532a..295630693b27 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2782,9 +2782,10 @@ static void ui_ext_cmdline_show(CmdlineInfo *line) void ui_ext_cmdline_block_append(int indent, const char *line) { - char *buf = xmallocz(indent + strlen(line)); + size_t linelen = strlen(line); + char *buf = xmallocz(indent + linelen); memset(buf, ' ', indent); - memcpy(buf+indent, line, strlen(line)); + memcpy(buf + indent, line, linelen); Array item = ARRAY_DICT_INIT; ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); --- src/nvim/ex_getln.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e79476ab53..c9567145e4 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2784,7 +2784,7 @@ void ui_ext_cmdline_block_append(int indent, const char *line) { char *buf = xmallocz(indent + strlen(line)); memset(buf, ' ', indent); - memcpy(buf+indent, line, strlen(line)); + memcpy(buf + indent, line, strlen(line)); // -V575 Array item = ARRAY_DICT_INIT; ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); -- cgit From 06fd32b8ffc437d596a2d82a986220add4315869 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 7 Nov 2017 18:53:42 +0100 Subject: ui: remove ext_cmdline noise (#7486) Only send cmdline contents once per ui_flush. Don't send extra redraws due to 'arshape', it makes no difference to external ui. --- src/nvim/ex_getln.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 27883997e4..43e7cf457d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -91,6 +91,13 @@ typedef struct { CmdlineColors colors; ///< Last colors. } ColoredCmdline; +/// Keeps track how much state must be sent to external ui. +typedef enum { + kCmdRedrawNone, + kCmdRedrawPos, + kCmdRedrawAll, +} CmdRedraw; + /* * Variables shared between getcmdline(), redrawcmdline() and others. * These need to be saved when using CTRL-R |, that's why they are in a @@ -120,6 +127,7 @@ struct cmdline_info { struct cmdline_info *prev_ccline; ///< pointer to saved cmdline state char special_char; ///< last putcmdline char (used for redraws) bool special_shift; ///< shift of last putcmdline char + CmdRedraw redraw_state; ///< needed redraw for external cmdline }; /// Last value of prompt_id, incremented when doing new prompt static unsigned last_prompt_id = 0; @@ -423,6 +431,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) ccline.cmdbuff = NULL; if (ui_is_external(kUICmdline)) { + ccline.redraw_state = kCmdRedrawNone; ui_call_cmdline_hide(ccline.level); } ccline.level--; @@ -1816,7 +1825,8 @@ static int command_line_changed(CommandLineState *s) // right-left typing. Not efficient, but it works. // Do it only when there are no characters left to read // to avoid useless intermediate redraws. - if (vpeekc() == NUL) { + // if cmdline is external the ui handles shaping, no redraw needed. + if (!ui_is_external(kUICmdline) && vpeekc() == NUL) { redrawcmd(); } } @@ -2614,7 +2624,7 @@ static void draw_cmdline(int start, int len) if (ui_is_external(kUICmdline)) { ccline.special_char = NUL; - ui_ext_cmdline_show(&ccline); + ccline.redraw_state = kCmdRedrawAll; return; } @@ -2826,7 +2836,7 @@ void cmdline_screen_cleared(void) if (prev_ccline->level == prev_level) { // don't redraw a cmdline already shown in the cmdline window if (prev_level != cmdwin_level) { - ui_ext_cmdline_show(prev_ccline); + prev_ccline->redraw_state = kCmdRedrawAll; } prev_level--; } @@ -2834,6 +2844,28 @@ void cmdline_screen_cleared(void) } } +/// called by ui_flush, do what redraws neccessary to keep cmdline updated. +void cmdline_ui_flush(void) +{ + if (!ui_is_external(kUICmdline)) { + return; + } + int level = ccline.level; + CmdlineInfo *line = &ccline; + while (level > 0 && line) { + if (line->level == level) { + if (line->redraw_state == kCmdRedrawAll) { + ui_ext_cmdline_show(line); + } else if (line->redraw_state == kCmdRedrawPos) { + ui_call_cmdline_pos(line->cmdpos, line->level); + } + line->redraw_state = kCmdRedrawNone; + level--; + } + line = line->prev_ccline; + } +} + /* * Put a character on the command line. Shifts the following text to the * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc. @@ -2854,8 +2886,10 @@ void putcmdline(int c, int shift) } else { ccline.special_char = c; ccline.special_shift = shift; - ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift, - ccline.level); + if (ccline.redraw_state != kCmdRedrawAll) { + ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift, + ccline.level); + } } cursorcmd(); ui_cursor_shape(); @@ -3196,7 +3230,7 @@ static void redrawcmdprompt(void) if (cmd_silent) return; if (ui_is_external(kUICmdline)) { - ui_ext_cmdline_show(&ccline); + ccline.redraw_state = kCmdRedrawAll; return; } if (ccline.cmdfirstc != NUL) { @@ -3273,7 +3307,9 @@ static void cursorcmd(void) return; if (ui_is_external(kUICmdline)) { - ui_call_cmdline_pos(ccline.cmdpos, ccline.level); + if (ccline.redraw_state < kCmdRedrawPos) { + ccline.redraw_state = kCmdRedrawPos; + } return; } @@ -5867,6 +5903,7 @@ static int ex_window(void) changed_line_abv_curs(); invalidate_botline(); if (ui_is_external(kUICmdline)) { + ccline.redraw_state = kCmdRedrawNone; ui_call_cmdline_hide(ccline.level); } redraw_later(SOME_VALID); -- cgit From a2fdd0a72f9d1f72f2e49e80719902a6f555454e Mon Sep 17 00:00:00 2001 From: KunMing Xie Date: Sat, 11 Nov 2017 08:26:55 +0800 Subject: vim-patch:8.0.0237 (#7531) Problem: When setting wildoptions=tagfile the completion context is not set correctly. (desjardins) Solution: Check for EXPAND_TAGS_LISTFILES. (Christian Brabandt, closes vim/vim#1399) https://github.com/vim/vim/commit/ba47b51ff88d91c9bb5aa522183e23a656865697 --- src/nvim/ex_getln.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 43e7cf457d..9c9ccbca4d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4147,7 +4147,9 @@ addstar ( || context == EXPAND_OWNSYNTAX || context == EXPAND_FILETYPE || context == EXPAND_PACKADD - || (context == EXPAND_TAGS && fname[0] == '/')) + || ((context == EXPAND_TAGS_LISTFILES + || context == EXPAND_TAGS) + && fname[0] == '/')) retval = vim_strnsave(fname, len); else { new_len = len + 2; /* +2 for '^' at start, NUL at end */ -- cgit From a4f6cec7a31ff8dbfa089b9e22227afbeb951e9b Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 22 Nov 2017 22:35:20 +0100 Subject: cmdline: CmdlineEnter and CmdlineLeave autocommands (#7422) vim-patch:fafcf0dd59fd patch 8.0.1206: no autocmd for entering or leaving the command line Problem: No autocmd for entering or leaving the command line. Solution: Add CmdlineEnter and CmdlineLeave. https://github.com/vim/vim/commit/fafcf0dd59fd9c4ef743bb333ae40d1d322b6079 --- src/nvim/ex_getln.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'src/nvim/ex_getln.c') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9c9ccbca4d..c1500e3121 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -348,8 +348,57 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) got_int = false; s->state.check = command_line_check; s->state.execute = command_line_execute; + + TryState tstate; + Error err = ERROR_INIT; + bool tl_ret = true; + dict_T *dict = get_vim_var_dict(VV_EVENT); + char firstcbuf[2]; + firstcbuf[0] = firstc > 0 ? firstc : '-'; + firstcbuf[1] = 0; + + if (has_event(EVENT_CMDLINEENTER)) { + // set v:event to a dictionary with information about the commandline + tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf); + tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level); + tv_dict_set_keys_readonly(dict); + try_enter(&tstate); + + apply_autocmds(EVENT_CMDLINEENTER, (char_u *)firstcbuf, (char_u *)firstcbuf, + false, curbuf); + tv_dict_clear(dict); + + + tl_ret = try_leave(&tstate, &err); + if (!tl_ret && ERROR_SET(&err)) { + msg_putchar('\n'); + msg_printf_attr(hl_attr(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg); + api_clear_error(&err); + redrawcmd(); + } + tl_ret = true; + } + state_enter(&s->state); + if (has_event(EVENT_CMDLINELEAVE)) { + tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf); + tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level); + tv_dict_set_keys_readonly(dict); + // not readonly: + tv_dict_add_special(dict, S_LEN("abort"), + s->gotesc ? kSpecialVarTrue : kSpecialVarFalse); + try_enter(&tstate); + apply_autocmds(EVENT_CMDLINELEAVE, (char_u *)firstcbuf, (char_u *)firstcbuf, + false, curbuf); + // error printed below, to avoid redraw issues + tl_ret = try_leave(&tstate, &err); + if (tv_dict_get_number(dict, "abort") != 0) { + s->gotesc = 1; + } + tv_dict_clear(dict); + } + cmdmsg_rl = false; cmd_fkmap = 0; @@ -410,8 +459,14 @@ static uint8_t *command_line_enter(int firstc, long count, int indent) msg_scroll = s->save_msg_scroll; redir_off = false; + if (!tl_ret && ERROR_SET(&err)) { + msg_putchar('\n'); + msg_printf_attr(hl_attr(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg); + api_clear_error(&err); + } + // When the command line was typed, no need for a wait-return prompt. - if (s->some_key_typed) { + if (s->some_key_typed && tl_ret) { need_wait_return = false; } -- cgit