From b6a33e1c2e2ff06c59940707f24f55fb4c396cae Mon Sep 17 00:00:00 2001 From: s1yle <1373003655@qq.com> Date: Fri, 9 Jan 2026 15:56:58 +0800 Subject: [PATCH] fix: proper tab handling in lexer and font metrics --- src/free_glyph.c | 10 ++++++++++ src/lexer.c | 16 +++++++++++++++- src/lexer.h | 1 + src/main.c | 4 +--- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/free_glyph.c b/src/free_glyph.c index fe2b55b3..4cd3adda 100644 --- a/src/free_glyph.c +++ b/src/free_glyph.c @@ -73,6 +73,16 @@ void free_glyph_atlas_init(Free_Glyph_Atlas *atlas, FT_Face face) face->glyph->bitmap.buffer); x += face->glyph->bitmap.width; } + + // Set tab character metric as 4 times the space metric + Glyph_Metric space_metric = atlas->metrics[(size_t)' ']; + atlas->metrics[(size_t)'\t'].ax = space_metric.ax * 4; + atlas->metrics[(size_t)'\t'].ay = space_metric.ay; + atlas->metrics[(size_t)'\t'].bw = space_metric.bw; + atlas->metrics[(size_t)'\t'].bh = space_metric.bh; + atlas->metrics[(size_t)'\t'].bl = space_metric.bl; + atlas->metrics[(size_t)'\t'].bt = space_metric.bt; + atlas->metrics[(size_t)'\t'].tx = space_metric.tx; } float free_glyph_atlas_cursor_pos(const Free_Glyph_Atlas *atlas, const char *text, size_t text_size, Vec2f pos, size_t col) diff --git a/src/lexer.c b/src/lexer.c index cfd9022c..988c412e 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -102,6 +102,11 @@ void lexer_chop_char(Lexer *l, size_t len) l->line += 1; l->bol = l->cursor; l->x = 0; + } else if(x == '\t') { + if(l->atlas) { + Glyph_Metric space_metric = l->atlas->metrics[(size_t)' ']; + l->x += space_metric.ax * 4; + } } else { if (l->atlas) { size_t glyph_index = x; @@ -118,7 +123,9 @@ void lexer_chop_char(Lexer *l, size_t len) void lexer_trim_left(Lexer *l) { - while (l->cursor < l->content_len && isspace(l->content[l->cursor])) { + while (l->cursor < l->content_len && isspace(l->content[l->cursor]) + && l->content[l->cursor] != '\t' + ) { lexer_chop_char(l, 1); } } @@ -146,6 +153,13 @@ Token lexer_next(Lexer *l) if (l->cursor >= l->content_len) return token; + if (l->content[l->cursor] == '\t') { + token.kind = TOKEN_TAB; + token.text_len = 1; + lexer_chop_char(l, 1); + return token; + } + if (l->content[l->cursor] == '"') { // TODO: TOKEN_STRING should also handle escape sequences token.kind = TOKEN_STRING; diff --git a/src/lexer.h b/src/lexer.h index 6ee721ed..885c813c 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -8,6 +8,7 @@ typedef enum { TOKEN_END = 0, TOKEN_INVALID, + TOKEN_TAB, TOKEN_PREPROC, TOKEN_SYMBOL, TOKEN_OPEN_PAREN, diff --git a/src/main.c b/src/main.c index eac9ac5f..35120c14 100644 --- a/src/main.c +++ b/src/main.c @@ -328,9 +328,7 @@ int main(int argc, char **argv) // - tabs/spaces // - tab width // - etc. - for (size_t i = 0; i < 4; ++i) { - editor_insert_char(&editor, ' '); - } + editor_insert_char(&editor, '\t'); } break;