feat(prompt): multiline prompt input #33371

Problem:
Cannot enter multiline prompts in a buftype=prompt buffer.

Solution:
- Support shift+enter (`<s-enter>`) to start a new line in the prompt.
- Pasting multiline text via OS paste, clipboard, "xp, etc.
- A/I in editable region works as usual.
- i/a/A/I outside of editable region moves cursor to end of current
  prompt.
- Support undo/redo in prompt buffer.
- Support o/O in prompt buffer.
- Expose prompt location as `':` mark.
This commit is contained in:
Shadman
2025-06-17 21:46:57 +06:00
committed by GitHub
parent 496691f985
commit 286371b4d2
13 changed files with 409 additions and 39 deletions

View File

@@ -1077,7 +1077,7 @@ check_pum:
cmdwin_result = CAR;
return 0;
}
if (bt_prompt(curbuf)) {
if ((mod_mask & MOD_MASK_SHIFT) == 0 && bt_prompt(curbuf)) {
invoke_prompt_callback();
if (!bt_prompt(curbuf)) {
// buffer changed to a non-prompt buffer, get out of
@@ -1532,9 +1532,14 @@ static void init_prompt(int cmdchar_todo)
{
char *prompt = prompt_text();
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
if (curwin->w_cursor.lnum < curbuf->b_prompt_start.mark.lnum) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
coladvance(curwin, MAXCOL);
}
char *text = get_cursor_line_ptr();
if (strncmp(text, prompt, strlen(prompt)) != 0) {
if ((curbuf->b_prompt_start.mark.lnum == curwin->w_cursor.lnum
&& strncmp(text, prompt, strlen(prompt)) != 0)
|| curbuf->b_prompt_start.mark.lnum > curwin->w_cursor.lnum) {
// prompt is missing, insert it or append a line with it
if (*text == NUL) {
ml_replace(curbuf->b_ml.ml_line_count, prompt, true);
@@ -1547,8 +1552,9 @@ static void init_prompt(int cmdchar_todo)
}
// Insert always starts after the prompt, allow editing text after it.
if (Insstart_orig.lnum != curwin->w_cursor.lnum || Insstart_orig.col != (colnr_T)strlen(prompt)) {
Insstart.lnum = curwin->w_cursor.lnum;
if (Insstart_orig.lnum != curbuf->b_prompt_start.mark.lnum
|| Insstart_orig.col != (colnr_T)strlen(prompt)) {
Insstart.lnum = curbuf->b_prompt_start.mark.lnum;
Insstart.col = (colnr_T)strlen(prompt);
Insstart_orig = Insstart;
Insstart_textlen = Insstart.col;
@@ -1559,7 +1565,9 @@ static void init_prompt(int cmdchar_todo)
if (cmdchar_todo == 'A') {
coladvance(curwin, MAXCOL);
}
curwin->w_cursor.col = MAX(curwin->w_cursor.col, (colnr_T)strlen(prompt));
if (curbuf->b_prompt_start.mark.lnum == curwin->w_cursor.lnum) {
curwin->w_cursor.col = MAX(curwin->w_cursor.col, (colnr_T)strlen(prompt));
}
// Make sure the cursor is in a valid position.
check_cursor(curwin);
}
@@ -1568,8 +1576,9 @@ static void init_prompt(int cmdchar_todo)
bool prompt_curpos_editable(void)
FUNC_ATTR_PURE
{
return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
&& curwin->w_cursor.col >= (int)strlen(prompt_text());
return curwin->w_cursor.lnum > curbuf->b_prompt_start.mark.lnum
|| (curwin->w_cursor.lnum == curbuf->b_prompt_start.mark.lnum
&& curwin->w_cursor.col >= (int)strlen(prompt_text()));
}
// Undo the previous edit_putchar().