diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 125 |
1 files changed, 97 insertions, 28 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c42929ef7c..aab777955c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6733,6 +6733,39 @@ static void prepare_assert_error(garray_T *gap) } } +// Append "str" to "gap", escaping unprintable characters. +// Changes NL to \n, CR to \r, etc. +static void ga_concat_esc(garray_T *gap, char_u *str) +{ + char_u *p; + char_u buf[NUMBUFLEN]; + + if (str == NULL) { + ga_concat(gap, (char_u *)"NULL"); + return; + } + + for (p = str; *p != NUL; p++) { + switch (*p) { + case BS: ga_concat(gap, (char_u *)"\\b"); break; + case ESC: ga_concat(gap, (char_u *)"\\e"); break; + case FF: ga_concat(gap, (char_u *)"\\f"); break; + case NL: ga_concat(gap, (char_u *)"\\n"); break; + case TAB: ga_concat(gap, (char_u *)"\\t"); break; + case CAR: ga_concat(gap, (char_u *)"\\r"); break; + case '\\': ga_concat(gap, (char_u *)"\\\\"); break; + default: + if (*p < ' ') { + vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p); + ga_concat(gap, buf); + } else { + ga_append(gap, *p); + } + break; + } + } +} + // Fill "gap" with information about an assert error. static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, @@ -6747,28 +6780,30 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, } else { if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) { ga_concat(gap, (char_u *)"Pattern "); + } else if (atype == ASSERT_NOTEQUAL) { + ga_concat(gap, (char_u *)"Expected not equal to "); } else { ga_concat(gap, (char_u *)"Expected "); } if (exp_str == NULL) { - tofree = (char_u *) encode_tv2string(exp_tv, NULL); - ga_concat(gap, tofree); + tofree = (char_u *)encode_tv2string(exp_tv, NULL); + ga_concat_esc(gap, tofree); xfree(tofree); } else { - ga_concat(gap, exp_str); + ga_concat_esc(gap, exp_str); } - tofree = (char_u *)encode_tv2string(got_tv, NULL); - if (atype == ASSERT_MATCH) { - ga_concat(gap, (char_u *)" does not match "); - } else if (atype == ASSERT_NOTMATCH) { - ga_concat(gap, (char_u *)" does match "); - } else if (atype == ASSERT_NOTEQUAL) { - ga_concat(gap, (char_u *)" differs from "); - } else { - ga_concat(gap, (char_u *)" but got "); + if (atype != ASSERT_NOTEQUAL) { + if (atype == ASSERT_MATCH) { + ga_concat(gap, (char_u *)" does not match "); + } else if (atype == ASSERT_NOTMATCH) { + ga_concat(gap, (char_u *)" does match "); + } else { + ga_concat(gap, (char_u *)" but got "); + } + tofree = (char_u *)encode_tv2string(got_tv, NULL); + ga_concat_esc(gap, tofree); + xfree(tofree); } - ga_concat(gap, tofree); - xfree(tofree); } } @@ -11031,6 +11066,7 @@ void get_user_input(const typval_T *const argvars, const char *defstr = ""; const char *cancelreturn = NULL; const char *xp_name = NULL; + Callback input_callback = { .type = kCallbackNone }; char prompt_buf[NUMBUFLEN]; char defstr_buf[NUMBUFLEN]; char cancelreturn_buf[NUMBUFLEN]; @@ -11040,7 +11076,7 @@ void get_user_input(const typval_T *const argvars, emsgf(_("E5050: {opts} must be the only argument")); return; } - const dict_T *const dict = argvars[0].vval.v_dict; + dict_T *const dict = argvars[0].vval.v_dict; prompt = tv_dict_get_string_buf_chk(dict, S_LEN("prompt"), prompt_buf, ""); if (prompt == NULL) { return; @@ -11066,6 +11102,9 @@ void get_user_input(const typval_T *const argvars, if (xp_name == def) { // default to NULL xp_name = NULL; } + if (!tv_dict_get_callback(dict, S_LEN("highlight"), &input_callback)) { + return; + } } else { prompt = tv_get_string_buf_chk(&argvars[0], prompt_buf); if (prompt == NULL) { @@ -11124,12 +11163,13 @@ void get_user_input(const typval_T *const argvars, stuffReadbuffSpec(defstr); - int save_ex_normal_busy = ex_normal_busy; + const int save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; rettv->vval.v_string = - getcmdline_prompt(inputsecret_flag ? NUL : '@', (char_u *)p, echo_attr, - xp_type, (char_u *)xp_arg); + (char_u *)getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, + xp_type, xp_arg, input_callback); ex_normal_busy = save_ex_normal_busy; + callback_free(&input_callback); if (rettv->vval.v_string == NULL && cancelreturn != NULL) { rettv->vval.v_string = (char_u *)xstrdup(cancelreturn); @@ -17488,7 +17528,7 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol); } -/// Writes list of strings to file +/// Write "list" of strings to file "fd". /// /// @param fp File to write to. /// @param[in] list List to write. @@ -22770,7 +22810,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) bool eval_has_provider(const char *name) { -#define check_provider(name) \ +#define CHECK_PROVIDER(name) \ if (has_##name == -1) { \ has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \ if (!has_##name) { \ @@ -22786,17 +22826,17 @@ bool eval_has_provider(const char *name) static int has_python3 = -1; static int has_ruby = -1; - if (!strcmp(name, "clipboard")) { - check_provider(clipboard); + if (strequal(name, "clipboard")) { + CHECK_PROVIDER(clipboard); return has_clipboard; - } else if (!strcmp(name, "python3")) { - check_provider(python3); + } else if (strequal(name, "python3")) { + CHECK_PROVIDER(python3); return has_python3; - } else if (!strcmp(name, "python")) { - check_provider(python); + } else if (strequal(name, "python")) { + CHECK_PROVIDER(python); return has_python; - } else if (!strcmp(name, "ruby")) { - check_provider(ruby); + } else if (strequal(name, "ruby")) { + CHECK_PROVIDER(ruby); return has_ruby; } @@ -22810,3 +22850,32 @@ void eval_format_source_name_line(char *buf, size_t bufsize) (sourcing_name ? sourcing_name : (char_u *)"?"), (sourcing_name ? sourcing_lnum : 0)); } + +/// ":checkhealth [plugins]" +void ex_checkhealth(exarg_T *eap) +{ + bool found = !!find_func((char_u *)"health#check"); + if (!found + && script_autoload("health#check", sizeof("health#check") - 1, false)) { + found = !!find_func((char_u *)"health#check"); + } + if (!found) { + const char *vimruntime_env = os_getenv("VIMRUNTIME"); + if (vimruntime_env == NULL) { + EMSG(_("E5009: $VIMRUNTIME is empty or unset")); + return; + } else { + EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), os_getenv("VIMRUNTIME")); + return; + } + } + + size_t bufsize = STRLEN(eap->arg) + sizeof("call health#check('')"); + char *buf = xmalloc(bufsize); + snprintf(buf, bufsize, "call health#check('%s')", eap->arg); + + do_cmdline_cmd(buf); + + xfree(buf); +} + |