aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-12-26 07:06:43 +0100
committerGitHub <noreply@github.com>2019-12-26 07:06:43 +0100
commitb0196586debd55b9b8be62966084eee12bf0e4ad (patch)
tree738e9c21a57e31950420cb0533b8a8b2a8838eb0
parent927a4f24e09e879ae1006aab32ead81985c61865 (diff)
parentbbad324b175f1bd35201f0ba73fba1b11af7093d (diff)
downloadrneovim-b0196586debd55b9b8be62966084eee12bf0e4ad.tar.gz
rneovim-b0196586debd55b9b8be62966084eee12bf0e4ad.tar.bz2
rneovim-b0196586debd55b9b8be62966084eee12bf0e4ad.zip
Merge #11568 'fillchars: foldopen, foldsep, foldclose'
-rw-r--r--runtime/doc/options.txt3
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/mouse.c2
-rw-r--r--src/nvim/option.c3
-rw-r--r--src/nvim/screen.c139
-rw-r--r--test/functional/ui/fold_spec.lua39
6 files changed, 125 insertions, 64 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 4b8740c5d2..519cbf66b1 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2371,6 +2371,9 @@ A jump table for the options with a short description can be found at |Q_op|.
stlnc:c ' ' or '=' statusline of the non-current windows
vert:c '│' or '|' vertical separators |:vsplit|
fold:c '·' or '-' filling 'foldtext'
+ foldopen:c '-' mark the beginning of a fold
+ foldclose:c '+' show a closed fold
+ foldsep:c '|' open fold middle marker
diff:c '-' deleted lines of the 'diff' option
msgsep:c ' ' message separator 'display'
eob:c '~' empty lines at the end of a buffer
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index bc4fb2997d..265fc05f67 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1126,6 +1126,9 @@ struct window_S {
int stlnc;
int vert;
int fold;
+ int foldopen; ///< when fold is open
+ int foldclosed; ///< when fold is closed
+ int foldsep; ///< continuous fold marker
int diff;
int msgsep;
int eob;
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index de2db63651..dab2e44890 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -350,7 +350,7 @@ retnomove:
count |= CURSOR_MOVED; // Cursor has moved
}
- if (mouse_char == '+') {
+ if (mouse_char == curwin->w_p_fcs_chars.foldclosed) {
count |= MOUSE_FOLD_OPEN;
} else if (mouse_char != ' ') {
count |= MOUSE_FOLD_CLOSE;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index e48ed201e8..de25ee3218 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -3542,6 +3542,9 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set)
{ &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
{ &wp->w_p_fcs_chars.vert, "vert", 9474 }, // │
{ &wp->w_p_fcs_chars.fold, "fold", 183 }, // ·
+ { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' },
+ { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' },
+ { &wp->w_p_fcs_chars.foldsep, "foldsep", '|' },
{ &wp->w_p_fcs_chars.diff, "diff", '-' },
{ &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
{ &wp->w_p_fcs_chars.eob, "eob", '~' },
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 4082208dd4..1b7eeeecb8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -126,7 +126,8 @@
// temporary buffer for rendering a single screenline, so it can be
-// comparared with previous contents to calculate smallest delta.
+// compared with previous contents to calculate smallest delta.
+// Per-cell attributes
static size_t linebuf_size = 0;
static schar_T *linebuf_char = NULL;
static sattr_T *linebuf_attr = NULL;
@@ -1814,27 +1815,6 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
col++;
}
- // 2. Add the 'foldcolumn'
- // Reduce the width when there is not enough space.
- fdc = compute_foldcolumn(wp, col);
- if (fdc > 0) {
- fill_foldcolumn(buf, wp, TRUE, lnum);
- if (wp->w_p_rl) {
- int i;
-
- copy_text_attr(off + wp->w_grid.Columns - fdc - col, buf, fdc,
- win_hl_attr(wp, HLF_FC));
- // reverse the fold column
- for (i = 0; i < fdc; i++) {
- schar_from_ascii(linebuf_char[off + wp->w_grid.Columns - i - 1 - col],
- buf[i]);
- }
- } else {
- copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC));
- }
- col += fdc;
- }
-
# define RL_MEMSET(p, v, l) \
do { \
if (wp->w_p_rl) { \
@@ -1848,6 +1828,25 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
} \
} while (0)
+ // 2. Add the 'foldcolumn'
+ // Reduce the width when there is not enough space.
+ fdc = compute_foldcolumn(wp, col);
+ if (fdc > 0) {
+ fill_foldcolumn(buf, wp, true, lnum);
+ const char_u *it = &buf[0];
+ for (int i = 0; i < fdc; i++) {
+ int mb_c = mb_ptr2char_adv(&it);
+ if (wp->w_p_rl) {
+ schar_from_char(linebuf_char[off + wp->w_grid.Columns - i - 1 - col],
+ mb_c);
+ } else {
+ schar_from_char(linebuf_char[off + col + i], mb_c);
+ }
+ }
+ RL_MEMSET(col, win_hl_attr(wp, HLF_FC), fdc);
+ col += fdc;
+ }
+
/* Set all attributes of the 'number' or 'relativenumber' column and the
* text */
RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col);
@@ -2068,58 +2067,73 @@ static void copy_text_attr(int off, char_u *buf, int len, int attr)
}
}
-/*
- * Fill the foldcolumn at "p" for window "wp".
- * Only to be called when 'foldcolumn' > 0.
- */
-static void
-fill_foldcolumn (
+/// Fills the foldcolumn at "p" for window "wp".
+/// Only to be called when 'foldcolumn' > 0.
+///
+/// @param[out] p Char array to write into
+/// @param lnum Absolute current line number
+/// @param closed Whether it is in 'foldcolumn' mode
+///
+/// Assume monocell characters
+/// @return number of chars added to \param p
+static size_t
+fill_foldcolumn(
char_u *p,
win_T *wp,
- int closed, /* TRUE of FALSE */
- linenr_T lnum /* current line number */
+ int closed,
+ linenr_T lnum
)
{
int i = 0;
int level;
int first_level;
- int empty;
- int fdc = compute_foldcolumn(wp, 0);
-
+ int fdc = compute_foldcolumn(wp, 0); // available cell width
+ size_t char_counter = 0;
+ int symbol = 0;
+ int len = 0;
// Init to all spaces.
- memset(p, ' ', (size_t)fdc);
+ memset(p, ' ', MAX_MCO * fdc + 1);
level = win_foldinfo.fi_level;
- if (level > 0) {
- // If there is only one column put more info in it.
- empty = (fdc == 1) ? 0 : 1;
-
- // If the column is too narrow, we start at the lowest level that
- // fits and use numbers to indicated the depth.
- first_level = level - fdc - closed + 1 + empty;
- if (first_level < 1) {
- first_level = 1;
- }
-
- for (i = 0; i + empty < fdc; i++) {
- if (win_foldinfo.fi_lnum == lnum
- && first_level + i >= win_foldinfo.fi_low_level) {
- p[i] = '-';
- } else if (first_level == 1) {
- p[i] = '|';
- } else if (first_level + i <= 9) {
- p[i] = '0' + first_level + i;
- } else {
- p[i] = '>';
- }
- if (first_level + i == level) {
- break;
- }
+
+ // If the column is too narrow, we start at the lowest level that
+ // fits and use numbers to indicated the depth.
+ first_level = level - fdc - closed + 1;
+ if (first_level < 1) {
+ first_level = 1;
+ }
+
+ for (i = 0; i < MIN(fdc, level); i++) {
+ if (win_foldinfo.fi_lnum == lnum
+ && first_level + i >= win_foldinfo.fi_low_level) {
+ symbol = wp->w_p_fcs_chars.foldopen;
+ } else if (first_level == 1) {
+ symbol = wp->w_p_fcs_chars.foldsep;
+ } else if (first_level + i <= 9) {
+ symbol = '0' + first_level + i;
+ } else {
+ symbol = '>';
+ }
+
+ len = utf_char2bytes(symbol, &p[char_counter]);
+ char_counter += len;
+ if (first_level + i >= level) {
+ i++;
+ break;
}
}
+
if (closed) {
- p[i >= fdc ? i - 1 : i] = '+';
+ if (symbol != 0) {
+ // rollback length
+ char_counter -= len;
+ }
+ symbol = wp->w_p_fcs_chars.foldclosed;
+ len = utf_char2bytes(symbol, &p[char_counter]);
+ char_counter += len;
}
+
+ return MAX(char_counter + (fdc-i), (size_t)fdc);
}
/*
@@ -2807,9 +2821,8 @@ win_line (
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
// already be in use.
xfree(p_extra_free);
- p_extra_free = xmalloc(12 + 1);
- fill_foldcolumn(p_extra_free, wp, false, lnum);
- n_extra = fdc;
+ p_extra_free = xmalloc(MAX_MCO * fdc + 1);
+ n_extra = fill_foldcolumn(p_extra_free, wp, false, lnum);
p_extra_free[n_extra] = NUL;
p_extra = p_extra_free;
c_extra = NUL;
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index eb81aba131..0b788e7afb 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -60,6 +60,45 @@ describe("folded lines", function()
]])
end)
+ it("works with multibyte fillchars", function()
+ insert([[
+ aa
+ bb
+ cc
+ dd
+ ee
+ ff]])
+ command("set fillchars+=foldopen:▾,foldsep:│,foldclose:▸")
+ feed_command('1')
+ command("set foldcolumn=2")
+ feed('zf4j')
+ feed('zf2j')
+ feed('zO')
+ screen:expect{grid=[[
+ {7:▾▾}^aa |
+ {7:││}bb |
+ {7:││}cc |
+ {7:││}dd |
+ {7:││}ee |
+ {7:│ }ff |
+ {1:~ }|
+ :1 |
+ ]]}
+
+ feed_command("set rightleft")
+ screen:expect{grid=[[
+ a^a{7:▾▾}|
+ bb{7:││}|
+ cc{7:││}|
+ dd{7:││}|
+ ee{7:││}|
+ ff{7: │}|
+ {1: ~}|
+ :set rightleft |
+ ]]}
+ end)
+
+
it("works with multibyte text", function()
-- Currently the only allowed value of 'maxcombine'
eq(6, meths.get_option('maxcombine'))