Command_Close
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
- What precise workflow do I need for me to be viable to use this?
|
- 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?
|
- From a user (novice) point of view, how does it look like?
|
||||||
|
|
||||||
- "DO YOU REALLY WANT TO QUIT?" popup
|
- Close all (ask to save)
|
||||||
- open all in the folder and ctrl + p like in VSCode (without special buffers)
|
- 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
|
- 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?)
|
- Window, View, Buffer + flags design (or is completely new kind based approach needed for Windows/Views?)
|
||||||
|
|||||||
@@ -1577,3 +1577,17 @@ void ReopenBuffer(Buffer *buffer) {
|
|||||||
buffer->changed_on_disk = false;
|
buffer->changed_on_disk = false;
|
||||||
buffer->dirty = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ struct Buffer {
|
|||||||
unsigned changed_on_disk : 1;
|
unsigned changed_on_disk : 1;
|
||||||
unsigned garbage : 1;
|
unsigned garbage : 1;
|
||||||
unsigned dont_warn_on_save : 1;
|
unsigned dont_warn_on_save : 1;
|
||||||
|
unsigned kill : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,10 @@ bool YesNoMessageBox(const char *title, const char *msg) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SaveMessageBox(const char *title, const char *msg) {
|
int 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_MessageBoxButtonData buttons[] = {
|
||||||
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 2, "Save" },
|
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 2, "Save" },
|
||||||
{ 0, 1, "Don't save" },
|
{ 0, 1, "Don't save" },
|
||||||
@@ -345,52 +348,6 @@ void ApplyClangFormat(Buffer *buffer) {
|
|||||||
ReplaceWithoutMovingCarets(buffer, GetRange(buffer), {temp_buffer->str, temp_buffer->len});
|
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) {
|
void GotoNextInList(Window *window, Int line_offset = 1) {
|
||||||
Assert(line_offset == 1 || line_offset == -1);
|
Assert(line_offset == 1 || line_offset == -1);
|
||||||
View *active_view = GetView(window->active_view);
|
View *active_view = GetView(window->active_view);
|
||||||
@@ -710,10 +667,41 @@ void Command_KillProcess() {
|
|||||||
KillProcess(main.view);
|
KillProcess(main.view);
|
||||||
} RegisterCommand(Command_KillProcess, "");
|
} RegisterCommand(Command_KillProcess, "");
|
||||||
|
|
||||||
void Command_KillWindow() {
|
void Command_CloseWindow() {
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
main.window->kill = true;
|
main.window->kill = true;
|
||||||
} RegisterCommand(Command_KillWindow, "ctrl-w");
|
} RegisterCommand(Command_CloseWindow, "");
|
||||||
|
|
||||||
|
void Command_Close() {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
|
||||||
|
if (main.buffer->dirty) {
|
||||||
|
int save = SaveMessageBox(main.buffer->name);
|
||||||
|
if (save == 0) {
|
||||||
|
return;
|
||||||
|
} else if (save == 2) {
|
||||||
|
SaveBuffer(main.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_GotoBackward() {
|
void Command_GotoBackward() {
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
|||||||
@@ -417,12 +417,10 @@ void OnCommand(Event event) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (it->dirty) {
|
if (it->dirty) {
|
||||||
String message = Format(scratch, "Do you really want to quit? Unsaved buffer: %S", it->name);
|
int save = SaveMessageBox(it->name);
|
||||||
int save = SaveMessageBox("There are unsaved changes, do you really want to quit!", message.data);
|
|
||||||
if (save == 0) {
|
if (save == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
} else if (save == 2) {
|
||||||
if (save == 2) {
|
|
||||||
SaveBuffer(it);
|
SaveBuffer(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,14 +469,16 @@ void GarbageCollect() {
|
|||||||
IterRemove(Views) {
|
IterRemove(Views) {
|
||||||
IterRemovePrepare(Views);
|
IterRemovePrepare(Views);
|
||||||
|
|
||||||
Buffer *buffer = GetBuffer(it->active_buffer);
|
if (it->kill == 0) {
|
||||||
if (!buffer->garbage) {
|
Buffer *buffer = GetBuffer(it->active_buffer);
|
||||||
continue;
|
if (!buffer->garbage) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool ref = ViewIsReferenced(it->id);
|
bool ref = ViewIsReferenced(it->id);
|
||||||
if (ref) {
|
if (ref) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_item = true;
|
remove_item = true;
|
||||||
@@ -489,13 +489,21 @@ void GarbageCollect() {
|
|||||||
IterRemove(Buffers) {
|
IterRemove(Buffers) {
|
||||||
IterRemovePrepare(Buffers);
|
IterRemovePrepare(Buffers);
|
||||||
|
|
||||||
if (!it->garbage) {
|
|
||||||
|
if (it->id.id == 0) {
|
||||||
|
it->kill = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ref = BufferIsReferenced(it->id);
|
if (it->kill == 0) {
|
||||||
if (ref) {
|
if (!it->garbage) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ref = BufferIsReferenced(it->id);
|
||||||
|
if (ref) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_item = true;
|
remove_item = true;
|
||||||
|
|||||||
@@ -59,6 +59,15 @@ API bool ViewIsCrumb(ViewID view_id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ViewIsActive(ViewID id) {
|
||||||
|
For (Windows) {
|
||||||
|
if (it->active_view == id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
API bool ViewIsReferenced(ViewID view) {
|
API bool ViewIsReferenced(ViewID view) {
|
||||||
if (view == NullViewID) {
|
if (view == NullViewID) {
|
||||||
return true;
|
return true;
|
||||||
@@ -68,12 +77,14 @@ API bool ViewIsReferenced(ViewID view) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
For(Windows) {
|
return ViewIsActive(view);
|
||||||
if (it->active_view == view) {
|
}
|
||||||
return true;
|
|
||||||
}
|
ViewID FindInactiveView(ViewID default_view = NullViewID) {
|
||||||
|
For (Views) {
|
||||||
|
if (!ViewIsActive(it->id)) return it->id;
|
||||||
}
|
}
|
||||||
return false;
|
return default_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
String16 FetchLoadWord(View *view) {
|
String16 FetchLoadWord(View *view) {
|
||||||
@@ -566,3 +577,35 @@ void DuplicateLine(View *view, int direction) {
|
|||||||
caret->range.max = XYToPos(buffer, xymax);
|
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;
|
bool update_scroll;
|
||||||
|
|
||||||
String16 prev_search_line;
|
String16 prev_search_line;
|
||||||
|
struct {
|
||||||
|
unsigned kill : 1;
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GotoCrumb {
|
struct GotoCrumb {
|
||||||
@@ -28,4 +32,4 @@ API View *FindView(String name, View *default_view = NULL);
|
|||||||
API View *GetView(ViewID id);
|
API View *GetView(ViewID id);
|
||||||
API View *OpenBufferView(String name);
|
API View *OpenBufferView(String name);
|
||||||
API bool ViewIsCrumb(ViewID view_id);
|
API bool ViewIsCrumb(ViewID view_id);
|
||||||
API bool ViewIsReferenced(ViewID view);
|
API bool ViewIsReferenced(ViewID view);
|
||||||
|
|||||||
Reference in New Issue
Block a user