aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_getln.c144
-rw-r--r--src/nvim/getchar.c5
-rw-r--r--src/nvim/main.c2
3 files changed, 59 insertions, 92 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 84fca137d2..1d02c74c41 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -192,13 +192,12 @@ typedef struct command_line_state {
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
- * to be saved with save_cmdline() and restored with restore_cmdline().
- * TODO: make it local to getcmdline() and pass it around. */
+/// 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().
static struct cmdline_info ccline;
-static int cmd_showtail; // Only show path tail in lists ?
+static int cmd_showtail; // Only show path tail in lists ?
static int new_cmdpos; // position set by set_cmdline_pos()
@@ -732,9 +731,10 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool
/// Internal entry point for cmdline mode.
///
-/// caller must use save_cmdline and restore_cmdline. Best is to use
-/// getcmdline or getcmdline_prompt, instead of calling this directly.
-static uint8_t *command_line_enter(int firstc, long count, int indent)
+/// @param count only used for incremental search
+/// @param indent indent for inside conditionals
+/// @param init_ccline clear ccline first
+static uint8_t *command_line_enter(int firstc, long count, int indent, bool init_ccline)
{
// can be invoked recursively, identify each level
static int cmdline_level = 0;
@@ -751,6 +751,20 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
CommandLineState *s = &state;
s->save_p_icm = vim_strsave(p_icm);
init_incsearch_state(&s->is_state);
+ CmdlineInfo save_ccline;
+ bool did_save_ccline = false;
+
+ if (ccline.cmdbuff != NULL) {
+ // Currently ccline can never be in use if init_ccline is false.
+ // Some changes will be needed if this is no longer the case.
+ assert(init_ccline);
+ // Being called recursively. Since ccline is global, we need to save
+ // the current buffer and restore it when returning.
+ save_cmdline(&save_ccline);
+ did_save_ccline = true;
+ } else if (init_ccline) {
+ memset(&ccline, 0, sizeof(struct cmdline_info));
+ }
if (s->firstc == -1) {
s->firstc = NUL;
@@ -997,6 +1011,13 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
}
cmdline_level--;
+
+ if (did_save_ccline) {
+ restore_cmdline(&save_ccline);
+ } else {
+ ccline.cmdbuff = NULL;
+ }
+
return p;
}
@@ -1340,15 +1361,9 @@ static int command_line_execute(VimState *state, int key)
s->c = get_expr_register();
if (s->c == '=') {
- // Need to save and restore ccline. And set "textlock"
- // to avoid nasty things like going to another buffer when
- // evaluating an expression.
- CmdlineInfo save_ccline;
- save_cmdline(&save_ccline);
textlock++;
p = get_expr_line();
textlock--;
- restore_cmdline(&save_ccline);
if (p != NULL) {
len = (int)STRLEN(p);
@@ -1889,10 +1904,7 @@ static int command_line_handle_key(CommandLineState *s)
beep_flush();
s->c = ESC;
} else {
- CmdlineInfo save_ccline;
- save_cmdline(&save_ccline);
s->c = get_expr_register();
- restore_cmdline(&save_ccline);
}
}
@@ -2120,7 +2132,7 @@ static int command_line_handle_key(CommandLineState *s)
int len = 0;
int old_firstc;
- xfree(ccline.cmdbuff);
+ XFREE_CLEAR(ccline.cmdbuff);
s->xpc.xp_context = EXPAND_NOTHING;
if (s->hiscnt == hislen) {
p = s->lookfor; // back to the old one
@@ -2403,14 +2415,7 @@ static void abandon_cmdline(void)
/// @param indent indent for inside conditionals
char_u *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
{
- // Be prepared for situations where cmdline can be invoked recursively.
- // That includes cmd mappings, event handlers, as well as update_screen()
- // (custom status line eval), which all may invoke ":normal :".
- CmdlineInfo save_ccline;
- save_cmdline(&save_ccline);
- char_u *retval = command_line_enter(firstc, count, indent);
- restore_cmdline(&save_ccline);
- return retval;
+ return command_line_enter(firstc, count, indent, true);
}
/// Get a command line with a prompt
@@ -2434,8 +2439,14 @@ char *getcmdline_prompt(const char firstc, const char *const prompt, const int a
const int msg_col_save = msg_col;
CmdlineInfo save_ccline;
- save_cmdline(&save_ccline);
-
+ bool did_save_ccline = false;
+ if (ccline.cmdbuff != NULL) {
+ // Save the values of the current cmdline and restore them below.
+ save_cmdline(&save_ccline);
+ did_save_ccline = true;
+ } else {
+ memset(&ccline, 0, sizeof(struct cmdline_info));
+ }
ccline.prompt_id = last_prompt_id++;
ccline.cmdprompt = (char_u *)prompt;
ccline.cmdattr = attr;
@@ -2447,9 +2458,11 @@ char *getcmdline_prompt(const char firstc, const char *const prompt, const int a
int msg_silent_saved = msg_silent;
msg_silent = 0;
- char *const ret = (char *)command_line_enter(firstc, 1L, 0);
+ char *const ret = (char *)command_line_enter(firstc, 1L, 0, false);
- restore_cmdline(&save_ccline);
+ if (did_save_ccline) {
+ 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
@@ -2601,7 +2614,6 @@ bool cmdline_at_end(void)
/*
* Allocate a new command line buffer.
* Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
- * Returns the new value of ccline.cmdbuff and ccline.cmdbufflen.
*/
static void alloc_cmdbuff(int len)
{
@@ -3367,53 +3379,23 @@ void put_on_cmdline(char_u *str, int len, int redraw)
}
}
-/*
- * Save ccline, because obtaining the "=" register may execute "normal :cmd"
- * and overwrite it. But get_cmdline_str() may need it, thus make it
- * available globally in prev_ccline.
- */
+/// Save ccline, because obtaining the "=" register may execute "normal :cmd"
+/// and overwrite it.
static void save_cmdline(struct cmdline_info *ccp)
{
*ccp = ccline;
+ memset(&ccline, 0, sizeof(struct cmdline_info));
ccline.prev_ccline = ccp;
- ccline.cmdbuff = NULL;
- ccline.cmdprompt = NULL;
- ccline.xpc = NULL;
- ccline.special_char = NUL;
- ccline.level = 0;
+ ccline.cmdbuff = NULL; // signal that ccline is not in use
}
-/*
- * Restore ccline after it has been saved with save_cmdline().
- */
+/// Restore ccline after it has been saved with save_cmdline().
static void restore_cmdline(struct cmdline_info *ccp)
FUNC_ATTR_NONNULL_ALL
{
ccline = *ccp;
}
-/*
- * Save the command line into allocated memory. Returns a pointer to be
- * passed to restore_cmdline_alloc() later.
- */
-char_u *save_cmdline_alloc(void)
- FUNC_ATTR_NONNULL_RET
-{
- struct cmdline_info *p = xmalloc(sizeof(struct cmdline_info));
- save_cmdline(p);
- return (char_u *)p;
-}
-
-/*
- * Restore the command line from the return value of save_cmdline_alloc().
- */
-void restore_cmdline_alloc(char_u *p)
- FUNC_ATTR_NONNULL_ALL
-{
- restore_cmdline((struct cmdline_info *)p);
- xfree(p);
-}
-
/// Paste a yank register into the command line.
/// Used by CTRL-R command in command-line mode.
/// insert_reg() can't be used here, because special characters from the
@@ -3429,7 +3411,6 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
char_u *arg;
char_u *p;
bool allocated;
- struct cmdline_info save_ccline;
// check for valid regname; also accept special characters for CTRL-R in
// the command line
@@ -3447,13 +3428,11 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
}
- // Need to save and restore ccline. And set "textlock" to avoid nasty
- // things like going to another buffer when evaluating an expression.
- save_cmdline(&save_ccline);
+ // Need to set "textlock" to avoid nasty things like going to another
+ // buffer when evaluating an expression.
textlock++;
const bool i = get_spec_reg(regname, &arg, &allocated, true);
textlock--;
- restore_cmdline(&save_ccline);
if (i) {
// Got the value of a special register in "arg".
@@ -5307,7 +5286,6 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
typval_T args[4];
char_u *pat = NULL;
const sctx_T save_current_sctx = current_sctx;
- struct cmdline_info save_ccline;
if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) {
return NULL;
@@ -5329,15 +5307,10 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
args[1].vval.v_string = xp->xp_line;
args[2].vval.v_number = xp->xp_col;
- // Save the cmdline, we don't know what the function may do.
- save_ccline = ccline;
- ccline.cmdbuff = NULL;
- ccline.cmdprompt = NULL;
current_sctx = xp->xp_script_ctx;
void *const ret = user_expand_func(xp->xp_arg, 3, args);
- ccline = save_ccline;
current_sctx = save_current_sctx;
if (ccline.cmdbuff != NULL) {
ccline.cmdbuff[ccline.cmdlen] = keep;
@@ -5947,10 +5920,8 @@ int get_history_idx(int histype)
}
-/*
- * Get pointer to the command line info to use. cmdline_paste() may clear
- * ccline and put the previous value in prev_ccline.
- */
+/// Get pointer to the command line info to use. save_cmdline() may clear
+/// ccline and put the previous value in ccline.prev_ccline.
static struct cmdline_info *get_ccline_ptr(void)
{
if ((State & CMDLINE) == 0) {
@@ -6350,6 +6321,11 @@ int hist_type2char(int type)
return NUL;
}
+void cmdline_init(void)
+{
+ memset(&ccline, 0, sizeof(struct cmdline_info));
+}
+
/// Open a window on the current command line and history. Allow editing in
/// the window. Returns when the window is closed.
/// Returns:
@@ -6358,7 +6334,6 @@ int hist_type2char(int type)
/// K_IGNORE if editing continues
static int open_cmdwin(void)
{
- struct cmdline_info save_ccline;
bufref_T old_curbuf;
bufref_T bufref;
win_T *old_curwin = curwin;
@@ -6459,9 +6434,6 @@ static int open_cmdwin(void)
}
redraw_later(curwin, SOME_VALID);
- // Save the command line info, can be used recursively.
- save_cmdline(&save_ccline);
-
// No Ex mode here!
exmode_active = false;
@@ -6499,8 +6471,6 @@ static int open_cmdwin(void)
// Restore KeyTyped in case it is modified by autocommands
KeyTyped = save_KeyTyped;
- // Restore the command line info.
- restore_cmdline(&save_ccline);
cmdwin_type = 0;
cmdwin_level = 0;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index c10172cc52..b12b99b7ee 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -4001,7 +4001,6 @@ static char_u *eval_map_expr(mapblock_T *mp, int c)
char_u *res;
char_u *p = NULL;
char_u *expr = NULL;
- char_u *save_cmd;
pos_T save_cursor;
int save_msg_col;
int save_msg_row;
@@ -4013,8 +4012,6 @@ static char_u *eval_map_expr(mapblock_T *mp, int c)
vim_unescape_ks(expr);
}
- save_cmd = save_cmdline_alloc();
-
// Forbid changing text or using ":normal" to avoid most of the bad side
// effects. Also restore the cursor position.
textlock++;
@@ -4045,8 +4042,6 @@ static char_u *eval_map_expr(mapblock_T *mp, int c)
msg_col = save_msg_col;
msg_row = save_msg_row;
- restore_cmdline_alloc(save_cmd);
-
if (p == NULL) {
return NULL;
}
diff --git a/src/nvim/main.c b/src/nvim/main.c
index afb9313cba..6ea1cb0875 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -20,6 +20,7 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
+#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
@@ -156,6 +157,7 @@ bool event_teardown(void)
void early_init(mparm_T *paramp)
{
env_init();
+ cmdline_init();
eval_init(); // init global variables
init_path(argv0 ? argv0 : "nvim");
init_normal_cmds(); // Init the table of Normal mode commands.