mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 21:25:04 -07:00
signs: support multiple columns #9295
closes #990 closes #9295 - Support for multiple auto-adjusted sign columns. With this change, having more than one sign on a line, and with the 'auto' setting on 'signcolumn', extra columns will shown automatically to accomodate all the existing signs. For example, suppose we have this view: 5147 } 5148 5149 return sign->typenr; 5150 } 5151 } 5152 return 0; 5153 } 5154 We have GitGutter installed, so it tells us about modified lines that are not commmited. So let's change line 5152: 5147 } 5148 5149 return sign->typenr; 5150 } 5151 } ~ 5152 return 0; 5153 } 5154 Now we add a mark over line 5152 using 'ma' in normal mode: 5147 } 5148 5149 return sign->typenr; 5150 } 5151 } a ~ 5152 return 0; 5153 } 5154 Previously, Vim/Nvim would have picked only one of the signs, because there was no support for having multiple signs in a line. - Remove signs from deleted lines. Suppose we have highlights on a group of lines and we delete them: + 6 use std::ops::Deref; --+ 7 use std::borrow::Cow; --+ 8 use std::io::{Cursor}; 9 use proc_macro2::TokenStream; 10 use syn::export::ToTokens; --+ 11 use std::io::Write; >> 12 use std::ops::Deref; Without this change, these signs will momentarily accumulate in the sign column until the plugins wake up to refresh them. + --+ --+ --+ >> 6 Discussion: It may be better to extend the API a bit and allow this to happen for only certain types of signs. For example, VIM marks and vim-gitgutter removal signs may want to be presreved, unlike line additions and linter highlights. - 'signcolumn': support 'auto:NUM' and 'yes:NUM' settings - sort signs according to id, from lowest to highest. If you have git-gutter, vim-signature, and ALE, it would appear in this order: git-gutter - vim-signature - ALE. - recalculate size before screen update - If no space for all signs, prefer the higher ids (while keeping the rendering order from low to high). - Prevent duplicate signs. Duplicate signs were invisible to the user, before using our extended non-standard signcolumn settings. - multi signcols: fix bug related to wrapped lines. In wrapped lines, the wrapped parts of a line did not include the extra columns if they existed. The result was a misdrawing of the wrapped parts. Fix the issue by: 1. initializing the signcol counter to 0 when we are on a wrap boundary 2. allowing for the draw of spaces in that case.
This commit is contained in:
parent
f705ed22fd
commit
36762a00a8
@ -5403,10 +5403,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
*'signcolumn'* *'scl'*
|
*'signcolumn'* *'scl'*
|
||||||
'signcolumn' 'scl' string (default "auto")
|
'signcolumn' 'scl' string (default "auto")
|
||||||
local to window
|
local to window
|
||||||
Whether or not to draw the signcolumn. Valid values are:
|
When and how to draw the signcolumn. Valid values are:
|
||||||
"auto" only when there is a sign to display
|
"auto" only when there is a sign to display
|
||||||
|
"auto:[1-9]" resize to accommodate multiple signs up to the
|
||||||
|
given number (maximum 9), e.g. "auto:4"
|
||||||
"no" never
|
"no" never
|
||||||
"yes" always
|
"yes" always
|
||||||
|
"yes:[1-9]" always, with fixed space for signs up to the given
|
||||||
|
number (maximum 9), e.g. "yes:3"
|
||||||
|
|
||||||
|
|
||||||
*'smartcase'* *'scs'* *'nosmartcase'* *'noscs'*
|
*'smartcase'* *'scs'* *'nosmartcase'* *'noscs'*
|
||||||
|
@ -857,7 +857,7 @@ Short explanation of each option: *option-list*
|
|||||||
'showtabline' 'stal' tells when the tab pages line is displayed
|
'showtabline' 'stal' tells when the tab pages line is displayed
|
||||||
'sidescroll' 'ss' minimum number of columns to scroll horizontal
|
'sidescroll' 'ss' minimum number of columns to scroll horizontal
|
||||||
'sidescrolloff' 'siso' min. nr. of columns to left and right of cursor
|
'sidescrolloff' 'siso' min. nr. of columns to left and right of cursor
|
||||||
'signcolumn' 'scl' when to display the sign column
|
'signcolumn' 'scl' when and how to display the sign column
|
||||||
'smartcase' 'scs' no ignore case when pattern has uppercase
|
'smartcase' 'scs' no ignore case when pattern has uppercase
|
||||||
'smartindent' 'si' smart autoindenting for C programs
|
'smartindent' 'si' smart autoindenting for C programs
|
||||||
'smarttab' 'sta' use 'shiftwidth' when inserting <Tab>
|
'smarttab' 'sta' use 'shiftwidth' when inserting <Tab>
|
||||||
|
@ -193,11 +193,15 @@ Options:
|
|||||||
'listchars' local to window
|
'listchars' local to window
|
||||||
'pumblend' pseudo-transparent popupmenu
|
'pumblend' pseudo-transparent popupmenu
|
||||||
'scrollback'
|
'scrollback'
|
||||||
|
'signcolumn' supports up to 9 dynamic/fixed columns
|
||||||
'statusline' supports unlimited alignment sections
|
'statusline' supports unlimited alignment sections
|
||||||
'tabline' %@Func@foo%X can call any function on mouse-click
|
'tabline' %@Func@foo%X can call any function on mouse-click
|
||||||
'wildoptions' `pum` flag to use popupmenu for wildmode completion
|
'wildoptions' `pum` flag to use popupmenu for wildmode completion
|
||||||
'winhighlight' window-local highlights
|
'winhighlight' window-local highlights
|
||||||
|
|
||||||
|
Signs:
|
||||||
|
Signs are removed if the associated line is deleted.
|
||||||
|
|
||||||
Variables:
|
Variables:
|
||||||
|v:event|
|
|v:event|
|
||||||
|v:exiting|
|
|v:exiting|
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
/*
|
//
|
||||||
* buffer.c: functions for dealing with the buffer structure
|
// buffer.c: functions for dealing with the buffer structure
|
||||||
*/
|
//
|
||||||
|
|
||||||
/*
|
//
|
||||||
* The buffer list is a double linked list of all buffers.
|
// The buffer list is a double linked list of all buffers.
|
||||||
* Each buffer can be in one of these states:
|
// Each buffer can be in one of these states:
|
||||||
* never loaded: BF_NEVERLOADED is set, only the file name is valid
|
// never loaded: BF_NEVERLOADED is set, only the file name is valid
|
||||||
* not loaded: b_ml.ml_mfp == NULL, no memfile allocated
|
// not loaded: b_ml.ml_mfp == NULL, no memfile allocated
|
||||||
* hidden: b_nwindows == 0, loaded but not displayed in a window
|
// hidden: b_nwindows == 0, loaded but not displayed in a window
|
||||||
* normal: loaded and displayed in a window
|
// normal: loaded and displayed in a window
|
||||||
*
|
//
|
||||||
* Instead of storing file names all over the place, each file name is
|
// Instead of storing file names all over the place, each file name is
|
||||||
* stored in the buffer list. It can be referenced by a number.
|
// stored in the buffer list. It can be referenced by a number.
|
||||||
*
|
//
|
||||||
* The current implementation remembers all file names ever used.
|
// The current implementation remembers all file names ever used.
|
||||||
*/
|
//
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -1688,6 +1688,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
|||||||
buf = xcalloc(1, sizeof(buf_T));
|
buf = xcalloc(1, sizeof(buf_T));
|
||||||
// init b: variables
|
// init b: variables
|
||||||
buf->b_vars = tv_dict_alloc();
|
buf->b_vars = tv_dict_alloc();
|
||||||
|
buf->b_signcols_max = -1;
|
||||||
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
||||||
buf_init_changedtick(buf);
|
buf_init_changedtick(buf);
|
||||||
}
|
}
|
||||||
@ -5046,6 +5047,7 @@ static void insert_sign(
|
|||||||
if (next != NULL) {
|
if (next != NULL) {
|
||||||
next->prev = newsign;
|
next->prev = newsign;
|
||||||
}
|
}
|
||||||
|
buf->b_signcols_max = -1;
|
||||||
|
|
||||||
if (prev == NULL) {
|
if (prev == NULL) {
|
||||||
/* When adding first sign need to redraw the windows to create the
|
/* When adding first sign need to redraw the windows to create the
|
||||||
@ -5063,6 +5065,96 @@ static void insert_sign(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sign_compare(const void *a1, const void *a2)
|
||||||
|
{
|
||||||
|
const signlist_T *s1 = *(const signlist_T **)a1;
|
||||||
|
const signlist_T *s2 = *(const signlist_T **)a2;
|
||||||
|
|
||||||
|
// Sort by line number and the by id
|
||||||
|
|
||||||
|
if (s1->lnum > s2->lnum) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (s1->lnum < s2->lnum) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (s1->id > s2->id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (s1->id < s2->id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buf_signcols(buf_T *buf)
|
||||||
|
{
|
||||||
|
if (buf->b_signcols_max == -1) {
|
||||||
|
signlist_T *sign; // a sign in the signlist
|
||||||
|
signlist_T **signs_array;
|
||||||
|
signlist_T **prev_sign;
|
||||||
|
int nr_signs = 0, i = 0, same;
|
||||||
|
|
||||||
|
// Count the number of signs
|
||||||
|
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
||||||
|
nr_signs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an array of all the signs
|
||||||
|
signs_array = xcalloc((size_t)nr_signs, sizeof(*sign));
|
||||||
|
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
||||||
|
signs_array[i] = sign;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the array
|
||||||
|
qsort(signs_array, (size_t)nr_signs, sizeof(signlist_T *),
|
||||||
|
sign_compare);
|
||||||
|
|
||||||
|
// Find the maximum amount of signs existing in a single line
|
||||||
|
buf->b_signcols_max = 0;
|
||||||
|
|
||||||
|
same = 1;
|
||||||
|
for (i = 1; i < nr_signs; i++) {
|
||||||
|
if (signs_array[i - 1]->lnum != signs_array[i]->lnum) {
|
||||||
|
if (buf->b_signcols_max < same) {
|
||||||
|
buf->b_signcols_max = same;
|
||||||
|
}
|
||||||
|
same = 1;
|
||||||
|
} else {
|
||||||
|
same++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_signs > 0 && buf->b_signcols_max < same) {
|
||||||
|
buf->b_signcols_max = same;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate the linked list with the sorted order of the array
|
||||||
|
buf->b_signlist = NULL;
|
||||||
|
prev_sign = &buf->b_signlist;
|
||||||
|
|
||||||
|
for (i = 0; i < nr_signs; i++) {
|
||||||
|
sign = signs_array[i];
|
||||||
|
sign->next = NULL;
|
||||||
|
*prev_sign = sign;
|
||||||
|
|
||||||
|
prev_sign = &sign->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(signs_array);
|
||||||
|
|
||||||
|
// Check if we need to redraw
|
||||||
|
if (buf->b_signcols_max != buf->b_signcols) {
|
||||||
|
buf->b_signcols = buf->b_signcols_max;
|
||||||
|
redraw_buf_later(buf, NOT_VALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf->b_signcols;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the sign into the signlist. Find the right spot to do it though.
|
* Add the sign into the signlist. Find the right spot to do it though.
|
||||||
*/
|
*/
|
||||||
@ -5073,8 +5165,9 @@ void buf_addsign(
|
|||||||
int typenr /* typenr of sign we are adding */
|
int typenr /* typenr of sign we are adding */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
signlist_T *sign; /* a sign in the signlist */
|
signlist_T **lastp; // pointer to pointer to current sign
|
||||||
signlist_T *prev; /* the previous sign */
|
signlist_T *sign; // a sign in the signlist
|
||||||
|
signlist_T *prev; // the previous sign
|
||||||
|
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
||||||
@ -5110,7 +5203,18 @@ void buf_addsign(
|
|||||||
}
|
}
|
||||||
insert_sign(buf, prev, sign, id, lnum, typenr);
|
insert_sign(buf, prev, sign, id, lnum, typenr);
|
||||||
|
|
||||||
return;
|
// Having more than one sign with _the same type_ and on the _same line_ is
|
||||||
|
// unwanted, let's prevent it.
|
||||||
|
|
||||||
|
lastp = &buf->b_signlist;
|
||||||
|
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
||||||
|
if (lnum == sign->lnum && sign->typenr == typenr && id != sign->id) {
|
||||||
|
*lastp = sign->next;
|
||||||
|
xfree(sign);
|
||||||
|
} else {
|
||||||
|
lastp = &sign->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For an existing, placed sign "markId" change the type to "typenr".
|
// For an existing, placed sign "markId" change the type to "typenr".
|
||||||
@ -5133,16 +5237,23 @@ linenr_T buf_change_sign_type(
|
|||||||
return (linenr_T)0;
|
return (linenr_T)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Gets a sign from a given line.
|
/// Gets a sign from a given line.
|
||||||
/// In case of multiple signs, returns the most recently placed one.
|
|
||||||
///
|
///
|
||||||
/// @param buf Buffer in which to search
|
/// @param buf Buffer in which to search
|
||||||
/// @param lnum Line in which to search
|
/// @param lnum Line in which to search
|
||||||
/// @param type Type of sign to look for
|
/// @param type Type of sign to look for
|
||||||
/// @return Identifier of the first matching sign, or 0
|
/// @param idx if there multiple signs, this index will pick the n-th
|
||||||
int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type)
|
// out of the most `max_signs` sorted ascending by Id.
|
||||||
|
/// @param max_signs the number of signs, with priority for the ones
|
||||||
|
// with the highest Ids.
|
||||||
|
/// @return Identifier of the matching sign, or 0
|
||||||
|
int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type,
|
||||||
|
int idx, int max_signs)
|
||||||
{
|
{
|
||||||
signlist_T *sign; // a sign in a b_signlist
|
signlist_T *sign; // a sign in a b_signlist
|
||||||
|
signlist_T *matches[9];
|
||||||
|
int nr_matches = 0;
|
||||||
|
|
||||||
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
for (sign = buf->b_signlist; sign != NULL; sign = sign->next) {
|
||||||
if (sign->lnum == lnum
|
if (sign->lnum == lnum
|
||||||
@ -5153,13 +5264,30 @@ int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type)
|
|||||||
&& sign_get_attr(sign->typenr, SIGN_LINEHL) != 0)
|
&& sign_get_attr(sign->typenr, SIGN_LINEHL) != 0)
|
||||||
|| (type == SIGN_NUMHL
|
|| (type == SIGN_NUMHL
|
||||||
&& sign_get_attr(sign->typenr, SIGN_NUMHL) != 0))) {
|
&& sign_get_attr(sign->typenr, SIGN_NUMHL) != 0))) {
|
||||||
return sign->typenr;
|
matches[nr_matches] = sign;
|
||||||
|
nr_matches++;
|
||||||
|
|
||||||
|
if (nr_matches == ARRAY_SIZE(matches)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nr_matches > 0) {
|
||||||
|
if (nr_matches > max_signs) {
|
||||||
|
idx += nr_matches - max_signs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx >= nr_matches) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches[idx]->typenr;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
linenr_T buf_delsign(
|
linenr_T buf_delsign(
|
||||||
buf_T *buf, /* buffer sign is stored in */
|
buf_T *buf, /* buffer sign is stored in */
|
||||||
int id /* sign id */
|
int id /* sign id */
|
||||||
@ -5170,6 +5298,7 @@ linenr_T buf_delsign(
|
|||||||
signlist_T *next; /* the next sign in a b_signlist */
|
signlist_T *next; /* the next sign in a b_signlist */
|
||||||
linenr_T lnum; /* line number whose sign was deleted */
|
linenr_T lnum; /* line number whose sign was deleted */
|
||||||
|
|
||||||
|
buf->b_signcols_max = -1;
|
||||||
lastp = &buf->b_signlist;
|
lastp = &buf->b_signlist;
|
||||||
lnum = 0;
|
lnum = 0;
|
||||||
for (sign = buf->b_signlist; sign != NULL; sign = next) {
|
for (sign = buf->b_signlist; sign != NULL; sign = next) {
|
||||||
@ -5255,6 +5384,7 @@ void buf_delete_signs(buf_T *buf)
|
|||||||
xfree(buf->b_signlist);
|
xfree(buf->b_signlist);
|
||||||
buf->b_signlist = next;
|
buf->b_signlist = next;
|
||||||
}
|
}
|
||||||
|
buf->b_signcols_max = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5309,18 +5439,27 @@ void sign_list_placed(buf_T *rbuf)
|
|||||||
*/
|
*/
|
||||||
void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after)
|
void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after)
|
||||||
{
|
{
|
||||||
signlist_T *sign; /* a sign in a b_signlist */
|
signlist_T *sign; // a sign in a b_signlist
|
||||||
|
signlist_T *next; // the next sign in a b_signlist
|
||||||
|
signlist_T **lastp; // pointer to pointer to current sign
|
||||||
|
|
||||||
for (sign = curbuf->b_signlist; sign != NULL; sign = sign->next) {
|
curbuf->b_signcols_max = -1;
|
||||||
|
lastp = &curbuf->b_signlist;
|
||||||
|
|
||||||
|
for (sign = curbuf->b_signlist; sign != NULL; sign = next) {
|
||||||
|
next = sign->next;
|
||||||
if (sign->lnum >= line1 && sign->lnum <= line2) {
|
if (sign->lnum >= line1 && sign->lnum <= line2) {
|
||||||
if (amount == MAXLNUM) {
|
if (amount == MAXLNUM) {
|
||||||
sign->lnum = line1;
|
*lastp = next;
|
||||||
|
xfree(sign);
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
sign->lnum += amount;
|
sign->lnum += amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sign->lnum > line2)
|
else if (sign->lnum > line2)
|
||||||
sign->lnum += amount_after;
|
sign->lnum += amount_after;
|
||||||
|
lastp = &sign->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,7 +778,9 @@ struct file_buffer {
|
|||||||
* normally points to this, but some windows
|
* normally points to this, but some windows
|
||||||
* may use a different synblock_T. */
|
* may use a different synblock_T. */
|
||||||
|
|
||||||
signlist_T *b_signlist; /* list of signs to draw */
|
signlist_T *b_signlist; // list of signs to draw
|
||||||
|
int b_signcols_max; // cached maximum number of sign columns
|
||||||
|
int b_signcols; // last calculated number of sign columns
|
||||||
|
|
||||||
Terminal *terminal; // Terminal instance associated with the buffer
|
Terminal *terminal; // Terminal instance associated with the buffer
|
||||||
|
|
||||||
|
@ -5899,10 +5899,7 @@ comp_textwidth (
|
|||||||
textwidth -= 1;
|
textwidth -= 1;
|
||||||
}
|
}
|
||||||
textwidth -= curwin->w_p_fdc;
|
textwidth -= curwin->w_p_fdc;
|
||||||
|
textwidth -= win_signcol_count(curwin);
|
||||||
if (signcolumn_on(curwin)) {
|
|
||||||
textwidth -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curwin->w_p_nu || curwin->w_p_rnu)
|
if (curwin->w_p_nu || curwin->w_p_rnu)
|
||||||
textwidth -= 8;
|
textwidth -= 8;
|
||||||
|
@ -692,7 +692,7 @@ int win_col_off(win_T *wp)
|
|||||||
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
|
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
|
||||||
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
|
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
|
||||||
+ (int)wp->w_p_fdc
|
+ (int)wp->w_p_fdc
|
||||||
+ (signcolumn_on(wp) ? win_signcol_width(wp) : 0);
|
+ (win_signcol_count(wp) * win_signcol_width(wp));
|
||||||
}
|
}
|
||||||
|
|
||||||
int curwin_col_off(void)
|
int curwin_col_off(void)
|
||||||
|
@ -305,7 +305,10 @@ static char *(p_fcl_values[]) = { "all", NULL };
|
|||||||
static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview",
|
static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview",
|
||||||
"noinsert", "noselect", NULL };
|
"noinsert", "noselect", NULL };
|
||||||
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
|
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
|
||||||
static char *(p_scl_values[]) = { "yes", "no", "auto", NULL };
|
static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2",
|
||||||
|
"auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9",
|
||||||
|
"yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8",
|
||||||
|
"yes:9", NULL };
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "option.c.generated.h"
|
# include "option.c.generated.h"
|
||||||
@ -7091,16 +7094,34 @@ int csh_like_shell(void)
|
|||||||
return strstr((char *)path_tail(p_sh), "csh") != NULL;
|
return strstr((char *)path_tail(p_sh), "csh") != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true when window "wp" has a column to draw signs in.
|
/// Return the number of requested sign columns, based on current
|
||||||
bool signcolumn_on(win_T *wp)
|
/// buffer signs and on user configuration.
|
||||||
|
int win_signcol_count(win_T *wp)
|
||||||
{
|
{
|
||||||
if (*wp->w_p_scl == 'n') {
|
int maximum = 1, needed_signcols;
|
||||||
return false;
|
const char *scl = (const char *)wp->w_p_scl;
|
||||||
}
|
|
||||||
if (*wp->w_p_scl == 'y') {
|
if (*scl == 'n') {
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
return wp->w_buffer->b_signlist != NULL;
|
needed_signcols = buf_signcols(wp->w_buffer);
|
||||||
|
|
||||||
|
// yes or yes
|
||||||
|
if (!strncmp(scl, "yes:", 4)) {
|
||||||
|
// Fixed amount of columns
|
||||||
|
return scl[4] - '0';
|
||||||
|
}
|
||||||
|
if (*scl == 'y') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto or auto:<NUM>
|
||||||
|
if (!strncmp(scl, "auto:", 5)) {
|
||||||
|
// Variable depending on a configuration
|
||||||
|
maximum = scl[5] - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIN(maximum, needed_signcols);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get window or buffer local options
|
/// Get window or buffer local options
|
||||||
|
@ -621,6 +621,11 @@ static void win_update(win_T *wp)
|
|||||||
linenr_T mod_bot = 0;
|
linenr_T mod_bot = 0;
|
||||||
int save_got_int;
|
int save_got_int;
|
||||||
|
|
||||||
|
// If we can compute a change in the automatic sizing of the sign column
|
||||||
|
// under 'signcolumn=auto:X' and signs currently placed in the buffer, better
|
||||||
|
// figuring it out here so we can redraw the entire screen for it.
|
||||||
|
buf_signcols(buf);
|
||||||
|
|
||||||
type = wp->w_redr_type;
|
type = wp->w_redr_type;
|
||||||
|
|
||||||
win_grid_alloc(wp);
|
win_grid_alloc(wp);
|
||||||
@ -1568,8 +1573,9 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
|
|||||||
wp->w_grid.Columns, ' ', ' ', win_hl_attr(wp, HLF_FC));
|
wp->w_grid.Columns, ' ', ' ', win_hl_attr(wp, HLF_FC));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signcolumn_on(wp)) {
|
int count = win_signcol_count(wp);
|
||||||
int nn = n + win_signcol_width(wp);
|
if (count > 0) {
|
||||||
|
int nn = n + win_signcol_width(wp) * count;
|
||||||
|
|
||||||
// draw the sign column left of the fold column
|
// draw the sign column left of the fold column
|
||||||
if (nn > wp->w_grid.Columns) {
|
if (nn > wp->w_grid.Columns) {
|
||||||
@ -1607,8 +1613,9 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
|
|||||||
n = nn;
|
n = nn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signcolumn_on(wp)) {
|
int count = win_signcol_count(wp);
|
||||||
int nn = n + win_signcol_width(wp);
|
if (count > 0) {
|
||||||
|
int nn = n + win_signcol_width(wp) * count;
|
||||||
|
|
||||||
// draw the sign column after the fold column
|
// draw the sign column after the fold column
|
||||||
if (nn > wp->w_grid.Columns) {
|
if (nn > wp->w_grid.Columns) {
|
||||||
@ -1773,10 +1780,10 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
|
|||||||
RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col);
|
RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col);
|
||||||
|
|
||||||
// If signs are being displayed, add spaces.
|
// If signs are being displayed, add spaces.
|
||||||
if (signcolumn_on(wp)) {
|
if (win_signcol_count(wp) > 0) {
|
||||||
len = wp->w_grid.Columns - col;
|
len = wp->w_grid.Columns - col;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
int len_max = win_signcol_width(wp);
|
int len_max = win_signcol_width(wp) * win_signcol_count(wp);
|
||||||
if (len > len_max) {
|
if (len > len_max) {
|
||||||
len = len_max;
|
len = len_max;
|
||||||
}
|
}
|
||||||
@ -2404,7 +2411,7 @@ win_line (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this line has a sign with line highlighting set line_attr.
|
// If this line has a sign with line highlighting set line_attr.
|
||||||
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
|
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL, 0, 1);
|
||||||
if (v != 0) {
|
if (v != 0) {
|
||||||
line_attr = sign_get_attr((int)v, SIGN_LINEHL);
|
line_attr = sign_get_attr((int)v, SIGN_LINEHL);
|
||||||
}
|
}
|
||||||
@ -2654,6 +2661,7 @@ win_line (
|
|||||||
extra_check = true;
|
extra_check = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sign_idx = 0;
|
||||||
// Repeat for the whole displayed line.
|
// Repeat for the whole displayed line.
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
has_match_conc = 0;
|
has_match_conc = 0;
|
||||||
@ -2694,7 +2702,8 @@ win_line (
|
|||||||
draw_state = WL_SIGN;
|
draw_state = WL_SIGN;
|
||||||
/* Show the sign column when there are any signs in this
|
/* Show the sign column when there are any signs in this
|
||||||
* buffer or when using Netbeans. */
|
* buffer or when using Netbeans. */
|
||||||
if (signcolumn_on(wp)) {
|
int count = win_signcol_count(wp);
|
||||||
|
if (count > 0) {
|
||||||
int text_sign;
|
int text_sign;
|
||||||
// Draw cells with the sign value or blank.
|
// Draw cells with the sign value or blank.
|
||||||
c_extra = ' ';
|
c_extra = ' ';
|
||||||
@ -2703,7 +2712,8 @@ win_line (
|
|||||||
n_extra = win_signcol_width(wp);
|
n_extra = win_signcol_width(wp);
|
||||||
|
|
||||||
if (row == startrow + filler_lines && filler_todo <= 0) {
|
if (row == startrow + filler_lines && filler_todo <= 0) {
|
||||||
text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT);
|
text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT,
|
||||||
|
sign_idx, count);
|
||||||
if (text_sign != 0) {
|
if (text_sign != 0) {
|
||||||
p_extra = sign_get_text(text_sign);
|
p_extra = sign_get_text(text_sign);
|
||||||
int symbol_blen = (int)STRLEN(p_extra);
|
int symbol_blen = (int)STRLEN(p_extra);
|
||||||
@ -2721,6 +2731,11 @@ win_line (
|
|||||||
char_attr = sign_get_attr(text_sign, SIGN_TEXT);
|
char_attr = sign_get_attr(text_sign, SIGN_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sign_idx++;
|
||||||
|
if (sign_idx < count) {
|
||||||
|
draw_state = WL_SIGN - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2769,7 +2784,8 @@ win_line (
|
|||||||
n_extra = number_width(wp) + 1;
|
n_extra = number_width(wp) + 1;
|
||||||
char_attr = win_hl_attr(wp, HLF_N);
|
char_attr = win_hl_attr(wp, HLF_N);
|
||||||
|
|
||||||
int num_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_NUMHL);
|
int num_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_NUMHL,
|
||||||
|
0, 1);
|
||||||
if (num_sign != 0) {
|
if (num_sign != 0) {
|
||||||
// :sign defined with "numhl" highlight.
|
// :sign defined with "numhl" highlight.
|
||||||
char_attr = sign_get_attr(num_sign, SIGN_NUMHL);
|
char_attr = sign_get_attr(num_sign, SIGN_NUMHL);
|
||||||
@ -2856,6 +2872,7 @@ win_line (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (draw_state == WL_LINE - 1 && n_extra == 0) {
|
if (draw_state == WL_LINE - 1 && n_extra == 0) {
|
||||||
|
sign_idx = 0;
|
||||||
draw_state = WL_LINE;
|
draw_state = WL_LINE;
|
||||||
if (saved_n_extra) {
|
if (saved_n_extra) {
|
||||||
/* Continue item from end of wrapped line. */
|
/* Continue item from end of wrapped line. */
|
||||||
|
@ -115,6 +115,115 @@ describe('Signs', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('multiple signs #9295', function()
|
||||||
|
feed('ia<cr>b<cr>c<cr><esc>')
|
||||||
|
command('set number')
|
||||||
|
command('set signcolumn=yes:2')
|
||||||
|
command('sign define pietSearch text=>> texthl=Search')
|
||||||
|
command('sign define pietError text=XX texthl=Error')
|
||||||
|
command('sign define pietWarn text=WW texthl=Warning')
|
||||||
|
command('sign place 1 line=1 name=pietSearch buffer=1')
|
||||||
|
command('sign place 2 line=1 name=pietError buffer=1')
|
||||||
|
-- Line 2 helps checking that signs in the same line are ordered by Id.
|
||||||
|
command('sign place 4 line=2 name=pietSearch buffer=1')
|
||||||
|
command('sign place 3 line=2 name=pietError buffer=1')
|
||||||
|
-- Line 3 checks that with a limit over the maximum number
|
||||||
|
-- of signs, the ones with the highest Ids are being picked,
|
||||||
|
-- and presented by their sorted Id order.
|
||||||
|
command('sign place 4 line=3 name=pietSearch buffer=1')
|
||||||
|
command('sign place 5 line=3 name=pietWarn buffer=1')
|
||||||
|
command('sign place 3 line=3 name=pietError buffer=1')
|
||||||
|
screen:expect([[
|
||||||
|
{1:>>}XX{6: 1 }a |
|
||||||
|
XX{1:>>}{6: 2 }b |
|
||||||
|
{1:>>}WW{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
-- With the default setting, we get the sign with the top id.
|
||||||
|
command('set signcolumn=yes:1')
|
||||||
|
screen:expect([[
|
||||||
|
XX{6: 1 }a |
|
||||||
|
{1:>>}{6: 2 }b |
|
||||||
|
WW{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
-- "auto:3" accommodates all the signs we defined so far.
|
||||||
|
command('set signcolumn=auto:3')
|
||||||
|
screen:expect([[
|
||||||
|
{1:>>}XX{2: }{6: 1 }a |
|
||||||
|
XX{1:>>}{2: }{6: 2 }b |
|
||||||
|
XX{1:>>}WW{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
-- Check "yes:9".
|
||||||
|
command('set signcolumn=yes:9')
|
||||||
|
screen:expect([[
|
||||||
|
{1:>>}XX{2: }{6: 1 }a |
|
||||||
|
XX{1:>>}{2: }{6: 2 }b |
|
||||||
|
XX{1:>>}WW{2: }{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
-- Check "auto:N" larger than the maximum number of signs defined in
|
||||||
|
-- a single line (same result as "auto:3").
|
||||||
|
command('set signcolumn=auto:4')
|
||||||
|
screen:expect{grid=[[
|
||||||
|
{1:>>}XX{2: }{6: 1 }a |
|
||||||
|
XX{1:>>}{2: }{6: 2 }b |
|
||||||
|
XX{1:>>}WW{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
{2: }{0:~ }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
|
|
||||||
it('can have 32bit sign IDs', function()
|
it('can have 32bit sign IDs', function()
|
||||||
command('sign define piet text=>> texthl=Search')
|
command('sign define piet text=>> texthl=Search')
|
||||||
command('sign place 100000 line=1 name=piet buffer=1')
|
command('sign place 100000 line=1 name=piet buffer=1')
|
||||||
|
Loading…
Reference in New Issue
Block a user