Files
neovim/src/nvim/decoration.h
bfredl 5119c03be7 fix(treesitter): use subpriorities for tree ordering
This partially reverts 0b8a72b739,
that is unreverts 15e77a56b7

"priority" is an internal neovim concept which does not occur in shared
queries. Ideally a single priority space should eventually be enough
for our needs. But as we don't want to poke at the usages of
priorities right now in the wider ecosystem,
introduce the "subpriorities" so that treesitter code can distinguish
highlights of the same priorities with different tree nesting depth.

This mainly affects `injection.combined` as parent-tree nodes might appear
in the middle of child-tree nodes which otherwise is not possible.
2025-09-09 12:56:49 +02:00

118 lines
3.5 KiB
C

#pragma once
#include <stdbool.h>
#include <stddef.h> // IWYU pragma: keep
#include <stdint.h>
#include "klib/kvec.h"
#include "nvim/decoration_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
#include "nvim/marktree_defs.h"
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/sign_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
// actual Decor* data is in decoration_defs.h
/// Keep in sync with VirtTextPos in decoration_defs.h
EXTERN const char *const virt_text_pos_str[] INIT( = { "eol", "eol_right_align", "inline",
"overlay", "right_align", "win_col" });
/// Keep in sync with HlMode in decoration_defs.h
EXTERN const char *const hl_mode_str[] INIT( = { "", "replace", "combine", "blend" });
typedef enum {
kDecorKindHighlight,
kDecorKindSign,
kDecorKindVirtText,
kDecorKindVirtLines,
kDecorKindUIWatched,
} DecorRangeKindEnum;
typedef uint8_t DecorRangeKind;
typedef struct {
int start_row;
int start_col;
int end_row;
int end_col;
int ordering; ///< range insertion order
DecorPriorityInternal priority_internal;
bool owned; ///< ephemeral decoration, free memory immediately
DecorRangeKind kind;
// next pointers MUST NOT be used, these are separate ranges
// vt->next could be pointing to freelist memory at this point
union {
DecorSignHighlight sh;
DecorVirtText *vt;
struct {
uint32_t ns_id;
uint32_t mark_id;
VirtTextPos pos;
} ui;
} data;
int attr_id; ///< cached lookup of inl.hl_id if it was a highlight
/// Screen column to draw the virtual text.
/// When -1, it should be drawn on the current screen line after deciding where.
/// When -3, it may be drawn at a position yet to be assigned.
/// When -10, it has just been added.
/// When INT_MIN, it should no longer be drawn.
int draw_col;
} DecorRange;
/// DecorRange can be removed from `DecorState` list in any order,
/// so we track available slots using a freelist (with `next_free_i`).
/// The list head is in `DecorState.free_slot_i`.
typedef union {
DecorRange range;
int next_free_i;
} DecorRangeSlot;
typedef struct {
MarkTreeIter itr[1];
kvec_t(DecorRangeSlot) slots;
kvec_t(int) ranges_i;
/// Indices in [0; current_end) of `ranges_i` point to ranges that start
/// before current position. Sorted by priority and order of insertion.
int current_end;
/// Indices in [future_begin, kv_size(ranges_i)) of `ranges_i` point to
/// ranges that start after current position. Sorted by starting position.
int future_begin;
/// Head of DecorRangeSlot freelist. -1 if none are freed.
int free_slot_i;
/// Index for keeping track of range insertion order.
int new_range_ordering;
win_T *win;
int top_row;
int row;
int col_until;
int current;
int eol_col;
int conceal;
schar_T conceal_char;
int conceal_attr;
TriState spell;
bool running_decor_provider;
bool itr_valid;
} DecorState;
EXTERN DecorState decor_state INIT( = { 0 });
// TODO(bfredl): These should maybe be per-buffer, so that all resources
// associated with a buffer can be freed when the buffer is unloaded.
EXTERN kvec_t(DecorSignHighlight) decor_items INIT( = KV_INITIAL_VALUE);
#include "decoration.h.generated.h"
#include "decoration.h.inline.generated.h"
static inline int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *state)
FUNC_ATTR_ALWAYS_INLINE
{
if (col <= state->col_until) {
return state->current;
}
return decor_redraw_col_impl(wp, col, win_col, hidden, state);
}