Reopen changed files
This commit is contained in:
@@ -26,13 +26,14 @@ void Advance(FileIter *it);
|
||||
FileIter IterateFiles(Allocator allocator, String path);
|
||||
void InitOS(void (*error_proc)(const char *, ...));
|
||||
|
||||
String GetExePath(Allocator allocator);
|
||||
String GetExeDir(Allocator allocator);
|
||||
bool FileExists(String path);
|
||||
bool IsDir(String path);
|
||||
bool IsFile(String path);
|
||||
String GetWorkingDir(Allocator arena);
|
||||
bool IsAbsolute(String path);
|
||||
String GetExePath(Allocator allocator);
|
||||
String GetExeDir(Allocator allocator);
|
||||
bool FileExists(String path);
|
||||
bool IsDir(String path);
|
||||
bool IsFile(String path);
|
||||
String GetWorkingDir(Allocator arena);
|
||||
bool IsAbsolute(String path);
|
||||
int64_t GetFileModTime(String file);
|
||||
|
||||
struct Process {
|
||||
bool is_valid;
|
||||
|
||||
@@ -262,6 +262,21 @@ bool DeleteFile(String path) {
|
||||
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 {
|
||||
HANDLE handle;
|
||||
HANDLE child_stdout_read;
|
||||
|
||||
@@ -667,7 +667,8 @@ void SaveBuffer(View *view) {
|
||||
bool success = WriteFile(buffer->name, string);
|
||||
|
||||
if (success) {
|
||||
buffer->dirty = false;
|
||||
buffer->file_mod_time = GetFileModTime(buffer->name);
|
||||
buffer->dirty = false;
|
||||
} else {
|
||||
ReportWarningf("Failed to save file with name: %.*s", FmtString(buffer->name));
|
||||
}
|
||||
|
||||
@@ -116,6 +116,12 @@ int Lua_Open(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Lua_Reopen(lua_State *L) {
|
||||
BSet main = GetActiveMainSet();
|
||||
ReopenBuffer(main.buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Lua_Print(lua_State *L) {
|
||||
Scratch scratch;
|
||||
String string = lua_tostring(L, 1);
|
||||
|
||||
@@ -4,6 +4,7 @@ luaL_Reg LuaFunctions[] = {
|
||||
{"C", Lua_C},
|
||||
{"Kill", Lua_Kill},
|
||||
{"Open", Lua_Open},
|
||||
{"Reopen", Lua_Reopen},
|
||||
{"Print", Lua_Print},
|
||||
{"ListBuffers", Lua_ListBuffers},
|
||||
{"GetBufferList", Lua_GetBufferList},
|
||||
|
||||
@@ -309,15 +309,34 @@ Buffer *BufferOpenFile(String path) {
|
||||
IKnowWhatImDoing_Appendf(buffer, "%.*s\n", FmtString(it.filename));
|
||||
}
|
||||
} else {
|
||||
String string = ReadFile(scratch, path);
|
||||
buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096);
|
||||
buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap);
|
||||
String string = ReadFile(scratch, path);
|
||||
buffer = CreateBuffer(sys_allocator, path, string.len * 4 + 4096);
|
||||
buffer->len = ConvertUTF8ToUTF16UnixLine(string, buffer->str, buffer->cap);
|
||||
buffer->file_mod_time = GetFileModTime(path);
|
||||
UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len});
|
||||
}
|
||||
|
||||
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) {
|
||||
Buffer *buffer = BufferOpenFile(name);
|
||||
View *view = CreateView(buffer->id);
|
||||
@@ -364,6 +383,15 @@ View *BufferIsReferenced(BufferID buffer_id) {
|
||||
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) {
|
||||
For(Windows) {
|
||||
Window *window = it.o;
|
||||
@@ -378,7 +406,11 @@ void GarbageCollect() {
|
||||
IterRemovePrepare(Views);
|
||||
View *view = it.o;
|
||||
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);
|
||||
if (gc && !ref) {
|
||||
@@ -394,10 +426,6 @@ void GarbageCollect() {
|
||||
IterRemovePrepare(Buffers);
|
||||
Buffer *buffer = it.o;
|
||||
bool gc = buffer->gc;
|
||||
if (buffer->is_directory) {
|
||||
Window *ref = BufferIsCrumb(buffer->id);
|
||||
if (!ref) gc = true;
|
||||
}
|
||||
|
||||
View *ref = BufferIsReferenced(buffer->id);
|
||||
if (gc && !ref) {
|
||||
@@ -409,6 +437,11 @@ void GarbageCollect() {
|
||||
// @todo: add buffer to free list
|
||||
|
||||
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;
|
||||
String name;
|
||||
Int change_id;
|
||||
Int file_mod_time;
|
||||
|
||||
union {
|
||||
U16 *data;
|
||||
@@ -42,6 +43,7 @@ struct Buffer {
|
||||
int dirty : 1;
|
||||
int is_directory : 1;
|
||||
int gc : 1;
|
||||
int changed_on_disk : 1;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ void ReplaceTitleBarData(Window *window) {
|
||||
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_to_replace = GetString(title.buffer, replace_range);
|
||||
if (string_to_replace != string) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
- 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)
|
||||
- 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
|
||||
- add plumb rules for some web stuff
|
||||
- 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
|
||||
|
||||
- Check if file exists in ApplyRules otherwise return null
|
||||
- Different buffers should be GCed differently
|
||||
- Special buffers that store metadata
|
||||
- Add the event buffer with serialized events
|
||||
- Gotos, jumping between views should preserve cursors
|
||||
|
||||
- OnWindowCommand allow config user to overwrite the WindowCommand keybinding, introduce his own
|
||||
|
||||
|
||||
Reference in New Issue
Block a user