-
Notifications
You must be signed in to change notification settings - Fork 2
Update open register windows when register contents are modified #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
I've been floating around one idea in my head: We could
And also allow adding a file in Seems good right? Looks like it's ok and a common practice to set a completely custom-named filetype, for example in I will now test this branch :) |
|
It works great and seems worth it to me. It would be great and more consistent if we could also update non-macro registers when their content has changed, such as updating the Code I think is ok and can be easily improved, if e.g. we find a better way to match the correct buffers, I think we should add the |
Great idea! Much simpler than keeping that map, and also can help solve some other problems as well going forward.
Also a great idea. We can use this PR. I'll work on implementing this using |
EDIT: disregard this comment. See below.There is a problem with
Textlock specifies that while you are doing -M.update_register_buffers = function()
- -- get the register that is being recorded
- local register = vim.fn.reg_recording()
+M.update_register_buffers = function(yank)
+ -- get the register that is being recorded or yanked into
+ local register = yank and vim.api.nvim_get_vvar("event").regname
+ or vim.fn.reg_recording()
local register = yank and vim.api.nvim_get_vvar("event").regname
or vim.fn.reg_recording()
-- get a list of all buffers
local all_buffers = vim.api.nvim_list_bufs()
-- iterate over all buffers, updating the matching ones
for _, buffer in pairs(all_buffers) do
-- get info about the buffer
local buffer_name = vim.api.nvim_buf_get_name(buffer)
local buffer_filetype =
vim.api.nvim_get_option_value("filetype", { buf = buffer })
-- if the buffer has the 'registereditor' filetype and is named
-- @<register>, then it should be updated
if
buffer_filetype == "registereditor"
and buffer_name:endswith("@" .. register)
then
-- get the content of the register
local reg_content = vim.api.nvim_get_vvar("event").regcontents
- local buf_lines = reg_content:split("\n")
+ local buf_lines = yank and reg_content or reg_content:split("\n")
-- update the buffer with the register contents
vim.api.nvim_buf_set_lines(buffer, 0, -1, false, buf_lines)
end
end
end -- update open RegisterEdit buffers when a macro is recorded
vim.api.nvim_create_autocmd({ "RecordingLeave" }, {
- callback = internals.update_register_buffers,
+ callback = function()
+ internals.update_register_buffers(false)
+ end,
})
+ -- update open RegisterEdit buffers when text is yanked into a register
+ vim.api.nvim_create_autocmd({ "TextYankPost" }, {
+ callback = function()
+ internals.update_register_buffers(true)
+ end,
+ })But it gave an error on the |
|
Oh, no worries I forgot about |
…ust by recording Related to tuurep#12.
I think this is the only outstanding issue. All registers except the Examples
It's a shame that
|
|
Looking at this now, I realize one additional problem: When a register automatically updates like this, it sets this is probably easy to fix I'll take a look at the final |
|
Yeah this has some serious complications, because ideally we'd update the buffer whenever a register's contents has changed in any way, doesn't work either with for example:
when Then there are a few specialties like the So the difficult part is that if we can't do it all, where should we draw the line? Gotta investigate if it's at all possible to have a generic: "if a register's contents has in any way changed, update visible buffers" Edit: loose idea for the cases of
Edit: more registers that update in a more special way:
|
|
Hmm, so about the Maybe we could consider an approach:
or something similar? Did a quick test that the
|
|
This was a bit brainstormy 😄 we don't have to do anything exactly as above but let me know if it gave you an idea |
ec80739 to
8b498a5
Compare
Yes, missed that. Fixed.
I misread the docs on this one. What it actually is talking about is the black hole register, which is That being said, we should probably disable
Yes, I think
Yeah... some of these might be tricky. Need to look into it. |
|
Nice, very cool. The I now realized that using Another edge case:
On
Putting out a message like "Blackhole register will always be empty" is a fine alternative too, but I find it harmless that it can be opened tbh, and then we don't even need a special message? Yeah, the fact that Some more ideas:
|
Actually now that I think about it, this issue applies to all registereditor windows. If you modify the buffer and don't save it, then modify the underlying register, your changes are deleted. Vim has various ways of handling this (swap files, eww gross!) and that message we've all seen before: I suppose if the buffer is modified by the user and then the register updates, maybe we should issue a warning or keep the modified unsaved content or something. Or keep the current behavior of just blowing it away. What do you think?
It does for me. Screen.Recording.2025-05-12.143010.mp4
I'm not sure the current behavior is right. If you open
Yes to both of these. Should look into it. NoteI added a TODO list to the PR description. |
|
On file overwrite and undo: I like the behavior where it changes without prompting (or as you say, "just blowing it away"), but only in the special case of It appears like you can easily get your last unsaved state back by undoing in the registereditor, but that's where I hit that What I meant about undo not setting
^ can you reproduce?
Yeah although the way I see it that's precisely working as expected if we go by vim help description:
Actually maybe the closest to accurate would be to wipe out that buffer's contents on save? 😄 However yes, totally agreed it just makes no sense to edit that buffer. My favorite, kinda logically sound solution would be that wipeout on save, though. Do you see what I mean with this? It's kinda like an Easter Egg though... Thanks for the Todo, very nice |
…ust by recording Related to tuurep#12.
64b795c to
dd86730
Compare
|
My latest update allows for updating the buffers automatically using |
related to tuurep#12.
|
Sounds great! When that is out of the way, we are very close to the finish line. I'll open the issue, btw it's ok to remove the whole test suite
Yeah absolutely P.S. I may want to refactor/rename some stuff in the end and squash some of the more WIP parts of the commit history |
This was too complicated, see tuurep#22
4bd4244 to
25be829
Compare
|
This is really quite finished! on the 2 failing tests: #12 (comment) The
The
Should see if it happens for example on Update:
Update: Maybe relevant for the ( But the test didn't pass when temporarily trying without the readonly property so maybe not. The warning is pretty obtrusive on open of the readonly buffers anyways though. I'd like to make it quiet on open, and noisy only when trying to write. |
Lack of restarts just happened to not be an issue for these tests, but they were meant to restart. Most extensive note on the most confusing failing test.
50e0499 to
712f4b2
Compare
In addition, readonly buffers are set as `nomodifiable`, now they're:
- nice to read, doesn't give "Warning: Changing a readonly file"
errors when opening and initializing contents with a delay
- clear that you cannot edit them: no matter what, those registers
cannot be written to
|
Patched On open, literally set the buffer contents as More important change: I made it so readonly buffers are also nonmodifiable (similar to helpfiles when you try to edit them: you won't be allowed) And that they never show the error Worst of all was that readonly regs contents came in with a delay due to this warning. So, only 1 failing test left! |
|
Spotted a mistake, the whole time I've thought Sigh. Todo: tomorrow |
|
It's adding a little mess but something that should be rethought in the future anyways. Related: #19 |
I mistakenly thought @# is a readonly register. It can be written to,
but only if the content is a substring matching an existing buffername,
or an existing buffer id.
@# and @= need to update themselves immediately after write. This has
worked on :w, but only because:
- you're on the cmdline, not in the buffer
- CmdLineLeave is fired, refreshing all register buffers
410efdf to
7d6d6bc
Compare
|
What in tarnation. Now writing the I'll make a separate test file for write behavior, getting it mixed up with autocmd autorefresh is making this harder. |
f0d6656 to
ad19ed5
Compare
|
Somewhere along the way introduced a bug that multi-line contents can't be written (the register becomes empty) On any register, not just |
037570e to
aeef019
Compare
Too confusing when I'm testing autorefresh and what happens on write at the same time. Currently there is a big bug that multiline contents can't be written to registers, the reg becomes empty instead.
aeef019 to
2aa13d0
Compare
|
Big progress! I could not fix the multiline write bug before reworking the whole See commit message: At first I thought this is a big breaking change, but it turns out the Related and now easier to implement: #19 |
At first I thought this is a big breaking change, but it turns out the
'newline at the end' -semantics are already similar, if not exactly the
same as what I achieved with my hacky approach before, see:
:h setreg()
If {options} contains no register settings, then the default
is to use character mode unless {value} ends in a <NL> for
string {value} and linewise mode for list {value}. Blockwise
mode is never selected automatically.
Related and now easier to implement: tuurep#19
a4265c2 to
659bdc4
Compare
|
@nullromo I'm quite finished, could you run the tests and tell me what you see?
I can't make sense of that But certainly doesn't seem like a real problem, just some test environment thing? Edit: also do the system cb/selection tests ever fail for you? (any of the |

Related to #2.
When a macro is recorded, text is yanked, commands are run, etc. update the contents of whatever registers changed.
Problems
Already solved, see discussion below
Buffer collision
If the user has a buffer named
@afor some other reason, it will be modified. One way around this is to have this plugin keep a map of buffers that it has opened. For instance, we could build a table like{ a = { 1000, 1001, 1002 }, b = { 1005, 1007 }, }and that way we would know exactly which buffers to update. In this case, if register
achanges, we need to update buffers 1000, 1001, and 1002. If registerbchanges, then we need to update buffers 1005 and 1007. Every time we open a new:RegisterEditbuffer, we have to add it to this table. Every time we close one of those buffers, we should remove it from the list.No live update
This still doesn't handle the "the buffer would update in real-time (character-by-character) while recording the macro" feature from #2. I don't know if this is possible. Vim registers are only updated when the macro is finished being recorded. There is no autocommand event for generic keypresses. So it might not be possible. In theory you could register an autocommand on a whole bunch of different events, like
CursorMovedand such, but I think there would be cases that are missed. Not 100% sure. But maybe that's better than nothing. At the very least, after the macro is done it would be updated properly.TODO list
CmdlineLeaveto update certain registers (:,/, and=).-)._) when it is modified.InsertLeaveto update.register.TextYankPostto update numbered registers (0-9).#and%)./register when*or#are pressed from normal mode.ufrom the-register edit buffer.FocusGainedlistener to update system clipboard registers.Not Possible
These would become possible if a
RegisterChangedevent existed.*and+).FocusGainedas a decent approximation.g*,g#,gd, andgD