feat(statusline): support multibyte fillchar

This includes a partial port of Vim patch 8.2.2569 and some changes to
nvim_eval_statusline() to allow a multibyte fillchar. Literally every
line of C code touched by that patch has been refactored in Nvim, and
that patch contains some irrelevant foldcolumn tests I'm not sure how to
port (as Nvim's foldcolumn behavior has diverged from Vim's).
This commit is contained in:
zeertzjq
2022-01-16 18:44:28 +08:00
parent 7085e5b0c8
commit be15ac06ba
8 changed files with 152 additions and 91 deletions

View File

@@ -3418,7 +3418,7 @@ typedef enum {
///
/// @return The final width of the statusline
int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use_sandbox,
char_u fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
{
static size_t stl_items_len = 20; // Initial value, grows as needed.
static stl_item_t *stl_items = NULL;
@@ -3461,9 +3461,6 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
if (fillchar == 0) {
fillchar = ' ';
} else if (utf_char2len(fillchar) > 1) {
// Can't handle a multi-byte fill character yet.
fillchar = '-';
}
// The cursor in windows other than the current one isn't always
@@ -3661,7 +3658,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
out_p = out_p - n + 1;
// Fill up space left over by half a double-wide char.
while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
*out_p++ = fillchar;
MB_CHAR2BYTES(fillchar, out_p);
}
// }
@@ -3684,14 +3681,14 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
if (min_group_width < 0) {
min_group_width = 0 - min_group_width;
while (group_len++ < min_group_width && out_p < out_end_p) {
*out_p++ = fillchar;
MB_CHAR2BYTES(fillchar, out_p);
}
// If the group is right-aligned, shift everything to the right and
// prepend with filler characters.
} else {
// { Move the group to the right
memmove(t + min_group_width - group_len, t, (size_t)(out_p - t));
group_len = min_group_width - group_len;
group_len = (min_group_width - group_len) * utf_char2len(fillchar);
memmove(t + group_len, t, (size_t)(out_p - t));
if (out_p + group_len >= (out_end_p + 1)) {
group_len = (long)(out_end_p - out_p);
}
@@ -3705,7 +3702,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
// Prepend the fill characters
for (; group_len > 0; group_len--) {
*t++ = fillchar;
MB_CHAR2BYTES(fillchar, t);
}
}
}
@@ -4237,7 +4234,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t)) {
*out_p++ = ' ';
} else {
*out_p++ = fillchar;
MB_CHAR2BYTES(fillchar, out_p);
}
}
minwid = 0;
@@ -4248,20 +4245,21 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
}
// { Copy the string text into the output buffer
while (*t && out_p < out_end_p) {
*out_p++ = *t++;
for (; *t && out_p < out_end_p; t++) {
// Change a space by fillchar, unless fillchar is '-' and a
// digit follows.
if (fillable && out_p[-1] == ' '
&& (!ascii_isdigit(*t) || fillchar != '-')) {
out_p[-1] = fillchar;
if (fillable && *t == ' '
&& (!ascii_isdigit(*(t + 1)) || fillchar != '-')) {
MB_CHAR2BYTES(fillchar, out_p);
} else {
*out_p++ = *t;
}
}
// }
// For left-aligned items, fill any remaining space with the fillchar
for (; l < minwid && out_p < out_end_p; l++) {
*out_p++ = fillchar;
MB_CHAR2BYTES(fillchar, out_p);
}
// Otherwise if the item is a number, copy that to the output buffer.
@@ -4454,7 +4452,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
// Fill up for half a double-wide character.
while (++width < maxwidth) {
*trunc_p++ = fillchar;
MB_CHAR2BYTES(fillchar, trunc_p);
*trunc_p = NUL;
}
// }
@@ -4505,13 +4503,13 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
standard_spaces * (num_separators - 1);
for (int i = 0; i < num_separators; i++) {
int dislocation = (i == (num_separators - 1))
? final_spaces : standard_spaces;
int dislocation = (i == (num_separators - 1)) ? final_spaces : standard_spaces;
dislocation *= utf_char2len(fillchar);
char_u *start = stl_items[stl_separator_locations[i]].start;
char_u *seploc = start + dislocation;
STRMOVE(seploc, start);
for (char_u *s = start; s < seploc; s++) {
*s = fillchar;
for (char_u *s = start; s < seploc; ) {
MB_CHAR2BYTES(fillchar, s);
}
for (int item_idx = stl_separator_locations[i] + 1;