diff options
-rw-r--r-- | src/nvim/eval.c | 177 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 4 | ||||
-rw-r--r-- | src/nvim/message.c | 3 | ||||
-rw-r--r-- | src/nvim/viml/executor/executor.c | 38 |
4 files changed, 136 insertions, 86 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8b6638f1d7..fa817bb705 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12280,93 +12280,70 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) static int inputsecret_flag = 0; +/// Get user input +/// +/// Used for f_input and f_inputdialog functions. +/// +/// @param[in] prompt Input prompt. +/// @param[in] initval Initial value, may be NULL. +/// @param[in] xp_name Completion, for input(). +/// @param[in] cancelval Value returned when user cancelled dialog, for +/// inputdialog(). +/// +/// @return [allocated] User input or NULL. +char *get_user_input(const char *const prompt, + const char *const initval, + const char *const xp_name, + const char *const cancelval) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC +{ + char *ret = NULL; + const int saved_cmd_silent = cmd_silent; + cmd_silent = false; // Want to see the prompt. + // Only the part of the message after the last NL is considered as + // prompt for the command line. + const char *p = strrchr(prompt, NL); + if (p == NULL) { + p = prompt; + } else { + p++; + msg_start(); + msg_clr_eos(); + msg_puts_attr_len(prompt, (int)(p - prompt) + 1, echo_attr); + msg_didout = false; + msg_starthere(); + } + cmdline_row = msg_row; -/* - * This function is used by f_input() and f_inputdialog() functions. The third - * argument to f_input() specifies the type of completion to use at the - * prompt. The third argument to f_inputdialog() specifies the value to return - * when the user cancels the prompt. - */ -static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) -{ - char_u *prompt = get_tv_string_chk(&argvars[0]); - char_u *p = NULL; - int c; - char_u buf[NUMBUFLEN]; - int cmd_silent_save = cmd_silent; - char_u *defstr = (char_u *)""; - int xp_type = EXPAND_NOTHING; - char_u *xp_arg = NULL; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; + stuffReadbuffSpec((char_u *)initval); - cmd_silent = FALSE; /* Want to see the prompt. */ - if (prompt != NULL) { - /* Only the part of the message after the last NL is considered as - * prompt for the command line */ - p = vim_strrchr(prompt, '\n'); - if (p == NULL) - p = prompt; - else { - ++p; - c = *p; - *p = NUL; - msg_start(); - msg_clr_eos(); - msg_puts_attr((const char *)prompt, echo_attr); - msg_didout = false; - msg_starthere(); - *p = c; + char *xp_arg = NULL; + int xp_type = EXPAND_NOTHING; + if (xp_name != NULL) { + uint32_t argt; + if (parse_compl_arg((const char_u *)xp_name, (int)strlen(xp_name), + &xp_type, &argt, (char_u **)&xp_arg) == FAIL) { + return NULL; } - cmdline_row = msg_row; - - if (argvars[1].v_type != VAR_UNKNOWN) { - defstr = get_tv_string_buf_chk(&argvars[1], buf); - if (defstr != NULL) - stuffReadbuffSpec(defstr); - - if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) { - char_u *xp_name; - int xp_namelen; - uint32_t argt; - - /* input() with a third argument: completion */ - rettv->vval.v_string = NULL; - - xp_name = get_tv_string_buf_chk(&argvars[2], buf); - if (xp_name == NULL) - return; + } - xp_namelen = (int)STRLEN(xp_name); + const int saved_ex_normal_busy = ex_normal_busy; + ex_normal_busy = 0; + ret = (char *)getcmdline_prompt(inputsecret_flag ? NUL : '@', (char_u *)p, + echo_attr, xp_type, (char_u *)xp_arg); + ex_normal_busy = saved_ex_normal_busy; - if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, - &xp_arg) == FAIL) - return; - } - } - - if (defstr != NULL) { - int save_ex_normal_busy = ex_normal_busy; - ex_normal_busy = 0; - rettv->vval.v_string = - getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, - xp_type, xp_arg); - ex_normal_busy = save_ex_normal_busy; - } - if (inputdialog && rettv->vval.v_string == NULL - && argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) - rettv->vval.v_string = vim_strsave(get_tv_string_buf( - &argvars[2], buf)); + if (ret == NULL && cancelval != NULL) { + ret = xstrdup(cancelval); + } - xfree(xp_arg); + xfree(xp_arg); - /* since the user typed this, no need to wait for return */ - need_wait_return = FALSE; - msg_didout = FALSE; - } - cmd_silent = cmd_silent_save; + // Since the user typed this, no need to wait for return. + need_wait_return = false; + msg_didout = false; + cmd_silent = saved_cmd_silent; + return ret; } /* @@ -12375,7 +12352,25 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) */ static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - get_user_input(argvars, rettv, FALSE); + char initval_buf[NUMBUFLEN]; + char xp_name_buf[NUMBUFLEN]; + const char *const prompt = (const char *)get_tv_string_chk(&argvars[0]); + const char *const initval = ( + argvars[1].v_type != VAR_UNKNOWN + ? (const char *)get_tv_string_buf(&argvars[1], (char_u *)initval_buf) + : ""); + const char *const xp_name = ( + argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN + ? (const char *)get_tv_string_buf(&argvars[2], (char_u *)xp_name_buf) + : NULL); + if (prompt == NULL || initval == NULL || ( + argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN + && xp_name == NULL)) { + return; + } + rettv->v_type = VAR_STRING; + rettv->vval.v_string = (char_u *)get_user_input(prompt, initval, xp_name, + NULL); } /* @@ -12383,7 +12378,25 @@ static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - get_user_input(argvars, rettv, TRUE); + char initval_buf[NUMBUFLEN]; + char cancelval_buf[NUMBUFLEN]; + const char *const prompt = (const char *)get_tv_string_chk(&argvars[0]); + const char *const initval = ( + argvars[1].v_type != VAR_UNKNOWN + ? (const char *)get_tv_string_buf(&argvars[1], (char_u *)initval_buf) + : ""); + const char *const cancelval = ( + argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN + ? (const char *)get_tv_string_buf(&argvars[2], (char_u *)cancelval_buf) + : NULL); + if (prompt == NULL || initval == NULL || ( + argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN + && cancelval == NULL)) { + return; + } + rettv->v_type = VAR_STRING; + rettv->vval.v_string = (char_u *)get_user_input(prompt, initval, NULL, + cancelval); } /* diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 74bb6177c6..69dab9c18f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5757,10 +5757,10 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt, * copied to allocated memory and stored in "*compl_arg". * Returns FAIL if something is wrong. */ -int parse_compl_arg(char_u *value, int vallen, int *complp, +int parse_compl_arg(const char_u *value, int vallen, int *complp, uint32_t *argt, char_u **compl_arg) { - char_u *arg = NULL; + const char_u *arg = NULL; size_t arglen = 0; int i; int valend = vallen; diff --git a/src/nvim/message.c b/src/nvim/message.c index bf54284881..4b786c11dd 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1564,7 +1564,6 @@ void msg_puts_attr(const char *const s, const int attr) /// Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes). /// When "maxlen" is -1 there is no maximum length. -/// When "maxlen" is >= 0 the message is not put in the history. void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr) { // If redirection is on, also write to the redirection file. @@ -1576,7 +1575,7 @@ void msg_puts_attr_len(const char *str, const ptrdiff_t maxlen, int attr) } // if MSG_HIST flag set, add message to history - if ((attr & MSG_HIST) && maxlen < 0) { + if (attr & MSG_HIST) { add_msg_hist(str, -1, attr); attr &= ~MSG_HIST; } diff --git a/src/nvim/viml/executor/executor.c b/src/nvim/viml/executor/executor.c index 4eb63f38ad..d0e269bf6a 100644 --- a/src/nvim/viml/executor/executor.c +++ b/src/nvim/viml/executor/executor.c @@ -250,15 +250,28 @@ static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL /// Called by lua interpreter itself to initialize state. static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { + // stricmp lua_pushcfunction(lstate, &nlua_stricmp); lua_setglobal(lstate, "stricmp"); + + // print lua_pushcfunction(lstate, &nlua_print); lua_setglobal(lstate, "print"); + + // debug.debug + lua_getglobal(lstate, "debug"); + lua_pushcfunction(lstate, &nlua_debug); + lua_setfield(lstate, -2, "debug"); + lua_pop(lstate, 1); + + // vim if (luaL_dostring(lstate, (char *)&vim_module[0])) { nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); return 1; } + // vim.api nlua_add_api_functions(lstate); + // vim.types, vim.type_idx, vim.val_idx nlua_init_types(lstate); lua_setglobal(lstate, "vim"); return 0; @@ -442,6 +455,31 @@ nlua_print_error: return 0; } +/// debug.debug implementation: interaction with user while debugging +/// +/// @param lstate Lua interpreter state. +int nlua_debug(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + for (;;) { + lua_settop(lstate, 0); + char *const input = get_user_input("lua_debug> ", "", NULL, NULL); + msg_putchar('\n'); // Avoid outputting on input line. + if (input == NULL || *input == NUL || strcmp(input, "cont") == 0) { + xfree(input); + return 0; + } + if (luaL_loadbuffer(lstate, input, strlen(input), "=(debug command)")) { + nlua_error(lstate, _("E5115: Error while loading debug string: %.*s")); + } + xfree(input); + if (lua_pcall(lstate, 0, 0, 0)) { + nlua_error(lstate, _("E5116: Error while calling debug string: %.*s")); + } + } + return 0; +} + /// Evaluate lua string /// /// Used for luaeval(). |