diff options
author | georgev93 <39860568+georgev93@users.noreply.github.com> | 2025-01-24 22:57:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-24 19:57:45 -0800 |
commit | 931ee5591fa764a769946318e05062098baf7c21 (patch) | |
tree | 82dd7f486cc47d1e7a2d44d204ab12f967a5e0da /src/nvim/drawline.c | |
parent | c6d2cbf8f51abfa0c9d244ef384a15b0b69e16c6 (diff) | |
download | rneovim-931ee5591fa764a769946318e05062098baf7c21.tar.gz rneovim-931ee5591fa764a769946318e05062098baf7c21.tar.bz2 rneovim-931ee5591fa764a769946318e05062098baf7c21.zip |
feat(extmarks): virtual text can be right-aligned, truncated #31921
Problem: Right aligned virtual text can cover up buffer text if virtual
text is too long
Solution: An additional option for `virt_text_pos` called
`eol_right_align` has been added to truncate virtual text if it would
have otherwise covered up buffer text. This ensures the virtual text
extends no further left than EOL.
Diffstat (limited to 'src/nvim/drawline.c')
-rw-r--r-- | src/nvim/drawline.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 4a7bc9170a..37a42917b0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -263,6 +263,9 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int *const indices = state->ranges_i.items; DecorRangeSlot *const slots = state->slots.items; + /// Total width of all virtual text with "eol_right_align" alignment + int totalWidthOfEolRightAlignedVirtText = 0; + for (int i = 0; i < end; i++) { DecorRange *item = &slots[indices[i]].range; if (!(item->start_row == state->row && decor_virt_pos(item))) { @@ -277,7 +280,44 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int if (decor_virt_pos(item) && item->draw_col == -1) { bool updated = true; VirtTextPos pos = decor_virt_pos_kind(item); - if (pos == kVPosRightAlign) { + + if (do_eol && pos == kVPosEndOfLineRightAlign) { + int eolOffset = 0; + if (totalWidthOfEolRightAlignedVirtText == 0) { + // Look ahead to the remaining decor items + for (int j = i; j < end; j++) { + /// A future decor to be handled in this function's call + DecorRange *lookaheadItem = &slots[indices[j]].range; + + if (lookaheadItem->start_row != state->row + || !decor_virt_pos(lookaheadItem) + || lookaheadItem->draw_col != -1) { + continue; + } + + /// The Virtual Text of the decor item we're looking ahead to + DecorVirtText *lookaheadVt = NULL; + if (item->kind == kDecorKindVirtText) { + assert(item->data.vt); + lookaheadVt = item->data.vt; + } + + if (decor_virt_pos_kind(lookaheadItem) == kVPosEndOfLineRightAlign) { + // An extra space is added for single character spacing in EOL alignment + totalWidthOfEolRightAlignedVirtText += (lookaheadVt->width + 1); + } + } + + // Remove one space from the total width since there's no single space after the last entry + totalWidthOfEolRightAlignedVirtText--; + + if (totalWidthOfEolRightAlignedVirtText <= (right_pos - state->eol_col)) { + eolOffset = right_pos - totalWidthOfEolRightAlignedVirtText - state->eol_col; + } + } + + item->draw_col = state->eol_col + eolOffset; + } else if (pos == kVPosRightAlign) { right_pos -= vt->width; item->draw_col = right_pos; } else if (pos == kVPosEndOfLine && do_eol) { @@ -304,7 +344,7 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int int vcol = item->draw_col - col_off; int col = draw_virt_text_item(buf, item->draw_col, vt->data.virt_text, vt->hl_mode, max_col, vcol); - if (vt->pos == kVPosEndOfLine && do_eol) { + if (do_eol && ((vt->pos == kVPosEndOfLine) || (vt->pos == kVPosEndOfLineRightAlign))) { state->eol_col = col + 1; } *end_col = MAX(*end_col, col); |