Add auto save setting for the Warp text editor#13435
Conversation
Adds an opt-in "Auto save" setting (Settings > Code > Code Editor and Review) that automatically saves changes in the Warp text editor. Triggers mirror VS Code: - afterDelay: debounced ~1s while typing; saves without running the LSP formatter. - onFocusChange / onWindowChange: when the editor loses focus or its window is navigated away from; honors the existing "Format on save" setting. Applies to the Warp text editor, including diff/review views. Untitled files, disconnected remotes, and unchanged buffers are skipped. Defaults to off. Co-Authored-By: Oz <oz-agent@warp.dev>
- Only exclude pending accept/reject diffs (diff_type Some) from auto-save; code-review panel edits and normal editing remain eligible. Agent "edit-file" diffs use a separate view type (InlineDiffView) and were never auto-saved. - Suppress the "File saved." toast for auto-saves (shown only for manual cmd-s saves) via an auto_saved flag on LocalCodeEditorEvent::FileSaved. - Hide the unsaved-changes dot in code tabs when auto-save is enabled so it no longer flickers on/off as the user types. Co-Authored-By: Oz <oz-agent@warp.dev>
The pane-level (code pane header) indicator was already gated; this also gates the workspace tab-strip indicator, so no unsaved dot flickers at either level while auto-save persists edits. Co-Authored-By: Oz <oz-agent@warp.dev>
When auto-save is enabled and a file with a backing path is closed before the debounce fires, flush the pending edits and close instead of blocking on the "unsaved changes" dialog. The flush is marked as an auto-save so it stays silent (no toast). Untitled files still prompt, since auto-save can't persist them without a Save As. Co-Authored-By: Oz <oz-agent@warp.dev>
The code review diff headers render their own per-file unsaved indicator via render_unsaved_circle_with_tooltip; gate it on the auto_save setting like the editor tab and workspace tab indicators, so it no longer flickers while editing. Co-Authored-By: Oz <oz-agent@warp.dev>
…ode review) When auto-save is enabled, close/quit paths no longer prompt about unsaved FILE changes: they flush-save all saveable editors silently first. The warning still shows for things auto-save can't handle (running processes, shared sessions, or unsaved buffers with no backing file such as untitled files). Centralized via UnsavedStateSummary::save_unsaved_code_and_should_warn, backed by CodeView::auto_save_all_unsaved_tabs and CodeReviewView::auto_save_all_unsaved_files (both mark saves as auto-saves so no toast fires). Co-Authored-By: Oz <oz-agent@warp.dev>
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds an opt-in code.editor.auto_save setting, wires it into the code settings UI, implements debounce/focus/window-triggered saves, suppresses save indicators/toasts for auto-saves, and changes close/quit flows to flush code editors silently when auto-save is enabled.
Concerns
- Disconnected remote file buffers are treated as auto-saveable during close/quit flushing because the new code only checks for a
file_id; failed saves can allow the close to proceed without warning and discard unsaved remote edits. - The focus-loss auto-save marker can remain set when
save_localreturns an immediate error, causing the next successful manual save to be misclassified as an auto-save. - For this user-facing change, please include screenshots or a screen recording demonstrating the settings toggle and editor behavior working end to end.
Verdict
Found: 1 critical, 1 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| let has_backing_file = self | ||
| .tab_at(index) | ||
| .is_some_and(|tab| tab.editor_view.as_ref(ctx).file_id().is_some()); | ||
| if has_backing_file { |
There was a problem hiding this comment.
🚨 [CRITICAL] This only checks for a file_id, so disconnected remote buffers are treated as auto-saveable; save_local then fails immediately but unsaveable_changes_remain stays false, allowing close/quit to proceed without warning and discard unsaved remote edits. Check !editor.is_remote_disconnected(ctx) or return true when the save fails before suppressing the warning.
| // Mark this as an auto-save so the "File saved." toast is suppressed. | ||
| self.auto_save_in_flight = true; | ||
| let _ = self.save_local(ctx); |
There was a problem hiding this comment.
save_local returns early for NoFileId or RemoteDisconnected, auto_save_in_flight remains set and the next manual save is emitted as auto_saved, suppressing the success toast. Clear the marker when the save does not start.
| // Mark this as an auto-save so the "File saved." toast is suppressed. | |
| self.auto_save_in_flight = true; | |
| let _ = self.save_local(ctx); | |
| // Mark this as an auto-save so the "File saved." toast is suppressed. | |
| self.auto_save_in_flight = true; | |
| if self.save_local(ctx).is_err() { | |
| self.auto_save_in_flight = false; | |
| } |
- auto_save_all_unsaved_tabs: treat disconnected remote buffers (which have a file_id but cannot actually save) as unsaveable, so close/quit still warns instead of silently discarding their edits. - auto_save_on_focus_change: clear the auto_save_in_flight marker when save_local returns early (untitled/disconnected remote) so a later manual save still shows its 'File saved.' toast. - Add wasm stubs for CodeView::auto_save_all_unsaved_tabs and LocalCodeEditorView::mark_next_save_as_auto_save, which are called from non-wasm-gated code (quit_warning, code_review_view) and were breaking the wasm build. Co-Authored-By: Oz <oz-agent@warp.dev>
| // pending accept/reject diff (e.g. an agent "edit-file" | ||
| // proposal), which must never auto-save. Editable | ||
| // code-review diffs use `diff_type = None` and stay eligible. | ||
| if me.diff_type.is_none() && *CodeSettings::as_ref(ctx).auto_save { |
There was a problem hiding this comment.
very much a nit -- we should queue a debounced auto-save after user manually saves as well?
There was a problem hiding this comment.
[Warp Agent] Queuing a debounced auto-save right after a manual save would end up a no-op: auto_save_after_delay early-returns when has_unsaved_changes is false, and any edit made after the manual save re-queues the debounce via the ContentChanged handler anyway. So the current wiring already covers this — leaving as-is.
| /// Set while an auto-save (debounced or focus-change) is in flight so the | ||
| /// resulting `FileSaved` event can be marked as an auto-save and suppress | ||
| /// the success toast. | ||
| auto_save_in_flight: bool, |
There was a problem hiding this comment.
Should we have a general save state? Something like
enum SaveState {
Saving { is_auto_save: bool },
None
}
This way we could also do things like early return on save attempts when the editor is already saving
There was a problem hiding this comment.
[Warp Agent] Considered this — the subtlety is that auto_save_in_flight really means "label the next save as an auto-save", not "a save is in flight": the close flows set it via mark_next_save_as_auto_save() before separately invoking the save, so SaveState::Saving { is_auto_save } would conflate labeling with in-flight tracking. The early-return-on-saving idea is also a behavior change: saves complete asynchronously via GlobalBufferModel events, so a manual cmd-s during an in-flight auto-save would get dropped, and a stuck Saving state would silently swallow future saves (re-saving today is idempotent/harmless). Deferring the refactor to a follow-up rather than bundling it here — happy to pick it up if you feel strongly.
| /// as an auto-save so it stays silent (no "File saved." toast). Returns | ||
| /// `true` if any unsaved tab could NOT be auto-saved (e.g. an untitled | ||
| /// buffer with no path), so callers can still warn before discarding those. | ||
| pub fn auto_save_all_unsaved_tabs(&mut self, ctx: &mut ViewContext<Self>) -> bool { |
There was a problem hiding this comment.
CodeView wraps LocalCodeEditorView right? In that case, do we need an ad-hoc autosave logic for the parent view (I assume the child editors will handle auto-save themselves)?
There was a problem hiding this comment.
[Warp Agent] The child editors auto-save only on the typing debounce (1s) and focus change; auto_save_all_unsaved_tabs is the close/quit-time flush (called from UnsavedStateSummary::save_unsaved_code_and_should_warn). At close, a pending debounce hasn't fired yet and no blur may occur before teardown, so edits from the last second would be lost without it. The parent also needs to aggregate across all tabs to decide whether anything remains that auto-save can't persist (untitled buffers, disconnected remotes) and still warrant the warning dialog. The actual save is still delegated to the child editor — this is just tab orchestration.
| } | ||
| } | ||
|
|
||
| /// Flush-saves every unsaved file in the review, marking each save as an |
There was a problem hiding this comment.
ditto -- I assume the child editor views will handle auto-save here?
There was a problem hiding this comment.
[Warp Agent] Same rationale as CodeView: this is the close-time flush (called from CodeReviewView::close). The child editors can't know the review pane is closing, and the parent owns the unsaved-file aggregation and the close-vs-prompt decision.
Auto-save previously hid the unsaved-changes indicator (editor tab dot, workspace tab indicator, and code review per-file dot) unconditionally, even for untitled buffers and disconnected remotes that auto-save cannot persist. Add LocalCodeEditorView::can_auto_save and make all three indicator sites auto-save-aware so unsaveable changes stay visible. Co-Authored-By: Oz <oz-agent@warp.dev>
|
[Warp Agent] Pushed 348b260 fixing a bug in the unsaved-indicator suppression: with auto-save enabled, the unsaved-changes indicator (editor tab dot, workspace tab indicator, and code review per-file dot) was hidden unconditionally — including for untitled buffers and disconnected remotes that auto-save can't actually persist. The fix adds |
Co-Authored-By: Oz <oz-agent@warp.dev>
Demo: https://www.loom.com/share/e61d6e666caa41deb9171c1cbbcc07c3 Adds an opt-in **Auto save** setting for the Warp text editor. When enabled, the editor saves changes automatically so you don't have to press Cmd-S. Behavior mirrors VS Code: - **While typing** — debounced ~1s after you stop typing (VS Code's `files.autoSave: afterDelay`). Saves **without** running the LSP formatter, so formatting never disrupts you mid-edit. - **On focus loss** — when the editor loses focus to another view in the app (`onFocusChange`) or its window is navigated away from / the app is deactivated (`onWindowChange`). These **honor** the existing **Format on save** setting, exactly like a manual Cmd-S. Scope & guards: - Applies to normal file editing **and the code review panel's editable diffs** (both are `LocalCodeEditorView` with `diff_type = None`). - **Never** auto-saves the agent "edit-file" accept/reject diffs (a separate `InlineDiffView` type; plus a `diff_type.is_some()` guard). - Skips untitled files (no path), disconnected remotes, and buffers with no unsaved changes. - Defaults to **off**; cloud-synced like other editor settings. Unobtrusive behavior when auto-save is on: - The **"File saved." toast is suppressed** for auto-saves (still shown for manual Cmd-S), via an `auto_saved` flag on `LocalCodeEditorEvent::FileSaved`. - The **unsaved-changes dot is hidden** at every surface (editor tab bar, single-tab pane header, workspace tab strip, and code review diff headers), so it no longer flickers as you type. - **Closing never blocks on an "unsaved changes" dialog for files that can be auto-saved.** Instead the pending edits are flushed silently and the close proceeds. This covers the file/editor tab, the code pane, the workspace tab(s), the window, app quit, and the code review pane. The close/quit dialog still appears for things auto-save can't handle — running processes, shared sessions, or unsaved buffers with **no backing file** (e.g. untitled files) — so those are never silently discarded. The setting lives at **Settings → Code → Code Editor and Review → Auto save** (`code.editor.auto_save`). - New `auto_save` bool in `CodeSettings` (`app/src/settings/code.rs`), mirroring `format_on_save`. - Toggle widget + `ToggleAutoSave` action in `app/src/settings_view/code_page.rs`. - Auto-save logic in `app/src/code/local_code_editor.rs`: a debounced channel (afterDelay, no formatting), `View::on_blur` (focus loss), and a `WindowManager` subscription (window navigation). Both focus paths respect format-on-save. - Indicator/toast suppression in `app/src/code/view.rs`, `app/src/tab.rs`, and `app/src/code_review/code_review_view.rs`. - Close/quit handling centralized in `UnsavedStateSummary::save_unsaved_code_and_should_warn` (`app/src/quit_warning/mod.rs`), backed by `CodeView::auto_save_all_unsaved_tabs` and `CodeReviewView::auto_save_all_unsaved_files`. Wired into the window/app close (`app/src/lib.rs`), pane close (`app/src/pane_group/mod.rs`), tab close (`app/src/workspace/view.rs`), the editor tab close (`app/src/code/view.rs`), and the code review close (`app/src/code_review/code_review_view.rs`). _None._ - [ ] The linked issue is labeled `ready-to-spec` or `ready-to-implement`. - [ ] Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes). - [ ] I have manually tested my changes locally with `./script/run` Validated with `cargo fmt` and `cargo clippy -p warp --lib -- -D warnings` (both pass) after merging latest `master`. No automated tests were added: auto-save is driven by debounce timers plus focus/window/close lifecycle events that are awkward to unit test, and the underlying save path (`save_local` / `perform_save`) is unchanged and already exercised. Manual verification is recommended before merge. _N/A — settings toggle plus editor behavior. Happy to add a screen recording._ - [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode CHANGELOG-IMPROVEMENT: Added an opt-in "Auto save" setting for the Warp text editor (Settings > Code > Code Editor and Review) that saves changes as you type and when the editor loses focus, and flushes edits automatically when closing instead of prompting. --- [Warp conversation](https://staging.warp.dev/conversation/d9f632e9-8c0c-4f27-8c0c-a7fa791ad0f8) Co-Authored-By: Oz <oz-agent@warp.dev> --------- Co-authored-by: Oz <oz-agent@warp.dev>
Demo: https://www.loom.com/share/e61d6e666caa41deb9171c1cbbcc07c3
Description
Adds an opt-in Auto save setting for the Warp text editor. When enabled, the editor saves changes automatically so you don't have to press Cmd-S.
Behavior mirrors VS Code:
files.autoSave: afterDelay). Saves without running the LSP formatter, so formatting never disrupts you mid-edit.onFocusChange) or its window is navigated away from / the app is deactivated (onWindowChange). These honor the existing Format on save setting, exactly like a manual Cmd-S.Scope & guards:
LocalCodeEditorViewwithdiff_type = None).InlineDiffViewtype; plus adiff_type.is_some()guard).Unobtrusive behavior when auto-save is on:
auto_savedflag onLocalCodeEditorEvent::FileSaved.The setting lives at Settings → Code → Code Editor and Review → Auto save (
code.editor.auto_save).How
auto_savebool inCodeSettings(app/src/settings/code.rs), mirroringformat_on_save.ToggleAutoSaveaction inapp/src/settings_view/code_page.rs.app/src/code/local_code_editor.rs: a debounced channel (afterDelay, no formatting),View::on_blur(focus loss), and aWindowManagersubscription (window navigation). Both focus paths respect format-on-save.app/src/code/view.rs,app/src/tab.rs, andapp/src/code_review/code_review_view.rs.UnsavedStateSummary::save_unsaved_code_and_should_warn(app/src/quit_warning/mod.rs), backed byCodeView::auto_save_all_unsaved_tabsandCodeReviewView::auto_save_all_unsaved_files. Wired into the window/app close (app/src/lib.rs), pane close (app/src/pane_group/mod.rs), tab close (app/src/workspace/view.rs), the editor tab close (app/src/code/view.rs), and the code review close (app/src/code_review/code_review_view.rs).Linked Issue
None.
ready-to-specorready-to-implement.Testing
./script/runValidated with
cargo fmtandcargo clippy -p warp --lib -- -D warnings(both pass) after merging latestmaster. No automated tests were added: auto-save is driven by debounce timers plus focus/window/close lifecycle events that are awkward to unit test, and the underlying save path (save_local/perform_save) is unchanged and already exercised. Manual verification is recommended before merge.Screenshots / Videos
N/A — settings toggle plus editor behavior. Happy to add a screen recording.
Agent Mode
CHANGELOG-IMPROVEMENT: Added an opt-in "Auto save" setting for the Warp text editor (Settings > Code > Code Editor and Review) that saves changes as you type and when the editor loses focus, and flushes edits automatically when closing instead of prompting.
Warp conversation
Co-Authored-By: Oz oz-agent@warp.dev