mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(messages): recognize cmdline one_key/number prompt State (#34206)
Problem:  Since 48e2a736, prompt messages are handled by an actual
          active cmdline, resulting in `State` no longer being equal
          to `MODE_CONFIRM` which is used in some places. E.g. to
          specify the current `mode()` or to re-emit a confirm message.
Solution: Replace `MODE_CONFIRM` with a new `MODE_CMDLINE` sub-mode when
          `ccline.one_key/mouse_used` is set. Use it to avoid clearing
          mouse_used prompt messages, and to re-emit one_key messages
          (when ext_messages is inactive, for which this is unnecessary).
			
			
This commit is contained in:
		| @@ -266,12 +266,19 @@ void screenclear(void) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// Unlike cmdline "one_key" prompts, the message part of the prompt is not stored | ||||
| /// to be re-emitted: avoid clearing the prompt from the message grid. | ||||
| static bool cmdline_number_prompt(void) | ||||
| { | ||||
|   return !ui_has(kUIMessages) && State == MODE_CMDLINE && get_cmdline_info()->mouse_used != NULL; | ||||
| } | ||||
|  | ||||
| /// Set dimensions of the Nvim application "screen". | ||||
| void screen_resize(int width, int height) | ||||
| { | ||||
|   // Avoid recursiveness, can happen when setting the window size causes | ||||
|   // another window-changed signal. | ||||
|   if (updating_screen || resizing_screen) { | ||||
|   if (updating_screen || resizing_screen || cmdline_number_prompt()) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| @@ -348,7 +355,7 @@ void screen_resize(int width, int height) | ||||
|   resizing_autocmd = false; | ||||
|   redraw_all_later(UPD_CLEAR); | ||||
|  | ||||
|   if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) { | ||||
|   if (State != MODE_ASKMORE && State != MODE_EXTERNCMD) { | ||||
|     screenclear(); | ||||
|   } | ||||
|  | ||||
| @@ -364,8 +371,11 @@ void screen_resize(int width, int height) | ||||
|     // - While editing the command line, only redraw that. TODO: lies | ||||
|     // - in Ex mode, don't redraw anything. | ||||
|     // - Otherwise, redraw right now, and position the cursor. | ||||
|     if (State == MODE_ASKMORE || State == MODE_EXTERNCMD || State == MODE_CONFIRM | ||||
|         || exmode_active) { | ||||
|     if (State == MODE_ASKMORE || State == MODE_EXTERNCMD || exmode_active | ||||
|         || (State == MODE_CMDLINE && get_cmdline_info()->one_key)) { | ||||
|       if (State == MODE_CMDLINE) { | ||||
|         update_screen(); | ||||
|       } | ||||
|       if (msg_grid.chars) { | ||||
|         msg_grid_validate(); | ||||
|       } | ||||
| @@ -451,7 +461,7 @@ int update_screen(void) | ||||
|  | ||||
|   // Postpone the redrawing when it's not needed and when being called | ||||
|   // recursively. | ||||
|   if (!redrawing() || updating_screen) { | ||||
|   if (!redrawing() || updating_screen || cmdline_number_prompt()) { | ||||
|     return FAIL; | ||||
|   } | ||||
|  | ||||
| @@ -490,7 +500,7 @@ int update_screen(void) | ||||
|   } | ||||
|  | ||||
|   // if the screen was scrolled up when displaying a message, scroll it down | ||||
|   if (msg_scrolled || msg_grid_invalid) { | ||||
|   if ((msg_scrolled || msg_grid_invalid) && !cmdline_number_prompt()) { | ||||
|     clear_cmdline = true; | ||||
|     int valid = MAX(Rows - msg_scrollsize(), 0); | ||||
|     if (msg_grid.chars) { | ||||
| @@ -697,6 +707,7 @@ int update_screen(void) | ||||
|   if (still_may_intro) { | ||||
|     intro_message(false); | ||||
|   } | ||||
|   repeat_message(); | ||||
|  | ||||
|   decor_providers_invoke_end(); | ||||
|  | ||||
|   | ||||
| @@ -3716,12 +3716,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n | ||||
|  | ||||
|         if (subflags.do_ask && cmdpreview_ns <= 0) { | ||||
|           int typed = 0; | ||||
|  | ||||
|           // change State to MODE_CONFIRM, so that the mouse works | ||||
|           // properly | ||||
|           int save_State = State; | ||||
|           State = MODE_CONFIRM; | ||||
|           setmouse();                   // disable mouse in xterm | ||||
|           curwin->w_cursor.col = regmatch.startpos[0].col; | ||||
|  | ||||
|           if (curwin->w_p_crb) { | ||||
|   | ||||
| @@ -2197,7 +2197,6 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) | ||||
|       && !(p_paste && (State & (MODE_INSERT | MODE_CMDLINE))) | ||||
|       && !(State == MODE_HITRETURN && (tb_c1 == CAR || tb_c1 == ' ')) | ||||
|       && State != MODE_ASKMORE | ||||
|       && State != MODE_CONFIRM | ||||
|       && !at_ins_compl_key()) { | ||||
|     int mlen; | ||||
|     int nolmaplen; | ||||
|   | ||||
| @@ -41,8 +41,6 @@ int ask_yesno(const char *const str) | ||||
|   const int save_State = State; | ||||
|  | ||||
|   no_wait_return++; | ||||
|   State = MODE_CONFIRM;  // Mouse behaves like with :confirm. | ||||
|   setmouse();  // Disable mouse in xterm. | ||||
|   snprintf(IObuff, IOSIZE, _("%s (y/n)?"), str); | ||||
|   char *prompt = xstrdup(IObuff); | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
| #include "nvim/ex_cmds_defs.h" | ||||
| #include "nvim/ex_docmd.h" | ||||
| #include "nvim/ex_eval.h" | ||||
| #include "nvim/ex_getln.h" | ||||
| #include "nvim/fileio.h" | ||||
| #include "nvim/garray.h" | ||||
| #include "nvim/garray_defs.h" | ||||
| @@ -3072,13 +3073,17 @@ void msg_moremsg(bool full) | ||||
| } | ||||
|  | ||||
| /// Repeat the message for the current mode: MODE_ASKMORE, MODE_EXTERNCMD, | ||||
| /// MODE_CONFIRM or exmode_active. | ||||
| /// confirm() prompt or exmode_active. | ||||
| void repeat_message(void) | ||||
| { | ||||
|   if (ui_has(kUIMessages)) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if (State == MODE_ASKMORE) { | ||||
|     msg_moremsg(true);          // display --more-- message again | ||||
|     msg_row = Rows - 1; | ||||
|   } else if (State == MODE_CONFIRM) { | ||||
|   } else if (State == MODE_CMDLINE && confirm_msg != NULL) { | ||||
|     display_confirm_msg();      // display ":confirm" message again | ||||
|     msg_row = Rows - 1; | ||||
|   } else if (State == MODE_EXTERNCMD) { | ||||
| @@ -3550,8 +3555,6 @@ int do_dialog(int type, const char *title, const char *message, const char *butt | ||||
|   int oldState = State; | ||||
|  | ||||
|   msg_silent = 0;  // If dialog prompts for input, user needs to see it! #8788 | ||||
|   State = MODE_CONFIRM; | ||||
|   setmouse(); | ||||
|  | ||||
|   // Since we wait for a keypress, don't make the | ||||
|   // user press RETURN as well afterwards. | ||||
| @@ -3608,6 +3611,8 @@ int do_dialog(int type, const char *title, const char *message, const char *butt | ||||
|   } | ||||
|  | ||||
|   xfree(hotkeys); | ||||
|   xfree(confirm_msg); | ||||
|   confirm_msg = NULL; | ||||
|  | ||||
|   msg_silent = save_msg_silent; | ||||
|   State = oldState; | ||||
| @@ -3688,7 +3693,6 @@ static char *console_dialog_alloc(const char *message, const char *buttons, bool | ||||
|   } | ||||
|  | ||||
|   // Now allocate space for the strings | ||||
|   xfree(confirm_msg); | ||||
|   confirm_msg = xmalloc((size_t)msg_len); | ||||
|   snprintf(confirm_msg, (size_t)msg_len, "\n%s\n", message); | ||||
|  | ||||
|   | ||||
| @@ -184,12 +184,12 @@ void get_mode(char *buf) | ||||
| { | ||||
|   int i = 0; | ||||
|  | ||||
|   if (State == MODE_HITRETURN || State == MODE_ASKMORE | ||||
|       || State == MODE_SETWSIZE || State == MODE_CONFIRM) { | ||||
|   if (State == MODE_HITRETURN || State == MODE_ASKMORE || State == MODE_SETWSIZE | ||||
|       || (State == MODE_CMDLINE && get_cmdline_info()->one_key)) { | ||||
|     buf[i++] = 'r'; | ||||
|     if (State == MODE_ASKMORE) { | ||||
|       buf[i++] = 'm'; | ||||
|     } else if (State == MODE_CONFIRM) { | ||||
|     } else if (State == MODE_CMDLINE) { | ||||
|       buf[i++] = '?'; | ||||
|     } | ||||
|   } else if (State == MODE_EXTERNCMD) { | ||||
|   | ||||
| @@ -41,5 +41,4 @@ enum { | ||||
|   MODE_SETWSIZE    = 0x4000,  ///< window size has changed | ||||
|   MODE_EXTERNCMD   = 0x5000,  ///< executing an external command | ||||
|   MODE_SHOWMATCH   = 0x6000 | MODE_INSERT,  ///< show matching paren | ||||
|   MODE_CONFIRM     = 0x7000,  ///< ":confirm" prompt | ||||
| }; | ||||
|   | ||||
| @@ -613,8 +613,8 @@ void ui_check_mouse(void) | ||||
|     checkfor = MOUSE_INSERT; | ||||
|   } else if (State & MODE_CMDLINE) { | ||||
|     checkfor = MOUSE_COMMAND; | ||||
|   } else if (State == MODE_CONFIRM || State == MODE_EXTERNCMD) { | ||||
|     checkfor = ' ';  // don't use mouse for ":confirm" or ":!cmd" | ||||
|   } else if (State == MODE_EXTERNCMD) { | ||||
|     checkfor = ' ';  // don't use mouse for ":!cmd" | ||||
|   } | ||||
|  | ||||
|   // mouse should be active if at least one of the following is true: | ||||
|   | ||||
| @@ -2157,6 +2157,11 @@ describe('API', function() | ||||
|       feed('<F2>') | ||||
|       eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) | ||||
|     end) | ||||
|  | ||||
|     it('returns "c" during number prompt', function() | ||||
|       feed('ifoo<Esc>z=') | ||||
|       eq({ mode = 'c', blocking = false }, api.nvim_get_mode()) | ||||
|     end) | ||||
|   end) | ||||
|  | ||||
|   describe('RPC (K_EVENT)', function() | ||||
|   | ||||
| @@ -1106,7 +1106,7 @@ describe('cmdline redraw', function() | ||||
|     } | ||||
|   end) | ||||
|  | ||||
|   it('silent prompt', function() | ||||
|   it('prompt with silent mapping and screen update', function() | ||||
|     command([[nmap <silent> T :call confirm("Save changes?", "&Yes\n&No\n&Cancel")<CR>]]) | ||||
|     feed('T') | ||||
|     screen:expect([[ | ||||
| @@ -1116,6 +1116,31 @@ describe('cmdline redraw', function() | ||||
|       {6:Save changes?}            | | ||||
|       {6:[Y]es, (N)o, (C)ancel: }^  | | ||||
|     ]]) | ||||
|     command('call setline(1, "foo") | redraw') | ||||
|     screen:expect([[ | ||||
|       foo                      | | ||||
|       {3:                         }| | ||||
|                                | | ||||
|       {6:Save changes?}            | | ||||
|       {6:[Y]es, (N)o, (C)ancel: }^  | | ||||
|     ]]) | ||||
|     feed('Y') | ||||
|     screen:expect([[ | ||||
|       ^foo                      | | ||||
|       {1:~                        }|*3 | ||||
|                                | | ||||
|     ]]) | ||||
|     screen:try_resize(75, screen._height) | ||||
|     feed(':call inputlist(["foo", "bar"])<CR>') | ||||
|     screen:expect([[ | ||||
|       foo                                                                        | | ||||
|       {3:                                                                           }| | ||||
|       foo                                                                        | | ||||
|       bar                                                                        | | ||||
|       Type number and <Enter> or click with the mouse (q or empty cancels): ^     | | ||||
|     ]]) | ||||
|     command('redraw') | ||||
|     screen:expect_unchanged() | ||||
|   end) | ||||
|  | ||||
|   it('substitute confirm prompt does not scroll', function() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 luukvbaal
					luukvbaal