Step 117: session persistence

This commit is contained in:
Bill
2026-02-09 12:56:27 -07:00
parent 9c74603b10
commit fb9d24eee5
7 changed files with 227 additions and 2 deletions

View File

@@ -47,6 +47,7 @@
#include "GoToLine.h"
#include "Orchestrator.h"
#include "ProjectManager.h"
#include "SessionManager.h"
#include "ast/Serialization.h"
#include "ast/Generator.h"
#include "ast/Annotation.h"
@@ -557,6 +558,76 @@ struct EditorState {
}
}
std::filesystem::path sessionFilePath() const {
return configDir() / "session.json";
}
bool saveSession(const std::string& imguiIni) {
SessionData session;
session.workspaceRoot = workspaceRoot;
session.activePath = active() ? active()->path : "";
session.layoutPreset = LayoutManager::presetName(layoutPreset);
session.imguiIni = imguiIni;
for (const auto& bufPath : buffers.getOpenBuffers()) {
auto it = bufferStates.find(bufPath);
if (it == bufferStates.end()) continue;
const auto* buf = it->second.get();
SessionBufferState entry;
entry.path = bufPath;
entry.language = buf->language;
entry.mode = bufferModeToString(buf->bufferMode);
entry.cursorLine = buf->cursorLine;
entry.cursorCol = buf->cursorCol;
entry.foldedLines = buf->widget.getFoldedLines();
session.buffers.push_back(std::move(entry));
}
try {
std::ofstream out(sessionFilePath().string(), std::ios::binary);
if (!out.is_open()) return false;
out << sessionToJson(session).dump(2);
return true;
} catch (...) {
return false;
}
}
bool loadSession(SessionData& out) {
try {
std::ifstream in(sessionFilePath().string(), std::ios::binary);
if (!in.is_open()) return false;
nlohmann::json j;
in >> j;
out = sessionFromJson(j);
return true;
} catch (...) {
return false;
}
}
void applySession(const SessionData& session) {
closeAllBuffers();
if (!session.workspaceRoot.empty()) {
workspaceRoot = session.workspaceRoot;
fileTreeDirty = true;
projectSearch.setRoot(workspaceRoot);
}
layoutPreset = LayoutManager::presetFromName(session.layoutPreset);
for (const auto& buf : session.buffers) {
doOpen(buf.path, bufferModeFromString(buf.mode));
auto it = bufferStates.find(buf.path);
if (it != bufferStates.end()) {
auto* bs = it->second.get();
bs->cursorLine = buf.cursorLine;
bs->cursorCol = buf.cursorCol;
bs->widget.setDesiredFoldedLines(buf.foldedLines);
jumpTo(bs, std::max(0, buf.cursorLine - 1), std::max(0, buf.cursorCol - 1));
}
}
if (!session.activePath.empty() && buffers.hasBuffer(session.activePath)) {
switchToBuffer(session.activePath);
}
}
void init() {
outputLog = "Whetstone Editor ready.\n";
workspaceRoot = std::filesystem::current_path().string();
@@ -1740,6 +1811,14 @@ int main(int, char**) {
// Editor state
EditorState state;
state.init();
SessionData session;
if (state.loadSession(session)) {
if (!session.imguiIni.empty()) {
ImGui::LoadIniSettingsFromMemory(session.imguiIni.c_str(),
session.imguiIni.size());
}
state.applySession(session);
}
state.lspTransport = std::make_shared<NullLSPTransport>();
state.lsp = std::make_shared<LSPClient>(state.lspTransport);
@@ -3745,6 +3824,11 @@ int main(int, char**) {
}
// Cleanup
size_t iniSize = 0;
const char* iniData = ImGui::SaveIniSettingsToMemory(&iniSize);
if (iniData && iniSize > 0) {
state.saveSession(std::string(iniData, iniSize));
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();