aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/sign.c
diff options
context:
space:
mode:
authorJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2020-02-25 00:35:19 -0500
committerJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2020-03-01 20:02:09 -0500
commitc6481f70c22899604b7707299bb96d0f0768334f (patch)
tree8a4a771d85ba0412d0520fda224def3e759faae4 /src/nvim/sign.c
parent1caa85b677bc287883895558281d23e1fd55817e (diff)
downloadrneovim-c6481f70c22899604b7707299bb96d0f0768334f.tar.gz
rneovim-c6481f70c22899604b7707299bb96d0f0768334f.tar.bz2
rneovim-c6481f70c22899604b7707299bb96d0f0768334f.zip
vim-patch:8.1.1489: sign order wrong when priority was changed
Problem: Sign order wrong when priority was changed. Solution: Reorder signs when priority is changed. (Yegappan Lakshmanan, closes vim/vim#4502) https://github.com/vim/vim/commit/64416127fc184b5544530afe818722679158f059
Diffstat (limited to 'src/nvim/sign.c')
-rw-r--r--src/nvim/sign.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index e81d09aa4b..baa9c6538f 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -265,6 +265,81 @@ dict_T * sign_get_info(signlist_T *sign)
return d;
}
+// Sort the signs placed on the same line as "sign" by priority. Invoked after
+// changing the priority of an already placed sign. Assumes the signs in the
+// buffer are sorted by line number and priority.
+static void sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // If there is only one sign in the buffer or only one sign on the line or
+ // the sign is already sorted by priority, then return.
+ if ((sign->prev == NULL
+ || sign->prev->lnum != sign->lnum
+ || sign->prev->priority > sign->priority)
+ && (sign->next == NULL
+ || sign->next->lnum != sign->lnum
+ || sign->next->priority < sign->priority)) {
+ return;
+ }
+
+ // One or more signs on the same line as 'sign'
+ // Find a sign after which 'sign' should be inserted
+
+ // First search backward for a sign with higher priority on the same line
+ signlist_T *p = sign;
+ while (p->prev != NULL
+ && p->prev->lnum == sign->lnum
+ && p->prev->priority <= sign->priority) {
+ p = p->prev;
+ }
+ if (p == sign) {
+ // Sign not found. Search forward for a sign with priority just before
+ // 'sign'.
+ p = sign->next;
+ while (p->next != NULL
+ && p->next->lnum == sign->lnum
+ && p->next->priority > sign->priority) {
+ p = p->next;
+ }
+ }
+
+ // Remove 'sign' from the list
+ if (buf->b_signlist == sign) {
+ buf->b_signlist = sign->next;
+ }
+ if (sign->prev != NULL) {
+ sign->prev->next = sign->next;
+ }
+ if (sign->next != NULL) {
+ sign->next->prev = sign->prev;
+ }
+ sign->prev = NULL;
+ sign->next = NULL;
+
+ // Re-insert 'sign' at the right place
+ if (p->priority <= sign->priority) {
+ // 'sign' has a higher priority and should be inserted before 'p'
+ sign->prev = p->prev;
+ sign->next = p;
+ p->prev = sign;
+ if (sign->prev != NULL) {
+ sign->prev->next = sign;
+ }
+ if (buf->b_signlist == p) {
+ buf->b_signlist = sign;
+ }
+ } else {
+ // 'sign' has a lower priority and should be inserted after 'p'
+ sign->prev = p;
+ sign->next = p->next;
+ p->next = sign;
+ if (sign->next != NULL) {
+ sign->next->prev = sign;
+ }
+ }
+}
+
+
/// Add the sign into the signlist. Find the right spot to do it though.
void buf_addsign(
buf_T *buf, // buffer to store sign in
@@ -285,6 +360,7 @@ void buf_addsign(
// Update an existing sign
sign->typenr = typenr;
sign->priority = prio;
+ sign_sort_by_prio_on_line(buf, sign);
return;
} else if (lnum < sign->lnum) {
insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr);