Skip to content

feat(capture): Finalize on :w and show the destination - #1197

Merged
seflue merged 2 commits into
nvim-orgmode:masterfrom
seflue:feat/capture-refile-disposition
Oct 13, 2026
Merged

seflue merged 2 commits into
nvim-orgmode:masterfrom
seflue:feat/capture-refile-disposition

Conversation

@seflue

@seflue seflue commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Today :w in a capture buffer writes a temporary file that nothing reads. Only the finalize mapping refiles the capture, and it also closes the window.

With this change, :w refiles the capture and opens the destination in the same window, with the cursor where it was. :wq refiles and closes the window. The finalize mapping works as before. For org-roam this means :w creates the new node and leaves you in it, without a prompt since #1196.

refile() takes a new disposition option: 'close' (default, used by the mapping) or 'show' (used by :w).

Three details that are not obvious from the diff:

  • The BufWriteCmd is nested. The refile adds the destination with bufadd, and the buffer cache drops its cached miss only on BufAdd, which a non-nested autocmd suppresses. Without it the write fails with an invalid buffer id.
  • show() detaches the capture window's autocmds before swapping the buffer. The capture buffer is bufhidden=wipe, and its BufWipeout handler would start the refile again.
  • show() runs filetype detect, because bufload skips detection and :edit reuses the loaded buffer.

@seflue
seflue requested a review from kristijanhusak October 11, 2026 22:17
@kristijanhusak

Copy link
Copy Markdown
Member

How does "kill" behave in this scenario? Even after writing the file, you should be able to kill (cancel) the capture.

@seflue

seflue commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

That is actually the question. My intuition is: :w creates the file from a capture. That I can lose my work after a write by mistakenly pressing a "cancel" key combination is a real danger to me and I lost some work multiple times by that.

@seflue
seflue force-pushed the feat/capture-refile-disposition branch from 53441bf to b22030d Compare October 12, 2026 17:51
@kristijanhusak

Copy link
Copy Markdown
Member

Isn't org-roam creating a capture buffer with a path to a proper, non-temporary file? nvim-orgmode capture creates a temp file, so when the capture is finished, headline is refiled from the temp file to a destination.

@seflue

seflue commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

I'm working on a solution that is closer to what Emacs does. The biggest difference here is that Neovim cannot maintain (narrowed) views of the same buffer (where the write actually goes to the buffer).
My current belief state is now: for full-file capture we should write directly into the target buffer (that is what Emacs does) and on kill we should clear the buffer and ask if we actually should remove the file. Then the user can say "no" and undo if this was a mistake - Emacs + Roam works the same. There the confirmation question for deleting the file is implemented in Roam but I don't see a reason why it shouldn't always be the case.

@kristijanhusak

Copy link
Copy Markdown
Member

Sounds good to me, as long as it is only used for org-roam stuff. Plain nvim-orgmode capture should stay as it is, because it uses temp files.

@seflue
seflue force-pushed the feat/capture-refile-disposition branch from b22030d to 2699ad1 Compare October 12, 2026 21:07
@seflue

seflue commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

I reworked the branch into two commits. The second one implements what I described above, but only for whole_file captures into a file that doesn't exist yet, so in practice new roam nodes. Everything else still goes through the temp file. One thing changes for hooks: on_pre_refile now runs when such a capture opens, because roam resolves the node path in it and the path is needed to open the buffer.

The first commit only changes Escape on the :q! prompt, for all captures. Escape counted as No there and threw the capture away, now it reopens the capture instead.

@seflue
seflue force-pushed the feat/capture-refile-disposition branch 2 times, most recently from f53d153 to 2699ad1 Compare October 12, 2026 22:06
Closing a capture with unsaved changes asks whether to refile it.
Escape counted as No and discarded the capture, so dismissing the
prompt lost the text.

Escape now reopens the capture with its content, since an autocmd
cannot stop the buffer from being wiped. While Neovim exits, Escape
refiles instead. Only an explicit No still discards.

The prompt now comes before the refile target is resolved, so
dismissing it does not run on_pre_refile or create the target.

AI-assisted: Claude Code
:w in a capture buffer wrote a temp file nobody reads. For a
whole_file template into a new file, which is how org-roam creates
nodes, :w should create the file and keep the capture open, as
C-x C-s does in Emacs.

Such a capture now edits the target file's own buffer. Finishing
hands the buffer over as a normal one. Kill removes the text and,
when the file exists on disk, asks "Delete file for aborted
capture?" like org-roam. On No the buffer stays loaded, so undo
brings the text back.

on_pre_refile runs when the capture opens, since only the hook
knows the final path. Captures into existing files and all other
templates keep the temp buffer.

AI-assisted: Claude Code
@seflue
seflue force-pushed the feat/capture-refile-disposition branch from 2699ad1 to 2b8ae96 Compare October 12, 2026 22:07
@seflue
seflue merged commit 78c9928 into nvim-orgmode:master Oct 13, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants