mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 12:28:18 +00:00
vim-patch:8.2.1909: number of status line items is limited to 80
Problem: Number of status line items is limited to 80.
Solution: Dynamically allocate the arrays. (Rom Grk, closes vim/vim#7181)
8133cc6bf4
The members of stl_item_T have not been prefixed with stl_ contrary to
the vim patch because the amount of stl_ prefixes on single lines of
code in that region was hurtful to readability.
This commit is contained in:
@@ -5795,7 +5795,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
normal text. Each status line item is of the form:
|
normal text. Each status line item is of the form:
|
||||||
%-0{minwid}.{maxwid}{item}
|
%-0{minwid}.{maxwid}{item}
|
||||||
All fields except the {item} are optional. A single percent sign can
|
All fields except the {item} are optional. A single percent sign can
|
||||||
be given as "%%". Up to 80 items can be specified. *E541*
|
be given as "%%".
|
||||||
|
|
||||||
When the option starts with "%!" then it is used as an expression,
|
When the option starts with "%!" then it is used as an expression,
|
||||||
evaluated and the result is used as the option value. Example: >
|
evaluated and the result is used as the option value. Example: >
|
||||||
|
@@ -3440,31 +3440,17 @@ int build_stl_str_hl(
|
|||||||
int use_sandbox,
|
int use_sandbox,
|
||||||
char_u fillchar,
|
char_u fillchar,
|
||||||
int maxwidth,
|
int maxwidth,
|
||||||
struct stl_hlrec *hltab,
|
stl_hlrec_t **hltab,
|
||||||
StlClickRecord *tabtab
|
StlClickRecord **tabtab
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int groupitems[STL_MAX_ITEM];
|
static size_t stl_items_len = 20; // Initial value, grows as needed.
|
||||||
struct stl_item {
|
static stl_item_t *stl_items = NULL;
|
||||||
// Where the item starts in the status line output buffer
|
static int *stl_groupitems = NULL;
|
||||||
char_u *start;
|
static stl_hlrec_t *stl_hltab = NULL;
|
||||||
// Function to run for ClickFunc items.
|
static StlClickRecord *stl_tabtab = NULL;
|
||||||
char *cmd;
|
static int *stl_separator_locations = NULL;
|
||||||
// The minimum width of the item
|
|
||||||
int minwid;
|
|
||||||
// The maximum width of the item
|
|
||||||
int maxwid;
|
|
||||||
enum {
|
|
||||||
Normal,
|
|
||||||
Empty,
|
|
||||||
Group,
|
|
||||||
Separate,
|
|
||||||
Highlight,
|
|
||||||
TabPage,
|
|
||||||
ClickFunc,
|
|
||||||
Trunc
|
|
||||||
} type;
|
|
||||||
} items[STL_MAX_ITEM];
|
|
||||||
#define TMPLEN 70
|
#define TMPLEN 70
|
||||||
char_u buf_tmp[TMPLEN];
|
char_u buf_tmp[TMPLEN];
|
||||||
char_u win_tmp[TMPLEN];
|
char_u win_tmp[TMPLEN];
|
||||||
@@ -3472,6 +3458,14 @@ int build_stl_str_hl(
|
|||||||
const int save_must_redraw = must_redraw;
|
const int save_must_redraw = must_redraw;
|
||||||
const int save_redr_type = curwin->w_redr_type;
|
const int save_redr_type = curwin->w_redr_type;
|
||||||
|
|
||||||
|
if (stl_items == NULL) {
|
||||||
|
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
|
||||||
|
stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
|
||||||
|
stl_hltab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
|
||||||
|
stl_tabtab = xmalloc(sizeof(stl_hlrec_t) * stl_items_len);
|
||||||
|
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
|
||||||
|
}
|
||||||
|
|
||||||
// When the format starts with "%!" then evaluate it as an expression and
|
// When the format starts with "%!" then evaluate it as an expression and
|
||||||
// use the result as the actual format string.
|
// use the result as the actual format string.
|
||||||
if (fmt[0] == '%' && fmt[1] == '!') {
|
if (fmt[0] == '%' && fmt[1] == '!') {
|
||||||
@@ -3540,14 +3534,17 @@ int build_stl_str_hl(
|
|||||||
// Proceed character by character through the statusline format string
|
// Proceed character by character through the statusline format string
|
||||||
// fmt_p is the current positon in the input buffer
|
// fmt_p is the current positon in the input buffer
|
||||||
for (char_u *fmt_p = usefmt; *fmt_p; ) {
|
for (char_u *fmt_p = usefmt; *fmt_p; ) {
|
||||||
if (curitem == STL_MAX_ITEM) {
|
if (curitem == (int)stl_items_len) {
|
||||||
// There are too many items. Add the error code to the statusline
|
size_t new_len = stl_items_len * 3 / 2;
|
||||||
// to give the user a hint about what went wrong.
|
|
||||||
if (out_p + 5 < out_end_p) {
|
stl_items = xrealloc(stl_items, sizeof(stl_item_t) * new_len);
|
||||||
memmove(out_p, " E541", (size_t)5);
|
stl_groupitems = xrealloc(stl_groupitems, sizeof(int) * new_len);
|
||||||
out_p += 5;
|
stl_hltab = xrealloc(stl_hltab, sizeof(stl_hlrec_t) * new_len);
|
||||||
}
|
stl_tabtab = xrealloc(stl_tabtab, sizeof(StlClickRecord) * new_len);
|
||||||
break;
|
stl_separator_locations =
|
||||||
|
xrealloc(stl_separator_locations, sizeof(int) * new_len);
|
||||||
|
|
||||||
|
stl_items_len = new_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*fmt_p != NUL && *fmt_p != '%') {
|
if (*fmt_p != NUL && *fmt_p != '%') {
|
||||||
@@ -3591,16 +3588,16 @@ int build_stl_str_hl(
|
|||||||
if (groupdepth > 0) {
|
if (groupdepth > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
items[curitem].type = Separate;
|
stl_items[curitem].type = Separate;
|
||||||
items[curitem++].start = out_p;
|
stl_items[curitem++].start = out_p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STL_TRUNCMARK: Where to begin truncating if the statusline is too long.
|
// STL_TRUNCMARK: Where to begin truncating if the statusline is too long.
|
||||||
if (*fmt_p == STL_TRUNCMARK) {
|
if (*fmt_p == STL_TRUNCMARK) {
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
items[curitem].type = Trunc;
|
stl_items[curitem].type = Trunc;
|
||||||
items[curitem++].start = out_p;
|
stl_items[curitem++].start = out_p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3616,7 +3613,7 @@ int build_stl_str_hl(
|
|||||||
// Determine how long the group is.
|
// Determine how long the group is.
|
||||||
// Note: We set the current output position to null
|
// Note: We set the current output position to null
|
||||||
// so `vim_strsize` will work.
|
// so `vim_strsize` will work.
|
||||||
char_u *t = items[groupitems[groupdepth]].start;
|
char_u *t = stl_items[stl_groupitems[groupdepth]].start;
|
||||||
*out_p = NUL;
|
*out_p = NUL;
|
||||||
long group_len = vim_strsize(t);
|
long group_len = vim_strsize(t);
|
||||||
|
|
||||||
@@ -3626,40 +3623,40 @@ int build_stl_str_hl(
|
|||||||
// move the output pointer back to where the group started.
|
// move the output pointer back to where the group started.
|
||||||
// Note: This erases any non-item characters that were in the group.
|
// Note: This erases any non-item characters that were in the group.
|
||||||
// Otherwise there would be no reason to do this step.
|
// Otherwise there would be no reason to do this step.
|
||||||
if (curitem > groupitems[groupdepth] + 1
|
if (curitem > stl_groupitems[groupdepth] + 1
|
||||||
&& items[groupitems[groupdepth]].minwid == 0) {
|
&& stl_items[stl_groupitems[groupdepth]].minwid == 0) {
|
||||||
// remove group if all items are empty and highlight group
|
// remove group if all items are empty and highlight group
|
||||||
// doesn't change
|
// doesn't change
|
||||||
int group_start_userhl = 0;
|
int group_start_userhl = 0;
|
||||||
int group_end_userhl = 0;
|
int group_end_userhl = 0;
|
||||||
int n;
|
int n;
|
||||||
for (n = groupitems[groupdepth] - 1; n >= 0; n--) {
|
for (n = stl_groupitems[groupdepth] - 1; n >= 0; n--) {
|
||||||
if (items[n].type == Highlight) {
|
if (stl_items[n].type == Highlight) {
|
||||||
group_start_userhl = group_end_userhl = items[n].minwid;
|
group_start_userhl = group_end_userhl = stl_items[n].minwid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (n = groupitems[groupdepth] + 1; n < curitem; n++) {
|
for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
|
||||||
if (items[n].type == Normal) {
|
if (stl_items[n].type == Normal) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (items[n].type == Highlight) {
|
if (stl_items[n].type == Highlight) {
|
||||||
group_end_userhl = items[n].minwid;
|
group_end_userhl = stl_items[n].minwid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n == curitem && group_start_userhl == group_end_userhl) {
|
if (n == curitem && group_start_userhl == group_end_userhl) {
|
||||||
// empty group
|
// empty group
|
||||||
out_p = t;
|
out_p = t;
|
||||||
group_len = 0;
|
group_len = 0;
|
||||||
for (n = groupitems[groupdepth] + 1; n < curitem; n++) {
|
for (n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
|
||||||
// do not use the highlighting from the removed group
|
// do not use the highlighting from the removed group
|
||||||
if (items[n].type == Highlight) {
|
if (stl_items[n].type == Highlight) {
|
||||||
items[n].type = Empty;
|
stl_items[n].type = Empty;
|
||||||
}
|
}
|
||||||
// adjust the start position of TabPage to the next
|
// adjust the start position of TabPage to the next
|
||||||
// item position
|
// item position
|
||||||
if (items[n].type == TabPage) {
|
if (stl_items[n].type == TabPage) {
|
||||||
items[n].start = out_p;
|
stl_items[n].start = out_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3667,18 +3664,19 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// If the group is longer than it is allowed to be
|
// If the group is longer than it is allowed to be
|
||||||
// truncate by removing bytes from the start of the group text.
|
// truncate by removing bytes from the start of the group text.
|
||||||
if (group_len > items[groupitems[groupdepth]].maxwid) {
|
if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) {
|
||||||
// { Determine the number of bytes to remove
|
// { Determine the number of bytes to remove
|
||||||
long n;
|
long n;
|
||||||
if (has_mbyte) {
|
if (has_mbyte) {
|
||||||
// Find the first character that should be included.
|
// Find the first character that should be included.
|
||||||
n = 0;
|
n = 0;
|
||||||
while (group_len >= items[groupitems[groupdepth]].maxwid) {
|
while (group_len >= stl_items[stl_groupitems[groupdepth]].maxwid) {
|
||||||
group_len -= ptr2cells(t + n);
|
group_len -= ptr2cells(t + n);
|
||||||
n += (*mb_ptr2len)(t + n);
|
n += (*mb_ptr2len)(t + n);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n = (long)(out_p - t) - items[groupitems[groupdepth]].maxwid + 1;
|
n = (long)(out_p - t)
|
||||||
|
- stl_items[stl_groupitems[groupdepth]].maxwid + 1;
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -3689,25 +3687,26 @@ int build_stl_str_hl(
|
|||||||
memmove(t + 1, t + n, (size_t)(out_p - (t + n)));
|
memmove(t + 1, t + n, (size_t)(out_p - (t + n)));
|
||||||
out_p = out_p - n + 1;
|
out_p = out_p - n + 1;
|
||||||
// Fill up space left over by half a double-wide char.
|
// Fill up space left over by half a double-wide char.
|
||||||
while (++group_len < items[groupitems[groupdepth]].minwid) {
|
while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
|
||||||
*out_p++ = fillchar;
|
*out_p++ = fillchar;
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// correct the start of the items for the truncation
|
// correct the start of the items for the truncation
|
||||||
for (int idx = groupitems[groupdepth] + 1; idx < curitem; idx++) {
|
for (int idx = stl_groupitems[groupdepth] + 1; idx < curitem; idx++) {
|
||||||
// Shift everything back by the number of removed bytes
|
// Shift everything back by the number of removed bytes
|
||||||
items[idx].start -= n;
|
stl_items[idx].start -= n;
|
||||||
|
|
||||||
// If the item was partially or completely truncated, set its
|
// If the item was partially or completely truncated, set its
|
||||||
// start to the start of the group
|
// start to the start of the group
|
||||||
if (items[idx].start < t) {
|
if (stl_items[idx].start < t) {
|
||||||
items[idx].start = t;
|
stl_items[idx].start = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the group is shorter than the minimum width, add padding characters.
|
// If the group is shorter than the minimum width, add padding characters.
|
||||||
} else if (abs(items[groupitems[groupdepth]].minwid) > group_len) {
|
} else if (
|
||||||
long min_group_width = items[groupitems[groupdepth]].minwid;
|
abs(stl_items[stl_groupitems[groupdepth]].minwid) > group_len) {
|
||||||
|
long min_group_width = stl_items[stl_groupitems[groupdepth]].minwid;
|
||||||
// If the group is left-aligned, add characters to the right.
|
// If the group is left-aligned, add characters to the right.
|
||||||
if (min_group_width < 0) {
|
if (min_group_width < 0) {
|
||||||
min_group_width = 0 - min_group_width;
|
min_group_width = 0 - min_group_width;
|
||||||
@@ -3726,8 +3725,8 @@ int build_stl_str_hl(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Adjust item start positions
|
// Adjust item start positions
|
||||||
for (int n = groupitems[groupdepth] + 1; n < curitem; n++) {
|
for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
|
||||||
items[n].start += group_len;
|
stl_items[n].start += group_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend the fill characters
|
// Prepend the fill characters
|
||||||
@@ -3763,9 +3762,9 @@ int build_stl_str_hl(
|
|||||||
// User highlight groups override the min width field
|
// User highlight groups override the min width field
|
||||||
// to denote the styling to use.
|
// to denote the styling to use.
|
||||||
if (*fmt_p == STL_USER_HL) {
|
if (*fmt_p == STL_USER_HL) {
|
||||||
items[curitem].type = Highlight;
|
stl_items[curitem].type = Highlight;
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].minwid = minwid > 9 ? 1 : minwid;
|
stl_items[curitem].minwid = minwid > 9 ? 1 : minwid;
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
curitem++;
|
curitem++;
|
||||||
continue;
|
continue;
|
||||||
@@ -3799,8 +3798,8 @@ int build_stl_str_hl(
|
|||||||
if (minwid == 0) {
|
if (minwid == 0) {
|
||||||
// %X ends the close label, go back to the previous tab label nr.
|
// %X ends the close label, go back to the previous tab label nr.
|
||||||
for (long n = curitem - 1; n >= 0; n--) {
|
for (long n = curitem - 1; n >= 0; n--) {
|
||||||
if (items[n].type == TabPage && items[n].minwid >= 0) {
|
if (stl_items[n].type == TabPage && stl_items[n].minwid >= 0) {
|
||||||
minwid = items[n].minwid;
|
minwid = stl_items[n].minwid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3809,9 +3808,9 @@ int build_stl_str_hl(
|
|||||||
minwid = -minwid;
|
minwid = -minwid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items[curitem].type = TabPage;
|
stl_items[curitem].type = TabPage;
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].minwid = minwid;
|
stl_items[curitem].minwid = minwid;
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
curitem++;
|
curitem++;
|
||||||
continue;
|
continue;
|
||||||
@@ -3826,10 +3825,10 @@ int build_stl_str_hl(
|
|||||||
if (*fmt_p != STL_CLICK_FUNC) {
|
if (*fmt_p != STL_CLICK_FUNC) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
items[curitem].type = ClickFunc;
|
stl_items[curitem].type = ClickFunc;
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t)));
|
stl_items[curitem].cmd = xmemdupz(t, (size_t)(((char *)fmt_p - t)));
|
||||||
items[curitem].minwid = minwid;
|
stl_items[curitem].minwid = minwid;
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
curitem++;
|
curitem++;
|
||||||
continue;
|
continue;
|
||||||
@@ -3850,11 +3849,11 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// Denotes the start of a new group
|
// Denotes the start of a new group
|
||||||
if (*fmt_p == '(') {
|
if (*fmt_p == '(') {
|
||||||
groupitems[groupdepth++] = curitem;
|
stl_groupitems[groupdepth++] = curitem;
|
||||||
items[curitem].type = Group;
|
stl_items[curitem].type = Group;
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].minwid = minwid;
|
stl_items[curitem].minwid = minwid;
|
||||||
items[curitem].maxwid = maxwid;
|
stl_items[curitem].maxwid = maxwid;
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
curitem++;
|
curitem++;
|
||||||
continue;
|
continue;
|
||||||
@@ -4149,9 +4148,9 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// Create a highlight item based on the name
|
// Create a highlight item based on the name
|
||||||
if (*fmt_p == '#') {
|
if (*fmt_p == '#') {
|
||||||
items[curitem].type = Highlight;
|
stl_items[curitem].type = Highlight;
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
|
stl_items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
|
||||||
curitem++;
|
curitem++;
|
||||||
fmt_p++;
|
fmt_p++;
|
||||||
}
|
}
|
||||||
@@ -4162,8 +4161,8 @@ int build_stl_str_hl(
|
|||||||
// If we made it this far, the item is normal and starts at
|
// If we made it this far, the item is normal and starts at
|
||||||
// our current position in the output buffer.
|
// our current position in the output buffer.
|
||||||
// Non-normal items would have `continued`.
|
// Non-normal items would have `continued`.
|
||||||
items[curitem].start = out_p;
|
stl_items[curitem].start = out_p;
|
||||||
items[curitem].type = Normal;
|
stl_items[curitem].type = Normal;
|
||||||
|
|
||||||
// Copy the item string into the output buffer
|
// Copy the item string into the output buffer
|
||||||
if (str != NULL && *str) {
|
if (str != NULL && *str) {
|
||||||
@@ -4321,7 +4320,7 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// Otherwise, there was nothing to print so mark the item as empty
|
// Otherwise, there was nothing to print so mark the item as empty
|
||||||
} else {
|
} else {
|
||||||
items[curitem].type = Empty;
|
stl_items[curitem].type = Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only free the string buffer if we allocated it.
|
// Only free the string buffer if we allocated it.
|
||||||
@@ -4362,13 +4361,13 @@ int build_stl_str_hl(
|
|||||||
// Otherwise, look for the truncation item
|
// Otherwise, look for the truncation item
|
||||||
} else {
|
} else {
|
||||||
// Default to truncating at the first item
|
// Default to truncating at the first item
|
||||||
trunc_p = items[0].start;
|
trunc_p = stl_items[0].start;
|
||||||
item_idx = 0;
|
item_idx = 0;
|
||||||
|
|
||||||
for (int i = 0; i < itemcnt; i++) {
|
for (int i = 0; i < itemcnt; i++) {
|
||||||
if (items[i].type == Trunc) {
|
if (stl_items[i].type == Trunc) {
|
||||||
// Truncate at %< items.
|
// Truncate at %< stl_items.
|
||||||
trunc_p = items[i].start;
|
trunc_p = stl_items[i].start;
|
||||||
item_idx = i;
|
item_idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4403,7 +4402,7 @@ int build_stl_str_hl(
|
|||||||
// Ignore any items in the statusline that occur after
|
// Ignore any items in the statusline that occur after
|
||||||
// the truncation point
|
// the truncation point
|
||||||
for (int i = 0; i < itemcnt; i++) {
|
for (int i = 0; i < itemcnt; i++) {
|
||||||
if (items[i].start > trunc_p) {
|
if (stl_items[i].start > trunc_p) {
|
||||||
itemcnt = i;
|
itemcnt = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4458,12 +4457,12 @@ int build_stl_str_hl(
|
|||||||
for (int i = item_idx; i < itemcnt; i++) {
|
for (int i = item_idx; i < itemcnt; i++) {
|
||||||
// Items starting at or after the end of the truncated section need
|
// Items starting at or after the end of the truncated section need
|
||||||
// to be moved backwards.
|
// to be moved backwards.
|
||||||
if (items[i].start >= trunc_end_p) {
|
if (stl_items[i].start >= trunc_end_p) {
|
||||||
items[i].start -= item_offset;
|
stl_items[i].start -= item_offset;
|
||||||
// Anything inside the truncated area is set to start
|
// Anything inside the truncated area is set to start
|
||||||
// at the `<` truncation character.
|
// at the `<` truncation character.
|
||||||
} else {
|
} else {
|
||||||
items[i].start = trunc_p;
|
stl_items[i].start = trunc_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
@@ -4479,7 +4478,7 @@ int build_stl_str_hl(
|
|||||||
// figuring out how many groups there are.
|
// figuring out how many groups there are.
|
||||||
int num_separators = 0;
|
int num_separators = 0;
|
||||||
for (int i = 0; i < itemcnt; i++) {
|
for (int i = 0; i < itemcnt; i++) {
|
||||||
if (items[i].type == Separate) {
|
if (stl_items[i].type == Separate) {
|
||||||
num_separators++;
|
num_separators++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4488,11 +4487,10 @@ int build_stl_str_hl(
|
|||||||
if (num_separators) {
|
if (num_separators) {
|
||||||
// Create an array of the start location for each
|
// Create an array of the start location for each
|
||||||
// separator mark.
|
// separator mark.
|
||||||
int separator_locations[STL_MAX_ITEM];
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int i = 0; i < itemcnt; i++) {
|
for (int i = 0; i < itemcnt; i++) {
|
||||||
if (items[i].type == Separate) {
|
if (stl_items[i].type == Separate) {
|
||||||
separator_locations[index] = i;
|
stl_separator_locations[index] = i;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4504,16 +4502,17 @@ int build_stl_str_hl(
|
|||||||
for (int i = 0; i < num_separators; i++) {
|
for (int i = 0; i < num_separators; i++) {
|
||||||
int dislocation = (i == (num_separators - 1))
|
int dislocation = (i == (num_separators - 1))
|
||||||
? final_spaces : standard_spaces;
|
? final_spaces : standard_spaces;
|
||||||
char_u *seploc = items[separator_locations[i]].start + dislocation;
|
char_u *start = stl_items[stl_separator_locations[i]].start;
|
||||||
STRMOVE(seploc, items[separator_locations[i]].start);
|
char_u *seploc = start + dislocation;
|
||||||
for (char_u *s = items[separator_locations[i]].start; s < seploc; s++) {
|
STRMOVE(seploc, start);
|
||||||
|
for (char_u *s = start; s < seploc; s++) {
|
||||||
*s = fillchar;
|
*s = fillchar;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int item_idx = separator_locations[i] + 1;
|
for (int item_idx = stl_separator_locations[i] + 1;
|
||||||
item_idx < itemcnt;
|
item_idx < itemcnt;
|
||||||
item_idx++) {
|
item_idx++) {
|
||||||
items[item_idx].start += dislocation;
|
stl_items[item_idx].start += dislocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4523,11 +4522,12 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// Store the info about highlighting.
|
// Store the info about highlighting.
|
||||||
if (hltab != NULL) {
|
if (hltab != NULL) {
|
||||||
struct stl_hlrec *sp = hltab;
|
*hltab = stl_hltab;
|
||||||
|
stl_hlrec_t *sp = stl_hltab;
|
||||||
for (long l = 0; l < itemcnt; l++) {
|
for (long l = 0; l < itemcnt; l++) {
|
||||||
if (items[l].type == Highlight) {
|
if (stl_items[l].type == Highlight) {
|
||||||
sp->start = items[l].start;
|
sp->start = stl_items[l].start;
|
||||||
sp->userhl = items[l].minwid;
|
sp->userhl = stl_items[l].minwid;
|
||||||
sp++;
|
sp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4537,16 +4537,17 @@ int build_stl_str_hl(
|
|||||||
|
|
||||||
// Store the info about tab pages labels.
|
// Store the info about tab pages labels.
|
||||||
if (tabtab != NULL) {
|
if (tabtab != NULL) {
|
||||||
StlClickRecord *cur_tab_rec = tabtab;
|
*tabtab = stl_tabtab;
|
||||||
|
StlClickRecord *cur_tab_rec = stl_tabtab;
|
||||||
for (long l = 0; l < itemcnt; l++) {
|
for (long l = 0; l < itemcnt; l++) {
|
||||||
if (items[l].type == TabPage) {
|
if (stl_items[l].type == TabPage) {
|
||||||
cur_tab_rec->start = (char *)items[l].start;
|
cur_tab_rec->start = (char *)stl_items[l].start;
|
||||||
if (items[l].minwid == 0) {
|
if (stl_items[l].minwid == 0) {
|
||||||
cur_tab_rec->def.type = kStlClickDisabled;
|
cur_tab_rec->def.type = kStlClickDisabled;
|
||||||
cur_tab_rec->def.tabnr = 0;
|
cur_tab_rec->def.tabnr = 0;
|
||||||
} else {
|
} else {
|
||||||
int tabnr = items[l].minwid;
|
int tabnr = stl_items[l].minwid;
|
||||||
if (items[l].minwid > 0) {
|
if (stl_items[l].minwid > 0) {
|
||||||
cur_tab_rec->def.type = kStlClickTabSwitch;
|
cur_tab_rec->def.type = kStlClickTabSwitch;
|
||||||
} else {
|
} else {
|
||||||
cur_tab_rec->def.type = kStlClickTabClose;
|
cur_tab_rec->def.type = kStlClickTabClose;
|
||||||
@@ -4556,11 +4557,11 @@ int build_stl_str_hl(
|
|||||||
}
|
}
|
||||||
cur_tab_rec->def.func = NULL;
|
cur_tab_rec->def.func = NULL;
|
||||||
cur_tab_rec++;
|
cur_tab_rec++;
|
||||||
} else if (items[l].type == ClickFunc) {
|
} else if (stl_items[l].type == ClickFunc) {
|
||||||
cur_tab_rec->start = (char *)items[l].start;
|
cur_tab_rec->start = (char *)stl_items[l].start;
|
||||||
cur_tab_rec->def.type = kStlClickFuncRun;
|
cur_tab_rec->def.type = kStlClickFuncRun;
|
||||||
cur_tab_rec->def.tabnr = items[l].minwid;
|
cur_tab_rec->def.tabnr = stl_items[l].minwid;
|
||||||
cur_tab_rec->def.func = items[l].cmd;
|
cur_tab_rec->def.func = stl_items[l].cmd;
|
||||||
cur_tab_rec++;
|
cur_tab_rec++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -361,14 +361,36 @@ struct mapblock {
|
|||||||
sctx_T m_script_ctx; // SCTX where map was defined
|
sctx_T m_script_ctx; // SCTX where map was defined
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/// Used for highlighting in the status line.
|
||||||
* Used for highlighting in the status line.
|
typedef struct stl_hlrec stl_hlrec_t;
|
||||||
*/
|
|
||||||
struct stl_hlrec {
|
struct stl_hlrec {
|
||||||
char_u *start;
|
char_u *start;
|
||||||
int userhl; // 0: no HL, 1-9: User HL, < 0 for syn ID
|
int userhl; // 0: no HL, 1-9: User HL, < 0 for syn ID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Used for building the status line.
|
||||||
|
typedef struct stl_item stl_item_t;
|
||||||
|
struct stl_item {
|
||||||
|
// Where the item starts in the status line output buffer
|
||||||
|
char_u *start;
|
||||||
|
// Function to run for ClickFunc items.
|
||||||
|
char *cmd;
|
||||||
|
// The minimum width of the item
|
||||||
|
int minwid;
|
||||||
|
// The maximum width of the item
|
||||||
|
int maxwid;
|
||||||
|
enum {
|
||||||
|
Normal,
|
||||||
|
Empty,
|
||||||
|
Group,
|
||||||
|
Separate,
|
||||||
|
Highlight,
|
||||||
|
TabPage,
|
||||||
|
ClickFunc,
|
||||||
|
Trunc
|
||||||
|
} type;
|
||||||
|
};
|
||||||
|
|
||||||
// values for b_syn_spell: what to do with toplevel text
|
// values for b_syn_spell: what to do with toplevel text
|
||||||
#define SYNSPL_DEFAULT 0 // spell check if @Spell not defined
|
#define SYNSPL_DEFAULT 0 // spell check if @Spell not defined
|
||||||
#define SYNSPL_TOP 1 // spell check toplevel text
|
#define SYNSPL_TOP 1 // spell check toplevel text
|
||||||
|
@@ -3751,11 +3751,10 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set)
|
|||||||
/// Return error message or NULL.
|
/// Return error message or NULL.
|
||||||
char_u *check_stl_option(char_u *s)
|
char_u *check_stl_option(char_u *s)
|
||||||
{
|
{
|
||||||
int itemcnt = 0;
|
|
||||||
int groupdepth = 0;
|
int groupdepth = 0;
|
||||||
static char_u errbuf[80];
|
static char_u errbuf[80];
|
||||||
|
|
||||||
while (*s && itemcnt < STL_MAX_ITEM) {
|
while (*s) {
|
||||||
// Check for valid keys after % sequences
|
// Check for valid keys after % sequences
|
||||||
while (*s && *s != '%') {
|
while (*s && *s != '%') {
|
||||||
s++;
|
s++;
|
||||||
@@ -3764,9 +3763,6 @@ char_u *check_stl_option(char_u *s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
if (*s != '%' && *s != ')') {
|
|
||||||
itemcnt++;
|
|
||||||
}
|
|
||||||
if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE) {
|
if (*s == '%' || *s == STL_TRUNCMARK || *s == STL_SEPARATE) {
|
||||||
s++;
|
s++;
|
||||||
continue;
|
continue;
|
||||||
@@ -3808,9 +3804,6 @@ char_u *check_stl_option(char_u *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (itemcnt >= STL_MAX_ITEM) {
|
|
||||||
return (char_u *)N_("E541: too many items");
|
|
||||||
}
|
|
||||||
if (groupdepth != 0) {
|
if (groupdepth != 0) {
|
||||||
return (char_u *)N_("E542: unbalanced groups");
|
return (char_u *)N_("E542: unbalanced groups");
|
||||||
}
|
}
|
||||||
|
@@ -5191,8 +5191,8 @@ win_redr_custom (
|
|||||||
char_u buf[MAXPATHL];
|
char_u buf[MAXPATHL];
|
||||||
char_u *stl;
|
char_u *stl;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
struct stl_hlrec hltab[STL_MAX_ITEM];
|
stl_hlrec_t *hltab;
|
||||||
StlClickRecord tabtab[STL_MAX_ITEM];
|
StlClickRecord *tabtab;
|
||||||
int use_sandbox = false;
|
int use_sandbox = false;
|
||||||
win_T *ewp;
|
win_T *ewp;
|
||||||
int p_crb_save;
|
int p_crb_save;
|
||||||
@@ -5270,9 +5270,9 @@ win_redr_custom (
|
|||||||
/* Make a copy, because the statusline may include a function call that
|
/* Make a copy, because the statusline may include a function call that
|
||||||
* might change the option value and free the memory. */
|
* might change the option value and free the memory. */
|
||||||
stl = vim_strsave(stl);
|
stl = vim_strsave(stl);
|
||||||
width = build_stl_str_hl(ewp, buf, sizeof(buf),
|
width =
|
||||||
stl, use_sandbox,
|
build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox,
|
||||||
fillchar, maxwidth, hltab, tabtab);
|
fillchar, maxwidth, &hltab, &tabtab);
|
||||||
xfree(stl);
|
xfree(stl);
|
||||||
ewp->w_p_crb = p_crb_save;
|
ewp->w_p_crb = p_crb_save;
|
||||||
|
|
||||||
|
@@ -267,7 +267,6 @@ func Test_set_errors()
|
|||||||
call assert_fails('set commentstring=x', 'E537:')
|
call assert_fails('set commentstring=x', 'E537:')
|
||||||
call assert_fails('set complete=x', 'E539:')
|
call assert_fails('set complete=x', 'E539:')
|
||||||
call assert_fails('set statusline=%{', 'E540:')
|
call assert_fails('set statusline=%{', 'E540:')
|
||||||
call assert_fails('set statusline=' . repeat("%p", 81), 'E541:')
|
|
||||||
call assert_fails('set statusline=%(', 'E542:')
|
call assert_fails('set statusline=%(', 'E542:')
|
||||||
if has('cursorshape')
|
if has('cursorshape')
|
||||||
" This invalid value for 'guicursor' used to cause Vim to crash.
|
" This invalid value for 'guicursor' used to cause Vim to crash.
|
||||||
|
@@ -354,6 +354,21 @@ func Test_statusline()
|
|||||||
delfunc GetNested
|
delfunc GetNested
|
||||||
delfunc GetStatusLine
|
delfunc GetStatusLine
|
||||||
|
|
||||||
|
" Test statusline works with 80+ items
|
||||||
|
function! StatusLabel()
|
||||||
|
redrawstatus
|
||||||
|
return '[label]'
|
||||||
|
endfunc
|
||||||
|
let statusline = '%{StatusLabel()}'
|
||||||
|
for i in range(150)
|
||||||
|
let statusline .= '%#TabLine' . (i % 2 == 0 ? 'Fill' : 'Sel') . '#' . string(i)[0]
|
||||||
|
endfor
|
||||||
|
let &statusline = statusline
|
||||||
|
redrawstatus
|
||||||
|
set statusline&
|
||||||
|
delfunc StatusLabel
|
||||||
|
|
||||||
|
|
||||||
" Check statusline in current and non-current window
|
" Check statusline in current and non-current window
|
||||||
" with the 'fillchars' option.
|
" with the 'fillchars' option.
|
||||||
set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
|
set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
|
||||||
|
@@ -259,7 +259,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
|
|||||||
#define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno))
|
#define PERROR(msg) (void) emsgf("%s: %s", msg, strerror(errno))
|
||||||
|
|
||||||
#define SHOWCMD_COLS 10 // columns needed by shown command
|
#define SHOWCMD_COLS 10 // columns needed by shown command
|
||||||
#define STL_MAX_ITEM 80 // max nr of %<flag> in statusline
|
|
||||||
|
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
|
|
||||||
|
@@ -212,7 +212,7 @@ describe('buffer functions', function()
|
|||||||
|
|
||||||
describe('build_stl_str_hl', function()
|
describe('build_stl_str_hl', function()
|
||||||
local buffer_byte_size = 100
|
local buffer_byte_size = 100
|
||||||
local STL_MAX_ITEM = 80
|
local STL_INITIAL_ITEMS = 20
|
||||||
local output_buffer = ''
|
local output_buffer = ''
|
||||||
|
|
||||||
-- This function builds the statusline
|
-- This function builds the statusline
|
||||||
@@ -431,31 +431,23 @@ describe('buffer functions', function()
|
|||||||
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
|
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
|
||||||
'aaaa b c d e fg hi jk lmnop qrstuv wxyz')
|
'aaaa b c d e fg hi jk lmnop qrstuv wxyz')
|
||||||
|
|
||||||
-- maximum stl item testing
|
-- stl item testing
|
||||||
statusline_test('should handle a much larger amount of = than buffer locations', 20,
|
local tabline = ''
|
||||||
('%='):rep(STL_MAX_ITEM - 1),
|
for i= 1, 1000 do
|
||||||
' ') -- Should be fine, because within limit
|
tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
|
||||||
statusline_test('should handle a much larger amount of = than stl max item', 20,
|
end
|
||||||
('%='):rep(STL_MAX_ITEM + 1),
|
statusline_test('should handle a large amount of any items', 20,
|
||||||
' E541') -- Should show the VIM error
|
tabline,
|
||||||
|
'<1010101010101010101') -- Should not show any error
|
||||||
|
statusline_test('should handle a larger amount of = than stl initial item', 20,
|
||||||
|
('%='):rep(STL_INITIAL_ITEMS * 5),
|
||||||
|
' ') -- Should not show any error
|
||||||
statusline_test('should handle many extra characters', 20,
|
statusline_test('should handle many extra characters', 20,
|
||||||
'a' .. ('a'):rep(STL_MAX_ITEM * 4),
|
'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5),
|
||||||
'<aaaaaaaaaaaaaaaaaaa') -- Does not show the error because there are no items
|
'<aaaaaaaaaaaaaaaaaaa') -- Does not show any error
|
||||||
statusline_test('should handle almost maximum of characters and flags', 20,
|
|
||||||
'a' .. ('%=a'):rep(STL_MAX_ITEM - 1),
|
|
||||||
'a<aaaaaaaaaaaaaaaaaa') -- Should not show the VIM error
|
|
||||||
statusline_test('should handle many extra characters and flags', 20,
|
statusline_test('should handle many extra characters and flags', 20,
|
||||||
'a' .. ('%=a'):rep(STL_MAX_ITEM),
|
'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
|
||||||
'a<aaaaaaaaaaaaa E541') -- Should show the VIM error
|
'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error
|
||||||
statusline_test('should handle many extra characters and flags', 20,
|
|
||||||
'a' .. ('%=a'):rep(STL_MAX_ITEM * 2),
|
|
||||||
'a<aaaaaaaaaaaaa E541') -- Should show the VIM error
|
|
||||||
statusline_test('should handle many extra characters and flags with truncation', 20,
|
|
||||||
'aaa%<' .. ('%=a'):rep(STL_MAX_ITEM),
|
|
||||||
'aaa<aaaaaaaaaaa E541') -- Should show the VIM error
|
|
||||||
statusline_test('should handle many characters and flags before and after truncation', 20,
|
|
||||||
'a%=a%=a%<' .. ('%=a'):rep(STL_MAX_ITEM),
|
|
||||||
'aaa<aaaaaaaaaaa E541') -- Should show the VIM error
|
|
||||||
|
|
||||||
|
|
||||||
-- multi-byte testing
|
-- multi-byte testing
|
||||||
|
Reference in New Issue
Block a user