diff options
author | Matthieu Coudron <teto@users.noreply.github.com> | 2021-04-18 17:12:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-18 17:12:41 +0200 |
commit | e343437bb6b82a48b1001d98a08fb5c63dccda30 (patch) | |
tree | e9f487113ba6e3402e837fc7872a250183980077 | |
parent | a129887c00a2d5e49fc551ba0bbffe88cefb56c0 (diff) | |
parent | 5b8575fa0dc689e6de90ee3cc6805c0f8742c320 (diff) | |
download | rneovim-e343437bb6b82a48b1001d98a08fb5c63dccda30.tar.gz rneovim-e343437bb6b82a48b1001d98a08fb5c63dccda30.tar.bz2 rneovim-e343437bb6b82a48b1001d98a08fb5c63dccda30.zip |
Merge pull request #12323 from da-x/orphaned-signs
Handle 'orphaned signs' on line deletion for signcolumn >= 2
-rw-r--r-- | runtime/doc/options.txt | 6 | ||||
-rw-r--r-- | src/nvim/option.c | 16 | ||||
-rw-r--r-- | src/nvim/sign.c | 26 | ||||
-rw-r--r-- | src/nvim/testdir/test_signs.vim | 21 | ||||
-rw-r--r-- | test/functional/ui/sign_spec.lua | 18 |
5 files changed, 62 insertions, 25 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 651d4c4bc7..63a9db9d0d 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5555,6 +5555,12 @@ 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 appearence not appear weird + during line deletion. + *'smartcase'* *'scs'* *'nosmartcase'* *'noscs'* 'smartcase' 'scs' boolean (default off) diff --git a/src/nvim/option.c b/src/nvim/option.c index 914b92618c..666c526a18 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7583,9 +7583,19 @@ int csh_like_shell(void) /// buffer signs and on user configuration. int win_signcol_count(win_T *wp) { + return win_signcol_configured(wp, NULL); +} + +/// Return the number of requested sign columns, based on user / configuration. +int win_signcol_configured(win_T *wp, int *is_fixed) +{ int minimum = 0, maximum = 1, needed_signcols; const char *scl = (const char *)wp->w_p_scl; + if (is_fixed) { + *is_fixed = 1; + } + // Note: It checks "no" or "number" in 'signcolumn' option if (*scl == 'n' && (*(scl + 1) == 'o' || (*(scl + 1) == 'u' @@ -7603,7 +7613,11 @@ int win_signcol_count(win_T *wp) return 1; } - // auto or auto:<NUM> + if (is_fixed) { + // auto or auto:<NUM> + *is_fixed = 0; + } + if (!strncmp(scl, "auto:", 5)) { // Variable depending on a configuration maximum = scl[5] - '0'; diff --git a/src/nvim/sign.c b/src/nvim/sign.c index c7dc1a5b22..5c7b497a19 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -18,6 +18,7 @@ #include "nvim/move.h" #include "nvim/screen.h" #include "nvim/syntax.h" +#include "nvim/option.h" /// Struct to hold the sign properties. typedef struct sign sign_T; @@ -726,15 +727,29 @@ void sign_mark_adjust( long amount_after ) { - sign_entry_T *sign; // a sign in a b_signlist - linenr_T new_lnum; // new line number to assign to sign + sign_entry_T *sign; // a sign in a b_signlist + sign_entry_T *next; // the next sign in a b_signlist + sign_entry_T *last = NULL; // pointer to pointer to current sign + sign_entry_T **lastp = NULL; // pointer to pointer to current sign + linenr_T new_lnum; // new line number to assign to sign + int is_fixed = 0; + int signcol = win_signcol_configured(curwin, &is_fixed); curbuf->b_signcols_max = -1; + lastp = &curbuf->b_signlist; - FOR_ALL_SIGNS_IN_BUF(curbuf, sign) { + for (sign = curbuf->b_signlist; sign != NULL; sign = next) { + next = sign->se_next; new_lnum = sign->se_lnum; if (sign->se_lnum >= line1 && sign->se_lnum <= line2) { - if (amount != MAXLNUM) { + if (amount == MAXLNUM && (!is_fixed || signcol >= 2)) { + *lastp = next; + if (next) { + next->se_prev = last; + } + xfree(sign); + continue; + } else { new_lnum += amount; } } else if (sign->se_lnum > line2) { @@ -746,6 +761,9 @@ void sign_mark_adjust( if (sign->se_lnum >= line1 && new_lnum <= curbuf->b_ml.ml_line_count) { sign->se_lnum = new_lnum; } + + last = sign; + lastp = &sign->se_next; } } diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index f6b96c1e5d..9753100375 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -1628,26 +1628,7 @@ func Test_sign_lnum_adjust() " 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) - - " Break the undo - let &undolevels=&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) - - " 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) + call assert_equal(0, len(l[0].signs)) sign unplace * group=* sign undefine sign1 diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index 1937102782..06c92a4b10 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -264,6 +264,24 @@ describe('Signs', function() {0:~ }| | ]]} + -- line deletion deletes signs. + command('2d') + screen:expect([[ + {1:>>}XX{2: }{6: 1 }a | + XX{1:>>}WW{6: 2 }^c | + {2: }{6: 3 } | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) end) it('auto-resize sign column with minimum size (#13783)', function() |