Reopen changed files
This commit is contained in:
@@ -33,6 +33,7 @@ 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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -667,6 +667,7 @@ void SaveBuffer(View *view) {
|
|||||||
bool success = WriteFile(buffer->name, string);
|
bool success = WriteFile(buffer->name, string);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
buffer->file_mod_time = GetFileModTime(buffer->name);
|
||||||
buffer->dirty = false;
|
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));
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -312,12 +312,31 @@ Buffer *BufferOpenFile(String path) {
|
|||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user