Merge pull request #17113 from zeertzjq/vim-8.2.2569

feat(statusline): support multibyte fillchar
This commit is contained in:
zeertzjq
2022-02-01 17:57:01 +08:00
committed by GitHub
8 changed files with 152 additions and 91 deletions

View File

@@ -2462,7 +2462,8 @@ A jump table for the options with a short description can be found at |Q_op|.
< This is similar to the default, except that these characters will also < This is similar to the default, except that these characters will also
be used when there is highlighting. be used when there is highlighting.
for "stl" and "stlnc" only single-byte values are supported. For "stl" and "stlnc" single-byte and multibyte characters are
supported. But double-width characters are not supported.
The highlighting used for these items: The highlighting used for these items:
item highlight group ~ item highlight group ~

View File

@@ -19,6 +19,7 @@
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/buffer.h" #include "nvim/buffer.h"
#include "nvim/buffer_defs.h" #include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/context.h" #include "nvim/context.h"
#include "nvim/decoration.h" #include "nvim/decoration.h"
#include "nvim/edit.h" #include "nvim/edit.h"
@@ -2236,7 +2237,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
Dictionary result = ARRAY_DICT_INIT; Dictionary result = ARRAY_DICT_INIT;
int maxwidth; int maxwidth;
char fillchar = 0; int fillchar = 0;
Window window = 0; Window window = 0;
bool use_tabline = false; bool use_tabline = false;
bool highlights = false; bool highlights = false;
@@ -2251,12 +2252,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
} }
if (HAS_KEY(opts->fillchar)) { if (HAS_KEY(opts->fillchar)) {
if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size > 1) { if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0
api_set_error(err, kErrorTypeValidation, "fillchar must be an ASCII character"); || char2cells(fillchar = utf_ptr2char((char_u *)opts->fillchar.data.string.data)) != 1
|| (size_t)utf_char2len(fillchar) != opts->fillchar.data.string.size) {
api_set_error(err, kErrorTypeValidation, "fillchar must be a single-width character");
return result; return result;
} }
fillchar = opts->fillchar.data.string.data[0];
} }
if (HAS_KEY(opts->highlights)) { if (HAS_KEY(opts->highlights)) {
@@ -2292,7 +2293,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
if (fillchar == 0) { if (fillchar == 0) {
int attr; int attr;
fillchar = (char)fillchar_status(&attr, wp); fillchar = fillchar_status(&attr, wp);
} }
} }
@@ -2320,7 +2321,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
sizeof(buf), sizeof(buf),
(char_u *)str.data, (char_u *)str.data,
false, false,
(char_u)fillchar, fillchar,
maxwidth, maxwidth,
hltab_ptr, hltab_ptr,
NULL); NULL);

View File

@@ -3419,7 +3419,7 @@ typedef enum {
/// ///
/// @return The final width of the statusline /// @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, 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 size_t stl_items_len = 20; // Initial value, grows as needed.
static stl_item_t *stl_items = NULL; static stl_item_t *stl_items = NULL;
@@ -3462,9 +3462,6 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
if (fillchar == 0) { if (fillchar == 0) {
fillchar = ' '; 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 // The cursor in windows other than the current one isn't always
@@ -3662,7 +3659,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; 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 < stl_items[stl_groupitems[groupdepth]].minwid) { while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
*out_p++ = fillchar; MB_CHAR2BYTES(fillchar, out_p);
} }
// } // }
@@ -3685,14 +3682,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) { if (min_group_width < 0) {
min_group_width = 0 - min_group_width; min_group_width = 0 - min_group_width;
while (group_len++ < min_group_width && out_p < out_end_p) { 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 // If the group is right-aligned, shift everything to the right and
// prepend with filler characters. // prepend with filler characters.
} else { } else {
// { Move the group to the right // { 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) * utf_char2len(fillchar);
group_len = min_group_width - group_len; memmove(t + group_len, t, (size_t)(out_p - t));
if (out_p + group_len >= (out_end_p + 1)) { if (out_p + group_len >= (out_end_p + 1)) {
group_len = (long)(out_end_p - out_p); group_len = (long)(out_end_p - out_p);
} }
@@ -3706,7 +3703,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
// Prepend the fill characters // Prepend the fill characters
for (; group_len > 0; group_len--) { for (; group_len > 0; group_len--) {
*t++ = fillchar; MB_CHAR2BYTES(fillchar, t);
} }
} }
} }
@@ -4231,7 +4228,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)) { if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t)) {
*out_p++ = ' '; *out_p++ = ' ';
} else { } else {
*out_p++ = fillchar; MB_CHAR2BYTES(fillchar, out_p);
} }
} }
minwid = 0; minwid = 0;
@@ -4242,20 +4239,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 // { Copy the string text into the output buffer
while (*t && out_p < out_end_p) { for (; *t && out_p < out_end_p; t++) {
*out_p++ = *t++;
// Change a space by fillchar, unless fillchar is '-' and a // Change a space by fillchar, unless fillchar is '-' and a
// digit follows. // digit follows.
if (fillable && out_p[-1] == ' ' if (fillable && *t == ' '
&& (!ascii_isdigit(*t) || fillchar != '-')) { && (!ascii_isdigit(*(t + 1)) || fillchar != '-')) {
out_p[-1] = fillchar; MB_CHAR2BYTES(fillchar, out_p);
} else {
*out_p++ = *t;
} }
} }
// } // }
// For left-aligned items, fill any remaining space with the fillchar // For left-aligned items, fill any remaining space with the fillchar
for (; l < minwid && out_p < out_end_p; l++) { 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. // Otherwise if the item is a number, copy that to the output buffer.
@@ -4448,7 +4446,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. // Fill up for half a double-wide character.
while (++width < maxwidth) { while (++width < maxwidth) {
*trunc_p++ = fillchar; MB_CHAR2BYTES(fillchar, trunc_p);
*trunc_p = NUL; *trunc_p = NUL;
} }
// } // }
@@ -4499,13 +4497,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); standard_spaces * (num_separators - 1);
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; dislocation *= utf_char2len(fillchar);
char_u *start = stl_items[stl_separator_locations[i]].start; char_u *start = stl_items[stl_separator_locations[i]].start;
char_u *seploc = start + dislocation; char_u *seploc = start + dislocation;
STRMOVE(seploc, start); STRMOVE(seploc, start);
for (char_u *s = start; s < seploc; s++) { for (char_u *s = start; s < seploc; ) {
*s = fillchar; MB_CHAR2BYTES(fillchar, s);
} }
for (int item_idx = stl_separator_locations[i] + 1; for (int item_idx = stl_separator_locations[i] + 1;

View File

@@ -105,6 +105,9 @@
#define MB_PTR_BACK(s, p) \ #define MB_PTR_BACK(s, p) \
(p -= utf_head_off((char_u *)s, (char_u *)p - 1) + 1) (p -= utf_head_off((char_u *)s, (char_u *)p - 1) + 1)
// MB_CHAR2BYTES(): convert character to bytes and advance pointer to bytes
#define MB_CHAR2BYTES(c, b) ((b) += utf_char2bytes((c), (b)))
#define RESET_BINDING(wp) \ #define RESET_BINDING(wp) \
do { \ do { \
(wp)->w_p_scb = false; \ (wp)->w_p_scb = false; \

View File

@@ -1981,7 +1981,7 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_
level = foldinfo.fi_level; level = foldinfo.fi_level;
// If the column is too narrow, we start at the lowest level that // If the column is too narrow, we start at the lowest level that
// fits and use numbers to indicated the depth. // fits and use numbers to indicate the depth.
first_level = level - fdc - closed + 1; first_level = level - fdc - closed + 1;
if (first_level < 1) { if (first_level < 1) {
first_level = 1; first_level = 1;

View File

@@ -507,5 +507,20 @@ func Test_statusline_after_split_vsplit()
set ls& stl& set ls& stl&
endfunc endfunc
" Test using a multibyte character for 'stl' and 'stlnc' items in 'fillchars'
" with a custom 'statusline'
func Test_statusline_mbyte_fillchar()
only
set laststatus=2
set fillchars=vert:\|,fold:-,stl:━,stlnc:═
set statusline=a%=b
call assert_match('^a\+━\+b$', s:get_statusline())
vnew
call assert_match('^a\+━\+b━a\+═\+b$', s:get_statusline())
wincmd w
call assert_match('^a\+═\+b═a\+━\+b$', s:get_statusline())
set statusline& fillchars& laststatus&
%bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -2551,6 +2551,34 @@ describe('API', function()
'Should be truncated%<', 'Should be truncated%<',
{ maxwidth = 15 })) { maxwidth = 15 }))
end) end)
it('supports ASCII fillchar', function()
eq({ str = 'a~~~b', width = 5 },
meths.eval_statusline('a%=b', { fillchar = '~', maxwidth = 5 }))
end)
it('supports single-width multibyte fillchar', function()
eq({ str = 'a━━━b', width = 5 },
meths.eval_statusline('a%=b', { fillchar = '', maxwidth = 5 }))
end)
it('rejects double-width fillchar', function()
eq('fillchar must be a single-width character',
pcall_err(meths.eval_statusline, '', { fillchar = '' }))
end)
it('rejects control character fillchar', function()
eq('fillchar must be a single-width character',
pcall_err(meths.eval_statusline, '', { fillchar = '\a' }))
end)
it('rejects multiple-character fillchar', function()
eq('fillchar must be a single-width character',
pcall_err(meths.eval_statusline, '', { fillchar = 'aa' }))
end)
it('rejects empty string fillchar', function()
eq('fillchar must be a single-width character',
pcall_err(meths.eval_statusline, '', { fillchar = '' }))
end)
it('rejects non-string fillchar', function()
eq('fillchar must be a single-width character',
pcall_err(meths.eval_statusline, '', { fillchar = 1 }))
end)
describe('highlight parsing', function() describe('highlight parsing', function()
it('works', function() it('works', function()
eq({ eq({

View File

@@ -249,7 +249,7 @@ describe('buffer functions', function()
-- --
-- @param arg Options can be placed in an optional dictionary as the last parameter -- @param arg Options can be placed in an optional dictionary as the last parameter
-- .expected_cell_count The expected number of cells build_stl_str_hl will return -- .expected_cell_count The expected number of cells build_stl_str_hl will return
-- .expected_byte_length The expected byte length of the string -- .expected_byte_length The expected byte length of the string (defaults to byte length of expected_stl)
-- .file_name The name of the file to be tested (useful in %f type tests) -- .file_name The name of the file to be tested (useful in %f type tests)
-- .fillchar The character that will be used to fill any 'extra' space in the stl -- .fillchar The character that will be used to fill any 'extra' space in the stl
local function statusline_test (description, local function statusline_test (description,
@@ -264,7 +264,7 @@ describe('buffer functions', function()
local fillchar = option.fillchar or (' '):byte() local fillchar = option.fillchar or (' '):byte()
local expected_cell_count = option.expected_cell_count or statusline_cell_count local expected_cell_count = option.expected_cell_count or statusline_cell_count
local expected_byte_length = option.expected_byte_length or expected_cell_count local expected_byte_length = option.expected_byte_length or #expected_stl
itp(description, function() itp(description, function()
if option.file_name then if option.file_name then
@@ -312,12 +312,12 @@ describe('buffer functions', function()
statusline_test('should put fillchar `~` in between text', 10, statusline_test('should put fillchar `~` in between text', 10,
'abc%=def', 'abc~~~~def', 'abc%=def', 'abc~~~~def',
{fillchar=('~'):byte()}) {fillchar=('~'):byte()})
statusline_test('should put fillchar `━` in between text', 10,
'abc%=def', 'abc━━━━def',
{fillchar=0x2501})
statusline_test('should handle zero-fillchar as a space', 10, statusline_test('should handle zero-fillchar as a space', 10,
'abcde%=', 'abcde ', 'abcde%=', 'abcde ',
{fillchar=0}) {fillchar=0})
statusline_test('should handle multibyte-fillchar as a dash', 10,
'abcde%=', 'abcde-----',
{fillchar=0x80})
statusline_test('should print the tail file name', 80, statusline_test('should print the tail file name', 80,
'%t', 'buffer_spec.lua', '%t', 'buffer_spec.lua',
{file_name='test/unit/buffer_spec.lua', expected_cell_count=15}) {file_name='test/unit/buffer_spec.lua', expected_cell_count=15})
@@ -366,70 +366,86 @@ describe('buffer functions', function()
statusline_test('should ignore trailing %', 3, 'abc%', 'abc') statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
-- alignment testing -- alignment testing with fillchar
statusline_test('should right align when using =', 20, local function statusline_test_align (description,
'neo%=vim', 'neo vim') statusline_cell_count,
statusline_test('should, when possible, center text when using %=text%=', 20, input_stl,
'abc%=neovim%=def', 'abc neovim def') expected_stl,
statusline_test('should handle uneven spacing in the buffer when using %=text%=', 20, arg)
'abc%=neo_vim%=def', 'abc neo_vim def') arg = arg or {}
statusline_test('should have equal spaces even with non-equal sides when using =', 20, statusline_test(description .. ' without fillchar',
'foobar%=test%=baz', 'foobar test baz') statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg)
statusline_test('should have equal spaces even with longer right side when using =', 20, arg.fillchar = ('!'):byte()
'a%=test%=longtext', 'a test longtext') statusline_test(description .. ' with fillchar `!`',
statusline_test('should handle an empty left side when using ==', 20, statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg)
'%=test%=baz', ' test baz') arg.fillchar = 0x2501
statusline_test('should handle an empty right side when using ==', 20, statusline_test(description .. ' with fillchar `━`',
'foobar%=test%=', 'foobar test ') statusline_cell_count, input_stl, expected_stl:gsub('%~', ''), arg)
statusline_test('should handle consecutive empty ==', 20, end
'%=%=test%=', ' test ')
statusline_test('should handle an = alone', 20,
'%=', ' ')
statusline_test('should right align text when it is alone with =', 20,
'%=foo', ' foo')
statusline_test('should left align text when it is alone with =', 20,
'foo%=', 'foo ')
statusline_test('should approximately center text when using %=text%=', 21, statusline_test_align('should right align when using =', 20,
'abc%=neovim%=def', 'abc neovim def') 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
statusline_test('should completely fill the buffer when using %=text%=', 21, statusline_test_align('should, when possible, center text when using %=text%=', 20,
'abc%=neo_vim%=def', 'abc neo_vim def') 'abc%=neovim%=def', 'abc~~~~neovim~~~~def')
statusline_test('should have equal spaces even with non-equal sides when using =', 21, statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20,
'foobar%=test%=baz', 'foobar test baz') 'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def')
statusline_test('should have equal spaces even with longer right side when using =', 21, statusline_test_align('should have equal spaces even with non-equal sides when using =', 20,
'a%=test%=longtext', 'a test longtext') 'foobar%=test%=baz', 'foobar~~~test~~~~baz')
statusline_test('should handle an empty left side when using ==', 21, statusline_test_align('should have equal spaces even with longer right side when using =', 20,
'%=test%=baz', ' test baz') 'a%=test%=longtext', 'a~~~test~~~~longtext')
statusline_test('should handle an empty right side when using ==', 21, statusline_test_align('should handle an empty left side when using ==', 20,
'foobar%=test%=', 'foobar test ') '%=test%=baz', '~~~~~~test~~~~~~~baz')
statusline_test_align('should handle an empty right side when using ==', 20,
'foobar%=test%=', 'foobar~~~~~test~~~~~')
statusline_test_align('should handle consecutive empty ==', 20,
'%=%=test%=', '~~~~~~~~~~test~~~~~~')
statusline_test_align('should handle an = alone', 20,
'%=', '~~~~~~~~~~~~~~~~~~~~')
statusline_test_align('should right align text when it is alone with =', 20,
'%=foo', '~~~~~~~~~~~~~~~~~foo')
statusline_test_align('should left align text when it is alone with =', 20,
'foo%=', 'foo~~~~~~~~~~~~~~~~~')
statusline_test('should quadrant the text when using 3 %=', 40, statusline_test_align('should approximately center text when using %=text%=', 21,
'abcd%=n%=eovim%=ef', 'abcd n eovim ef') 'abc%=neovim%=def', 'abc~~~~neovim~~~~~def')
statusline_test('should work well with %t', 40, statusline_test_align('should completely fill the buffer when using %=text%=', 21,
'%t%=right_aligned', 'buffer_spec.lua right_aligned', 'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def')
statusline_test_align('should have equal spacing even with non-equal sides when using =', 21,
'foobar%=test%=baz', 'foobar~~~~test~~~~baz')
statusline_test_align('should have equal spacing even with longer right side when using =', 21,
'a%=test%=longtext', 'a~~~~test~~~~longtext')
statusline_test_align('should handle an empty left side when using ==', 21,
'%=test%=baz', '~~~~~~~test~~~~~~~baz')
statusline_test_align('should handle an empty right side when using ==', 21,
'foobar%=test%=', 'foobar~~~~~test~~~~~~')
statusline_test_align('should quadrant the text when using 3 %=', 40,
'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef')
statusline_test_align('should work well with %t', 40,
'%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should work well with %t and regular text', 40, statusline_test_align('should work well with %t and regular text', 40,
'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r', 'l%=m_l %t m_r%=r', 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should work well with %=, %t, %L, and %l', 40, statusline_test_align('should work well with %=, %t, %L, and %l', 40,
'%t %= %L %= %l', 'buffer_spec.lua 1 0', '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should quadrant the text when using 3 %=', 41, statusline_test_align('should quadrant the text when using 3 %=', 41,
'abcd%=n%=eovim%=ef', 'abcd n eovim ef') 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef')
statusline_test('should work well with %t', 41, statusline_test_align('should work well with %t', 41,
'%t%=right_aligned', 'buffer_spec.lua right_aligned', '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should work well with %t and regular text', 41, statusline_test_align('should work well with %t and regular text', 41,
'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r', 'l%=m_l %t m_r%=r', 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should work well with %=, %t, %L, and %l', 41, statusline_test_align('should work well with %=, %t, %L, and %l', 41,
'%t %= %L %= %l', 'buffer_spec.lua 1 0', '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
{file_name='test/unit/buffer_spec.lua'}) {file_name='test/unit/buffer_spec.lua'})
statusline_test('should work with 10 %=', 50, statusline_test_align('should work with 10 %=', 50,
'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')
-- stl item testing -- stl item testing
local tabline = '' local tabline = ''
@@ -452,11 +468,10 @@ describe('buffer functions', function()
-- multi-byte testing -- multi-byte testing
statusline_test('should handle multibyte characters', 10, statusline_test('should handle multibyte characters', 10,
'Ĉ%=x', 'Ĉ x', 'Ĉ%=x', 'Ĉ x')
{expected_byte_length=11})
statusline_test('should handle multibyte characters and different fillchars', 10, statusline_test('should handle multibyte characters and different fillchars', 10,
'Ą%=mid%=end', 'Ą@mid@@end', 'Ą%=mid%=end', 'Ą@mid@@end',
{fillchar=('@'):byte(), expected_byte_length=11}) {fillchar=('@'):byte()})
-- escaping % testing -- escaping % testing
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%') statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')