Console update

This commit is contained in:
krzosa
2025-05-02 22:20:09 +02:00
parent 4871494c50
commit 93c1ba606a
8 changed files with 207 additions and 121 deletions

View File

@@ -90,7 +90,7 @@ void Command_ListBuffers() {
String result = Merge(scratch, strings, "\n");
String16 string16 = ToString16(scratch, result);
String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "+list_buffers-");
String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "buffer_list");
View *new_view = WindowOpenBufferView(main.window, buffer_name);
Buffer *new_buffer = GetBuffer(new_view->active_buffer);
new_buffer->gc = true;
@@ -133,29 +133,49 @@ void Command_ReplaceWithoutMovingCarets(View *view, Range range, String16 string
AdjustCarets(edits, &caret_copy);
}
// @todo: revamp interface since it scrolls ALL VIEWS??? or maybe not??
void Command_Append(View *view, String16 string, bool scroll_to_end_if_cursor_on_last_line) {
Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer);
bool scroll_to_end = false;
if (scroll_to_end_if_cursor_on_last_line) {
Int line = PosToLine(buffer, GetFront(view->carets[0]));
if (line == buffer->line_starts.len - 1) scroll_to_end = true;
}
Array<Caret> caret_copy = {};
if (!scroll_to_end) caret_copy = Copy(GetSystemAllocator(), view->carets);
defer {
if (!scroll_to_end) {
Dealloc(&view->carets);
view->carets = caret_copy;
}
struct ViewInfo {
View *view;
Array<Caret> carets;
bool scroll_to_end;
};
Array<ViewInfo> view_info = {scratch};
For (Views) {
View *it_view = GetView(it);
if (it_view->active_buffer != buffer->id) {
continue;
}
ViewInfo vi = {it_view};
if (scroll_to_end_if_cursor_on_last_line) {
Int line = PosToLine(buffer, GetFront(it_view->carets[0]));
if (line == buffer->line_starts.len - 1) {
vi.scroll_to_end = true;
}
}
if (!vi.scroll_to_end) {
vi.carets = Copy(GetSystemAllocator(), it_view->carets);
}
Add(&view_info, vi);
}
Command_SelectRangeOneCursor(view, GetEndAsRange(buffer));
Command_Replace(view, string);
if (scroll_to_end) {
view->carets[0] = MakeCaret(GetEndAsRange(buffer).min);
For (view_info) {
if (it.scroll_to_end) {
it.view->carets[0] = MakeCaret(GetEndAsRange(buffer).min);
} else {
Dealloc(&it.view->carets);
it.view->carets = it.carets;
}
}
}

View File

@@ -47,17 +47,64 @@ void Command_GetCFiles(void) {
BSet main = GetActiveMainSet();
Scratch scratch;
String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "+ls-");
String buffer_name = GetUniqueBufferName(GetDir(main.buffer), "getcfiles");
Buffer *buffer = CreateBuffer(GetSystemAllocator(), buffer_name, 4096 * 4);
ListFilesRecursive(buffer, Command_GetDir());
WindowOpenBufferView(main.window, buffer_name);
}
void UpdateScroll(Window *window, bool update_caret_scrolling) {
ProfileFunction();
BSet set = GetBSet(window);
// Scrolling with caret
if (update_caret_scrolling) {
Caret c = set.view->carets[0];
Int front = GetFront(c);
XY xy = PosToXY(set.buffer, front);
Rect2I visible = GetVisibleCells(window);
Vec2I visible_cells = GetSize(visible);
Vec2I visible_size = visible_cells * Vec2I{FontCharSpacing, FontLineSpacing};
Vec2I rect_size = GetSize(window->document_rect);
if (xy.line >= visible.max.y - 2) {
Int set_view_at_line = xy.line - (visible_cells.y - 1);
Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y);
set.view->scroll.y = (set_view_at_line * FontLineSpacing) + cut_off_y;
}
if (xy.line < visible.min.y + 1) {
set.view->scroll.y = xy.line * FontLineSpacing;
}
if (xy.col >= visible.max.x - 1) {
Int set_view_at_line = xy.col - (visible_cells.x - 1);
Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x);
set.view->scroll.x = (set_view_at_line * FontCharSpacing) + cut_off_x;
}
if (xy.col <= visible.min.x) {
set.view->scroll.x = xy.col * FontCharSpacing;
}
}
// Clip scroll
{
Int last_line = LastLine(set.buffer);
set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing));
// @note:
// GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for
// calculating this value incrementally but do we even need X scrollbar or x clipping?
set.view->scroll.x = ClampBottom(set.view->scroll.x, (Int)0);
}
}
static bool update_scroll_memes;
void OnCommand(Event event) {
ProfileFunction();
WindowID start_command_active_window = ActiveWindow;
//
// Window cursor setting
//
@@ -288,6 +335,12 @@ void OnCommand(Event event) {
}
}
if (CtrlPress(SDLK_GRAVE)) {
if (ActiveWindow != NullWindowID) {
ActiveWindow = NullWindowID;
// GetView(NullViewID);
}
}
if (CtrlPress(SDLK_P)) {
Command_ListBuffers();
}
@@ -330,6 +383,9 @@ void OnCommand(Event event) {
void CallOnCommand(Event * event);
CallOnCommand(&event);
if (event.kind == EVENT_DROP_FILE) {
WindowOpenBufferView(active.window, event.text);
}
@@ -562,51 +618,3 @@ void OnCommand(Event event) {
MergeCarets(active.buffer, &active.view->carets);
IF_DEBUG(AssertRanges(active.view->carets));
}
void UpdateScroll(Window *window, bool update_caret_scrolling) {
ProfileFunction();
BSet set = GetBSet(window);
// Scrolling with caret
if (update_caret_scrolling) {
Caret c = set.view->carets[0];
Int front = GetFront(c);
XY xy = PosToXY(set.buffer, front);
Rect2I visible = GetVisibleCells(window);
Vec2I visible_cells = GetSize(visible);
Vec2I visible_size = visible_cells * Vec2I{FontCharSpacing, FontLineSpacing};
Vec2I rect_size = GetSize(window->document_rect);
if (xy.line >= visible.max.y - 2) {
Int set_view_at_line = xy.line - (visible_cells.y - 1);
Int cut_off_y = Max((Int)0, visible_size.y - rect_size.y);
set.view->scroll.y = (set_view_at_line * FontLineSpacing) + cut_off_y;
}
if (xy.line < visible.min.y + 1) {
set.view->scroll.y = xy.line * FontLineSpacing;
}
if (xy.col >= visible.max.x - 1) {
Int set_view_at_line = xy.col - (visible_cells.x - 1);
Int cut_off_x = Max((Int)0, visible_size.x - rect_size.x);
set.view->scroll.x = (set_view_at_line * FontCharSpacing) + cut_off_x;
}
if (xy.col <= visible.min.x) {
set.view->scroll.x = xy.col * FontCharSpacing;
}
}
// Clip scroll
{
Int last_line = LastLine(set.buffer);
set.view->scroll.y = Clamp(set.view->scroll.y, (Int)0, Max((Int)0, (last_line - 1) * FontLineSpacing));
// @note:
// GetCharCountOfLongestLine is a bottleneck, there is probably an algorithm for
// calculating this value incrementally but do we even need X scrollbar or x clipping?
set.view->scroll.x = ClampBottom(set.view->scroll.x, (Int)0);
}
}

View File

@@ -18,7 +18,7 @@ void Command_ExecInNewBuffer(BSet set, String cmd, String working_dir) {
CheckpointBeforeGoto(set.window);
Scratch scratch;
String buffer_name = GetUniqueBufferName(working_dir, "+cmd-");
String buffer_name = GetUniqueBufferName(working_dir, "shell_command");
View *view = WindowOpenBufferView(set.window, buffer_name);
Buffer *buffer = GetBuffer(view->active_buffer);
@@ -38,28 +38,28 @@ View *Command_ExecHidden(String buffer_name, String cmd, String working_dir) {
return view;
}
BSet Command_BeginConsoleJump() {
BSet main = GetActiveMainSet();
CheckpointBeforeGoto(main.window);
main.buffer = GetBuffer(NullBufferID);
main.view = WindowOpenBufferView(main.window, main.buffer->name);
return main;
void Command_BeginConsoleJump(BSet *set) {
CheckpointBeforeGoto(set->window);
set->buffer = GetBuffer(NullBufferID);
set->view = WindowOpenBufferView(set->window, set->buffer->name);
}
void Command_EndConsoleJump(BSet main) {
Int pos = XYToPos(main.buffer, {0, main.buffer->line_starts.len - 1});
main.view->carets[0] = MakeCaret(pos);
UpdateScroll(main.window, true);
ActiveWindow = main.window->id;
void Command_EndConsoleJump(BSet set) {
Int pos = XYToPos(set.buffer, {0, set.buffer->line_starts.len - 1});
set.view->carets[0] = MakeCaret(pos);
UpdateScroll(set.window, true);
}
void Command_Exec(String cmd, String working_dir) {
BSet set = Command_BeginConsoleJump();
BSet Command_Exec(String cmd, String working_dir) {
BSet set = GetActiveMainSet();
Command_BeginConsoleJump(&set);
Exec(set.view->id, true, cmd, working_dir);
Command_EndConsoleJump(set);
ActiveWindow = set.window->id;
return set;
}
void Command_Open(String path) {
BSet Command_Open(String path) {
Scratch scratch;
lua_getglobal(LuaState, "ApplyRules");
@@ -68,7 +68,7 @@ void Command_Open(String path) {
const char *error_message = lua_tostring(LuaState, -1);
ReportWarningf("Failed the call to ApplyRules! %s", error_message);
lua_pop(LuaState, 1);
return;
return {};
}
BSet main = GetActiveMainSet();
@@ -81,12 +81,13 @@ void Command_Open(String path) {
Int col = strtoll(col_string.data, NULL, 10);
if (IsDir(file_path)) {
BSet set = Command_BeginConsoleJump();
Command_Appendf(set.view, "%.*s..\n", FmtString(file_path));
Command_BeginConsoleJump(&main);
Command_Appendf(main.view, "%.*s/..\n", FmtString(file_path));
for (FileIter it = IterateFiles(scratch, file_path); IsValid(it); Advance(&it)) {
Command_Appendf(set.view, "%.*s\n", FmtString(it.absolute_path));
Command_Appendf(main.view, "%.*s\n", FmtString(it.absolute_path));
}
Command_EndConsoleJump(set);
Command_EndConsoleJump(main);
ActiveWindow = main.window->id;
} else {
CheckpointBeforeGoto(main.window);
View *view = WindowOpenBufferView(main.window, file_path);
@@ -110,6 +111,8 @@ void Command_Open(String path) {
} else {
ReportWarningf("Failed to match any of ApplyRules results!");
}
return main;
}
void Command_Open(String16 path) {
@@ -174,19 +177,19 @@ int Lua_Cmd(lua_State *L) {
String destination = lua_tostring(L, -1);
lua_pop(L, 1);
BSet active = GetActiveMainSet();
BSet set = {};
if (destination == "next") {
Window *next_window = GetNextLayoutWindow(active.window);
set = GetBSet(next_window);
} else if (destination == "3") {
Window *next_window = GetLayoutWindow(2);
if (!next_window) next_window = active.window;
set = GetBSet(next_window);
if (destination == "console") {
set = GetConsoleSet();
} else {
set = active;
set = GetActiveMainSet();
}
Command_BeginConsoleJump(&set);
Exec(set.view->id, true, cmd, working_dir);
Command_EndConsoleJump(set);
if (destination != "console") {
ActiveWindow = set.window->id;
}
Command_ExecInNewBuffer(set, cmd, working_dir);
return 0;
}
@@ -245,9 +248,8 @@ int Lua_Open(lua_State *L) {
}
int Lua_SetProjectFile(lua_State *L) {
String name = luaL_checkstring(L, 1);
lua_pop(L, 1);
LuaProjectBuffer = BufferOpenFile(name);
BSet set = GetActiveMainSet();
LuaProjectBuffer = set.buffer;
LuaProjectBuffer->user_change_id = -1;
return 0;
}
@@ -272,7 +274,6 @@ int Lua_GetBufferList(lua_State *L) {
int i = 1;
For(Buffers) {
if (StartsWith(it.o->name, "+titlebar")) continue;
lua_pushinteger(L, i++);
lua_pushlstring(L, it.o->name.data, it.o->name.len);
lua_settable(L, -3); /* 3rd element from the stack top */

View File

@@ -8,11 +8,15 @@ Array<WindowID> Windows;
BufferID NullBufferID; // +buffer
ViewID NullViewID;
WindowID NullWindowID;
Int NullWindowSize = 5;
WindowID DebugWindowID; // +debug
BufferID DebugBufferID;
WindowID ActiveWindow;
WindowID ActiveWindowCounterID;
Int ActiveWindowCounter;
WindowID ScrollbarSelected = {-1};
WindowID DocumentSelected = {-1};
@@ -22,6 +26,7 @@ Buffer *LuaProjectBuffer;
Buffer *LuaConfigBuffer;
Buffer *GCInfoBuffer;
Buffer *EventBuffer;
Buffer *ScratchBuffer;
RandomSeed UniqueBufferNameSeed = {};
String GetUniqueBufferName(String working_dir, String prepend_name) {
@@ -44,7 +49,9 @@ void InitScratchBuffer() {
GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "gc"));
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "events"));
ScratchBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "scratch"));
EventBuffer->no_history = true;
GCInfoBuffer->no_history = true;
}
inline bool IsDocumentSelectionValid() {
@@ -231,6 +238,14 @@ BSet GetActiveMainSet() {
return GetBSet(window);
}
BSet GetConsoleSet() {
BSet result = {};
result.window = GetWindow(NullWindowID);
result.view = GetView(NullViewID);
result.buffer = GetBuffer(NullBufferID);
return result;
}
BSet GetActiveTitleSet() {
Window *window = GetWindow(ActiveWindow);
if (!window->is_title_bar) window = GetWindow(window->title_bar_window);
@@ -338,13 +353,7 @@ Buffer *BufferOpenFile(String path) {
if (!FileExists(path)) {
buffer = CreateBuffer(sys_allocator, path);
} else if (IsDir(path)) {
String buffer_name = GetUniqueBufferName(path, "+dir-");
buffer = CreateBuffer(sys_allocator, buffer_name, 4096 * 2);
RawAppendf(buffer, "..\n");
for (FileIter it = IterateFiles(scratch, path); IsValid(it); Advance(&it)) {
RawAppendf(buffer, "%.*s\n", FmtString(it.filename));
}
Assert(!"Invalid codepath");
} else {
String string = ReadFile(scratch, path);
buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096);

View File

@@ -67,6 +67,7 @@ void FillEventWithBasicData(Event *event) {
SDL_GetWindowSize(SDLWindow, &xwindow, &ywindow);
event->xwindow = xwindow;
event->ywindow = ywindow;
event->text = "";
}
Event TranslateSDLEvent(SDL_Event *input_event) {
@@ -220,11 +221,14 @@ Array<Event> GetEventsForFrame(Allocator allocator) {
}
void Windows_SetupVCVarsall(mco_coro *co) {
Scratch scratch;
String working_dir = Command_GetDir();
String buffer_name = GetUniqueBufferName(working_dir, "+cmd-");
String cmd = Format(scratch, "\"%.*s\" && set", FmtString(StyleVCVarsall));
View *view = Command_ExecHidden(buffer_name, cmd, working_dir);
View *view = NULL;
{
Scratch scratch;
String working_dir = Command_GetDir();
String buffer_name = GetUniqueBufferName(working_dir, "+cmd-");
String cmd = Format(scratch, "\"%.*s\" && set", FmtString(StyleVCVarsall));
view = Command_ExecHidden(buffer_name, cmd, working_dir);
}
for (;;) {
if (!ProcessIsActive(view->id)) {
break;
@@ -232,6 +236,7 @@ void Windows_SetupVCVarsall(mco_coro *co) {
Yield(co);
}
Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer);
String16 string16 = GetString(buffer);
String string = ToString(scratch, string16);

View File

@@ -82,7 +82,7 @@ float DPIScale = 1.0f;
Rect2I GetVisibleCells(Window *window);
void AfterEdit(View *view, Array<Edit> edits);
Scroller ComputeScrollerRect(Window *window);
void Command_Open(String path);
BSet Command_Open(String path);
void Command_Open(String16 path);
void UpdateScroll(Window *window, bool update_caret_scrolling);

View File

@@ -1,5 +1,8 @@
!!As little lua code as possible, but lua code should be powerful just in case of quick edits
- maybe we could allow user to change window titles which would make them special in some way. A:/text_editor/+test_buffer:1:1:ADE |
- Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
- Fix B: not opening
- Scroll the console properly
--------------
buffer = make_buffer()
@@ -7,6 +10,7 @@ buffer.append(list_files("src/basic"))
activate_buffer
--------------
- shift down on last line should move the cursor to end of line!!! same for up
- maybe most of the bindings should be in lua, but actual code in C
- LoadWord, EncloseWord configurable?
- dump text editor state to file, restore state

View File

@@ -109,7 +109,7 @@ Int GetTitleBarSize(Window *window) {
void AddColumnWindow() {
Window *window = CreateWindow();
window->is_column = true;
View *view = OpenBufferView("+scratch");
View *view = OpenBufferView(ScratchBuffer->name);
window->active_view = view->id;
CreateTitlebar(window->id);
CreateSearchBar(window->id);
@@ -127,7 +127,7 @@ Int GetWindowIndex(WindowID window_id) {
void AddRowWindow() {
Window *active_window = GetActiveWindow();
Window *window = CreateWindow();
View *view = OpenBufferView("+scratch");
View *view = OpenBufferView(ScratchBuffer->name);
window->active_view = view->id;
CreateTitlebar(window->id);
CreateSearchBar(window->id);
@@ -213,8 +213,20 @@ void InitWindows() {
Reserve(&Views, 256);
#endif
{
Window *window = CreateWindow();
window->active_view = NullViewID;
Assert(NullWindowID.id == 0);
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID id = window->id;
CreateTitlebar(id);
CreateSearchBar(id);
}
{
Window *window = CreateWindow();
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID window_id = window->id;
window->is_column = true;
Buffer *buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkingDir, "test_buffer"));
@@ -223,10 +235,14 @@ void InitWindows() {
window->active_view = view->id;
CreateTitlebar(window_id);
CreateSearchBar(window->id);
ActiveWindow = ActiveWindowCounterID = window_id;
}
{
Window *window = CreateWindow();
// @todo - Windows, Buffers, Views should not be in a dynamic list it risks memory errors. Should be instead in a Double linked list, any freeing should happen at GC stage
WindowID window_id = window->id;
DebugWindowID = window->id;
window->draw_line_numbers = false;
@@ -249,20 +265,43 @@ void InitWindows() {
SetVisibility(window_id, false);
}
ActiveWindow = {0};
}
void
LayoutWindows(int16_t wx, int16_t wy) {
void LayoutWindows(int16_t wx, int16_t wy) {
float ScrollBarSize = (10.f * DPIScale);
Rect2I screen_rect = RectI0Size(wx, wy);
float line_numbers_size = (float)FontCharSpacing * 10;
float sizex = (float)GetSize(screen_rect).x;
{
Window *window = GetWindow(NullWindowID);
if (ActiveWindow == window->id) {
NullWindowSize = 20;
} else {
NullWindowSize = 5;
}
Rect2I rect = CutBottom(&screen_rect, FontLineSpacing*NullWindowSize);
Window *title_bar_window = GetWindow(window->title_bar_window);
title_bar_window->total_rect = CutBottom(&window->total_rect, GetTitleBarSize(title_bar_window));
title_bar_window->document_rect = title_bar_window->total_rect;
Rect2I save_rect = window->document_rect;
CutLeft(&save_rect, GetSize(save_rect).x/2);
Window *search_bar_window = GetWindow(window->search_bar_window);
search_bar_window->total_rect = CutTop(&save_rect, GetTitleBarSize(search_bar_window));
search_bar_window->document_rect = search_bar_window->total_rect;
window->document_rect = window->total_rect;
if (window->draw_scrollbar) window->scrollbar_rect = CutRight(&window->document_rect, (Int)ScrollBarSize);
if (window->draw_line_numbers) window->line_numbers_rect = CutLeft(&window->document_rect, (Int)line_numbers_size);
window->total_rect = rect;
}
Scratch scratch;
Array<VisualColumn> columns = GetVisualColumns(scratch);
float delta_column = 1.0f / (float)columns.len;
ForItem(col, columns) {
Int add = 0;