From 8896b84611d2c40a6e74d40604ec0c55e0065254 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 30 Sep 2025 05:32:16 +1000 Subject: [PATCH] add auto indenting --- dub.json | 2 +- src/editor/buffer.d | 144 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 121 insertions(+), 25 deletions(-) diff --git a/dub.json b/dub.json index ee30fc8..a908b41 100644 --- a/dub.json +++ b/dub.json @@ -16,7 +16,7 @@ "versions": [], "preGenerateCommands-linux": ["./build.sh"], "preGenerateCommands-windows": [], - "dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild", "-Jassets"], + "dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-link-debuglib"], "dflags-dmd": ["-P=-DSTBI_NO_SIMD"] }, ] diff --git a/src/editor/buffer.d b/src/editor/buffer.d index cf2387e..090e935 100644 --- a/src/editor/buffer.d +++ b/src/editor/buffer.d @@ -6,17 +6,23 @@ import std.math.algebraic : abs; struct FlatBuffer { - Tokenizer tk; - Arena arena; - u8[] data; - Arena ls_arena; - u64[] line_starts; - u64 length; - u64 lf_count; - i64 buf_pos; - i64 offset; - i64 rows; - bool dirty; + Tokenizer tk; + Arena arena; + u8[] data; + Arena ls_arena; + LineStart[] line_starts; + u64 length; + u64 lf_count; + i64 buf_pos; + i64 offset; + i64 rows; + bool dirty; +} + +struct LineStart +{ + u64 pos; + u16 level; } struct LineBuffers @@ -102,15 +108,51 @@ Fix(FlatBuffer* buffer) with(buffer) { Reset(&ls_arena); - line_starts = AllocArray!(u64)(&ls_arena, lf_count+1); - line_starts[0] = 0; + line_starts = AllocArray!(LineStart)(&ls_arena, lf_count+1); + line_starts[0].pos = 0; + u16 ignore, pending_level, level; u64 ls_idx = 1; for(u64 i = 0; i < length; i += 1) { + if(data[i] == '{' || data[i] == '(' || data[i] == '[') + { + if(pending_level > 0) + { + ignore += 1; + } + else + { + pending_level = 1; + } + } + + if(data[i] == '}' || data[i] == ')' || data[i] == ']') + { + if(ignore > 0) + { + ignore -= 1; + } + else if(pending_level == 1) + { + pending_level = 0; + } + else if(level > 0) + { + level -= 1; + } + } + if(data[i] == '\n') { - line_starts[ls_idx] = i+1; + level += pending_level; + pending_level = 0; + + line_starts[ls_idx].pos = i+1; + line_starts[ls_idx].level = level; + + Logf("line %s level %s", ls_idx, line_starts[ls_idx].level); + ls_idx += 1; } } @@ -149,6 +191,50 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos) } } + if(length == 1) + { + u8 new_ch; + switch(insert[0]) + { + case '[': new_ch = ']'; break; + case '(': new_ch = ')'; break; + case '{': new_ch = '}'; break; + case '\'', '"', '`', '\n': new_ch = insert[0]; break; + default: break; + } + + if(new_ch == '\n' && pos > 0) + { + u8 l = fb.data[pos-1]; + u8 r = fb.data[pos]; + bool expand = (l == '(' && r == ')') || (l == '{' && r == '}') || (l == '[' && r == ']'); + + u32 level = LevelFromPos(fb, pos) + u32(expand); + u64 limit = level + length; + for(; length < limit; length += 1, fb.buf_pos += 1) + { + insert[length] = '\t'; + } + + if(expand) + { + insert[length++] = '\n'; + fb.lf_count += 1; + + limit = level-1+length; + for(; length < limit; length += 1) + { + insert[length] = '\t'; + } + } + } + else if(new_ch > 0) + { + length += 1; + insert[1] = new_ch; + } + } + u64 temp_len = fb.length-pos; u8[] temp = AllocArray!(u8)(&fb.arena, temp_len); @@ -158,9 +244,12 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos) fb.data[pos .. pos+temp_len] = temp[0 .. temp_len]; fb.length += length; + Logf("out"); Fix(fb); + Logf("out"); + Reset(&fb.arena); AdjustOffset(fb); @@ -188,7 +277,7 @@ pragma(inline) u64 LinePos(FlatBuffer* fb, u64 pos) { u64 line = LineFromPos(fb, pos); - return pos - fb.line_starts[line]; + return pos - fb.line_starts[line].pos; } pragma(inline) U64Vec2 @@ -203,7 +292,7 @@ LineFromPos(FlatBuffer* fb, u64 pos) u64 line = 0; for(u64 i = 0; i < fb.line_starts.length; i += 1) { - if(fb.line_starts[i] > pos) + if(fb.line_starts[i].pos > pos) { break; } @@ -214,14 +303,21 @@ LineFromPos(FlatBuffer* fb, u64 pos) return line; } +pragma(inline) u16 +LevelFromPos(FlatBuffer* fb, u64 pos) +{ + u64 line = LineFromPos(fb, pos); + return fb.line_starts[line].level; +} + pragma(inline) u64 LineLength(FlatBuffer* fb, u64 line) { u64 len = 0; if(line < fb.line_starts.length) { - u64 start = fb.line_starts[line]; - u64 end = fb.line_starts.length-1 > line ? fb.line_starts[line+1] : fb.length; + u64 start = fb.line_starts[line].pos; + u64 end = fb.line_starts.length-1 > line ? fb.line_starts[line+1].pos : fb.length; len = end-start; } @@ -254,7 +350,7 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length) } else if(start_line == end_line) with(buffer) { - u64 start_of_line = line_starts[start_line]; + u64 start_of_line = line_starts[start_line].pos; u64 len = LineLength(buffer, start_line); linebufs.first.text = AllocArray!(u8)(&linebufs.arena, len); @@ -273,7 +369,7 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length) LineBuffer* current = first; for(u64 i = start_line; i < end_line; i += 1) { - u64 start = buffer.line_starts[i]; + u64 start = buffer.line_starts[i].pos; u64 len = LineLength(buffer, i); if(len > 0) @@ -317,9 +413,9 @@ MoveUp(FlatBuffer* fb, u64 col) u64 line = CurrentLine(fb); if(line > 0) { - u64 end = fb.line_starts[line]-1; + u64 end = fb.line_starts[line].pos-1; line -= 1; - fb.buf_pos = Min(fb.line_starts[line]+col, end); + fb.buf_pos = Min(fb.line_starts[line].pos+col, end); } } @@ -336,8 +432,8 @@ MoveDown(FlatBuffer* fb, u64 col) if(line+1 < fb.line_starts.length) { line += 1; - fb.buf_pos = fb.line_starts[line]; - u64 end = fb.line_starts.length > line+1 ? fb.line_starts[line+1]-1 : fb.length; + fb.buf_pos = fb.line_starts[line].pos; + u64 end = fb.line_starts.length > line+1 ? fb.line_starts[line+1].pos-1 : fb.length; fb.buf_pos = Min(fb.buf_pos+col, end); } }