Skip to content

Commit

Permalink
feat: cmdheight=0 neovim#16251
Browse files Browse the repository at this point in the history
Fix neovim#1004

Limitation: All outputs need hit-enter prompt.

Related:
neovim#6732
neovim#4382
  • Loading branch information
Shougo authored and kraftwerk28 committed Jul 5, 2022
1 parent bef7c8d commit 7e55f4f
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 36 deletions.
13 changes: 10 additions & 3 deletions runtime/doc/options.txt
Expand Up @@ -1320,6 +1320,9 @@ A jump table for the options with a short description can be found at |Q_op|.
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, it disables echo area and all outputs need
|hit-enter| prompt.

*'cmdwinheight'* *'cwh'*
'cmdwinheight' 'cwh' number (default 7)
global
Expand Down Expand Up @@ -4817,9 +4820,11 @@ A jump table for the options with a short description can be found at |Q_op|.
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 0, 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,
Expand Down Expand Up @@ -5525,6 +5530,7 @@ A jump table for the options with a short description can be found at |Q_op|.
global
Show (partial) command in the last line of the screen. Set this
option off if your terminal is slow.
The option is disabled if 'cmdheight' is 0.
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"
Expand Down Expand Up @@ -5571,6 +5577,7 @@ A jump table for the options with a short description can be found at |Q_op|.
global
If in Insert, Replace or Visual mode put a message on the last line.
The |hl-ModeMsg| highlight group determines the highlighting.
The option is disabled if 'cmdheight' is 0.

*'showtabline'* *'stal'*
'showtabline' 'stal' number (default 1)
Expand Down
30 changes: 24 additions & 6 deletions src/nvim/ex_getln.c
Expand Up @@ -108,11 +108,9 @@ typedef enum {
kCmdRedrawAll,
} CmdRedraw;

/*
* Variables shared between getcmdline(), redrawcmdline() and others.
* These need to be saved when using CTRL-R |, that's why they are in a
* structure.
*/
// Variables shared between getcmdline(), redrawcmdline() and others.
// These need to be saved when using CTRL-R |, that's why they are in a
// structure.
struct cmdline_info {
char_u *cmdbuff; // pointer to command line buffer
int cmdbufflen; // length of cmdbuff
Expand All @@ -139,6 +137,7 @@ struct cmdline_info {
bool special_shift; ///< shift of last putcmdline char
CmdRedraw redraw_state; ///< needed redraw for external cmdline
};

/// Last value of prompt_id, incremented when doing new prompt
static unsigned last_prompt_id = 0;

Expand Down Expand Up @@ -689,6 +688,14 @@ 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)
{
bool cmdheight0 = p_ch < 1 && !ui_has(kUIMessages) && vpeekc() == NUL;

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();
}

// can be invoked recursively, identify each level
static int cmdline_level = 0;
cmdline_level++;
Expand Down Expand Up @@ -976,6 +983,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
ccline.cmdbuff = NULL;
}

if (cmdheight0) {
// Restore cmdheight
set_option_value("ch", 0L, NULL, 0);
}

return p;
}

Expand Down Expand Up @@ -2670,6 +2682,12 @@ char *getcmdline_prompt(const char firstc, const char *const prompt, const int a
return ret;
}

// Return current cmdline prompt
char_u *get_cmdprompt(void)
{
return ccline.cmdprompt;
}

/*
* Return TRUE when the text must not be changed and we can't switch to
* another window or buffer. Used when editing the command line etc.
Expand Down Expand Up @@ -3777,7 +3795,7 @@ void redrawcmd(void)
msg_no_more = TRUE;
draw_cmdline(0, ccline.cmdlen);
msg_clr_eos();
msg_no_more = FALSE;
msg_no_more = false;

ccline.cmdspos = cmd_screencol(ccline.cmdpos);

Expand Down
34 changes: 20 additions & 14 deletions src/nvim/message.c
Expand Up @@ -18,6 +18,7 @@
#include "nvim/eval.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/func_attr.h"
#include "nvim/garray.h"
Expand Down Expand Up @@ -163,6 +164,7 @@ void msg_grid_validate(void)
{
grid_assign_handle(&msg_grid);
bool should_alloc = msg_use_grid();
int max_rows = Rows - p_ch;
if (should_alloc && (msg_grid.rows != Rows || msg_grid.cols != Columns
|| !msg_grid.chars)) {
// TODO(bfredl): eventually should be set to "invalid". I e all callers
Expand All @@ -174,7 +176,7 @@ void msg_grid_validate(void)
msg_grid.dirty_col = xcalloc(Rows, sizeof(*msg_grid.dirty_col));

// Tricky: allow resize while pager is active
int pos = msg_scrolled ? msg_grid_pos : Rows - p_ch;
int pos = msg_scrolled ? msg_grid_pos : max_rows;
ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.rows, msg_grid.cols,
false, true);
ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows);
Expand All @@ -184,7 +186,7 @@ void msg_grid_validate(void)
msg_grid.focusable = false;
msg_grid_adj.target = &msg_grid;
if (!msg_scrolled) {
msg_grid_set_pos(Rows - p_ch, false);
msg_grid_set_pos(max_rows, false);
}
} else if (!should_alloc && msg_grid.chars) {
ui_comp_remove_grid(&msg_grid);
Expand All @@ -195,8 +197,8 @@ void msg_grid_validate(void)
msg_grid_adj.row_offset = 0;
msg_grid_adj.target = &default_grid;
redraw_cmdline = true;
} else if (msg_grid.chars && !msg_scrolled && msg_grid_pos != Rows - p_ch) {
msg_grid_set_pos(Rows - p_ch, false);
} else if (msg_grid.chars && !msg_scrolled && msg_grid_pos != max_rows) {
msg_grid_set_pos(max_rows, false);
}

if (msg_grid.chars && cmdline_row < msg_grid_pos) {
Expand Down Expand Up @@ -1386,7 +1388,9 @@ void msg_start(void)
need_fileinfo = false;
}

if (need_clr_eos) {
bool no_msg_area = !ui_has(kUIMessages) && p_ch < 1;

if (need_clr_eos || (no_msg_area && redrawing_cmdline)) {
// Halfway an ":echo" command and getting an (error) message: clear
// any text from the command.
need_clr_eos = false;
Expand All @@ -1395,10 +1399,11 @@ void msg_start(void)

if (!msg_scroll && full_screen) { // overwrite last message
msg_row = cmdline_row;
msg_col =
cmdmsg_rl ? Columns - 1 :
0;
} else if (msg_didout) { // start message on next line
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
msg_putchar('\n');
did_return = true;
cmdline_row = msg_row;
Expand Down Expand Up @@ -3055,7 +3060,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) {
if (msg_silent == 0 && p_ch > 0) {
msg_clr_eos_force();
}
}
Expand All @@ -3077,10 +3082,11 @@ void msg_clr_eos_force(void)
msg_row = msg_grid_pos;
}

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));
if (p_ch > 0) {
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)) {
Expand Down
4 changes: 4 additions & 0 deletions src/nvim/normal.c
Expand Up @@ -2747,6 +2747,10 @@ void pop_showcmd(void)

static void display_showcmd(void)
{
if (p_ch < 1 && !ui_has(kUIMessages)) {
return;
}

int len;
len = (int)STRLEN(showcmd_buf);
showcmd_is_clear = (len == 0);
Expand Down
4 changes: 4 additions & 0 deletions src/nvim/ops.c
Expand Up @@ -6041,6 +6041,10 @@ void 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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/nvim/option.c
Expand Up @@ -4365,7 +4365,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
errmsg = e_positive;
}
} else if (pp == &p_ch) {
int minval = ui_has(kUIMessages) ? 0 : 1;
int minval = 0;
if (value < minval) {
errmsg = e_positive;
}
Expand Down
11 changes: 9 additions & 2 deletions src/nvim/screen.c
Expand Up @@ -6132,6 +6132,10 @@ void unshowmode(bool force)
// Clear the mode message.
void clearmode(void)
{
if (p_ch <= 0 && !ui_has(kUIMessages)) {
return;
}

const int save_msg_row = msg_row;
const int save_msg_col = msg_col;

Expand Down Expand Up @@ -6500,7 +6504,6 @@ static void win_redr_ruler(win_T *wp, bool always)

if (*p_ruf) {
int save_called_emsg = called_emsg;

called_emsg = false;
win_redr_custom(wp, false, true);
if (called_emsg) {
Expand Down Expand Up @@ -6558,6 +6561,10 @@ static void win_redr_ruler(win_T *wp, bool always)
off = 0;
}

if (!part_of_status && p_ch < 1 && !ui_has(kUIMessages)) {
return;
}

// In list mode virtcol needs to be recomputed
colnr_T virtcol = wp->w_virtcol;
if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) {
Expand Down Expand Up @@ -6770,7 +6777,7 @@ void screen_resize(int width, int height)
Columns = width;
check_shellsize();
int max_p_ch = Rows - min_rows() + 1;
if (!ui_has(kUIMessages) && p_ch > max_p_ch) {
if (!ui_has(kUIMessages) && p_ch > 0 && p_ch > max_p_ch) {
p_ch = max_p_ch ? max_p_ch : 1;
}
height = Rows;
Expand Down
10 changes: 8 additions & 2 deletions src/nvim/testdir/test_window_cmd.vim
Expand Up @@ -887,6 +887,7 @@ func Test_floatwin_splitmove()
endfunc

func Test_window_resize()
throw 'Skipped: Nvim supports cmdheight=0'
" Vertical :resize (absolute, relative, min and max size).
vsplit
vert resize 8
Expand Down Expand Up @@ -1028,9 +1029,14 @@ func Test_win_move_statusline()
call assert_equal(h0, winheight(0))
call assert_equal(1, &cmdheight)
endfor
" Nvim 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, 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)
Expand Down
13 changes: 7 additions & 6 deletions src/nvim/window.c
Expand Up @@ -907,7 +907,7 @@ void ui_ext_win_position(win_T *wp)
int comp_col = (int)col - (east ? wp->w_width_outer : 0);
comp_row += grid->comp_row;
comp_col += grid->comp_col;
comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - 1), 0);
comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - (p_ch > 0 ? 1 : 0)), 0);
comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0);
wp->w_winrow = comp_row;
wp->w_wincol = comp_col;
Expand Down Expand Up @@ -1144,6 +1144,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
if (flags & WSP_ROOM) {
needed += p_wh - wmh1 + oldwin->w_winbar_height;
}
if (p_ch < 1) {
needed += 1; // Adjust for cmdheight=0.
}
if (flags & (WSP_BOT | WSP_TOP)) {
minheight = frame_minheight(topframe, NOWIN) + need_status;
available = topframe->fr_height;
Expand Down Expand Up @@ -5501,7 +5504,7 @@ void win_setheight_win(int height, win_T *win)
}
}
cmdline_row = row;
p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1);
p_ch = MAX(Rows - cmdline_row, 0);
curtab->tp_ch_used = p_ch;
msg_row = row;
msg_col = 0;
Expand Down Expand Up @@ -5949,9 +5952,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
up = false;
// 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 + global_stl_height();
}
if (room < 0) {
Expand Down Expand Up @@ -6008,7 +6009,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
clear_cmdline = true;
}
cmdline_row = row;
p_ch = MAX(Rows - cmdline_row, ui_has(kUIMessages) ? 0 : 1);
p_ch = MAX(Rows - cmdline_row, 0);
curtab->tp_ch_used = p_ch;
redraw_all_later(SOME_VALID);
showmode();
Expand Down
2 changes: 1 addition & 1 deletion test/functional/options/num_options_spec.lua
Expand Up @@ -54,7 +54,7 @@ describe(':set validation', function()
should_fail('iminsert', 3, 'E474')
should_fail('imsearch', 3, 'E474')
should_fail('titlelen', -1, 'E487')
should_fail('cmdheight', 0, 'E487')
should_fail('cmdheight', -1, 'E487')
should_fail('updatecount', -1, 'E487')
should_fail('textwidth', -1, 'E487')
should_fail('tabstop', 0, 'E487')
Expand Down

0 comments on commit 7e55f4f

Please sign in to comment.