Reopen changed files

This commit is contained in:
Krzosa Karol
2024-08-14 07:35:12 +02:00
parent f125a38c50
commit 2b4a43ddc1
9 changed files with 80 additions and 22 deletions

View File

@@ -26,13 +26,14 @@ void Advance(FileIter *it);
FileIter IterateFiles(Allocator allocator, String path); FileIter IterateFiles(Allocator allocator, String path);
void InitOS(void (*error_proc)(const char *, ...)); void InitOS(void (*error_proc)(const char *, ...));
String GetExePath(Allocator allocator); String GetExePath(Allocator allocator);
String GetExeDir(Allocator allocator); String GetExeDir(Allocator allocator);
bool FileExists(String path); bool FileExists(String path);
bool IsDir(String path); bool IsDir(String path);
bool IsFile(String path); bool IsFile(String path);
String GetWorkingDir(Allocator arena); String GetWorkingDir(Allocator arena);
bool IsAbsolute(String path); bool IsAbsolute(String path);
int64_t GetFileModTime(String file);
struct Process { struct Process {
bool is_valid; bool is_valid;

View File

@@ -262,6 +262,21 @@ bool DeleteFile(String path) {
return result; return result;
} }
int64_t GetFileModTime(String file) {
Scratch scratch;
String16 string16 = ToString16(scratch, file);
WIN32_FIND_DATAW data;
HANDLE handle = FindFirstFileW(string16.data, &data);
if (handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
FILETIME time = data.ftLastWriteTime;
int64_t result = (int64_t)time.dwHighDateTime << 32 | time.dwLowDateTime;
return result;
} else {
return -1;
}
}
struct Win32Process { struct Win32Process {
HANDLE handle; HANDLE handle;
HANDLE child_stdout_read; HANDLE child_stdout_read;

View File

@@ -667,7 +667,8 @@ void SaveBuffer(View *view) {
bool success = WriteFile(buffer->name, string); bool success = WriteFile(buffer->name, string);
if (success) { if (success) {
buffer->dirty = false; buffer->file_mod_time = GetFileModTime(buffer->name);
buffer->dirty = false;
} else { } else {
ReportWarningf("Failed to save file with name: %.*s", FmtString(buffer->name)); ReportWarningf("Failed to save file with name: %.*s", FmtString(buffer->name));
} }

View File

@@ -116,6 +116,12 @@ int Lua_Open(lua_State *L) {
return 0; return 0;
} }
int Lua_Reopen(lua_State *L) {
BSet main = GetActiveMainSet();
ReopenBuffer(main.buffer);
return 0;
}
int Lua_Print(lua_State *L) { int Lua_Print(lua_State *L) {
Scratch scratch; Scratch scratch;
String string = lua_tostring(L, 1); String string = lua_tostring(L, 1);

View File

@@ -4,6 +4,7 @@ luaL_Reg LuaFunctions[] = {
{"C", Lua_C}, {"C", Lua_C},
{"Kill", Lua_Kill}, {"Kill", Lua_Kill},
{"Open", Lua_Open}, {"Open", Lua_Open},
{"Reopen", Lua_Reopen},
{"Print", Lua_Print}, {"Print", Lua_Print},
{"ListBuffers", Lua_ListBuffers}, {"ListBuffers", Lua_ListBuffers},
{"GetBufferList", Lua_GetBufferList}, {"GetBufferList", Lua_GetBufferList},

View File

@@ -309,15 +309,34 @@ Buffer *BufferOpenFile(String path) {
IKnowWhatImDoing_Appendf(buffer, "%.*s\n", FmtString(it.filename)); IKnowWhatImDoing_Appendf(buffer, "%.*s\n", FmtString(it.filename));
} }
} else { } else {
String string = ReadFile(scratch, path); String string = ReadFile(scratch, path);
buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096); buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096);
buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap); buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap);
buffer->file_mod_time = GetFileModTime(path);
UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len}); UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len});
} }
return buffer; return buffer;
} }
void ResetBuffer(Buffer *buffer) {
Assert(buffer->edit_phase == 0);
buffer->line_starts.len = 1;
DeallocHistoryEntries(&buffer->redo_stack);
DeallocHistoryEntries(&buffer->undo_stack);
}
void ReopenBuffer(Buffer *buffer) {
Scratch scratch;
String string = ReadFile(scratch, buffer->name);
if (string.len) {
ResetBuffer(buffer);
buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap);
buffer->file_mod_time = GetFileModTime(buffer->name);
UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len});
}
}
View *OpenBufferView(String name) { View *OpenBufferView(String name) {
Buffer *buffer = BufferOpenFile(name); Buffer *buffer = BufferOpenFile(name);
View *view = CreateView(buffer->id); View *view = CreateView(buffer->id);
@@ -364,6 +383,15 @@ View *BufferIsReferenced(BufferID buffer_id) {
return NULL; return NULL;
} }
Window *BufferIsInWindow(BufferID buffer_id) {
For(Windows) {
Window *window = it.o;
View *view = GetView(window->active_view);
if (view->active_buffer == buffer_id) return window;
}
return NULL;
}
Window *BufferIsCrumb(BufferID buffer_id) { Window *BufferIsCrumb(BufferID buffer_id) {
For(Windows) { For(Windows) {
Window *window = it.o; Window *window = it.o;
@@ -378,7 +406,11 @@ void GarbageCollect() {
IterRemovePrepare(Views); IterRemovePrepare(Views);
View *view = it.o; View *view = it.o;
Buffer *buffer = GetBuffer(view->active_buffer); Buffer *buffer = GetBuffer(view->active_buffer);
bool gc = buffer->gc || buffer->is_directory; bool gc = buffer->gc;
if (buffer->is_directory) {
Window *ref = BufferIsCrumb(buffer->id);
if (!ref) gc = true;
}
Window *ref = ViewIsReferenced(view->id); Window *ref = ViewIsReferenced(view->id);
if (gc && !ref) { if (gc && !ref) {
@@ -394,10 +426,6 @@ void GarbageCollect() {
IterRemovePrepare(Buffers); IterRemovePrepare(Buffers);
Buffer *buffer = it.o; Buffer *buffer = it.o;
bool gc = buffer->gc; bool gc = buffer->gc;
if (buffer->is_directory) {
Window *ref = BufferIsCrumb(buffer->id);
if (!ref) gc = true;
}
View *ref = BufferIsReferenced(buffer->id); View *ref = BufferIsReferenced(buffer->id);
if (gc && !ref) { if (gc && !ref) {
@@ -409,6 +437,11 @@ void GarbageCollect() {
// @todo: add buffer to free list // @todo: add buffer to free list
Command_Appendf(GCInfoView, "buffer %.*s", FmtString(buffer->name)); Command_Appendf(GCInfoView, "buffer %.*s", FmtString(buffer->name));
} else if (buffer->file_mod_time) {
int64_t new_file_mod_time = GetFileModTime(buffer->name);
if (buffer->file_mod_time != new_file_mod_time) {
buffer->changed_on_disk = true;
}
} }
} }
} }

View File

@@ -25,6 +25,7 @@ struct Buffer {
BufferID id; BufferID id;
String name; String name;
Int change_id; Int change_id;
Int file_mod_time;
union { union {
U16 *data; U16 *data;
@@ -42,6 +43,7 @@ struct Buffer {
int dirty : 1; int dirty : 1;
int is_directory : 1; int is_directory : 1;
int gc : 1; int gc : 1;
int changed_on_disk : 1;
}; };
}; };

View File

@@ -45,7 +45,8 @@ void ReplaceTitleBarData(Window *window) {
AdjustCarets(edits, &caret_copy); AdjustCarets(edits, &caret_copy);
} }
String s = Format(scratch, "%.*s:%lld:%lld", FmtString(main.buffer->name), (long long)xy.line + 1ll, (long long)xy.col + 1ll); char *reopen = main.buffer->changed_on_disk ? " #Reopen()" : "";
String s = Format(scratch, "%.*s:%lld:%lld%s", FmtString(main.buffer->name), (long long)xy.line + 1ll, (long long)xy.col + 1ll, reopen);
String16 string = ToString16(scratch, s); String16 string = ToString16(scratch, s);
String16 string_to_replace = GetString(title.buffer, replace_range); String16 string_to_replace = GetString(title.buffer, replace_range);
if (string_to_replace != string) { if (string_to_replace != string) {

View File

@@ -1,7 +1,5 @@
- garbage collect the buffers, views - store them in free list on destroy - garbage collect the buffers, views - store them in free list on destroy
- adding items to directory should create files on save - it should ask the user (syntax: dir/ | file) - adding items to directory should create files on save - it should ask the user (syntax: dir/ | file)
- refresh the directory - when opening up again?
- refresh the file content, periodically check file timestamp for changes and update if neccessary
- ask user if he really wants to quit even though he has an unsaved buffer - popup window - ask user if he really wants to quit even though he has an unsaved buffer - popup window
- add plumb rules for some web stuff - add plumb rules for some web stuff
- test the code editor: try writing in it, try browsing in it, create test tooling - test the code editor: try writing in it, try browsing in it, create test tooling
@@ -12,8 +10,8 @@
- group history entries so the you can rollback through multiple ones at once and not waste time on skipping whitespace trimming or deleting every character - group history entries so the you can rollback through multiple ones at once and not waste time on skipping whitespace trimming or deleting every character
- Check if file exists in ApplyRules otherwise return null - Check if file exists in ApplyRules otherwise return null
- Different buffers should be GCed differently - Add the event buffer with serialized events
- Special buffers that store metadata - Gotos, jumping between views should preserve cursors
- OnWindowCommand allow config user to overwrite the WindowCommand keybinding, introduce his own - OnWindowCommand allow config user to overwrite the WindowCommand keybinding, introduce his own