neovim / neovim

Vim-fork focused on extensibility and usability
https://neovim.io
Other
83k stars 5.69k forks source link

shada: "delmark" is not persisted in shada #4295

Closed mbr42 closed 1 year ago

mbr42 commented 8 years ago

if marks are deleted vim updates the .viminfo so that after reopening a file the deleted marks are NOT present anymore. Neovim behaves different so that these marks are still present after reopening.

Expected behaviour

Removing a marker should be updated in the main.shada on file close so that the marker is not present anymore after reopening the file. Otherwise it will remain forever in the file. You can only get rid of it if you use :wshada!. If you use :wshada! to store the actual markers a complete new main.shada is written so you loose all the information of the other files.

Steps to reproduce

nvim -u NONE testfile hack hack hack set marker b on e.g. line 10 in command mode with: 10ggmb close file and reopen show marks with: :marks delete marker b with: delmark b close file and reopen show marks again with: :marks

justinmk commented 8 years ago

Please just leave a comment on https://github.com/neovim/neovim/issues/4288 next time--it will be reopened if needed.

I did confirm my claims in https://github.com/neovim/neovim/issues/4288 using Vim 7.4.52, so I'm not sure what I'm missing. I could not find any explicit documentation on the matter. @ZyX-I can you comment on this?

ZyX-I commented 8 years ago

@justinmk You are probably missing difference between local and global marks. AFAIR Vim takes all local marks from the Vim instance if there is needed buffer and all local marks from viminfo if there is no, so delmarks works. But global marks are always merged, so it does not.

mbr42 commented 8 years ago

So once you have created a mark in a file and have saved the file, the mark will stay forever and can't be deleted anymore without destroying the main.shada file?? Am I right?

ZyX-I commented 8 years ago

@mbr42 You can always edit that file.

mbr42 commented 8 years ago

Hi ZyX-l, I'm sorry to bother you but maybe we misunderstand each other. When I was coding I use a lot of marks in a file and delete them when I don't use the marks anymore. After closing the file as I described above the marks were correctly saved if editing the file with vim. But neovim shows a different behavior. If editing a file with neovim the marks that I have deleted are not saved after closing the file, so that all marks are visible again after reopening it and they can only be deleted with :!wshada but this destroys the main shade file so that the marks from the other files are also removed. vim and I think in an older version of neovim too, I currently don't know the exact version number, don't show this behavior so I think this feature is currently not correctly implemented. If you think it is, can you please describe me a method of how to do this? Thank you very much.

ZyX-I commented 8 years ago

@mbr42 Deleted marks will not be saved unless you deleted them after closing and reopening the file.

And you can edit the ShaDa file by using nvim -i NONE …/main.shada which also allows deleting marks. Quiting Neovim or using :wshada are not the only ways to edit the file.

mbr42 commented 8 years ago

I think to edit the main.shada to only remove a mark from a file seems to be very unproductive in my opinion. But if this should be the design then what else can say?

justinmk commented 8 years ago

@mbr42 The alternative is to (1) not have the merge feature or (2) complicate the logic. Can you provide a use-case explaining why you need to delete marks frequently?

I also assume you saw this explanation: https://github.com/neovim/neovim/issues/4288#issuecomment-186076052

ZyX-I commented 8 years ago

@justinmk Currently deleting marks has the following problems comparing to deleting register:

  1. To delete register one may simply write “empty” characterwise register (actually, not truly “empty”, but “with a single empty line”, but this is insignificant differences) and stay compatible. Current specification does not allow creating “deleted” marks without breaking backward compatibility, so to be compatible one will need to add “deleted {local,global} mark” ShaDa items in place of reusing existing items used for marks.
  2. Writing “deleted local mark” items given the fact that ShaDa may contain many files will bloat the ShaDa file. There are not that much registers to worry about.
  3. Non-empty register may cause problems when @r is accidentally typed (and I sometimes do this). I do not see any problems with not deleted marks except that :marks output will be longer.
justinmk commented 8 years ago

Writing “deleted local mark” items given the fact that ShaDa may contain many files will bloat the ShaDa file.

And this is not a small problem. Loading large shada files takes a noticeable amount of time.

I do not see any problems with not deleted marks except that :marks output will be longer.

One use-case is for plugins like https://github.com/kshenoy/vim-signature/issues/106 which show the sign column if there is a mark. I assume that is what is driving this request, though I would like @mbr42 to confirm.

If that is the use-case, then we could avoid the problem by providing other ways to hide or manipulate the sign column.

mbr42 commented 8 years ago

Gentlemen,

thanks for the discussion. Let me shortly describe my workflow: I'm using the plugin markology: `http://github.com/jeetsukumaran/vim-markology'. This plugin allows me to visualize the valid markers set in a file e.g. with a highlighted line. So when studying and editing code it often happens to me that I set markers for code positions that are interesting for me in order to quickly find the positions again and to jump to them. Then e.g. at the end of the day I close the file and some times later after reopening it I would like to see the marks again. So far so good. Everything is fine, marks are saved and even setting an already setted mark to a different location is also. So after I've finished with a feature I'd like to delete some marks I'm not interested in anymore. But other marks that are still interesting I don't won't them to be deleted. So again after closing and reopening the file the previous deleted marks are still present and not cleared. This is not the way vim behave. Vim wouldn't show the deleted marks anymore. If neovim would follow this behavior of vim again I would be very happy.

If you need some settings of my vimrc or additional information please let me now and I will happily post them.

Again thanks very much for caring.

CallumHoward commented 8 years ago

I have a similar workflow using https://github.com/kshenoy/vim-signature, however I would use marks in this way even without a plugin. Regardless of the implications of a solution, I believe not being able to delete local marks is a valid issue, and would be surprised if this not common to many users workflows. I too would like to see the Vim behaviour restored. Please consider reopening the issue.

KillTheMule commented 8 years ago

Note the comment above, there's a difference in vim's behavior between global and local marks.

justinmk commented 8 years ago

See also https://github.com/neovim/neovim/issues/4288#issuecomment-186076052

CallumHoward commented 8 years ago

So the fact that it works in Vim is an accident because Vim doesn't merge local marks; and for global marks, it has the same behavior as Nvim.

After experimenting I now see the discrepancy with local and global marks in Vim. I tend not to use global marks, and so never noticed before. That being said, intuitively and according to the documentation :delmarks should delete a mark, and I would expect it to remain deleted. The average user may not know about the intricacies of ShaDa, and shouldn't have to learn it to find why :delm doesn't work as expected. "Deleted marks stay deleted" would be functionality I would like to see added to NeoVim (and Vim for global marks), if there is a way to implement the behaviour without detriment to performance.

justinmk commented 8 years ago

Writing “deleted local mark” items given the fact that ShaDa may contain many files will bloat the ShaDa file. There are not that much registers to worry about.

Instead of tracking deleted marks, :delmark could broadcast an event to other running nvim instances in a "p2p" fashion...

FractalWire commented 5 years ago

Writing “deleted local mark” items given the fact that ShaDa may contain many files will bloat the ShaDa file. There are not that much registers to worry about.

I'm not sure to totally understand how ShaDa works. But, if there is only one items per local mark per file in the ShaDa, what difference would it make to have an item with a "deleted local mark" or an actual local mark (that you don't use) ? In the end, the ShaDa file would then have the same number of items, right ?

Current specification does not allow creating “deleted” marks without breaking backward compatibility, so to be compatible one will need to add “deleted {local,global} mark” ShaDa items in place of reusing existing items used for marks.

Instead of creating a new item type, maybe you could change slightly the actual meaning of the *Mark items. For example, instead of having an unsigned integer for columns and lines, you could have a signed one and if those are negative, that means the mark should not be taken into account. Or just add a new boolean key to the mark item that is true if the mark is deleted ? (as it seems doable to add new key and keep backward compatibility)

justinmk commented 5 years ago

But, if there is only one items per local mark per file in the ShaDa, what difference would it make to have an item with a "deleted local mark" or an actual local mark (that you don't use) ? In the end, the ShaDa file would then have the same number of items, right ?

Compared to registers (which are limited to ~30 items), one may have 26+ marks per file, so it's relatively wasteful to store the deleted items. But as you hint, I don't think that cost should prevent a solution here.

Current specification does not allow creating “deleted” marks without breaking backward compatibility, so to be compatible one will need to add “deleted {local,global} mark” ShaDa items in place of reusing existing items used for marks.

As @ZyX-I notes this will be backwards-incompatible. But it's a minor inconvenience, given that

  1. shada files are typically machine-local
  2. it is unusual to run an old nvim after having already installed a newer nvim on the same machine.
  3. the worse case is that the old nvim will show old marks instead of recognizing them as deletd.

Status

Patch welcome.

FractalWire commented 5 years ago

Compared to registers (which are limited to ~30 items), one may have 26+ marks per file, so it's relatively wasteful to store the deleted items.

My point was that you already store potentially unused marks, and that seems already wasteful.

If you add an items for the mark deletion, you would have, in the worst case (if you delete all the mark you created) two items per mark (one for creation, one for deletion).

As you said, if you really want to avoid this kind of overhead, you'd need to use a p2p mechanism to broadcast to other nvim instance.

An alternative, not as effective but maybe less complex, would be to create a command that clean deleted marks from the shada file once we have that new way to indicate a mark is deleted. That would need manual intervention (if you know you only have one nvim session open), but could help keep the shada file clean if you really need it. Different from :wshada! in that it would preserve marks existing in non-opened files.

the worse case is that the old nvim will show old marks instead of recognizing them as deletd.

That feels very much backward compatible to me ;)

To sum up what would be needed to implement this :

  1. upon exiting nvim, copy deleted status of a mark in the shada file
  2. when loading the shada file, only pick marks without the deleted status.

Two ways to implement this :

  1. create a new entry type in the form "deleted {local,global} mark" as suggested by @ZyX-I.
  2. add a new boolean key to the {Global,Local} mark entry type, d for "deleted". True if the mark has been deleted, false or empty otherwise.

The first solution should be totally backward compatible, given that the deleted entry has some timestamp, so any mark older than the deleted entry should be ignored and the ones more recent should be picked up by the newer nvim version, whatever the nvim version you created your mark with. However it has a bit of overhead as you need a distinct entry from the {Global,Local} mark entry type.

The second solution feels more straight-forward to me as you have all the informations you need in one entry. The inconvenient is that it's not backward compatible: if an old nvim instance create or modify a previously deleted mark, it will not modify the deleted key, and so, the more recent version of nvim will not picked it up.

I don't know what should be the prefered way here.

justinmk commented 5 years ago

I would just add an extra "deleted" field to the mark field, as a timestamp value. Then when merging, compare the timestamps.

p0da commented 4 years ago

Has any progress been made on this issue?

mg979 commented 4 years ago

This is the same as https://github.com/vim/vim/issues/1339, that was fixed in https://github.com/vim/vim/commit/8cd6cd8087ccf08e4303dbf5f732fc4b82b917e1, non-test changed code is like 5 lines, it can't be too hard? But shada implementation seems different, still it supports timestamp for marks?

RonanMacF commented 4 years ago

Is this targeted for neovim 5.0? Has anyone found a nice workaround for it? My workflow is similar to that mentioned above.

justinmk commented 4 years ago

Status


Locked to keep the summary visible. You can always chat or open a ticket if you have new information/topics to discuss.