mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 06:28:35 +00:00
Merge pull request #25724 from luukvbaal/signmerge
refactor(sign): move legacy signs to extmarks
This commit is contained in:
@@ -2566,8 +2566,8 @@ nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
|
|||||||
|
|
||||||
*nvim_buf_get_extmarks()*
|
*nvim_buf_get_extmarks()*
|
||||||
nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
|
nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
|
||||||
Gets |extmarks| in "traversal order" from a |charwise| region defined by
|
Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
|
||||||
buffer positions (inclusive, 0-indexed |api-indexing|).
|
region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||||
|
|
||||||
Region can be given as (row,col) tuples, or valid extmark ids (whose
|
Region can be given as (row,col) tuples, or valid extmark ids (whose
|
||||||
positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
||||||
|
@@ -87,6 +87,14 @@ The following changes may require adaptations in user config or plugins.
|
|||||||
the option is set (e.g. using |:set| or |nvim_set_option_value()|) without a
|
the option is set (e.g. using |:set| or |nvim_set_option_value()|) without a
|
||||||
scope, which means they now behave the same way as string options.
|
scope, which means they now behave the same way as string options.
|
||||||
|
|
||||||
|
• Signs placed through the legacy |sign-commands| are now stored and displayed
|
||||||
|
as |extmarks| internally. Along with the following changes:
|
||||||
|
• A sign placed twice in the same group with the same identifier will be moved.
|
||||||
|
• Legacy signs are always deleted along with the line it is placed on.
|
||||||
|
• Legacy and extmark signs will show up in both |:sign-place-list| and |nvim_buf_get_extmarks()|.
|
||||||
|
• Legacy and extmark signs are displayed and listed with the same priority:
|
||||||
|
line number -> priority -> sign id -> recently placed
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
NEW FEATURES *news-features*
|
NEW FEATURES *news-features*
|
||||||
|
|
||||||
|
@@ -5624,12 +5624,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
"number" display signs in the 'number' column. If the number
|
"number" display signs in the 'number' column. If the number
|
||||||
column is not present, then behaves like "auto".
|
column is not present, then behaves like "auto".
|
||||||
|
|
||||||
Note regarding "orphaned signs": with signcolumn numbers higher than
|
|
||||||
1, deleting lines will also remove the associated signs automatically,
|
|
||||||
in contrast to the default Vim behavior of keeping and grouping them.
|
|
||||||
This is done in order for the signcolumn appearance not appear weird
|
|
||||||
during line deletion.
|
|
||||||
|
|
||||||
*'smartcase'* *'scs'* *'nosmartcase'* *'noscs'*
|
*'smartcase'* *'scs'* *'nosmartcase'* *'noscs'*
|
||||||
'smartcase' 'scs' boolean (default off)
|
'smartcase' 'scs' boolean (default off)
|
||||||
global
|
global
|
||||||
|
@@ -53,11 +53,10 @@ If 'cursorline' is enabled, then the CursorLineSign highlight group is used
|
|||||||
Each placed sign is identified by a number called the sign identifier. This
|
Each placed sign is identified by a number called the sign identifier. This
|
||||||
identifier is used to jump to the sign or to remove the sign. The identifier
|
identifier is used to jump to the sign or to remove the sign. The identifier
|
||||||
is assigned when placing the sign using the |:sign-place| command or the
|
is assigned when placing the sign using the |:sign-place| command or the
|
||||||
|sign_place()| function. Each sign identifier should be a unique number. If
|
|sign_place()| function. Each sign identifier should be a unique number.
|
||||||
multiple placed signs use the same identifier, then jumping to or removing a
|
Placing the same identifier twice will move the previously placed sign. The
|
||||||
sign becomes unpredictable. To avoid overlapping identifiers, sign groups can
|
|sign_place()| function can be called with a zero sign identifier to allocate
|
||||||
be used. The |sign_place()| function can be called with a zero sign identifier
|
the next available identifier.
|
||||||
to allocate the next available identifier.
|
|
||||||
|
|
||||||
*sign-group*
|
*sign-group*
|
||||||
Each placed sign can be assigned to either the global group or a named group.
|
Each placed sign can be assigned to either the global group or a named group.
|
||||||
@@ -77,9 +76,8 @@ When two signs with the same priority are present, and one has an icon or text
|
|||||||
in the signcolumn while the other has line highlighting, then both are
|
in the signcolumn while the other has line highlighting, then both are
|
||||||
displayed.
|
displayed.
|
||||||
|
|
||||||
When the line on which the sign is placed is deleted, the sign is moved to the
|
When the line on which the sign is placed is deleted, the sign is removed along
|
||||||
next line (or the last line of the buffer, if there is no next line). When
|
with it.
|
||||||
the delete is undone the sign does not move back.
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
2. Commands *sign-commands* *:sig* *:sign*
|
2. Commands *sign-commands* *:sig* *:sign*
|
||||||
@@ -177,11 +175,8 @@ See |sign_place()| for the equivalent Vim script function.
|
|||||||
space is ignored.
|
space is ignored.
|
||||||
|
|
||||||
The sign is remembered under {id}, this can be used for
|
The sign is remembered under {id}, this can be used for
|
||||||
further manipulation. {id} must be a number.
|
further manipulation. {id} must be a number. Placing the
|
||||||
It's up to the user to make sure the {id} is used only once in
|
same {id} multiple times will move the sign.
|
||||||
each file (if it's used several times unplacing will also have
|
|
||||||
to be done several times and making changes may not work as
|
|
||||||
expected).
|
|
||||||
|
|
||||||
The following optional sign attributes can be specified before
|
The following optional sign attributes can be specified before
|
||||||
"file=":
|
"file=":
|
||||||
|
@@ -340,6 +340,7 @@ Shell:
|
|||||||
|
|
||||||
Signs:
|
Signs:
|
||||||
Signs are removed if the associated line is deleted.
|
Signs are removed if the associated line is deleted.
|
||||||
|
Signs placed twice with the same identifier in the same group are moved.
|
||||||
|
|
||||||
Startup:
|
Startup:
|
||||||
|-e| and |-es| invoke the same "improved Ex mode" as -E and -Es.
|
|-e| and |-es| invoke the same "improved Ex mode" as -E and -Es.
|
||||||
|
4
runtime/lua/vim/_meta/api.lua
generated
4
runtime/lua/vim/_meta/api.lua
generated
@@ -317,8 +317,8 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end
|
|||||||
--- @return integer[]
|
--- @return integer[]
|
||||||
function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
|
function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
|
||||||
|
|
||||||
--- Gets `extmarks` in "traversal order" from a `charwise` region defined by
|
--- Gets `extmarks` (including `signs`) in "traversal order" from a `charwise`
|
||||||
--- buffer positions (inclusive, 0-indexed `api-indexing`).
|
--- region defined by buffer positions (inclusive, 0-indexed `api-indexing`).
|
||||||
--- Region can be given as (row,col) tuples, or valid extmark ids (whose
|
--- Region can be given as (row,col) tuples, or valid extmark ids (whose
|
||||||
--- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
--- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
||||||
--- respectively, thus the following are equivalent:
|
--- respectively, thus the following are equivalent:
|
||||||
|
6
runtime/lua/vim/_meta/options.lua
generated
6
runtime/lua/vim/_meta/options.lua
generated
@@ -5923,12 +5923,6 @@ vim.go.siso = vim.go.sidescrolloff
|
|||||||
--- "number" display signs in the 'number' column. If the number
|
--- "number" display signs in the 'number' column. If the number
|
||||||
--- column is not present, then behaves like "auto".
|
--- column is not present, then behaves like "auto".
|
||||||
---
|
---
|
||||||
--- Note regarding "orphaned signs": with signcolumn numbers higher than
|
|
||||||
--- 1, deleting lines will also remove the associated signs automatically,
|
|
||||||
--- in contrast to the default Vim behavior of keeping and grouping them.
|
|
||||||
--- This is done in order for the signcolumn appearance not appear weird
|
|
||||||
--- during line deletion.
|
|
||||||
---
|
|
||||||
--- @type string
|
--- @type string
|
||||||
vim.o.signcolumn = "auto"
|
vim.o.signcolumn = "auto"
|
||||||
vim.o.scl = vim.o.signcolumn
|
vim.o.scl = vim.o.signcolumn
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/pos.h"
|
#include "nvim/pos.h"
|
||||||
|
#include "nvim/sign.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ Dictionary nvim_get_namespaces(void)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *describe_ns(NS ns_id)
|
const char *describe_ns(NS ns_id, const char *unknown)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
handle_T id;
|
handle_T id;
|
||||||
@@ -90,7 +91,7 @@ const char *describe_ns(NS ns_id)
|
|||||||
return name.data;
|
return name.data;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return "(UNKNOWN PLUGIN)";
|
return unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the Namespace in use?
|
// Is the Namespace in use?
|
||||||
@@ -314,8 +315,8 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
|
|||||||
return extmark_to_array(&extmark, false, details, hl_name);
|
return extmark_to_array(&extmark, false, details, hl_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets |extmarks| in "traversal order" from a |charwise| region defined by
|
/// Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
|
||||||
/// buffer positions (inclusive, 0-indexed |api-indexing|).
|
/// region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||||
///
|
///
|
||||||
/// Region can be given as (row,col) tuples, or valid extmark ids (whose
|
/// Region can be given as (row,col) tuples, or valid extmark ids (whose
|
||||||
/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
|
||||||
@@ -750,7 +751,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (HAS_KEY(opts, set_extmark, sign_text)) {
|
if (HAS_KEY(opts, set_extmark, sign_text)) {
|
||||||
VALIDATE_S(init_sign_text(&decor.sign_text, opts->sign_text.data),
|
VALIDATE_S(init_sign_text(NULL, &decor.sign_text, opts->sign_text.data),
|
||||||
"sign_text", "", {
|
"sign_text", "", {
|
||||||
goto error;
|
goto error;
|
||||||
});
|
});
|
||||||
@@ -1150,41 +1151,6 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// adapted from sign.c:sign_define_init_text.
|
|
||||||
// TODO(lewis6991): Consider merging
|
|
||||||
static int init_sign_text(char **sign_text, char *text)
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
char *endp = text + (int)strlen(text);
|
|
||||||
|
|
||||||
// Count cells and check for non-printable chars
|
|
||||||
int cells = 0;
|
|
||||||
for (s = text; s < endp; s += utfc_ptr2len(s)) {
|
|
||||||
if (!vim_isprintc(utf_ptr2char(s))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cells += utf_ptr2cells(s);
|
|
||||||
}
|
|
||||||
// Currently must be empty, one or two display cells
|
|
||||||
if (s != endp || cells > 2) {
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
if (cells < 1) {
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate one byte more if we need to pad up
|
|
||||||
// with a space.
|
|
||||||
size_t len = (size_t)(endp - text + ((cells == 1) ? 1 : 0));
|
|
||||||
*sign_text = xstrnsave(text, len);
|
|
||||||
|
|
||||||
if (cells == 1) {
|
|
||||||
STRCPY(*sign_text + len - 1, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtText parse_virt_text(Array chunks, Error *err, int *width)
|
VirtText parse_virt_text(Array chunks, Error *err, int *width)
|
||||||
{
|
{
|
||||||
|
@@ -2196,13 +2196,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (statuscol_lnum) {
|
if (statuscol_lnum) {
|
||||||
HlPriId line = { 0 };
|
int line_id = 0;
|
||||||
HlPriId cul = { 0 };
|
int cul_id = 0;
|
||||||
HlPriId num = { 0 };
|
int num_id = 0;
|
||||||
linenr_T lnum = statuscol_lnum;
|
linenr_T lnum = statuscol_lnum;
|
||||||
int num_signs = buf_get_signattrs(wp->w_buffer, lnum, sattrs, &num, &line, &cul);
|
|
||||||
decor_redraw_signs(wp->w_buffer, lnum - 1, &num_signs, sattrs, &num, &line, &cul);
|
|
||||||
wp->w_scwidth = win_signcol_count(wp);
|
wp->w_scwidth = win_signcol_count(wp);
|
||||||
|
decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
|
||||||
|
|
||||||
statuscol.sattrs = sattrs;
|
statuscol.sattrs = sattrs;
|
||||||
statuscol.foldinfo = fold_info(wp, lnum);
|
statuscol.foldinfo = fold_info(wp, lnum);
|
||||||
@@ -2215,9 +2214,9 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
|||||||
statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
|
statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
|
||||||
}
|
}
|
||||||
|
|
||||||
statuscol.sign_cul_id = statuscol.use_cul ? cul.hl_id : 0;
|
statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
|
||||||
if (num.hl_id) {
|
if (num_id) {
|
||||||
stc_hl_id = num.hl_id;
|
stc_hl_id = num_id;
|
||||||
} else if (statuscol.use_cul) {
|
} else if (statuscol.use_cul) {
|
||||||
stc_hl_id = HLF_CLN + 1;
|
stc_hl_id = HLF_CLN + 1;
|
||||||
} else if (wp->w_p_rnu) {
|
} else if (wp->w_p_rnu) {
|
||||||
|
@@ -919,7 +919,6 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
|
|||||||
buf_init_changedtick(buf);
|
buf_init_changedtick(buf);
|
||||||
}
|
}
|
||||||
uc_clear(&buf->b_ucmds); // clear local user commands
|
uc_clear(&buf->b_ucmds); // clear local user commands
|
||||||
buf_delete_signs(buf, "*"); // delete any signs
|
|
||||||
extmark_free_all(buf); // delete any extmarks
|
extmark_free_all(buf); // delete any extmarks
|
||||||
map_clear_mode(buf, MAP_ALL_MODES, true, false); // clear local mappings
|
map_clear_mode(buf, MAP_ALL_MODES, true, false); // clear local mappings
|
||||||
map_clear_mode(buf, MAP_ALL_MODES, true, true); // clear local abbrevs
|
map_clear_mode(buf, MAP_ALL_MODES, true, true); // clear local abbrevs
|
||||||
@@ -4023,62 +4022,6 @@ char *buf_spname(buf_T *buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int buf_signcols_inner(buf_T *buf, int maximum)
|
|
||||||
{
|
|
||||||
sign_entry_T *sign; // a sign in the sign list
|
|
||||||
int signcols = 0;
|
|
||||||
int linesum = 0;
|
|
||||||
linenr_T curline = 0;
|
|
||||||
|
|
||||||
buf->b_signcols.sentinel = 0;
|
|
||||||
|
|
||||||
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
|
|
||||||
if (sign->se_lnum > curline) {
|
|
||||||
// Counted all signs, now add extmark signs
|
|
||||||
if (curline > 0) {
|
|
||||||
linesum += decor_signcols(buf, &decor_state, (int)curline - 1, (int)curline - 1,
|
|
||||||
maximum - linesum);
|
|
||||||
}
|
|
||||||
curline = sign->se_lnum;
|
|
||||||
if (linesum > signcols) {
|
|
||||||
signcols = linesum;
|
|
||||||
buf->b_signcols.sentinel = curline;
|
|
||||||
if (signcols >= maximum) {
|
|
||||||
return maximum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
linesum = 0;
|
|
||||||
}
|
|
||||||
if (sign->se_has_text_or_icon) {
|
|
||||||
linesum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curline > 0) {
|
|
||||||
linesum += decor_signcols(buf, &decor_state, (int)curline - 1, (int)curline - 1,
|
|
||||||
maximum - linesum);
|
|
||||||
}
|
|
||||||
if (linesum > signcols) {
|
|
||||||
signcols = linesum;
|
|
||||||
if (signcols >= maximum) {
|
|
||||||
return maximum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check extmarks between signs
|
|
||||||
linesum = decor_signcols(buf, &decor_state, 0, (int)buf->b_ml.ml_line_count - 1, maximum);
|
|
||||||
|
|
||||||
if (linesum > signcols) {
|
|
||||||
signcols = linesum;
|
|
||||||
buf->b_signcols.sentinel = curline;
|
|
||||||
if (signcols >= maximum) {
|
|
||||||
return maximum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return signcols;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invalidate the signcolumn if needed after deleting
|
/// Invalidate the signcolumn if needed after deleting
|
||||||
/// signs between line1 and line2 (inclusive).
|
/// signs between line1 and line2 (inclusive).
|
||||||
///
|
///
|
||||||
@@ -4108,18 +4051,18 @@ void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T line2)
|
|||||||
///
|
///
|
||||||
/// @param buf buffer to check
|
/// @param buf buffer to check
|
||||||
/// @param added sign being added
|
/// @param added sign being added
|
||||||
void buf_signcols_add_check(buf_T *buf, sign_entry_T *added)
|
void buf_signcols_add_check(buf_T *buf, linenr_T lnum)
|
||||||
{
|
{
|
||||||
if (!buf->b_signcols.valid) {
|
if (!buf->b_signcols.valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!added || !buf->b_signcols.sentinel) {
|
if (!buf->b_signcols.sentinel) {
|
||||||
buf->b_signcols.valid = false;
|
buf->b_signcols.valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (added->se_lnum == buf->b_signcols.sentinel) {
|
if (lnum == buf->b_signcols.sentinel) {
|
||||||
if (buf->b_signcols.size == buf->b_signcols.max) {
|
if (buf->b_signcols.size == buf->b_signcols.max) {
|
||||||
buf->b_signcols.max++;
|
buf->b_signcols.max++;
|
||||||
}
|
}
|
||||||
@@ -4128,42 +4071,32 @@ void buf_signcols_add_check(buf_T *buf, sign_entry_T *added)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_entry_T *s;
|
int signcols = decor_signcols(buf, lnum - 1, lnum - 1, SIGN_SHOW_MAX);
|
||||||
|
|
||||||
// Get first sign for added lnum
|
if (signcols > buf->b_signcols.size) {
|
||||||
for (s = added; s->se_prev && s->se_lnum == s->se_prev->se_lnum; s = s->se_prev) {}
|
buf->b_signcols.size = signcols;
|
||||||
|
buf->b_signcols.max = signcols;
|
||||||
// Count signs for lnum
|
buf->b_signcols.sentinel = lnum;
|
||||||
int linesum = 1;
|
|
||||||
for (; s->se_next && s->se_lnum == s->se_next->se_lnum; s = s->se_next) {
|
|
||||||
linesum++;
|
|
||||||
}
|
|
||||||
linesum += decor_signcols(buf, &decor_state, (int)s->se_lnum - 1, (int)s->se_lnum - 1,
|
|
||||||
SIGN_SHOW_MAX - linesum);
|
|
||||||
|
|
||||||
if (linesum > buf->b_signcols.size) {
|
|
||||||
buf->b_signcols.size = linesum;
|
|
||||||
buf->b_signcols.max = linesum;
|
|
||||||
buf->b_signcols.sentinel = added->se_lnum;
|
|
||||||
redraw_buf_later(buf, UPD_NOT_VALID);
|
redraw_buf_later(buf, UPD_NOT_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int buf_signcols(buf_T *buf, int maximum)
|
int buf_signcols(buf_T *buf, int max)
|
||||||
{
|
{
|
||||||
// The maximum can be determined from 'signcolumn' which is window scoped so
|
// The maximum can be determined from 'signcolumn' which is window scoped so
|
||||||
// need to invalidate signcols if the maximum is greater than the previous
|
// need to invalidate signcols if the maximum is greater than the previous
|
||||||
// maximum.
|
// (valid) maximum.
|
||||||
if (maximum > buf->b_signcols.max) {
|
if (buf->b_signcols.max && max > buf->b_signcols.max) {
|
||||||
buf->b_signcols.valid = false;
|
buf->b_signcols.valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buf->b_signcols.valid) {
|
if (!buf->b_signcols.valid) {
|
||||||
int signcols = buf_signcols_inner(buf, maximum);
|
buf->b_signcols.sentinel = 0;
|
||||||
|
int signcols = decor_signcols(buf, 0, (int)buf->b_ml.ml_line_count - 1, max);
|
||||||
// Check if we need to redraw
|
// Check if we need to redraw
|
||||||
if (signcols != buf->b_signcols.size) {
|
if (signcols != buf->b_signcols.size) {
|
||||||
buf->b_signcols.size = signcols;
|
buf->b_signcols.size = signcols;
|
||||||
buf->b_signcols.max = maximum;
|
buf->b_signcols.max = max;
|
||||||
redraw_buf_later(buf, UPD_NOT_VALID);
|
redraw_buf_later(buf, UPD_NOT_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -704,7 +704,6 @@ 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.
|
||||||
|
|
||||||
sign_entry_T *b_signlist; // list of placed signs
|
|
||||||
struct {
|
struct {
|
||||||
int size; // last calculated number of sign columns
|
int size; // last calculated number of sign columns
|
||||||
bool valid; // calculated sign columns is valid
|
bool valid; // calculated sign columns is valid
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
#include "nvim/pos.h"
|
#include "nvim/pos.h"
|
||||||
#include "nvim/sign_defs.h"
|
#include "nvim/sign.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "decoration.c.generated.h"
|
# include "decoration.c.generated.h"
|
||||||
@@ -92,6 +92,8 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sign_add_id = 0;
|
||||||
|
|
||||||
void decor_add(buf_T *buf, int row, int row2, Decoration *decor, bool hl_id)
|
void decor_add(buf_T *buf, int row, int row2, Decoration *decor, bool hl_id)
|
||||||
{
|
{
|
||||||
if (decor) {
|
if (decor) {
|
||||||
@@ -102,12 +104,12 @@ void decor_add(buf_T *buf, int row, int row2, Decoration *decor, bool hl_id)
|
|||||||
buf->b_virt_line_blocks++;
|
buf->b_virt_line_blocks++;
|
||||||
}
|
}
|
||||||
if (decor_has_sign(decor)) {
|
if (decor_has_sign(decor)) {
|
||||||
|
decor->sign_add_id = sign_add_id++;
|
||||||
buf->b_signs++;
|
buf->b_signs++;
|
||||||
}
|
}
|
||||||
if (decor->sign_text) {
|
if (decor->sign_text) {
|
||||||
buf->b_signs_with_text++;
|
buf->b_signs_with_text++;
|
||||||
// TODO(lewis6991): smarter invalidation
|
buf_signcols_add_check(buf, row + 1);
|
||||||
buf_signcols_add_check(buf, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decor || hl_id) {
|
if (decor || hl_id) {
|
||||||
@@ -152,6 +154,7 @@ void decor_clear(Decoration *decor)
|
|||||||
}
|
}
|
||||||
kv_destroy(decor->virt_lines);
|
kv_destroy(decor->virt_lines);
|
||||||
xfree(decor->sign_text);
|
xfree(decor->sign_text);
|
||||||
|
xfree(decor->sign_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decor_free(Decoration *decor)
|
void decor_free(Decoration *decor)
|
||||||
@@ -429,107 +432,73 @@ next_mark:
|
|||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattrs[],
|
/// Return the sign attributes on the currently refreshed row.
|
||||||
HlPriId *num_id, HlPriId *line_id, HlPriId *cul_id)
|
///
|
||||||
|
/// @param[out] sattrs Output array for sign text and texthl id
|
||||||
|
/// @param[out] line_attr Highest priority linehl id
|
||||||
|
/// @param[out] cul_attr Highest priority culhl id
|
||||||
|
/// @param[out] num_attr Highest priority numhl id
|
||||||
|
void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[], int *line_id,
|
||||||
|
int *cul_id, int *num_id)
|
||||||
{
|
{
|
||||||
if (!buf->b_signs) {
|
MarkTreeIter itr[1];
|
||||||
return;
|
if (!buf->b_signs || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
|
||||||
}
|
|
||||||
|
|
||||||
MarkTreeIter itr[1] = { 0 };
|
|
||||||
marktree_itr_get(buf->b_marktree, row, 0, itr);
|
|
||||||
|
|
||||||
// TODO(bfredl): integrate with main decor loop.
|
|
||||||
if (!marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPair pair;
|
MTPair pair;
|
||||||
|
int num_text = 0;
|
||||||
|
kvec_t(MTKey) signs = KV_INITIAL_VALUE;
|
||||||
|
// TODO(bfredl): integrate with main decor loop.
|
||||||
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
|
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
|
||||||
if (mt_invalid(pair.start) || marktree_decor_level(pair.start) < kDecorLevelVisible) {
|
if (!mt_invalid(pair.start) && pair.start.decor_full && decor_has_sign(pair.start.decor_full)) {
|
||||||
continue;
|
pair.start.pos.row = row;
|
||||||
|
num_text += (pair.start.decor_full->sign_text != NULL);
|
||||||
|
kv_push(signs, pair.start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoration *decor = pair.start.decor_full;
|
while (itr->x) {
|
||||||
|
|
||||||
if (!decor || !decor_has_sign(decor)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
decor_to_sign(decor, num_signs, sattrs, num_id, line_id, cul_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
MTKey mark = marktree_itr_current(itr);
|
MTKey mark = marktree_itr_current(itr);
|
||||||
if (mark.pos.row < 0 || mark.pos.row > row) {
|
if (mark.pos.row != row) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!mt_end(mark) && !mt_invalid(mark) && mark.decor_full && decor_has_sign(mark.decor_full)) {
|
||||||
if (mt_end(mark) || mt_invalid(mark) || marktree_decor_level(mark) < kDecorLevelVisible) {
|
num_text += (mark.decor_full->sign_text != NULL);
|
||||||
goto next_mark;
|
kv_push(signs, mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoration *decor = mark.decor_full;
|
|
||||||
|
|
||||||
if (!decor || !decor_has_sign(decor)) {
|
|
||||||
goto next_mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
decor_to_sign(decor, num_signs, sattrs, num_id, line_id, cul_id);
|
|
||||||
|
|
||||||
next_mark:
|
|
||||||
marktree_itr_next(buf->b_marktree, itr);
|
marktree_itr_next(buf->b_marktree, itr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void decor_to_sign(Decoration *decor, int *num_signs, SignTextAttrs sattrs[],
|
if (kv_size(signs)) {
|
||||||
HlPriId *num_id, HlPriId *line_id, HlPriId *cul_id)
|
int width = (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') ? 1 : wp->w_scwidth;
|
||||||
{
|
int idx = MIN(width, num_text) - 1;
|
||||||
if (decor->sign_text) {
|
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
|
||||||
int j;
|
|
||||||
for (j = (*num_signs); j > 0; j--) {
|
|
||||||
if (sattrs[j - 1].priority >= decor->priority) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (j < SIGN_SHOW_MAX) {
|
|
||||||
sattrs[j] = sattrs[j - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (j < SIGN_SHOW_MAX) {
|
|
||||||
sattrs[j] = (SignTextAttrs) {
|
|
||||||
.text = decor->sign_text,
|
|
||||||
.hl_id = decor->sign_hl_id,
|
|
||||||
.priority = decor->priority
|
|
||||||
};
|
|
||||||
(*num_signs)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct { HlPriId *dest; int hl; } cattrs[] = {
|
for (size_t i = 0; i < kv_size(signs); i++) {
|
||||||
{ line_id, decor->line_hl_id },
|
Decoration *decor = kv_A(signs, i).decor_full;
|
||||||
{ num_id, decor->number_hl_id },
|
if (idx >= 0 && decor->sign_text) {
|
||||||
{ cul_id, decor->cursorline_hl_id },
|
sattrs[idx].text = decor->sign_text;
|
||||||
{ NULL, -1 },
|
sattrs[idx--].hl_id = decor->sign_hl_id;
|
||||||
};
|
|
||||||
for (int i = 0; cattrs[i].dest; i++) {
|
|
||||||
if (cattrs[i].hl != 0 && decor->priority >= cattrs[i].dest->priority) {
|
|
||||||
*cattrs[i].dest = (HlPriId) {
|
|
||||||
.hl_id = cattrs[i].hl,
|
|
||||||
.priority = decor->priority
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (*num_id == 0) {
|
||||||
|
*num_id = decor->number_hl_id;
|
||||||
|
}
|
||||||
|
if (*line_id == 0) {
|
||||||
|
*line_id = decor->line_hl_id;
|
||||||
|
}
|
||||||
|
if (*cul_id == 0) {
|
||||||
|
*cul_id = decor->cursorline_hl_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kv_destroy(signs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the maximum required amount of sign columns needed between row and
|
// Get the maximum required amount of sign columns needed between row and
|
||||||
// end_row.
|
// end_row.
|
||||||
int decor_signcols(buf_T *buf, DecorState *state, int row, int end_row, int max)
|
int decor_signcols(buf_T *buf, int row, int end_row, int max)
|
||||||
{
|
{
|
||||||
int count = 0; // count for the number of signs on a given row
|
|
||||||
int count_remove = 0; // how much to decrement count by when iterating marks for a new row
|
|
||||||
int signcols = 0; // highest value of count
|
|
||||||
int currow = -1; // current row
|
|
||||||
|
|
||||||
if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
|
if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
@@ -538,68 +507,43 @@ int decor_signcols(buf_T *buf, DecorState *state, int row, int end_row, int max)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkTreeIter itr[1] = { 0 };
|
int signcols = 0; // highest value of count
|
||||||
marktree_itr_get(buf->b_marktree, 0, -1, itr);
|
for (int currow = row; currow <= end_row; currow++) {
|
||||||
while (true) {
|
MarkTreeIter itr[1];
|
||||||
|
if (!marktree_itr_get_overlap(buf->b_marktree, currow, 0, itr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
MTPair pair;
|
||||||
|
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
|
||||||
|
if (!mt_invalid(pair.start) && pair.start.decor_full && pair.start.decor_full->sign_text) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (itr->x) {
|
||||||
MTKey mark = marktree_itr_current(itr);
|
MTKey mark = marktree_itr_current(itr);
|
||||||
if (mark.pos.row < 0 || mark.pos.row > end_row) {
|
if (mark.pos.row != currow) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!mt_invalid(mark) && !mt_end(mark) && mark.decor_full && mark.decor_full->sign_text) {
|
||||||
if ((mark.pos.row < row && mt_end(mark))
|
|
||||||
|| marktree_decor_level(mark) < kDecorLevelVisible
|
|
||||||
|| !mark.decor_full) {
|
|
||||||
goto next_mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoration decor = get_decor(mark);
|
|
||||||
|
|
||||||
if (!decor.sign_text) {
|
|
||||||
goto next_mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mark.pos.row > currow) {
|
|
||||||
count -= count_remove;
|
|
||||||
count_remove = 0;
|
|
||||||
currow = mark.pos.row;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mt_paired(mark)) {
|
|
||||||
if (mark.pos.row >= row) {
|
|
||||||
count++;
|
count++;
|
||||||
if (count > signcols) {
|
|
||||||
signcols = count;
|
|
||||||
if (signcols >= max) {
|
|
||||||
return max;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
count_remove++;
|
|
||||||
}
|
|
||||||
goto next_mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
MTPos altpos = marktree_get_altpos(buf->b_marktree, mark, NULL);
|
|
||||||
|
|
||||||
if (mt_end(mark)) {
|
|
||||||
if (mark.pos.row >= row && altpos.row <= end_row) {
|
|
||||||
count_remove++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (altpos.row >= row) {
|
|
||||||
count++;
|
|
||||||
if (count > signcols) {
|
|
||||||
signcols = count;
|
|
||||||
if (signcols >= max) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next_mark:
|
|
||||||
marktree_itr_next(buf->b_marktree, itr);
|
marktree_itr_next(buf->b_marktree, itr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count > signcols) {
|
||||||
|
if (row != end_row) {
|
||||||
|
buf->b_signcols.sentinel = currow + 1;
|
||||||
|
}
|
||||||
|
if (count >= max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
signcols = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return signcols;
|
return signcols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -60,7 +60,9 @@ struct Decoration {
|
|||||||
int col; // fixed col value, like win_col
|
int col; // fixed col value, like win_col
|
||||||
int virt_text_width; // width of virt_text
|
int virt_text_width; // width of virt_text
|
||||||
char *sign_text;
|
char *sign_text;
|
||||||
|
char *sign_name;
|
||||||
int sign_hl_id;
|
int sign_hl_id;
|
||||||
|
int sign_add_id;
|
||||||
int number_hl_id;
|
int number_hl_id;
|
||||||
int line_hl_id;
|
int line_hl_id;
|
||||||
int cursorline_hl_id;
|
int cursorline_hl_id;
|
||||||
@@ -71,7 +73,7 @@ struct Decoration {
|
|||||||
};
|
};
|
||||||
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
|
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
|
||||||
kHlModeUnknown, false, false, false, false, kNone, \
|
kHlModeUnknown, false, false, false, false, kNone, \
|
||||||
DECOR_PRIORITY_BASE, 0, 0, NULL, 0, 0, 0, 0, 0, false }
|
DECOR_PRIORITY_BASE, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, false }
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int start_row;
|
int start_row;
|
||||||
|
@@ -25,7 +25,7 @@ static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE;
|
|||||||
|
|
||||||
static void decor_provider_error(DecorProvider *provider, const char *name, const char *msg)
|
static void decor_provider_error(DecorProvider *provider, const char *name, const char *msg)
|
||||||
{
|
{
|
||||||
const char *ns_name = describe_ns(provider->ns_id);
|
const char *ns_name = describe_ns(provider->ns_id, "(UNKNOWN PLUGIN)");
|
||||||
ELOG("error in provider %s.%s: %s", ns_name, name, msg);
|
ELOG("error in provider %s.%s: %s", ns_name, name, msg);
|
||||||
msg_schedule_semsg_multiline("Error in decoration provider %s.%s:\n%s", ns_name, name, msg);
|
msg_schedule_semsg_multiline("Error in decoration provider %s.%s:\n%s", ns_name, name, msg);
|
||||||
}
|
}
|
||||||
|
@@ -456,83 +456,35 @@ size_t fill_foldcolumn(char *p, win_T *wp, foldinfo_T foldinfo, linenr_T lnum, i
|
|||||||
|
|
||||||
/// Get information needed to display the sign in line "wlv->lnum" in window "wp".
|
/// Get information needed to display the sign in line "wlv->lnum" in window "wp".
|
||||||
/// If "nrcol" is true, the sign is going to be displayed in the number column.
|
/// If "nrcol" is true, the sign is going to be displayed in the number column.
|
||||||
/// Otherwise the sign is going to be displayed in the sign column.
|
/// Otherwise the sign is going to be displayed in the sign column. If there is no
|
||||||
|
/// sign, draw blank cells instead.
|
||||||
static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx,
|
static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx,
|
||||||
int sign_cul_attr)
|
int sign_cul_attr)
|
||||||
{
|
{
|
||||||
// Draw cells with the sign value or blank.
|
SignTextAttrs sattr = wlv->sattrs[sign_idx];
|
||||||
wlv->c_extra = ' ';
|
|
||||||
wlv->c_final = NUL;
|
wlv->c_final = NUL;
|
||||||
if (nrcol) {
|
|
||||||
wlv->n_extra = number_width(wp) + 1;
|
|
||||||
} else {
|
|
||||||
if (use_cursor_line_highlight(wp, wlv->lnum)) {
|
|
||||||
wlv->char_attr = win_hl_attr(wp, HLF_CLS);
|
|
||||||
} else {
|
|
||||||
wlv->char_attr = win_hl_attr(wp, HLF_SC);
|
|
||||||
}
|
|
||||||
wlv->n_extra = win_signcol_width(wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
|
if (sattr.text && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
|
||||||
SignTextAttrs *sattr = sign_get_attr(sign_idx, wlv->sattrs, wp->w_scwidth);
|
size_t fill = nrcol ? (size_t)number_width(wp) - SIGN_WIDTH : 0;
|
||||||
if (sattr != NULL) {
|
size_t sign_len = strlen(sattr.text);
|
||||||
wlv->p_extra = sattr->text;
|
|
||||||
if (wlv->p_extra != NULL) {
|
// Spaces + sign: " " + ">>" + ' '
|
||||||
|
wlv->n_extra = (int)(fill + sign_len + nrcol);
|
||||||
|
if (nrcol) {
|
||||||
|
memset(wlv->extra, ' ', (size_t)wlv->n_extra);
|
||||||
|
}
|
||||||
|
memcpy(wlv->extra + fill, sattr.text, sign_len);
|
||||||
|
wlv->p_extra = wlv->extra;
|
||||||
wlv->c_extra = NUL;
|
wlv->c_extra = NUL;
|
||||||
wlv->c_final = NUL;
|
wlv->char_attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr)
|
||||||
|
? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0;
|
||||||
if (nrcol) {
|
|
||||||
int width = number_width(wp) - 2;
|
|
||||||
size_t n;
|
|
||||||
for (n = 0; (int)n < width; n++) {
|
|
||||||
wlv->extra[n] = ' ';
|
|
||||||
}
|
|
||||||
wlv->extra[n] = NUL;
|
|
||||||
snprintf(wlv->extra + n, sizeof(wlv->extra) - n, "%s ", wlv->p_extra);
|
|
||||||
wlv->p_extra = wlv->extra;
|
|
||||||
wlv->n_extra = (int)strlen(wlv->p_extra);
|
|
||||||
} else {
|
} else {
|
||||||
size_t symbol_blen = strlen(wlv->p_extra);
|
wlv->c_extra = ' ';
|
||||||
|
wlv->n_extra = nrcol ? number_width(wp) + 1 : SIGN_WIDTH;
|
||||||
// TODO(oni-link): Is sign text already extended to
|
if (!nrcol) {
|
||||||
// full cell width?
|
wlv->char_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
|
||||||
assert((size_t)win_signcol_width(wp) >= mb_string2cells(wlv->p_extra));
|
|
||||||
// symbol(s) bytes + (filling spaces) (one byte each)
|
|
||||||
wlv->n_extra = (int)symbol_blen + win_signcol_width(wp) -
|
|
||||||
(int)mb_string2cells(wlv->p_extra);
|
|
||||||
|
|
||||||
assert(sizeof(wlv->extra) > symbol_blen);
|
|
||||||
memset(wlv->extra, ' ', sizeof(wlv->extra));
|
|
||||||
memcpy(wlv->extra, wlv->p_extra, symbol_blen);
|
|
||||||
|
|
||||||
wlv->p_extra = wlv->extra;
|
|
||||||
wlv->p_extra[wlv->n_extra] = NUL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr > 0) {
|
|
||||||
wlv->char_attr = sign_cul_attr;
|
|
||||||
} else {
|
|
||||||
wlv->char_attr = sattr->hl_id ? syn_id2attr(sattr->hl_id) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns width of the signcolumn that should be used for the whole window
|
|
||||||
///
|
|
||||||
/// @param wp window we want signcolumn width from
|
|
||||||
/// @return max width of signcolumn (cell unit)
|
|
||||||
///
|
|
||||||
/// @note Returns a constant for now but hopefully we can improve neovim so that
|
|
||||||
/// the returned value width adapts to the maximum number of marks to draw
|
|
||||||
/// for the window
|
|
||||||
/// TODO(teto)
|
|
||||||
int win_signcol_width(win_T *wp)
|
|
||||||
{
|
|
||||||
// 2 is vim default value
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len)
|
static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len)
|
||||||
@@ -598,8 +550,7 @@ static int get_line_number_attr(win_T *wp, winlinevars_T *wlv)
|
|||||||
|
|
||||||
/// Display the absolute or relative line number. After the first row fill with
|
/// Display the absolute or relative line number. After the first row fill with
|
||||||
/// blanks when the 'n' flag isn't in 'cpo'.
|
/// blanks when the 'n' flag isn't in 'cpo'.
|
||||||
static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int num_signs, int sign_idx,
|
static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int sign_cul_attr)
|
||||||
int sign_num_attr, int sign_cul_attr)
|
|
||||||
{
|
{
|
||||||
bool has_cpo_n = vim_strchr(p_cpo, CPO_NUMCOL) != NULL;
|
bool has_cpo_n = vim_strchr(p_cpo, CPO_NUMCOL) != NULL;
|
||||||
|
|
||||||
@@ -610,8 +561,8 @@ static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int num_signs, int si
|
|||||||
&& !((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' && num_signs > 0) {
|
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && wlv->sattrs[0].text) {
|
||||||
get_sign_display_info(true, wp, wlv, sign_idx, 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).
|
||||||
if (wlv->row == wlv->startrow + wlv->filler_lines
|
if (wlv->row == wlv->startrow + wlv->filler_lines
|
||||||
@@ -1317,15 +1268,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
area_highlighting = true;
|
area_highlighting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HlPriId line_id = { 0 };
|
int line_attr = 0;
|
||||||
HlPriId sign_cul = { 0 };
|
|
||||||
HlPriId sign_num = { 0 };
|
|
||||||
// TODO(bfredl, vigoux): line_attr should not take priority over decoration!
|
|
||||||
int num_signs = buf_get_signattrs(buf, wlv.lnum, wlv.sattrs, &sign_num, &line_id, &sign_cul);
|
|
||||||
decor_redraw_signs(buf, wlv.lnum - 1, &num_signs, wlv.sattrs, &sign_num, &line_id, &sign_cul);
|
|
||||||
|
|
||||||
int sign_cul_attr = 0;
|
int sign_cul_attr = 0;
|
||||||
int sign_num_attr = 0;
|
int sign_num_attr = 0;
|
||||||
|
// TODO(bfredl, vigoux): line_attr should not take priority over decoration!
|
||||||
|
decor_redraw_signs(wp, buf, wlv.lnum - 1, wlv.sattrs, &line_attr, &sign_cul_attr, &sign_num_attr);
|
||||||
|
|
||||||
statuscol_T statuscol = { 0 };
|
statuscol_T statuscol = { 0 };
|
||||||
if (*wp->w_p_stc != NUL) {
|
if (*wp->w_p_stc != NUL) {
|
||||||
// Draw the 'statuscolumn' if option is set.
|
// Draw the 'statuscolumn' if option is set.
|
||||||
@@ -1334,18 +1282,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
statuscol.foldinfo = foldinfo;
|
statuscol.foldinfo = foldinfo;
|
||||||
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
|
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
|
||||||
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
|
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
|
||||||
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul.hl_id : 0;
|
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul_attr : 0;
|
||||||
statuscol.num_attr = sign_num.hl_id > 0 ? syn_id2attr(sign_num.hl_id) : 0;
|
statuscol.num_attr = sign_num_attr > 0 ? syn_id2attr(sign_num_attr) : 0;
|
||||||
} else {
|
} else {
|
||||||
if (sign_cul.hl_id > 0) {
|
if (sign_cul_attr > 0) {
|
||||||
sign_cul_attr = syn_id2attr(sign_cul.hl_id);
|
sign_cul_attr = syn_id2attr(sign_cul_attr);
|
||||||
}
|
}
|
||||||
if (sign_num.hl_id > 0) {
|
if (sign_num_attr > 0) {
|
||||||
sign_num_attr = syn_id2attr(sign_num.hl_id);
|
sign_num_attr = syn_id2attr(sign_num_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line_id.hl_id > 0) {
|
if (line_attr > 0) {
|
||||||
wlv.line_attr = syn_id2attr(line_id.hl_id);
|
wlv.line_attr = syn_id2attr(line_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highlight the current line in the quickfix window.
|
// Highlight the current line in the quickfix window.
|
||||||
@@ -1661,8 +1609,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
wlv.draw_state = WL_SIGN;
|
wlv.draw_state = WL_SIGN;
|
||||||
if (wp->w_scwidth > 0) {
|
if (wp->w_scwidth > 0) {
|
||||||
get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr);
|
get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr);
|
||||||
sign_idx++;
|
if (++sign_idx < wp->w_scwidth) {
|
||||||
if (sign_idx < wp->w_scwidth) {
|
|
||||||
wlv.draw_state = WL_SIGN - 1;
|
wlv.draw_state = WL_SIGN - 1;
|
||||||
} else {
|
} else {
|
||||||
sign_idx = 0;
|
sign_idx = 0;
|
||||||
@@ -1673,14 +1620,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) {
|
if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) {
|
||||||
// Show the line number, if desired.
|
// Show the line number, if desired.
|
||||||
wlv.draw_state = WL_NR;
|
wlv.draw_state = WL_NR;
|
||||||
handle_lnum_col(wp, &wlv, num_signs, sign_idx, sign_num_attr, sign_cul_attr);
|
handle_lnum_col(wp, &wlv, sign_num_attr, sign_cul_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) {
|
if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) {
|
||||||
wlv.draw_state = WL_STC;
|
wlv.draw_state = WL_STC;
|
||||||
// Draw the 'statuscolumn' if option is set.
|
// Draw the 'statuscolumn' if option is set.
|
||||||
if (statuscol.draw) {
|
if (statuscol.draw) {
|
||||||
if (sign_num.hl_id == 0) {
|
if (sign_num_attr == 0) {
|
||||||
statuscol.num_attr = get_line_number_attr(wp, &wlv);
|
statuscol.num_attr = get_line_number_attr(wp, &wlv);
|
||||||
}
|
}
|
||||||
if (statuscol.textp == NULL) {
|
if (statuscol.textp == NULL) {
|
||||||
|
@@ -2558,7 +2558,7 @@ void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endr
|
|||||||
// draw the sign column
|
// draw the sign column
|
||||||
int count = wp->w_scwidth;
|
int count = wp->w_scwidth;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
n = win_fill_end(wp, ' ', ' ', n, win_signcol_width(wp) * count, row,
|
n = win_fill_end(wp, ' ', ' ', n, SIGN_WIDTH * count, row,
|
||||||
endrow, win_hl_attr(wp, HLF_SC));
|
endrow, win_hl_attr(wp, HLF_SC));
|
||||||
}
|
}
|
||||||
// draw the number column
|
// draw the number column
|
||||||
@@ -2633,7 +2633,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_signlist != NULL)
|
if (n < 2 && wp->w_buffer->b_signs_with_text
|
||||||
&& (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) {
|
&& (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) {
|
||||||
n = 2;
|
n = 2;
|
||||||
}
|
}
|
||||||
|
@@ -504,7 +504,7 @@ static dict_T *get_buffer_info(buf_T *buf)
|
|||||||
}
|
}
|
||||||
tv_dict_add_list(dict, S_LEN("windows"), windows);
|
tv_dict_add_list(dict, S_LEN("windows"), windows);
|
||||||
|
|
||||||
if (buf->b_signlist != NULL) {
|
if (buf->b_signs) {
|
||||||
// List of signs placed in this buffer
|
// List of signs placed in this buffer
|
||||||
tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf));
|
tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf));
|
||||||
}
|
}
|
||||||
|
@@ -159,21 +159,22 @@ static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
linenr_T extmark_del_id(buf_T *buf, uint32_t ns_id, uint32_t id)
|
/// Remove an extmark in "ns_id" by "id"
|
||||||
|
///
|
||||||
|
/// @return false on missing id
|
||||||
|
bool extmark_del_id(buf_T *buf, uint32_t ns_id, uint32_t id)
|
||||||
{
|
{
|
||||||
MarkTreeIter it[1] = { 0 };
|
MarkTreeIter itr[1] = { 0 };
|
||||||
MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, it);
|
MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, itr);
|
||||||
if (!key.id) {
|
if (key.id) {
|
||||||
return 0;
|
extmark_del(buf, itr, key, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return extmark_del(buf, it, key, false);
|
return key.id > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a (paired) extmark "key" pointed to by "itr"
|
/// Remove a (paired) extmark "key" pointed to by "itr"
|
||||||
///
|
void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
||||||
/// @return line number of the deleted mark
|
|
||||||
linenr_T extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
|
||||||
{
|
{
|
||||||
assert(key.pos.row >= 0);
|
assert(key.pos.row >= 0);
|
||||||
|
|
||||||
@@ -193,7 +194,6 @@ linenr_T extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bfredl): delete it from current undo header, opportunistically?
|
// TODO(bfredl): delete it from current undo header, opportunistically?
|
||||||
return key.pos.row + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Free extmarks in a ns between lines
|
/// Free extmarks in a ns between lines
|
||||||
@@ -240,8 +240,8 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
|
|||||||
///
|
///
|
||||||
/// if upper_lnum or upper_col are negative the buffer
|
/// if upper_lnum or upper_col are negative the buffer
|
||||||
/// will be searched to the start, or end
|
/// will be searched to the start, or end
|
||||||
/// dir can be set to control the order of the array
|
/// reverse can be set to control the order of the array
|
||||||
/// amount = amount of marks to find or -1 for all
|
/// amount = amount of marks to find or INT64_MAX for all
|
||||||
ExtmarkInfoArray extmark_get(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_row,
|
ExtmarkInfoArray extmark_get(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_row,
|
||||||
colnr_T u_col, int64_t amount, bool reverse, ExtmarkType type_filter,
|
colnr_T u_col, int64_t amount, bool reverse, ExtmarkType type_filter,
|
||||||
bool overlap)
|
bool overlap)
|
||||||
@@ -299,7 +299,10 @@ static void push_mark(ExtmarkInfoArray *array, uint32_t ns_id, ExtmarkType type_
|
|||||||
if (type_filter != kExtmarkNone) {
|
if (type_filter != kExtmarkNone) {
|
||||||
Decoration *decor = mark.decor_full;
|
Decoration *decor = mark.decor_full;
|
||||||
if (decor && (decor->sign_text || decor->number_hl_id)) {
|
if (decor && (decor->sign_text || decor->number_hl_id)) {
|
||||||
type_flags |= kExtmarkSign;
|
type_flags |= (kExtmarkSignHL|kExtmarkSign);
|
||||||
|
}
|
||||||
|
if (decor && (decor->line_hl_id || decor->cursorline_hl_id)) {
|
||||||
|
type_flags |= (kExtmarkSignHL|kExtmarkHighlight);
|
||||||
}
|
}
|
||||||
if (decor && decor->virt_text.size) {
|
if (decor && decor->virt_text.size) {
|
||||||
type_flags |= kExtmarkVirtText;
|
type_flags |= kExtmarkVirtText;
|
||||||
@@ -307,8 +310,7 @@ static void push_mark(ExtmarkInfoArray *array, uint32_t ns_id, ExtmarkType type_
|
|||||||
if (decor && decor->virt_lines.size) {
|
if (decor && decor->virt_lines.size) {
|
||||||
type_flags |= kExtmarkVirtLines;
|
type_flags |= kExtmarkVirtLines;
|
||||||
}
|
}
|
||||||
if ((decor && (decor->line_hl_id || decor->cursorline_hl_id))
|
if (mark.hl_id) {
|
||||||
|| mark.hl_id) {
|
|
||||||
type_flags |= kExtmarkHighlight;
|
type_flags |= kExtmarkHighlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,6 +598,20 @@ void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t
|
|||||||
extmark_splice_delete(buf, start_row, start_col, end_row, end_col, undo);
|
extmark_splice_delete(buf, start_row, start_col, end_row, end_col, undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move the signcolumn sentinel line
|
||||||
|
if (buf->b_signs_with_text && buf->b_signcols.sentinel) {
|
||||||
|
linenr_T se_lnum = buf->b_signcols.sentinel;
|
||||||
|
if (se_lnum >= start_row) {
|
||||||
|
if (old_row != 0 && se_lnum > old_row + start_row) {
|
||||||
|
buf->b_signcols.sentinel += new_row - old_row;
|
||||||
|
} else if (new_row == 0) {
|
||||||
|
buf->b_signcols.sentinel = 0;
|
||||||
|
} else {
|
||||||
|
buf->b_signcols.sentinel += new_row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
marktree_splice(buf->b_marktree, (int32_t)start_row, start_col,
|
marktree_splice(buf->b_marktree, (int32_t)start_row, start_col,
|
||||||
old_row, old_col,
|
old_row, old_col,
|
||||||
new_row, new_col);
|
new_row, new_col);
|
||||||
|
@@ -84,9 +84,10 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
kExtmarkNone = 0x1,
|
kExtmarkNone = 0x1,
|
||||||
kExtmarkSign = 0x2,
|
kExtmarkSign = 0x2,
|
||||||
kExtmarkVirtText = 0x4,
|
kExtmarkSignHL = 0x4,
|
||||||
kExtmarkVirtLines = 0x8,
|
kExtmarkVirtText = 0x8,
|
||||||
kExtmarkHighlight = 0x10,
|
kExtmarkVirtLines = 0x10,
|
||||||
|
kExtmarkHighlight = 0x20,
|
||||||
} ExtmarkType;
|
} ExtmarkType;
|
||||||
|
|
||||||
// TODO(bfredl): reduce the number of undo action types
|
// TODO(bfredl): reduce the number of undo action types
|
||||||
|
@@ -474,10 +474,6 @@ EXTERN buf_T *curbuf INIT( = NULL); // currently active buffer
|
|||||||
#define FOR_ALL_BUF_WININFO(buf, wip) \
|
#define FOR_ALL_BUF_WININFO(buf, wip) \
|
||||||
for ((wip) = (buf)->b_wininfo; (wip) != NULL; (wip) = (wip)->wi_next) // NOLINT
|
for ((wip) = (buf)->b_wininfo; (wip) != NULL; (wip) = (wip)->wi_next) // NOLINT
|
||||||
|
|
||||||
// Iterate through all the signs placed in a buffer
|
|
||||||
#define FOR_ALL_SIGNS_IN_BUF(buf, sign) \
|
|
||||||
for ((sign) = (buf)->b_signlist; (sign) != NULL; (sign) = (sign)->se_next) // NOLINT
|
|
||||||
|
|
||||||
// List of files being edited (global argument list). curwin->w_alist points
|
// List of files being edited (global argument list). curwin->w_alist points
|
||||||
// to this when the window is using the global argument list.
|
// to this when the window is using the global argument list.
|
||||||
EXTERN alist_T global_alist; // global argument list
|
EXTERN alist_T global_alist; // global argument list
|
||||||
|
@@ -246,9 +246,3 @@ typedef struct {
|
|||||||
} ColorItem;
|
} ColorItem;
|
||||||
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \
|
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \
|
||||||
.is_default = false, .link_global = false }
|
.is_default = false, .link_global = false }
|
||||||
|
|
||||||
/// highlight attributes with associated priorities
|
|
||||||
typedef struct {
|
|
||||||
int hl_id;
|
|
||||||
int priority;
|
|
||||||
} HlPriId;
|
|
||||||
|
@@ -69,7 +69,6 @@
|
|||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/runtime.h"
|
#include "nvim/runtime.h"
|
||||||
#include "nvim/shada.h"
|
#include "nvim/shada.h"
|
||||||
#include "nvim/sign.h"
|
|
||||||
#include "nvim/statusline.h"
|
#include "nvim/statusline.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
@@ -217,8 +216,6 @@ void early_init(mparm_T *paramp)
|
|||||||
TIME_MSG("inits 1");
|
TIME_MSG("inits 1");
|
||||||
|
|
||||||
set_lang_var(); // set v:lang and v:ctype
|
set_lang_var(); // set v:lang and v:ctype
|
||||||
|
|
||||||
init_signs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAKE_LIB
|
#ifdef MAKE_LIB
|
||||||
|
@@ -33,7 +33,6 @@
|
|||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/sign.h"
|
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/textobject.h"
|
#include "nvim/textobject.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
@@ -1190,8 +1189,6 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount
|
|||||||
if (!found_one) {
|
if (!found_one) {
|
||||||
buf->b_has_qf_entry &= ~BUF_HAS_LL_ENTRY;
|
buf->b_has_qf_entry &= ~BUF_HAS_LL_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_mark_adjust(buf, line1, line2, amount, amount_after);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op != kExtmarkNOOP) {
|
if (op != kExtmarkNOOP) {
|
||||||
|
@@ -760,8 +760,7 @@ int win_col_off(win_T *wp)
|
|||||||
return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL) ?
|
return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL) ?
|
||||||
(number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
|
(number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
|
||||||
+ ((cmdwin_type == 0 || wp != curwin) ? 0 : 1)
|
+ ((cmdwin_type == 0 || wp != curwin) ? 0 : 1)
|
||||||
+ win_fdccol_count(wp)
|
+ win_fdccol_count(wp) + (win_signcol_count(wp) * SIGN_WIDTH);
|
||||||
+ (win_signcol_count(wp) * win_signcol_width(wp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int curwin_col_off(void)
|
int curwin_col_off(void)
|
||||||
|
@@ -6170,7 +6170,7 @@ 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, NULL);
|
return win_signcol_configured(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true when window "wp" has no sign column.
|
/// Return true when window "wp" has no sign column.
|
||||||
@@ -6182,14 +6182,10 @@ bool win_no_signcol(win_T *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of requested sign columns, based on user / configuration.
|
/// Return the number of requested sign columns, based on user / configuration.
|
||||||
int win_signcol_configured(win_T *wp, int *is_fixed)
|
int win_signcol_configured(win_T *wp)
|
||||||
{
|
{
|
||||||
const char *scl = wp->w_p_scl;
|
const char *scl = wp->w_p_scl;
|
||||||
|
|
||||||
if (is_fixed) {
|
|
||||||
*is_fixed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (win_no_signcol(wp)) {
|
if (win_no_signcol(wp)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -6203,11 +6199,6 @@ int win_signcol_configured(win_T *wp, int *is_fixed)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_fixed) {
|
|
||||||
// auto or auto:<NUM>
|
|
||||||
*is_fixed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int minimum = 0, maximum = 1;
|
int minimum = 0, maximum = 1;
|
||||||
|
|
||||||
if (!strncmp(scl, "auto:", 5)) {
|
if (!strncmp(scl, "auto:", 5)) {
|
||||||
|
@@ -7590,12 +7590,6 @@ return {
|
|||||||
number (maximum 9), e.g. "yes:3"
|
number (maximum 9), e.g. "yes:3"
|
||||||
"number" display signs in the 'number' column. If the number
|
"number" display signs in the 'number' column. If the number
|
||||||
column is not present, then behaves like "auto".
|
column is not present, then behaves like "auto".
|
||||||
|
|
||||||
Note regarding "orphaned signs": with signcolumn numbers higher than
|
|
||||||
1, deleting lines will also remove the associated signs automatically,
|
|
||||||
in contrast to the default Vim behavior of keeping and grouping them.
|
|
||||||
This is done in order for the signcolumn appearance not appear weird
|
|
||||||
during line deletion.
|
|
||||||
]=],
|
]=],
|
||||||
expand_cb = 'expand_set_signcolumn',
|
expand_cb = 'expand_set_signcolumn',
|
||||||
full_name = 'signcolumn',
|
full_name = 'signcolumn',
|
||||||
|
1815
src/nvim/sign.c
1815
src/nvim/sign.c
File diff suppressed because it is too large
Load Diff
@@ -5,47 +5,23 @@
|
|||||||
#include "nvim/pos.h"
|
#include "nvim/pos.h"
|
||||||
#include "nvim/types.h"
|
#include "nvim/types.h"
|
||||||
|
|
||||||
// signs: line annotations
|
|
||||||
|
|
||||||
// Sign group
|
|
||||||
typedef struct signgroup_S {
|
|
||||||
int sg_next_sign_id; ///< next sign id for this group
|
|
||||||
uint16_t sg_refcount; ///< number of signs in this group
|
|
||||||
char sg_name[]; ///< sign group name
|
|
||||||
} signgroup_T;
|
|
||||||
|
|
||||||
// Macros to get the sign group structure from the group name
|
|
||||||
#define SGN_KEY_OFF offsetof(signgroup_T, sg_name)
|
|
||||||
#define HI2SG(hi) ((signgroup_T *)((hi)->hi_key - SGN_KEY_OFF))
|
|
||||||
|
|
||||||
typedef struct sign_entry sign_entry_T;
|
|
||||||
|
|
||||||
struct sign_entry {
|
|
||||||
int se_id; // unique identifier for each placed sign
|
|
||||||
int se_typenr; // typenr of sign
|
|
||||||
int se_priority; // priority for highlighting
|
|
||||||
bool se_has_text_or_icon; // has text or icon
|
|
||||||
linenr_T se_lnum; // line number which has this sign
|
|
||||||
signgroup_T *se_group; // sign group
|
|
||||||
sign_entry_T *se_next; // next entry in a list of signs
|
|
||||||
sign_entry_T *se_prev; // previous entry -- for easy reordering
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Sign attributes. Used by the screen refresh routines.
|
/// Sign attributes. Used by the screen refresh routines.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *text;
|
char *text;
|
||||||
int hl_id;
|
int hl_id;
|
||||||
int priority;
|
|
||||||
} SignTextAttrs;
|
} SignTextAttrs;
|
||||||
|
|
||||||
#define SIGN_SHOW_MAX 9
|
/// Struct to hold the sign properties.
|
||||||
|
typedef struct sign {
|
||||||
|
char *sn_name; // name of sign
|
||||||
|
char *sn_icon; // name of pixmap
|
||||||
|
char *sn_text; // text used instead of pixmap
|
||||||
|
int sn_line_hl; // highlight ID for line
|
||||||
|
int sn_text_hl; // highlight ID for text
|
||||||
|
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
|
||||||
|
int sn_num_hl; // highlight ID for line number
|
||||||
|
} sign_T;
|
||||||
|
|
||||||
// Default sign priority for highlighting
|
#define SIGN_WIDTH 2 // Number of display cells for a sign in the signcolumn
|
||||||
#define SIGN_DEF_PRIO 10
|
#define SIGN_SHOW_MAX 9 // Maximum number of signs shown on a single line
|
||||||
|
#define SIGN_DEF_PRIO 10 // Default sign highlight priority
|
||||||
// type argument for sign_get_attr()
|
|
||||||
typedef enum {
|
|
||||||
SIGN_LINEHL,
|
|
||||||
SIGN_NUMHL,
|
|
||||||
SIGN_TEXT,
|
|
||||||
} SignType;
|
|
||||||
|
@@ -1656,9 +1656,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
|
|||||||
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
|
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
if (!fold) {
|
if (!fold) {
|
||||||
SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth);
|
SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
|
||||||
p = sattr && sattr->text ? sattr->text : " ";
|
p = sattr && sattr->text ? sattr->text : " ";
|
||||||
stl_items[curitem].minwid = -(sattr ? stcp->sign_cul_id ? stcp->sign_cul_id
|
stl_items[curitem].minwid = -(sattr && sattr->text ? stcp->sign_cul_id ? stcp->sign_cul_id
|
||||||
: sattr->hl_id : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
|
: sattr->hl_id : (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
|
||||||
}
|
}
|
||||||
stl_items[curitem].type = Highlight;
|
stl_items[curitem].type = Highlight;
|
||||||
|
@@ -4680,7 +4680,7 @@ l5
|
|||||||
|
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
{1: }^l1 |
|
{1: }^l1 |
|
||||||
S2S1l2 |
|
S1S2l2 |
|
||||||
{1: }l3 |
|
{1: }l3 |
|
||||||
{1: }l4 |
|
{1: }l4 |
|
||||||
{1: }l5 |
|
{1: }l5 |
|
||||||
@@ -4720,7 +4720,7 @@ l5
|
|||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
{1: }^l1 |
|
{1: }^l1 |
|
||||||
S1{1: }l2 |
|
S1{1: }l2 |
|
||||||
S2S1l3 |
|
S1S2l3 |
|
||||||
S2{1: }l4 |
|
S2{1: }l4 |
|
||||||
{1: }l5 |
|
{1: }l5 |
|
||||||
{1: } |
|
{1: } |
|
||||||
@@ -4765,7 +4765,7 @@ l5
|
|||||||
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
||||||
|
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
S4S1^l1 |
|
S1S4^l1 |
|
||||||
x S2l2 |
|
x S2l2 |
|
||||||
S5{1: }l3 |
|
S5{1: }l3 |
|
||||||
{1: }l4 |
|
{1: }l4 |
|
||||||
@@ -4792,9 +4792,9 @@ l5
|
|||||||
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
||||||
|
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
S3S4S1^l1 |
|
S1S3S4^l1 |
|
||||||
x S2S3l2 |
|
x S2S3l2 |
|
||||||
S5S3{1: }l3 |
|
S3S5{1: }l3 |
|
||||||
S3{1: }l4 |
|
S3{1: }l4 |
|
||||||
S3{1: }l5 |
|
S3{1: }l5 |
|
||||||
{1: } |
|
{1: } |
|
||||||
@@ -4848,15 +4848,15 @@ l5
|
|||||||
end
|
end
|
||||||
|
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
|
||||||
X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:^h} |
|
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:^h} |
|
||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
@@ -274,9 +274,9 @@ describe('Signs', function()
|
|||||||
-- Line 3 checks that with a limit over the maximum number
|
-- Line 3 checks that with a limit over the maximum number
|
||||||
-- of signs, the ones with the highest Ids are being picked,
|
-- of signs, the ones with the highest Ids are being picked,
|
||||||
-- and presented by their sorted Id order.
|
-- and presented by their sorted Id order.
|
||||||
command('sign place 4 line=3 name=pietSearch buffer=1')
|
command('sign place 6 line=3 name=pietSearch buffer=1')
|
||||||
command('sign place 5 line=3 name=pietWarn buffer=1')
|
command('sign place 7 line=3 name=pietWarn buffer=1')
|
||||||
command('sign place 3 line=3 name=pietError buffer=1')
|
command('sign place 5 line=3 name=pietError buffer=1')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
{1:>>}{8:XX}{6: 1 }a |
|
{1:>>}{8:XX}{6: 1 }a |
|
||||||
{8:XX}{1:>>}{6: 2 }b |
|
{8:XX}{1:>>}{6: 2 }b |
|
||||||
|
@@ -377,6 +377,7 @@ describe('statuscolumn', function()
|
|||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
command('set breakindent')
|
command('set breakindent')
|
||||||
|
command('sign unplace 2')
|
||||||
feed('J2gjg0')
|
feed('J2gjg0')
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
{2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
|
{2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
|
||||||
|
@@ -1501,50 +1501,33 @@ func Test_sign_priority()
|
|||||||
call sign_place(3, '', 'sign3', 'Xsign',
|
call sign_place(3, '', 'sign3', 'Xsign',
|
||||||
\ {'lnum' : 4, 'priority' : 20})
|
\ {'lnum' : 4, 'priority' : 20})
|
||||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||||
call assert_equal([
|
let se = [
|
||||||
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
||||||
\ 'priority' : 20},
|
\ 'priority' : 20},
|
||||||
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
||||||
\ 'priority' : 20},
|
\ 'priority' : 20},
|
||||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
||||||
\ 'priority' : 20}],
|
\ 'priority' : 20}]
|
||||||
\ s[0].signs)
|
call assert_equal(se, s[0].signs)
|
||||||
|
|
||||||
|
" Nvim: signs are always sorted lnum->priority->sign_id->last_modified
|
||||||
|
" Last modified does not take precedence over sign_id here.
|
||||||
|
|
||||||
" Place the last sign again with the same priority
|
" Place the last sign again with the same priority
|
||||||
call sign_place(1, '', 'sign1', 'Xsign',
|
call sign_place(1, '', 'sign1', 'Xsign',
|
||||||
\ {'lnum' : 4, 'priority' : 20})
|
\ {'lnum' : 4, 'priority' : 20})
|
||||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||||
call assert_equal([
|
call assert_equal(se, s[0].signs)
|
||||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20}],
|
|
||||||
\ s[0].signs)
|
|
||||||
" Place the first sign again with the same priority
|
" Place the first sign again with the same priority
|
||||||
call sign_place(1, '', 'sign1', 'Xsign',
|
call sign_place(1, '', 'sign1', 'Xsign',
|
||||||
\ {'lnum' : 4, 'priority' : 20})
|
\ {'lnum' : 4, 'priority' : 20})
|
||||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||||
call assert_equal([
|
call assert_equal(se, s[0].signs)
|
||||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20}],
|
|
||||||
\ s[0].signs)
|
|
||||||
" Place the middle sign again with the same priority
|
" Place the middle sign again with the same priority
|
||||||
call sign_place(3, '', 'sign3', 'Xsign',
|
call sign_place(3, '', 'sign3', 'Xsign',
|
||||||
\ {'lnum' : 4, 'priority' : 20})
|
\ {'lnum' : 4, 'priority' : 20})
|
||||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||||
call assert_equal([
|
call assert_equal(se, s[0].signs)
|
||||||
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20},
|
|
||||||
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
|
||||||
\ 'priority' : 20}],
|
|
||||||
\ s[0].signs)
|
|
||||||
|
|
||||||
call sign_unplace('*')
|
call sign_unplace('*')
|
||||||
|
|
||||||
@@ -1670,34 +1653,33 @@ func Test_sign_lnum_adjust()
|
|||||||
" changes made by this function.
|
" changes made by this function.
|
||||||
let &g:undolevels=&g:undolevels
|
let &g:undolevels=&g:undolevels
|
||||||
|
|
||||||
" Nvim: make sign adjustment when deleting lines match Vim
|
" Nvim: deleting a line removes the signs along with it.
|
||||||
set signcolumn=yes:1
|
|
||||||
|
|
||||||
" Delete the line with the sign
|
" " Delete the line with the sign
|
||||||
call deletebufline('', 4)
|
" call deletebufline('', 4)
|
||||||
let l = sign_getplaced(bufnr(''))
|
" let l = sign_getplaced(bufnr(''))
|
||||||
call assert_equal(4, l[0].signs[0].lnum)
|
" call assert_equal(4, l[0].signs[0].lnum)
|
||||||
|
|
||||||
" Undo the delete operation
|
" " Undo the delete operation
|
||||||
undo
|
" undo
|
||||||
let l = sign_getplaced(bufnr(''))
|
" let l = sign_getplaced(bufnr(''))
|
||||||
call assert_equal(5, l[0].signs[0].lnum)
|
" call assert_equal(5, l[0].signs[0].lnum)
|
||||||
|
|
||||||
" Break the undo
|
" " Break the undo
|
||||||
let &g:undolevels=&g:undolevels
|
" let &g:undolevels=&g:undolevels
|
||||||
|
|
||||||
" Delete few lines at the end of the buffer including the line with the sign
|
" " Delete few lines at the end of the buffer including the line with the sign
|
||||||
" Sign line number should not change (as it is placed outside of the buffer)
|
" " Sign line number should not change (as it is placed outside of the buffer)
|
||||||
call deletebufline('', 3, 6)
|
" call deletebufline('', 3, 6)
|
||||||
let l = sign_getplaced(bufnr(''))
|
" let l = sign_getplaced(bufnr(''))
|
||||||
call assert_equal(5, l[0].signs[0].lnum)
|
" call assert_equal(5, l[0].signs[0].lnum)
|
||||||
|
|
||||||
" Undo the delete operation. Sign should be restored to the previous line
|
" " Undo the delete operation. Sign should be restored to the previous line
|
||||||
undo
|
" undo
|
||||||
let l = sign_getplaced(bufnr(''))
|
" let l = sign_getplaced(bufnr(''))
|
||||||
call assert_equal(5, l[0].signs[0].lnum)
|
" call assert_equal(5, l[0].signs[0].lnum)
|
||||||
|
|
||||||
set signcolumn&
|
" set signcolumn&
|
||||||
|
|
||||||
sign unplace * group=*
|
sign unplace * group=*
|
||||||
sign undefine sign1
|
sign undefine sign1
|
||||||
@@ -1971,7 +1953,8 @@ func Test_sign_funcs_multi()
|
|||||||
call sign_unplace('*')
|
call sign_unplace('*')
|
||||||
|
|
||||||
" Place multiple signs at once with auto-generated sign identifier
|
" Place multiple signs at once with auto-generated sign identifier
|
||||||
call assert_equal([1, 1, 5], sign_placelist([
|
" Nvim: next sign id is not reset and is always incremented
|
||||||
|
call assert_equal([2, 3, 4], sign_placelist([
|
||||||
\ {'group' : 'g1', 'name' : 'sign1',
|
\ {'group' : 'g1', 'name' : 'sign1',
|
||||||
\ 'buffer' : 'Xsign', 'lnum' : 11},
|
\ 'buffer' : 'Xsign', 'lnum' : 11},
|
||||||
\ {'group' : 'g2', 'name' : 'sign2',
|
\ {'group' : 'g2', 'name' : 'sign2',
|
||||||
@@ -1980,17 +1963,17 @@ func Test_sign_funcs_multi()
|
|||||||
\ 'buffer' : 'Xsign', 'lnum' : 11}]))
|
\ 'buffer' : 'Xsign', 'lnum' : 11}]))
|
||||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||||
call assert_equal([
|
call assert_equal([
|
||||||
\ {'id' : 5, 'name' : 'sign3', 'lnum' : 11,
|
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 11,
|
||||||
\ 'group' : '', 'priority' : 10},
|
\ 'group' : '', 'priority' : 10},
|
||||||
\ {'id' : 1, 'name' : 'sign2', 'lnum' : 11,
|
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 11,
|
||||||
\ 'group' : 'g2', 'priority' : 10},
|
\ 'group' : 'g2', 'priority' : 10},
|
||||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 11,
|
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 11,
|
||||||
\ 'group' : 'g1', 'priority' : 10}], s[0].signs)
|
\ 'group' : 'g1', 'priority' : 10}], s[0].signs)
|
||||||
|
|
||||||
" Change an existing sign without specifying the group
|
" Change an existing sign without specifying the group
|
||||||
call assert_equal([5], [{'id' : 5, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
|
call assert_equal([4], [{'id' : 4, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
|
||||||
let s = sign_getplaced('Xsign', {'id' : 5, 'group' : ''})
|
let s = sign_getplaced('Xsign', {'id' : 4, 'group' : ''})
|
||||||
call assert_equal([{'id' : 5, 'name' : 'sign1', 'lnum' : 11,
|
call assert_equal([{'id' : 4, 'name' : 'sign1', 'lnum' : 11,
|
||||||
\ 'group' : '', 'priority' : 10}], s[0].signs)
|
\ 'group' : '', 'priority' : 10}], s[0].signs)
|
||||||
|
|
||||||
" Place a sign using '.' as the line number
|
" Place a sign using '.' as the line number
|
||||||
@@ -2017,8 +2000,8 @@ func Test_sign_funcs_multi()
|
|||||||
call assert_fails('call sign_placelist([100])', "E715:")
|
call assert_fails('call sign_placelist([100])', "E715:")
|
||||||
|
|
||||||
" Unplace multiple signs
|
" Unplace multiple signs
|
||||||
call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 5},
|
call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 4},
|
||||||
\ {'id' : 1, 'group' : 'g1'}, {'id' : 1, 'group' : 'g2'}]))
|
\ {'id' : 2, 'group' : 'g1'}, {'id' : 3, 'group' : 'g2'}]))
|
||||||
|
|
||||||
" Invalid arguments
|
" Invalid arguments
|
||||||
call assert_equal([], []->sign_unplacelist())
|
call assert_equal([], []->sign_unplacelist())
|
||||||
|
Reference in New Issue
Block a user