feat(ui): use msg_grid based implementation for cmdheight=0

This commit is contained in:
bfredl 2022-09-13 12:56:30 +02:00
parent bf6de51f55
commit 708bd68651
17 changed files with 89 additions and 135 deletions

View File

@ -1337,7 +1337,8 @@ A jump table for the options with a short description can be found at |Q_op|.
page can have a different value.
When 'cmdheight' is zero, there is no command-line unless it is being
used. Some informative messages will not be displayed, any other
used. The command-line will cover the last line of the screen when
shown. Some informative messages will not be displayed, any other
messages will cause the |hit-enter| prompt. Expect some other
unexpected behavior too.

View File

@ -3616,13 +3616,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
}
const bool cmdheight0 = !ui_has_messages();
if (cmdheight0) {
// If cmdheight is 0, cmdheight must be set to 1 when we enter command line.
set_option_value("ch", 1L, NULL, 0);
redraw_statuslines();
}
// Check for a match on each line.
// If preview: limit to max('cmdwinheight', viewport).
linenr_T line2 = eap->line2;
@ -3914,7 +3907,9 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
msg_no_more = false;
msg_scroll = (int)i;
show_cursor_info(true);
ui_cursor_goto(msg_row, msg_col);
if (!ui_has(kUIMessages)) {
ui_cursor_goto(msg_row, msg_col);
}
RedrawingDisabled = temp;
no_mapping++; // don't map this key
@ -4370,7 +4365,7 @@ skip:
beginline(BL_WHITE | BL_FIX);
}
}
if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask) {
if (!cmdpreview && !do_sub_msg(subflags.do_count) && subflags.do_ask && p_ch > 0) {
msg("");
}
} else {
@ -4385,7 +4380,9 @@ skip:
emsg(_(e_interr));
} else if (got_match) {
// did find something but nothing substituted
msg("");
if (p_ch > 0) {
msg("");
}
} else if (subflags.do_error) {
// nothing found
semsg(_(e_patnotf2), get_search_pat());
@ -4418,11 +4415,6 @@ skip:
}
}
if (cmdheight0) {
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
}
kv_destroy(preview_lines.subresults);
return retv;
#undef ADJUST_SUB_FIRSTLNUM

View File

@ -599,24 +599,6 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool
/// @param init_ccline clear ccline first
static uint8_t *command_line_enter(int firstc, long count, int indent, bool init_ccline)
{
const bool cmdheight0 = !ui_has_messages();
if (cmdheight0) {
const long save_so = lastwin->w_p_so;
// If cmdheight is 0, cmdheight must be set to 1 when we enter the
// command line. Set "made_cmdheight_nonzero" and reset 'scrolloff' to
// avoid scrolling the last window.
made_cmdheight_nonzero = true;
lastwin->w_p_so = 0;
set_option_value("ch", 1L, NULL, 0);
update_screen(UPD_VALID); // redraw the screen NOW
made_cmdheight_nonzero = false;
lastwin->w_p_so = save_so;
}
// can be invoked recursively, identify each level
static int cmdline_level = 0;
cmdline_level++;
@ -865,6 +847,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
// If the line is too long, clear it, so ruler and shown command do
// not get printed in the middle of it.
msg_check();
if (p_ch == 0 && !ui_has(kUIMessages)) {
if (must_redraw < UPD_VALID) {
must_redraw = UPD_VALID;
}
}
msg_scroll = s->save_msg_scroll;
redir_off = false;
@ -911,17 +898,6 @@ theend:
ccline.cmdbuff = NULL;
}
if (cmdheight0) {
made_cmdheight_nonzero = true;
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
// Redraw is needed for command line completion
redraw_all_later(UPD_NOT_VALID);
made_cmdheight_nonzero = false;
}
return p;
}
@ -3717,6 +3693,9 @@ void compute_cmdrow(void)
cmdline_row = wp->w_winrow + wp->w_height
+ wp->w_hsep_height + wp->w_status_height + global_stl_height();
}
if (cmdline_row == Rows) {
cmdline_row--;
}
lines_left = cmdline_row;
}

View File

@ -1655,9 +1655,10 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
no_mapping++;
allow_keys++;
for (;;) {
// Position the cursor. Needed after a message that ends in a space,
// or if event processing caused a redraw.
ui_cursor_goto(msg_row, msg_col);
if (msg_col > 0) {
// Position the cursor. Needed after a message that ends in a space.
ui_cursor_goto(msg_row, msg_col);
}
if (argvars[0].v_type == VAR_UNKNOWN) {
// getchar(): blocking wait.
@ -1695,12 +1696,6 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
no_mapping--;
allow_keys--;
if (!ui_has_messages()) {
// redraw the screen after getchar()
update_screen(UPD_NOT_VALID);
clear_cmdline = true;
}
set_vim_var_nr(VV_MOUSE_WIN, 0);
set_vim_var_nr(VV_MOUSE_WINID, 0);
set_vim_var_nr(VV_MOUSE_LNUM, 0);

View File

@ -1071,7 +1071,4 @@ EXTERN char windowsVersion[20] INIT(= { 0 });
EXTERN int exit_need_delay INIT(= 0);
// Set when 'cmdheight' is changed from zero to one temporarily.
EXTERN bool made_cmdheight_nonzero INIT(= false);
#endif // NVIM_GLOBALS_H

View File

@ -909,7 +909,7 @@ char *msg_may_trunc(bool force, char *s)
room = (Rows - cmdline_row - 1) * Columns + sc_col - 1;
if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
&& (int)strlen(s) - room > 0 && p_ch > 0) {
&& (int)STRLEN(s) - room > 0) {
int size = vim_strsize(s);
// There may be room anyway when there are multibyte chars.
@ -1401,9 +1401,7 @@ void msg_start(void)
need_fileinfo = false;
}
const bool no_msg_area = !ui_has_messages();
if (need_clr_eos || (no_msg_area && redrawing_cmdline)) {
if (need_clr_eos || (p_ch == 0 && redrawing_cmdline)) {
// Halfway an ":echo" command and getting an (error) message: clear
// any text from the command.
need_clr_eos = false;
@ -1411,12 +1409,14 @@ void msg_start(void)
}
if (!msg_scroll && full_screen) { // overwrite last message
if (cmdline_row >= Rows && !ui_has(kUIMessages)) {
msg_scroll_up(false, true);
msg_scrolled++;
cmdline_row = Rows - 1;
}
msg_row = cmdline_row;
msg_col = cmdmsg_rl ? Columns - 1 : 0;
if (no_msg_area && get_cmdprompt() == NULL) {
msg_row -= 1;
}
} else if (msg_didout || no_msg_area) { // start message on next line
} else if (msg_didout || (p_ch == 0 && !ui_has(kUIMessages))) { // start message on next line
msg_putchar('\n');
did_return = true;
cmdline_row = msg_row;
@ -2186,7 +2186,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse)
// Scroll the screen up one line.
bool has_last_char = ((uint8_t)(*s) >= ' ' && !cmdmsg_rl);
msg_scroll_up(!has_last_char);
msg_scroll_up(!has_last_char, false);
msg_row = Rows - 2;
if (msg_col >= Columns) { // can happen after screen resize
@ -2350,7 +2350,7 @@ bool msg_use_msgsep(void)
{
// the full-screen scroll behavior doesn't really make sense with
// 'ext_multigrid'
return (dy_flags & DY_MSGSEP) || ui_has(kUIMultigrid);
return (dy_flags & DY_MSGSEP) || p_ch == 0 || ui_has(kUIMultigrid);
}
bool msg_do_throttle(void)
@ -2359,7 +2359,7 @@ bool msg_do_throttle(void)
}
/// Scroll the screen up one line for displaying the next message line.
void msg_scroll_up(bool may_throttle)
void msg_scroll_up(bool may_throttle, bool zerocmd)
{
if (may_throttle && msg_do_throttle()) {
msg_grid.throttled = true;
@ -2367,7 +2367,13 @@ void msg_scroll_up(bool may_throttle)
msg_did_scroll = true;
if (msg_use_msgsep()) {
if (msg_grid_pos > 0) {
msg_grid_set_pos(msg_grid_pos - 1, true);
msg_grid_set_pos(msg_grid_pos - 1, !zerocmd);
// When displaying the first line with cmdheight=0, we need to draw over
// the existing last line of the screen.
if (zerocmd && msg_grid.chars) {
grid_clear_line(&msg_grid, msg_grid.line_offset[0], msg_grid.cols, false);
}
} else {
grid_del_lines(&msg_grid, 0, 1, msg_grid.rows, 0, msg_grid.cols);
memmove(msg_grid.dirty_col, msg_grid.dirty_col + 1,
@ -2378,8 +2384,7 @@ void msg_scroll_up(bool may_throttle)
grid_del_lines(&msg_grid_adj, 0, 1, Rows, 0, Columns);
}
grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ',
HL_ATTR(HLF_MSG));
grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ', HL_ATTR(HLF_MSG));
}
/// Send throttled message output to UI clients
@ -2958,7 +2963,7 @@ static int do_more_prompt(int typed_char)
msg_grid_scroll_discount++;
}
// scroll up, display line at bottom
msg_scroll_up(true);
msg_scroll_up(true, false);
inc_msg_scrolled();
grid_fill(&msg_grid_adj, Rows - 2, Rows - 1, 0, Columns, ' ', ' ',
HL_ATTR(HLF_MSG));
@ -3094,7 +3099,7 @@ void repeat_message(void)
/// Skip this when ":silent" was used, no need to clear for redirection.
void msg_clr_eos(void)
{
if (msg_silent == 0 && p_ch > 0) {
if (msg_silent == 0) {
msg_clr_eos_force();
}
}
@ -3116,12 +3121,10 @@ void msg_clr_eos_force(void)
msg_row = msg_grid_pos;
}
if (ui_has_messages()) {
grid_fill(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol,
' ', ' ', HL_ATTR(HLF_MSG));
grid_fill(&msg_grid_adj, msg_row + 1, Rows, 0, Columns,
' ', ' ', HL_ATTR(HLF_MSG));
}
grid_fill(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol,
' ', ' ', HL_ATTR(HLF_MSG));
grid_fill(&msg_grid_adj, msg_row + 1, Rows, 0, Columns,
' ', ' ', HL_ATTR(HLF_MSG));
redraw_cmdline = true; // overwritten the command line
if (msg_row < Rows - 1 || msg_col == (cmdmsg_rl ? Columns : 0)) {

View File

@ -2817,7 +2817,8 @@ void pop_showcmd(void)
static void display_showcmd(void)
{
if (!ui_has_messages()) {
if (p_ch == 0 && !ui_has(kUIMessages)) {
// TODO(bfredl): would be nice to show in global statusline, perhaps
return;
}

View File

@ -896,7 +896,6 @@ int do_record(int c)
{
char_u *p;
static int regname;
static bool changed_cmdheight = false;
yankreg_T *old_y_previous;
int retval;
@ -907,18 +906,11 @@ int do_record(int c)
retval = FAIL;
} else {
reg_recording = c;
// TODO(bfredl): showmode based messaging is currently missing with cmdheight=0
showmode();
regname = c;
retval = OK;
if (!ui_has_messages()) {
// Enable macro indicator temporarily
set_option_value("ch", 1L, NULL, 0);
update_screen(UPD_VALID);
changed_cmdheight = true;
}
apply_autocmds(EVENT_RECORDINGENTER, NULL, NULL, false, curbuf);
}
} else { // stop recording
@ -948,7 +940,7 @@ int do_record(int c)
restore_v_event(dict, &save_v_event);
reg_recorded = reg_recording;
reg_recording = 0;
if (ui_has(kUIMessages)) {
if (p_ch == 0 || ui_has(kUIMessages)) {
showmode();
} else {
msg("");
@ -964,12 +956,6 @@ int do_record(int c)
y_previous = old_y_previous;
}
if (changed_cmdheight) {
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
redraw_all_later(UPD_CLEAR);
}
}
return retval;
}

View File

@ -2570,9 +2570,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
Rows = (int)p_lines;
Columns = (int)p_columns;
check_screensize();
if (cmdline_row > Rows - p_ch && Rows > p_ch) {
assert(p_ch >= 0 && Rows - p_ch <= INT_MAX);
cmdline_row = (int)(Rows - p_ch);
int new_row = (int)(Rows - MAX(p_ch, 1));
if (cmdline_row > new_row && Rows > p_ch) {
assert(p_ch >= 0 && new_row <= INT_MAX);
cmdline_row = new_row;
}
}
if (p_window >= Rows || !option_was_set("window")) {

View File

@ -442,7 +442,7 @@ void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, i
// Put the wildmenu just above the command line. If there is
// no room, scroll the screen one line up.
if (cmdline_row == Rows - 1) {
msg_scroll_up(false);
msg_scroll_up(false, false);
msg_scrolled++;
} else {
cmdline_row++;
@ -1173,7 +1173,9 @@ bool redrawing(void)
/// Return true if printing messages should currently be done.
bool messaging(void)
{
return !(p_lz && char_avail() && !KeyTyped) && ui_has_messages();
// TODO(bfredl): with general support for "async" messages with p_ch,
// this should be re-enabled.
return !(p_lz && char_avail() && !KeyTyped) && (p_ch > 0 || ui_has(kUIMessages));
}
#define COL_RULER 17 // columns needed by standard ruler

View File

@ -266,7 +266,7 @@ void win_redr_ruler(win_T *wp, bool always)
off = 0;
}
if (!part_of_status && !ui_has_messages()) {
if (!part_of_status && p_ch == 0 && !ui_has(kUIMessages)) {
return;
}

View File

@ -398,7 +398,7 @@ func Test_cmdheight_zero()
" Check change/restore cmdheight when macro
call feedkeys("qa", "xt")
call assert_equal(1, &cmdheight)
call assert_equal(0, &cmdheight)
call feedkeys("q", "xt")
call assert_equal(0, &cmdheight)

View File

@ -614,12 +614,6 @@ bool ui_has(UIExtension ext)
return ui_ext[ext];
}
/// Returns true if the UI has messages area.
bool ui_has_messages(void)
{
return p_ch > 0 || ui_has(kUIMessages);
}
Array ui_array(void)
{
Array all_uis = ARRAY_DICT_INIT;

View File

@ -485,6 +485,10 @@ static void compose_debug(Integer startrow, Integer endrow, Integer startcol, In
endcol = MIN(endcol, default_grid.cols);
int attr = syn_id2attr(syn_id);
if (delay) {
debug_delay(endrow - startrow);
}
for (int row = (int)startrow; row < endrow; row++) {
ui_composed_call_raw_line(1, row, startcol, startcol, endcol, attr, false,
(const schar_T *)linebuf,
@ -610,7 +614,7 @@ static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrol
if (row > msg_current_row && ui_comp_should_draw()) {
compose_area(MAX(msg_current_row - 1, 0), row, 0, default_grid.cols);
} else if (row < msg_current_row && ui_comp_should_draw()
&& msg_current_row < Rows) {
&& (msg_current_row < Rows || (scrolled && !msg_was_scrolled))) {
int delta = msg_current_row - (int)row;
if (msg_grid.blending) {
int first_row = MAX((int)row - (scrolled?1:0), 0);

View File

@ -6193,8 +6193,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)
// There is no point in adjusting the scroll position when exiting. Some
// values might be invalid.
// Skip scroll_to_fraction() when 'cmdheight' was set to one from zero.
if (!exiting && !made_cmdheight_nonzero && valid_cursor) {
if (!exiting && valid_cursor) {
scroll_to_fraction(wp, prev_height);
}
redraw_later(wp, UPD_NOT_VALID); // UPD_SOME_VALID??

View File

@ -1022,7 +1022,7 @@ describe('cmdheight=0', function()
~ |
:^ |
]]}
eq(1, eval('&cmdheight'))
eq(0, eval('&cmdheight'))
feed('<cr>')
screen:expect{grid=[[
^ |
@ -1040,11 +1040,11 @@ describe('cmdheight=0', function()
screen:expect{grid=[[
|
~ |
~ |
~ |
|
:call input("foo >") |
foo >^ |
]]}
eq(1, eval('&cmdheight'))
eq(0, eval('&cmdheight'))
feed('<cr>')
screen:expect{grid=[[
^ |
@ -1060,8 +1060,8 @@ describe('cmdheight=0', function()
command("set cmdheight=0 noruler laststatus=3 winbar=foo")
feed(':split<CR>')
screen:expect{grid=[[
foo |
|
:split |
E36: Not enough room |
Press ENTER or type comma|
nd to continue^ |
@ -1079,7 +1079,7 @@ describe('cmdheight=0', function()
foo |
|
~ |
[No Name] |
~ |
:^ |
]]}
feed('<Esc>')
@ -1103,8 +1103,8 @@ describe('cmdheight=0', function()
~ |
~ |
~ |
recording @q |
]], showmode={}}
~ |
]]}
feed('q')
screen:expect{grid=[[
^ |
@ -1112,7 +1112,7 @@ describe('cmdheight=0', function()
~ |
~ |
~ |
]], showmode={}}
]], unchanged=true}
end)
it("when substitute text", function()
@ -1131,7 +1131,7 @@ describe('cmdheight=0', function()
foo |
~ |
~ |
[No Name] [+] |
~ |
replace wi...q/l/^E/^Y)?^ |
]]}

View File

@ -131,26 +131,15 @@ describe('timers', function()
nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem', {'repeat': -1})")
screen:expect([[
ITEM 1 |
^ITEM 1 |
ITEM 2 |
{1:~ }|
{1:~ }|
{1:~ }|
^ |
|
]])
nvim_async("command", "let g:cont = 1")
screen:expect([[
ITEM 1 |
ITEM 2 |
ITEM 3 |
{1:~ }|
{1:~ }|
^ |
]])
feed("3")
eq(51, eval("g:c2"))
screen:expect([[
^ITEM 1 |
ITEM 2 |
@ -159,6 +148,17 @@ describe('timers', function()
{1:~ }|
|
]])
feed("3")
eq(51, eval("g:c2"))
screen:expect{grid=[[
^ITEM 1 |
ITEM 2 |
ITEM 3 |
{1:~ }|
{1:~ }|
|
]], unchanged=true}
end)
it('can be stopped', function()