aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_getln.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-08-03 07:42:52 +0800
committerGitHub <noreply@github.com>2024-08-02 23:42:52 +0000
commit383f6934720a203d093c762cbd5362092110f35f (patch)
tree00c2b4ff33f60e4b30247fb6fba197f9d5b9b3c3 /src/nvim/ex_getln.c
parente7f8349a2eec01dda531d93fecb8df920b042d9f (diff)
downloadrneovim-383f6934720a203d093c762cbd5362092110f35f.tar.gz
rneovim-383f6934720a203d093c762cbd5362092110f35f.tar.bz2
rneovim-383f6934720a203d093c762cbd5362092110f35f.zip
refactor: move some functions out of eval.c (#29964)
- common_function() has always been in evalfunc.c in Vim - return_register() has always been in evalfunc.c in Vim - get_user_input() was moved to ex_getln.c in Vim 8.1.1957 - tv_get_lnum_buf() was moved to typval.c in Vim 8.2.0847
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r--src/nvim/ex_getln.c146
1 files changed, 138 insertions, 8 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index c8ca6f0e4e..8a34e03d91 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -267,6 +267,18 @@ static void init_incsearch_state(incsearch_state_T *s)
save_viewstate(curwin, &s->old_viewstate);
}
+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(curwin, MAXCOL);
+ }
+}
+
// Return true when 'incsearch' highlighting is to be done.
// Sets search_first_line and search_last_line to the address range.
static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *s,
@@ -4622,14 +4634,132 @@ char *script_get(exarg_T *const eap, size_t *const lenp)
return (char *)ga.ga_data;
}
-static void set_search_match(pos_T *t)
+/// 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.
+void get_user_input(const typval_T *const argvars, typval_T *const rettv, const bool inputdialog,
+ const bool secret)
+ FUNC_ATTR_NONNULL_ALL
{
- // 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(curwin, MAXCOL);
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+
+ const char *prompt;
+ const char *defstr = "";
+ typval_T *cancelreturn = NULL;
+ typval_T cancelreturn_strarg2 = TV_INITIAL_VALUE;
+ const char *xp_name = NULL;
+ Callback input_callback = { .type = kCallbackNone };
+ char prompt_buf[NUMBUFLEN];
+ char defstr_buf[NUMBUFLEN];
+ char cancelreturn_buf[NUMBUFLEN];
+ char xp_name_buf[NUMBUFLEN];
+ char def[1] = { 0 };
+ if (argvars[0].v_type == VAR_DICT) {
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ emsg(_("E5050: {opts} must be the only argument"));
+ return;
+ }
+ 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;
+ }
+ defstr = tv_dict_get_string_buf_chk(dict, S_LEN("default"), defstr_buf, "");
+ if (defstr == NULL) {
+ return;
+ }
+ dictitem_T *cancelreturn_di = tv_dict_find(dict, S_LEN("cancelreturn"));
+ if (cancelreturn_di != NULL) {
+ cancelreturn = &cancelreturn_di->di_tv;
+ }
+ xp_name = tv_dict_get_string_buf_chk(dict, S_LEN("completion"),
+ xp_name_buf, def);
+ if (xp_name == NULL) { // error
+ return;
+ }
+ 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) {
+ return;
+ }
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ defstr = tv_get_string_buf_chk(&argvars[1], defstr_buf);
+ if (defstr == NULL) {
+ return;
+ }
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ const char *const strarg2 = tv_get_string_buf_chk(&argvars[2], cancelreturn_buf);
+ if (strarg2 == NULL) {
+ return;
+ }
+ if (inputdialog) {
+ cancelreturn_strarg2.v_type = VAR_STRING;
+ cancelreturn_strarg2.vval.v_string = (char *)strarg2;
+ cancelreturn = &cancelreturn_strarg2;
+ } else {
+ xp_name = strarg2;
+ }
+ }
+ }
+ }
+
+ int xp_type = EXPAND_NOTHING;
+ char *xp_arg = NULL;
+ if (xp_name != NULL) {
+ // input() with a third argument: completion
+ const int xp_namelen = (int)strlen(xp_name);
+
+ uint32_t argt = 0;
+ if (parse_compl_arg(xp_name, xp_namelen, &xp_type,
+ &argt, &xp_arg) == FAIL) {
+ return;
+ }
+ }
+
+ const bool cmd_silent_save = 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, unlsess cmdline is externalized
+ const char *p = prompt;
+ if (!ui_has(kUICmdline)) {
+ const char *lastnl = strrchr(prompt, '\n');
+ if (lastnl != NULL) {
+ p = lastnl + 1;
+ msg_start();
+ msg_clr_eos();
+ msg_puts_len(prompt, p - prompt, get_echo_attr());
+ msg_didout = false;
+ msg_starthere();
+ }
}
+ cmdline_row = msg_row;
+
+ stuffReadbuffSpec(defstr);
+
+ const int save_ex_normal_busy = ex_normal_busy;
+ ex_normal_busy = 0;
+ rettv->vval.v_string = getcmdline_prompt(secret ? NUL : '@', p, get_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) {
+ tv_copy(cancelreturn, rettv);
+ }
+
+ 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;
}