Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cf2f7bf
add TableIterator (#79)
defname Oct 20, 2025
6314f66
Add early-exit guards to table lookup functions (#80)
defname Oct 21, 2025
6802145
Add CodeRabbit configuration template
defname Oct 21, 2025
c42caad
Merge branch 'main' into feat/71-syntax-highlighting
defname Oct 23, 2025
b7fce6c
add SyntaxHighlightingBinding to connect SyntaxHighlighting with the …
defname Oct 24, 2025
c0f1c11
fix some obvious bugs in SyntaxHighlighingBinding
defname Oct 24, 2025
5d44d53
fix memory leak
defname Oct 24, 2025
c28e50e
add basic test
defname Oct 24, 2025
f5e0b14
add Stack_Size()
defname Oct 24, 2025
57bc8db
rename test function
defname Oct 24, 2025
1f598f8
add Stack_CopyTo()
defname Oct 24, 2025
517e941
save open_blocks_at_begin and open_blocks_at_end to SyntaxHighlightin…
defname Oct 24, 2025
6229560
Merge branch 'feat/71-syntax-highlighting' into feat/sh-tb-bindings
defname Oct 24, 2025
f748bb5
adept code to the changed SyntaxHighlighingString scheme
defname Oct 24, 2025
c13c280
improve tests
defname Oct 25, 2025
154937f
Compare the open_blocks_at_begin with the open_blocks parameter for a…
defname Oct 25, 2025
558c925
add testcases and improve test framework's flexibility
defname Oct 25, 2025
f412a0d
fix coderabbit config
defname Oct 25, 2025
0b223a6
fix resizing in Stack_CopyTo()
defname Oct 25, 2025
cb33a8f
add NULL guard to SyntaxHighlighting_HighlightString()
defname Oct 25, 2025
6b6703b
change multiline string to valid C string
defname Oct 25, 2025
811b0e2
change multiline strings to valid C strings
defname Oct 25, 2025
b0a7167
set shs->tags_capacity correctly in SyntaxHighlioghtingString_Create()
defname Oct 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
805 changes: 805 additions & 0 deletions .coderabbit.yaml

Large diffs are not rendered by default.

66 changes: 38 additions & 28 deletions src/common/stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,23 @@
#include <string.h>
#include "logging.h"


static void increase_capacity(Stack *stack) {
if (!stack) {
static void resize_capacity(Stack *stack, size_t new_capacity) {
if (!stack || stack->capacity >= new_capacity) {
return;
}
if (stack->capacity == 0) {
stack->capacity = STACK_INITIAL_CAPACITY;
}
else {
stack->capacity *= STACK_GROW_FACTOR;
}
stack->items = realloc(stack->items, stack->capacity * sizeof(void *));
stack->items = realloc(stack->items, new_capacity * sizeof(void *));
if (!stack->items) {
logFatal("Failed to reallocate stack items.");
}
stack->capacity = new_capacity;
}
Comment thread
defname marked this conversation as resolved.

static void increase_capacity(Stack *stack) {
if (!stack) {
return;
}
size_t new_cap = stack->capacity == 0 ? STACK_INITIAL_CAPACITY : stack->capacity * STACK_GROW_FACTOR;
resize_capacity(stack, new_cap);
}

void Stack_Init(Stack *stack) {
Expand Down Expand Up @@ -72,28 +74,32 @@ Stack *Stack_Copy(const Stack *src) {
if (!src) {
return NULL;
}
Stack *copy = malloc(sizeof(Stack));
if (!copy) {
logFatal("Failed to allocate memory for stack copy.");
}

size_t cap = src->capacity ? src->capacity : STACK_INITIAL_CAPACITY; // handle capacity == 0
Stack *copy = Stack_Create();
Stack_CopyTo(copy, src);
return copy;
}

// allocate memory
copy->items = malloc(cap * sizeof(void *));
if (!copy->items) {
logFatal("Failed to allocate memory for stack copy items.");
void Stack_CopyTo(Stack *dst, const Stack *src) {
if (!dst || !src) {
return;
}
// only copy items
memcpy(copy->items, src->items, src->size * sizeof(void *));
if (src->size == 0) {
// early exit if src is empty
Stack_Clear(dst);
return;
}
if (src->size > dst->capacity) {
// resize dst to a multiple of STACK_INITIAL_SIZE
size_t new_cap = ((src->size + STACK_INITIAL_CAPACITY - 1) / STACK_INITIAL_CAPACITY) * STACK_INITIAL_CAPACITY;
resize_capacity(dst, new_cap);
}
// copy items
memcpy(dst->items, src->items, src->size * sizeof(void *));
Comment thread
defname marked this conversation as resolved.
// set remainder to 0
if (cap > src->size) {
memset(copy->items + src->size, 0, (cap - src->size) * sizeof(void *));
if (dst->capacity > src->size) {
memset(dst->items + src->size, 0, (dst->capacity - src->size) * sizeof(void *));
}
copy->size = src->size;
copy->capacity = src->capacity;

return copy;
dst->size = src->size;
}

void Stack_Push(Stack *stack, void *item) {
Expand Down Expand Up @@ -137,6 +143,10 @@ bool Stack_IsEmpty(const Stack *stack) {
return stack->size == 0;
}

size_t Stack_Size(const Stack *stack) {
return stack->size;
}

void Stack_Clear(Stack *stack) {
if (!stack) {
return;
Expand Down
4 changes: 3 additions & 1 deletion src/common/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ void Stack_Deinit(Stack *stack);
Stack *Stack_Create();
void Stack_Destroy(Stack *stack);

Stack *Stack_Copy(const Stack *stack);
Stack *Stack_Copy(const Stack *stack); //< create a new copy of stack
void Stack_CopyTo(Stack *dst, const Stack *src); //< copy src to the (already initialized) dst

void Stack_Push(Stack *stack, void *item);
void *Stack_Pop(Stack *stack);
Expand All @@ -44,6 +45,7 @@ void *Stack_Peek(const Stack *stack);
bool Stack_Has(const Stack *stack, const void *item);

bool Stack_IsEmpty(const Stack *stack);
size_t Stack_Size(const Stack *stack);

void Stack_Clear(Stack *stack);

Expand Down
38 changes: 31 additions & 7 deletions src/syntax/highlighting.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ SyntaxHighlightingString *SyntaxHighlightingString_Create(const String *text) {
shs->tags = NULL;
shs->tags_count = 0;
shs->tags_capacity = 0;
Stack_Init(&shs->open_blocks_at_begin);
Stack_Init(&shs->open_blocks_at_end);

shs->tags = malloc(sizeof(SyntaxHighlightingTag) * SHS_TAGS_INITIAL_CAPACITY);
if (!shs->tags) {
logFatal("Cannot allocate memory for SyntaxHighlightingString tags.");
}
shs->tags_capacity = SHS_TAGS_INITIAL_CAPACITY;

return shs;
}
Expand All @@ -44,7 +46,9 @@ void SyntaxHighlightingString_Destroy(SyntaxHighlightingString *shs) {
shs->tags_count = 0;
shs->tags_capacity = 0;
shs->text = NULL;
Stack_Deinit(&shs->open_blocks_at_begin);
Stack_Deinit(&shs->open_blocks_at_end);

free(shs);
}

Expand Down Expand Up @@ -168,28 +172,48 @@ static void init_match_cache(SyntaxHighlighting *sh) {
}
}

Stack *SyntaxHighlighting_HighlightString(SyntaxHighlighting *sh, const String *text, const Stack *open_blocks_at_begin) {
static bool stack_equal(const Stack *a, const Stack *b) {
if (a->size != b->size) {
return false;
}
for (size_t i=0; i<a->size; i++) {
if (a->items[i] != b->items[i]) {
return false;
}
}
return true;
}

const Stack *SyntaxHighlighting_HighlightString(SyntaxHighlighting *sh, const String *text, const Stack *open_blocks_at_begin) {
// check if there is already old infomation about text in the table
SyntaxHighlightingString *shs = Table_Get(sh->strings, text);
if (shs) {
// clear it if so
// early exit if nothing changed since the last calculation
if (open_blocks_at_begin && stack_equal(&shs->open_blocks_at_begin, open_blocks_at_begin)) {
return &shs->open_blocks_at_end;
}
// if open_blocks_at_begin changed clear the old information
SyntaxHighlightingString_Clear(shs);
}
else {
Comment thread
defname marked this conversation as resolved.
// otherwise create and store
// if there is no object present in sh->strings table create one and store it
shs = SyntaxHighlightingString_Create(text);
Table_Set(sh->strings, text, shs, (void(*)(void*))SyntaxHighlightingString_Destroy);
}

// create a working copy of the stack
Stack *open_blocks;
if (open_blocks_at_begin) {
open_blocks = Stack_Copy(open_blocks_at_begin);
Stack_CopyTo(&shs->open_blocks_at_begin, open_blocks_at_begin);
Stack_CopyTo(&shs->open_blocks_at_end, open_blocks_at_begin);
}
else {
open_blocks = Stack_Create();
Stack_Push(open_blocks, sh->def->root);
// or create a new one if open_blocks_at_begin is NULL
Stack_Clear(&shs->open_blocks_at_begin);
Stack_Push(&shs->open_blocks_at_begin, sh->def->root);
Stack_CopyTo(&shs->open_blocks_at_end, &shs->open_blocks_at_begin);
}
Stack *open_blocks = &shs->open_blocks_at_end;


// initialize the cache fields of the SyntaxBlockDefs
init_match_cache(sh);
Expand Down
10 changes: 7 additions & 3 deletions src/syntax/highlighting.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ typedef struct _SyntaxHighlightingString {
size_t tags_count; //< number of tags in `tags`
size_t tags_capacity; //< capacity of `tags`

Stack open_blocks_at_end; //< Stack of (SyntaxBlockDef*) elements that are open at the end of `text`
Stack open_blocks_at_begin; //< Stack of (SyntaxBlockDef*) elements that are open
Stack open_blocks_at_end; //< Stack of (SyntaxBlockDef*) elements that are open at the end of `text`
} SyntaxHighlightingString;

#define SHS_TAGS_INITIAL_CAPACITY 16
Expand Down Expand Up @@ -95,14 +96,17 @@ void SyntaxHighlighting_Deinit(SyntaxHighlighting *sh);
* @brief Highlight a string according to given context.
*
* Add a `SyntaxHighlightingString`to `hl->strings` or update an existing one.
* The table uses the pointer address of text as key, so make sure it does not change.
* open_blocks should only be NULL for the first line. In any other case if should be set to
* SyntaxHighlighlightingString->open_blocks_at_end of the previous line/text.
*
* @param hl The `SyntaxHighlighting` instance to use.
* @param text The text to hightlight.
* @param open_blocks An pointer to a `Stack` instance that holds the open blocks at the beginning of string. If NULL it's assumed that the root block is current.
*
Comment thread
defname marked this conversation as resolved.
* @returns
* A new created `Stack` containing all open blocks at the end of `text`.
* A reference to the `Stack` containing all open blocks at the end of `text`.
*/
Stack *SyntaxHighlighting_HighlightString(SyntaxHighlighting *sh, const String *text, const Stack *open_blocks);
const Stack *SyntaxHighlighting_HighlightString(SyntaxHighlighting *sh, const String *text, const Stack *open_blocks);

#endif
51 changes: 51 additions & 0 deletions src/syntax/textlayoutbindings.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "textlayoutbindings.h"

void SyntaxHighlightingBinding_Init(SyntaxHighlightingBinding *binding, const TextLayout *tl, SyntaxHighlighting *sh) {
binding->tl = tl;
binding->sh = sh;
}

void SyntaxHighlightingBinding_Deinit(SyntaxHighlightingBinding *binding) {
binding->tl = NULL;
binding->sh = NULL;
}

static void update_lines(SyntaxHighlightingBinding *binding, const Line *line, const Line *last_line, const Stack *open_blocks) {
const Stack *open_blocks_begin = open_blocks;
while (line) {
// open_blocks == NULL is also handled by the function
const Stack *open_blocks_end = SyntaxHighlighting_HighlightString(binding->sh, &line->text, open_blocks_begin);
open_blocks_begin = open_blocks_end;
if (line == last_line) {
break;
}
line = line->next;
}
}

void SyntaxHighlightingBinding_Update(SyntaxHighlightingBinding *binding, const Line *line, const Line *last_line) {
Line *prev_line = line->prev;
Stack *open_blocks = NULL;
if (prev_line) {
// check if highlighting for the previous line is already calculated
SyntaxHighlightingString *shs = Table_Get(binding->sh->strings, &prev_line->text);
if (shs) {
// use the open_blocks from the end of previous line
open_blocks = &shs->open_blocks_at_end;
}
else {
// highlighting for the line is not calculated so far
// so run this function for thr previous line
SyntaxHighlightingBinding_Update(binding, prev_line, last_line);
return;
}
}
if (line == binding->tl->tb->current_line) {
// this is super dirty cause the gap funcitonality is totally disabled this way!!!
// NEED A BETTER SOLUTION
TextBuffer_MergeGap((TextBuffer*)binding->tl->tb);
}

// update all lines until last_line (including)
update_lines(binding, line, last_line, open_blocks);
}
17 changes: 17 additions & 0 deletions src/syntax/textlayoutbindings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef SYNTAX_TEXTLAYOUTBINDINGS_H
#define SYNTAX_TEXTLAYOUTBINDINGS_H

#include "highlighting.h"
#include "document/textlayout.h"

typedef struct _SyntaxHighlightingBinding {
const TextLayout *tl;
SyntaxHighlighting *sh;
} SyntaxHighlightingBinding;

void SyntaxHighlightingBinding_Init(SyntaxHighlightingBinding *binding, const TextLayout *tl, SyntaxHighlighting *sh);
void SyntaxHighlightingBinding_Deinit(SyntaxHighlightingBinding *binding);

void SyntaxHighlightingBinding_Update(SyntaxHighlightingBinding *binding, const Line *line, const Line *last_line);

#endif
Loading