# HG changeset patch # User Bram Moolenaar # Date 1659196803 -7200 # Node ID 8a243ecfe2dde381f8010e1133a656d19d666738 # Parent b544e30ddc6c959f6c619d728311947e1277892f patch 9.0.0114: the command line takes up space even when not used Commit: https://github.com/vim/vim/commit/f39cfb72629f3e7fefaf578a3faa2619cd0654f8 Author: Shougo Matsushita Date: Sat Jul 30 16:54:05 2022 +0100 patch 9.0.0114: the command line takes up space even when not used Problem: The command line takes up space even when not used. Solution: Allow for 'cmdheight' to be set to zero. (Shougo Matsushita, closes #10675, closes #940) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1760,12 +1760,15 @@ A jump table for the options with a shor *'cmdheight'* *'ch'* 'cmdheight' 'ch' number (default 1) - global + global or local to tab page Number of screen lines to use for the command-line. Helps avoiding |hit-enter| prompts. The value of this option is stored with the tab page, so that each tab page can have a different value. + When 'cmdheight' is zero, there is no command-line unless it is being + used. Any messages will cause the |hit-enter| prompt. + *'cmdwinheight'* *'cwh'* 'cmdwinheight' 'cwh' number (default 7) global @@ -6446,9 +6449,11 @@ A jump table for the options with a shor 45% relative position in the file If 'rulerformat' is set, it will determine the contents of the ruler. Each window has its own ruler. If a window has a status line, the - ruler is shown there. Otherwise it is shown in the last line of the - screen. If the statusline is given by 'statusline' (i.e. not empty), - this option takes precedence over 'ruler' and 'rulerformat' + ruler is shown there. If a window doesn't have a status line and + 'cmdheight' is zero, the ruler is not shown. Otherwise it is shown in + the last line of the screen. If the statusline is given by + 'statusline' (i.e. not empty), this option takes precedence over + 'ruler' and 'rulerformat' If the number of characters displayed is different from the number of bytes in the text (e.g., for a TAB or a multibyte character), both the text column (byte number) and the screen column are shown, @@ -7098,6 +7103,7 @@ A jump table for the options with a shor |+cmdline_info| feature} Show (partial) command in the last line of the screen. Set this option off if your terminal is slow. + The option has no effect when 'cmdheight' is zero. In Visual mode the size of the selected area is shown: - When selecting characters within a line, the number of characters. If the number of bytes is different it is also displayed: "2-6" @@ -7147,6 +7153,7 @@ A jump table for the options with a shor If in Insert, Replace or Visual mode put a message on the last line. Use the 'M' flag in 'highlight' to set the type of highlighting for this message. + The option has no effect when 'cmdheight' is zero. When |XIM| may be used the message will include "XIM". But this doesn't mean XIM is really active, especially when 'imactivatekey' is not set. diff --git a/src/drawscreen.c b/src/drawscreen.c --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -649,8 +649,8 @@ win_redr_ruler(win_T *wp, int always, in int off = 0; int width; - // If 'ruler' off or redrawing disabled, don't do anything - if (!p_ru) + // If 'ruler' off or messages area disabled, don't do anything + if (!p_ru || (wp->w_status_height == 0 && p_ch == 0)) return; /* @@ -671,7 +671,7 @@ win_redr_ruler(win_T *wp, int always, in return; #ifdef FEAT_STL_OPT - if (*p_ruf) + if (*p_ruf && p_ch > 0) { int called_emsg_before = called_emsg; @@ -2506,7 +2506,8 @@ win_update(win_T *wp) // Past end of the window or end of the screen. Note that after // resizing wp->w_height may be end up too big. That's a problem // elsewhere, but prevent a crash here. - if (row > wp->w_height || row + wp->w_winrow >= Rows) + if (row > wp->w_height + || row + wp->w_winrow >= (p_ch > 0 ? Rows : Rows + 1)) { // we may need the size of that too long line later on if (dollar_vcol == -1) @@ -2560,7 +2561,7 @@ win_update(win_T *wp) // Safety check: if any of the wl_size values is wrong we might go over // the end of w_lines[]. - if (idx >= Rows) + if (idx >= (p_ch > 0 ? Rows : Rows + 1)) break; } @@ -2946,8 +2947,10 @@ redraw_asap(int type) schar_T *screenline2 = NULL; // copy from ScreenLines2[] redraw_later(type); - if (msg_scrolled || (State != MODE_NORMAL && State != MODE_NORMAL_BUSY) - || exiting) + if (msg_scrolled + || (State != MODE_NORMAL && State != MODE_NORMAL_BUSY) + || exiting + || p_ch == 0) return ret; // Allocate space to save the text displayed in the command line area. diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3704,6 +3704,7 @@ ex_substitute(exarg_T *eap) int endcolumn = FALSE; // cursor in last column when done pos_T old_cursor = curwin->w_cursor; int start_nsubs; + int cmdheight0 = p_ch == 0; #ifdef FEAT_EVAL int save_ma = 0; int save_sandbox = 0; @@ -4010,6 +4011,14 @@ ex_substitute(exarg_T *eap) } } + if (cmdheight0) + { + // If cmdheight is 0, cmdheight must be set to 1 when we enter command + // line. + set_option_value((char_u *)"ch", 1L, NULL, 0); + redraw_statuslines(); + } + /* * Check for a match on each line. */ @@ -4833,6 +4842,10 @@ outofmem: changed_window_setting(); #endif + // Restore cmdheight + if (cmdheight0) + set_option_value((char_u *)"ch", 0L, NULL, 0); + vim_regfree(regmatch.regprog); vim_free(sub_copy); diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1611,6 +1611,15 @@ getcmdline_int( int did_save_ccline = FALSE; int cmdline_type; int wild_type; + int cmdheight0 = p_ch == 0; + + if (cmdheight0) + { + // If cmdheight is 0, cmdheight must be set to 1 when we enter command + // line. + set_option_value((char_u *)"ch", 1L, NULL, 0); + update_screen(VALID); // redraw the screen NOW + } // one recursion level deeper ++depth; @@ -2595,6 +2604,13 @@ theend: { char_u *p = ccline.cmdbuff; + if (cmdheight0) + { + set_option_value((char_u *)"ch", 0L, NULL, 0); + // Redraw is needed for command line completion + redraw_all_later(CLEAR); + } + --depth; if (did_save_ccline) restore_cmdline(&save_ccline); diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -2096,6 +2096,10 @@ getchar_common(typval_T *argvars, typval --no_mapping; --allow_keys; + // redraw the screen after getchar() + if (p_ch == 0) + update_screen(CLEAR); + set_vim_var_nr(VV_MOUSE_WIN, 0); set_vim_var_nr(VV_MOUSE_WINID, 0); set_vim_var_nr(VV_MOUSE_LNUM, 0); diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -953,7 +953,7 @@ msg_may_trunc(int force, char_u *s) // just in case. room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1; if (room > 0 && (force || (shortmess(SHM_TRUNC) && !exmode_active)) - && (n = (int)STRLEN(s) - room) > 0) + && (n = (int)STRLEN(s) - room) > 0 && p_ch > 0) { if (has_mbyte) { @@ -1430,7 +1430,7 @@ msg_start(void) } #ifdef FEAT_EVAL - if (need_clr_eos) + if (need_clr_eos || p_ch == 0) { // Halfway an ":echo" command and getting an (error) message: clear // any text from the command. @@ -1448,7 +1448,7 @@ msg_start(void) #endif 0; } - else if (msg_didout) // start message on next line + else if (msg_didout || p_ch == 0) // start message on next line { msg_putchar('\n'); did_return = TRUE; @@ -3460,7 +3460,7 @@ msg_clr_eos_force(void) out_str(T_CE); // clear to end of line } } - else + else if (p_ch > 0) { #ifdef FEAT_RIGHTLEFT if (cmdmsg_rl) diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -1798,6 +1798,9 @@ display_showcmd(void) { int len; + if (p_ch == 0) + return; + cursor_off(); len = (int)STRLEN(showcmd_buf); diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -3260,6 +3260,11 @@ cursor_pos_info(dict_T *dict) // Don't shorten this message, the user asked for it. p = p_shm; p_shm = (char_u *)""; + if (p_ch < 1) + { + msg_start(); + msg_scroll = TRUE; + } msg((char *)IObuff); p_shm = p; } diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -3559,7 +3559,7 @@ set_num_option( // if p_ch changed value, change the command line height else if (pp == &p_ch) { - if (p_ch < 1) + if (p_ch < 0) { errmsg = e_argument_must_be_positive; p_ch = 1; diff --git a/src/register.c b/src/register.c --- a/src/register.c +++ b/src/register.c @@ -371,6 +371,7 @@ do_record(int c) { char_u *p; static int regname; + static int changed_cmdheight = FALSE; yankreg_T *old_y_previous, *old_y_current; int retval; @@ -385,6 +386,15 @@ do_record(int c) showmode(); regname = c; retval = OK; + + if (p_ch < 1) + { + // Enable macro indicator temporary + set_option_value((char_u *)"ch", 1L, NULL, 0); + update_screen(VALID); + + changed_cmdheight = TRUE; + } } } else // stop recording @@ -412,6 +422,13 @@ do_record(int c) y_previous = old_y_previous; y_current = old_y_current; } + + if (changed_cmdheight) + { + // Restore cmdheight + set_option_value((char_u *)"ch", 0L, NULL, 0); + redraw_all_later(CLEAR); + } } return retval; } diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -4726,7 +4726,7 @@ redrawing(void) int messaging(void) { - return (!(p_lz && char_avail() && !KeyTyped)); + return (!(p_lz && char_avail() && !KeyTyped)) && p_ch > 0; } /* diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -27,7 +27,7 @@ let fontname = has('win32') ? 'fixedsys' " Two lists with values: values that work and values that fail. " When not listed, "othernum" or "otherstring" is used. let test_values = { - \ 'cmdheight': [[1, 2, 10], [-1, 0]], + \ 'cmdheight': [[0, 1, 2, 10], [-1]], \ 'cmdwinheight': [[1, 2, 10], [-1, 0]], \ 'columns': [[12, 80], [-1, 0, 10]], \ 'conceallevel': [[0, 1, 2, 3], [-1, 4, 99]], diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -387,4 +387,51 @@ func Test_fileinfo_after_echo() call delete('b.txt') endfunc +func Test_cmdheight_zero() + set cmdheight=0 + set showcmd + redraw! + + echo 'test echo' + call assert_equal(116, screenchar(&lines, 1)) + redraw! + + echomsg 'test echomsg' + call assert_equal(116, screenchar(&lines, 1)) + redraw! + + call feedkeys(":ls\", "xt") + call assert_equal(':ls', Screenline(&lines - 1)) + redraw! + + let char = getchar(0) + call assert_match(char, 0) + + " Check change/restore cmdheight when macro + call feedkeys("qa", "xt") + call assert_equal(&cmdheight, 1) + call feedkeys("q", "xt") + call assert_equal(&cmdheight, 0) + + call setline(1, 'somestring') + call feedkeys("y", "n") + %s/somestring/otherstring/gc + call assert_equal(getline(1), 'otherstring') + + call feedkeys("g\", "xt") + call assert_match( + \ 'Col 1 of 11; Line 1 of 1; Word 1 of 1', + \ Screenline(&lines)) + + " Check split behavior + for i in range(1, 10) + split + endfor + only + call assert_equal(&cmdheight, 0) + + set cmdheight& + set showcmd& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -1481,9 +1481,12 @@ func Test_win_move_statusline() call assert_equal(h0, winheight(0)) call assert_equal(1, &cmdheight) endfor + " supports cmdheight=0 + set cmdheight=0 call assert_true(win_move_statusline(0, 1)) - call assert_equal(h0, winheight(0)) - call assert_equal(1, &cmdheight) + call assert_equal(h0 + 1, winheight(0)) + call assert_equal(0, &cmdheight) + set cmdheight& " check win_move_statusline from bottom window on top window ID let id = win_getid(1) for offset in range(5) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -736,6 +736,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 114, +/**/ 113, /**/ 112, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -1005,6 +1005,8 @@ win_split_ins( needed = wmh1 + STATUS_HEIGHT; if (flags & WSP_ROOM) needed += p_wh - wmh1; + if (p_ch == 0) + needed += 1; // Adjust for cmdheight=0. if (flags & (WSP_BOT | WSP_TOP)) { minheight = frame_minheight(topframe, NOWIN) + need_status; @@ -5668,6 +5670,8 @@ win_setheight_win(int height, win_T *win if (full_screen && msg_scrolled == 0 && row < cmdline_row) screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0); cmdline_row = row; + p_ch = MAX(Rows - cmdline_row, 0); + curtab->tp_ch_used = p_ch; msg_row = row; msg_col = 0; @@ -5704,9 +5708,12 @@ frame_setheight(frame_T *curfrp, int hei if (curfrp->fr_parent == NULL) { - // topframe: can only change the command line if (height > ROWS_AVAIL) - height = ROWS_AVAIL; + // If height is greater than the available space, try to create + // space for the frame by reducing 'cmdheight' if possible, while + // making sure `cmdheight` doesn't go below 1. + height = MIN((p_ch > 0 ? ROWS_AVAIL + (p_ch - 1) + : ROWS_AVAIL), height); if (height > 0) frame_new_height(curfrp, height, FALSE, FALSE); } @@ -6037,7 +6044,7 @@ win_setminheight(void) while (p_wmh > 0) { room = Rows - p_ch; - needed = min_rows() - 1; // 1 was added for the cmdline + needed = min_rows(); if (room >= needed) break; --p_wmh; @@ -6143,9 +6150,7 @@ win_drag_status_line(win_T *dragwin, int * Only dragging the last status line can reduce p_ch. */ room = Rows - cmdline_row; - if (curfr->fr_next == NULL) - room -= 1; - else + if (curfr->fr_next != NULL) room -= p_ch; if (room < 0) room = 0; @@ -6196,9 +6201,7 @@ win_drag_status_line(win_T *dragwin, int row = win_comp_pos(); screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0); cmdline_row = row; - p_ch = Rows - cmdline_row; - if (p_ch < 1) - p_ch = 1; + p_ch = MAX(Rows - cmdline_row, 0); curtab->tp_ch_used = p_ch; redraw_all_later(SOME_VALID); showmode(); @@ -6733,7 +6736,8 @@ min_rows(void) total = n; } total += tabline_height(); - total += 1; // count the room for the command line + if (p_ch > 0) + total += 1; // count the room for the command line return total; }