Merge pull request #18562 from famiu/feat/ui/winbar

feat(ui): add `'winbar'`
This commit is contained in:
bfredl 2022-05-18 13:08:07 +02:00 committed by GitHub
commit d7dd600716
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 538 additions and 169 deletions

View File

@ -844,8 +844,11 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
Treated as single-width even if it isn't.
• highlights: (boolean) Return highlight
information.
• use_winbar: (boolean) Evaluate winbar instead of
statusline.
• use_tabline: (boolean) Evaluate tabline instead
of statusline. When |TRUE|, {winid} is ignored.
Mutually exclusive with {use_winbar}.
Return: ~
Dictionary containing statusline information, with these

View File

@ -1501,8 +1501,9 @@ tag command action ~
|:recover| :rec[over] recover a file from a swap file
|:redo| :red[o] redo one undone change
|:redir| :redi[r] redirect messages to a file or register
|:redraw| :redr[aw] force a redraw of the display
|:redrawstatus| :redraws[tatus] force a redraw of the status line(s)
|:redraw| :redr[aw] force a redraw of the display
|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) and
window bar(s)
|:redrawtabline| :redrawt[abline] force a redraw of the tabline
|:registers| :reg[isters] display the contents of registers
|:resize| :res[ize] change current window height

View File

@ -2452,6 +2452,7 @@ A jump table for the options with a short description can be found at |Q_op|.
item default Used for ~
stl:c ' ' or '^' statusline of the current window
stlnc:c ' ' or '=' statusline of the non-current windows
wbr:c ' ' window bar
horiz:c '─' or '-' horizontal separators |:split|
horizup:c '┴' or '-' upwards facing horizontal separator
horizdown:c '┬' or '-' downwards facing horizontal separator
@ -2492,6 +2493,7 @@ A jump table for the options with a short description can be found at |Q_op|.
item highlight group ~
stl:c StatusLine |hl-StatusLine|
stlnc:c StatusLineNC |hl-StatusLineNC|
wbr:c WinBar |hl-WinBar| or |hl-WinBarNC|
horiz:c WinSeparator |hl-WinSeparator|
horizup:c WinSeparator |hl-WinSeparator|
horizdown:c WinSeparator |hl-WinSeparator|
@ -7045,6 +7047,19 @@ A jump table for the options with a short description can be found at |Q_op|.
key is never used for the menu.
This option is not used for <F10>; on Win32.
*'winbar'* *'wbr'*
'winbar' 'wbr' string (default empty)
global or local to window |global-local|
When non-empty, this option enables the window bar and determines its
contents. The window bar is a bar that's shown at the top of every
window with it enabled. The value of 'winbar' is evaluated like with
'statusline'.
When changing something that is used in 'winbar' that does not trigger
it to be updated, use |:redrawstatus|.
This option cannot be set in a modeline when 'modelineexpr' is off.
*'winblend'* *'winbl'*
'winblend' 'winbl' number (default 0)
local to window

View File

@ -5244,6 +5244,10 @@ Whitespace "nbsp", "space", "tab", "multispace", "lead" and "trail"
in 'listchars'.
*hl-WildMenu*
WildMenu Current match in 'wildmenu' completion.
*hl-WinBar*
WinBar Window bar of current window.
*hl-WinBarNC*
WinBarNC Window bar of not-current windows.
*hl-User1* *hl-User1..9* *hl-User9*
The 'statusline' syntax allows the use of 9 different highlights in the

View File

@ -30,10 +30,10 @@ CTRL-L Clears and redraws the screen. The redraw may happen
function (or a mapping if 'lazyredraw' set).
*:redraws* *:redrawstatus*
:redraws[tatus][!] Redraws the status line of the current window, or all
status lines if "!" is included.
Useful if 'statusline' includes an item that doesn't
cause automatic updating.
:redraws[tatus][!] Redraws the status line and window bar of the current
window, or all status lines and window bars if "!" is
included. Useful if 'statusline' or 'winbar' includes
an item that doesn't cause automatic updating.
*:redrawt* *:redrawtabline*
:redrawt[abline] Redraw the tabline. Useful to update the tabline when

View File

@ -80,6 +80,7 @@ return {
"maxwidth";
"fillchar";
"highlights";
"use_winbar";
"use_tabline";
};
option = {

View File

@ -1418,14 +1418,14 @@ bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
}
/// Get default statusline highlight for window
const char *get_default_stl_hl(win_T *wp)
const char *get_default_stl_hl(win_T *wp, bool use_winbar)
{
if (wp == NULL) {
return "TabLineFill";
} else if (wp == curwin) {
return "StatusLine";
} else if (use_winbar) {
return (wp == curwin) ? "WinBar" : "WinBarNC";
} else {
return "StatusLineNC";
return (wp == curwin) ? "StatusLine" : "StatusLineNC";
}
}

View File

@ -2274,8 +2274,9 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// - fillchar: (string) Character to fill blank spaces in the statusline (see
/// 'fillchars'). Treated as single-width even if it isn't.
/// - highlights: (boolean) Return highlight information.
/// - use_winbar: (boolean) Evaluate winbar instead of statusline.
/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid}
/// is ignored.
/// is ignored. Mutually exclusive with {use_winbar}.
///
/// @param[out] err Error details, if any.
/// @return Dictionary containing statusline information, with these keys:
@ -2294,6 +2295,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
int maxwidth;
int fillchar = 0;
Window window = 0;
bool use_winbar = false;
bool use_tabline = false;
bool highlights = false;
@ -2313,7 +2315,6 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
window = (Window)opts->winid.data.integer;
}
if (HAS_KEY(opts->fillchar)) {
if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0
|| ((size_t)utf_ptr2len(opts->fillchar.data.string.data)
@ -2323,7 +2324,6 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
}
fillchar = utf_ptr2char(opts->fillchar.data.string.data);
}
if (HAS_KEY(opts->highlights)) {
highlights = api_object_to_bool(opts->highlights, "highlights", false, err);
@ -2331,7 +2331,13 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
return result;
}
}
if (HAS_KEY(opts->use_winbar)) {
use_winbar = api_object_to_bool(opts->use_winbar, "use_winbar", false, err);
if (ERROR_SET(err)) {
return result;
}
}
if (HAS_KEY(opts->use_tabline)) {
use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err);
@ -2339,6 +2345,10 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
return result;
}
}
if (use_winbar && use_tabline) {
api_set_error(err, kErrorTypeValidation, "use_winbar and use_tabline are mutually exclusive");
return result;
}
win_T *wp, *ewp;
@ -2348,7 +2358,6 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar = ' ';
} else {
wp = find_window_by_handle(window, err);
if (wp == NULL) {
api_set_error(err, kErrorTypeException, "unknown winid %d", window);
return result;
@ -2356,8 +2365,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
ewp = wp;
if (fillchar == 0) {
int attr;
fillchar = fillchar_status(&attr, wp);
if (use_winbar) {
fillchar = wp->w_p_fcs_chars.wbr;
} else {
int attr;
fillchar = fillchar_status(&attr, wp);
}
}
}
@ -2369,7 +2382,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
maxwidth = (int)opts->maxwidth.data.integer;
} else {
maxwidth = (use_tabline || global_stl_height() > 0) ? Columns : wp->w_width;
maxwidth = (use_tabline || (!use_winbar && global_stl_height() > 0)) ? Columns : wp->w_width;
}
char buf[MAXPATHL];
@ -2404,7 +2417,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
// add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || ((char *)hltab->start - buf) != 0) {
Dictionary hl_info = ARRAY_DICT_INIT;
grpname = get_default_stl_hl(wp);
grpname = get_default_stl_hl(wp, use_winbar);
PUT(hl_info, "start", INTEGER_OBJ(0));
PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
@ -2418,22 +2431,18 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
PUT(hl_info, "start", INTEGER_OBJ((char *)sp->start - buf));
if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp);
grpname = get_default_stl_hl(wp, use_winbar);
} else if (sp->userhl < 0) {
grpname = (char *)syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
grpname = user_group;
}
PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
ADD(hl_values, DICTIONARY_OBJ(hl_info));
}
PUT(result, "highlights", ARRAY_OBJ(hl_values));
}
PUT(result, "str", CSTR_TO_OBJ((char *)buf));
return result;

View File

@ -233,6 +233,8 @@ typedef struct {
#define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak'
char_u *wo_stl;
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline'
char *wo_wbr;
#define w_p_wbr w_onebuf_opt.wo_wbr // 'winbar'
int wo_scb;
#define w_p_scb w_onebuf_opt.wo_scb // 'scrollbind'
int wo_diff_saved; // options were saved for starting diff mode
@ -1235,6 +1237,7 @@ struct window_S {
struct {
int stl;
int stlnc;
int wbr;
int horiz;
int horizup;
int horizdown;
@ -1282,14 +1285,20 @@ struct window_S {
//
int w_winrow; // first row of window in screen
int w_height; // number of rows in window, excluding
// status/command/winbar line(s)
// status/command line(s)
int w_status_height; // number of status lines (0 or 1)
int w_winbar_height; // number of window bars (0 or 1)
int w_wincol; // Leftmost column of window in screen.
int w_width; // Width of window, excluding separation.
int w_hsep_height; // Number of horizontal separator rows (0 or 1)
int w_vsep_width; // Number of vertical separator columns (0 or 1).
pos_save_T w_save_cursor; // backup of cursor pos and topline
int w_winrow_off; ///< offset from winrow to the inner window area
int w_wincol_off; ///< offset from wincol to the inner window area
///< this includes float border but excludes special columns
///< implemented in win_line() (i.e. signs, folds, numbers)
// inner size of window, which can be overridden by external UI
int w_height_inner;
int w_width_inner;
@ -1379,6 +1388,7 @@ struct window_S {
linenr_T w_redraw_top; // when != 0: first line needing redraw
linenr_T w_redraw_bot; // when != 0: last line needing redraw
bool w_redr_status; // if true status line must be redrawn
bool w_redr_winbar; // if true window bar must be redrawn
bool w_redr_border; // if true border must be redrawn
// remember what is shown in the ruler for this window (if 'ruler' set)
@ -1408,6 +1418,7 @@ struct window_S {
// A few options have local flags for P_INSECURE.
uint32_t w_p_stl_flags; // flags for 'statusline'
uint32_t w_p_wbr_flags; // flags for 'winbar'
uint32_t w_p_fde_flags; // flags for 'foldexpr'
uint32_t w_p_fdt_flags; // flags for 'foldtext'
int *w_p_cc_cols; // array of columns to highlight or NULL

View File

@ -6405,7 +6405,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow + 1);
tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline);
tv_dict_add_nr(dict, S_LEN("botline"), wp->w_botline - 1);
tv_dict_add_nr(dict, S_LEN("winbar"), 0);
tv_dict_add_nr(dict, S_LEN("winbar"), wp->w_winbar_height);
tv_dict_add_nr(dict, S_LEN("width"), wp->w_width);
tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum);
tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1);

View File

@ -3611,8 +3611,8 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// necessary for a top border since `row` starts at -1 in that case.
if (row < height + wp->w_border_adj[2]) {
winid = wp->handle;
winrow = row + 1 + wp->w_border_adj[0]; // Adjust by 1 for top border
wincol = col + 1 + wp->w_border_adj[3]; // Adjust by 1 for left border
winrow = row + 1 + wp->w_winrow_off; // Adjust by 1 for top border
wincol = col + 1 + wp->w_wincol_off; // Adjust by 1 for left border
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) {
(void)mouse_comp_pos(wp, &row, &col, &lnum);
col = vcol2col(wp, lnum, col);

View File

@ -8830,7 +8830,7 @@ static void ex_redraw(exarg_T *eap)
ui_flush();
}
/// ":redrawstatus": force redraw of status line(s)
/// ":redrawstatus": force redraw of status line(s) and window bar(s)
static void ex_redrawstatus(exarg_T *eap)
{
if (State & MODE_CMDPREVIEW) {
@ -8846,8 +8846,7 @@ static void ex_redrawstatus(exarg_T *eap)
} else {
status_redraw_curbuf();
}
update_screen(VIsual_active ? INVERTED :
0);
update_screen(VIsual_active ? INVERTED : 0);
RedrawingDisabled = r;
p_lz = p;
ui_flush();

View File

@ -111,7 +111,9 @@ typedef enum {
HLF_NFLOAT, // Floating window
HLF_MSG, // Message area
HLF_BORDER, // Floating window border
HLF_COUNT, // MUST be the last one
HLF_WBR, // Window bars
HLF_WBRNC, // Window bars of not-current windows
HLF_COUNT, // MUST be the last one
} hlf_T;
EXTERN const char *hlf_names[] INIT(= {
@ -172,6 +174,8 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_NFLOAT] = "NormalFloat",
[HLF_MSG] = "MsgArea",
[HLF_BORDER] = "FloatBorder",
[HLF_WBR] = "WinBar",
[HLF_WBRNC] = "WinBarNC",
});

View File

@ -103,9 +103,11 @@ static const char *highlight_init_both[] = {
"TabLineFill cterm=reverse gui=reverse",
"TabLineSel cterm=bold gui=bold",
"TermCursor cterm=reverse gui=reverse",
"WinBar cterm=bold gui=bold",
"WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
"default link VertSplit Normal",
"default link WinSeparator VertSplit",
"default link WinBarNC WinBar",
"default link EndOfBuffer NonText",
"default link LineNrAbove LineNr",
"default link LineNrBelow LineNr",

View File

@ -68,12 +68,12 @@ bool is_mouse_key(int c)
/// mouse was previously on a status line, then the status line may be dragged.
///
/// If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
/// cursor is moved unless the cursor was on a status line.
/// cursor is moved unless the cursor was on a status line or window bar.
/// This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
/// IN_SEP_LINE depending on where the cursor was clicked.
///
/// If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
/// the mouse is on the status line of the same window.
/// the mouse is on the status line or window bar of the same window.
///
/// If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
/// the last call.
@ -87,6 +87,7 @@ int jump_to_mouse(int flags, bool *inclusive, int which_button)
{
static int on_status_line = 0; // #lines below bottom of window
static int on_sep_line = 0; // on separator right of window
static bool on_winbar = false;
static int prev_row = -1;
static int prev_col = -1;
static win_T *dragwin = NULL; // window being dragged
@ -126,6 +127,9 @@ retnomove:
if (on_sep_line) {
return IN_SEP_LINE;
}
if (on_winbar) {
return IN_OTHER_WIN | MOUSE_WINBAR;
}
if (flags & MOUSE_MAY_STOP_VIS) {
end_visual_mode();
redraw_curbuf_later(INVERTED); // delete the inversion
@ -155,9 +159,11 @@ retnomove:
fdc = win_fdccol_count(wp);
dragwin = NULL;
if (row == -1) {
return IN_OTHER_WIN;
if (row == -1 + wp->w_winbar_height) {
on_winbar = !!wp->w_winbar_height;
return IN_OTHER_WIN | (on_winbar ? MOUSE_WINBAR : 0);
}
on_winbar = false;
// winpos and height may change in win_enter()!
if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) {
@ -253,6 +259,9 @@ retnomove:
did_drag |= count;
}
return IN_SEP_LINE; // Cursor didn't move
} else if (on_winbar) {
// After a click on the window bar don't start Visual mode.
return IN_OTHER_WIN | MOUSE_WINBAR;
} else {
// keep_window_focus must be true
// before moving the cursor for a left click, stop Visual mode
@ -497,6 +506,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
// exist.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == fp->fr_win) {
*rowp -= wp->w_winrow_off - wp->w_winbar_height;
return wp;
}
}

View File

@ -1016,7 +1016,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
col -= wp->w_leftcol;
if (col >= 0 && col < wp->w_width) {
coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_border_adj[3]) + 1;
coloff = col - scol + (local ? 0 : wp->w_wincol + wp->w_wincol_off) + 1;
} else {
scol = ccol = ecol = 0;
// character is left or right of the window
@ -1027,7 +1027,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
}
}
}
*rowp = (local ? 0 : wp->w_winrow + wp->w_border_adj[0]) + row + rowoff;
*rowp = (local ? 0 : wp->w_winrow + wp->w_winrow_off) + row + rowoff;
*scolp = scol + coloff;
*ccolp = ccol + coloff;
*ecolp = ecol + coloff;

View File

@ -1280,7 +1280,8 @@ static void normal_redraw(NormalState *s)
validate_cursor();
if (VIsual_active) {
update_curbuf(INVERTED); // update inverted part
redraw_curbuf_later(INVERTED); // update inverted part
update_screen(INVERTED);
} else if (must_redraw) {
update_screen(0);
} else if (redraw_cmdline || clear_cmdline) {
@ -1850,6 +1851,11 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
oap == NULL ? NULL : &(oap->inclusive),
which_button);
// A click in the window bar has no side effects.
if (jump_flags & MOUSE_WINBAR) {
return false;
}
moved = (jump_flags & CURSOR_MOVED);
in_status_line = (jump_flags & IN_STATUS_LINE);
in_sep_line = (jump_flags & IN_SEP_LINE);

View File

@ -2149,6 +2149,8 @@ static uint32_t *insecure_flag(win_T *const wp, int opt_idx, int opt_flags)
switch ((int)options[opt_idx].indir) {
case PV_STL:
return &wp->w_p_stl_flags;
case PV_WBR:
return &wp->w_p_wbr_flags;
case PV_FDE:
return &wp->w_p_fde_flags;
case PV_FDT:
@ -2930,8 +2932,8 @@ ambw_end:
curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
redraw_titles();
}
} else if (gvarp == &p_stl || varp == &p_tal || varp == &p_ruf) {
// 'statusline', 'tabline' or 'rulerformat'
} else if (gvarp == &p_stl || gvarp == (char_u **)&p_wbr || varp == &p_tal || varp == &p_ruf) {
// 'statusline', 'winbar', 'tabline' or 'rulerformat'
int wid;
if (varp == &p_ruf) { // reset ru_wid first
@ -2950,12 +2952,16 @@ ambw_end:
errmsg = check_stl_option(p_ruf);
}
} else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
// check 'statusline' or 'tabline' only if it doesn't start with "%!"
// check 'statusline', 'winbar' or 'tabline' only if it doesn't start with "%!"
errmsg = check_stl_option(s);
}
if (varp == &p_ruf && errmsg == NULL) {
comp_col();
}
// add / remove window bars for 'winbar'
if (gvarp == (char_u **)&p_wbr) {
set_winbar();
}
} else if (gvarp == &p_cpt) {
// check if it is a valid value for 'complete' -- Acevedo
for (s = *varp; *s;) {
@ -3570,6 +3576,7 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
struct chars_tab fcs_tab[] = {
{ &wp->w_p_fcs_chars.stl, "stl", ' ' },
{ &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
{ &wp->w_p_fcs_chars.wbr, "wbr", ' ' },
{ &wp->w_p_fcs_chars.horiz, "horiz", 9472 }, // ─
{ &wp->w_p_fcs_chars.horizup, "horizup", 9524 }, // ┴
{ &wp->w_p_fcs_chars.horizdown, "horizdown", 9516 }, // ┬
@ -3612,15 +3619,15 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
if (*p_ambw == 'd') {
// XXX: If ambiwidth=double then some characters take 2 columns,
// which is forbidden (TUI limitation?). Set old defaults.
fcs_tab[2].def = '-';
fcs_tab[3].def = '-';
fcs_tab[4].def = '-';
fcs_tab[5].def = '|';
fcs_tab[5].def = '-';
fcs_tab[6].def = '|';
fcs_tab[7].def = '|';
fcs_tab[8].def = '+';
fcs_tab[9].def = '-';
fcs_tab[12].def = '|';
fcs_tab[8].def = '|';
fcs_tab[9].def = '+';
fcs_tab[10].def = '-';
fcs_tab[13].def = '|';
}
}
@ -4766,7 +4773,7 @@ static void check_redraw(uint32_t flags)
bool doclear = (flags & P_RCLR) == P_RCLR;
bool all = ((flags & P_RALL) == P_RALL || doclear);
if ((flags & P_RSTAT) || all) { // mark all status lines dirty
if ((flags & P_RSTAT) || all) { // mark all status lines and window bars dirty
status_redraw_all();
}
@ -5814,6 +5821,9 @@ void unset_global_local_option(char *name, void *from)
case PV_STL:
clear_string_option(&((win_T *)from)->w_p_stl);
break;
case PV_WBR:
clear_string_option((char_u **)&((win_T *)from)->w_p_wbr);
break;
case PV_UL:
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
break;
@ -5891,6 +5901,8 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
return (char_u *)&(curwin->w_p_sbr);
case PV_STL:
return (char_u *)&(curwin->w_p_stl);
case PV_WBR:
return (char_u *)&(curwin->w_p_wbr);
case PV_UL:
return (char_u *)&(curbuf->b_p_ul);
case PV_LW:
@ -5984,6 +5996,9 @@ static char_u *get_varp(vimoption_T *p)
case PV_STL:
return *curwin->w_p_stl != NUL
? (char_u *)&(curwin->w_p_stl) : p->var;
case PV_WBR:
return *curwin->w_p_wbr != NUL
? (char_u *)&(curwin->w_p_wbr) : p->var;
case PV_UL:
return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
? (char_u *)&(curbuf->b_p_ul) : p->var;
@ -6252,6 +6267,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_rlc = vim_strsave(from->wo_rlc);
to->wo_sbr = vim_strsave(from->wo_sbr);
to->wo_stl = vim_strsave(from->wo_stl);
to->wo_wbr = xstrdup(from->wo_wbr);
to->wo_wrap = from->wo_wrap;
to->wo_wrap_save = from->wo_wrap_save;
to->wo_lbr = from->wo_lbr;
@ -6327,6 +6343,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_fcs);
check_string_option(&wop->wo_lcs);
check_string_option(&wop->wo_ve);
check_string_option((char_u **)&wop->wo_wbr);
}
/// Free the allocated memory inside a winopt_T.
@ -6352,6 +6369,7 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_fcs);
clear_string_option(&wop->wo_lcs);
clear_string_option(&wop->wo_ve);
clear_string_option((char_u **)&wop->wo_wbr);
}
void didset_window_options(win_T *wp)

View File

@ -618,6 +618,7 @@ EXTERN int p_stmp; // 'shelltemp'
EXTERN int p_ssl; // 'shellslash'
#endif
EXTERN char_u *p_stl; // 'statusline'
EXTERN char *p_wbr; // 'winbar'
EXTERN int p_sr; // 'shiftround'
EXTERN char_u *p_shm; // 'shortmess'
EXTERN char_u *p_sbr; // 'showbreak'
@ -897,6 +898,7 @@ enum {
WV_FCS,
WV_LCS,
WV_WINBL,
WV_WBR,
WV_COUNT, // must be the last one
};

View File

@ -2831,6 +2831,16 @@ return {
varname='p_wak',
defaults={if_true="menu"}
},
{
full_name='winbar', abbreviation='wbr',
short_desc=N_("custom format for the window bar"),
type='string', scope={'global', 'window'},
alloced=true,
modelineexpr=true,
redraw={'statuslines'},
varname='p_wbr',
defaults={if_true=""}
},
{
full_name='winblend', abbreviation='winbl',
short_desc=N_("Controls transparency level for floating windows"),

View File

@ -276,25 +276,25 @@ void redrawWinline(win_T *wp, linenr_T lnum)
}
}
/*
* update all windows that are editing the current buffer
*/
void update_curbuf(int type)
{
redraw_curbuf_later(type);
update_screen(type);
}
/// called when the status bars for the buffer 'buf' need to be updated
void redraw_buf_status_later(buf_T *buf)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == buf
&& (wp->w_status_height || (wp == curwin && global_stl_height()))) {
if (wp->w_buffer != buf) {
continue;
}
bool redraw = false;
if (wp->w_status_height || (wp == curwin && global_stl_height())) {
wp->w_redr_status = true;
if (must_redraw < VALID) {
must_redraw = VALID;
}
redraw = true;
}
if (wp->w_winbar_height) {
wp->w_redr_winbar = true;
redraw = true;
}
if (redraw && must_redraw < VALID) {
must_redraw = VALID;
}
}
}
@ -400,6 +400,9 @@ int update_screen(int type)
if (wp->w_floating) {
continue;
}
if (wp->w_winrow + wp->w_winbar_height > valid) {
wp->w_redr_winbar = true;
}
if (W_ENDROW(wp) > valid) {
wp->w_redr_type = MAX(wp->w_redr_type, NOT_VALID);
}
@ -431,6 +434,9 @@ int update_screen(int type)
wp->w_redr_type = REDRAW_TOP;
} else {
wp->w_redr_type = NOT_VALID;
if (wp->w_winrow + wp->w_winbar_height <= msg_scrolled) {
wp->w_redr_winbar = true;
}
if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height <= msg_scrolled) {
wp->w_redr_status = true;
}
@ -585,10 +591,13 @@ int update_screen(int type)
win_update(wp, &providers);
}
// redraw status line after the window to minimize cursor movement
// redraw status line and window bar after the window to minimize cursor movement
if (wp->w_redr_status) {
win_redr_status(wp);
}
if (wp->w_redr_winbar) {
win_redr_winbar(wp);
}
}
end_search_hl();
@ -743,6 +752,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (type >= NOT_VALID) {
wp->w_redr_status = true;
wp->w_redr_winbar = true;
wp->w_lines_valid = 0;
}
@ -4528,42 +4538,55 @@ void rl_mirror(char_u *str)
}
}
/*
* mark all status lines for redraw; used after first :cd
*/
/// Mark all status lines and window bars for redraw; used after first :cd
void status_redraw_all(void)
{
if (global_stl_height()) {
curwin->w_redr_status = true;
redraw_later(curwin, VALID);
} else {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height) {
wp->w_redr_status = true;
redraw_later(wp, VALID);
}
bool is_stl_global = global_stl_height() != 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
bool redraw = false;
if ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin)) {
wp->w_redr_status = true;
redraw = true;
}
if (wp->w_winbar_height) {
wp->w_redr_winbar = true;
redraw = true;
}
if (redraw) {
redraw_later(wp, VALID);
}
}
}
/// Marks all status lines of the current buffer for redraw.
/// Marks all status lines and window bars of the current buffer for redraw.
void status_redraw_curbuf(void)
{
status_redraw_buf(curbuf);
}
/// Marks all status lines of the specified buffer for redraw.
/// Marks all status lines and window bars of the given buffer for redraw.
void status_redraw_buf(buf_T *buf)
{
if (global_stl_height() != 0 && curwin->w_buffer == buf) {
curwin->w_redr_status = true;
redraw_later(curwin, VALID);
} else {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height != 0 && wp->w_buffer == buf) {
wp->w_redr_status = true;
redraw_later(wp, VALID);
}
bool is_stl_global = global_stl_height() != 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer != buf) {
continue;
}
bool redraw = false;
if ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin)) {
wp->w_redr_status = true;
redraw = true;
}
if (wp->w_winbar_height) {
wp->w_redr_winbar = true;
redraw = true;
}
if (redraw) {
redraw_later(wp, VALID);
}
}
}
@ -4577,6 +4600,9 @@ void redraw_statuslines(void)
if (wp->w_redr_status) {
win_redr_status(wp);
}
if (wp->w_redr_winbar) {
win_redr_winbar(wp);
}
}
if (redraw_tabline) {
draw_tabline();
@ -5075,7 +5101,7 @@ static void redraw_custom_statusline(win_T *wp)
entered = true;
did_emsg = false;
win_redr_custom(wp, false);
win_redr_custom(wp, false, false);
if (did_emsg) {
// When there is an error disable the statusline, otherwise the
// display is messed up with errors and a redraw triggers the problem
@ -5088,6 +5114,41 @@ static void redraw_custom_statusline(win_T *wp)
entered = false;
}
static void win_redr_winbar(win_T *wp)
{
static bool entered = false;
// Return when called recursively. This can happen when the winbar contains an expression
// that triggers a redraw.
if (entered) {
return;
}
entered = true;
wp->w_redr_winbar = false;
if (wp->w_winbar_height == 0) {
// No window bar, do nothing.
} else if (!redrawing()) {
// Don't redraw right now, do it later.
wp->w_redr_winbar = true;
} else if (*p_wbr != NUL || *wp->w_p_wbr != NUL) {
int saved_did_emsg = did_emsg;
did_emsg = false;
win_redr_custom(wp, true, false);
if (did_emsg) {
// When there is an error disable the winbar, otherwise the
// display is messed up with errors and a redraw triggers the problem
// again and again.
set_string_option_direct("winbar", -1, (char_u *)"",
OPT_FREE | (*wp->w_p_stl != NUL
? OPT_LOCAL : OPT_GLOBAL), SID_ERROR);
}
did_emsg |= saved_did_emsg;
}
entered = false;
}
/// Only call if (wp->w_vsep_width != 0).
///
/// @return true if the status line of window "wp" is connected to the status
@ -5224,11 +5285,9 @@ bool get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len)
return buf[0] != NUL;
}
/*
* Redraw the status line or ruler of window "wp".
* When "wp" is NULL redraw the tab pages line from 'tabline'.
*/
static void win_redr_custom(win_T *wp, bool draw_ruler)
/// Redraw the status line, window bar or ruler of window "wp".
/// When "wp" is NULL redraw the tab pages line from 'tabline'.
static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
{
static bool entered = false;
int attr;
@ -5269,6 +5328,14 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
attr = HL_ATTR(HLF_TPF);
maxwidth = Columns;
use_sandbox = was_set_insecurely(wp, "tabline", 0);
} else if (draw_winbar) {
stl = (char_u *)((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
row = wp->w_winrow;
col = wp->w_wincol;
fillchar = wp->w_p_fcs_chars.wbr;
attr = (wp == curwin) ? HL_ATTR(HLF_WBR) : HL_ATTR(HLF_WBRNC);
maxwidth = wp->w_width_inner;
use_sandbox = was_set_insecurely(wp, "winbar", 0);
} else {
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
fillchar = fillchar_status(&attr, wp);
@ -5553,14 +5620,17 @@ void win_grid_alloc(win_T *wp)
grid->Rows = rows;
grid->Columns = cols;
wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
wp->w_wincol_off = wp->w_border_adj[3];
if (want_allocation) {
grid->target = grid_allocated;
grid->row_offset = wp->w_border_adj[0];
grid->col_offset = wp->w_border_adj[3];
grid->row_offset = wp->w_winrow_off;
grid->col_offset = wp->w_wincol_off;
} else {
grid->target = &default_grid;
grid->row_offset = wp->w_winrow;
grid->col_offset = wp->w_wincol;
grid->row_offset = wp->w_winrow + wp->w_winrow_off;
grid->col_offset = wp->w_wincol + wp->w_wincol_off;
}
// send grid resize event if:
@ -6220,7 +6290,7 @@ void draw_tabline(void)
// Check for an error. If there is one we would loop in redrawing the
// screen. Avoid that by making 'tabline' empty.
did_emsg = false;
win_redr_custom(NULL, false);
win_redr_custom(NULL, false, false);
if (did_emsg) {
set_string_option_direct("tabline", -1,
(char_u *)"", OPT_FREE, SID_ERROR);
@ -6516,7 +6586,7 @@ static void win_redr_ruler(win_T *wp, bool always)
int save_called_emsg = called_emsg;
called_emsg = false;
win_redr_custom(wp, true);
win_redr_custom(wp, false, true);
if (called_emsg) {
set_string_option_direct("rulerformat", -1, (char_u *)"",
OPT_FREE, SID_ERROR);

View File

@ -102,10 +102,11 @@ func Test_screenpos()
bwipe!
call assert_equal({'col': 1, 'row': 1, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
" Needs WinBar
" nmenu WinBar.TEST :
" call assert_equal({'col': 1, 'row': 2, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
setlocal winbar=TEST
call assert_equal({'col': 1, 'row': 2, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
" nunmenu WinBar.TEST
setlocal winbar&
endfunc
func Test_screenpos_number()

View File

@ -695,6 +695,7 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err)
}
wp->w_floating = 1;
wp->w_status_height = 0;
wp->w_winbar_height = 0;
wp->w_hsep_height = 0;
wp->w_vsep_width = 0;
@ -780,10 +781,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
}
if (!ui_has(kUIMultigrid)) {
wp->w_height = MIN(wp->w_height,
Rows - 1 - (wp->w_border_adj[0] + wp->w_border_adj[2]));
wp->w_width = MIN(wp->w_width,
Columns - (wp->w_border_adj[1] + wp->w_border_adj[3]));
wp->w_height = MIN(wp->w_height, Rows - 1 - win_extra_height(wp));
wp->w_width = MIN(wp->w_width, Columns - win_extra_width(wp));
}
win_set_inner_size(wp);
@ -1138,15 +1137,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else {
layout = FR_COL;
/*
* Check if we are able to split the current window and compute its
* height.
*/
// Current window requires at least 1 space.
wmh1 = p_wmh == 0 ? 1 : p_wmh;
// Check if we are able to split the current window and compute its height.
// Current window requires at least 1 space plus space for the window bar.
wmh1 = MAX(p_wmh, 1) + oldwin->w_winbar_height;
needed = wmh1 + STATUS_HEIGHT;
if (flags & WSP_ROOM) {
needed += p_wh - wmh1;
needed += p_wh - wmh1 + oldwin->w_winbar_height;
}
if (flags & (WSP_BOT | WSP_TOP)) {
minheight = frame_minheight(topframe, NOWIN) + need_status;
@ -1155,8 +1151,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else if (p_ea) {
minheight = frame_minheight(oldwin->w_frame, NOWIN) + need_status;
prevfrp = oldwin->w_frame;
for (frp = oldwin->w_frame->fr_parent; frp != NULL;
frp = frp->fr_parent) {
for (frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) {
if (frp->fr_layout == FR_COL) {
FOR_ALL_FRAMES(frp2, frp->fr_child) {
if (frp2 != prevfrp) {
@ -1339,6 +1334,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
set_fraction(oldwin);
}
wp->w_fraction = oldwin->w_fraction;
wp->w_winbar_height = oldwin->w_winbar_height;
if (flags & WSP_VERT) {
wp->w_p_scr = curwin->w_p_scr;
@ -1416,9 +1412,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
if (flags & (WSP_TOP | WSP_BOT)) {
int new_fr_height = curfrp->fr_height - new_size;
if (!((flags & WSP_BOT) && p_ls == 0) && global_stl_height() == 0) {
if (!((flags & WSP_BOT) && p_ls == 0) && !is_stl_global) {
new_fr_height -= STATUS_HEIGHT;
} else if (global_stl_height() > 0) {
} else if (is_stl_global) {
if (flags & WSP_BOT) {
frame_add_hsep(curfrp);
} else {
@ -1452,7 +1448,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
}
if ((flags & WSP_BOT) && global_stl_height() == 0) {
if ((flags & WSP_BOT) && !is_stl_global) {
frame_add_statusline(curfrp);
}
frame_fix_height(wp);
@ -1482,10 +1478,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
* equalize the window sizes.
*/
if (do_equal || dir != 0) {
win_equal(wp, true,
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
: dir == 'h' ? 'b' :
'v');
win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
}
// Don't change the window height/width to 'winheight' / 'winwidth' if a
@ -1675,10 +1668,10 @@ int win_count(void)
}
/// Make "count" windows on the screen.
/// Must be called when there is just one window, filling the whole screen
/// Must be called when there is just one window, filling the whole screen.
/// (excluding the command line).
///
/// @param vertical split windows vertically if true
/// @param vertical split windows vertically if true.
///
/// @return actual number of windows on the screen.
int make_windows(int count, bool vertical)
@ -1687,15 +1680,15 @@ int make_windows(int count, bool vertical)
int todo;
if (vertical) {
// Each window needs at least 'winminwidth' lines and a separator
// column.
// Each window needs at least 'winminwidth' lines and a separator column.
maxcount = (curwin->w_width + curwin->w_vsep_width
- (p_wiw - p_wmw)) / (p_wmw + 1);
} else {
// Each window needs at least 'winminheight' lines
// If statusline isn't global, each window also needs a statusline
// Each window needs at least 'winminheight' lines.
// If statusline isn't global, each window also needs a statusline.
// If 'winbar' is set, each window also needs a winbar.
maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height
- (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
- (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT + global_winbar_height());
}
if (maxcount < 2) {
@ -1705,17 +1698,13 @@ int make_windows(int count, bool vertical)
count = maxcount;
}
/*
* add status line now, otherwise first window will be too big
*/
// add status line now, otherwise first window will be too big
if (count > 1) {
last_status(true);
}
/*
* Don't execute autocommands while creating the windows. Must do that
* when putting the buffers in the windows.
*/
// Don't execute autocommands while creating the windows. Must do that
// when putting the buffers in the windows.
block_autocmds();
// todo is number of windows left to create
@ -1790,7 +1779,7 @@ static void win_exchange(long Prenum)
* if wp != wp2
* 3. remove wp from the list
* 4. insert wp after wp2
* 5. exchange the status line height, hsep height and vsep width.
* 5. exchange the status line height, winbar height, hsep height and vsep width.
*/
wp2 = curwin->w_prev;
frp2 = curwin->w_frame->fr_prev;
@ -1897,7 +1886,7 @@ static void win_rotate(bool upwards, int count)
frame_insert(frp->fr_parent->fr_child, frp);
}
// exchange status height, hsep height and vsep width of old and new last window
// exchange status height, winbar height, hsep height and vsep width of old and new last window
n = wp2->w_status_height;
wp2->w_status_height = wp1->w_status_height;
wp1->w_status_height = n;
@ -1988,7 +1977,8 @@ void win_move_after(win_T *win1, win_T *win2)
return;
}
// may need move the status line, horizontal or vertical separator of the last window
// may need move the status line, window bar, horizontal or vertical separator of the last
// window
if (win1 == lastwin) {
height = win1->w_prev->w_status_height;
win1->w_prev->w_status_height = win1->w_status_height;
@ -2237,7 +2227,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else {
extra_sep = 0;
}
totwincount = (n + extra_sep) / (p_wmh + STATUS_HEIGHT);
totwincount = (n + extra_sep) / (p_wmh + STATUS_HEIGHT + global_winbar_height());
has_next_curwin = frame_has_win(topfr, next_curwin);
/*
@ -2272,7 +2262,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else {
// These windows don't use up room.
totwincount -= (n + (fr->fr_next == NULL
? extra_sep : 0)) / (p_wmh + STATUS_HEIGHT);
? extra_sep : 0)) / (p_wmh + STATUS_HEIGHT + global_winbar_height());
}
room -= new_size - n;
if (room < 0) {
@ -2318,7 +2308,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
// Compute the maximum number of windows vert. in "fr".
n = frame_minheight(fr, NOWIN);
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
/ (p_wmh + STATUS_HEIGHT);
/ (p_wmh + STATUS_HEIGHT + global_winbar_height());
m = frame_minheight(fr, next_curwin);
if (has_next_curwin) {
hnc = frame_has_win(fr, next_curwin);
@ -3732,13 +3722,9 @@ static void frame_fix_height(win_T *wp)
wp->w_frame->fr_height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
}
/*
* Compute the minimal height for frame "topfrp".
* Uses the 'winminheight' option.
* When "next_curwin" isn't NULL, use p_wh for this window.
* When "next_curwin" is NOWIN, don't use at least one line for the current
* window.
*/
/// Compute the minimal height for frame "topfrp". Uses the 'winminheight' option.
/// When "next_curwin" isn't NULL, use p_wh for this window.
/// When "next_curwin" is NOWIN, don't use at least one line for the current window.
static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
{
frame_T *frp;
@ -3746,12 +3732,14 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
int n;
if (topfrp->fr_win != NULL) {
// Combined height of window bar and separator column or status line.
int extra_height = topfrp->fr_win->w_winbar_height + topfrp->fr_win->w_hsep_height
+ topfrp->fr_win->w_status_height;
if (topfrp->fr_win == next_curwin) {
m = p_wh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
m = p_wh + extra_height;
} else {
// window: minimal height of the window plus separator column or status line
// depending on whether global statusline is enabled
m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
m = p_wmh + extra_height;
if (topfrp->fr_win == curwin && next_curwin == NULL) {
// Current window is minimal one line high.
if (p_wmh == 0) {
@ -3976,7 +3964,7 @@ static void new_frame(win_T *wp)
void win_init_size(void)
{
firstwin->w_height = ROWS_AVAIL;
firstwin->w_height_inner = firstwin->w_height;
firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height;
firstwin->w_height_outer = firstwin->w_height;
topframe->fr_height = ROWS_AVAIL;
firstwin->w_width = Columns;
@ -4087,6 +4075,7 @@ int win_new_tabpage(int after, char_u *filename)
newtp->tp_topframe = topframe;
last_status(false);
set_winbar();
redraw_all_later(NOT_VALID);
@ -5460,16 +5449,9 @@ void win_setheight(int height)
*/
void win_setheight_win(int height, win_T *win)
{
if (win == curwin) {
// Always keep current window at least one line high, even when
// 'winminheight' is zero.
if (height < p_wmh) {
height = p_wmh;
}
if (height == 0) {
height = 1;
}
}
// Always keep current window at least one line high, even when 'winminheight' is zero.
// Keep window at least two lines high if 'winbar' is enabled.
height = MAX(height, (win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height);
if (win->w_floating) {
win->w_float_config.height = height;
@ -6262,7 +6244,7 @@ void win_set_inner_size(win_T *wp)
int prev_height = wp->w_height_inner;
int height = wp->w_height_request;
if (height == 0) {
height = wp->w_height;
height = wp->w_height - wp->w_winbar_height;
}
if (height != prev_height) {
@ -6279,8 +6261,9 @@ void win_set_inner_size(win_T *wp)
set_fraction(wp);
}
}
wp->w_height_inner = height;
wp->w_skipcol = 0;
wp->w_height_inner = height;
wp->w_winrow_off = wp->w_border_adj[0] + wp->w_winbar_height;
// There is no point in adjusting the scroll position when exiting. Some
// values might be invalid.
@ -6306,10 +6289,18 @@ void win_set_inner_size(win_T *wp)
terminal_check_size(wp->w_buffer->terminal);
}
wp->w_height_outer = (wp->w_height_inner
+ wp->w_border_adj[0] + wp->w_border_adj[2]);
wp->w_width_outer = (wp->w_width_inner
+ wp->w_border_adj[1] + wp->w_border_adj[3]);
wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp));
wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp));
}
static int win_extra_height(win_T *wp)
{
return wp->w_border_adj[0] + wp->w_border_adj[2];
}
static int win_extra_width(win_T *wp)
{
return wp->w_border_adj[1] + wp->w_border_adj[3];
}
/// Set the width of a window.
@ -6662,6 +6653,19 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
}
}
// Add or remove window bars from windows depending on the value of 'winbar'.
void set_winbar(void)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
int winbar_height = (*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0;
if (wp->w_winbar_height != winbar_height) {
wp->w_winbar_height = winbar_height;
win_set_inner_size(wp);
wp->w_redr_winbar = winbar_height;
}
}
}
/// Return the number of lines used by the tab page line.
int tabline_height(void)
{
@ -6678,6 +6682,12 @@ int tabline_height(void)
return 1;
}
/// Return the number of lines used by default by the window bar.
int global_winbar_height(void)
{
return *p_wbr != NUL ? 1 : 0;
}
/// Return the number of lines used by the global statusline
int global_stl_height(void)
{

View File

@ -3102,6 +3102,19 @@ describe('API', function()
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
{ use_tabline = true, highlights = true }))
end)
it('works with winbar', function()
eq({
str = 'TextWithNoHighlightTextWithWarningHighlight',
width = 43,
highlights = {
{ start = 0, group = 'WinBar' },
{ start = 19, group = 'WarningMsg' }
}
},
meths.eval_statusline(
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
{ use_winbar = true, highlights = true }))
end)
end)
end)
describe('nvim_parse_cmd', function()

View File

@ -212,10 +212,10 @@ describe('ui/cursor', function()
if m.blinkwait then m.blinkwait = 700 end
end
if m.hl_id then
m.hl_id = 62
m.hl_id = 64
m.attr = {background = Screen.colors.DarkGray}
end
if m.id_lm then m.id_lm = 63 end
if m.id_lm then m.id_lm = 65 end
end
-- Assert the new expectation.

View File

@ -0,0 +1,180 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
describe('winbar', function()
local screen
before_each(function()
clear()
screen = Screen.new(60, 13)
screen:attach()
screen:set_default_attr_ids({
[1] = {bold = true},
[2] = {reverse = true},
[3] = {bold = true, foreground = Screen.colors.Blue},
[4] = {bold = true, reverse = true},
[5] = {bold = true, foreground = Screen.colors.Red},
[6] = {foreground = Screen.colors.Blue},
})
command('set winbar=Set\\ Up\\ The\\ Bars')
end)
it('works', function()
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
|
]])
end)
it('works with custom \'fillchars\' value', function()
command('set fillchars=wbr:+')
screen:expect([[
{1:Set Up The Bars+++++++++++++++++++++++++++++++++++++++++++++}|
^ |
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
|
]])
end)
it('works with custom highlight', function()
command('hi WinBar guifg=red')
screen:expect([[
{5:Set Up The Bars }|
^ |
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
|
]])
end)
it('works with splits', function()
command('hi WinBar guifg=red')
command('hi WinBarNC guifg=blue')
command('belowright vsplit | split | split')
screen:expect([[
{6:Set Up The Bars }{5:Set Up The Bars }|
^ |
{3:~ }{3:~ }|
{3:~ }{4:[No Name] }|
{3:~ }{6:Set Up The Bars }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }{2:[No Name] }|
{3:~ }{6:Set Up The Bars }|
{3:~ } |
{3:~ }{3:~ }|
{2:[No Name] [No Name] }|
|
]])
end)
it('works when switching value of \'winbar\'', function()
command('belowright vsplit | split | split | set winbar=')
screen:expect([[
^ |
{3:~ }{3:~ }|
{3:~ }{3:~ }|
{3:~ }{4:[No Name] }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }{3:~ }|
{3:~ }{2:[No Name] }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }{3:~ }|
{2:[No Name] [No Name] }|
|
]])
command('set winbar=All\\ Your\\ Bar\\ Are\\ Belong\\ To\\ Us')
screen:expect([[
{1:All Your Bar Are Belong To Us}{1:All Your Bar Are Belong To Us }|
^ |
{3:~ }{3:~ }|
{3:~ }{4:[No Name] }|
{3:~ }{1:All Your Bar Are Belong To Us }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }{2:[No Name] }|
{3:~ }{1:All Your Bar Are Belong To Us }|
{3:~ } |
{3:~ }{3:~ }|
{2:[No Name] [No Name] }|
|
]])
command('set winbar=Changed\\ winbar')
screen:expect([[
{1:Changed winbar }{1:Changed winbar }|
^ |
{3:~ }{3:~ }|
{3:~ }{4:[No Name] }|
{3:~ }{1:Changed winbar }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }{2:[No Name] }|
{3:~ }{1:Changed winbar }|
{3:~ } |
{3:~ }{3:~ }|
{2:[No Name] [No Name] }|
|
]])
end)
it('works with laststatus=3', function()
command('set laststatus=3')
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{3:~ }|
{4:[No Name] }|
|
]])
command('belowright vsplit | split | split')
screen:expect([[
{1:Set Up The Bars }{1:Set Up The Bars }|
^ |
{3:~ }{3:~ }|
{3:~ }|
{3:~ }{1:Set Up The Bars }|
{3:~ } |
{3:~ }{3:~ }|
{3:~ }|
{3:~ }{1:Set Up The Bars }|
{3:~ } |
{3:~ }{3:~ }|
{4:[No Name] }|
|
]])
end)
end)