aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/statusline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/statusline.c')
-rw-r--r--src/nvim/statusline.c156
1 files changed, 68 insertions, 88 deletions
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index ca7083a9e3..07bb7dd69a 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -123,10 +123,7 @@ void win_redr_status(win_T *wp)
// len += (int)strlen(p + len); // dead assignment
}
- int this_ru_col = ru_col - (Columns - stl_width);
- if (this_ru_col < (stl_width + 1) / 2) {
- this_ru_col = (stl_width + 1) / 2;
- }
+ int this_ru_col = MAX(ru_col - (Columns - stl_width), (stl_width + 1) / 2);
if (this_ru_col <= 1) {
p = "<"; // No room for file name!
len = 1;
@@ -374,10 +371,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
stl = p_ruf;
}
}
- col = ru_col - (Columns - maxwidth);
- if (col < (maxwidth + 1) / 2) {
- col = (maxwidth + 1) / 2;
- }
+ col = MAX(ru_col - (Columns - maxwidth), (maxwidth + 1) / 2);
maxwidth -= col;
if (!in_status_line) {
grid = &msg_grid_adj;
@@ -574,15 +568,9 @@ void win_redr_ruler(win_T *wp)
if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen
o++;
}
- int this_ru_col = ru_col - (Columns - width);
- if (this_ru_col < 0) {
- this_ru_col = 0;
- }
// Never use more than half the window/screen width, leave the other half
// for the filename.
- if (this_ru_col < (width + 1) / 2) {
- this_ru_col = (width + 1) / 2;
- }
+ int this_ru_col = MAX(ru_col - (Columns - width), (width + 1) / 2);
if (this_ru_col + o < width) {
// Need at least 3 chars left for get_rel_pos() + NUL.
while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) {
@@ -660,14 +648,14 @@ static void ui_ext_tabline_update(void)
Array tabs = arena_array(&arena, n_tabs);
FOR_ALL_TABS(tp) {
- Dictionary tab_info = arena_dict(&arena, 2);
+ Dict tab_info = arena_dict(&arena, 2);
PUT_C(tab_info, "tab", TABPAGE_OBJ(tp->handle));
win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
get_trans_bufname(cwp->w_buffer);
PUT_C(tab_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
- ADD_C(tabs, DICTIONARY_OBJ(tab_info));
+ ADD_C(tabs, DICT_OBJ(tab_info));
}
size_t n_buffers = 0;
@@ -682,13 +670,13 @@ static void ui_ext_tabline_update(void)
continue;
}
- Dictionary buffer_info = arena_dict(&arena, 2);
+ Dict buffer_info = arena_dict(&arena, 2);
PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
get_trans_bufname(buf);
PUT_C(buffer_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
- ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
+ ADD_C(buffers, DICT_OBJ(buffer_info));
}
ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers);
@@ -726,7 +714,6 @@ void draw_tabline(void)
win_redr_custom(NULL, false, false);
} else {
int tabcount = 0;
- int tabwidth = 0;
int col = 0;
win_T *cwp;
int wincount;
@@ -735,13 +722,7 @@ void draw_tabline(void)
tabcount++;
}
- if (tabcount > 0) {
- tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
- }
-
- if (tabwidth < 6) {
- tabwidth = 6;
- }
+ int tabwidth = MAX(tabcount > 0 ? (Columns - 1 + tabcount / 2) / tabcount : 0, 6);
int attr = attr_nosel;
tabcount = 0;
@@ -810,9 +791,7 @@ void draw_tabline(void)
len -= ptr2cells(p);
MB_PTR_ADV(p);
}
- if (len > Columns - col - 1) {
- len = Columns - col - 1;
- }
+ len = MIN(len, Columns - col - 1);
grid_line_puts(col, p, -1, attr);
col += len;
@@ -831,6 +810,16 @@ void draw_tabline(void)
}
}
+ for (int scol = col; scol < Columns; scol++) {
+ // Use 0 as tabpage number here, so that double-click opens a tabpage
+ // after the last one, and single-click goes to the next tabpage.
+ tab_page_click_defs[scol] = (StlClickDefinition) {
+ .type = kStlClickTabSwitch,
+ .tabnr = 0,
+ .func = NULL,
+ };
+ }
+
char c = use_sep_chars ? '_' : ' ';
grid_line_fill(col, Columns, schar_from_ascii(c), attr_fill);
@@ -975,7 +964,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
};
set_var(S_LEN("g:statusline_winid"), &tv, false);
- usefmt = eval_to_string_safe(fmt + 2, use_sandbox);
+ usefmt = eval_to_string_safe(fmt + 2, use_sandbox, false);
if (usefmt == NULL) {
usefmt = fmt;
}
@@ -1017,7 +1006,6 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
int evaldepth = 0;
int curitem = 0;
- int foldsignitem = -1;
bool prevchar_isflag = true;
bool prevchar_isitem = false;
@@ -1194,9 +1182,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// If the item was partially or completely truncated, set its
// start to the start of the group
- if (stl_items[idx].start < t) {
- stl_items[idx].start = t;
- }
+ stl_items[idx].start = MAX(stl_items[idx].start, t);
}
// If the group is shorter than the minimum width, add padding characters.
} else if (abs(stl_items[stl_groupitems[groupdepth]].minwid) > group_len) {
@@ -1234,6 +1220,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
}
int minwid = 0;
int maxwid = 9999;
+ int foldsignitem = -1; // Start of fold or sign item
+ bool left_align_num = false; // Number item for should be left-aligned
bool left_align = false;
// Denotes that numbers should be left-padded with zeros
@@ -1268,24 +1256,17 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// TABPAGE pairs are used to denote a region that when clicked will
// either switch to or close a tab.
//
- // Ex: tabline=%0Ttab\ zero%X
- // This tabline has a TABPAGENR item with minwid `0`,
+ // Ex: tabline=%1Ttab\ one%X
+ // This tabline has a TABPAGENR item with minwid `1`,
// which is then closed with a TABCLOSENR item.
- // Clicking on this region with mouse enabled will switch to tab 0.
+ // Clicking on this region with mouse enabled will switch to tab 1.
// Setting the minwid to a different value will switch
// to that tab, if it exists
//
// Ex: tabline=%1Xtab\ one%X
// This tabline has a TABCLOSENR item with minwid `1`,
// which is then closed with a TABCLOSENR item.
- // Clicking on this region with mouse enabled will close tab 0.
- // This is determined by the following formula:
- // tab to close = (1 - minwid)
- // This is because for TABPAGENR we use `minwid` = `tab number`.
- // For TABCLOSENR we store the tab number as a negative value.
- // Because 0 is a valid TABPAGENR value, we have to
- // start our numbering at `-1`.
- // So, `-1` corresponds to us wanting to close tab `0`
+ // Clicking on this region with mouse enabled will close tab 1.
//
// Note: These options are only valid when creating a tabline.
if (*fmt_p == STL_TABPAGENR || *fmt_p == STL_TABCLOSENR) {
@@ -1451,7 +1432,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
}
// Note: The result stored in `t` is unused.
- str = eval_to_string_safe(out_p, use_sandbox);
+ str = eval_to_string_safe(out_p, use_sandbox, false);
curwin = save_curwin;
curbuf = save_curbuf;
@@ -1505,12 +1486,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
}
case STL_LINE:
- // Overload %l with v:lnum for 'statuscolumn'
- if (stcp != NULL) {
- if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
- num = (int)get_vim_var_nr(VV_LNUM);
+ // Overload %l with v:(re)lnum for 'statuscolumn'. Place a sign when 'signcolumn'
+ // is set to "number". Take care of alignment for 'number' + 'relativenumber'.
+ if (stcp != NULL && (wp->w_p_nu || wp->w_p_rnu) && get_vim_var_nr(VV_VIRTNUM) == 0) {
+ if (wp->w_maxscwidth == SCL_NUM && stcp->sattrs[0].text[0]) {
+ goto stcsign;
}
- } else {
+ int relnum = (int)get_vim_var_nr(VV_RELNUM);
+ num = (!wp->w_p_rnu || (wp->w_p_nu && relnum == 0)) ? (int)get_vim_var_nr(VV_LNUM) : relnum;
+ left_align_num = wp->w_p_rnu && wp->w_p_nu && relnum == 0;
+ if (!left_align_num) {
+ stl_items[curitem].type = Separate;
+ stl_items[curitem++].start = out_p;
+ }
+ } else if (stcp == NULL) {
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0 : wp->w_cursor.lnum;
}
break;
@@ -1609,16 +1598,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
case STL_ROFLAG:
case STL_ROFLAG_ALT:
- // Overload %r with v:relnum for 'statuscolumn'
- if (stcp != NULL) {
- if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
- num = (int)get_vim_var_nr(VV_RELNUM);
- }
- } else {
- itemisflag = true;
- if (wp->w_buffer->b_p_ro) {
- str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
- }
+ itemisflag = true;
+ if (wp->w_buffer->b_p_ro) {
+ str = (opt == STL_ROFLAG_ALT) ? ",RO" : _("[RO]");
}
break;
@@ -1632,21 +1614,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
case STL_FOLDCOL: // 'C' for 'statuscolumn'
case STL_SIGNCOL: { // 's' for 'statuscolumn'
+stcsign:
if (stcp == NULL) {
break;
}
- bool fold = opt == STL_FOLDCOL;
- int fdc = fold ? compute_foldcolumn(wp, 0) : 0;
- int width = fold ? fdc > 0 : wp->w_scwidth;
+ int fdc = opt == STL_FOLDCOL ? compute_foldcolumn(wp, 0) : 0;
+ int width = opt == STL_FOLDCOL ? fdc > 0 : opt == STL_SIGNCOL ? wp->w_scwidth : 1;
if (width <= 0) {
break;
}
foldsignitem = curitem;
- char *p = NULL;
- if (fold) {
- schar_T fold_buf[10];
+ if (fdc > 0) {
+ schar_T fold_buf[9];
fill_foldcolumn(wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM),
0, fdc, NULL, fold_buf);
stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
@@ -1654,31 +1635,26 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// TODO(bfredl): this is very backwards. we must support schar_T
// being used directly in 'statuscolumn'
for (int i = 0; i < fdc; i++) {
- buflen += schar_get(out_p + buflen, fold_buf[i]);
+ buflen += schar_get(buf_tmp + buflen, fold_buf[i]);
}
- p = out_p;
}
- char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
- size_t buflen = 0;
- varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
+ size_t signlen = 0;
for (int i = 0; i < width; i++) {
- if (!fold) {
- SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
- p = " ";
- if (sattr && sattr->text[0]) {
- describe_sign_text(buf, sattr->text);
- p = buf;
+ stl_items[curitem].start = out_p + signlen;
+ if (fdc == 0) {
+ if (stcp->sattrs[i].text[0] && get_vim_var_nr(VV_VIRTNUM) == 0) {
+ SignTextAttrs sattrs = stcp->sattrs[i];
+ signlen += describe_sign_text(buf_tmp + signlen, sattrs.text);
+ stl_items[curitem].minwid = -(stcp->sign_cul_id ? stcp->sign_cul_id : sattrs.hl_id);
+ } else {
+ buf_tmp[signlen++] = ' ';
+ buf_tmp[signlen++] = ' ';
+ buf_tmp[signlen] = NUL;
+ stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
- stl_items[curitem].minwid = -(sattr && sattr->text[0]
- ? (stcp->sign_cul_id ? stcp->sign_cul_id : sattr->hl_id)
- : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
- stl_items[curitem].type = Highlight;
- stl_items[curitem].start = out_p + buflen;
- xstrlcpy(buf_tmp + buflen, p, TMPLEN - buflen);
- buflen += strlen(p);
- curitem++;
+ stl_items[curitem++].type = Highlight;
}
str = buf_tmp;
break;
@@ -1851,7 +1827,6 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// For a 'statuscolumn' sign or fold item, add an item to reset the highlight group
if (foldsignitem >= 0) {
- foldsignitem = -1;
stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p;
stl_items[curitem].minwid = 0;
@@ -1956,6 +1931,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
// Item processed, move to the next
curitem++;
+ // For a 'statuscolumn' number item that is left aligned, add a separator item.
+ if (left_align_num) {
+ stl_items[curitem].type = Separate;
+ stl_items[curitem++].start = out_p;
+ }
}
*out_p = NUL;