add session save and session load functionality

New [key-bindings]:
- session-save: captures cwd and foreground process argv to ~/.local/share/foot/state/{name}.json
- session-save-secure: prompts for a password, encrypts the scrollback with argon2id + XChaCha20-Poly1305 (libsodium) and writes it to {name}.scrollback.enc(stores up to 1Mb scrollback buffer).
- session-load: a minimal fuzzy picker that displays saved sessions (both secure and vanilla), UI piggybacks on search bar subsurface. use arrows to navigate and delete to delete a previously saved session.
This commit is contained in:
entailz 2026-05-21 14:08:33 -07:00
parent 05ee680778
commit cabddb26e6
16 changed files with 1947 additions and 49 deletions

View file

@ -344,6 +344,15 @@ enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
enum search_direction { SEARCH_BACKWARD_SAME_POSITION, SEARCH_BACKWARD, SEARCH_FORWARD };
enum search_case_mode { SEARCH_CASE_SMART, SEARCH_CASE_SENSITIVE, SEARCH_CASE_INSENSITIVE };
enum search_mode {
SEARCH_MODE_NORMAL,
SEARCH_MODE_SESSION_SAVE,
SEARCH_MODE_SESSION_LOAD,
SEARCH_MODE_SESSION_OVERWRITE_CONFIRM,
SEARCH_MODE_SESSION_SAVE_SECURE_NAME,
SEARCH_MODE_SESSION_SAVE_SECURE_PASSWORD,
SEARCH_MODE_SESSION_LOAD_PASSWORD,
};
struct ptmx_buffer {
void *data;
@ -626,6 +635,7 @@ struct terminal {
size_t len;
size_t sz;
size_t cursor;
enum search_mode mode;
int original_view;
bool view_followed_offset;
@ -865,6 +875,24 @@ struct terminal {
char *foot_exe;
char *cwd;
/* Active only while term->search.mode == SEARCH_MODE_SESSION_LOAD */
struct {
char **all; /* All session names from disk */
size_t all_count;
size_t *filtered; /* indices into all[] matching current input */
size_t filtered_count;
size_t filtered_cap;
size_t sel; /* index within filtered[] */
} session_picker;
/* Name held across a multi-step session flow (overwrite confirm, secure
* save name->password, load password). */
char *session_pending_name;
bool session_pending_secure; /* set when overwrite-confirm precedes a secure save */
/* For LOAD_PASSWORD: heap-allocated session_state pulled from JSON. The
* new tab isn't spawned until decryption succeeds, so we hold it here. */
void *session_pending_load_state;
bool grapheme_shaping;
bool size_notifications;
};
@ -882,6 +910,15 @@ struct terminal *term_tab_new(
int argc, char *const *argv, const char *const *envp,
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
/*
* Like term_tab_new but with an explicit override for the new tab's cwd.
* If override_cwd is NULL behaves identically to term_tab_new.
*/
struct terminal *term_tab_new_with_cwd(
struct terminal *primary, const char *override_cwd,
int argc, char *const *argv, const char *const *envp,
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
void term_tab_switch(struct wl_window *win, size_t idx);
void term_tab_close(struct terminal *term);
size_t term_tab_bar_hit_test(const struct terminal *term, int x, int y);