Compare commits
2 Commits
32efabac6a
...
6243cace7d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6243cace7d | ||
|
|
3ba7eeb1f2 |
@@ -1,8 +1,9 @@
|
||||
- What precise workflow do I need for me to be viable to use this?
|
||||
- From a user (novice) point of view, how does it look like?
|
||||
|
||||
- "DO YOU REALLY WANT TO QUIT?" popup
|
||||
- open all in the folder and ctrl + p like in VSCode (without special buffers)
|
||||
- Close all (ask to save)
|
||||
- Close buffer instead of window (ask to save)
|
||||
- Open all in the folder and ctrl + p like in VSCode (without special buffers)
|
||||
- Guide on the first page for new users with links to configs, tutorials
|
||||
|
||||
- Window, View, Buffer + flags design (or is completely new kind based approach needed for Windows/Views?)
|
||||
|
||||
@@ -1460,21 +1460,22 @@ String GetUniqueBufferName(String working_dir, String prepend_name, String exten
|
||||
void InitBuffers() {
|
||||
Allocator sys_allocator = GetSystemAllocator();
|
||||
Scratch scratch;
|
||||
Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console"));
|
||||
null_buffer->dont_warn_on_save = true;
|
||||
Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console"));
|
||||
null_buffer->special = true;
|
||||
View *null_view = CreateView(null_buffer->id);
|
||||
null_view->special = true;
|
||||
Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID);
|
||||
TraceBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "trace"));
|
||||
TraceBuffer->dont_warn_on_save = true;
|
||||
TraceBuffer->special = true;
|
||||
TraceView = CreateView(TraceBuffer->id);
|
||||
GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "gc"));
|
||||
GCInfoBuffer->dont_warn_on_save = true;
|
||||
GCInfoBuffer->special = true;
|
||||
GCInfoBuffer->no_history = true;
|
||||
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events"));
|
||||
EventBuffer->dont_warn_on_save = true;
|
||||
EventBuffer->no_history = true;
|
||||
EventBuffer->special = true;
|
||||
ScratchBuffer = BufferOpenFile(GetUniqueBufferName(WorkDir, "scratch"));
|
||||
ScratchBuffer->dont_warn_on_save = true;
|
||||
ScratchBuffer->special = true;
|
||||
}
|
||||
|
||||
Int ConvertUTF8ToUTF16UnixLine(String string, char16_t *buffer, Int buffer_cap) {
|
||||
@@ -1577,3 +1578,17 @@ void ReopenBuffer(Buffer *buffer) {
|
||||
buffer->changed_on_disk = false;
|
||||
buffer->dirty = false;
|
||||
}
|
||||
|
||||
void SaveBuffer(Buffer *buffer) {
|
||||
Scratch scratch;
|
||||
String string = AllocCharString(scratch, buffer);
|
||||
bool success = WriteFile(buffer->name, string);
|
||||
|
||||
if (success) {
|
||||
buffer->file_mod_time = GetFileModTime(buffer->name);
|
||||
buffer->dirty = false;
|
||||
buffer->garbage = false;
|
||||
} else {
|
||||
ReportWarningf("Failed to save file with name: %S", buffer->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,9 @@ struct Buffer {
|
||||
unsigned dirty : 1;
|
||||
unsigned changed_on_disk : 1;
|
||||
unsigned garbage : 1;
|
||||
unsigned dont_warn_on_save : 1;
|
||||
unsigned dont_try_to_save_in_bulk_ops : 1;
|
||||
unsigned kill : 1;
|
||||
unsigned special : 1;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -193,11 +193,20 @@ bool YesNoMessageBox(const char *title, const char *msg) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int SaveMessageBox(const char *title, const char *msg) {
|
||||
enum SaveResult {
|
||||
SAVE_CANCEL,
|
||||
SAVE_NO,
|
||||
SAVE_YES,
|
||||
};
|
||||
|
||||
SaveResult SaveMessageBox(String filename) {
|
||||
Scratch scratch;
|
||||
const char *title = "There are unsaved changes, do you really want to quit?";
|
||||
const char *msg = Format(scratch, "Do you really want to quit? Unsaved buffer: %S", filename).data;
|
||||
SDL_MessageBoxButtonData buttons[] = {
|
||||
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 2, "Save" },
|
||||
{ 0, 1, "Don't save" },
|
||||
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "Cancel" },
|
||||
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, SAVE_YES, "Save" },
|
||||
{ 0, SAVE_NO, "Don't save" },
|
||||
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, SAVE_CANCEL, "Cancel" },
|
||||
};
|
||||
SDL_MessageBoxData data = {};
|
||||
data.flags = SDL_MESSAGEBOX_WARNING;
|
||||
@@ -208,7 +217,7 @@ int SaveMessageBox(const char *title, const char *msg) {
|
||||
int resp;
|
||||
bool status = SDL_ShowMessageBox(&data, &resp);
|
||||
Assert(status);
|
||||
return resp;
|
||||
return (SaveResult)resp;
|
||||
}
|
||||
|
||||
void ReportErrorf(const char *fmt, ...) {
|
||||
@@ -345,52 +354,6 @@ void ApplyClangFormat(Buffer *buffer) {
|
||||
ReplaceWithoutMovingCarets(buffer, GetRange(buffer), {temp_buffer->str, temp_buffer->len});
|
||||
}
|
||||
|
||||
void SaveBuffer(Buffer *buffer) {
|
||||
Scratch scratch;
|
||||
String string = AllocCharString(scratch, buffer);
|
||||
bool success = WriteFile(buffer->name, string);
|
||||
|
||||
if (success) {
|
||||
buffer->file_mod_time = GetFileModTime(buffer->name);
|
||||
buffer->dirty = false;
|
||||
buffer->garbage = false;
|
||||
} else {
|
||||
ReportWarningf("Failed to save file with name: %S", buffer->name);
|
||||
}
|
||||
}
|
||||
|
||||
void KillSelectedLines(View *view) {
|
||||
Scratch scratch;
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
SaveCaretHistoryBeforeBeginEdit(buffer, view->carets);
|
||||
|
||||
For (view->carets) {
|
||||
Int eof = 0;
|
||||
it.range.max = GetFullLineEnd(buffer, it.range.max, &eof);
|
||||
it.range.min = GetFullLineStart(buffer, it.range.min);
|
||||
it.range.min -= Clamp(eof, (Int)0, buffer->len);
|
||||
}
|
||||
Replace(view, u"");
|
||||
}
|
||||
|
||||
void EncloseLine(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
For (view->carets) {
|
||||
Int eof = 0;
|
||||
it.range.max = GetFullLineEnd(buffer, it.range.max, &eof);
|
||||
it.range.min = GetFullLineStart(buffer, it.range.min);
|
||||
}
|
||||
}
|
||||
|
||||
void EncloseScope(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
For (view->carets) {
|
||||
it.range = EncloseScope(buffer, it.range.min - 1, it.range.max + 1, u'(', u')');
|
||||
it.range.min = Clamp(buffer, it.range.min + 1);
|
||||
it.range.max = Clamp(buffer, it.range.max - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GotoNextInList(Window *window, Int line_offset = 1) {
|
||||
Assert(line_offset == 1 || line_offset == -1);
|
||||
View *active_view = GetView(window->active_view);
|
||||
@@ -490,7 +453,7 @@ void ListFilesRecursive(Buffer *buffer, String dir) {
|
||||
View *ExecHidden(String buffer_name, String cmd, String working_dir) {
|
||||
View *view = OpenBufferView(buffer_name);
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
buffer->dont_warn_on_save = true;
|
||||
buffer->dont_try_to_save_in_bulk_ops = true;
|
||||
Exec(view->id, true, cmd, working_dir);
|
||||
return view;
|
||||
}
|
||||
@@ -710,10 +673,90 @@ void Command_KillProcess() {
|
||||
KillProcess(main.view);
|
||||
} RegisterCommand(Command_KillProcess, "");
|
||||
|
||||
void Command_KillWindow() {
|
||||
void Command_CloseWindow() {
|
||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||
main.window->kill = true;
|
||||
} RegisterCommand(Command_KillWindow, "ctrl-w");
|
||||
} RegisterCommand(Command_CloseWindow, "");
|
||||
|
||||
SaveResult TrySavingBuffer(Buffer *buffer) {
|
||||
if (buffer->dirty) {
|
||||
SaveResult save = SaveMessageBox(buffer->name);
|
||||
if (save == SAVE_CANCEL) {
|
||||
return SAVE_CANCEL;
|
||||
} else if (save == SAVE_YES) {
|
||||
SaveBuffer(buffer);
|
||||
return SAVE_YES;
|
||||
} else {
|
||||
return SAVE_NO;
|
||||
}
|
||||
}
|
||||
return SAVE_YES;
|
||||
}
|
||||
|
||||
SaveResult TrySavingAllBuffers() {
|
||||
For (Buffers) {
|
||||
if (it->garbage || it->special || it->dont_try_to_save_in_bulk_ops) {
|
||||
continue;
|
||||
}
|
||||
if (it->dirty) {
|
||||
SaveResult save = SaveMessageBox(it->name);
|
||||
if (save == SAVE_CANCEL) {
|
||||
return SAVE_CANCEL;
|
||||
} else if (save == SAVE_YES) {
|
||||
SaveBuffer(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SAVE_YES;
|
||||
}
|
||||
|
||||
void Command_Close() {
|
||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||
if (TrySavingBuffer(main.buffer) == SAVE_CANCEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
main.window->active_view = FindInactiveView();
|
||||
main.view->kill = true;
|
||||
|
||||
bool ref = false;
|
||||
For (Views) {
|
||||
if (it->id == main.view->id) {
|
||||
continue;
|
||||
}
|
||||
if (it->active_buffer == main.buffer->id) {
|
||||
ref = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ref) {
|
||||
main.buffer->kill = true;
|
||||
}
|
||||
} RegisterCommand(Command_Close, "ctrl-w");
|
||||
|
||||
void Command_Quit() {
|
||||
if (TrySavingAllBuffers() != SAVE_CANCEL) {
|
||||
AppIsRunning = false;
|
||||
}
|
||||
} RegisterCommand(Command_Quit, "");
|
||||
|
||||
void Command_CloseAll() {
|
||||
if (TrySavingAllBuffers() != SAVE_CANCEL) {
|
||||
For (Views) {
|
||||
if (it->special) {
|
||||
continue;
|
||||
}
|
||||
it->kill = true;
|
||||
}
|
||||
For (Buffers) {
|
||||
if (it->special) {
|
||||
continue;
|
||||
}
|
||||
it->kill = true;
|
||||
}
|
||||
}
|
||||
} RegisterCommand(Command_CloseAll, "");
|
||||
|
||||
void Command_GotoBackward() {
|
||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||
@@ -1032,6 +1075,10 @@ void Command_FocusWindow3() {
|
||||
}
|
||||
} RegisterCommand(Command_FocusWindow3, "ctrl-3");
|
||||
|
||||
void Command_NewWindow() {
|
||||
CreateWind();
|
||||
} RegisterCommand(Command_NewWindow, "ctrl-backslash");
|
||||
|
||||
void Command_ClearCarets() {
|
||||
BSet active = GetBSet(ActiveWindowID);
|
||||
active.view->carets.len = 1;
|
||||
|
||||
@@ -410,27 +410,7 @@ void OnCommand(Event event) {
|
||||
}
|
||||
|
||||
if (event.kind == EVENT_QUIT) {
|
||||
Scratch scratch;
|
||||
bool do_quit = true;
|
||||
For (Buffers) {
|
||||
if (it->garbage || it->dont_warn_on_save) {
|
||||
continue;
|
||||
}
|
||||
if (it->dirty) {
|
||||
String message = Format(scratch, "Do you really want to quit? Unsaved buffer: %S", it->name);
|
||||
int save = SaveMessageBox("There are unsaved changes, do you really want to quit!", message.data);
|
||||
if (save == 0) {
|
||||
break;
|
||||
}
|
||||
if (save == 2) {
|
||||
SaveBuffer(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_quit) {
|
||||
AppIsRunning = false;
|
||||
}
|
||||
Command_Quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,15 +452,18 @@ void GarbageCollect() {
|
||||
IterRemovePrepare(Views);
|
||||
|
||||
Buffer *buffer = GetBuffer(it->active_buffer);
|
||||
if (!buffer->garbage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ref = ViewIsReferenced(it->id);
|
||||
if (ref) {
|
||||
continue;
|
||||
if (it->kill == 0) {
|
||||
if (!buffer->garbage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ref = ViewIsReferenced(it->id);
|
||||
if (ref) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RawAppendf(GCInfoBuffer, "View %d %S\n", (int)it->id.id, buffer->name);
|
||||
remove_item = true;
|
||||
Dealloc(&it->carets);
|
||||
Dealloc(sys_allocator, it);
|
||||
@@ -489,15 +472,24 @@ void GarbageCollect() {
|
||||
IterRemove(Buffers) {
|
||||
IterRemovePrepare(Buffers);
|
||||
|
||||
if (!it->garbage) {
|
||||
|
||||
if (it->id.id == 0) {
|
||||
it->kill = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ref = BufferIsReferenced(it->id);
|
||||
if (ref) {
|
||||
continue;
|
||||
if (it->kill == 0) {
|
||||
if (!it->garbage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ref = BufferIsReferenced(it->id);
|
||||
if (ref) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RawAppendf(GCInfoBuffer, "Buff %d %S\n", (int)it->id.id, it->name);
|
||||
remove_item = true;
|
||||
DeallocBuffer(it);
|
||||
}
|
||||
@@ -505,6 +497,7 @@ void GarbageCollect() {
|
||||
IterRemove(Windows) {
|
||||
IterRemovePrepare(Windows);
|
||||
if (it->kill) {
|
||||
RawAppendf(GCInfoBuffer, "Wind %d %S\n", (int)it->id.id);
|
||||
Dealloc(&it->goto_history);
|
||||
Dealloc(&it->goto_redo);
|
||||
Dealloc(sys_allocator, it);
|
||||
|
||||
@@ -59,6 +59,15 @@ API bool ViewIsCrumb(ViewID view_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewIsActive(ViewID id) {
|
||||
For (Windows) {
|
||||
if (it->active_view == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
API bool ViewIsReferenced(ViewID view) {
|
||||
if (view == NullViewID) {
|
||||
return true;
|
||||
@@ -68,12 +77,14 @@ API bool ViewIsReferenced(ViewID view) {
|
||||
return true;
|
||||
}
|
||||
|
||||
For(Windows) {
|
||||
if (it->active_view == view) {
|
||||
return true;
|
||||
}
|
||||
return ViewIsActive(view);
|
||||
}
|
||||
|
||||
ViewID FindInactiveView(ViewID default_view = NullViewID) {
|
||||
For (Views) {
|
||||
if (!ViewIsActive(it->id)) return it->id;
|
||||
}
|
||||
return false;
|
||||
return default_view;
|
||||
}
|
||||
|
||||
String16 FetchLoadWord(View *view) {
|
||||
@@ -566,3 +577,35 @@ void DuplicateLine(View *view, int direction) {
|
||||
caret->range.max = XYToPos(buffer, xymax);
|
||||
}
|
||||
}
|
||||
|
||||
void KillSelectedLines(View *view) {
|
||||
Scratch scratch;
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
SaveCaretHistoryBeforeBeginEdit(buffer, view->carets);
|
||||
|
||||
For (view->carets) {
|
||||
Int eof = 0;
|
||||
it.range.max = GetFullLineEnd(buffer, it.range.max, &eof);
|
||||
it.range.min = GetFullLineStart(buffer, it.range.min);
|
||||
it.range.min -= Clamp(eof, (Int)0, buffer->len);
|
||||
}
|
||||
Replace(view, u"");
|
||||
}
|
||||
|
||||
void EncloseLine(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
For (view->carets) {
|
||||
Int eof = 0;
|
||||
it.range.max = GetFullLineEnd(buffer, it.range.max, &eof);
|
||||
it.range.min = GetFullLineStart(buffer, it.range.min);
|
||||
}
|
||||
}
|
||||
|
||||
void EncloseScope(View *view) {
|
||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||
For (view->carets) {
|
||||
it.range = EncloseScope(buffer, it.range.min - 1, it.range.max + 1, u'(', u')');
|
||||
it.range.min = Clamp(buffer, it.range.min + 1);
|
||||
it.range.max = Clamp(buffer, it.range.max - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ struct View {
|
||||
bool update_scroll;
|
||||
|
||||
String16 prev_search_line;
|
||||
struct {
|
||||
unsigned kill : 1;
|
||||
unsigned special : 1;
|
||||
};
|
||||
};
|
||||
|
||||
struct GotoCrumb {
|
||||
|
||||
@@ -2,8 +2,9 @@ void CommandWindowInit() {
|
||||
Window *window = CreateWind();
|
||||
CommandBarWindowID = window->id;
|
||||
Buffer *buffer = CreateBuffer(SysAllocator, "command_bar");
|
||||
buffer->dont_warn_on_save = true;
|
||||
buffer->special = true;
|
||||
View *view = CreateView(buffer->id);
|
||||
view->special = true;
|
||||
window->active_view = view->id;
|
||||
window->draw_line_numbers = false;
|
||||
window->draw_scrollbar = false;
|
||||
|
||||
@@ -9,11 +9,12 @@ void DebugWindowInit() {
|
||||
|
||||
Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "debug"));
|
||||
DebugBufferID = buffer->id;
|
||||
buffer->dont_warn_on_save = true;
|
||||
buffer->no_history = true;
|
||||
buffer->special = true;
|
||||
|
||||
View *view = CreateView(buffer->id);
|
||||
DebugViewID = view->id;
|
||||
View *view = CreateView(buffer->id);
|
||||
view->special = true;
|
||||
DebugViewID = view->id;
|
||||
window->active_view = view->id;
|
||||
window->visible = false;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ void SearchWindowInit() {
|
||||
Window *window = CreateWind();
|
||||
SearchBarWindowID = window->id;
|
||||
Buffer *buffer = CreateBuffer(SysAllocator, "search_bar");
|
||||
buffer->dont_warn_on_save = true;
|
||||
buffer->special = true;
|
||||
SearchBufferID = buffer->id;
|
||||
View *view = CreateView(buffer->id);
|
||||
view->special = true;
|
||||
SearchViewID = view->id;
|
||||
window->active_view = view->id;
|
||||
window->draw_line_numbers = false;
|
||||
|
||||
@@ -2,8 +2,9 @@ void StatusWindowInit() {
|
||||
Window *window = CreateWind();
|
||||
StatusBarWindowID = window->id;
|
||||
Buffer *buffer = CreateBuffer(SysAllocator, "status_bar");
|
||||
buffer->dont_warn_on_save = true;
|
||||
buffer->special = true;
|
||||
View *view = CreateView(buffer->id);
|
||||
view->special = true;
|
||||
window->active_view = view->id;
|
||||
window->font = &SecondaryFont;
|
||||
window->draw_line_numbers = false;
|
||||
|
||||
Reference in New Issue
Block a user