From f383b45591ccd6aac6401515b67561011d570ca4 Mon Sep 17 00:00:00 2001 From: Phil Hagelberg Date: Mon, 4 May 2020 17:28:21 -0700 Subject: [PATCH] Implement naive matched-delimiter highlighting in code editor. This supports skipping nested delimiter pairs, but it does not support skipping over false-positive matched delimiters from strings and comments yet. --- src/code.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/code.h | 1 + 2 files changed, 49 insertions(+) diff --git a/src/code.c b/src/code.c index f7033bb41..7f0652dac 100644 --- a/src/code.c +++ b/src/code.c @@ -84,6 +84,13 @@ static void drawCursor(Code* code, s32 x, s32 y, char symbol) } } +static void drawMatchedDelim(Code* code, s32 x, s32 y, char symbol, u8 color) +{ + tic_api_rectb(code->tic, x-1, y-1, (getFontWidth(code))+1, TIC_FONT_HEIGHT+1, + getConfig()->theme.code.cursor); + drawChar(code->tic, symbol, x, y, color, code->altFont); +} + static void drawCode(Code* code, bool withCursor) { drawBookmarks(code); @@ -99,6 +106,7 @@ static void drawCode(Code* code, bool withCursor) MAX(code->cursor.selection, code->cursor.position)}; struct { s32 x; s32 y; char symbol; } cursor = {-1, -1, 0}; + struct { s32 x; s32 y; char symbol; u8 color; } matchedDelim = {-1, -1, 0, 0}; while(*pointer) { @@ -126,6 +134,12 @@ static void drawCode(Code* code, bool withCursor) if(code->cursor.position == pointer) cursor.x = x, cursor.y = y, cursor.symbol = symbol; + if(code->matchedDelim == pointer) + { + matchedDelim.x = x, matchedDelim.y = y, + matchedDelim.symbol = symbol, matchedDelim.color = *colorPointer; + } + if(symbol == '\n') { x = xStart; @@ -142,6 +156,11 @@ static void drawCode(Code* code, bool withCursor) if(withCursor && cursor.x >= 0 && cursor.y >= 0) drawCursor(code, cursor.x, cursor.y, cursor.symbol); + + if(matchedDelim.symbol) { + drawMatchedDelim(code, matchedDelim.x, matchedDelim.y, + matchedDelim.symbol, matchedDelim.color); + } } static void getCursorPosition(Code* code, s32* x, s32* y) @@ -185,11 +204,40 @@ static void removeInvalidChars(char* code) for(s = d = code; (*d = *s); d += (*s++ != '\r')); } +char* findMatchedDelim(const char* start, char* current) +{ + // TODO: return immediately if inside a string or comment + char initial = *current; + char seeking = 0; + s8 dir = (initial == '(' || initial == '[' || initial == '{') ? 1 : -1; + switch (initial) + { + case '(': seeking = ')'; break; + case ')': seeking = '('; break; + case '[': seeking = ']'; break; + case ']': seeking = '['; break; + case '{': seeking = '}'; break; + case '}': seeking = '{'; break; + default: return 0; + } + + while(*current && (start < current)) + { + current += dir; + if(*current == seeking) return current; + if(*current == initial) current = findMatchedDelim(start, current); + // TODO: if we enter a string, skip to the end + // TODO: if we enter a comment, skip to the end + } + return 0; +} + static void updateEditor(Code* code) { s32 column = 0; s32 line = 0; getCursorPosition(code, &column, &line); + code->matchedDelim = findMatchedDelim(code->src, code->cursor.position); const s32 BufferWidth = TIC80_WIDTH / getFontWidth(code); diff --git a/src/code.h b/src/code.h index 8230133e3..0ff50a470 100644 --- a/src/code.h +++ b/src/code.h @@ -98,6 +98,7 @@ struct Code s32 index; } outline; + char* matchedDelim; bool altFont; void(*tick)(Code*);