aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2023-01-31 00:52:34 +0100
committerLuuk van Baal <luukvbaal@gmail.com>2023-02-04 11:04:43 +0100
commit08fb3b5309dee79585f3eec2450636966cbb01b4 (patch)
tree8569a3aeea80ce77d20056e663f3ec726d267d43
parent964ae205a583807127eda75d9876fb6dfda6065c (diff)
downloadrneovim-08fb3b5309dee79585f3eec2450636966cbb01b4.tar.gz
rneovim-08fb3b5309dee79585f3eec2450636966cbb01b4.tar.bz2
rneovim-08fb3b5309dee79585f3eec2450636966cbb01b4.zip
perf(column): only build fold/sign column when present in 'statuscolumn'
Problem: The fold and sign column is built and stored regardless of whether the corresponding item is present in 'statuscolumn'. Solution: Since the 'statuscolumn' parses itself, we can defer building the columns until the corresponding item is actually encountered.
-rw-r--r--src/nvim/buffer_defs.h11
-rw-r--r--src/nvim/drawline.c45
-rw-r--r--src/nvim/fold.h11
-rw-r--r--src/nvim/fold_defs.h17
-rw-r--r--src/nvim/statusline.c38
-rw-r--r--test/functional/ui/statuscolumn_spec.lua2
6 files changed, 64 insertions, 60 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 4c99191170..4f0e991ad5 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -18,6 +18,7 @@ typedef struct {
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/eval/typval.h"
+#include "nvim/fold_defs.h"
#include "nvim/garray.h"
#include "nvim/grid_defs.h"
#include "nvim/hashtab.h"
@@ -1423,17 +1424,17 @@ struct statuscol {
int width; ///< width of the status column
int cur_attr; ///< current attributes in text
int num_attr; ///< attributes used for line number
- int fold_attr; ///< attributes used for fold column
- int sign_attr[SIGN_SHOW_MAX + 1]; ///< attributes used for signs
+ int sign_cul_attr; ///< cursorline sign attr
int truncate; ///< truncated width
- bool draw; ///< draw statuscolumn or not
- char fold_text[9 * 4 + 1]; ///< text in fold column (%C)
- char *sign_text[SIGN_SHOW_MAX + 1]; ///< text in sign column (%s)
+ bool draw; ///< whether to draw the statuscolumn
+ bool use_cul; ///< whether to use cursorline attrs
char text[MAXPATHL]; ///< text in status column
char *textp; ///< current position in text
char *text_end; ///< end of text (the NUL byte)
stl_hlrec_t *hlrec; ///< highlight groups
stl_hlrec_t *hlrecp; ///< current highlight group
+ foldinfo_T foldinfo; ///< fold information
+ SignTextAttrs *sattrs; ///< sign attributes
};
/// Macros defined in Vim, but not in Neovim
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 01ff207c2b..5281370995 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -404,37 +404,10 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
/// the start of the buffer line "lnum" and once for the wrapped lines.
///
/// @param[out] stcp Status column attributes
-static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
- int cul_attr, int sign_num_attr, int sign_cul_attr, statuscol_T *stcp,
- foldinfo_T foldinfo, SignTextAttrs *sattrs)
+static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T *stcp)
{
- long relnum = -1;
- bool use_cul = use_cursor_line_sign(wp, lnum);
- int virtnum = row - startrow - filler_lines;
-
- // When called the first time for line "lnum" set num_attr
- if (stcp->num_attr == 0) {
- stcp->num_attr = sign_num_attr ? sign_num_attr
- : get_line_number_attr(wp, lnum, row, startrow, filler_lines);
- }
- // When called for the first non-filler row of line "lnum" set num v:vars and fold column
- if (virtnum == 0) {
- relnum = labs(get_cursor_rel_lnum(wp, lnum));
- if (compute_foldcolumn(wp, 0)) {
- size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum);
- stcp->fold_text[n] = NUL;
- stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
- }
- }
- // Make sure to clear->set->clear sign column for filler->first->wrapped lines
- int i = 0;
- for (; i < wp->w_scwidth; i++) {
- SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
- stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
- stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id)
- : win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC);
- }
- stcp->sign_text[i] = NULL;
+ // When called for the first non-filler row of line "lnum" set num v:vars
+ long relnum = virtnum == 0 ? labs(get_cursor_rel_lnum(wp, lnum)) : -1;
// When a buffer's line count has changed, make a best estimate for the full
// width of the status column by building with "w_nrwidth_line_count". Add
@@ -496,8 +469,7 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st
if (stcp->textp + *n_extrap < stcp->text_end) {
int hl = stcp->hlrecp->userhl;
stcp->textp = stcp->hlrecp->start;
- stcp->cur_attr = hl < 0 ? syn_id2attr(-stcp->hlrecp->userhl)
- : hl > 0 ? hl : stcp->num_attr;
+ stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : hl > 0 ? hl : stcp->num_attr;
stcp->hlrecp++;
*draw_state = WL_STC - 1;
}
@@ -1211,7 +1183,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (*wp->w_p_stc != NUL) {
// Draw the 'statuscolumn' if option is set.
statuscol.draw = true;
+ statuscol.sattrs = sattrs;
+ statuscol.foldinfo = foldinfo;
statuscol.width = win_col_off(wp);
+ statuscol.use_cul = use_cursor_line_sign(wp, lnum);
+ statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0;
+ statuscol.num_attr = sign_num_attr ? sign_num_attr
+ : get_line_number_attr(wp, lnum, row, startrow, filler_lines);
}
int sign_idx = 0;
@@ -1357,8 +1335,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Draw the 'statuscolumn' if option is set.
if (statuscol.draw) {
if (statuscol.textp == NULL) {
- get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr,
- sign_num_attr, sign_cul_attr, &statuscol, foldinfo, sattrs);
+ get_statuscol_str(wp, lnum, row - startrow - filler_lines, &statuscol);
if (wp->w_redr_statuscol) {
break;
}
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index ac1e8c9419..cf44cf14c3 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -9,17 +9,6 @@
#include "nvim/pos.h"
#include "nvim/types.h"
-// Info used to pass info about a fold from the fold-detection code to the
-// code that displays the foldcolumn.
-typedef struct foldinfo {
- linenr_T fi_lnum; // line number where fold starts
- int fi_level; // level of the fold; when this is zero the
- // other fields are invalid
- int fi_low_level; // lowest fold level that starts in the same
- // line
- linenr_T fi_lines;
-} foldinfo_T;
-
EXTERN int disable_fold_update INIT(= 0);
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/fold_defs.h b/src/nvim/fold_defs.h
new file mode 100644
index 0000000000..c528d25348
--- /dev/null
+++ b/src/nvim/fold_defs.h
@@ -0,0 +1,17 @@
+#ifndef NVIM_FOLD_DEFS_H
+#define NVIM_FOLD_DEFS_H
+
+#include "nvim/pos.h"
+
+// Info used to pass info about a fold from the fold-detection code to the
+// code that displays the foldcolumn.
+typedef struct foldinfo {
+ linenr_T fi_lnum; // line number where fold starts
+ int fi_level; // level of the fold; when this is zero the
+ // other fields are invalid
+ int fi_low_level; // lowest fold level that starts in the same
+ // line
+ linenr_T fi_lines;
+} foldinfo_T;
+
+#endif // NVIM_FOLD_DEFS_H
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index 6ad1f31143..1882cbbacc 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -38,7 +38,7 @@
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/screen.h"
-#include "nvim/sign_defs.h"
+#include "nvim/sign.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/types.h"
@@ -1648,20 +1648,40 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (stcp == NULL) {
break;
}
-
bool fold = opt == STL_FOLDCOL;
+ int width = fold ? (compute_foldcolumn(wp, 0) > 0) : wp->w_scwidth;
+
+ if (width == 0) {
+ break;
+ }
+
+ char *p;
+ if (fold) {
+ size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM));
+ stl_items[curitem].minwid = win_hl_attr(wp, stcp->use_cul ? HLF_CLF : HLF_FC);
+ p = out_p;
+ p[n] = NUL;
+ }
+
*buf_tmp = NUL;
- for (int i = 0; i <= SIGN_SHOW_MAX; i++) {
- char *p = fold ? stcp->fold_text : stcp->sign_text[i];
- if ((!p || !*p) && *buf_tmp == NUL) {
- break;
+ varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
+ for (int i = 0; i <= width; i++) {
+ if (i == width) {
+ if (*buf_tmp == NUL) {
+ break;
+ }
+ stl_items[curitem].minwid = 0;
+ } else if (!fold) {
+ SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth);
+ p = sattr && sattr->text ? sattr->text : " ";
+ stl_items[curitem].minwid = sattr ? stcp->sign_cul_attr ? stcp->sign_cul_attr
+ : sattr->hl_attr_id
+ : win_hl_attr(wp, stcp->use_cul ? HLF_CLS : HLF_SC);
}
stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p + strlen(buf_tmp);
- stl_items[curitem].minwid = !p || (fold && i) ? 0 : fold ? stcp->fold_attr
- : stcp->sign_attr[i];
curitem++;
- if (!p || (fold && i)) {
+ if (i == width) {
str = buf_tmp;
break;
}
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index 3233e6cd19..287686cf37 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -456,7 +456,7 @@ describe('statuscolumn', function()
14 aaaaa |
|
]])
- command('set stc=') -- also for the default sign column
+ command('set stc=') -- also for the default fold column
screen:expect_unchanged()
-- 'statuscolumn' is not too wide with custom (bogus) fold column
command([[set stc=%{foldlevel(v:lnum)>0?repeat('-',foldlevel(v:lnum)):''}%=%l\ ]])