can now open files through command palette

This commit is contained in:
Matthew 2025-09-27 21:16:46 +10:00
parent 54619b52d3
commit 6905c73710
4 changed files with 278 additions and 103 deletions

@ -1 +1 @@
Subproject commit cadb2b5f853a22aa870dc1d986e73330c9136bb5 Subproject commit 6e1952eab0ee2eed5c105311df56e603857798c2

View File

@ -48,21 +48,12 @@ CreateFlatBuffer(u8[] data)
u8[] buf = MAllocArray!(u8)(capacity); u8[] buf = MAllocArray!(u8)(capacity);
buf[0 .. data.length] = data[0 .. data.length]; 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 = { FlatBuffer fb = {
arena: CreateArena(MB(1)), arena: CreateArena(MB(1)),
ls_arena: CreateArena(KB(512)), ls_arena: CreateArena(KB(512)),
data: buf, data: buf,
length: cast(u64)data.length, length: cast(u64)data.length,
lf_count: lf_count, lf_count: CountLF(data),
}; };
fb.tk = CreateTokenizer(&fb); fb.tk = CreateTokenizer(&fb);
@ -72,6 +63,38 @@ CreateFlatBuffer(u8[] data)
return fb; 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 void
Fix(FlatBuffer* buffer) Fix(FlatBuffer* buffer)
{ {
@ -89,12 +112,12 @@ Fix(FlatBuffer* buffer)
line_starts[ls_idx] = i+1; line_starts[ls_idx] = i+1;
ls_idx += 1; ls_idx += 1;
} }
} }
dirty = false; dirty = false;
Tokenize(buffer); // TODO: fix
//Tokenize(buffer);
} }
} }
@ -537,16 +560,23 @@ struct Tokenizer
} }
Tokenizer Tokenizer
CreateTokenizer(FlatBuffer* buffer) CreateTokenizer(FlatBuffer* fb)
{ {
Tokenizer tokenizer = { Tokenizer tokenizer = {
arena: CreateArena(MB(8)), arena: CreateArena(MB(8)),
buffer: MAllocArray!(TS)(buffer.data.length), buffer: MAllocArray!(TS)(fb.data.length),
}; };
return tokenizer; return tokenizer;
} }
void
Change(FlatBuffer* fb)
{
MFreeArray(fb.tk.buffer);
fb.tk.buffer = MAllocArray!(TS)(fb.data.length);
}
u8 u8
PeekNextChar(FlatBuffer* fb) PeekNextChar(FlatBuffer* fb)
{ {

View File

@ -31,17 +31,20 @@ struct EditorCtx
u32 icount; u32 icount;
Timer timer; Timer timer;
CmdPalette cmd; CmdPalette cmd;
u8[][] file_names;
} }
struct CmdPalette struct CmdPalette
{ {
Arena arena; Arena arena;
u8[] buffer; Arena cmd_arena;
u32 icount; u8[] buffer;
Command[] commands; u32 icount;
u8[][] opt_strs; Command[] commands;
i64 selected; u8[][] opt_strs;
Command current; i64 selected;
Command current;
Parameter[] params;
} }
struct Editor struct Editor
@ -67,6 +70,12 @@ struct Command
CmdType type; CmdType type;
} }
struct Parameter
{
u8[] value;
bool visible;
}
enum CmdType enum CmdType
{ {
None, None,
@ -144,7 +153,8 @@ InitEditorCtx(PlatformWindow* window)
EditorCtx ctx = { EditorCtx ctx = {
arena: CreateArena(MB(2)), arena: CreateArena(MB(2)),
cmd: { cmd: {
arena: CreateArena(KB(512)), arena: CreateArena(MB(1)),
cmd_arena: CreateArena(MB(1)),
buffer: MAllocArray!(u8)(1024), buffer: MAllocArray!(u8)(1024),
}, },
}; };
@ -154,6 +164,37 @@ InitEditorCtx(PlatformWindow* window)
ctx.timer = CreateTimer(); ctx.timer = CreateTimer();
SetFocusedPanel(ctx.base_panel); 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; return ctx;
} }
@ -179,9 +220,35 @@ EditModeActive()
} }
void 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 // 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 void
HandleInputs(EditorCtx* ctx, Inputs* inputs) HandleInputs(EditorCtx* ctx, Inputs* inputs)
{ {
@ -304,10 +383,7 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
{ {
if(key == Input.Escape) if(key == Input.Escape)
{ {
ctx.state = ES.NormalMode; ResetCtx(ctx);
ctx.cmd.icount = 0;
ctx.cmd.commands = [];
InsertInputToBuf(ctx);
taken = true; taken = true;
} }
else if(ctx.state == ES.InputMode) else if(ctx.state == ES.InputMode)
@ -472,6 +548,52 @@ TextLineCharCases()
return result; 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 void
GetCommands(CmdPalette* cmd) GetCommands(CmdPalette* cmd)
{ {
@ -492,6 +614,7 @@ GetCommands(CmdPalette* cmd)
Reset(&cmd.arena); Reset(&cmd.arena);
cmd.commands = AllocArray!(Command)(&cmd.arena, cmd_list.length); cmd.commands = AllocArray!(Command)(&cmd.arena, cmd_list.length);
cmd.params = [];
u8[] str = cmd.buffer[0 .. cmd.icount]; u8[] str = cmd.buffer[0 .. cmd.icount];
@ -500,16 +623,7 @@ GetCommands(CmdPalette* cmd)
{ {
for(u64 i = 0; i < cmd_list.length; i += 1) for(u64 i = 0; i < cmd_list.length; i += 1)
{ {
u64 match = 0; if(StrContains!(true)(cmd_list[i].name, str))
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)
{ {
cmd.commands[count] = cast(Command)cmd_list[i]; cmd.commands[count] = cast(Command)cmd_list[i];
count += 1; count += 1;
@ -543,7 +657,28 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
u64 prev_count = cmd.icount; u64 prev_count = cmd.icount;
switch(ev.key) with(Input) 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: case Backspace:
{ {
if(cmd.icount > 0) if(cmd.icount > 0)
@ -580,11 +715,12 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
} break; } break;
case Down: case Down:
{ {
if(cmd.selected < cmd.commands.length) if(cmd.selected < cmd.opt_strs.length)
{ {
cmd.selected += 1; cmd.selected += 1;
} }
} break; } break;
mixin(TextLineCharCases());
default: break; default: break;
} }
@ -594,13 +730,69 @@ HandleCmdMode(EditorCtx* ctx, InputEvent ev)
cmd.buffer[cmd.icount++] = result; 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); GetCommands(cmd);
cmd.selected = 0; 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; return taken;
} }

View File

@ -11,47 +11,23 @@ import core.stdc.math : fabsf;
import std.conv; import std.conv;
import core.stdc.stdio : sprintf; import core.stdc.stdio : sprintf;
const Vec4[4] DEFAULT_COL = [ 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),
Vec4(0.13, 0.13, 0.13, 1.0),
];
const Vec4[4] CMD_PALETTE_COL = [ 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),
Vec4(0.21, 0.21, 0.21, 1.0),
];
const Vec4[4] DEFAULT_BORDER_COL = [ 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),
Vec4(0.254, 0.254, 0.266, 1.0),
];
const Vec4[4] HL_BORDER_COL = [ 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),
Vec4(0.035, 0.549, 0.824, 1.0),
];
const Vec4[4] LC_COLOR = [ 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),
Vec4(0.12, 0.12, 0.12, 1.0),
];
const Vec4[4] LC_HL_COLOR = [ 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), const Vec4[4] CMD_PALETTE_INPUT_HL = Vec4(0.24, 0.45, 0.81, 1.0);
Vec4(0.012, 0.176, 0.29, 1.0),
Vec4(0.012, 0.176, 0.29, 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 = [ const Vec4[4] CMD_PALETTE_INPUT_COL = [
Vec4(0.14, 0.14, 0.14, 1.0), 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), 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; const UIPanel g_ui_nil_panel;
UIPanel* g_UI_NIL_PANEL; UIPanel* g_UI_NIL_PANEL;