feat(ui): add 'winbar'

Adds support for a bar at the top of each window, enabled through the
`'winbar'` option.

Co-authored-by: Björn Linse <bjorn.linse@gmail.com>
This commit is contained in:
Famiu Haque 2022-05-13 20:47:11 +06:00
parent b9b5577d6d
commit e1bdb2a258
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. Treated as single-width even if it isn't.
• highlights: (boolean) Return highlight • highlights: (boolean) Return highlight
information. information.
• use_winbar: (boolean) Evaluate winbar instead of
statusline.
• use_tabline: (boolean) Evaluate tabline instead • use_tabline: (boolean) Evaluate tabline instead
of statusline. When |TRUE|, {winid} is ignored. of statusline. When |TRUE|, {winid} is ignored.
Mutually exclusive with {use_winbar}.
Return: ~ Return: ~
Dictionary containing statusline information, with these 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 |:recover| :rec[over] recover a file from a swap file
|:redo| :red[o] redo one undone change |:redo| :red[o] redo one undone change
|:redir| :redi[r] redirect messages to a file or register |:redir| :redi[r] redirect messages to a file or register
|:redraw| :redr[aw] force a redraw of the display |:redraw| :redr[aw] force a redraw of the display
|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) |:redrawstatus| :redraws[tatus] force a redraw of the status line(s) and
window bar(s)
|:redrawtabline| :redrawt[abline] force a redraw of the tabline |:redrawtabline| :redrawt[abline] force a redraw of the tabline
|:registers| :reg[isters] display the contents of registers |:registers| :reg[isters] display the contents of registers
|:resize| :res[ize] change current window height |: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 ~ item default Used for ~
stl:c ' ' or '^' statusline of the current window stl:c ' ' or '^' statusline of the current window
stlnc:c ' ' or '=' statusline of the non-current windows stlnc:c ' ' or '=' statusline of the non-current windows
wbr:c ' ' window bar
horiz:c '─' or '-' horizontal separators |:split| horiz:c '─' or '-' horizontal separators |:split|
horizup:c '┴' or '-' upwards facing horizontal separator horizup:c '┴' or '-' upwards facing horizontal separator
horizdown:c '┬' or '-' downwards 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 ~ item highlight group ~
stl:c StatusLine |hl-StatusLine| stl:c StatusLine |hl-StatusLine|
stlnc:c StatusLineNC |hl-StatusLineNC| stlnc:c StatusLineNC |hl-StatusLineNC|
wbr:c WinBar |hl-WinBar| or |hl-WinBarNC|
horiz:c WinSeparator |hl-WinSeparator| horiz:c WinSeparator |hl-WinSeparator|
horizup:c WinSeparator |hl-WinSeparator| horizup:c WinSeparator |hl-WinSeparator|
horizdown: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. key is never used for the menu.
This option is not used for <F10>; on Win32. 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'*
'winblend' 'winbl' number (default 0) 'winblend' 'winbl' number (default 0)
local to window local to window

View File

@ -5244,6 +5244,10 @@ Whitespace "nbsp", "space", "tab", "multispace", "lead" and "trail"
in 'listchars'. in 'listchars'.
*hl-WildMenu* *hl-WildMenu*
WildMenu Current match in 'wildmenu' completion. 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* *hl-User1* *hl-User1..9* *hl-User9*
The 'statusline' syntax allows the use of 9 different highlights in the 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). function (or a mapping if 'lazyredraw' set).
*:redraws* *:redrawstatus* *:redraws* *:redrawstatus*
:redraws[tatus][!] Redraws the status line of the current window, or all :redraws[tatus][!] Redraws the status line and window bar of the current
status lines if "!" is included. window, or all status lines and window bars if "!" is
Useful if 'statusline' includes an item that doesn't included. Useful if 'statusline' or 'winbar' includes
cause automatic updating. an item that doesn't cause automatic updating.
*:redrawt* *:redrawtabline* *:redrawt* *:redrawtabline*
:redrawt[abline] Redraw the tabline. Useful to update the tabline when :redrawt[abline] Redraw the tabline. Useful to update the tabline when

View File

@ -80,6 +80,7 @@ return {
"maxwidth"; "maxwidth";
"fillchar"; "fillchar";
"highlights"; "highlights";
"use_winbar";
"use_tabline"; "use_tabline";
}; };
option = { 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 /// 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) { if (wp == NULL) {
return "TabLineFill"; return "TabLineFill";
} else if (wp == curwin) { } else if (use_winbar) {
return "StatusLine"; return (wp == curwin) ? "WinBar" : "WinBarNC";
} else { } 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 /// - fillchar: (string) Character to fill blank spaces in the statusline (see
/// 'fillchars'). Treated as single-width even if it isn't. /// 'fillchars'). Treated as single-width even if it isn't.
/// - highlights: (boolean) Return highlight information. /// - highlights: (boolean) Return highlight information.
/// - use_winbar: (boolean) Evaluate winbar instead of statusline.
/// - use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid} /// - 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. /// @param[out] err Error details, if any.
/// @return Dictionary containing statusline information, with these keys: /// @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 maxwidth;
int fillchar = 0; int fillchar = 0;
Window window = 0; Window window = 0;
bool use_winbar = false;
bool use_tabline = false; bool use_tabline = false;
bool highlights = 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; window = (Window)opts->winid.data.integer;
} }
if (HAS_KEY(opts->fillchar)) { if (HAS_KEY(opts->fillchar)) {
if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0 if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0
|| ((size_t)utf_ptr2len(opts->fillchar.data.string.data) || ((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); fillchar = utf_ptr2char(opts->fillchar.data.string.data);
} }
if (HAS_KEY(opts->highlights)) { if (HAS_KEY(opts->highlights)) {
highlights = api_object_to_bool(opts->highlights, "highlights", false, err); 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; 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)) { if (HAS_KEY(opts->use_tabline)) {
use_tabline = api_object_to_bool(opts->use_tabline, "use_tabline", false, err); 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; 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; win_T *wp, *ewp;
@ -2348,7 +2358,6 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
fillchar = ' '; fillchar = ' ';
} else { } else {
wp = find_window_by_handle(window, err); wp = find_window_by_handle(window, err);
if (wp == NULL) { if (wp == NULL) {
api_set_error(err, kErrorTypeException, "unknown winid %d", window); api_set_error(err, kErrorTypeException, "unknown winid %d", window);
return result; return result;
@ -2356,8 +2365,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
ewp = wp; ewp = wp;
if (fillchar == 0) { if (fillchar == 0) {
int attr; if (use_winbar) {
fillchar = fillchar_status(&attr, wp); 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; maxwidth = (int)opts->maxwidth.data.integer;
} else { } 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]; 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 // add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || ((char *)hltab->start - buf) != 0) { if (hltab->start == NULL || ((char *)hltab->start - buf) != 0) {
Dictionary hl_info = ARRAY_DICT_INIT; 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, "start", INTEGER_OBJ(0));
PUT(hl_info, "group", CSTR_TO_OBJ(grpname)); 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)); PUT(hl_info, "start", INTEGER_OBJ((char *)sp->start - buf));
if (sp->userhl == 0) { if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp); grpname = get_default_stl_hl(wp, use_winbar);
} else if (sp->userhl < 0) { } else if (sp->userhl < 0) {
grpname = (char *)syn_id2name(-sp->userhl); grpname = (char *)syn_id2name(-sp->userhl);
} else { } else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl); snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
grpname = user_group; grpname = user_group;
} }
PUT(hl_info, "group", CSTR_TO_OBJ(grpname)); PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
ADD(hl_values, DICTIONARY_OBJ(hl_info)); ADD(hl_values, DICTIONARY_OBJ(hl_info));
} }
PUT(result, "highlights", ARRAY_OBJ(hl_values)); PUT(result, "highlights", ARRAY_OBJ(hl_values));
} }
PUT(result, "str", CSTR_TO_OBJ((char *)buf)); PUT(result, "str", CSTR_TO_OBJ((char *)buf));
return result; return result;

View File

@ -233,6 +233,8 @@ typedef struct {
#define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak' #define w_p_sbr w_onebuf_opt.wo_sbr // 'showbreak'
char_u *wo_stl; char_u *wo_stl;
#define w_p_stl w_onebuf_opt.wo_stl // 'statusline' #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; int wo_scb;
#define w_p_scb w_onebuf_opt.wo_scb // 'scrollbind' #define w_p_scb w_onebuf_opt.wo_scb // 'scrollbind'
int wo_diff_saved; // options were saved for starting diff mode int wo_diff_saved; // options were saved for starting diff mode
@ -1235,6 +1237,7 @@ struct window_S {
struct { struct {
int stl; int stl;
int stlnc; int stlnc;
int wbr;
int horiz; int horiz;
int horizup; int horizup;
int horizdown; int horizdown;
@ -1282,14 +1285,20 @@ struct window_S {
// //
int w_winrow; // first row of window in screen int w_winrow; // first row of window in screen
int w_height; // number of rows in window, excluding 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_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_wincol; // Leftmost column of window in screen.
int w_width; // Width of window, excluding separation. int w_width; // Width of window, excluding separation.
int w_hsep_height; // Number of horizontal separator rows (0 or 1) int w_hsep_height; // Number of horizontal separator rows (0 or 1)
int w_vsep_width; // Number of vertical separator columns (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 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 // inner size of window, which can be overridden by external UI
int w_height_inner; int w_height_inner;
int w_width_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_top; // when != 0: first line needing redraw
linenr_T w_redraw_bot; // when != 0: last 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_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 bool w_redr_border; // if true border must be redrawn
// remember what is shown in the ruler for this window (if 'ruler' set) // 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. // A few options have local flags for P_INSECURE.
uint32_t w_p_stl_flags; // flags for 'statusline' 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_fde_flags; // flags for 'foldexpr'
uint32_t w_p_fdt_flags; // flags for 'foldtext' uint32_t w_p_fdt_flags; // flags for 'foldtext'
int *w_p_cc_cols; // array of columns to highlight or NULL 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("winrow"), wp->w_winrow + 1);
tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline); 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("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("width"), wp->w_width);
tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); 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); 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. // necessary for a top border since `row` starts at -1 in that case.
if (row < height + wp->w_border_adj[2]) { if (row < height + wp->w_border_adj[2]) {
winid = wp->handle; winid = wp->handle;
winrow = row + 1 + wp->w_border_adj[0]; // Adjust by 1 for top border winrow = row + 1 + wp->w_winrow_off; // Adjust by 1 for top border
wincol = col + 1 + wp->w_border_adj[3]; // Adjust by 1 for left 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) { if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) {
(void)mouse_comp_pos(wp, &row, &col, &lnum); (void)mouse_comp_pos(wp, &row, &col, &lnum);
col = vcol2col(wp, lnum, col); col = vcol2col(wp, lnum, col);

View File

@ -8831,7 +8831,7 @@ static void ex_redraw(exarg_T *eap)
ui_flush(); 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) static void ex_redrawstatus(exarg_T *eap)
{ {
if (State & MODE_CMDPREVIEW) { if (State & MODE_CMDPREVIEW) {
@ -8847,8 +8847,7 @@ static void ex_redrawstatus(exarg_T *eap)
} else { } else {
status_redraw_curbuf(); status_redraw_curbuf();
} }
update_screen(VIsual_active ? INVERTED : update_screen(VIsual_active ? INVERTED : 0);
0);
RedrawingDisabled = r; RedrawingDisabled = r;
p_lz = p; p_lz = p;
ui_flush(); ui_flush();

View File

@ -111,7 +111,9 @@ typedef enum {
HLF_NFLOAT, // Floating window HLF_NFLOAT, // Floating window
HLF_MSG, // Message area HLF_MSG, // Message area
HLF_BORDER, // Floating window border 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; } hlf_T;
EXTERN const char *hlf_names[] INIT(= { EXTERN const char *hlf_names[] INIT(= {
@ -172,6 +174,8 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_NFLOAT] = "NormalFloat", [HLF_NFLOAT] = "NormalFloat",
[HLF_MSG] = "MsgArea", [HLF_MSG] = "MsgArea",
[HLF_BORDER] = "FloatBorder", [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", "TabLineFill cterm=reverse gui=reverse",
"TabLineSel cterm=bold gui=bold", "TabLineSel cterm=bold gui=bold",
"TermCursor cterm=reverse gui=reverse", "TermCursor cterm=reverse gui=reverse",
"WinBar cterm=bold gui=bold",
"WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black", "WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
"default link VertSplit Normal", "default link VertSplit Normal",
"default link WinSeparator VertSplit", "default link WinSeparator VertSplit",
"default link WinBarNC WinBar",
"default link EndOfBuffer NonText", "default link EndOfBuffer NonText",
"default link LineNrAbove LineNr", "default link LineNrAbove LineNr",
"default link LineNrBelow 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. /// 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 /// 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 /// This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
/// IN_SEP_LINE depending on where the cursor was clicked. /// IN_SEP_LINE depending on where the cursor was clicked.
/// ///
/// If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless /// 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 /// If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
/// the last call. /// 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_status_line = 0; // #lines below bottom of window
static int on_sep_line = 0; // on separator right 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_row = -1;
static int prev_col = -1; static int prev_col = -1;
static win_T *dragwin = NULL; // window being dragged static win_T *dragwin = NULL; // window being dragged
@ -126,6 +127,9 @@ retnomove:
if (on_sep_line) { if (on_sep_line) {
return IN_SEP_LINE; return IN_SEP_LINE;
} }
if (on_winbar) {
return IN_OTHER_WIN | MOUSE_WINBAR;
}
if (flags & MOUSE_MAY_STOP_VIS) { if (flags & MOUSE_MAY_STOP_VIS) {
end_visual_mode(); end_visual_mode();
redraw_curbuf_later(INVERTED); // delete the inversion redraw_curbuf_later(INVERTED); // delete the inversion
@ -155,9 +159,11 @@ retnomove:
fdc = win_fdccol_count(wp); fdc = win_fdccol_count(wp);
dragwin = NULL; dragwin = NULL;
if (row == -1) { if (row == -1 + wp->w_winbar_height) {
return IN_OTHER_WIN; 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()! // winpos and height may change in win_enter()!
if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) { if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) {
@ -253,6 +259,9 @@ retnomove:
did_drag |= count; did_drag |= count;
} }
return IN_SEP_LINE; // Cursor didn't move 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 { } else {
// keep_window_focus must be true // keep_window_focus must be true
// before moving the cursor for a left click, stop Visual mode // 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. // exist.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == fp->fr_win) { if (wp == fp->fr_win) {
*rowp -= wp->w_winrow_off - wp->w_winbar_height;
return wp; 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; col -= wp->w_leftcol;
if (col >= 0 && col < wp->w_width) { 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 { } else {
scol = ccol = ecol = 0; scol = ccol = ecol = 0;
// character is left or right of the window // 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; *scolp = scol + coloff;
*ccolp = ccol + coloff; *ccolp = ccol + coloff;
*ecolp = ecol + coloff; *ecolp = ecol + coloff;

View File

@ -1280,7 +1280,8 @@ static void normal_redraw(NormalState *s)
validate_cursor(); validate_cursor();
if (VIsual_active) { if (VIsual_active) {
update_curbuf(INVERTED); // update inverted part redraw_curbuf_later(INVERTED); // update inverted part
update_screen(INVERTED);
} else if (must_redraw) { } else if (must_redraw) {
update_screen(0); update_screen(0);
} else if (redraw_cmdline || clear_cmdline) { } 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), oap == NULL ? NULL : &(oap->inclusive),
which_button); which_button);
// A click in the window bar has no side effects.
if (jump_flags & MOUSE_WINBAR) {
return false;
}
moved = (jump_flags & CURSOR_MOVED); moved = (jump_flags & CURSOR_MOVED);
in_status_line = (jump_flags & IN_STATUS_LINE); in_status_line = (jump_flags & IN_STATUS_LINE);
in_sep_line = (jump_flags & IN_SEP_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) { switch ((int)options[opt_idx].indir) {
case PV_STL: case PV_STL:
return &wp->w_p_stl_flags; return &wp->w_p_stl_flags;
case PV_WBR:
return &wp->w_p_wbr_flags;
case PV_FDE: case PV_FDE:
return &wp->w_p_fde_flags; return &wp->w_p_fde_flags;
case PV_FDT: case PV_FDT:
@ -2930,8 +2932,8 @@ ambw_end:
curbuf->b_help = (curbuf->b_p_bt[0] == 'h'); curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
redraw_titles(); redraw_titles();
} }
} else if (gvarp == &p_stl || varp == &p_tal || varp == &p_ruf) { } else if (gvarp == &p_stl || gvarp == (char_u **)&p_wbr || varp == &p_tal || varp == &p_ruf) {
// 'statusline', 'tabline' or 'rulerformat' // 'statusline', 'winbar', 'tabline' or 'rulerformat'
int wid; int wid;
if (varp == &p_ruf) { // reset ru_wid first if (varp == &p_ruf) { // reset ru_wid first
@ -2950,12 +2952,16 @@ ambw_end:
errmsg = check_stl_option(p_ruf); errmsg = check_stl_option(p_ruf);
} }
} else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') { } 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); errmsg = check_stl_option(s);
} }
if (varp == &p_ruf && errmsg == NULL) { if (varp == &p_ruf && errmsg == NULL) {
comp_col(); comp_col();
} }
// add / remove window bars for 'winbar'
if (gvarp == (char_u **)&p_wbr) {
set_winbar();
}
} else if (gvarp == &p_cpt) { } else if (gvarp == &p_cpt) {
// check if it is a valid value for 'complete' -- Acevedo // check if it is a valid value for 'complete' -- Acevedo
for (s = *varp; *s;) { 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[] = { struct chars_tab fcs_tab[] = {
{ &wp->w_p_fcs_chars.stl, "stl", ' ' }, { &wp->w_p_fcs_chars.stl, "stl", ' ' },
{ &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' }, { &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.horiz, "horiz", 9472 }, // ─
{ &wp->w_p_fcs_chars.horizup, "horizup", 9524 }, // ┴ { &wp->w_p_fcs_chars.horizup, "horizup", 9524 }, // ┴
{ &wp->w_p_fcs_chars.horizdown, "horizdown", 9516 }, // ┬ { &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') { if (*p_ambw == 'd') {
// XXX: If ambiwidth=double then some characters take 2 columns, // XXX: If ambiwidth=double then some characters take 2 columns,
// which is forbidden (TUI limitation?). Set old defaults. // which is forbidden (TUI limitation?). Set old defaults.
fcs_tab[2].def = '-';
fcs_tab[3].def = '-'; fcs_tab[3].def = '-';
fcs_tab[4].def = '-'; fcs_tab[4].def = '-';
fcs_tab[5].def = '|'; fcs_tab[5].def = '-';
fcs_tab[6].def = '|'; fcs_tab[6].def = '|';
fcs_tab[7].def = '|'; fcs_tab[7].def = '|';
fcs_tab[8].def = '+'; fcs_tab[8].def = '|';
fcs_tab[9].def = '-'; fcs_tab[9].def = '+';
fcs_tab[12].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 doclear = (flags & P_RCLR) == P_RCLR;
bool all = ((flags & P_RALL) == P_RALL || doclear); 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(); status_redraw_all();
} }
@ -5814,6 +5821,9 @@ void unset_global_local_option(char *name, void *from)
case PV_STL: case PV_STL:
clear_string_option(&((win_T *)from)->w_p_stl); clear_string_option(&((win_T *)from)->w_p_stl);
break; break;
case PV_WBR:
clear_string_option((char_u **)&((win_T *)from)->w_p_wbr);
break;
case PV_UL: case PV_UL:
buf->b_p_ul = NO_LOCAL_UNDOLEVEL; buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
break; break;
@ -5891,6 +5901,8 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
return (char_u *)&(curwin->w_p_sbr); return (char_u *)&(curwin->w_p_sbr);
case PV_STL: case PV_STL:
return (char_u *)&(curwin->w_p_stl); return (char_u *)&(curwin->w_p_stl);
case PV_WBR:
return (char_u *)&(curwin->w_p_wbr);
case PV_UL: case PV_UL:
return (char_u *)&(curbuf->b_p_ul); return (char_u *)&(curbuf->b_p_ul);
case PV_LW: case PV_LW:
@ -5984,6 +5996,9 @@ static char_u *get_varp(vimoption_T *p)
case PV_STL: case PV_STL:
return *curwin->w_p_stl != NUL return *curwin->w_p_stl != NUL
? (char_u *)&(curwin->w_p_stl) : p->var; ? (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: case PV_UL:
return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
? (char_u *)&(curbuf->b_p_ul) : p->var; ? (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_rlc = vim_strsave(from->wo_rlc);
to->wo_sbr = vim_strsave(from->wo_sbr); to->wo_sbr = vim_strsave(from->wo_sbr);
to->wo_stl = vim_strsave(from->wo_stl); to->wo_stl = vim_strsave(from->wo_stl);
to->wo_wbr = xstrdup(from->wo_wbr);
to->wo_wrap = from->wo_wrap; to->wo_wrap = from->wo_wrap;
to->wo_wrap_save = from->wo_wrap_save; to->wo_wrap_save = from->wo_wrap_save;
to->wo_lbr = from->wo_lbr; 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_fcs);
check_string_option(&wop->wo_lcs); check_string_option(&wop->wo_lcs);
check_string_option(&wop->wo_ve); check_string_option(&wop->wo_ve);
check_string_option((char_u **)&wop->wo_wbr);
} }
/// Free the allocated memory inside a winopt_T. /// 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_fcs);
clear_string_option(&wop->wo_lcs); clear_string_option(&wop->wo_lcs);
clear_string_option(&wop->wo_ve); clear_string_option(&wop->wo_ve);
clear_string_option((char_u **)&wop->wo_wbr);
} }
void didset_window_options(win_T *wp) void didset_window_options(win_T *wp)

View File

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

View File

@ -2831,6 +2831,16 @@ return {
varname='p_wak', varname='p_wak',
defaults={if_true="menu"} 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', full_name='winblend', abbreviation='winbl',
short_desc=N_("Controls transparency level for floating windows"), 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 /// called when the status bars for the buffer 'buf' need to be updated
void redraw_buf_status_later(buf_T *buf) void redraw_buf_status_later(buf_T *buf)
{ {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == buf if (wp->w_buffer != buf) {
&& (wp->w_status_height || (wp == curwin && global_stl_height()))) { continue;
}
bool redraw = false;
if (wp->w_status_height || (wp == curwin && global_stl_height())) {
wp->w_redr_status = true; wp->w_redr_status = true;
if (must_redraw < VALID) { redraw = true;
must_redraw = VALID; }
} 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) { if (wp->w_floating) {
continue; continue;
} }
if (wp->w_winrow + wp->w_winbar_height > valid) {
wp->w_redr_winbar = true;
}
if (W_ENDROW(wp) > valid) { if (W_ENDROW(wp) > valid) {
wp->w_redr_type = MAX(wp->w_redr_type, NOT_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; wp->w_redr_type = REDRAW_TOP;
} else { } else {
wp->w_redr_type = NOT_VALID; 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) { if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height <= msg_scrolled) {
wp->w_redr_status = true; wp->w_redr_status = true;
} }
@ -585,10 +591,13 @@ int update_screen(int type)
win_update(wp, &providers); 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) { if (wp->w_redr_status) {
win_redr_status(wp); win_redr_status(wp);
} }
if (wp->w_redr_winbar) {
win_redr_winbar(wp);
}
} }
end_search_hl(); end_search_hl();
@ -743,6 +752,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (type >= NOT_VALID) { if (type >= NOT_VALID) {
wp->w_redr_status = true; wp->w_redr_status = true;
wp->w_redr_winbar = true;
wp->w_lines_valid = 0; wp->w_lines_valid = 0;
} }
@ -4528,42 +4538,55 @@ void rl_mirror(char_u *str)
} }
} }
/* /// Mark all status lines and window bars for redraw; used after first :cd
* mark all status lines for redraw; used after first :cd
*/
void status_redraw_all(void) void status_redraw_all(void)
{ {
if (global_stl_height()) { bool is_stl_global = global_stl_height() != 0;
curwin->w_redr_status = true;
redraw_later(curwin, VALID); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
} else { bool redraw = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height) { if ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin)) {
wp->w_redr_status = true; wp->w_redr_status = true;
redraw_later(wp, VALID); 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) void status_redraw_curbuf(void)
{ {
status_redraw_buf(curbuf); 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) void status_redraw_buf(buf_T *buf)
{ {
if (global_stl_height() != 0 && curwin->w_buffer == buf) { bool is_stl_global = global_stl_height() != 0;
curwin->w_redr_status = true;
redraw_later(curwin, VALID); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
} else { if (wp->w_buffer != buf) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { continue;
if (wp->w_status_height != 0 && wp->w_buffer == buf) { }
wp->w_redr_status = true; bool redraw = false;
redraw_later(wp, VALID);
} 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) { if (wp->w_redr_status) {
win_redr_status(wp); win_redr_status(wp);
} }
if (wp->w_redr_winbar) {
win_redr_winbar(wp);
}
} }
if (redraw_tabline) { if (redraw_tabline) {
draw_tabline(); draw_tabline();
@ -5075,7 +5101,7 @@ static void redraw_custom_statusline(win_T *wp)
entered = true; entered = true;
did_emsg = false; did_emsg = false;
win_redr_custom(wp, false); win_redr_custom(wp, false, false);
if (did_emsg) { if (did_emsg) {
// When there is an error disable the statusline, otherwise the // When there is an error disable the statusline, otherwise the
// display is messed up with errors and a redraw triggers the problem // 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; 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). /// Only call if (wp->w_vsep_width != 0).
/// ///
/// @return true if the status line of window "wp" is connected to the status /// @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; return buf[0] != NUL;
} }
/* /// Redraw the status line, window bar or ruler of window "wp".
* Redraw the status line or ruler of window "wp". /// When "wp" is NULL redraw the tab pages line from 'tabline'.
* 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 void win_redr_custom(win_T *wp, bool draw_ruler)
{ {
static bool entered = false; static bool entered = false;
int attr; int attr;
@ -5269,6 +5328,14 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
attr = HL_ATTR(HLF_TPF); attr = HL_ATTR(HLF_TPF);
maxwidth = Columns; maxwidth = Columns;
use_sandbox = was_set_insecurely(wp, "tabline", 0); 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 { } else {
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp); row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
fillchar = fillchar_status(&attr, wp); fillchar = fillchar_status(&attr, wp);
@ -5553,14 +5620,17 @@ void win_grid_alloc(win_T *wp)
grid->Rows = rows; grid->Rows = rows;
grid->Columns = cols; 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) { if (want_allocation) {
grid->target = grid_allocated; grid->target = grid_allocated;
grid->row_offset = wp->w_border_adj[0]; grid->row_offset = wp->w_winrow_off;
grid->col_offset = wp->w_border_adj[3]; grid->col_offset = wp->w_wincol_off;
} else { } else {
grid->target = &default_grid; grid->target = &default_grid;
grid->row_offset = wp->w_winrow; grid->row_offset = wp->w_winrow + wp->w_winrow_off;
grid->col_offset = wp->w_wincol; grid->col_offset = wp->w_wincol + wp->w_wincol_off;
} }
// send grid resize event if: // 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 // Check for an error. If there is one we would loop in redrawing the
// screen. Avoid that by making 'tabline' empty. // screen. Avoid that by making 'tabline' empty.
did_emsg = false; did_emsg = false;
win_redr_custom(NULL, false); win_redr_custom(NULL, false, false);
if (did_emsg) { if (did_emsg) {
set_string_option_direct("tabline", -1, set_string_option_direct("tabline", -1,
(char_u *)"", OPT_FREE, SID_ERROR); (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; int save_called_emsg = called_emsg;
called_emsg = false; called_emsg = false;
win_redr_custom(wp, true); win_redr_custom(wp, false, true);
if (called_emsg) { if (called_emsg) {
set_string_option_direct("rulerformat", -1, (char_u *)"", set_string_option_direct("rulerformat", -1, (char_u *)"",
OPT_FREE, SID_ERROR); OPT_FREE, SID_ERROR);

View File

@ -102,10 +102,11 @@ func Test_screenpos()
bwipe! bwipe!
call assert_equal({'col': 1, 'row': 1, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1)) call assert_equal({'col': 1, 'row': 1, 'endcol': 1, 'curscol': 1}, screenpos(win_getid(), 1, 1))
" Needs WinBar
" nmenu WinBar.TEST : " 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 " nunmenu WinBar.TEST
setlocal winbar&
endfunc endfunc
func Test_screenpos_number() 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_floating = 1;
wp->w_status_height = 0; wp->w_status_height = 0;
wp->w_winbar_height = 0;
wp->w_hsep_height = 0; wp->w_hsep_height = 0;
wp->w_vsep_width = 0; wp->w_vsep_width = 0;
@ -780,10 +781,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
} }
if (!ui_has(kUIMultigrid)) { if (!ui_has(kUIMultigrid)) {
wp->w_height = MIN(wp->w_height, wp->w_height = MIN(wp->w_height, Rows - 1 - win_extra_height(wp));
Rows - 1 - (wp->w_border_adj[0] + wp->w_border_adj[2])); wp->w_width = MIN(wp->w_width, Columns - win_extra_width(wp));
wp->w_width = MIN(wp->w_width,
Columns - (wp->w_border_adj[1] + wp->w_border_adj[3]));
} }
win_set_inner_size(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 { } else {
layout = FR_COL; layout = FR_COL;
/* // Check if we are able to split the current window and compute its height.
* Check if we are able to split the current window and compute its // Current window requires at least 1 space plus space for the window bar.
* height. wmh1 = MAX(p_wmh, 1) + oldwin->w_winbar_height;
*/
// Current window requires at least 1 space.
wmh1 = p_wmh == 0 ? 1 : p_wmh;
needed = wmh1 + STATUS_HEIGHT; needed = wmh1 + STATUS_HEIGHT;
if (flags & WSP_ROOM) { if (flags & WSP_ROOM) {
needed += p_wh - wmh1; needed += p_wh - wmh1 + oldwin->w_winbar_height;
} }
if (flags & (WSP_BOT | WSP_TOP)) { if (flags & (WSP_BOT | WSP_TOP)) {
minheight = frame_minheight(topframe, NOWIN) + need_status; 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) { } else if (p_ea) {
minheight = frame_minheight(oldwin->w_frame, NOWIN) + need_status; minheight = frame_minheight(oldwin->w_frame, NOWIN) + need_status;
prevfrp = oldwin->w_frame; prevfrp = oldwin->w_frame;
for (frp = oldwin->w_frame->fr_parent; frp != NULL; for (frp = oldwin->w_frame->fr_parent; frp != NULL; frp = frp->fr_parent) {
frp = frp->fr_parent) {
if (frp->fr_layout == FR_COL) { if (frp->fr_layout == FR_COL) {
FOR_ALL_FRAMES(frp2, frp->fr_child) { FOR_ALL_FRAMES(frp2, frp->fr_child) {
if (frp2 != prevfrp) { if (frp2 != prevfrp) {
@ -1339,6 +1334,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
set_fraction(oldwin); set_fraction(oldwin);
} }
wp->w_fraction = oldwin->w_fraction; wp->w_fraction = oldwin->w_fraction;
wp->w_winbar_height = oldwin->w_winbar_height;
if (flags & WSP_VERT) { if (flags & WSP_VERT) {
wp->w_p_scr = curwin->w_p_scr; 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)) { if (flags & (WSP_TOP | WSP_BOT)) {
int new_fr_height = curfrp->fr_height - new_size; 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; new_fr_height -= STATUS_HEIGHT;
} else if (global_stl_height() > 0) { } else if (is_stl_global) {
if (flags & WSP_BOT) { if (flags & WSP_BOT) {
frame_add_hsep(curfrp); frame_add_hsep(curfrp);
} else { } 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_add_statusline(curfrp);
} }
frame_fix_height(wp); 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. * equalize the window sizes.
*/ */
if (do_equal || dir != 0) { if (do_equal || dir != 0) {
win_equal(wp, true, win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
: dir == 'h' ? 'b' :
'v');
} }
// Don't change the window height/width to 'winheight' / 'winwidth' if a // 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. /// 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). /// (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. /// @return actual number of windows on the screen.
int make_windows(int count, bool vertical) int make_windows(int count, bool vertical)
@ -1687,15 +1680,15 @@ int make_windows(int count, bool vertical)
int todo; int todo;
if (vertical) { if (vertical) {
// Each window needs at least 'winminwidth' lines and a separator // Each window needs at least 'winminwidth' lines and a separator column.
// column.
maxcount = (curwin->w_width + curwin->w_vsep_width maxcount = (curwin->w_width + curwin->w_vsep_width
- (p_wiw - p_wmw)) / (p_wmw + 1); - (p_wiw - p_wmw)) / (p_wmw + 1);
} else { } else {
// Each window needs at least 'winminheight' lines // Each window needs at least 'winminheight' lines.
// If statusline isn't global, each window also needs a statusline // 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 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) { if (maxcount < 2) {
@ -1705,17 +1698,13 @@ int make_windows(int count, bool vertical)
count = maxcount; 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) { if (count > 1) {
last_status(true); last_status(true);
} }
/* // Don't execute autocommands while creating the windows. Must do that
* Don't execute autocommands while creating the windows. Must do that // when putting the buffers in the windows.
* when putting the buffers in the windows.
*/
block_autocmds(); block_autocmds();
// todo is number of windows left to create // todo is number of windows left to create
@ -1790,7 +1779,7 @@ static void win_exchange(long Prenum)
* if wp != wp2 * if wp != wp2
* 3. remove wp from the list * 3. remove wp from the list
* 4. insert wp after wp2 * 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; wp2 = curwin->w_prev;
frp2 = curwin->w_frame->fr_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); 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; n = wp2->w_status_height;
wp2->w_status_height = wp1->w_status_height; wp2->w_status_height = wp1->w_status_height;
wp1->w_status_height = n; wp1->w_status_height = n;
@ -1988,7 +1977,8 @@ void win_move_after(win_T *win1, win_T *win2)
return; 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) { if (win1 == lastwin) {
height = win1->w_prev->w_status_height; height = win1->w_prev->w_status_height;
win1->w_prev->w_status_height = win1->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 { } else {
extra_sep = 0; 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); 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 { } else {
// These windows don't use up room. // These windows don't use up room.
totwincount -= (n + (fr->fr_next == NULL 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; room -= new_size - n;
if (room < 0) { 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". // Compute the maximum number of windows vert. in "fr".
n = frame_minheight(fr, NOWIN); n = frame_minheight(fr, NOWIN);
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0)) 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); m = frame_minheight(fr, next_curwin);
if (has_next_curwin) { if (has_next_curwin) {
hnc = frame_has_win(fr, 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; 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.
* Compute the minimal height for frame "topfrp". /// When "next_curwin" isn't NULL, use p_wh for this window.
* Uses the 'winminheight' option. /// When "next_curwin" is NOWIN, don't use at least one line for the current window.
* 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) static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
{ {
frame_T *frp; frame_T *frp;
@ -3746,12 +3732,14 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
int n; int n;
if (topfrp->fr_win != NULL) { 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) { 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 { } else {
// window: minimal height of the window plus separator column or status line m = p_wmh + extra_height;
// depending on whether global statusline is enabled
m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
if (topfrp->fr_win == curwin && next_curwin == NULL) { if (topfrp->fr_win == curwin && next_curwin == NULL) {
// Current window is minimal one line high. // Current window is minimal one line high.
if (p_wmh == 0) { if (p_wmh == 0) {
@ -3976,7 +3964,7 @@ static void new_frame(win_T *wp)
void win_init_size(void) void win_init_size(void)
{ {
firstwin->w_height = ROWS_AVAIL; 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; firstwin->w_height_outer = firstwin->w_height;
topframe->fr_height = ROWS_AVAIL; topframe->fr_height = ROWS_AVAIL;
firstwin->w_width = Columns; firstwin->w_width = Columns;
@ -4087,6 +4075,7 @@ int win_new_tabpage(int after, char_u *filename)
newtp->tp_topframe = topframe; newtp->tp_topframe = topframe;
last_status(false); last_status(false);
set_winbar();
redraw_all_later(NOT_VALID); redraw_all_later(NOT_VALID);
@ -5460,16 +5449,9 @@ void win_setheight(int height)
*/ */
void win_setheight_win(int height, win_T *win) 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.
// Always keep current window at least one line high, even when // Keep window at least two lines high if 'winbar' is enabled.
// 'winminheight' is zero. height = MAX(height, (win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height);
if (height < p_wmh) {
height = p_wmh;
}
if (height == 0) {
height = 1;
}
}
if (win->w_floating) { if (win->w_floating) {
win->w_float_config.height = height; 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 prev_height = wp->w_height_inner;
int height = wp->w_height_request; int height = wp->w_height_request;
if (height == 0) { if (height == 0) {
height = wp->w_height; height = wp->w_height - wp->w_winbar_height;
} }
if (height != prev_height) { if (height != prev_height) {
@ -6279,8 +6261,9 @@ void win_set_inner_size(win_T *wp)
set_fraction(wp); set_fraction(wp);
} }
} }
wp->w_height_inner = height;
wp->w_skipcol = 0; 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 // There is no point in adjusting the scroll position when exiting. Some
// values might be invalid. // values might be invalid.
@ -6306,10 +6289,18 @@ void win_set_inner_size(win_T *wp)
terminal_check_size(wp->w_buffer->terminal); terminal_check_size(wp->w_buffer->terminal);
} }
wp->w_height_outer = (wp->w_height_inner wp->w_height_outer = (wp->w_height_inner + win_extra_height(wp));
+ wp->w_border_adj[0] + wp->w_border_adj[2]); wp->w_width_outer = (wp->w_width_inner + win_extra_width(wp));
wp->w_width_outer = (wp->w_width_inner }
+ wp->w_border_adj[1] + wp->w_border_adj[3]);
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. /// 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. /// Return the number of lines used by the tab page line.
int tabline_height(void) int tabline_height(void)
{ {
@ -6678,6 +6682,12 @@ int tabline_height(void)
return 1; 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 /// Return the number of lines used by the global statusline
int global_stl_height(void) int global_stl_height(void)
{ {

View File

@ -3102,6 +3102,19 @@ describe('API', function()
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
{ use_tabline = true, highlights = true })) { use_tabline = true, highlights = true }))
end) 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)
end) end)
describe('nvim_parse_cmd', function() describe('nvim_parse_cmd', function()

View File

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