Text editor: Remove prototype. Update README
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Compiler front-end in a single-header-file C library
|
# Compiler front-end in a single-header-file C library
|
||||||
|
|
||||||
I have no illusions here, this is not the next big language. What I propose is very simple - a return to C. Not to the language as it was, but a return to the ideal of 'C'. A return to something in it - that is more then it. A small language supplemented with modern ideas - distributed as a dependency free, easy to use single-header-file library.
|
For a very simple statically typed language. I mostly designed it for personal use, it's small but complete - you can actually program in it and so on. It compiles to C with all the debug info so debuggers work. Currently I find that it's pretty good for metaprogramming and code generation, particularly when you have a workflow "metaprogram -> program". The library provides functions for traversing, printing the AST and other niceties:
|
||||||
|
|
||||||
- **User has full control over compilation!**
|
- **User has full control over compilation!**
|
||||||
- **No dependencies, permissive license, single file that compile both in C and C++!**
|
- **No dependencies, permissive license, single file that compile both in C and C++!**
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ if not exist build\bld.exe (
|
|||||||
)
|
)
|
||||||
|
|
||||||
rem ubuntu run ./build.sh
|
rem ubuntu run ./build.sh
|
||||||
build\bld.exe --tests text_editor
|
build\bld.exe
|
||||||
|
|||||||
@@ -36,3 +36,8 @@ ClampFloat :: proc(val: float, min: float, max: float): float {
|
|||||||
if (val < min) return min;
|
if (val < min) return min;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsFlagSet :: proc(flags: u64, f: u64): bool {
|
||||||
|
result := flags & f;
|
||||||
|
return :bool(result);
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ main :: proc(): int {
|
|||||||
|
|
||||||
SANDBOX_TEXT_EDITOR :: 1;
|
SANDBOX_TEXT_EDITOR :: 1;
|
||||||
SANDBOX_PROTOTYPE :: 2;
|
SANDBOX_PROTOTYPE :: 2;
|
||||||
sandbox_chosen := SANDBOX_PROTOTYPE;
|
sandbox_chosen := SANDBOX_TEXT_EDITOR;
|
||||||
|
|
||||||
for !WindowShouldClose() {
|
for !WindowShouldClose() {
|
||||||
screen_size: Vector2 = {:f32(GetScreenWidth()), :f32(GetScreenHeight())};
|
screen_size: Vector2 = {:f32(GetScreenWidth()), :f32(GetScreenHeight())};
|
||||||
|
|||||||
@@ -1,58 +1,3 @@
|
|||||||
Inited: bool;
|
|
||||||
Perm: MA_Arena;
|
|
||||||
Transcripts: TranscriptStack;
|
|
||||||
|
|
||||||
SearchBar: TE.Buffer;
|
|
||||||
FilenamesBuffer: TE.Buffer;
|
|
||||||
ResultsBuffer: TE.Buffer;
|
|
||||||
|
|
||||||
UpdatePrototype :: proc(rect: Rect2P, font: Font, font_size: float, font_spacing: float) {
|
UpdatePrototype :: proc(rect: Rect2P, font: Font, font_size: float, font_spacing: float) {
|
||||||
if !Inited {
|
|
||||||
Inited = true;
|
|
||||||
for iter := OS_IterateFiles(&Perm, S8("C:/video")); OS_IsValid(iter); OS_Advance(&iter) {
|
|
||||||
if S8_EndsWith(iter.absolute_path, S8(".srt"), true) {
|
|
||||||
file_content := OS_ReadFile(&Perm, iter.absolute_path);
|
|
||||||
PushTranscript(&Transcripts, {
|
|
||||||
absolute_path = STR(iter.absolute_path),
|
|
||||||
file_content = STR(file_content)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < Transcripts.len; i += 1 {
|
|
||||||
TE.ReplaceText(&FilenamesBuffer, {FilenamesBuffer.len, FilenamesBuffer.len}, Transcripts.data[i].absolute_path);
|
|
||||||
TE.ReplaceText(&FilenamesBuffer, {FilenamesBuffer.len, FilenamesBuffer.len}, "\n");
|
|
||||||
}
|
|
||||||
TE.ReplaceText(&ResultsBuffer, {ResultsBuffer.len, ResultsBuffer.len}, Transcripts.data[0].file_content);
|
|
||||||
TE.ReplaceText(&SearchBar, {SearchBar.len, SearchBar.len}, "");
|
|
||||||
|
|
||||||
TE.AddWindow({buffer = &SearchBar});
|
|
||||||
TE.AddWindow({buffer = &ResultsBuffer, flags = TE.WindowFlags_DrawScrollbar});
|
|
||||||
TE.FocusedWindow = &TE.WindowStack[0];
|
|
||||||
TE.FocusedWindow = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Te.ComputeWindowRects(rect);
|
|
||||||
TE.WindowStack[0].rect = CutTop(&rect, font_size * 2);
|
|
||||||
TE.WindowStack[1].rect = CutLeft(&rect, 1.0 * GetRectX(rect));
|
|
||||||
|
|
||||||
TE.UpdateAndDrawWindows(font, font_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S8 :: proc(str: String): S8_String { return {str = str.str, len = :i64(str.len)}; }
|
|
||||||
STR :: proc(str: S8_String): String { return {str = str.str, len = :int(str.len)}; }
|
|
||||||
|
|
||||||
Transcript :: struct {
|
|
||||||
file_content: String;
|
|
||||||
absolute_path: String;
|
|
||||||
}
|
|
||||||
|
|
||||||
TranscriptStack :: struct {
|
|
||||||
data: [2048]Transcript;
|
|
||||||
len: int;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushTranscript :: proc(stack: *TranscriptStack, t: Transcript) {
|
|
||||||
assert(stack.len + 1 < lengthof(stack.data));
|
|
||||||
stack.data[stack.len] = t;
|
|
||||||
stack.len += 1;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,10 +34,25 @@ AdjustUTF8PosUnsafe :: proc(buffer: *Buffer, pos: int, direction: int = 1): int
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetBufferEnd :: proc(buffer: *Buffer): int {
|
||||||
|
result := MaxInt(0, buffer.len - 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetBufferEndRange :: proc(buffer: *Buffer): Range {
|
||||||
|
result := GetBufferEnd(buffer);
|
||||||
|
return {result, result};
|
||||||
|
}
|
||||||
|
|
||||||
|
GetEntireBufferRange :: proc(buffer: *Buffer): Range {
|
||||||
|
result: Range = {0, GetBufferEnd(buffer)};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
AdjustUTF8Pos :: proc(buffer: *Buffer, pos: int, direction: int = 1): int {
|
AdjustUTF8Pos :: proc(buffer: *Buffer, pos: int, direction: int = 1): int {
|
||||||
assert(direction == 1 || direction == -1);
|
assert(direction == 1 || direction == -1);
|
||||||
pos = AdjustUTF8PosUnsafe(buffer, pos, direction);
|
pos = AdjustUTF8PosUnsafe(buffer, pos, direction);
|
||||||
pos = ClampInt(pos, 0, MaxInt(0, buffer.len - 1));
|
pos = ClampInt(pos, 0, GetBufferEnd(buffer));
|
||||||
if (buffer.data) assert(!IsUTF8ContinuationByte(buffer.data[pos]));
|
if (buffer.data) assert(!IsUTF8ContinuationByte(buffer.data[pos]));
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
@@ -131,8 +146,7 @@ GetStringFromBuffer :: proc(buffer: *Buffer, range: Range): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddText :: proc(buffer: *Buffer, text: String) {
|
AddText :: proc(buffer: *Buffer, text: String) {
|
||||||
end_of_buffer: Range = {buffer.len - 1, buffer.len - 1};
|
ReplaceText(buffer, GetBufferEndRange(buffer), text);
|
||||||
ReplaceText(buffer, end_of_buffer, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FindLineOfPos :: proc(buffer: *Buffer, pos: int): LineInfo {
|
FindLineOfPos :: proc(buffer: *Buffer, pos: int): LineInfo {
|
||||||
@@ -204,7 +218,7 @@ SeekOnWordBoundary :: proc(buffer: *Buffer, pos: int, direction: int = GO_FORWAR
|
|||||||
seek_whitespace := standing_on_whitespace == false;
|
seek_whitespace := standing_on_whitespace == false;
|
||||||
seek_word := standing_on_whitespace;
|
seek_word := standing_on_whitespace;
|
||||||
|
|
||||||
end := buffer.len - 1;
|
end := GetBufferEnd(buffer);
|
||||||
if (direction == GO_BACKWARD) end = 0;
|
if (direction == GO_BACKWARD) end = 0;
|
||||||
|
|
||||||
result := end;
|
result := end;
|
||||||
|
|||||||
@@ -26,11 +26,10 @@ UpdateTextEditor :: proc(rect: Rect2P, font: Font, font_size: float, font_spacin
|
|||||||
UpdateAndDrawWindows(font, font_size);
|
UpdateAndDrawWindows(font, font_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowFlags :: typedef u64;
|
|
||||||
WindowFlags_DrawScrollbar :: 1;
|
WindowFlags_DrawScrollbar :: 1;
|
||||||
|
|
||||||
Window :: struct {
|
Window :: struct {
|
||||||
flags: WindowFlags;
|
flags: u64;
|
||||||
buffer: *Buffer;
|
buffer: *Buffer;
|
||||||
|
|
||||||
cursor: Selection;
|
cursor: Selection;
|
||||||
@@ -76,10 +75,9 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
text_window_rect := w.rect;
|
text_window_rect := w.rect;
|
||||||
bar_rect := CutRight(&text_window_rect, 10);
|
bar_rect := CutRight(&text_window_rect, 10);
|
||||||
horizontal_bar_rect := CutBottom(&text_window_rect, 10);
|
horizontal_bar_rect := CutBottom(&text_window_rect, 10);
|
||||||
horizontal_bar_rect; @unused
|
|
||||||
// line_numbers_rect := CutLeft(&text_window_rect, Monosize.x * 4);
|
// line_numbers_rect := CutLeft(&text_window_rect, Monosize.x * 4);
|
||||||
|
|
||||||
buffer_end_vpos := CalculateVisualPos(w.buffer, w.buffer.len - 1);
|
buffer_end_vpos := CalculateVisualPos(w.buffer, GetBufferEnd(w.buffer));
|
||||||
buffer_end_wpos := CalculateWorldPosUnscrolled(buffer_end_vpos);
|
buffer_end_wpos := CalculateWorldPosUnscrolled(buffer_end_vpos);
|
||||||
|
|
||||||
if CheckCollisionPointRec(GetMousePosition(), Rect2PToRectangle(w.rect)) {
|
if CheckCollisionPointRec(GetMousePosition(), Rect2PToRectangle(w.rect)) {
|
||||||
@@ -251,7 +249,7 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
// @todo: buffer.len abstract
|
// @todo: buffer.len abstract
|
||||||
if IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_A) {
|
if IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_A) {
|
||||||
w.cursor.a = 0;
|
w.cursor.a = 0;
|
||||||
w.cursor.b = w.buffer.len - 1;
|
w.cursor.b = GetBufferEnd(w.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsKeyPressed(KEY_PAGE_DOWN) || IsKeyPressedRepeat(KEY_PAGE_DOWN) {
|
if IsKeyPressed(KEY_PAGE_DOWN) || IsKeyPressedRepeat(KEY_PAGE_DOWN) {
|
||||||
@@ -323,7 +321,6 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
}
|
}
|
||||||
if (w.scroll.x < 0) w.scroll.x = 0;
|
if (w.scroll.x < 0) w.scroll.x = 0;
|
||||||
if (w.scroll.y < 0) w.scroll.y = 0;
|
if (w.scroll.y < 0) w.scroll.y = 0;
|
||||||
|
|
||||||
if (w.scroll.y > buffer_end_wpos.y) w.scroll.y = buffer_end_wpos.y;
|
if (w.scroll.y > buffer_end_wpos.y) w.scroll.y = buffer_end_wpos.y;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -345,7 +342,6 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
SetMouseCursor(MOUSE_CURSOR_IBEAM);
|
||||||
} else {
|
} else {
|
||||||
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
|
SetMouseCursor(MOUSE_CURSOR_DEFAULT);
|
||||||
|
|
||||||
if IsMouseButtonPressed(MOUSE_BUTTON_LEFT) {
|
if IsMouseButtonPressed(MOUSE_BUTTON_LEFT) {
|
||||||
w.mouse_scrolling = true;
|
w.mouse_scrolling = true;
|
||||||
}
|
}
|
||||||
@@ -364,7 +360,7 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
w.mouse_selecting = false;
|
w.mouse_selecting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.mouse_scrolling {
|
if IsFlagSet(w.flags, WindowFlags_DrawScrollbar) && w.mouse_scrolling {
|
||||||
mouse_scroll_marker_normalized := (mouse_p.y - w.rect.min.y) / GetRectY(bar_rect);
|
mouse_scroll_marker_normalized := (mouse_p.y - w.rect.min.y) / GetRectY(bar_rect);
|
||||||
w.scroll.y = mouse_scroll_marker_normalized * buffer_end_wpos.y;
|
w.scroll.y = mouse_scroll_marker_normalized * buffer_end_wpos.y;
|
||||||
|
|
||||||
@@ -459,7 +455,7 @@ UpdateAndDrawWindow :: proc(w: *Window, font: Font, font_size: float) {
|
|||||||
|
|
||||||
|
|
||||||
// Draw bar
|
// Draw bar
|
||||||
{
|
if IsFlagSet(w.flags, WindowFlags_DrawScrollbar) {
|
||||||
DrawRect(bar_rect, LIGHTGRAY);
|
DrawRect(bar_rect, LIGHTGRAY);
|
||||||
DrawRect(horizontal_bar_rect, LIGHTGRAY);
|
DrawRect(horizontal_bar_rect, LIGHTGRAY);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user