Add QueryUserString. QueryUserFile working, fix bug in Open with line,col.

This commit is contained in:
Krzosa Karol
2026-01-18 22:53:10 +01:00
parent 76e279920f
commit 70f28de0e1
7 changed files with 165 additions and 110 deletions

View File

@@ -1557,7 +1557,7 @@ void SaveBuffer(Buffer *buffer) {
} }
} }
String GetBufferDirectory(Buffer *buffer) { String GetDirectory(Buffer *buffer) {
#if PLUGIN_DIRECTORY_NAVIGATION #if PLUGIN_DIRECTORY_NAVIGATION
if (buffer->is_dir) { if (buffer->is_dir) {
return buffer->name; return buffer->name;

View File

@@ -178,7 +178,7 @@ void TrimWhitespace(Buffer *buffer, bool trim_lines_with_caret) {
void ApplyFormattingTool(Buffer *buffer, String tool) { void ApplyFormattingTool(Buffer *buffer, String tool) {
Scratch scratch; Scratch scratch;
String string = AllocCharString(scratch, buffer); String string = AllocCharString(scratch, buffer);
ExecResult exec_result = ExecAndWait(scratch, tool, GetBufferDirectory(buffer), string); ExecResult exec_result = ExecAndWait(scratch, tool, GetDirectory(buffer), string);
String16 string16 = {exec_result.buffer->str, exec_result.buffer->len}; String16 string16 = {exec_result.buffer->str, exec_result.buffer->len};
if (exec_result.exit_code == 0) { if (exec_result.exit_code == 0) {
ReplaceWithoutMovingCarets(buffer, GetRange(buffer), string16); ReplaceWithoutMovingCarets(buffer, GetRange(buffer), string16);
@@ -205,7 +205,7 @@ void CMD_FormatSelection() {
MergeCarets(primary.buffer, &primary.view->carets); MergeCarets(primary.buffer, &primary.view->carets);
For (primary.view->carets) { For (primary.view->carets) {
String input_string = ToString(scratch, GetString(primary.buffer, it.range)); String input_string = ToString(scratch, GetString(primary.buffer, it.range));
ExecResult exec_result = ExecAndWait(scratch, tool, GetBufferDirectory(primary.buffer), input_string); ExecResult exec_result = ExecAndWait(scratch, tool, GetDirectory(primary.buffer), input_string);
String16 string16 = {exec_result.buffer->str, exec_result.buffer->len}; String16 string16 = {exec_result.buffer->str, exec_result.buffer->len};
AddEdit(&edits, it.range, string16); AddEdit(&edits, it.range, string16);
} }
@@ -217,7 +217,7 @@ void New(Window *window, String name = "") {
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
Scratch scratch; Scratch scratch;
String dir = GetBufferDirectory(buffer); String dir = GetDirectory(buffer);
if (name != "") { if (name != "") {
if (!IsAbsolute(name)) { if (!IsAbsolute(name)) {
name = Format(scratch, "%S/%S", dir, name); name = Format(scratch, "%S/%S", dir, name);
@@ -315,7 +315,7 @@ void CO_Close(mco_coro *co) {
} }
String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", main.buffer->name); String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", main.buffer->name);
UIAction ui_action = ShowYesNoCancelUI(co, main, question); UIAction ui_action = QueryUserYesNoCancel(co, main, question);
if (ui_action == UIAction_Yes) { if (ui_action == UIAction_Yes) {
SaveBuffer(main.buffer); SaveBuffer(main.buffer);
Close(main.buffer->id); Close(main.buffer->id);
@@ -351,7 +351,7 @@ UIAction ShowCloseAllUI(mco_coro *co) {
} }
String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", it->name); String question = Format(CoCurr->arena, "Do you want to save [%S] before closing?", it->name);
UIAction ui_action = ShowYesNoCancelUI(co, main, question); UIAction ui_action = QueryUserYesNoCancel(co, main, question);
it = GetBuffer(id, NULL); it = GetBuffer(id, NULL);
if (it && ui_action == UIAction_Yes) { if (it && ui_action == UIAction_Yes) {
SaveBuffer(it); SaveBuffer(it);
@@ -458,4 +458,9 @@ void CMD_ToggleFullscreen() {
SDL_SetWindowPosition(SDLWindow, 0, 0); SDL_SetWindowPosition(SDLWindow, 0, 0);
} }
IsInFullscreen = !IsInFullscreen; IsInFullscreen = !IsInFullscreen;
} RegisterCommand(CMD_ToggleFullscreen, "f11", "switches between the fullscreen and non-fulscreen mode"); } RegisterCommand(CMD_ToggleFullscreen, "f11", "Switches between the fullscreen and non-fulscreen mode");
void CMD_OpenLogs() {
Buffer *buffer = GetBuffer(NullBufferID);
Open(buffer->name);
} RegisterCommand(CMD_OpenLogs, "", "Opens the text editor logs");

View File

@@ -61,10 +61,10 @@ void CMD_RunFile() {
if (OS_WINDOWS) { if (OS_WINDOWS) {
String cmd = Format(scratch, "cl %S -Fe:cfile.exe /Zi /FC /nologo /WX /W3 /wd4200 /wd4334 /diagnostics:column && cfile.exe", primary.buffer->name); String cmd = Format(scratch, "cl %S -Fe:cfile.exe /Zi /FC /nologo /WX /W3 /wd4200 /wd4334 /diagnostics:column && cfile.exe", primary.buffer->name);
ExecBuild(cmd, GetBufferDirectory(primary.buffer)); ExecBuild(cmd, GetDirectory(primary.buffer));
} else { } else {
String cmd = Format(scratch, "bash <<EOF\nclang %S -o cfile.exe -g -Wall -Wno-missing-braces -Wno-writable-strings -Wno-writable-strings -fsanitize=address -fdiagnostics-absolute-paths -lm \n ./cfile.exe\nEOF", primary.buffer->name); String cmd = Format(scratch, "bash <<EOF\nclang %S -o cfile.exe -g -Wall -Wno-missing-braces -Wno-writable-strings -Wno-writable-strings -fsanitize=address -fdiagnostics-absolute-paths -lm \n ./cfile.exe\nEOF", primary.buffer->name);
ExecBuild(cmd, GetBufferDirectory(primary.buffer)); ExecBuild(cmd, GetDirectory(primary.buffer));
} }
build.window->visible = true; build.window->visible = true;
} RegisterCommand(CMD_RunFile, "", "Run and build current file, currently only C/C++ supported"); } RegisterCommand(CMD_RunFile, "", "Run and build current file, currently only C/C++ supported");

View File

@@ -11,7 +11,7 @@ void SetProjectDirectory(String dir) {
void CMD_SetProjectDirectoryHere() { void CMD_SetProjectDirectoryHere() {
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
SetProjectDirectory(GetBufferDirectory(main.buffer)); SetProjectDirectory(GetDirectory(main.buffer));
} RegisterCommand(CMD_SetProjectDirectoryHere, "", "Sets work directory to the directory of the current buffer, it also renames couple special buffers to make them accomodate the new ProjectDirectory"); } RegisterCommand(CMD_SetProjectDirectoryHere, "", "Sets work directory to the directory of the current buffer, it also renames couple special buffers to make them accomodate the new ProjectDirectory");
void CO_OpenCode(mco_coro *co) { void CO_OpenCode(mco_coro *co) {

View File

@@ -41,6 +41,32 @@ enum UIAction {
UIAction_No, UIAction_No,
}; };
enum OpenKind {
OpenKind_Invalid,
OpenKind_Skip,
OpenKind_Exec,
OpenKind_BackgroundExec,
OpenKind_Goto,
OpenKind_Command,
#if PLUGIN_CONFIG
OpenKind_Set,
#endif
};
typedef uint32_t ResolveOpenMeta;
enum {
ResolveOpenMeta_Normal = 0,
ResolveOpenMeta_DontError = 2,
ResolveOpenMeta_DontExec = 4, // dont error +
};
struct ResolvedOpen {
OpenKind kind;
String path;
Int line, col;
bool existing_buffer;
};
struct Buffer { struct Buffer {
BufferID id; BufferID id;
String name; String name;
@@ -125,6 +151,8 @@ struct Window {
ViewID active_goto_list; ViewID active_goto_list;
Int goto_list_pos; Int goto_list_pos;
String ui_query_file;
void (*after_resolve_open_hook)(Window *window, ResolvedOpen *resolved);
Array<Command> commands; Array<Command> commands;
struct { struct {
uint32_t draw_scrollbar : 1; uint32_t draw_scrollbar : 1;
@@ -245,32 +273,6 @@ struct Register_Variable {
type name = __VA_ARGS__; \ type name = __VA_ARGS__; \
Register_Variable var_##name(&Variables, VariableType_##type, #name, &name) Register_Variable var_##name(&Variables, VariableType_##type, #name, &name)
enum OpenKind {
OpenKind_Invalid,
OpenKind_Skip,
OpenKind_Exec,
OpenKind_BackgroundExec,
OpenKind_Goto,
OpenKind_Command,
#if PLUGIN_CONFIG
OpenKind_Set,
#endif
};
typedef uint32_t ResolveOpenMeta;
enum {
ResolveOpenMeta_Normal = 0,
ResolveOpenMeta_DontError = 2,
ResolveOpenMeta_DontExec = 4, // dont error +
};
struct ResolvedOpen {
OpenKind kind;
String path;
Int line, col;
bool existing_buffer;
};
void AddCommand(Array<Command> *arr, String name, struct Trigger *trigger, CMDFunction *function); void AddCommand(Array<Command> *arr, String name, struct Trigger *trigger, CMDFunction *function);
struct Register_Command { struct Register_Command {
Register_Command(Array<Command> *funcs, CMDFunction *function, String name, String binding, String docs = "") { Register_Command(Array<Command> *funcs, CMDFunction *function, String name, String binding, String docs = "") {
@@ -330,7 +332,7 @@ View *CreateView(BufferID active_buffer);
void EvalCommand(String command); void EvalCommand(String command);
void EvalCommand(String16 command); void EvalCommand(String16 command);
Rect2I GetVisibleCells(Window *window); Rect2I GetVisibleCells(Window *window);
ResolvedOpen ResolveOpen(Allocator scratch, String path, ResolveOpenMeta meta); ResolvedOpen ResolveOpen(Allocator scratch, Window *window, String path, ResolveOpenMeta meta);
BSet Open(String path, ResolveOpenMeta meta = ResolveOpenMeta_Normal); BSet Open(String path, ResolveOpenMeta meta = ResolveOpenMeta_Normal);
BSet Open(String16 path, ResolveOpenMeta meta = ResolveOpenMeta_Normal); BSet Open(String16 path, ResolveOpenMeta meta = ResolveOpenMeta_Normal);
void CenterView(WindowID window); void CenterView(WindowID window);

View File

@@ -1,6 +1,6 @@
void JumpTempBuffer(BSet *set, String buffer_name) { void JumpTempBuffer(BSet *set, String buffer_name) {
if (buffer_name.len == 0) { if (buffer_name.len == 0) {
buffer_name = GetUniqueBufferName(GetBufferDirectory(set->buffer), "temp"); buffer_name = GetUniqueBufferName(GetDirectory(set->buffer), "temp");
} }
set->view = WindowOpenBufferView(set->window, buffer_name); set->view = WindowOpenBufferView(set->window, buffer_name);
set->buffer = GetBuffer(set->view->active_buffer); set->buffer = GetBuffer(set->view->active_buffer);
@@ -41,7 +41,7 @@ UIAction WaitForUIAction(mco_coro *co, BSet main) {
return result; return result;
} }
UIAction ShowYesNoCancelUI(mco_coro *co, BSet main, String question) { UIAction QueryUserYesNoCancel(mco_coro *co, BSet main, String question) {
JumpTempBuffer(&main); JumpTempBuffer(&main);
NextActiveWindowID = main.window->id; NextActiveWindowID = main.window->id;
RawAppendf(main.buffer, R"==( RawAppendf(main.buffer, R"==(
@@ -72,11 +72,53 @@ void ShowUIMessagef(const char *fmt, ...) {
}); });
} }
void DetectUserFileCallback(Window *window, ResolvedOpen *resolved) {
if (resolved->kind == OpenKind_Goto) {
if (IsFile(resolved->path)) {
resolved->kind = OpenKind_Skip;
window->ui_query_file = Intern(&GlobalInternTable, resolved->path);
window->after_resolve_open_hook = NULL;
}
}
}
String16 QueryUserString(mco_coro *co, String ask) {
BSet main = GetBSet(PrimaryWindowID);
Buffer *original_buffer = main.buffer;
JumpTempBuffer(&main);
NextActiveWindowID = main.window->id;
RawAppendf(main.buffer, R"==(
(Enter) :Submit :Cancel (Escape)
%S
================================================
>)==", ask);
main.view->carets[0] = MakeCaret(GetBufferEnd(main.buffer));
AddUIAction(main.view, "Submit", EnterKey, UIAction_Yes);
AddUIAction(main.view, "Cancel", EscapeKey, UIAction_Cancel);
UIAction action = WaitForUIAction(co, main);
if (action != UIAction_Yes) {
return u"";
}
Caret a = FindNext(main.buffer, u">", MakeCaret(-1));
if (a.range.min == -1) {
ReportErrorf("You changed the format of the UI buffer, I was looking for the '>' but can't find it, can't proceed");
return u"";
}
a.range.min = a.range.max + 1;
a.range.max = GetBufferEnd(main.buffer);
return GetString(main.buffer, a.range);
}
String QueryUserFile(mco_coro *co) { String QueryUserFile(mco_coro *co) {
// @todo: how to make it so that it doesn't open the file?
#if PLUGIN_DIRECTORY_NAVIGATION #if PLUGIN_DIRECTORY_NAVIGATION
Open(GetPrimaryDirectory());
Window *window = GetWindow(PrimaryWindowID); Window *window = GetWindow(PrimaryWindowID);
ViewID original_view = window->active_view;
Open(GetPrimaryDirectory());
window->after_resolve_open_hook = DetectUserFileCallback;
String filename = ""; String filename = "";
for (;;) { for (;;) {
BSet main = GetBSet(window); BSet main = GetBSet(window);
@@ -84,25 +126,34 @@ String QueryUserFile(mco_coro *co) {
break; break;
} }
if (!main.buffer->is_dir) { if (window->after_resolve_open_hook == NULL) {
filename = main.buffer->name;
break; break;
} }
CoYield(co); CoYield(co);
} }
return filename; window->active_view = original_view;
return window->ui_query_file;
#else #else
// Just simple query String16 string16 = QueryUserString(co, "Please input the path to the desired file");
// @todo: do we want to split like this? The plugin is maybe leaking too much? String result = "";
// @todo: String QueryUserString(mco_coro *co) {
Scratch scratch;
String i = ToString(scratch, string16);
result = Intern(&GlobalInternTable, i);
}
return result;
#endif #endif
return "todo";
} }
void CO_TestQueryFile(mco_coro *co) { void CO_TestQueryFile(mco_coro *co) {
String file = QueryUserFile(co); //String file = QueryUserFile(co);
ReportConsolef("%S", file); String16 file16 = QueryUserString(co, "Input some kind of a string PLEASE!");
{
Scratch scratch;
String file = ToString(scratch, file16);
ReportConsolef("%S", file);
}
} RegisterCoroutineCommand(CO_TestQueryFile, "", ""); } RegisterCoroutineCommand(CO_TestQueryFile, "", "");
void MouseLoadWord(Event event, ResolveOpenMeta meta = ResolveOpenMeta_Normal) { void MouseLoadWord(Event event, ResolveOpenMeta meta = ResolveOpenMeta_Normal) {
@@ -124,68 +175,59 @@ void MouseLoadWord(Event event, ResolveOpenMeta meta = ResolveOpenMeta_Normal) {
} }
} }
ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) { ResolvedOpen ResolveOpen(Allocator alo, Window *window, String path, ResolveOpenMeta meta) {
ResolvedOpen result = {}; ResolvedOpen result = {};
path = Trim(path); path = Trim(path);
bool exec = !(ResolveOpenMeta_DontExec & meta);
// Editor command
if(!(ResolveOpenMeta_DontExec & meta)) {
if (StartsWith(path, ":")) {
#if PLUGIN_CONFIG #if PLUGIN_CONFIG
if (StartsWith(path, ":Set ")) { if (exec && result.kind == OpenKind_Invalid && StartsWith(path, ":Set ")) {
result.kind = OpenKind_Set; result.kind = OpenKind_Set;
result.path = Skip(path, 5); result.path = Skip(path, 5);
return result; }
}
#endif #endif
result.kind = OpenKind_Command; // :Command
path = Skip(path, 1); if (exec && result.kind == OpenKind_Invalid && StartsWith(path, ":")) {
result.path.data = path.data; result.kind = OpenKind_Command;
for (Int i = 0; i < path.len; i += 1) { path = Skip(path, 1);
if (IsNonWord(path.data[i])) { result.path.data = path.data;
break; for (Int i = 0; i < path.len; i += 1) {
} if (IsNonWord(path.data[i])) {
result.path.len += 1; break;
} }
return result; result.path.len += 1;
} }
} }
// Shell // !!exec_hidden
if (!(ResolveOpenMeta_DontExec & meta)) { if (exec && result.kind == OpenKind_Invalid && StartsWith(path, "!!")) {
if (StartsWith(path, "!!")) { result.kind = OpenKind_BackgroundExec;
result.kind = OpenKind_BackgroundExec; result.path = Skip(path, 2);
result.path = Skip(path, 2);
return result;
}
if (StartsWith(path, "!")) {
result.kind = OpenKind_Exec;
result.path = Skip(path, 1);
return result;
}
} }
// Web // !exec
if (!(ResolveOpenMeta_DontExec & meta)) { if (exec && result.kind == OpenKind_Invalid && StartsWith(path, "!")) {
if (StartsWith(path, "https://") || StartsWith(path, "http://")) { result.kind = OpenKind_Exec;
result.path = Format(alo, "%S %S", InternetBrowser, path); result.path = Skip(path, 1);
result.kind = OpenKind_BackgroundExec;
return result;
}
} }
// Commit // https://web
if (!(ResolveOpenMeta_DontExec & meta)) { bool web = StartsWith(path, "https://") || StartsWith(path, "http://");
if (StartsWith(path, "commit ")) { if (exec && result.kind == OpenKind_Invalid && web) {
path = Skip(path, 7); result.path = Format(alo, "%S %S", InternetBrowser, path);
result.path = Format(alo, "git --no-pager show %S", path); result.kind = OpenKind_BackgroundExec;
result.kind = OpenKind_Exec;
return result;
}
} }
{ // commit 3kc09as92
if (exec && result.kind == OpenKind_Invalid && StartsWith(path, "commit ")) {
path = Skip(path, 7);
result.path = Format(alo, "git --no-pager show %S", path);
result.kind = OpenKind_Exec;
}
// c:/filename:32:12
if (result.kind == OpenKind_Invalid) {
String p = NormalizePath(alo, path); String p = NormalizePath(alo, path);
if (p.len == 2 && IsAlphabetic(ToLowerCase(At(p, 0))) && At(p, 1) == ':') { if (p.len == 2 && IsAlphabetic(ToLowerCase(At(p, 0))) && At(p, 1) == ':') {
p = Format(alo, "%S/", p); p = Format(alo, "%S/", p);
@@ -225,34 +267,35 @@ ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) {
} }
Buffer *existing_buffer = GetBuffer(path, NULL); Buffer *existing_buffer = GetBuffer(path, NULL);
if (existing_buffer != NULL) { if (result.kind == OpenKind_Invalid && existing_buffer != NULL) {
result.path = path; result.path = path;
result.kind = OpenKind_Goto; result.kind = OpenKind_Goto;
result.existing_buffer = true; result.existing_buffer = true;
return result;
} }
if (is_absolute && FileExists(path)) { if (result.kind == OpenKind_Invalid && is_absolute && FileExists(path)) {
result.path = path; result.path = path;
result.kind = OpenKind_Goto; result.kind = OpenKind_Goto;
return result; }
} else {
String rel_path = Format(alo, "%S/%S", GetPrimaryDirectory(), path); if (result.kind == OpenKind_Invalid) {
String rel_path = Format(alo, "%S/%S", GetDirectory(window), path);
existing_buffer = GetBuffer(rel_path, NULL); existing_buffer = GetBuffer(rel_path, NULL);
if (existing_buffer || FileExists(rel_path)) { if (existing_buffer || FileExists(rel_path)) {
result.existing_buffer = existing_buffer; result.existing_buffer = existing_buffer;
result.path = rel_path; result.path = rel_path;
result.kind = OpenKind_Goto; result.kind = OpenKind_Goto;
return result;
} }
} }
} }
if (meta & ResolveOpenMeta_DontError) { if (result.kind == OpenKind_Invalid && (meta & ResolveOpenMeta_DontError)) {
result.path = path; result.path = path;
result.kind = OpenKind_Skip; result.kind = OpenKind_Skip;
return result; }
if (window->after_resolve_open_hook) {
window->after_resolve_open_hook(window, &result);
} }
return result; return result;
@@ -261,7 +304,7 @@ ResolvedOpen ResolveOpen(Allocator alo, String path, ResolveOpenMeta meta) {
BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = true) { BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = true) {
Scratch scratch; Scratch scratch;
BSet set = GetBSet(window); BSet set = GetBSet(window);
ResolvedOpen o = ResolveOpen(scratch, path, meta); ResolvedOpen o = ResolveOpen(scratch, window, path, meta);
if (o.kind == OpenKind_Goto) { if (o.kind == OpenKind_Goto) {
if (set_active) { if (set_active) {
NextActiveWindowID = set.window->id; NextActiveWindowID = set.window->id;
@@ -274,8 +317,8 @@ BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = t
} }
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
if (o.line != -1) { if (o.line != 0) {
if (o.col == -1) o.col = 1; if (o.col == 0) o.col = 1;
Int pos = XYToPos(buffer, {o.col - 1, o.line - 1}); Int pos = XYToPos(buffer, {o.col - 1, o.line - 1});
SelectRange(view, MakeCaret(pos)); SelectRange(view, MakeCaret(pos));
} }

View File

@@ -393,7 +393,12 @@ BSet GetBSet(WindowID window_id) {
String GetPrimaryDirectory() { String GetPrimaryDirectory() {
BSet main = GetBSet(PrimaryWindowID); BSet main = GetBSet(PrimaryWindowID);
return GetBufferDirectory(main.buffer); return GetDirectory(main.buffer);
}
String GetDirectory(Window *window) {
BSet main = GetBSet(PrimaryWindowID);
return GetDirectory(main.buffer);
} }
void MoveCursorByPageSize(Window *window, int direction, bool shift = false) { void MoveCursorByPageSize(Window *window, int direction, bool shift = false) {