From d7cf1b31d5caf6c4e13cb6d8b2d55c4092739270 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Tue, 9 Dec 2025 23:46:22 -0500 Subject: [PATCH] vim-patch:8.2.2834: Vim9: :cexpr does not work with local variables Problem: Vim9: :cexpr does not work with local variables. Solution: Compile :cexpr. https://github.com/vim/vim/commit/5f7d4c049e934dbc8d2c3f2720797c10ee3c55c2 Co-authored-by: Bram Moolenaar --- src/nvim/quickfix.c | 48 +++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index f947fc84f1..3bd156867e 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1249,7 +1249,8 @@ static void qf_store_title(qf_list_T *qfl, const char *title) /// that created the quickfix list with the ":" prefix. /// Create a quickfix list title string by prepending ":" to a user command. /// Returns a pointer to a static buffer with the title. -static char *qf_cmdtitle(char *cmd) +static char *qf_cmdtitle(const char *cmd) + FUNC_ATTR_NONNULL_ALL { static char qftitle_str[IOSIZE]; @@ -7344,30 +7345,27 @@ static char *cexpr_get_auname(cmdidx_T cmdidx) } } -/// ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command. -/// ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command. -void ex_cexpr(exarg_T *eap) +static int trigger_cexpr_autocmd(int cmdidx) { - char *au_name = cexpr_get_auname(eap->cmdidx); + char *au_name = cexpr_get_auname(cmdidx); if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, curbuf->b_fname, true, curbuf)) { if (aborting()) { - return; + return FAIL; } } + return OK; +} +int cexpr_core(const exarg_T *eap, typval_T *tv) + FUNC_ATTR_NONNULL_ALL +{ win_T *wp = NULL; qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp); - // Evaluate the expression. When the result is a string or a list we can - // use it to fill the errorlist. - typval_T *tv = eval_expr(eap->arg, eap); - if (tv == NULL) { - return; - } - if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL) || tv->v_type == VAR_LIST) { + char *au_name = cexpr_get_auname(eap->cmdidx); incr_quickfix_busy(); int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, tv, p_efm, (eap->cmdidx != CMD_caddexpr @@ -7376,7 +7374,7 @@ void ex_cexpr(exarg_T *eap) qf_cmdtitle(*eap->cmdlinep), NULL); if (qf_stack_empty(qi)) { decr_quickfix_busy(); - goto cleanup; + return FAIL; } if (res >= 0) { qf_list_changed(qf_get_curlist(qi)); @@ -7396,10 +7394,30 @@ void ex_cexpr(exarg_T *eap) qf_jump_first(qi, save_qfid, eap->forceit); } decr_quickfix_busy(); + return OK; } else { emsg(_("E777: String or List expected")); } -cleanup: + return FAIL; +} + +/// ":cexpr {expr}", ":cgetexpr {expr}", ":caddexpr {expr}" command. +/// ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command. +/// Also: ":caddexpr", ":cgetexpr", "laddexpr" and "laddexpr". +void ex_cexpr(exarg_T *eap) +{ + if (trigger_cexpr_autocmd(eap->cmdidx) == FAIL) { + return; + } + + // Evaluate the expression. When the result is a string or a list we can + // use it to fill the errorlist. + typval_T *tv = eval_expr(eap->arg, eap); + if (tv == NULL) { + return; + } + + (void)cexpr_core(eap, tv); tv_free(tv); }