-
Notifications
You must be signed in to change notification settings - Fork 0
Session Persistence
ctrlvim remembers what you had open — the way closing a VS Code window and reopening it restores your tabs, including edits you never saved. This is not a swapfile: ctrlvim-text's buffer storage deliberately dropped Neovim's swapfile/crash-recovery machinery (it's a rope, not a swapfile-backed B-tree). Session persistence is the modern replacement for that gap, built on top of the existing async job/timer infrastructure instead.
Two independent pieces, mirroring the split VS Code itself makes between window.restoreWindows and files.hotExit:
On a clean quit (:q, :qa, :qa!, or Ctrl-C — anything that sets App::should_quit), ctrlvim writes the current project's open-buffer list to disk. The next time you launch cvi in that same project with no file named on the command line, it reopens those buffers, restores the active tab, and restores cursor position per buffer.
cvi some/file.rs behaves like plain Vim — it does not also resurrect an unrelated stale window. Restore only happens on a bare cvi (or cvi some/dir/).
A clean quit gives you a hook to flush state; kill -9 or a power loss doesn't. So for buffers with unsaved changes, ctrlvim also snapshots their live text to disk periodically while running (every 5 seconds, reusing the same poll-tick infrastructure that already drives background job/AI polling — see ctrlvim_async::TimerService).
On restore, any buffer that was marked modified loads from that snapshot instead of the (older) on-disk file — you get your edits back, still marked dirty, ready for :w. The snapshot is cleared automatically once you actually save.
~/.local/state/ctrlvim/sessions/<sanitized-project-root>/
index.tsv # one line per open buffer: path, cursor line, cursor col, modified flag, active flag
recovery/
<sanitized-file-path>.txt # live text of a dirty buffer, present only while it's unsaved
Same convention as the existing per-project pins store (~/.local/state/ctrlvim/pins/) and theme store — the project root is sanitized (non-alphanumeric → _) into the filename, so every project gets its own session file with no collisions.
The SESSIONS panel (Dashboard → workspace) shows the current project's row with:
- A
+marker (same orange used for a dirty tab in the tabline) when any open buffer has unsaved changes worth keeping — or clearing. - An
[X]control — pressXwhile on the workspace section, or click the badge — that wipes this project's saved tab list and recovery snapshots viaApp::discard_session(). This only ever touches ctrlvim's own state directory; it never touches your actual files. If you keep editing afterward, the next periodic snapshot just writes fresh state again — it clears what's saved now, it doesn't turn saving off.
-
Buffer(inctrlvim-tui/src/app.rs) gained acursor: (usize, usize)field, updated inApp::snapshot_active()alongside the existingtext/modifiedcaching, and restored inApp::load_active_into_engine()viaSession::set_cursor_clamped. This is also what fixed cursor position resetting to the top of the file on ordinary tab switches — a pre-existing gap, not something session persistence introduced. -
App::restore_session/App::save_session/App::tick_session_snapshot/App::write_session_stateincrates/ctrlvim-tui/src/app.rs. - Directory helpers (
session_dir,sanitize_path_key) incrates/ctrlvim-tui/src/data.rs, following the exact patternpins_path/pins_path_inalready established. - Wired into
crates/ctrlvim-tui/src/main.rs:restore_session()after config load (only when no CLI files given),tick_session_snapshot()in the same poll-tick aspoll_jobs/poll_ai,save_session()once after the main loop exits.