buffer fixes, indenting fix

This commit is contained in:
Matthew 2025-10-18 09:56:45 +11:00
parent ef360946cd
commit fffa58a286
4 changed files with 252 additions and 208 deletions

View File

@ -1,6 +1,7 @@
import dlib;
import core.stdc.stdio : EOF;
import parsing;
import parsing : SetBuffers;
import std.format : sformat;
import std.math.algebraic : abs;
import editor;
@ -10,14 +11,18 @@ struct FlatBuffer
Tokenizer tk;
Arena arena;
Arena ls_arena;
u8[] file_name;
u8[] data;
LineStart[] line_starts;
u64 length;
u64 lf_count;
i64 buf_pos;
i64 offset;
u8[] file_name;
u8[] _buf;
u8* pbuf;
u64 length;
LineStart[] lines;
u64 line_count;
i64 pos;
i64 line_offset;
i64 rows;
I64Vec2 sel;
@ -38,6 +43,8 @@ alias SM = SelectMode;
struct LineStart
{
u64 pos;
u64 length;
u32 line;
u16 level;
}
@ -100,51 +107,62 @@ const bool[128] SYM_TOKENS = [
';': true,
];
const u64 SPACING = 2;
const u64 BUF_START = 1;
FlatBuffer
CreateFlatBuffer(u8[] data)
CreateFlatBuffer(u8[] data, u8[] file_name)
{
u64 capacity = data.length > 0 ? RoundUp(cast(u64)(data.length) * 2, KB(4)) : KB(4);
u8[] buf = Alloc!(u8)(capacity);
buf[0 .. data.length] = data[0 .. data.length];
FlatBuffer fb = {
arena: CreateArena(MB(1)),
ls_arena: CreateArena(KB(512)),
data: buf,
length: cast(u64)data.length,
lf_count: CountLF(data),
sel: -1,
};
Init(&fb, data, file_name);
fb.tk = CreateTokenizer(&fb);
Fix(&fb);
return fb;
}
void
Change(FlatBuffer* fb, u8[] data)
Init(FlatBuffer* fb, u8[] data, u8[] file_name)
{
Free(fb.data);
u64 capacity = data.length > 0 ? RoundUp(cast(u64)(data.length)*2, KB(4)) : KB(4);
u64 cap = data.length > 0 ? RoundUp(cast(u64)(data.length) * 2, KB(4)) : KB(4);
u8[] buf = Alloc!(u8)(capacity);
fb.data = Alloc!(u8)(cap);
fb.data[0 .. data.length] = data[0 .. $];
fb.length = data.length;
fb.lf_count = CountLF(data);
fb.file_name = file_name;
fb.line_count = CountLF(data);
fb.sel = -1;
fb.sel_mode = SM.None;
ResetTokenizer(fb);
SetBuffers(fb, buf);
MemCpy(fb.pbuf, data.ptr, data.length);
}
void
SetBuffers(FlatBuffer* fb, u8[] data)
{
fb._buf = data;
fb.pbuf = fb._buf.ptr+BUF_START;
}
void
Change(FlatBuffer* fb, u8[] data, u8[] file_name)
{
Free(fb._buf);
Init(fb, data, file_name);
ResetTokenizer(&fb.tk, fb._buf.length);
Fix(fb);
}
u64
CountLF(u8[] data)
{
u64 lf_count = 0;
u64 lf_count = 1;
for(u64 i = 0; i < data.length; i += 1)
{
lf_count += u64(data.ptr[i] == '\n');
@ -153,20 +171,42 @@ CountLF(u8[] data)
return lf_count;
}
pragma(inline) bool
ScanLineRightBrace(u8* pbuf, u64 start, u64 len)
{
bool result;
for(u64 i = start; i < len; i += 1)
{
if(pbuf[i] == '\t' || pbuf[i] == ' ') continue;
if(pbuf[i] == '}' || pbuf[i] == ']' || pbuf[i] == ')')
{
result = true;
break;
}
break;
}
return result;
}
void
Fix(FlatBuffer* fb)
{
with(fb)
{
Reset(&ls_arena);
line_starts = Alloc!(LineStart)(&ls_arena, lf_count+1);
line_starts[0].pos = 0;
u16 ignore, pending_level, level;
u64 ls_idx = 1;
lines = Alloc!(LineStart)(&ls_arena, line_count);
lines[0].pos = 0;
LineStart* prev = null;
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(pbuf[i] == '{' || pbuf[i] == '(' || pbuf[i] == '[')
{
if(pending_level > 0)
{
@ -178,7 +218,7 @@ Fix(FlatBuffer* fb)
}
}
if(data[i] == '}' || data[i] == ')' || data[i] == ']')
else if(pbuf[i] == '}' || pbuf[i] == ')' || pbuf[i] == ']')
{
if(ignore > 0)
{
@ -190,22 +230,35 @@ Fix(FlatBuffer* fb)
}
else if(level > 0)
{
if(prev)
{
prev.level = cast(u16)Max(prev.level-u16(1), 0);
}
level -= 1;
}
}
if(data[i] == '\n')
if(pbuf[i] == '\n')
{
level += pending_level;
pending_level = 0;
line_starts[ls_idx].pos = i+1;
line_starts[ls_idx].level = level;
lines[ls_idx].pos = i+1;
lines[ls_idx].level = level;
prev = &lines[ls_idx];
ls_idx += 1;
}
}
for(u64 i = 0; i < line_count-1; i += 1)
{
lines[i].length = lines[i+1].pos - lines[i+0].pos;
}
lines[line_count-1].length = length - lines[line_count-1].pos;
dirty = false;
TokenizeD(fb);
@ -215,25 +268,23 @@ Fix(FlatBuffer* fb)
LineBuffers
CreateLineBuffers(u64 arena_size)
{
return LineBuffers(
arena: CreateArena(arena_size),
);
return LineBuffers(arena: CreateArena(arena_size));
}
void
Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
{
if(fb.length + length > fb.data.length)
if(fb.length + length > fb._buf.length-SPACING)
{
fb.tk.buffer = Realloc!(TokenStyle)(fb.tk.buffer, fb.data.length*2);
fb.data = Realloc!(u8)(fb.data, fb.data.length*2);
SetBuffers(&fb.tk, Realloc(fb.tk._tokens, fb._buf.length*2));
SetBuffers(fb, Realloc(fb._buf, fb._buf.length*2));
}
u64 prev_lf = fb.lf_count;
u64 new_lines;
for(u64 i = 0; i < length; i += 1)
{
fb.buf_pos += 1;
fb.lf_count += u64(insert.ptr[i] == '\n');
fb.pos += 1;
new_lines += u64(insert.ptr[i] == '\n');
}
if(length == 1)
@ -250,14 +301,13 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
if(new_ch == '\n' && pos > 0)
{
Logf("yeah");
u8 l = fb.data[pos-1];
u8 r = fb.data[pos];
u8 l = fb.pbuf[pos-1];
u8 r = fb.pbuf[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)
for(; length < limit; length += 1, fb.pos += 1)
{
insert[length] = '\t';
}
@ -265,7 +315,7 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
if(expand)
{
insert[length++] = '\n';
fb.lf_count += 1;
new_lines += 1;
limit = level-1+length;
for(; length < limit; length += 1)
@ -276,21 +326,23 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
}
else if(new_ch != '\n' && new_ch > 0)
{
length += 1;
length += 1;
insert[1] = new_ch;
}
}
u64 temp_len = fb.length-pos;
u8[] temp = Alloc!(u8)(&fb.arena, fb.data, pos, temp_len);
u8[] temp = Alloc!(u8)(&fb.arena, fb.pbuf[pos .. pos+temp_len]);
fb.data[pos .. pos+length] = insert[0 .. length];
fb.pbuf[pos .. pos+length] = insert[0 .. length];
pos += length;
fb.data[pos .. pos+temp_len] = temp[0 .. temp_len];
fb.pbuf[pos .. pos+temp_len] = temp[0 .. temp_len];
fb.length += length;
fb.line_count += new_lines;
Fix(fb);
Reset(&fb.arena);
@ -318,7 +370,7 @@ StartSelection(FlatBuffer* fb, SelectMode mode)
if(mode == SM.Normal)
{
fb.sel = fb.buf_pos;
fb.sel = fb.pos;
}
else if(mode == SM.Line)
{
@ -336,26 +388,26 @@ EndSelection(FlatBuffer* fb)
void
Insert(FlatBuffer* fb, u8[] insert, u64 length)
{
Insert(fb, insert, length, fb.buf_pos);
Insert(fb, insert, length, fb.pos);
}
pragma(inline) u64
CurrentLine(FlatBuffer* fb)
{
return LineFromPos(fb, fb.buf_pos);
return LineFromPos(fb, fb.pos);
}
pragma(inline) u64
CurrentCol(FlatBuffer* fb)
{
return LinePos(fb, fb.buf_pos);
return LinePos(fb, fb.pos);
}
pragma(inline) u64
LinePos(FlatBuffer* fb, u64 pos)
{
u64 line = LineFromPos(fb, pos);
return pos - fb.line_starts[line].pos;
return pos - fb.lines[line].pos;
}
pragma(inline) U64Vec2
@ -368,9 +420,9 @@ pragma(inline) u64
LineFromPos(FlatBuffer* fb, u64 pos)
{
u64 line = 0;
for(u64 i = 0; i < fb.line_starts.length; i += 1)
for(u64 i = 0; i < fb.line_count; i += 1)
{
if(fb.line_starts[i].pos > pos)
if(fb.lines[i].pos > pos)
{
break;
}
@ -385,37 +437,32 @@ pragma(inline) u16
LevelFromPos(FlatBuffer* fb, u64 pos)
{
u64 line = LineFromPos(fb, pos);
return fb.line_starts[line].level;
return fb.lines[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].pos;
u64 end = fb.line_starts.length-1 > line ? fb.line_starts[line+1].pos : fb.length;
len = end-start;
}
return len;
return fb.lines[line].length;
}
void
GetLines(FlatBuffer* fb, LineBuffers* linebufs, u64 length)
{
fb.rows = length;
GetLines(fb, linebufs, fb.offset, length);
GetLines(fb, linebufs, fb.line_offset, length);
}
pragma(inline) void
SliceLineBuffer(FlatBuffer* fb, LineBuffers* lbufs, LineBuffer* lbuf, u64 start, u64 len)
SliceLineBuffer(FlatBuffer* fb, LineBuffers* lbufs, LineStart* ls)
{
lbuf.text = fb.data[start .. start+len];
lbuf.style = fb.tk.buffer[start .. start+len];
LineBuffer* lbuf = Alloc!(LineBuffer)(&lbufs.arena);
lbuf.text = fb.pbuf[ls.pos .. ls.pos+ls.length];
lbuf.style = fb.tk.ptokens[ls.pos .. ls.pos+ls.length];
lbufs.count += 1;
SLLPush(lbufs, lbuf, null);
}
void
@ -424,45 +471,26 @@ GetLines(FlatBuffer* fb, LineBuffers* linebufs, u64 start_line, u64 length)
assert(linebufs != null, "GetLines failure: linebufs is null");
Reset(&linebufs.arena);
linebufs.first = Alloc!(LineBuffer)(&linebufs.arena);
linebufs.first = linebufs.last = null;
linebufs.count = 0;
u64 total_lines = fb.line_starts.length;
u64 total_lines = fb.lines.length;
linebufs.start = Min(start_line, total_lines);
linebufs.end = Min(start_line + length, total_lines);
if(fb.length == 0)
{
linebufs.first.text = Alloc!(u8)(&linebufs.arena, 1);
linebufs.first.style = Alloc!(TS)(&linebufs.arena, 1);
SliceLineBuffer(fb, linebufs, &fb.lines[0]);
}
else if(linebufs.start == linebufs.end) with(fb)
{
SliceLineBuffer(fb, linebufs, linebufs.first, line_starts[linebufs.start].pos, LineLength(fb, linebufs.start));
SliceLineBuffer(fb, linebufs, &lines[linebufs.start]);
}
else with(linebufs)
{
LineBuffer* current = first;
for(u64 i = start; i < end; i += 1)
{
u64 start_pos = fb.line_starts[i].pos;
u64 len = LineLength(fb, i);
if(len > 0)
{
SliceLineBuffer(fb, linebufs, current, start_pos, len);
current.next = Alloc!(LineBuffer)(&arena);
current = current.next;
}
if(i == fb.lf_count && fb.data[fb.length-1] == '\n')
{
current.text = Alloc!(u8)(&arena, 1);
current.style = Alloc!(TS)(&arena, 1);
count += 1;
current.next = Alloc!(LineBuffer)(&arena);
}
SliceLineBuffer(fb, linebufs, &fb.lines[i]);
}
}
}
@ -470,13 +498,13 @@ GetLines(FlatBuffer* fb, LineBuffers* linebufs, u64 start_line, u64 length)
void
MoveToEOL(FlatBuffer* fb)
{
if(fb.data[fb.buf_pos] != '\n')
if(fb.pbuf[fb.pos] != '\n')
{
for(u64 i = 0; i < fb.line_starts.length; i += 1)
for(u64 i = 0; i < fb.lines.length; i += 1)
{
if(fb.buf_pos < fb.line_starts[i].pos)
if(fb.pos < fb.lines[i].pos)
{
fb.buf_pos = 0 < i ? fb.line_starts[i].pos-1 : fb.length;
fb.pos = 0 < i ? fb.lines[i].pos-1 : fb.length;
break;
}
}
@ -486,13 +514,13 @@ MoveToEOL(FlatBuffer* fb)
void
MoveToSOL(FlatBuffer* fb)
{
if(fb.buf_pos != 0 && fb.data[fb.buf_pos-1] != '\n')
if(fb.pos != 0 && fb.pbuf[fb.pos-1] != '\n')
{
for(u64 i = 0; i < fb.line_starts.length; i += 1)
for(u64 i = 0; i < fb.lines.length; i += 1)
{
if(fb.buf_pos < fb.line_starts[i].pos)
if(fb.pos < fb.lines[i].pos)
{
fb.buf_pos = i > 0 ? fb.line_starts[i-1].pos : 0;
fb.pos = i > 0 ? fb.lines[i-1].pos : 0;
break;
}
}
@ -502,7 +530,7 @@ MoveToSOL(FlatBuffer* fb)
void
MoveUp(FlatBuffer* fb)
{
MoveUp(fb, LinePos(fb, fb.buf_pos));
MoveUp(fb, LinePos(fb, fb.pos));
}
void
@ -511,28 +539,28 @@ MoveUp(FlatBuffer* fb, u64 col)
u64 line = CurrentLine(fb);
if(line > 0)
{
u64 end = fb.line_starts[line].pos-1;
u64 end = fb.lines[line].pos-1;
line -= 1;
fb.buf_pos = Min(fb.line_starts[line].pos+col, end);
fb.pos = Min(fb.lines[line].pos+col, end);
}
}
void
MoveDown(FlatBuffer* fb)
{
MoveDown(fb, LinePos(fb, fb.buf_pos));
MoveDown(fb, LinePos(fb, fb.pos));
}
void
MoveDown(FlatBuffer* fb, u64 col)
{
u64 line = CurrentLine(fb);
if(line+1 < fb.line_starts.length)
if(line+1 < fb.lines.length)
{
line += 1;
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);
fb.pos = fb.lines[line].pos;
u64 end = fb.lines.length > line+1 ? fb.lines[line+1].pos-1 : fb.length;
fb.pos = Min(fb.pos+col, end);
}
}
@ -544,33 +572,33 @@ MoveToEmptyLine(bool up)(FlatBuffer* fb)
u64 step = up ? -1 : 1;
u8 ch = 0;
if((fb.buf_pos != 0 && up) || (fb.buf_pos != fb.length && !up))
if((fb.pos != 0 && up) || (fb.pos != fb.length && !up))
{
for(u64 i = fb.buf_pos + step; true; i += step)
for(u64 i = fb.pos + step; true; i += step)
{
static if(!up)
{
if(i == fb.length-1)
{
fb.buf_pos = fb.length;
fb.pos = fb.length;
break;
}
ch = fb.data[i];
ch = fb.pbuf[i];
}
static if(up)
{
if(i == 0)
{
fb.buf_pos = 0;
fb.pos = 0;
break;
}
ch = fb.data[i-1];
ch = fb.pbuf[i-1];
}
if(started && !CheckWhiteSpace(fb.data[i]))
if(started && !CheckWhiteSpace(fb.pbuf[i]))
{
started = false;
}
@ -584,7 +612,7 @@ MoveToEmptyLine(bool up)(FlatBuffer* fb)
if(started && ch == '\n')
{
fb.buf_pos = i;
fb.pos = i;
MoveToSOL(fb);
break;
}
@ -651,52 +679,52 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
{
u64 step = forward ? 1 : -1;
if((forward && fb.buf_pos < fb.length-1) || (!forward && fb.buf_pos > 0))
if((forward && fb.pos < fb.length-1) || (!forward && fb.pos > 0))
{
ChType type = GetChType(fb.data[fb.buf_pos]);
if(type != GetChType(fb.data[fb.buf_pos+step]))
ChType type = GetChType(fb.pbuf[fb.pos]);
if(type != GetChType(fb.pbuf[fb.pos+step]))
{
fb.buf_pos += step;
fb.pos += step;
}
else for(u64 i = fb.buf_pos+step; true; i += step)
else for(u64 i = fb.pos+step; true; i += step)
{
static if(forward)
{
u8 next = i < fb.length-1 ? fb.data[i+1] : 0;
u8 next = i < fb.length-1 ? fb.pbuf[i+1] : 0;
}
else
{
u8 next = i > 1 ? fb.data[i-1] : 0;
u8 next = i > 1 ? fb.pbuf[i-1] : 0;
}
static if(forward) if(i == fb.length-2)
{
fb.buf_pos = i;
fb.buf_pos += u64(GetChType(next) == type);
fb.pos = i;
fb.pos += u64(GetChType(next) == type);
break;
}
static if(!forward) if(i == 1)
{
fb.buf_pos = i;
fb.buf_pos += GetChType(next) == type ? -1 : 0;
fb.pos = i;
fb.pos += GetChType(next) == type ? -1 : 0;
break;
}
if(CheckChMatch(next, type))
{
fb.buf_pos = i;
fb.pos = i;
break;
}
}
while(CheckWhiteSpace(fb.data[fb.buf_pos]))
while(CheckWhiteSpace(fb.pbuf[fb.pos]))
{
bool exit = forward ? fb.buf_pos == fb.length-1 : fb.buf_pos == 0;
bool exit = forward ? fb.pos == fb.length-1 : fb.pos == 0;
if(exit) break;
fb.buf_pos += step;
fb.pos += step;
}
}
}
@ -704,25 +732,25 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
void
MoveToNextWord(bool forward)(FlatBuffer* fb)
{
ChType type = GetChType(fb.data[fb.buf_pos]);
ChType type = GetChType(fb.pbuf[fb.pos]);
bool hit_ws;
u64 step = forward ? 1 : -1;
for(u64 i = fb.buf_pos; true; i += step) with(ChType)
for(u64 i = fb.pos; true; i += step) with(ChType)
{
static if(forward) if(i == fb.length-1)
{
fb.buf_pos = i;
fb.pos = i;
break;
}
static if(!forward) if(i == 0)
{
fb.buf_pos = i;
fb.pos = i;
break;
}
u8 ch = fb.data[i];
u8 ch = fb.pbuf[i];
if(CheckWhiteSpace(ch))
{
@ -732,19 +760,19 @@ MoveToNextWord(bool forward)(FlatBuffer* fb)
if(hit_ws)
{
fb.buf_pos = i;
fb.pos = i;
break;
}
if(CheckChMatch(ch, type))
{
fb.buf_pos = i;
fb.pos = i;
break;
}
}
assert(fb.buf_pos >= 0 && fb.buf_pos <= fb.length);
assert(fb.pos >= 0 && fb.pos <= fb.length);
}
bool
@ -766,20 +794,20 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} break;
case Left:
{
if(fb.buf_pos > 0)
if(fb.pos > 0)
{
MoveToWordEdge!(false)(fb);
}
} break;
case Right:
{
if(fb.buf_pos < fb.length)
if(fb.pos < fb.length)
{
MoveToWordEdge!(true)(fb);
}
} break;
case Home: fb.buf_pos = 0; taken = true; break;
case End: fb.buf_pos = fb.length; taken = true; break;
case Home: fb.pos = 0; taken = true; break;
case End: fb.pos = fb.length; taken = true; break;
default: break;
}
}
@ -795,14 +823,14 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} break;
case Left:
{
if(fb.buf_pos > 0)
if(fb.pos > 0)
{
MoveToNextWord!(false)(fb);
}
} break;
case Right:
{
if(fb.buf_pos < fb.length)
if(fb.pos < fb.length)
{
MoveToNextWord!(true)(fb);
}
@ -826,17 +854,17 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} break;
case Left:
{
if(fb.buf_pos > 0 && fb.data[fb.buf_pos-1] != '\n')
if(fb.pos > 0 && fb.pbuf[fb.pos-1] != '\n')
{
fb.buf_pos -= 1;
fb.pos -= 1;
taken = true;
}
} break;
case Right:
{
if(fb.buf_pos < fb.length && fb.data[fb.buf_pos] != '\n')
if(fb.pos < fb.length && fb.pbuf[fb.pos] != '\n')
{
fb.buf_pos += 1;
fb.pos += 1;
taken = true;
}
} break;
@ -859,7 +887,7 @@ UpdateSelection(FlatBuffer* fb)
{
if(fb.sel_mode == SM.Normal)
{
fb.sel.y = fb.buf_pos;
fb.sel.y = fb.pos;
}
if(fb.sel_mode == SM.Line)
@ -873,32 +901,32 @@ UpdateOffset(FlatBuffer* fb)
{
if(fb.rows > 0) with(fb)
{
i64 screen_pos = CurrentLine(fb) - offset;
i64 screen_pos = CurrentLine(fb) - line_offset;
i64 start = 0;
i64 end = rows-2;
Logf("p %s start %s end %s", screen_pos, start, end);
if(offset > 0 && screen_pos < start)
if(line_offset > 0 && screen_pos < start)
{
offset += screen_pos;
Logf("scroll up %s", offset);
line_offset += screen_pos;
Logf("scroll up %s", line_offset);
}
else if(screen_pos > end)
{
offset += screen_pos - end;
Logf("scroll down %s", offset);
line_offset += screen_pos - end;
Logf("scroll down %s", line_offset);
}
}
assert(fb.offset <= fb.lf_count);
assert(fb.line_offset <= fb.line_count);
}
void
Backspace(FlatBuffer* fb)
{
if(fb.buf_pos-1 >= 0)
if(fb.pos-1 >= 0)
{
fb.buf_pos -= 1;
Delete(fb, 1, fb.buf_pos);
fb.pos -= 1;
Delete(fb, 1, fb.pos);
}
}
@ -910,9 +938,9 @@ Delete(FlatBuffer* fb, u64 length, u64 pos)
for(u64 i = pos; i < fb.length && i < pos+length; i += 1)
{
if(fb.data[i] == '\n')
if(fb.pbuf[i] == '\n')
{
fb.lf_count -= 1;
fb.line_count -= 1;
}
}
@ -920,8 +948,8 @@ Delete(FlatBuffer* fb, u64 length, u64 pos)
if(end != fb.length)
{
temp = Alloc!(u8)(&fb.arena, fb.length-end);
temp[0 .. temp.length] = fb.data[end .. fb.length];
fb.data[pos .. pos+temp.length] = temp[0 .. temp.length];
temp[0 .. temp.length] = fb.pbuf[end .. fb.length];
fb.pbuf[pos .. pos+temp.length] = temp[0 .. temp.length];
}
fb.length -= length;

View File

@ -319,7 +319,7 @@ SaveFile(Editor* ed, u8[] file_name)
u64 tab_count;
for(u64 i = 0; i < ed.buf.length; i += 1)
{
if(ed.buf.data[i] == '\t')
if(ed.buf.pbuf[i] == '\t')
{
tab_count += 1;
}
@ -332,7 +332,7 @@ SaveFile(Editor* ed, u8[] file_name)
u64 buf_pos;
for(u64 i = 0; i < ed.buf.length; i += 1)
{
if(ed.buf.data[i] == '\t')
if(ed.buf.pbuf[i] == '\t')
{
for(u64 j = 0; j < tab_width; j += 1)
{
@ -341,7 +341,7 @@ SaveFile(Editor* ed, u8[] file_name)
}
else
{
temp_buf[buf_pos++] = ed.buf.data[i];
temp_buf[buf_pos++] = ed.buf.pbuf[i];
}
}
@ -373,7 +373,7 @@ OpenFile(Editor* ed, u8[] file_name)
{
u8[] buf = ScratchAlloc!(u8)(len);
fread(buf.ptr, u8.sizeof, len, f);
Change(&ed.buf, buf);
Change(&ed.buf, buf, file_name);
ed.buf.file_name = file_name;
}
@ -394,7 +394,7 @@ CreateEditor(EditorCtx* ctx)
Editor* ed = Alloc!(Editor)(&ctx.arena);
ed.arena = CreateArena(MB(4));
ed.buf = CreateFlatBuffer([]);
ed.buf = CreateFlatBuffer([], []);
ed.linebufs = CreateLineBuffers(MB(1));
return ed;

View File

@ -389,7 +389,8 @@ struct Token
struct Tokenizer
{
Arena arena;
TokenStyle[] buffer;
TokenStyle[] _tokens;
TokenStyle* ptokens;
u64 tk_count;
u64 pos;
Token* first;
@ -402,14 +403,22 @@ Nil(Token* tk)
return tk == g_NIL_TOKEN || tk == null;
}
void
SetBuffers(Tokenizer* tk, TokenStyle[] tokens)
{
tk._tokens = tokens;
tk.ptokens = tokens.ptr+BUF_START;
}
Tokenizer
CreateTokenizer(FlatBuffer* fb)
{
Tokenizer tk = {
arena: CreateArena(MB(4)),
buffer: Alloc!(TS)(fb.data.length),
};
SetBuffers(&tk, Alloc!(TS)(fb._buf.length));
g_NIL_TOKEN = cast(Token*)&g_nil_tk;
tk.first = tk.last = g_NIL_TOKEN;
@ -433,14 +442,14 @@ CreateTokenizer(FlatBuffer* fb)
}
void
ResetTokenizer(FlatBuffer* fb)
ResetTokenizer(Tokenizer* tk, u64 len)
{
Reset(&fb.tk.arena);
Free(fb.tk.buffer);
Reset(&tk.arena);
Free(tk._tokens);
fb.tk.buffer = Alloc!(TS)(fb.data.length);
fb.tk.pos = 0;
fb.tk.first = fb.tk.last = g_NIL_TOKEN;
SetBuffers(tk, Alloc!(TS)(len));
tk.pos = 0;
tk.first = tk.last = g_NIL_TOKEN;
}
Token*
@ -460,7 +469,7 @@ MakeToken(Tokenizer* tk, TokenType type, u64 start, u64 end)
u8
Peek(FlatBuffer* fb)
{
return fb.tk.pos+1 < fb.length ? fb.data[fb.tk.pos+1] : 0;
return fb.tk.pos+1 < fb.length ? fb.pbuf[fb.tk.pos+1] : 0;
}
void
@ -474,7 +483,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length;)
{
u8 ch = fb.data[tk.pos];
u8 ch = fb.pbuf[tk.pos];
bool alpha = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
if(ch == ' ' || ch == '\t')
@ -483,7 +492,7 @@ TokenizeD(FlatBuffer* fb)
for(tk.pos += 1; tk.pos < fb.length; tk.pos += 1)
{
if(fb.data[tk.pos] != ' ' && fb.data[tk.pos] != '\t')
if(fb.pbuf[tk.pos] != ' ' && fb.pbuf[tk.pos] != '\t')
{
break;
}
@ -568,7 +577,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
u8 c = fb.data[tk.pos];
u8 c = fb.pbuf[tk.pos];
if(CheckWhiteSpace(c)) break;
if(!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) break;
@ -582,7 +591,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(fb.data[tk.pos] != '.') break;
if(fb.pbuf[tk.pos] != '.') break;
}
t.end = tk.pos;
@ -593,7 +602,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckWhiteSpace(fb.data[tk.pos])) break;
if(CheckWhiteSpace(fb.pbuf[tk.pos])) break;
}
t.end = tk.pos;
@ -610,7 +619,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckEOL(fb.data[tk.pos]))
if(CheckEOL(fb.pbuf[tk.pos]))
{
break;
}
@ -625,7 +634,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(fb.data[tk.pos] == '/' && fb.data[tk.pos-1] == '*')
if(fb.pbuf[tk.pos] == '/' && fb.pbuf[tk.pos-1] == '*')
{
break;
}
@ -646,7 +655,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckWhiteSpace(fb.data[tk.pos]))
if(CheckWhiteSpace(fb.pbuf[tk.pos]))
{
break;
}
@ -707,7 +716,7 @@ TokenizeD(FlatBuffer* fb)
for(auto token = tk.first; !Nil(token); token = token.next)
{
tk.buffer[token.start .. token.end] = TOKEN_STYLES[token.type];
tk.ptokens[token.start .. token.end] = TOKEN_STYLES[token.type];
}
}
@ -817,7 +826,7 @@ CheckFuncOrTemplateSig(FlatBuffer* fb, Token* token)
u8[]
TokenStr(FlatBuffer* fb, Token* t)
{
return fb.data[t.start .. t.end];
return fb.pbuf[t.start .. t.end];
}
Token*
@ -902,7 +911,7 @@ ParseNum(FlatBuffer* fb)
{
tk.pos += 1;
u8 ch = fb.data[tk.pos];
u8 ch = fb.pbuf[tk.pos];
if(ch != '_' && ch != '.' && !(ch >= '0' && ch <= '9') && ch != 'x' && ch != 'X' && !((ch == '-' || ch == '+') && first))
{
@ -914,7 +923,7 @@ ParseNum(FlatBuffer* fb)
while (tk.pos < fb.length)
{
u8 ch = fb.data[tk.pos];
u8 ch = fb.pbuf[tk.pos];
if(ch != 'l' && ch != 'u' && ch != 'U' && ch != 'L' && ch != 'f' && ch != 'F')
{
break;
@ -943,9 +952,9 @@ ParseStr(u8 str_ch)(FlatBuffer* fb)
static if(str_ch == '`') tk.pos += 1;
bool ignore = str_ch != '`';
for(; (fb.data[tk.pos] != str_ch || ignore) && tk.pos < fb.length; tk.pos += 1)
for(; (fb.pbuf[tk.pos] != str_ch || ignore) && tk.pos < fb.length; tk.pos += 1)
{
static if(str_ch != '`') ignore = fb.data[tk.pos] == '\\';
static if(str_ch != '`') ignore = fb.pbuf[tk.pos] == '\\';
}
tk.pos += 1;
@ -962,7 +971,7 @@ ParseId(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
u8 ch = fb.data[tk.pos];
u8 ch = fb.pbuf[tk.pos];
if(!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && ch != '.' && ch != '_' && !(ch >= '0' && ch <= '9'))
{
@ -971,11 +980,11 @@ ParseId(FlatBuffer* fb)
}
}
u8 ch = fb.data[t.start];
u8 ch = fb.pbuf[t.start];
if(ch < D_KEYWORDS.length && D_KEYWORDS[ch] != null && D_KEYWORDS[ch].length > 0)
{
bool found = false;
u8[] id = fb.data[t.start .. t.end];
u8[] id = fb.pbuf[t.start .. t.end];
foreach(ref k; D_TYPES[ch])
{
@ -1023,7 +1032,7 @@ FixOpAssign(FlatBuffer* fb, Token* t)
{
if(t.end+1 < fb.length)
{
u8[] str = fb.data[t.start .. t.end+1];
u8[] str = fb.pbuf[t.start .. t.end+1];
if(
str == "/=" ||
str == "+=" ||
@ -1066,7 +1075,7 @@ SkipWhiteSpace(FlatBuffer* fb)
{
while (fb.tk.pos < fb.length)
{
u8 ch = fb.data[fb.tk.pos];
u8 ch = fb.pbuf[fb.tk.pos];
bool white_space = CheckWhiteSpace(ch);

View File

@ -465,11 +465,18 @@ Panel(UIPanel* panel)
u64 ch_offset;
auto parts = MakeMultiline(buf.text, code_view_width, buf.style);
for(auto n = parts; n != null; n = n.next)
if(parts == null)
{
if(pos.y == ed.buf.line_offset+i)
{
DrawCursor(atlas, [], 0, x+lcw+padding*2.0, y, ch_offset, edit);
}
}
else for(auto n = parts; n != null; n = n.next)
{
auto l = &n.value;
if(pos.y == ed.buf.offset+i)
if(pos.y == ed.buf.line_offset+i)
{
DrawCursor(atlas, l.text, pos.x, x+lcw+padding*2.0, y, ch_offset, edit);
}
@ -511,7 +518,7 @@ pragma(inline) void
DrawLineCount(FontAtlas* atlas, char[] fmt, f32* x_pos, f32 y, u64 line)
{
char[32] line_buf = '\0';
char[] line_str = sformat(line_buf, fmt, line);
char[] line_str = sformat(line_buf, fmt, line+1);
foreach(j; 0 .. line_str.length)
{
@ -940,7 +947,7 @@ MakeMultiline(u8[] text, f32 width, TS[] style = [])
if(ch_w + w > scaled_width || i == text.length-1)
{
u64 len = i-start;
u64 len = i-start+1;
u8[] str = ScratchAlloc!(u8)(text, start, len);