aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawline.c
diff options
context:
space:
mode:
authorgeorgev93 <39860568+georgev93@users.noreply.github.com>2025-01-24 22:57:45 -0500
committerGitHub <noreply@github.com>2025-01-24 19:57:45 -0800
commit931ee5591fa764a769946318e05062098baf7c21 (patch)
tree82dd7f486cc47d1e7a2d44d204ab12f967a5e0da /src/nvim/drawline.c
parentc6d2cbf8f51abfa0c9d244ef384a15b0b69e16c6 (diff)
downloadrneovim-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.c44
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);