mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
refactor(sign): store 'signcolumn' width range when it is set
Problem: Minimum and maximum signcolumn width is determined each redraw. Solution: Determine and store 'signcolumn' range when option is set.
This commit is contained in:

committed by
Lewis Russell

parent
fec5e3ab24
commit
585eeacb24
@@ -1206,6 +1206,8 @@ struct window_S {
|
|||||||
int w_nrwidth; // width of 'number' and 'relativenumber'
|
int w_nrwidth; // width of 'number' and 'relativenumber'
|
||||||
// column being used
|
// column being used
|
||||||
int w_scwidth; // width of 'signcolumn'
|
int w_scwidth; // width of 'signcolumn'
|
||||||
|
int w_minscwidth; // minimum width or SCL_NO/SCL_NUM
|
||||||
|
int w_maxscwidth; // maximum width or SCL_NO/SCL_NUM
|
||||||
|
|
||||||
// === end of cached values ===
|
// === end of cached values ===
|
||||||
|
|
||||||
|
@@ -442,7 +442,9 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
|
|||||||
int *cul_id, int *num_id)
|
int *cul_id, int *num_id)
|
||||||
{
|
{
|
||||||
MarkTreeIter itr[1];
|
MarkTreeIter itr[1];
|
||||||
if (!buf->b_signs || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
|
if (!buf->b_signs
|
||||||
|
|| wp->w_minscwidth == SCL_NO
|
||||||
|
|| !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +473,7 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kv_size(signs)) {
|
if (kv_size(signs)) {
|
||||||
int width = (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') ? 1 : wp->w_scwidth;
|
int width = wp->w_minscwidth == SCL_NUM ? 1 : wp->w_scwidth;
|
||||||
int idx = MIN(width, num_text) - 1;
|
int idx = MIN(width, num_text) - 1;
|
||||||
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
|
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
|
||||||
|
|
||||||
|
@@ -561,7 +561,7 @@ static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, in
|
|||||||
&& !((has_cpo_n && !wp->w_p_bri) && wp->w_skipcol > 0 && wlv->lnum == wp->w_topline)) {
|
&& !((has_cpo_n && !wp->w_p_bri) && wp->w_skipcol > 0 && wlv->lnum == wp->w_topline)) {
|
||||||
// If 'signcolumn' is set to 'number' and a sign is present in "lnum",
|
// If 'signcolumn' is set to 'number' and a sign is present in "lnum",
|
||||||
// then display the sign instead of the line number.
|
// then display the sign instead of the line number.
|
||||||
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && wlv->sattrs[0].text) {
|
if (wp->w_minscwidth == SCL_NUM && wlv->sattrs[0].text) {
|
||||||
get_sign_display_info(true, wp, wlv, 0, sign_cul_attr);
|
get_sign_display_info(true, wp, wlv, 0, sign_cul_attr);
|
||||||
} else {
|
} else {
|
||||||
// Draw the line number (empty space after wrapping).
|
// Draw the line number (empty space after wrapping).
|
||||||
|
@@ -606,7 +606,7 @@ int update_screen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
|
// Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
|
||||||
if (*wp->w_p_stc != NUL && !wp->w_buffer->b_signcols.valid && win_no_signcol(wp)) {
|
if (*wp->w_p_stc != NUL && !wp->w_buffer->b_signcols.valid && wp->w_minscwidth <= SCL_NO) {
|
||||||
wp->w_nrwidth_line_count = 0;
|
wp->w_nrwidth_line_count = 0;
|
||||||
wp->w_valid &= ~VALID_WCOL;
|
wp->w_valid &= ~VALID_WCOL;
|
||||||
wp->w_redr_type = UPD_NOT_VALID;
|
wp->w_redr_type = UPD_NOT_VALID;
|
||||||
@@ -619,7 +619,7 @@ int update_screen(void)
|
|||||||
|
|
||||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
// Validate b_signcols if there is no dedicated signcolumn but 'statuscolumn' is set.
|
// Validate b_signcols if there is no dedicated signcolumn but 'statuscolumn' is set.
|
||||||
if (*wp->w_p_stc != NUL && win_no_signcol(wp)) {
|
if (*wp->w_p_stc != NUL && wp->w_minscwidth <= SCL_NO) {
|
||||||
buf_signcols(wp->w_buffer, 0);
|
buf_signcols(wp->w_buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2632,8 +2632,7 @@ int number_width(win_T *wp)
|
|||||||
|
|
||||||
// If 'signcolumn' is set to 'number' and there is a sign to display, then
|
// If 'signcolumn' is set to 'number' and there is a sign to display, then
|
||||||
// the minimal width for the number column is 2.
|
// the minimal width for the number column is 2.
|
||||||
if (n < 2 && wp->w_buffer->b_signs_with_text
|
if (n < 2 && wp->w_buffer->b_signs_with_text && wp->w_minscwidth == SCL_NUM) {
|
||||||
&& (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) {
|
|
||||||
n = 2;
|
n = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2245,6 +2245,7 @@ static const char *did_set_number_relativenumber(optset_T *args)
|
|||||||
// When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width.
|
// When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width.
|
||||||
win->w_nrwidth_line_count = 0;
|
win->w_nrwidth_line_count = 0;
|
||||||
}
|
}
|
||||||
|
check_signcolumn(win);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4861,6 +4862,7 @@ void didset_window_options(win_T *wp, bool valid_cursor)
|
|||||||
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
|
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
|
||||||
check_blending(wp);
|
check_blending(wp);
|
||||||
set_winbar_win(wp, false, valid_cursor);
|
set_winbar_win(wp, false, valid_cursor);
|
||||||
|
check_signcolumn(wp);
|
||||||
wp->w_grid_alloc.blending = wp->w_p_winbl > 0;
|
wp->w_grid_alloc.blending = wp->w_p_winbl > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6170,49 +6172,12 @@ bool fish_like_shell(void)
|
|||||||
/// buffer signs and on user configuration.
|
/// buffer signs and on user configuration.
|
||||||
int win_signcol_count(win_T *wp)
|
int win_signcol_count(win_T *wp)
|
||||||
{
|
{
|
||||||
return win_signcol_configured(wp);
|
if (wp->w_minscwidth <= SCL_NO) {
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true when window "wp" has no sign column.
|
|
||||||
bool win_no_signcol(win_T *wp)
|
|
||||||
{
|
|
||||||
const char *scl = wp->w_p_scl;
|
|
||||||
return (*scl == 'n' && (*(scl + 1) == 'o' || (*(scl + 1) == 'u'
|
|
||||||
&& (wp->w_p_nu || wp->w_p_rnu))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the number of requested sign columns, based on user / configuration.
|
|
||||||
int win_signcol_configured(win_T *wp)
|
|
||||||
{
|
|
||||||
const char *scl = wp->w_p_scl;
|
|
||||||
|
|
||||||
if (win_no_signcol(wp)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// yes or yes
|
int needed_signcols = buf_signcols(wp->w_buffer, wp->w_maxscwidth);
|
||||||
if (!strncmp(scl, "yes:", 4)) {
|
int ret = MAX(wp->w_minscwidth, MIN(wp->w_maxscwidth, needed_signcols));
|
||||||
// Fixed amount of columns
|
|
||||||
return scl[4] - '0';
|
|
||||||
}
|
|
||||||
if (*scl == 'y') {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int minimum = 0, maximum = 1;
|
|
||||||
|
|
||||||
if (!strncmp(scl, "auto:", 5)) {
|
|
||||||
// Variable depending on a configuration
|
|
||||||
maximum = scl[5] - '0';
|
|
||||||
// auto:<NUM>-<NUM>
|
|
||||||
if (strlen(scl) == 8 && *(scl + 6) == '-') {
|
|
||||||
minimum = maximum;
|
|
||||||
maximum = scl[7] - '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int needed_signcols = buf_signcols(wp->w_buffer, maximum);
|
|
||||||
int ret = MAX(minimum, MIN(maximum, needed_signcols));
|
|
||||||
assert(ret <= SIGN_SHOW_MAX);
|
assert(ret <= SIGN_SHOW_MAX);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -947,3 +947,6 @@ enum {
|
|||||||
#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
|
#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
|
||||||
|
|
||||||
#define TABSTOP_MAX 9999
|
#define TABSTOP_MAX 9999
|
||||||
|
|
||||||
|
#define SCL_NO -1 // 'signcolumn' set to "no"
|
||||||
|
#define SCL_NUM -2 // 'signcolumn' set to "number"
|
||||||
|
@@ -388,34 +388,53 @@ static bool valid_filetype(const char *val)
|
|||||||
return valid_name(val, ".-_");
|
return valid_name(val, ".-_");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle setting 'signcolumn' for value 'val'
|
/// Handle setting 'signcolumn' for value 'val'. Store minimum and maximum width.
|
||||||
///
|
///
|
||||||
/// @return OK when the value is valid, FAIL otherwise
|
/// @return OK when the value is valid, FAIL otherwise
|
||||||
static int check_signcolumn(char *val)
|
int check_signcolumn(win_T *wp)
|
||||||
{
|
{
|
||||||
|
char *val = wp->w_p_scl;
|
||||||
if (*val == NUL) {
|
if (*val == NUL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
// check for basic match
|
|
||||||
if (check_opt_strings(val, p_scl_values, false) == OK) {
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for 'auto:<NUMBER>-<NUMBER>'
|
if (check_opt_strings(val, p_scl_values, false) == OK) {
|
||||||
if (strlen(val) == 8
|
if (!strncmp(val, "no", 2)) { // no
|
||||||
&& !strncmp(val, "auto:", 5)
|
wp->w_minscwidth = wp->w_maxscwidth = SCL_NO;
|
||||||
&& ascii_isdigit(val[5])
|
} else if (!strncmp(val, "nu", 2) && (wp->w_p_nu || wp->w_p_rnu)) { // number
|
||||||
&& val[6] == '-'
|
wp->w_minscwidth = wp->w_maxscwidth = SCL_NUM;
|
||||||
&& ascii_isdigit(val[7])) {
|
} else if (!strncmp(val, "yes:", 4)) { // yes:<NUM>
|
||||||
int min = val[5] - '0';
|
wp->w_minscwidth = wp->w_maxscwidth = val[4] - '0';
|
||||||
int max = val[7] - '0';
|
} else if (*val == 'y') { // yes
|
||||||
if (min < 1 || max < 2 || min > 8 || max > 9 || min >= max) {
|
wp->w_minscwidth = wp->w_maxscwidth = 1;
|
||||||
return FAIL;
|
} else if (!strncmp(val, "auto:", 5)) { // auto:<NUM>
|
||||||
|
wp->w_minscwidth = 0;
|
||||||
|
wp->w_maxscwidth = val[5] - '0';
|
||||||
|
} else { // auto
|
||||||
|
wp->w_minscwidth = 0;
|
||||||
|
wp->w_maxscwidth = 1;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FAIL;
|
if (strncmp(val, "auto:", 5) != 0
|
||||||
|
|| strlen(val) != 8
|
||||||
|
|| !ascii_isdigit(val[5])
|
||||||
|
|| val[6] != '-'
|
||||||
|
|| !ascii_isdigit(val[7])) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto:<NUM>-<NUM>
|
||||||
|
int min = val[5] - '0';
|
||||||
|
int max = val[7] - '0';
|
||||||
|
if (min < 1 || max < 2 || min > 8 || min >= max) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp->w_minscwidth = min;
|
||||||
|
wp->w_maxscwidth = max;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check validity of options with the 'statusline' format.
|
/// Check validity of options with the 'statusline' format.
|
||||||
@@ -2072,16 +2091,13 @@ int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches)
|
|||||||
const char *did_set_signcolumn(optset_T *args)
|
const char *did_set_signcolumn(optset_T *args)
|
||||||
{
|
{
|
||||||
win_T *win = (win_T *)args->os_win;
|
win_T *win = (win_T *)args->os_win;
|
||||||
char **varp = (char **)args->os_varp;
|
|
||||||
const char *oldval = args->os_oldval.string.data;
|
const char *oldval = args->os_oldval.string.data;
|
||||||
if (check_signcolumn(*varp) != OK) {
|
if (check_signcolumn(win) != OK) {
|
||||||
return e_invarg;
|
return e_invarg;
|
||||||
}
|
}
|
||||||
// When changing the 'signcolumn' to or from 'number', recompute the
|
// When changing the 'signcolumn' to or from 'number', recompute the
|
||||||
// width of the number column if 'number' or 'relativenumber' is set.
|
// width of the number column if 'number' or 'relativenumber' is set.
|
||||||
if (((*oldval == 'n' && *(oldval + 1) == 'u')
|
if ((*oldval == 'n' && *(oldval + 1) == 'u') || win->w_minscwidth == SCL_NUM) {
|
||||||
|| (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u'))
|
|
||||||
&& (win->w_p_nu || win->w_p_rnu)) {
|
|
||||||
win->w_nrwidth_line_count = 0;
|
win->w_nrwidth_line_count = 0;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Reference in New Issue
Block a user