diff --git a/src/dlib b/src/dlib index cadb2b5..6e1952e 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit cadb2b5f853a22aa870dc1d986e73330c9136bb5 +Subproject commit 6e1952eab0ee2eed5c105311df56e603857798c2 diff --git a/src/editor/buffer.d b/src/editor/buffer.d index 8de0cb3..5e536ec 100644 --- a/src/editor/buffer.d +++ b/src/editor/buffer.d @@ -48,21 +48,12 @@ CreateFlatBuffer(u8[] data) u8[] buf = MAllocArray!(u8)(capacity); buf[0 .. data.length] = data[0 .. data.length]; - u64 lf_count = 0; - for(u64 i = 0; i < cast(u64)data.length; i += 1) - { - if(data.ptr[i] == '\n') - { - lf_count += 1; - } - } - FlatBuffer fb = { arena: CreateArena(MB(1)), ls_arena: CreateArena(KB(512)), data: buf, length: cast(u64)data.length, - lf_count: lf_count, + lf_count: CountLF(data), }; fb.tk = CreateTokenizer(&fb); @@ -72,6 +63,38 @@ CreateFlatBuffer(u8[] data) return fb; } +void +Change(FlatBuffer* fb, u8[] data) +{ + MFreeArray(fb.data); + + u64 cap = data.length > 0 ? RoundUp(cast(u64)(data.length) * 2, KB(4)) : KB(4); + + fb.data = MAllocArray!(u8)(cap); + fb.data[0 .. data.length] = data[0 .. $]; + fb.length = data.length; + fb.lf_count = CountLF(data); + + Change(fb); + + Fix(fb); +} + +u64 +CountLF(u8[] data) +{ + u64 lf_count = 0; + for(u64 i = 0; i < data.length; i += 1) + { + if(data.ptr[i] == '\n') + { + lf_count += 1; + } + } + + return lf_count; +} + void Fix(FlatBuffer* buffer) { @@ -89,12 +112,12 @@ Fix(FlatBuffer* buffer) line_starts[ls_idx] = i+1; ls_idx += 1; } - } dirty = false; - Tokenize(buffer); + // TODO: fix + //Tokenize(buffer); } } @@ -537,16 +560,23 @@ struct Tokenizer } Tokenizer -CreateTokenizer(FlatBuffer* buffer) +CreateTokenizer(FlatBuffer* fb) { Tokenizer tokenizer = { arena: CreateArena(MB(8)), - buffer: MAllocArray!(TS)(buffer.data.length), + buffer: MAllocArray!(TS)(fb.data.length), }; return tokenizer; } +void +Change(FlatBuffer* fb) +{ + MFreeArray(fb.tk.buffer); + fb.tk.buffer = MAllocArray!(TS)(fb.data.length); +} + u8 PeekNextChar(FlatBuffer* fb) { diff --git a/src/editor/editor.d b/src/editor/editor.d index 9e83f71..d1f54f9 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -31,17 +31,20 @@ struct EditorCtx u32 icount; Timer timer; CmdPalette cmd; + u8[][] file_names; } struct CmdPalette { - Arena arena; - u8[] buffer; - u32 icount; - Command[] commands; - u8[][] opt_strs; - i64 selected; - Command current; + Arena arena; + Arena cmd_arena; + u8[] buffer; + u32 icount; + Command[] commands; + u8[][] opt_strs; + i64 selected; + Command current; + Parameter[] params; } struct Editor @@ -67,6 +70,12 @@ struct Command CmdType type; } +struct Parameter +{ + u8[] value; + bool visible; +} + enum CmdType { None, @@ -144,7 +153,8 @@ InitEditorCtx(PlatformWindow* window) EditorCtx ctx = { arena: CreateArena(MB(2)), cmd: { - arena: CreateArena(KB(512)), + arena: CreateArena(MB(1)), + cmd_arena: CreateArena(MB(1)), buffer: MAllocArray!(u8)(1024), }, }; @@ -154,6 +164,37 @@ InitEditorCtx(PlatformWindow* window) ctx.timer = CreateTimer(); SetFocusedPanel(ctx.base_panel); + if(getcwd() != "/") + { + // TODO: replace this with something nogc/nothrow + try + { + u64 count = 0; + foreach(DirEntry e; dirEntries(".", SpanMode.breadth)) + { + if(indexOf(e.name, ".git") != -1 || e.isDir) continue; + + u64 start = indexOf(e.name, "./") == 0 ? 2 : 0; + count += 1; + } + + ctx.file_names = AllocArray!(u8[])(&ctx.arena, count); + + count = 0; + foreach(DirEntry e; dirEntries(".", SpanMode.breadth)) + { + if(indexOf(e.name, ".git") != -1 || e.isDir) continue; + + u64 start = indexOf(e.name, "./") == 0 ? 2 : 0; + ctx.file_names[count++] = AllocCopy!(u8)(&ctx.arena, CastStr!(u8)(e.name[start .. $])); + } + } + catch(Exception e) + { + Logf("failed to open directory for filenames"); + } + } + return ctx; } @@ -179,9 +220,35 @@ EditModeActive() } void -ScanFiles(EditorCtx* ctx) +OpenFile(Editor* ed, u8[] file_name) { - + import core.stdc.stdio; + + auto f = fopen(cast(char*)file_name.ptr, "rb"); + if(f != null) + { + Logf("opened"); + scope(exit) fclose(f); + + fseek(f, 0, SEEK_END); + i64 len = ftell(f); + fseek(f, 0, SEEK_SET); + + if(len > 0) + { + Logf("b"); + u8[] buf = ScratchAlloc!(u8)(len); + Logf("a"); + fread(buf.ptr, u8.sizeof, len, f); + Change(&ed.buf, buf); + + Logf("read"); + } + } + else + { + Logf("[Error] Unable to open file %s", cast(char[])file_name); + } } // Load all files then move things into editor after being created when selected @@ -290,6 +357,18 @@ InsertInputToBuf(EditorCtx* ctx) } } +void +ResetCtx(EditorCtx* ctx) +{ + InsertInputToBuf(ctx); + + ctx.state = ES.NormalMode; + ctx.cmd.icount = 0; + ctx.cmd.commands = []; + ctx.cmd.current = cast(Command)NO_CMD; + ctx.cmd.selected = 0; +} + void HandleInputs(EditorCtx* ctx, Inputs* inputs) { @@ -304,10 +383,7 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs) { if(key == Input.Escape) { - ctx.state = ES.NormalMode; - ctx.cmd.icount = 0; - ctx.cmd.commands = []; - InsertInputToBuf(ctx); + ResetCtx(ctx); taken = true; } else if(ctx.state == ES.InputMode) @@ -472,6 +548,52 @@ TextLineCharCases() return result; } +pragma(inline) u8 +Lower(u8 ch) +{ + if(ch >= 65 && ch <= 90) + { + ch += 32; + } + + return ch; +} + +bool +StrContains(bool begins_with)(const u8[] str, u8[] match) +{ + return StrContains!(begins_with)(cast(u8[])str, match); +} + +bool +StrContains(bool begins_with)(u8[] str, u8[] match) +{ + u64 count; + for(u64 i = 0; i < str.length; i += 1) + { + static if(begins_with) if(i >= match.length) + { + break; + } + + if(Lower(str[i]) == Lower(match[count])) + { + count += 1; + } + else + { + count = 0; + } + + static if(!begins_with) if(count == match.length) + { + break; + } + } + + return count == match.length; +} + void GetCommands(CmdPalette* cmd) { @@ -492,6 +614,7 @@ GetCommands(CmdPalette* cmd) Reset(&cmd.arena); cmd.commands = AllocArray!(Command)(&cmd.arena, cmd_list.length); + cmd.params = []; u8[] str = cmd.buffer[0 .. cmd.icount]; @@ -500,16 +623,7 @@ GetCommands(CmdPalette* cmd) { for(u64 i = 0; i < cmd_list.length; i += 1) { - u64 match = 0; - for(u64 j = 0; j < str.length && j < cmd_list[i].name.length; j += 1) - { - if(str[j] == cmd_list[i].name[j] || (str[j]-32) == cmd_list[i].name[j]) - { - match += 1; - } - } - - if(match == str.length) + if(StrContains!(true)(cmd_list[i].name, str)) { cmd.commands[count] = cast(Command)cmd_list[i]; count += 1; @@ -543,7 +657,28 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev) u64 prev_count = cmd.icount; switch(ev.key) with(Input) { - mixin(TextLineCharCases()); + case Enter: + { + if(cmd.current.type == CT.None) + { + goto case Tab; + } + + switch(cmd.current.type) + { + case CT.OpenFile: + { + UIPanel* p = GetFocusedPanel(); + if(!Nil(p) && cmd.selected >= 0 && cmd.selected < cmd.opt_strs.length) + { + OpenFile(p.ed, cmd.opt_strs[cmd.selected]); + } + } break; + default: break; + } + + ResetCtx(ctx); + } goto CmdInputEnd; case Backspace: { if(cmd.icount > 0) @@ -580,11 +715,12 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev) } break; case Down: { - if(cmd.selected < cmd.commands.length) + if(cmd.selected < cmd.opt_strs.length) { cmd.selected += 1; } } break; + mixin(TextLineCharCases()); default: break; } @@ -594,13 +730,69 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev) cmd.buffer[cmd.icount++] = result; } - if(cmd.commands.length == 0 || prev_count != cmd.icount) + if(cmd.current.type == CT.None && (cmd.commands.length == 0 || prev_count != cmd.icount)) { GetCommands(cmd); cmd.selected = 0; - - Logf("%s", cmd.current.type); } + else if(prev_count != cmd.icount) + { + u64 start = cmd.current.name.length; + bool has_param; + for(u64 i = start; i < cmd.icount; i += 1) + { + if(cmd.buffer[i] != ' ') + { + start = i; + has_param = true; + break; + } + } + + u8[] param = cmd.buffer[start .. cmd.icount]; + + switch(cmd.current.type) with(CT) + { + case OpenFile: + { + if(cmd.params.length == 0 || !has_param) + { + cmd.params = AllocArray!(Parameter)(&cmd.cmd_arena, ctx.file_names.length); + cmd.opt_strs = AllocArray!(u8[])(&cmd.cmd_arena, ctx.file_names.length); + + for(u64 i = 0; i < cmd.params.length; i += 1) + { + cmd.params[i].value = ctx.file_names[i]; + cmd.params[i].visible = true; + cmd.opt_strs[i] = cmd.params[i].value; + } + } + + if(has_param) + { + cmd.opt_strs = AllocArray!(u8[])(&cmd.cmd_arena, ctx.file_names.length); + + u64 matches; + for(u64 i = 0; i < cmd.params.length; i += 1) + { + bool contains = StrContains!(false)(cmd.params[i].value, param); + if(contains) + { + cmd.opt_strs[matches] = cmd.params[i].value; + matches += 1; + } + + cmd.params[i].visible = contains; + } + + cmd.opt_strs = cmd.opt_strs[0 .. matches]; + } + } break; + default: break; + } + } + +CmdInputEnd: return taken; } diff --git a/src/editor/widgets.d b/src/editor/widgets.d index e377de9..008cf72 100644 --- a/src/editor/widgets.d +++ b/src/editor/widgets.d @@ -11,47 +11,23 @@ import core.stdc.math : fabsf; import std.conv; import core.stdc.stdio : sprintf; -const Vec4[4] DEFAULT_COL = [ - Vec4(0.13, 0.13, 0.13, 1.0), - Vec4(0.13, 0.13, 0.13, 1.0), - Vec4(0.13, 0.13, 0.13, 1.0), - Vec4(0.13, 0.13, 0.13, 1.0), -]; +const Vec4[4] DEFAULT_COL = Vec4(0.13, 0.13, 0.13, 1.0); -const Vec4[4] CMD_PALETTE_COL = [ - Vec4(0.21, 0.21, 0.21, 1.0), - Vec4(0.21, 0.21, 0.21, 1.0), - Vec4(0.21, 0.21, 0.21, 1.0), - Vec4(0.21, 0.21, 0.21, 1.0), -]; +const Vec4[4] CMD_PALETTE_COL = Vec4(0.21, 0.21, 0.21, 1.0); -const Vec4[4] DEFAULT_BORDER_COL = [ - Vec4(0.254, 0.254, 0.266, 1.0), - Vec4(0.254, 0.254, 0.266, 1.0), - Vec4(0.254, 0.254, 0.266, 1.0), - Vec4(0.254, 0.254, 0.266, 1.0), -]; +const Vec4[4] DEFAULT_BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0); -const Vec4[4] HL_BORDER_COL = [ - Vec4(0.035, 0.549, 0.824, 1.0), - Vec4(0.035, 0.549, 0.824, 1.0), - Vec4(0.035, 0.549, 0.824, 1.0), - Vec4(0.035, 0.549, 0.824, 1.0), -]; +const Vec4[4] HL_BORDER_COL = Vec4(0.035, 0.549, 0.824, 1.0); -const Vec4[4] LC_COLOR = [ - Vec4(0.12, 0.12, 0.12, 1.0), - Vec4(0.12, 0.12, 0.12, 1.0), - Vec4(0.12, 0.12, 0.12, 1.0), - Vec4(0.12, 0.12, 0.12, 1.0), -]; +const Vec4[4] LC_COLOR = Vec4(0.12, 0.12, 0.12, 1.0); -const Vec4[4] LC_HL_COLOR = [ - Vec4(0.012, 0.176, 0.29, 1.0), - Vec4(0.012, 0.176, 0.29, 1.0), - Vec4(0.012, 0.176, 0.29, 1.0), - Vec4(0.012, 0.176, 0.29, 1.0), -]; +const Vec4[4] LC_HL_COLOR = Vec4(0.012, 0.176, 0.29, 1.0); + +const Vec4[4] CMD_PALETTE_INPUT_HL = Vec4(0.24, 0.45, 0.81, 1.0); + +const Vec4[4] CMD_INPUT_BORDER_COL = Vec4(0.003, 0.48, 0.68, 1.0); + +const Vec4[4] CMD_INPUT_BORDER_HL = Vec4(0.05, 0.56, 0.76, 1.0); const Vec4[4] CMD_PALETTE_INPUT_COL = [ Vec4(0.14, 0.14, 0.14, 1.0), @@ -60,29 +36,6 @@ const Vec4[4] CMD_PALETTE_INPUT_COL = [ Vec4(0.17, 0.17, 0.17, 1.0), ]; -const Vec4[4] CMD_PALETTE_INPUT_HL = [ - Vec4(0.24, 0.45, 0.81, 1.0), - Vec4(0.24, 0.45, 0.81, 1.0), - Vec4(0.24, 0.45, 0.81, 1.0), - Vec4(0.24, 0.45, 0.81, 1.0), -]; - -const Vec4[4] CMD_INPUT_BORDER_COL = [ - Vec4(0.003, 0.48, 0.68, 1.0), - Vec4(0.003, 0.48, 0.68, 1.0), - Vec4(0.003, 0.48, 0.68, 1.0), - Vec4(0.003, 0.48, 0.68, 1.0), -]; - -const Vec4[4] CMD_INPUT_BORDER_HL = [ - Vec4(0.05, 0.56, 0.76, 1.0), - Vec4(0.05, 0.56, 0.76, 1.0), - Vec4(0.05, 0.56, 0.76, 1.0), - Vec4(0.05, 0.56, 0.76, 1.0), -]; - -// 9, 141, 211 - const UIPanel g_ui_nil_panel; UIPanel* g_UI_NIL_PANEL;