mirror of https://github.com/neovim/neovim.git
Merge 630990934e
into efb44e0cad
This commit is contained in:
commit
1c2d9e8727
|
@ -95,6 +95,7 @@ CSType init_charsize_arg(CharsizeArg *csarg, win_T *wp, linenr_T lnum, char *lin
|
|||
csarg->virt_row = -1;
|
||||
csarg->indent_width = INT_MIN;
|
||||
csarg->use_tabstop = !wp->w_p_list || wp->w_p_lcs_chars.tab1;
|
||||
csarg->lbr_skip_count = -1;
|
||||
|
||||
if (lnum > 0) {
|
||||
if (marktree_itr_get_filter(wp->w_buffer->b_marktree, lnum - 1, 0, lnum, 0,
|
||||
|
@ -283,46 +284,98 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
|
|||
}
|
||||
|
||||
bool need_lbr = false;
|
||||
// If 'linebreak' set check at a blank before a non-blank if the line
|
||||
// needs a break here.
|
||||
if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width_inner != 0
|
||||
&& vim_isbreak((uint8_t)cur[0]) && !vim_isbreak((uint8_t)cur[1])) {
|
||||
char *t = csarg->line;
|
||||
while (vim_isbreak((uint8_t)t[0])) {
|
||||
t++;
|
||||
if (wp->w_p_wrap && wp->w_p_lbr && wp->w_width_inner != 0) {
|
||||
// note: cur[1] may be a part of current char.
|
||||
need_lbr = vim_isbreak((uint8_t)cur[0]) && !vim_isbreak((uint8_t)cur[1]);
|
||||
|
||||
// Determine if a line break should be skipped.
|
||||
// If the line starts with 'breakat' characters
|
||||
// then the first line break is skipped.
|
||||
if (csarg->lbr_skip_count < 0) {
|
||||
if (EXPECT(cur == csarg->line, true)) {
|
||||
// If iterating from the start of the line,
|
||||
// the first time a possible linebreak position is encountered
|
||||
// would be the first such position for the entire line.
|
||||
csarg->lbr_skip_count = vim_isbreak((uint8_t)cur[0]) ? 1 : 0;
|
||||
} else if (need_lbr) {
|
||||
// CharsizeArg is initialized in the middle of the line.
|
||||
// Need to scan the line from the start to find if there was a
|
||||
// possible linebreak position before this one.
|
||||
char *first_word = csarg->line;
|
||||
while (vim_isbreak((uint8_t)(*first_word))) {
|
||||
first_word++;
|
||||
}
|
||||
csarg->lbr_skip_count = cur < first_word ? 1 : 0;
|
||||
}
|
||||
}
|
||||
// 'linebreak' is only needed when not in leading whitespace.
|
||||
need_lbr = cur >= t;
|
||||
}
|
||||
if (need_lbr) {
|
||||
char *s = cur;
|
||||
// Count all characters from first non-blank after a blank up to next
|
||||
// non-blank after a blank.
|
||||
int numberextra = win_col_off(wp);
|
||||
colnr_T col_adj = size - 1;
|
||||
colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj);
|
||||
if (vcol >= colmax) {
|
||||
colmax += col_adj;
|
||||
int n = colmax + win_col_off2(wp);
|
||||
if (n > 0) {
|
||||
colmax += (((vcol - colmax) / n) + 1) * n - col_adj;
|
||||
|
||||
if (need_lbr && csarg->lbr_skip_count > 0) {
|
||||
csarg->lbr_skip_count--;
|
||||
} else if (need_lbr) {
|
||||
int const width = wp->w_width_inner - win_col_off(wp);
|
||||
int const width2 = width + win_col_off2(wp);
|
||||
|
||||
int cur_vcol = vcol + size; // start of the word (next character)
|
||||
|
||||
bool can_break;
|
||||
int colmax;
|
||||
if (width <= 0 || cur_vcol == width) {
|
||||
can_break = false;
|
||||
} else if (cur_vcol < width) {
|
||||
can_break = true;
|
||||
colmax = width;
|
||||
} else {
|
||||
assert(width2 > 0); // win_col__off2() >= 0, width > 0
|
||||
|
||||
int const line_count = (cur_vcol - width) / width2;
|
||||
int const line_vcol = (cur_vcol - width) % width2;
|
||||
if (line_vcol == 0) { // next char is at the start of the line
|
||||
can_break = false;
|
||||
} else {
|
||||
can_break = true;
|
||||
colmax = width + (line_count + 1) * width2;
|
||||
}
|
||||
}
|
||||
|
||||
colnr_T vcol2 = vcol;
|
||||
while (true) {
|
||||
char *ps = s;
|
||||
MB_PTR_ADV(s);
|
||||
int c = (uint8_t)(*s);
|
||||
if (!(c != NUL
|
||||
&& (vim_isbreak(c) || vcol2 == vcol || !vim_isbreak((uint8_t)(*ps))))) {
|
||||
break;
|
||||
if (can_break) {
|
||||
int indent_width = csarg->indent_width;
|
||||
if (indent_width == INT_MIN) {
|
||||
indent_width = 0;
|
||||
if (*sbr != NUL) {
|
||||
indent_width += vim_strsize(sbr);
|
||||
}
|
||||
if (wp->w_p_bri) {
|
||||
indent_width += get_breakindent_win(wp, line);
|
||||
}
|
||||
csarg->indent_width = indent_width;
|
||||
}
|
||||
|
||||
vcol2 += win_chartabsize(wp, s, vcol2);
|
||||
if (vcol2 >= colmax) { // doesn't fit
|
||||
size = colmax - vcol + col_adj;
|
||||
break;
|
||||
can_break = (width2 - indent_width) > (colmax - cur_vcol);
|
||||
}
|
||||
|
||||
if (can_break) {
|
||||
int const start_vcol = cur_vcol;
|
||||
bool const tabstop = csarg->use_tabstop;
|
||||
|
||||
StrCharInfo sci = utf_ptr2StrCharInfo(cur);
|
||||
bool prev_break = true;
|
||||
|
||||
// Count all characters from first non-blank after a blank up to next
|
||||
// non-blank after a blank.
|
||||
// note: doesn't consider inline virtual text
|
||||
while (true) {
|
||||
sci = utfc_next(sci);
|
||||
bool const cur_break = vim_isbreak((uint8_t)(*sci.ptr));
|
||||
if (*sci.ptr == NUL || (prev_break && !cur_break && cur_vcol != start_vcol)) {
|
||||
break;
|
||||
}
|
||||
prev_break = cur_break;
|
||||
cur_vcol += charsize_nowrap(buf, tabstop, cur_vcol, sci.chr.value);
|
||||
if (cur_vcol > colmax) {
|
||||
size = colmax - vcol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +383,19 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco
|
|||
return (CharSize){ .width = size, .head = head };
|
||||
}
|
||||
|
||||
/// Return the number of cells the cur_char will take on the screen.
|
||||
int charsize_nowrap(buf_T *buf, bool use_tabstop, int vcol, int32_t cur_char)
|
||||
FUNC_ATTR_PURE
|
||||
{
|
||||
if (cur_char == TAB && use_tabstop) {
|
||||
return tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array);
|
||||
} else if (cur_char < 0) {
|
||||
return kInvalidByteCells;
|
||||
} else {
|
||||
return char2cells(cur_char);
|
||||
}
|
||||
}
|
||||
|
||||
/// Like charsize_regular(), except it doesn't handle inline virtual text,
|
||||
/// 'linebreak', 'breakindent' or 'showbreak'.
|
||||
/// Handles normal characters, tabs and wrapping.
|
||||
|
|
|
@ -21,6 +21,7 @@ typedef struct {
|
|||
char *line; ///< Start of the line.
|
||||
|
||||
bool use_tabstop; ///< Use 'tabstop' instead of char2cells() for a TAB.
|
||||
int8_t lbr_skip_count; ///< Positive - skip next n line breaks, negative - not calculated.
|
||||
int indent_width; ///< Width of 'showbreak' and 'breakindent' on wrapped
|
||||
///< parts of lines, INT_MIN if not yet calculated.
|
||||
|
||||
|
|
|
@ -142,10 +142,10 @@ describe('listlbr', function()
|
|||
abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP
|
||||
|
||||
Test 1: set linebreak
|
||||
abcdef
|
||||
+hijklmn
|
||||
abcdef hijklmn
|
||||
+pqrstuvwxyz_1060ABC
|
||||
+DEFGHIJKLMNOP
|
||||
~
|
||||
|
||||
Test 2: set linebreak + set list
|
||||
^Iabcdef hijklmn^I
|
||||
|
@ -154,10 +154,10 @@ describe('listlbr', function()
|
|||
|
||||
|
||||
Test 3: set linebreak nolist
|
||||
abcdef
|
||||
+hijklmn
|
||||
abcdef hijklmn
|
||||
+pqrstuvwxyz_1060ABC
|
||||
+DEFGHIJKLMNOP
|
||||
|
||||
1 aaaaaaaaaaaaaaaaaa
|
||||
|
||||
Test 4: set linebreak with tab and 1 line as long as screen: should break!
|
||||
|
|
|
@ -157,10 +157,10 @@ describe('linebreak', function()
|
|||
abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP
|
||||
|
||||
Test 1: set linebreak + set list + fancy listchars
|
||||
▕———abcdef
|
||||
+hijklmn▕———
|
||||
▕———abcdef hijklmn▕—
|
||||
+pqrstuvwxyz␣1060ABC
|
||||
+DEFGHIJKLMNOPˑ¶
|
||||
~
|
||||
|
||||
Test 2: set nolinebreak list
|
||||
▕———abcdef hijklmn▕—
|
||||
|
|
|
@ -33,10 +33,10 @@ func Test_set_linebreak()
|
|||
call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ " abcdef ",
|
||||
\ "+hijklmn ",
|
||||
\ " abcdef hijklmn ",
|
||||
\ "+pqrstuvwxyz_1060ABC",
|
||||
\ "+DEFGHIJKLMNOP ",
|
||||
\ "~ ",
|
||||
\ ]
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
@ -64,10 +64,10 @@ func Test_linebreak_with_nolist()
|
|||
call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ " abcdef ",
|
||||
\ "+hijklmn ",
|
||||
\ " abcdef hijklmn ",
|
||||
\ "+pqrstuvwxyz_1060ABC",
|
||||
\ "+DEFGHIJKLMNOP ",
|
||||
\ "~ ",
|
||||
\ ]
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
@ -373,19 +373,95 @@ func Test_ctrl_char_on_wrap_column()
|
|||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
func Test_linebreak_no_break_after_whitespace_only()
|
||||
func Test_linebreak_break_after_whitespace()
|
||||
call s:test_windows('setl ts=4 linebreak wrap')
|
||||
call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ " abcdefghijklmn",
|
||||
\ "opqrstuvwxyzabcdefgh",
|
||||
\ "ijklmnopqrstuvwxyz ",
|
||||
\ "~ ",
|
||||
\ ]
|
||||
\ ">---.abcdefghijklmno",
|
||||
\ 'pqrstuvwxyzabcdefghi',
|
||||
\ "jklmnopqrstuvwxyz ",
|
||||
\ "~ "]
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
func Test_linebreak_with_breakindent()
|
||||
call s:test_windows('setl ts=4 breakindent briopt=min:15 sbr=>>')
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "\t a bcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ ">---.a.bcdefghijklmn",
|
||||
\ " >>opqrstuvwxyza",
|
||||
\ " >>bcdefghijklmn",
|
||||
\ " >>opqrstuvwxyz "]
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
||||
call s:test_windows('setl ts=4 breakindent briopt=min:16 sbr=>>')
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "\t a bcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ ">---.a. ",
|
||||
\ " >>bcdefghijklmno",
|
||||
\ " >>pqrstuvwxyzabc",
|
||||
\ " >>defghijklmnopq"]
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
func Test_linebreak_with_showbreak()
|
||||
call s:test_windows('setl ts=4 linebreak showbreak=123456 wrap')
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ '!@#$.abcdefghijklmno',
|
||||
\ '123456pqrstuvwxyzabc',
|
||||
\ '123456defghijklmnopq',
|
||||
\ '123456rstuvwxyz ']
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
||||
call s:test_windows('setl ts=4 linebreak showbreak=12345 wrap')
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ '!@#$.abcdefghijklmno',
|
||||
\ '12345pqrstuvwxyzabcd',
|
||||
\ '12345efghijklmnopqrs',
|
||||
\ '12345tuvwxyz ']
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
||||
call s:test_windows('setl ts=4 linebreak showbreak=1234 wrap')
|
||||
setl list listchars=tab:>-,space:.
|
||||
call setline(1, "!@#$ abcdefghijklmnopqrstuvwxyz" ..
|
||||
\ "abcdefghijklmnopqrstuvwxyz")
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ '!@#$. ',
|
||||
\ '1234abcdefghijklmnop',
|
||||
\ '1234qrstuvwxyzabcdef',
|
||||
\ '1234ghijklmnopqrstuv']
|
||||
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
|
|
@ -47,10 +47,10 @@ func Test_linebreak_with_fancy_listchars()
|
|||
redraw!
|
||||
let lines = s:screen_lines([1, 4], winwidth(0))
|
||||
let expect = [
|
||||
\ "▕———abcdef ",
|
||||
\ "+hijklmn▕——— ",
|
||||
\ "▕———abcdef hijklmn▕—",
|
||||
\ "+pqrstuvwxyz␣1060ABC",
|
||||
\ "+DEFGHIJKLMNOPˑ¶ ",
|
||||
\ "~ ",
|
||||
\ ]
|
||||
call s:compare_lines(expect, lines)
|
||||
call s:close_windows()
|
||||
|
|
|
@ -294,14 +294,14 @@ func Test_vartabs_linebreak()
|
|||
call setline(1, "\tx\tx\tx\tx")
|
||||
|
||||
let expect = [' x ',
|
||||
\ 'x x ',
|
||||
\ 'x ']
|
||||
\ 'x ',
|
||||
\ 'x x ']
|
||||
let lines = ScreenLines([1, 3], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
setl list listchars=tab:>-
|
||||
let expect = ['>---------x>------------------ ',
|
||||
\ 'x>------------------x>------------------',
|
||||
\ 'x ']
|
||||
\ 'x>------------------ ',
|
||||
\ 'x>------------------x ']
|
||||
let lines = ScreenLines([1, 3], winwidth(0))
|
||||
call s:compare_lines(expect, lines)
|
||||
setl linebreak vartabstop=40
|
||||
|
|
Loading…
Reference in New Issue