mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
refactor(sign): move legacy signs to extmarks
Problem: The legacy signlist data structures and associated functions are redundant since the introduction of extmark signs. Solution: Store signs defined through the legacy commands in a hashmap, placed signs in the extmark tree. Replace signlist associated functions. Usage of the legacy sign commands should yield no change in behavior with the exception of: - "orphaned signs" are now always removed when the line it is placed on is deleted. This used to depend on the value of 'signcolumn'. - It is no longer possible to place multiple signs with the same identifier in a single group on multiple lines. This will now move the sign instead. Moreover, both signs placed through the legacy sign commands and through |nvim_buf_set_extmark()|: - Will show up in both |sign-place| and |nvim_buf_get_extmarks()|. - Are displayed by increasing sign identifier, left to right. Extmark signs used to be ordered decreasingly as opposed to legacy signs.
This commit is contained in:
parent
ba58c6f8a4
commit
c4afb9788c
@ -2566,8 +2566,8 @@ nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
|
||||
|
||||
*nvim_buf_get_extmarks()*
|
||||
nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
|
||||
Gets |extmarks| in "traversal order" from a |charwise| region defined by
|
||||
buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||
Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
|
||||
region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||
|
||||
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)
|
||||
|
@ -80,6 +80,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
|
||||
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*
|
||||
|
||||
|
@ -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
|
||||
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' boolean (default off)
|
||||
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
|
||||
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
|
||||
|sign_place()| function. Each sign identifier should be a unique number. If
|
||||
multiple placed signs use the same identifier, then jumping to or removing a
|
||||
sign becomes unpredictable. To avoid overlapping identifiers, sign groups can
|
||||
be used. The |sign_place()| function can be called with a zero sign identifier
|
||||
to allocate the next available identifier.
|
||||
|sign_place()| function. Each sign identifier should be a unique number.
|
||||
Placing the same identifier twice will move the previously placed sign. The
|
||||
|sign_place()| function can be called with a zero sign identifier to allocate
|
||||
the next available identifier.
|
||||
|
||||
*sign-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
|
||||
displayed.
|
||||
|
||||
When the line on which the sign is placed is deleted, the sign is moved to the
|
||||
next line (or the last line of the buffer, if there is no next line). When
|
||||
the delete is undone the sign does not move back.
|
||||
When the line on which the sign is placed is deleted, the sign is removed along
|
||||
with it.
|
||||
|
||||
==============================================================================
|
||||
2. Commands *sign-commands* *:sig* *:sign*
|
||||
@ -177,11 +175,8 @@ See |sign_place()| for the equivalent Vim script function.
|
||||
space is ignored.
|
||||
|
||||
The sign is remembered under {id}, this can be used for
|
||||
further manipulation. {id} must be a number.
|
||||
It's up to the user to make sure the {id} is used only once in
|
||||
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).
|
||||
further manipulation. {id} must be a number. Placing the
|
||||
same {id} multiple times will move the sign.
|
||||
|
||||
The following optional sign attributes can be specified before
|
||||
"file=":
|
||||
|
@ -340,6 +340,7 @@ Shell:
|
||||
|
||||
Signs:
|
||||
Signs are removed if the associated line is deleted.
|
||||
Signs placed twice with the same identifier in the same group are moved.
|
||||
|
||||
Startup:
|
||||
|-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[]
|
||||
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
|
||||
--- buffer positions (inclusive, 0-indexed `api-indexing`).
|
||||
--- Gets `extmarks` (including `signs`) in "traversal order" from a `charwise`
|
||||
--- region defined by buffer positions (inclusive, 0-indexed `api-indexing`).
|
||||
--- 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)
|
||||
--- 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
|
||||
--- 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
|
||||
vim.o.signcolumn = "auto"
|
||||
vim.o.scl = vim.o.signcolumn
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nvim/memline.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/sign.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/vim.h"
|
||||
|
||||
@ -81,7 +82,7 @@ Dictionary nvim_get_namespaces(void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char *describe_ns(NS ns_id)
|
||||
const char *describe_ns(NS ns_id, const char *unknown)
|
||||
{
|
||||
String name;
|
||||
handle_T id;
|
||||
@ -90,7 +91,7 @@ const char *describe_ns(NS ns_id)
|
||||
return name.data;
|
||||
}
|
||||
})
|
||||
return "(UNKNOWN PLUGIN)";
|
||||
return unknown;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// Gets |extmarks| in "traversal order" from a |charwise| region defined by
|
||||
/// buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||
/// Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
|
||||
/// region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
|
||||
///
|
||||
/// 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)
|
||||
@ -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)) {
|
||||
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", "", {
|
||||
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)
|
||||
{
|
||||
|
@ -2196,13 +2196,12 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
}
|
||||
}
|
||||
if (statuscol_lnum) {
|
||||
HlPriId line = { 0 };
|
||||
HlPriId cul = { 0 };
|
||||
HlPriId num = { 0 };
|
||||
int line_id = 0;
|
||||
int cul_id = 0;
|
||||
int num_id = 0;
|
||||
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);
|
||||
decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
|
||||
|
||||
statuscol.sattrs = sattrs;
|
||||
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.sign_cul_id = statuscol.use_cul ? cul.hl_id : 0;
|
||||
if (num.hl_id) {
|
||||
stc_hl_id = num.hl_id;
|
||||
statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
|
||||
if (num_id) {
|
||||
stc_hl_id = num_id;
|
||||
} else if (statuscol.use_cul) {
|
||||
stc_hl_id = HLF_CLN + 1;
|
||||
} else if (wp->w_p_rnu) {
|
||||
|
@ -917,7 +917,6 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
|
||||
buf_init_changedtick(buf);
|
||||
}
|
||||
uc_clear(&buf->b_ucmds); // clear local user commands
|
||||
buf_delete_signs(buf, "*"); // delete any signs
|
||||
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, true); // clear local abbrevs
|
||||
@ -4021,62 +4020,6 @@ char *buf_spname(buf_T *buf)
|
||||
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
|
||||
/// signs between line1 and line2 (inclusive).
|
||||
///
|
||||
@ -4106,18 +4049,18 @@ void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T line2)
|
||||
///
|
||||
/// @param buf buffer to check
|
||||
/// @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) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!added || !buf->b_signcols.sentinel) {
|
||||
if (!buf->b_signcols.sentinel) {
|
||||
buf->b_signcols.valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (added->se_lnum == buf->b_signcols.sentinel) {
|
||||
if (lnum == buf->b_signcols.sentinel) {
|
||||
if (buf->b_signcols.size == buf->b_signcols.max) {
|
||||
buf->b_signcols.max++;
|
||||
}
|
||||
@ -4126,42 +4069,32 @@ void buf_signcols_add_check(buf_T *buf, sign_entry_T *added)
|
||||
return;
|
||||
}
|
||||
|
||||
sign_entry_T *s;
|
||||
int signcols = decor_signcols(buf, lnum - 1, lnum - 1, SIGN_SHOW_MAX);
|
||||
|
||||
// Get first sign for added lnum
|
||||
for (s = added; s->se_prev && s->se_lnum == s->se_prev->se_lnum; s = s->se_prev) {}
|
||||
|
||||
// Count signs for 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;
|
||||
if (signcols > buf->b_signcols.size) {
|
||||
buf->b_signcols.size = signcols;
|
||||
buf->b_signcols.max = signcols;
|
||||
buf->b_signcols.sentinel = lnum;
|
||||
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
|
||||
// need to invalidate signcols if the maximum is greater than the previous
|
||||
// maximum.
|
||||
if (maximum > buf->b_signcols.max) {
|
||||
// (valid) maximum.
|
||||
if (buf->b_signcols.max && max > buf->b_signcols.max) {
|
||||
buf->b_signcols.valid = false;
|
||||
}
|
||||
|
||||
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
|
||||
if (signcols != buf->b_signcols.size) {
|
||||
buf->b_signcols.size = signcols;
|
||||
buf->b_signcols.max = maximum;
|
||||
buf->b_signcols.max = max;
|
||||
redraw_buf_later(buf, UPD_NOT_VALID);
|
||||
}
|
||||
|
||||
|
@ -708,7 +708,6 @@ struct file_buffer {
|
||||
// normally points to this, but some windows
|
||||
// may use a different synblock_T.
|
||||
|
||||
sign_entry_T *b_signlist; // list of placed signs
|
||||
struct {
|
||||
int size; // last calculated number of sign columns
|
||||
bool valid; // calculated sign columns is valid
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/move.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/sign_defs.h"
|
||||
#include "nvim/sign.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# 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)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
if (decor_has_sign(decor)) {
|
||||
decor->sign_add_id = sign_add_id++;
|
||||
buf->b_signs++;
|
||||
}
|
||||
if (decor->sign_text) {
|
||||
buf->b_signs_with_text++;
|
||||
// TODO(lewis6991): smarter invalidation
|
||||
buf_signcols_add_check(buf, NULL);
|
||||
buf_signcols_add_check(buf, row + 1);
|
||||
}
|
||||
}
|
||||
if (decor || hl_id) {
|
||||
@ -152,6 +154,7 @@ void decor_clear(Decoration *decor)
|
||||
}
|
||||
kv_destroy(decor->virt_lines);
|
||||
xfree(decor->sign_text);
|
||||
xfree(decor->sign_name);
|
||||
}
|
||||
|
||||
void decor_free(Decoration *decor)
|
||||
@ -429,107 +432,73 @@ next_mark:
|
||||
return attr;
|
||||
}
|
||||
|
||||
void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattrs[],
|
||||
HlPriId *num_id, HlPriId *line_id, HlPriId *cul_id)
|
||||
/// Return the sign attributes on the currently refreshed row.
|
||||
///
|
||||
/// @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) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)) {
|
||||
MarkTreeIter itr[1];
|
||||
if (!buf->b_signs || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)) {
|
||||
if (mt_invalid(pair.start) || marktree_decor_level(pair.start) < kDecorLevelVisible) {
|
||||
continue;
|
||||
if (!mt_invalid(pair.start) && pair.start.decor_full && decor_has_sign(pair.start.decor_full)) {
|
||||
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;
|
||||
|
||||
if (!decor || !decor_has_sign(decor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
decor_to_sign(decor, num_signs, sattrs, num_id, line_id, cul_id);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
while (itr->x) {
|
||||
MTKey mark = marktree_itr_current(itr);
|
||||
if (mark.pos.row < 0 || mark.pos.row > row) {
|
||||
if (mark.pos.row != row) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mt_end(mark) || mt_invalid(mark) || marktree_decor_level(mark) < kDecorLevelVisible) {
|
||||
goto next_mark;
|
||||
if (!mt_end(mark) && !mt_invalid(mark) && mark.decor_full && decor_has_sign(mark.decor_full)) {
|
||||
num_text += (mark.decor_full->sign_text != NULL);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void decor_to_sign(Decoration *decor, int *num_signs, SignTextAttrs sattrs[],
|
||||
HlPriId *num_id, HlPriId *line_id, HlPriId *cul_id)
|
||||
{
|
||||
if (decor->sign_text) {
|
||||
int j;
|
||||
for (j = (*num_signs); j > 0; j--) {
|
||||
if (sattrs[j - 1].priority >= decor->priority) {
|
||||
break;
|
||||
if (kv_size(signs)) {
|
||||
int width = (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') ? 1 : wp->w_scwidth;
|
||||
int idx = MIN(width, num_text) - 1;
|
||||
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
|
||||
|
||||
for (size_t i = 0; i < kv_size(signs); i++) {
|
||||
Decoration *decor = kv_A(signs, i).decor_full;
|
||||
if (idx >= 0 && decor->sign_text) {
|
||||
sattrs[idx].text = decor->sign_text;
|
||||
sattrs[idx--].hl_id = decor->sign_hl_id;
|
||||
}
|
||||
if (j < SIGN_SHOW_MAX) {
|
||||
sattrs[j] = sattrs[j - 1];
|
||||
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;
|
||||
}
|
||||
}
|
||||
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[] = {
|
||||
{ line_id, decor->line_hl_id },
|
||||
{ num_id, decor->number_hl_id },
|
||||
{ cul_id, decor->cursorline_hl_id },
|
||||
{ NULL, -1 },
|
||||
};
|
||||
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
|
||||
};
|
||||
}
|
||||
kv_destroy(signs);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the maximum required amount of sign columns needed between row and
|
||||
// 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) {
|
||||
return max;
|
||||
}
|
||||
@ -538,66 +507,41 @@ int decor_signcols(buf_T *buf, DecorState *state, int row, int end_row, int max)
|
||||
return 0;
|
||||
}
|
||||
|
||||
MarkTreeIter itr[1] = { 0 };
|
||||
marktree_itr_get(buf->b_marktree, 0, -1, itr);
|
||||
while (true) {
|
||||
MTKey mark = marktree_itr_current(itr);
|
||||
if (mark.pos.row < 0 || mark.pos.row > end_row) {
|
||||
break;
|
||||
int signcols = 0; // highest value of count
|
||||
for (int currow = row; currow <= end_row; currow++) {
|
||||
MarkTreeIter itr[1];
|
||||
if (!marktree_itr_get_overlap(buf->b_marktree, currow, 0, itr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
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++;
|
||||
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++;
|
||||
while (itr->x) {
|
||||
MTKey mark = marktree_itr_current(itr);
|
||||
if (mark.pos.row != currow) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (altpos.row >= row) {
|
||||
if (!mt_invalid(mark) && !mt_end(mark) && mark.decor_full && mark.decor_full->sign_text) {
|
||||
count++;
|
||||
if (count > signcols) {
|
||||
signcols = count;
|
||||
if (signcols >= max) {
|
||||
return max;
|
||||
}
|
||||
}
|
||||
}
|
||||
marktree_itr_next(buf->b_marktree, itr);
|
||||
}
|
||||
|
||||
next_mark:
|
||||
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;
|
||||
|
@ -60,7 +60,9 @@ struct Decoration {
|
||||
int col; // fixed col value, like win_col
|
||||
int virt_text_width; // width of virt_text
|
||||
char *sign_text;
|
||||
char *sign_name;
|
||||
int sign_hl_id;
|
||||
int sign_add_id;
|
||||
int number_hl_id;
|
||||
int line_hl_id;
|
||||
int cursorline_hl_id;
|
||||
@ -71,7 +73,7 @@ struct Decoration {
|
||||
};
|
||||
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
|
||||
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 {
|
||||
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)
|
||||
{
|
||||
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);
|
||||
msg_schedule_semsg_multiline("Error in decoration provider %s.%s:\n%s", ns_name, name, msg);
|
||||
}
|
||||
|
@ -460,85 +460,37 @@ 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".
|
||||
/// 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,
|
||||
int sign_cul_attr)
|
||||
{
|
||||
// Draw cells with the sign value or blank.
|
||||
wlv->c_extra = ' ';
|
||||
SignTextAttrs sattr = wlv->sattrs[sign_idx];
|
||||
wlv->c_final = NUL;
|
||||
if (nrcol) {
|
||||
wlv->n_extra = number_width(wp) + 1;
|
||||
|
||||
if (sattr.text && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
|
||||
size_t fill = nrcol ? (size_t)number_width(wp) - SIGN_WIDTH : 0;
|
||||
size_t sign_len = strlen(sattr.text);
|
||||
|
||||
// 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->char_attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr)
|
||||
? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0;
|
||||
} 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) {
|
||||
SignTextAttrs *sattr = sign_get_attr(sign_idx, wlv->sattrs, wp->w_scwidth);
|
||||
if (sattr != NULL) {
|
||||
wlv->p_extra = sattr->text;
|
||||
if (wlv->p_extra != NULL) {
|
||||
wlv->c_extra = NUL;
|
||||
wlv->c_final = NUL;
|
||||
|
||||
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 {
|
||||
size_t symbol_blen = strlen(wlv->p_extra);
|
||||
|
||||
// TODO(oni-link): Is sign text already extended to
|
||||
// full cell width?
|
||||
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;
|
||||
}
|
||||
wlv->c_extra = ' ';
|
||||
wlv->n_extra = nrcol ? number_width(wp) + 1 : SIGN_WIDTH;
|
||||
if (!nrcol) {
|
||||
wlv->char_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
{
|
||||
linenr_T num;
|
||||
@ -602,8 +554,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
|
||||
/// 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,
|
||||
int sign_num_attr, int sign_cul_attr)
|
||||
static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int sign_cul_attr)
|
||||
{
|
||||
bool has_cpo_n = vim_strchr(p_cpo, CPO_NUMCOL) != NULL;
|
||||
|
||||
@ -614,8 +565,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)) {
|
||||
// If 'signcolumn' is set to 'number' and a sign is present in "lnum",
|
||||
// then display the sign instead of the line number.
|
||||
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) {
|
||||
get_sign_display_info(true, wp, wlv, sign_idx, sign_cul_attr);
|
||||
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && wlv->sattrs[0].text) {
|
||||
get_sign_display_info(true, wp, wlv, 0, sign_cul_attr);
|
||||
} else {
|
||||
// Draw the line number (empty space after wrapping).
|
||||
if (wlv->row == wlv->startrow + wlv->filler_lines
|
||||
@ -1333,15 +1284,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
area_highlighting = true;
|
||||
}
|
||||
|
||||
HlPriId line_id = { 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 line_attr = 0;
|
||||
int sign_cul_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 };
|
||||
if (*wp->w_p_stc != NUL) {
|
||||
// Draw the 'statuscolumn' if option is set.
|
||||
@ -1350,18 +1298,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
statuscol.foldinfo = foldinfo;
|
||||
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
|
||||
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
|
||||
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul.hl_id : 0;
|
||||
statuscol.num_attr = sign_num.hl_id > 0 ? syn_id2attr(sign_num.hl_id) : 0;
|
||||
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul_attr : 0;
|
||||
statuscol.num_attr = sign_num_attr > 0 ? syn_id2attr(sign_num_attr) : 0;
|
||||
} else {
|
||||
if (sign_cul.hl_id > 0) {
|
||||
sign_cul_attr = syn_id2attr(sign_cul.hl_id);
|
||||
if (sign_cul_attr > 0) {
|
||||
sign_cul_attr = syn_id2attr(sign_cul_attr);
|
||||
}
|
||||
if (sign_num.hl_id > 0) {
|
||||
sign_num_attr = syn_id2attr(sign_num.hl_id);
|
||||
if (sign_num_attr > 0) {
|
||||
sign_num_attr = syn_id2attr(sign_num_attr);
|
||||
}
|
||||
}
|
||||
if (line_id.hl_id > 0) {
|
||||
wlv.line_attr = syn_id2attr(line_id.hl_id);
|
||||
if (line_attr > 0) {
|
||||
wlv.line_attr = syn_id2attr(line_attr);
|
||||
}
|
||||
|
||||
// Highlight the current line in the quickfix window.
|
||||
@ -1677,8 +1625,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
||||
wlv.draw_state = WL_SIGN;
|
||||
if (wp->w_scwidth > 0) {
|
||||
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;
|
||||
} else {
|
||||
sign_idx = 0;
|
||||
@ -1689,14 +1636,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) {
|
||||
// Show the line number, if desired.
|
||||
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) {
|
||||
wlv.draw_state = WL_STC;
|
||||
// Draw the 'statuscolumn' if option is set.
|
||||
if (statuscol.draw) {
|
||||
if (sign_num.hl_id == 0) {
|
||||
if (sign_num_attr == 0) {
|
||||
statuscol.num_attr = get_line_number_attr(wp, &wlv);
|
||||
}
|
||||
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
|
||||
int count = wp->w_scwidth;
|
||||
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));
|
||||
}
|
||||
// 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
|
||||
// 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')) {
|
||||
n = 2;
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ static dict_T *get_buffer_info(buf_T *buf)
|
||||
}
|
||||
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
|
||||
tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf));
|
||||
}
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/buffer.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/buffer_updates.h"
|
||||
#include "nvim/decoration.h"
|
||||
@ -161,21 +160,22 @@ static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
|
||||
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 };
|
||||
MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, it);
|
||||
if (!key.id) {
|
||||
return 0;
|
||||
MarkTreeIter itr[1] = { 0 };
|
||||
MTKey key = marktree_lookup_ns(buf->b_marktree, ns_id, id, false, itr);
|
||||
if (key.id) {
|
||||
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"
|
||||
///
|
||||
/// @return line number of the deleted mark
|
||||
linenr_T extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
||||
void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
||||
{
|
||||
assert(key.pos.row >= 0);
|
||||
|
||||
@ -195,7 +195,6 @@ linenr_T extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
|
||||
}
|
||||
|
||||
// TODO(bfredl): delete it from current undo header, opportunistically?
|
||||
return key.pos.row + 1;
|
||||
}
|
||||
|
||||
/// Free extmarks in a ns between lines
|
||||
@ -242,8 +241,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
|
||||
/// will be searched to the start, or end
|
||||
/// dir can be set to control the order of the array
|
||||
/// amount = amount of marks to find or -1 for all
|
||||
/// reverse can be set to control the order of the array
|
||||
/// 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,
|
||||
colnr_T u_col, int64_t amount, bool reverse, ExtmarkType type_filter,
|
||||
bool overlap)
|
||||
@ -301,7 +300,10 @@ static void push_mark(ExtmarkInfoArray *array, uint32_t ns_id, ExtmarkType type_
|
||||
if (type_filter != kExtmarkNone) {
|
||||
Decoration *decor = mark.decor_full;
|
||||
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) {
|
||||
type_flags |= kExtmarkVirtText;
|
||||
@ -309,8 +311,7 @@ static void push_mark(ExtmarkInfoArray *array, uint32_t ns_id, ExtmarkType type_
|
||||
if (decor && decor->virt_lines.size) {
|
||||
type_flags |= kExtmarkVirtLines;
|
||||
}
|
||||
if ((decor && (decor->line_hl_id || decor->cursorline_hl_id))
|
||||
|| mark.hl_id) {
|
||||
if (mark.hl_id) {
|
||||
type_flags |= kExtmarkHighlight;
|
||||
}
|
||||
|
||||
@ -598,6 +599,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);
|
||||
}
|
||||
|
||||
// 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,
|
||||
old_row, old_col,
|
||||
new_row, new_col);
|
||||
|
@ -84,9 +84,10 @@ typedef enum {
|
||||
typedef enum {
|
||||
kExtmarkNone = 0x1,
|
||||
kExtmarkSign = 0x2,
|
||||
kExtmarkVirtText = 0x4,
|
||||
kExtmarkVirtLines = 0x8,
|
||||
kExtmarkHighlight = 0x10,
|
||||
kExtmarkSignHL = 0x4,
|
||||
kExtmarkVirtText = 0x8,
|
||||
kExtmarkVirtLines = 0x10,
|
||||
kExtmarkHighlight = 0x20,
|
||||
} ExtmarkType;
|
||||
|
||||
// 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) \
|
||||
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
|
||||
// to this when the window is using the global argument list.
|
||||
EXTERN alist_T global_alist; // global argument list
|
||||
|
@ -246,9 +246,3 @@ typedef struct {
|
||||
} ColorItem;
|
||||
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \
|
||||
.is_default = false, .link_global = false }
|
||||
|
||||
/// highlight attributes with associated priorities
|
||||
typedef struct {
|
||||
int hl_id;
|
||||
int priority;
|
||||
} HlPriId;
|
||||
|
@ -70,7 +70,6 @@
|
||||
#include "nvim/quickfix.h"
|
||||
#include "nvim/runtime.h"
|
||||
#include "nvim/shada.h"
|
||||
#include "nvim/sign.h"
|
||||
#include "nvim/statusline.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/syntax.h"
|
||||
@ -218,8 +217,6 @@ void early_init(mparm_T *paramp)
|
||||
TIME_MSG("inits 1");
|
||||
|
||||
set_lang_var(); // set v:lang and v:ctype
|
||||
|
||||
init_signs();
|
||||
}
|
||||
|
||||
#ifdef MAKE_LIB
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/path.h"
|
||||
#include "nvim/quickfix.h"
|
||||
#include "nvim/sign.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/textobject.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) {
|
||||
buf->b_has_qf_entry &= ~BUF_HAS_LL_ENTRY;
|
||||
}
|
||||
|
||||
sign_mark_adjust(buf, line1, line2, amount, amount_after);
|
||||
}
|
||||
|
||||
if (op != kExtmarkNOOP) {
|
||||
|
@ -758,8 +758,7 @@ int win_col_off(win_T *wp)
|
||||
return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL) ?
|
||||
(number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
|
||||
+ ((cmdwin_type == 0 || wp != curwin) ? 0 : 1)
|
||||
+ win_fdccol_count(wp)
|
||||
+ (win_signcol_count(wp) * win_signcol_width(wp));
|
||||
+ win_fdccol_count(wp) + (win_signcol_count(wp) * SIGN_WIDTH);
|
||||
}
|
||||
|
||||
int curwin_col_off(void)
|
||||
|
@ -6170,7 +6170,7 @@ bool fish_like_shell(void)
|
||||
/// buffer signs and on user configuration.
|
||||
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.
|
||||
@ -6182,14 +6182,10 @@ bool win_no_signcol(win_T *wp)
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
if (is_fixed) {
|
||||
*is_fixed = 1;
|
||||
}
|
||||
|
||||
if (win_no_signcol(wp)) {
|
||||
return 0;
|
||||
}
|
||||
@ -6203,11 +6199,6 @@ int win_signcol_configured(win_T *wp, int *is_fixed)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_fixed) {
|
||||
// auto or auto:<NUM>
|
||||
*is_fixed = 0;
|
||||
}
|
||||
|
||||
int minimum = 0, maximum = 1;
|
||||
|
||||
if (!strncmp(scl, "auto:", 5)) {
|
||||
|
@ -7590,12 +7590,6 @@ return {
|
||||
number (maximum 9), e.g. "yes:3"
|
||||
"number" display signs in the 'number' column. If the number
|
||||
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',
|
||||
full_name = 'signcolumn',
|
||||
|
1835
src/nvim/sign.c
1835
src/nvim/sign.c
File diff suppressed because it is too large
Load Diff
@ -5,47 +5,23 @@
|
||||
#include "nvim/pos.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.
|
||||
typedef struct {
|
||||
char *text;
|
||||
int hl_id;
|
||||
int priority;
|
||||
} 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_DEF_PRIO 10
|
||||
|
||||
// type argument for sign_get_attr()
|
||||
typedef enum {
|
||||
SIGN_LINEHL,
|
||||
SIGN_NUMHL,
|
||||
SIGN_TEXT,
|
||||
} SignType;
|
||||
#define SIGN_WIDTH 2 // Number of display cells for a sign in the signcolumn
|
||||
#define SIGN_SHOW_MAX 9 // Maximum number of signs shown on a single line
|
||||
#define SIGN_DEF_PRIO 10 // Default sign highlight priority
|
||||
|
@ -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);
|
||||
for (int i = 0; i < width; i++) {
|
||||
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 : " ";
|
||||
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);
|
||||
}
|
||||
stl_items[curitem].type = Highlight;
|
||||
|
@ -4680,7 +4680,7 @@ l5
|
||||
|
||||
screen:expect{grid=[[
|
||||
{1: }^l1 |
|
||||
S2S1l2 |
|
||||
S1S2l2 |
|
||||
{1: }l3 |
|
||||
{1: }l4 |
|
||||
{1: }l5 |
|
||||
@ -4720,7 +4720,7 @@ l5
|
||||
screen:expect{grid=[[
|
||||
{1: }^l1 |
|
||||
S1{1: }l2 |
|
||||
S2S1l3 |
|
||||
S1S2l3 |
|
||||
S2{1: }l4 |
|
||||
{1: }l5 |
|
||||
{1: } |
|
||||
@ -4765,7 +4765,7 @@ l5
|
||||
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
||||
|
||||
screen:expect{grid=[[
|
||||
S4S1^l1 |
|
||||
S1S4^l1 |
|
||||
x S2l2 |
|
||||
S5{1: }l3 |
|
||||
{1: }l4 |
|
||||
@ -4792,9 +4792,9 @@ l5
|
||||
meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
|
||||
|
||||
screen:expect{grid=[[
|
||||
S3S4S1^l1 |
|
||||
S1S3S4^l1 |
|
||||
x S2S3l2 |
|
||||
S5S3{1: }l3 |
|
||||
S3S5{1: }l3 |
|
||||
S3{1: }l4 |
|
||||
S3{1: }l5 |
|
||||
{1: } |
|
||||
@ -4848,15 +4848,15 @@ l5
|
||||
end
|
||||
|
||||
screen:expect{grid=[[
|
||||
X Y Z W {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} |
|
||||
X Y Z W {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} |
|
||||
X Y Z W {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} |
|
||||
X Y Z W {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} |
|
||||
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} |
|
||||
W X Y Z {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} |
|
||||
W X Y Z {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} |
|
||||
W X Y Z {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} |
|
||||
W X Y Z {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)
|
||||
|
@ -274,9 +274,9 @@ describe('Signs', function()
|
||||
-- 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')
|
||||
command('sign place 6 line=3 name=pietSearch buffer=1')
|
||||
command('sign place 7 line=3 name=pietWarn buffer=1')
|
||||
command('sign place 5 line=3 name=pietError buffer=1')
|
||||
screen:expect([[
|
||||
{1:>>}{8:XX}{6: 1 }a |
|
||||
{8:XX}{1:>>}{6: 2 }b |
|
||||
|
@ -377,6 +377,7 @@ describe('statuscolumn', function()
|
||||
|
|
||||
]])
|
||||
command('set breakindent')
|
||||
command('sign unplace 2')
|
||||
feed('J2gjg0')
|
||||
screen:expect([[
|
||||
{2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
|
||||
|
@ -1501,50 +1501,33 @@ func Test_sign_priority()
|
||||
call sign_place(3, '', 'sign3', 'Xsign',
|
||||
\ {'lnum' : 4, 'priority' : 20})
|
||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||
call assert_equal([
|
||||
let se = [
|
||||
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
|
||||
\ 'priority' : 20},
|
||||
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
|
||||
\ 'priority' : 20},
|
||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
|
||||
\ 'priority' : 20}],
|
||||
\ s[0].signs)
|
||||
\ 'priority' : 20}]
|
||||
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
|
||||
call sign_place(1, '', 'sign1', 'Xsign',
|
||||
\ {'lnum' : 4, 'priority' : 20})
|
||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||
call assert_equal([
|
||||
\ {'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)
|
||||
call assert_equal(se, s[0].signs)
|
||||
" Place the first sign again with the same priority
|
||||
call sign_place(1, '', 'sign1', 'Xsign',
|
||||
\ {'lnum' : 4, 'priority' : 20})
|
||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||
call assert_equal([
|
||||
\ {'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)
|
||||
call assert_equal(se, s[0].signs)
|
||||
" Place the middle sign again with the same priority
|
||||
call sign_place(3, '', 'sign3', 'Xsign',
|
||||
\ {'lnum' : 4, 'priority' : 20})
|
||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||
call assert_equal([
|
||||
\ {'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 assert_equal(se, s[0].signs)
|
||||
|
||||
call sign_unplace('*')
|
||||
|
||||
@ -1670,34 +1653,33 @@ func Test_sign_lnum_adjust()
|
||||
" changes made by this function.
|
||||
let &g:undolevels=&g:undolevels
|
||||
|
||||
" Nvim: make sign adjustment when deleting lines match Vim
|
||||
set signcolumn=yes:1
|
||||
" Nvim: deleting a line removes the signs along with it.
|
||||
|
||||
" Delete the line with the sign
|
||||
call deletebufline('', 4)
|
||||
let l = sign_getplaced(bufnr(''))
|
||||
call assert_equal(4, l[0].signs[0].lnum)
|
||||
" " Delete the line with the sign
|
||||
" call deletebufline('', 4)
|
||||
" let l = sign_getplaced(bufnr(''))
|
||||
" call assert_equal(4, l[0].signs[0].lnum)
|
||||
|
||||
" Undo the delete operation
|
||||
undo
|
||||
let l = sign_getplaced(bufnr(''))
|
||||
call assert_equal(5, l[0].signs[0].lnum)
|
||||
" " Undo the delete operation
|
||||
" undo
|
||||
" let l = sign_getplaced(bufnr(''))
|
||||
" call assert_equal(5, l[0].signs[0].lnum)
|
||||
|
||||
" Break the undo
|
||||
let &g:undolevels=&g:undolevels
|
||||
" " Break the undo
|
||||
" let &g:undolevels=&g:undolevels
|
||||
|
||||
" 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)
|
||||
call deletebufline('', 3, 6)
|
||||
let l = sign_getplaced(bufnr(''))
|
||||
call assert_equal(5, l[0].signs[0].lnum)
|
||||
" " 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)
|
||||
" call deletebufline('', 3, 6)
|
||||
" let l = sign_getplaced(bufnr(''))
|
||||
" call assert_equal(5, l[0].signs[0].lnum)
|
||||
|
||||
" Undo the delete operation. Sign should be restored to the previous line
|
||||
undo
|
||||
let l = sign_getplaced(bufnr(''))
|
||||
call assert_equal(5, l[0].signs[0].lnum)
|
||||
" " Undo the delete operation. Sign should be restored to the previous line
|
||||
" undo
|
||||
" let l = sign_getplaced(bufnr(''))
|
||||
" call assert_equal(5, l[0].signs[0].lnum)
|
||||
|
||||
set signcolumn&
|
||||
" set signcolumn&
|
||||
|
||||
sign unplace * group=*
|
||||
sign undefine sign1
|
||||
@ -1971,7 +1953,8 @@ func Test_sign_funcs_multi()
|
||||
call sign_unplace('*')
|
||||
|
||||
" 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',
|
||||
\ 'buffer' : 'Xsign', 'lnum' : 11},
|
||||
\ {'group' : 'g2', 'name' : 'sign2',
|
||||
@ -1980,17 +1963,17 @@ func Test_sign_funcs_multi()
|
||||
\ 'buffer' : 'Xsign', 'lnum' : 11}]))
|
||||
let s = sign_getplaced('Xsign', {'group' : '*'})
|
||||
call assert_equal([
|
||||
\ {'id' : 5, 'name' : 'sign3', 'lnum' : 11,
|
||||
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 11,
|
||||
\ 'group' : '', 'priority' : 10},
|
||||
\ {'id' : 1, 'name' : 'sign2', 'lnum' : 11,
|
||||
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 11,
|
||||
\ 'group' : 'g2', 'priority' : 10},
|
||||
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 11,
|
||||
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 11,
|
||||
\ 'group' : 'g1', 'priority' : 10}], s[0].signs)
|
||||
|
||||
" Change an existing sign without specifying the group
|
||||
call assert_equal([5], [{'id' : 5, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
|
||||
let s = sign_getplaced('Xsign', {'id' : 5, 'group' : ''})
|
||||
call assert_equal([{'id' : 5, 'name' : 'sign1', 'lnum' : 11,
|
||||
call assert_equal([4], [{'id' : 4, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
|
||||
let s = sign_getplaced('Xsign', {'id' : 4, 'group' : ''})
|
||||
call assert_equal([{'id' : 4, 'name' : 'sign1', 'lnum' : 11,
|
||||
\ 'group' : '', 'priority' : 10}], s[0].signs)
|
||||
|
||||
" 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:")
|
||||
|
||||
" Unplace multiple signs
|
||||
call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 5},
|
||||
\ {'id' : 1, 'group' : 'g1'}, {'id' : 1, 'group' : 'g2'}]))
|
||||
call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 4},
|
||||
\ {'id' : 2, 'group' : 'g1'}, {'id' : 3, 'group' : 'g2'}]))
|
||||
|
||||
" Invalid arguments
|
||||
call assert_equal([], []->sign_unplacelist())
|
||||
|
Loading…
Reference in New Issue
Block a user