diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2014-08-20 12:24:34 -0400 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2014-08-20 12:24:34 -0400 |
commit | 118a31c24c7ce76da909026cd10a94feb88803bc (patch) | |
tree | 8bbd708d924ef68017949e4bf9b773d5d833b82d | |
parent | bbefc73c553d681f78f40df9d97ec89ae9b06520 (diff) | |
parent | 3b0f7fe59392138c886063b09e3cf41b25d53056 (diff) | |
download | rneovim-118a31c24c7ce76da909026cd10a94feb88803bc.tar.gz rneovim-118a31c24c7ce76da909026cd10a94feb88803bc.tar.bz2 rneovim-118a31c24c7ce76da909026cd10a94feb88803bc.zip |
Merge pull request #691 from fmoralesc/master
Port vim's breakindent patch to neovim's codebase. (vim patches 7.4.338, 7.4.346, 7.4.352, 7.4.353, 7.4.370, 7.4.371, 7.4.388)
-rw-r--r-- | src/nvim/buffer_defs.h | 7 | ||||
-rw-r--r-- | src/nvim/charset.c | 70 | ||||
-rw-r--r-- | src/nvim/cursor.c | 2 | ||||
-rw-r--r-- | src/nvim/edit.c | 22 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 8 | ||||
-rw-r--r-- | src/nvim/getchar.c | 2 | ||||
-rw-r--r-- | src/nvim/indent.c | 75 | ||||
-rw-r--r-- | src/nvim/misc1.c | 11 | ||||
-rw-r--r-- | src/nvim/ops.c | 20 | ||||
-rw-r--r-- | src/nvim/option.c | 64 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/screen.c | 109 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.in | 79 | ||||
-rw-r--r-- | src/nvim/testdir/test_breakindent.ok | 55 | ||||
-rw-r--r-- | src/nvim/testdir/test_listlbr.in | 52 | ||||
-rw-r--r-- | src/nvim/testdir/test_listlbr.ok | 27 | ||||
-rw-r--r-- | src/nvim/testdir/test_listlbr_utf8.in | 52 | ||||
-rw-r--r-- | src/nvim/testdir/test_listlbr_utf8.ok | 21 | ||||
-rw-r--r-- | src/nvim/version.c | 14 |
20 files changed, 613 insertions, 85 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 9f5d7b86eb..4162df63ab 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -136,6 +136,10 @@ struct buffheader { typedef struct { int wo_arab; # define w_p_arab w_onebuf_opt.wo_arab /* 'arabic' */ + int wo_bri; +# define w_p_bri w_onebuf_opt.wo_bri /* 'breakindent' */ + char_u *wo_briopt; +# define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */ int wo_diff; # define w_p_diff w_onebuf_opt.wo_diff /* 'diff' */ long wo_fdc; @@ -1069,6 +1073,9 @@ struct window_S { long_u w_p_fde_flags; /* flags for 'foldexpr' */ long_u w_p_fdt_flags; /* flags for 'foldtext' */ int *w_p_cc_cols; /* array of columns to highlight or NULL */ + int w_p_brimin; /* minimum width for breakindent */ + int w_p_brishift; /* additional shift for breakindent */ + bool w_p_brisbr; /* sbr in 'briopt' */ /* transform a pointer to a "onebuf" option into a "allbuf" option */ #define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T)) diff --git a/src/nvim/charset.c b/src/nvim/charset.c index baf6895b4c..57c4aec395 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -13,6 +13,7 @@ #include "nvim/charset.h" #include "nvim/farsi.h" #include "nvim/func_attr.h" +#include "nvim/indent.h" #include "nvim/main.h" #include "nvim/mbyte.h" #include "nvim/memline.h" @@ -775,9 +776,10 @@ int linetabsize(char_u *s) int linetabsize_col(int startcol, char_u *s) { colnr_T col = startcol; + char_u *line = s; /* pointer to start of line, for breakindent */ while (*s != NUL) { - col += lbr_chartabsize_adv(&s, col); + col += lbr_chartabsize_adv(line, &s, col); } return (int)col; } @@ -785,17 +787,17 @@ int linetabsize_col(int startcol, char_u *s) /// Like linetabsize(), but for a given window instead of the current one. /// /// @param wp -/// @param p +/// @param line /// @param len /// /// @return Number of characters the string will take on the screen. -int win_linetabsize(win_T *wp, char_u *p, colnr_T len) +int win_linetabsize(win_T *wp, char_u *line, colnr_T len) { colnr_T col = 0; char_u *s; - for (s = p; *s != NUL && (len == MAXCOL || s < p + len); mb_ptr_adv(s)) { - col += win_lbr_chartabsize(wp, s, col, NULL); + for (s = line; *s != NUL && (len == MAXCOL || s < line + len); mb_ptr_adv(s)) { + col += win_lbr_chartabsize(wp, line, s, col, NULL); } return (int)col; } @@ -922,32 +924,34 @@ int vim_isprintc_strict(int c) /// like chartabsize(), but also check for line breaks on the screen /// +/// @param line /// @param s /// @param col /// /// @return The number of characters taken up on the screen. -int lbr_chartabsize(unsigned char *s, colnr_T col) +int lbr_chartabsize(char_u *line, unsigned char *s, colnr_T col) { - if (!curwin->w_p_lbr && (*p_sbr == NUL)) { + if (!curwin->w_p_lbr && (*p_sbr == NUL) && !curwin->w_p_bri) { if (curwin->w_p_wrap) { return win_nolbr_chartabsize(curwin, s, col, NULL); } RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col) } - return win_lbr_chartabsize(curwin, s, col, NULL); + return win_lbr_chartabsize(curwin, line == NULL ? s: line, s, col, NULL); } /// Call lbr_chartabsize() and advance the pointer. /// +/// @param line /// @param s /// @param col /// /// @return The number of characters take up on the screen. -int lbr_chartabsize_adv(char_u **s, colnr_T col) +int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col) { int retval; - retval = lbr_chartabsize(*s, col); + retval = lbr_chartabsize(line, *s, col); mb_ptr_adv(*s); return retval; } @@ -959,14 +963,16 @@ int lbr_chartabsize_adv(char_u **s, colnr_T col) /// value, init to 0 before calling. /// /// @param wp +/// @param line /// @param s /// @param col /// @param headp /// /// @return The number of characters taken up on the screen. -int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) +int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp) { colnr_T col2; + colnr_T col_adj = 0; /* col + screen size of tab */ colnr_T colmax; int added; int mb_added = 0; @@ -975,8 +981,8 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) int tab_corr = (*s == TAB); int n; - // No 'linebreak' and 'showbreak': return quickly. - if (!wp->w_p_lbr && (*p_sbr == NUL)) { + // No 'linebreak', 'showbreak' and 'breakindent': return quickly. + if (!wp->w_p_lbr && !wp->w_p_bri && (*p_sbr == NUL)) { if (wp->w_p_wrap) { return win_nolbr_chartabsize(wp, s, col, headp); } @@ -986,26 +992,29 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) // First get normal size, without 'linebreak' int size = win_chartabsize(wp, s, col); int c = *s; + if (tab_corr) { + col_adj = size - 1; + } // If 'linebreak' set check at a blank before a non-blank if the line // needs a break here if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(s[1]) - && !wp->w_p_list && wp->w_p_wrap && (wp->w_width != 0)) { // Count all characters from first non-blank after a blank up to next // non-blank after a blank. numberextra = win_col_off(wp); col2 = col; - colmax = (colnr_T)(wp->w_width - numberextra); + colmax = (colnr_T)(wp->w_width - numberextra - col_adj); if (col >= colmax) { - n = colmax + win_col_off2(wp); + colmax += col_adj; + n = colmax + win_col_off2(wp); if (n > 0) { - colmax += (((col - colmax) / n) + 1) * n; + colmax += (((col - colmax) / n) + 1) * n - col_adj; } } @@ -1024,7 +1033,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) col2 += win_chartabsize(wp, s, col2); if (col2 >= colmax) { /* doesn't fit */ - size = colmax - col; + size = colmax - col + col_adj; tab_corr = FALSE; break; } @@ -1039,11 +1048,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) mb_added = 1; } - // May have to add something for 'showbreak' string at start of line + // May have to add something for 'breakindent' and/or 'showbreak' + // string at start of line. // Set *headp to the size of what we add. added = 0; - if ((*p_sbr != NUL) && wp->w_p_wrap && (col != 0)) { + if ((*p_sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && (col != 0)) { numberextra = win_col_off(wp); col += numberextra + mb_added; @@ -1056,7 +1066,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) } if ((col == 0) || (col + size > (colnr_T)wp->w_width)) { - added = vim_strsize(p_sbr); + added = 0; + if (*p_sbr != NUL) + added += vim_strsize(p_sbr); + if (wp->w_p_bri) + added += get_breakindent_win(wp, line); + if (tab_corr) { size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts; } else { @@ -1157,13 +1172,14 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T vcol; char_u *ptr; // points to current char char_u *posptr; // points to char at pos->col + char_u *line; // start of the line int incr; int head; int ts = wp->w_buffer->b_p_ts; int c; vcol = 0; - ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); + line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE); if (pos->col == MAXCOL) { // continue until the NUL @@ -1173,11 +1189,13 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, } // This function is used very often, do some speed optimizations. - // When 'list', 'linebreak' and 'showbreak' are not set use a simple loop. - // Also use this when 'list' is set but tabs take their normal size. + // When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set + // use a simple loop. + // Also use this when 'list' is set but tabs take their normal size. if ((!wp->w_p_list || (lcs_tab1 != NUL)) && !wp->w_p_lbr - && (*p_sbr == NUL)) { + && (*p_sbr == NUL) + && !wp->w_p_bri ) { for (;;) { head = 0; c = *ptr; @@ -1229,7 +1247,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, for (;;) { // A tab gets expanded, depending on the current column head = 0; - incr = win_lbr_chartabsize(wp, ptr, vcol, &head); + incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head); // make sure we don't go past the end of the line if (*ptr == NUL) { diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 64a3b73f15..cd84d7014c 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -138,7 +138,7 @@ static int coladvance2( ptr = line; while (col <= wcol && *ptr != NUL) { /* Count a tab for what it's worth (if list mode not on) */ - csize = win_lbr_chartabsize(curwin, ptr, col, &head); + csize = win_lbr_chartabsize(curwin, line, ptr, col, &head); mb_ptr_adv(ptr); col += csize; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 93e127394b..6158176e56 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1551,7 +1551,7 @@ change_indent ( new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col); else ++new_cursor_col; - vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol); + vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol); } vcol = last_vcol; @@ -5898,9 +5898,11 @@ int oneleft(void) width = 1; for (;; ) { coladvance(v - width); - /* getviscol() is slow, skip it when 'showbreak' is empty and - * there are no multi-byte characters */ + /* getviscol() is slow, skip it when 'showbreak' is empty, + 'breakindent' is not set and there are no multi-byte + characters */ if ((*p_sbr == NUL + && !curwin->w_p_bri && !has_mbyte ) || getviscol() < v) break; @@ -7914,10 +7916,10 @@ static int ins_tab(void) getvcol(curwin, &fpos, &vcol, NULL, NULL); getvcol(curwin, cursor, &want_vcol, NULL, NULL); - /* Use as many TABs as possible. Beware of 'showbreak' and - * 'linebreak' adding extra virtual columns. */ + /* Use as many TABs as possible. Beware of 'breakindent', 'showbreak' + and 'linebreak' adding extra virtual columns. */ while (vim_iswhite(*ptr)) { - i = lbr_chartabsize((char_u *)"\t", vcol); + i = lbr_chartabsize(NULL, (char_u *)"\t", vcol); if (vcol + i > want_vcol) break; if (*ptr != TAB) { @@ -7936,10 +7938,11 @@ static int ins_tab(void) if (change_col >= 0) { int repl_off = 0; + char_u *line = ptr; /* Skip over the spaces we need. */ while (vcol < want_vcol && *ptr == ' ') { - vcol += lbr_chartabsize(ptr, vcol); + vcol += lbr_chartabsize(line, ptr, vcol); ++ptr; ++repl_off; } @@ -8126,6 +8129,7 @@ int ins_copychar(linenr_T lnum) int c; int temp; char_u *ptr, *prev_ptr; + char_u *line; if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { vim_beep(); @@ -8134,12 +8138,12 @@ int ins_copychar(linenr_T lnum) /* try to advance to the cursor column */ temp = 0; - ptr = ml_get(lnum); + line = ptr = ml_get(lnum); prev_ptr = ptr; validate_virtcol(); while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) { prev_ptr = ptr; - temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp); + temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp); } if ((colnr_T)temp > curwin->w_virtcol) ptr = prev_ptr; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 28048c933c..74f3edc8d9 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1817,10 +1817,10 @@ getexmodeline ( p = (char_u *)line_ga.ga_data; p[line_ga.ga_len] = NUL; - indent = get_indent_str(p, 8); + indent = get_indent_str(p, 8, FALSE); indent += sw - indent % sw; add_indent: - while (get_indent_str(p, 8) < indent) { + while (get_indent_str(p, 8, FALSE) < indent) { char_u *s = skipwhite(p); ga_grow(&line_ga, 1); @@ -1858,11 +1858,11 @@ redraw: p[--line_ga.ga_len] = NUL; } else { p[line_ga.ga_len] = NUL; - indent = get_indent_str(p, 8); + indent = get_indent_str(p, 8, FALSE); --indent; indent -= indent % get_sw_value(curbuf); } - while (get_indent_str(p, 8) > indent) { + while (get_indent_str(p, 8, FALSE) > indent) { char_u *s = skipwhite(p); memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index e98bb2744c..6c772a8a66 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2163,7 +2163,7 @@ static int vgetorpeek(int advance) while (col < curwin->w_cursor.col) { if (!vim_iswhite(ptr[col])) curwin->w_wcol = vcol; - vcol += lbr_chartabsize(ptr + col, + vcol += lbr_chartabsize(ptr, ptr + col, (colnr_T)vcol); if (has_mbyte) col += (*mb_ptr2len)(ptr + col); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index d4c6b36177..9258ee93b6 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -10,8 +10,10 @@ #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/misc2.h" +#include "nvim/move.h" #include "nvim/option.h" #include "nvim/regexp.h" +#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/undo.h" @@ -24,14 +26,14 @@ // Count the size (in window cells) of the indent in the current line. int get_indent(void) { - return get_indent_str(get_cursor_line_ptr(), (int)curbuf->b_p_ts); + return get_indent_str(get_cursor_line_ptr(), (int)curbuf->b_p_ts, false); } // Count the size (in window cells) of the indent in line "lnum". int get_indent_lnum(linenr_T lnum) { - return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts); + return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, false); } @@ -39,20 +41,27 @@ int get_indent_lnum(linenr_T lnum) // "buf". int get_indent_buf(buf_T *buf, linenr_T lnum) { - return get_indent_str(ml_get_buf(buf, lnum, false), (int)buf->b_p_ts); + return get_indent_str(ml_get_buf(buf, lnum, false), (int)buf->b_p_ts, false); } // Count the size (in window cells) of the indent in line "ptr", with // 'tabstop' at "ts". -int get_indent_str(char_u *ptr, int ts) +// If @param list is TRUE, count only screen size for tabs. +int get_indent_str(char_u *ptr, int ts, int list) { int count = 0; for (; *ptr; ++ptr) { // Count a tab for what it is worth. if (*ptr == TAB) { - count += ts - (count % ts); + if (!list || lcs_tab1) { // count a tab for what it is worth + count += ts - (count % ts); + } else { + // in list mode, when tab is not set, count screen char width for Tab: + // ^I + count += ptr2cells(ptr); + } } else if (*ptr == ' ') { // Count a space for one. count++; @@ -433,6 +442,50 @@ int get_number_indent(linenr_T lnum) return (int)col; } +/* + * Return appropriate space number for breakindent, taking influencing + * parameters into account. Window must be specified, since it is not + * necessarily always the current one. + */ +int get_breakindent_win(win_T *wp, char_u *line) { + static int prev_indent = 0; /* cached indent value */ + static int prev_ts = 0L; /* cached tabstop value */ + static char_u *prev_line = NULL; /* cached pointer to line */ + int bri = 0; + /* window width minus window margin space, i.e. what rests for text */ + const int eff_wwidth = wp->w_width + - ((wp->w_p_nu || wp->w_p_rnu) + && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) + ? number_width(wp) + 1 : 0); + + /* used cached indent, unless pointer or 'tabstop' changed */ + if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts) + { + prev_line = line; + prev_ts = wp->w_buffer->b_p_ts; + prev_indent = get_indent_str(line, + (int)wp->w_buffer->b_p_ts, wp->w_p_list); + } + bri = prev_indent + wp->w_p_brishift; + + /* indent minus the length of the showbreak string */ + if (wp->w_p_brisbr) + bri -= vim_strsize(p_sbr); + + /* Add offset for number column, if 'n' is in 'cpoptions' */ + bri += win_col_off2(wp); + + /* never indent past left window margin */ + if (bri < 0) + bri = 0; + /* always leave at least bri_min characters on the left, + * if text width is sufficient */ + else if (bri > eff_wwidth - wp->w_p_brimin) + bri = (eff_wwidth - wp->w_p_brimin < 0) + ? 0 : eff_wwidth - wp->w_p_brimin; + + return bri; +} // When extra == 0: Return true if the cursor is before or on the first // non-blank in the line. @@ -608,10 +661,12 @@ int get_lisp_indent(void) if (vi_lisp && (get_indent() == 0)) { amount = 2; } else { + char_u *line = that; + amount = 0; while (*that && col) { - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); col--; } @@ -628,7 +683,7 @@ int get_lisp_indent(void) firsttry = amount; while (vim_iswhite(*that)) { - amount += lbr_chartabsize(that, (colnr_T)amount); + amount += lbr_chartabsize(line, that, (colnr_T)amount); that++; } @@ -658,15 +713,15 @@ int get_lisp_indent(void) parencount--; } if ((*that == '\\') && (*(that + 1) != NUL)) { - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); } - amount += lbr_chartabsize_adv(&that, (colnr_T)amount); + amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount); } } while (vim_iswhite(*that)) { - amount += lbr_chartabsize(that, (colnr_T)amount); + amount += lbr_chartabsize(line, that, (colnr_T)amount); that++; } diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index f0c4ee492e..986374b352 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -194,7 +194,7 @@ open_line ( /* * count white space on current line */ - newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts); + newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) newindent = second_line_indent; /* for ^^D command in insert mode */ @@ -631,7 +631,7 @@ open_line ( if (curbuf->b_p_ai || do_si ) - newindent = get_indent_str(leader, (int)curbuf->b_p_ts); + newindent = get_indent_str(leader, (int)curbuf->b_p_ts, FALSE); /* Add the indent offset */ if (newindent + off < 0) { @@ -1306,6 +1306,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) char_u *s; int lines = 0; int width; + char_u *line; /* Check for filler lines above this buffer line. When folded the result * is one line anyway. */ @@ -1317,11 +1318,11 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) if (wp->w_width == 0) return lines + 1; - s = ml_get_buf(wp->w_buffer, lnum, FALSE); + line = s = ml_get_buf(wp->w_buffer, lnum, FALSE); col = 0; while (*s != NUL && --column >= 0) { - col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL); + col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL); mb_ptr_adv(s); } @@ -1333,7 +1334,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) * 'ts') -- webb. */ if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1)) - col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1; + col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL) - 1; /* * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc. diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 0bf338947b..0b0a913a95 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -350,7 +350,8 @@ static void shift_block(oparg_T *oap, int amount) ++bd.textstart; } for (; vim_iswhite(*bd.textstart); ) { - incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol)); + // TODO: is passing bd.textstart for start of the line OK? + incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (colnr_T)(bd.start_vcol)); total += incr; bd.start_vcol += incr; } @@ -405,7 +406,7 @@ static void shift_block(oparg_T *oap, int amount) non_white_col = bd.start_vcol; while (vim_iswhite(*non_white)) { - incr = lbr_chartabsize_adv(&non_white, non_white_col); + incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col); non_white_col += incr; } @@ -429,7 +430,10 @@ static void shift_block(oparg_T *oap, int amount) if (bd.startspaces) verbatim_copy_width -= bd.start_char_vcols; while (verbatim_copy_width < destination_col) { - incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width); + char_u *line = verbatim_copy_end; + + // TODO: is passing verbatim_copy_end for start of the line OK? + incr = lbr_chartabsize(line, verbatim_copy_end, verbatim_copy_width); if (verbatim_copy_width + incr > destination_col) break; verbatim_copy_width += incr; @@ -2824,7 +2828,7 @@ do_put ( oldlen = (int)STRLEN(oldp); for (ptr = oldp; vcol < col && *ptr; ) { /* Count a tab for what it's worth (if list mode not on) */ - incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol); + incr = lbr_chartabsize_adv(oldp, &ptr, (colnr_T)vcol); vcol += incr; } bd.textcol = (colnr_T)(ptr - oldp); @@ -2854,7 +2858,7 @@ do_put ( /* calculate number of spaces required to fill right side of block*/ spaces = y_width + 1; for (j = 0; j < yanklen; j++) - spaces -= lbr_chartabsize(&y_array[i][j], 0); + spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0); if (spaces < 0) spaces = 0; @@ -4114,7 +4118,7 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int i prev_pstart = line; while (bdp->start_vcol < oap->start_vcol && *pstart) { /* Count a tab for what it's worth (if list mode not on) */ - incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol); + incr = lbr_chartabsize(line, pstart, (colnr_T)bdp->start_vcol); bdp->start_vcol += incr; if (vim_iswhite(*pstart)) { bdp->pre_whitesp += incr; @@ -4163,7 +4167,9 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int i while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) { /* Count a tab for what it's worth (if list mode not on) */ prev_pend = pend; - incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol); + // TODO: is passing prev_pend for start of the line OK? + // prehaps it should be "line" + incr = lbr_chartabsize_adv(prev_pend, &pend, (colnr_T)bdp->end_vcol); bdp->end_vcol += incr; } if (bdp->end_vcol <= oap->end_vcol diff --git a/src/nvim/option.c b/src/nvim/option.c index 63ea2ee338..a878ba6455 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -176,6 +176,8 @@ */ #define PV_LIST OPT_WIN(WV_LIST) # define PV_ARAB OPT_WIN(WV_ARAB) +# define PV_BRI OPT_WIN(WV_BRI) +# define PV_BRIOPT OPT_WIN(WV_BRIOPT) # define PV_DIFF OPT_WIN(WV_DIFF) # define PV_FDC OPT_WIN(WV_FDC) # define PV_FEN OPT_WIN(WV_FEN) @@ -471,6 +473,14 @@ static struct vimoption (char_u *)&p_breakat, PV_NONE, {(char_u *)" \t!@*-+;:,./?", (char_u *)0L} SCRIPTID_INIT}, + {"breakindent", "bri", P_BOOL|P_VI_DEF|P_VIM|P_RWIN, + (char_u *)VAR_WIN, PV_BRI, + {(char_u *)FALSE, (char_u *)0L} + SCRIPTID_INIT}, + {"breakindentopt", "briopt", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_COMMA|P_NODUP, + (char_u *)VAR_WIN, PV_BRIOPT, + {(char_u *)"", (char_u *)NULL} + SCRIPTID_INIT}, {"browsedir", "bsdir",P_STRING|P_VI_DEF, (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} @@ -3481,6 +3491,7 @@ static void didset_options(void) (void)compile_cap_prog(curwin->w_s); /* set cedit_key */ (void)check_cedit(); + briopt_check(); } /* @@ -3815,6 +3826,11 @@ did_set_string_option ( *p_pm == '.' ? p_pm + 1 : p_pm) == 0) errmsg = (char_u *)N_("E589: 'backupext' and 'patchmode' are equal"); } + /* 'breakindentopt' */ + else if (varp == &curwin->w_p_briopt) { + if (briopt_check() == FAIL) + errmsg = e_invarg; + } /* * 'isident', 'iskeyword', 'isprint or 'isfname' option: refill chartab[] * If the new option is invalid, use old value. 'lisp' option: refill @@ -6681,6 +6697,8 @@ static char_u *get_varp(struct vimoption *p) case PV_SCROLL: return (char_u *)&(curwin->w_p_scr); case PV_WRAP: return (char_u *)&(curwin->w_p_wrap); case PV_LBR: return (char_u *)&(curwin->w_p_lbr); + case PV_BRI: return (char_u *)&(curwin->w_p_bri); + case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt); case PV_SCBIND: return (char_u *)&(curwin->w_p_scb); case PV_CRBIND: return (char_u *)&(curwin->w_p_crb); case PV_COCU: return (char_u *)&(curwin->w_p_cocu); @@ -6788,6 +6806,8 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_wrap = from->wo_wrap; to->wo_wrap_save = from->wo_wrap_save; to->wo_lbr = from->wo_lbr; + to->wo_bri = from->wo_bri; + to->wo_briopt = vim_strsave(from->wo_briopt); to->wo_scb = from->wo_scb; to->wo_scb_save = from->wo_scb_save; to->wo_crb = from->wo_crb; @@ -6842,6 +6862,7 @@ void check_winopt(winopt_T *wop) check_string_option(&wop->wo_stl); check_string_option(&wop->wo_cc); check_string_option(&wop->wo_cocu); + check_string_option(&wop->wo_briopt); } /* @@ -6859,6 +6880,7 @@ void clear_winopt(winopt_T *wop) clear_string_option(&wop->wo_stl); clear_string_option(&wop->wo_cc); clear_string_option(&wop->wo_cocu); + clear_string_option(&wop->wo_briopt); } /* @@ -8134,3 +8156,45 @@ void find_mps_values(int *initc, int *findc, int *backwards, int switchit) ++ptr; } } + +/* This is called when 'breakindentopt' is changed and when a window is + initialized */ +int briopt_check(void) +{ + char_u *p; + int bri_shift = 0; + long bri_min = 20; + bool bri_sbr = false; + + p = curwin->w_p_briopt; + while (*p != NUL) + { + if (STRNCMP(p, "shift:", 6) == 0 + && ((p[6] == '-' && VIM_ISDIGIT(p[7])) || VIM_ISDIGIT(p[6]))) + { + p += 6; + bri_shift = getdigits(&p); + } + else if (STRNCMP(p, "min:", 4) == 0 && VIM_ISDIGIT(p[4])) + { + p += 4; + bri_min = getdigits(&p); + } + else if (STRNCMP(p, "sbr", 3) == 0) + { + p += 3; + bri_sbr = true; + } + if (*p != ',' && *p != NUL) + return FAIL; + if (*p == ',') + ++p; + } + + curwin->w_p_brishift = bri_shift; + curwin->w_p_brimin = bri_min; + curwin->w_p_brisbr = bri_sbr; + + return OK; +} + diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index d862ab2761..555e9166d6 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -726,6 +726,8 @@ enum { , WV_COCU , WV_COLE , WV_CRBIND + , WV_BRI + , WV_BRIOPT , WV_DIFF , WV_FDC , WV_FEN diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 03c59bf584..811f265902 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -106,6 +106,7 @@ #include "nvim/farsi.h" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/indent.h" #include "nvim/getchar.h" #include "nvim/main.h" #include "nvim/mbyte.h" @@ -2196,6 +2197,7 @@ win_line ( char_u extra[18]; /* line number and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ char_u *p_extra = NULL; /* string of extra chars, plus NUL */ + char_u *p_extra_free = NULL; /* p_extra needs to be freed */ int c_extra = NUL; /* extra chars, all the same */ int extra_attr = 0; /* attributes when n_extra != 0 */ static char_u *at_end_str = (char_u *)""; /* used for p_extra when @@ -2283,7 +2285,8 @@ win_line ( # define WL_FOLD WL_CMDLINE + 1 /* 'foldcolumn' */ # define WL_SIGN WL_FOLD + 1 /* column for signs */ #define WL_NR WL_SIGN + 1 /* line number */ -# define WL_SBR WL_NR + 1 /* 'showbreak' or 'diff' */ +# define WL_BRI WL_NR + 1 /* 'breakindent' */ +# define WL_SBR WL_BRI + 1 /* 'showbreak' or 'diff' */ #define WL_LINE WL_SBR + 1 /* text in the line */ int draw_state = WL_START; /* what to draw next */ @@ -2540,7 +2543,7 @@ win_line ( if (v > 0) { char_u *prev_ptr = ptr; while (vcol < v && *ptr != NUL) { - c = win_lbr_chartabsize(wp, ptr, (colnr_T)vcol, NULL); + c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL); vcol += c; prev_ptr = ptr; mb_ptr_adv(ptr); @@ -2817,6 +2820,34 @@ win_line ( } } + if (wp->w_p_brisbr && draw_state == WL_BRI - 1 + && n_extra == 0 && *p_sbr != NUL) { + // draw indent after showbreak value + draw_state = WL_BRI; + } else if (wp->w_p_brisbr && draw_state == WL_SBR && n_extra == 0) { + // after the showbreak, draw the breakindent + draw_state = WL_BRI - 1; + } + + // draw 'breakindent': indent wrapped text accodringly + if (draw_state == WL_BRI - 1 && n_extra == 0) { + draw_state = WL_BRI; + if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) { + char_attr = 0; // was: hl_attr(HLF_AT); + + if (diff_hlf != (hlf_T)0) + char_attr = hl_attr(diff_hlf); + + p_extra = NULL; + c_extra = ' '; + n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, FALSE)); + /* Correct end of highlighted area for 'breakindent', + required wen 'linebreak' is also set. */ + if (tocol == vcol) + tocol += n_extra; + } + } + if (draw_state == WL_SBR - 1 && n_extra == 0) { draw_state = WL_SBR; if (filler_todo > 0) { @@ -3078,6 +3109,10 @@ win_line ( } --n_extra; } else { + if (p_extra_free != NULL) { + free(p_extra_free); + p_extra_free = NULL; + } /* * Get a character from the line itself. */ @@ -3378,17 +3413,20 @@ win_line ( /* * Found last space before word: check for line break. */ - if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr) - && !wp->w_p_list) { - n_extra = win_lbr_chartabsize(wp, ptr - ( - has_mbyte ? mb_l : - 1), (colnr_T)vcol, NULL) - 1; + if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)) { + char_u *p = ptr - ( + has_mbyte ? mb_l : + 1); + // TODO: is passing p for start of the line OK? + n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1; c_extra = ' '; if (vim_iswhite(c)) { if (c == TAB) /* See "Tab alignment" below. */ FIX_FOR_BOGUSCOLS; - c = ' '; + if (!wp->w_p_list) { + c = ' '; + } } } @@ -3419,9 +3457,36 @@ win_line ( * into "ScreenLines". */ if (c == TAB && (!wp->w_p_list || lcs_tab1)) { + int tab_len = 0; /* tab amount depends on current column */ - n_extra = (int)wp->w_buffer->b_p_ts + tab_len = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1; + if (!wp->w_p_lbr || !wp->w_p_list) { + n_extra = tab_len; + } else { + char_u *p; + int len = n_extra; + int i; + int saved_nextra = n_extra; + + /* if n_extra > 0, it gives the number of chars to use for + * a tab, else we need to calculate the width for a tab */ + len = (tab_len * mb_char2len(lcs_tab2)); + if (n_extra > 0) { + len += n_extra - tab_len; + } + c = lcs_tab1; + p = xmalloc(len + 1); + memset(p, ' ', len); + p[len] = NUL; + p_extra_free = p; + for (i = 0; i < tab_len; i++) { + mb_char2bytes(lcs_tab2, p); + p += mb_char2len(lcs_tab2); + n_extra += mb_char2len(lcs_tab2) - (saved_nextra > 0 ? 1: 0); + } + p_extra = p_extra_free; + } /* Tab alignment should be identical regardless of * 'conceallevel' value. So tab compensates of all * previous concealed characters, and thus resets vcol_off @@ -3432,8 +3497,12 @@ win_line ( mb_utf8 = FALSE; /* don't draw as UTF-8 */ if (wp->w_p_list) { c = lcs_tab1; - c_extra = lcs_tab2; - n_attr = n_extra + 1; + if (wp->w_p_lbr) { + c_extra = NUL; /* using p_extra from above */ + } else { + c_extra = lcs_tab2; + } + n_attr = tab_len + 1; extra_attr = hl_attr(HLF_8); saved_attr2 = char_attr; /* save current attr */ mb_c = c; @@ -3493,11 +3562,25 @@ win_line ( mb_utf8 = FALSE; /* don't draw as UTF-8 */ } else if (c != NUL) { p_extra = transchar(c); + if (n_extra == 0) { + n_extra = byte2cells(c); + } if ((dy_flags & DY_UHEX) && wp->w_p_rl) rl_mirror(p_extra); /* reverse "<12>" */ - n_extra = byte2cells(c) - 1; c_extra = NUL; - c = *p_extra++; + if (wp->w_p_lbr) { + char_u *p; + + c = *p_extra; + p = xmalloc(n_extra + 1); + memset(p, ' ', n_extra); + STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); + p[n_extra] = NUL; + p_extra_free = p_extra = p; + } else { + n_extra = byte2cells(c) - 1; + c = *p_extra++; + } if (!attr_pri) { n_attr = n_extra + 1; extra_attr = hl_attr(HLF_8); diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index a7f9dd8fa1..db88755a01 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -30,8 +30,10 @@ SCRIPTS := test_autoformat_join.out \ test91.out test92.out test93.out test94.out test95.out \ test96.out test97.out test98.out test99.out test100.out \ test101.out test102.out test103.out test104.out test105.out \ - test106.out test107.out \ - test_options.out + test106.out test107.out \ + test_options.out \ + test_listlbr.out test_listlbr_utf8.out \ + test_breakindent.out SCRIPTS_GUI := test16.out diff --git a/src/nvim/testdir/test_breakindent.in b/src/nvim/testdir/test_breakindent.in new file mode 100644 index 0000000000..8f40e4f7e5 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.in @@ -0,0 +1,79 @@ +Test for breakindent + +STARTTEST +:so small.vim +:if !exists("+breakindent") | e! test.ok | w! test.out | qa! | endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\" +:set ts=4 sw=4 sts=4 breakindent +:fu! ScreenChar(width) +: let c='' +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.'), i)) +: endfor +: let c.="\n" +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.')+1, i)) +: endfor +: let c.="\n" +: for i in range(1,a:width) +: let c.=nr2char(screenchar(line('.')+2, i)) +: endfor +: return c +:endfu +:fu DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line1 +: wincmd p +:endfu +:let g:test="Test 1: Simple breakindent" +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test="Test 2: Simple breakindent + sbr=>>" +:set sbr=>> +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test ="Test 3: Simple breakindent + briopt:sbr" +:set briopt=sbr,min:0 sbr=++ +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test ="Test 4: Simple breakindent + min width: 18" +:set sbr= briopt=min:18 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test =" Test 5: Simple breakindent + shift by 2" +:set briopt=shift:2,min:0 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test=" Test 6: Simple breakindent + shift by -1" +:set briopt=shift:-1,min:0 +:let line1=ScreenChar(8) +:call DoRecordScreen() +:let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr" +:set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr" +:set briopt=shift:1,sbr,min:0 nu sbr=# list +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list" +:set briopt-=sbr +:let line1=ScreenChar(10) +:call DoRecordScreen() +:let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n" +:set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 +:let line1=ScreenChar(10) +:call DoRecordScreen() +:wincmd p +:let g:test="\n Test 11: strdisplaywidth when breakindent is on" +:set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 +:let text=getline(2) "skip leading tab when calculating text width +:let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3 " text wraps 3 times +:$put =g:test +:$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width) +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_breakindent.ok b/src/nvim/testdir/test_breakindent.ok new file mode 100644 index 0000000000..723cb25012 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.ok @@ -0,0 +1,55 @@ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP + +Test 1: Simple breakindent + abcd + qrst + GHIJ + +Test 2: Simple breakindent + sbr=>> + abcd + >>qr + >>EF + +Test 3: Simple breakindent + briopt:sbr + abcd +++ qrst +++ GHIJ + +Test 4: Simple breakindent + min width: 18 + abcd + qrstuv + IJKLMN + + Test 5: Simple breakindent + shift by 2 + abcd + qr + EF + + Test 6: Simple breakindent + shift by -1 + abcd + qrstu + HIJKL + + Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr + 2 ab +? m +? x + + Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr + 2 ^Iabcd +# opq +# BCD + + Test 9: breakindent + shift by +1 + 'nu' + sbr=# list + 2 ^Iabcd + #op + #AB + + Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n + 2 ab +~ mn +~ yz + + Test 11: strdisplaywidth when breakindent is on +strdisplaywidth: 46 == calculated: 64 diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in new file mode 100644 index 0000000000..0cce4c23a5 --- /dev/null +++ b/src/nvim/testdir/test_listlbr.in @@ -0,0 +1,52 @@ +Test for linebreak and list option (non-utf8) + +STARTTEST +:so small.vim +:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \" +:norm! zt +:set ts=4 sw=4 sts=4 linebreak sbr=+ wrap +:fu! ScreenChar(width) +: let c='' +: for j in range(1,4) +: for i in range(1,a:width) +: let c.=nr2char(screenchar(j, i)) +: endfor +: let c.="\n" +: endfor +: return c +:endfu +:fu! DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line +: wincmd p +:endfu +:let g:test="Test 1: set linebreak" +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test="Test 2: set linebreak + set list" +:set linebreak list listchars= +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 3: set linebreak nolist" +:set nolist linebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!" +:set nolist linebreak ts=8 +:let line="1\t".repeat('a', winwidth(0)-2) +:$put =line +:$ +:norm! zt +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_listlbr.ok b/src/nvim/testdir/test_listlbr.ok new file mode 100644 index 0000000000..be323d4dc7 --- /dev/null +++ b/src/nvim/testdir/test_listlbr.ok @@ -0,0 +1,27 @@ + + abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP + +Test 1: set linebreak + abcdef ++hijklmn ++pqrstuvwxyz_1060ABC ++DEFGHIJKLMNOP + +Test 2: set linebreak + set list +^Iabcdef hijklmn^I ++pqrstuvwxyz_1060ABC ++DEFGHIJKLMNOP + + +Test 3: set linebreak nolist + abcdef ++hijklmn ++pqrstuvwxyz_1060ABC ++DEFGHIJKLMNOP +1 aaaaaaaaaaaaaaaaaa + +Test 4: set linebreak with tab and 1 line as long as screen: should break! +1 ++aaaaaaaaaaaaaaaaaa +~ +~ diff --git a/src/nvim/testdir/test_listlbr_utf8.in b/src/nvim/testdir/test_listlbr_utf8.in new file mode 100644 index 0000000000..ba12adae05 --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.in @@ -0,0 +1,52 @@ +Test for linebreak and list option in utf-8 mode + +STARTTEST +:so small.vim +:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif +:so mbyte.vim +:if &enc !=? 'utf-8'|:e! test.ok|:w! test.out|qa!|endif +:10new|:vsp|:vert resize 20 +:put =\"\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP \" +:norm! zt +:set ts=4 sw=4 sts=4 linebreak sbr=+ wrap +:fu! ScreenChar(width) +: let c='' +: for j in range(1,4) +: for i in range(1,a:width) +: let c.=nr2char(screenchar(j, i)) +: endfor +: let c.="\n" +: endfor +: return c +:endfu +:fu! DoRecordScreen() +: wincmd l +: $put =printf(\"\n%s\", g:test) +: $put =g:line +: wincmd p +:endfu +:let g:test ="Test 1: set linebreak + set list + fancy listchars" +:exe "set linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6" +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:" +:let g:test ="Test 2: set nolinebreak list" +:set list nolinebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:" +:let g:test ="Test 3: set linebreak nolist" +:$put =\"\t*mask = nil;\" +:$ +:norm! zt +:set nolist linebreak +:redraw! +:let line=ScreenChar(winwidth(0)) +:call DoRecordScreen() +:" +:%w! test.out +:qa! +ENDTEST +dummy text diff --git a/src/nvim/testdir/test_listlbr_utf8.ok b/src/nvim/testdir/test_listlbr_utf8.ok new file mode 100644 index 0000000000..634cf3906d --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.ok @@ -0,0 +1,21 @@ + + abcdef hijklmn pqrstuvwxyz 1060ABCDEFGHIJKLMNOP + +Test 1: set linebreak + set list + fancy listchars +▕———abcdef ++hijklmn▕——— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ + +Test 2: set nolinebreak list +▕———abcdef hijklmn▕— ++pqrstuvwxyz␣1060ABC ++DEFGHIJKLMNOPˑ¶ +¶ + *mask = nil; + +Test 3: set linebreak nolist + *mask = nil; +~ +~ +~ diff --git a/src/nvim/version.c b/src/nvim/version.c index 6e503200f0..5684a3f8d8 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -207,7 +207,7 @@ static int included_patches[] = { //391, //390, //389, - //388, + 388, //387, //386, //385, @@ -224,8 +224,8 @@ static int included_patches[] = { //374, //373, //372, - //371, - //370, + 371, + 370, //369, //368, //367, @@ -242,14 +242,14 @@ static int included_patches[] = { //356 NA //355, //354, - //353, - //352, + 353, + 352, //351, //350, //349, //348, //347, - //346, + 346, //345, //344, //343, @@ -257,7 +257,7 @@ static int included_patches[] = { //341, //340 NA //339, - //338, + 338, //337, //336, 335, |