GithubHelp home page GithubHelp logo

Comments (21)

fent avatar fent commented on May 8, 2024 1

hey @zhimsel i no longer use this plugin, so i'm not as incentivized to go through with the change. plus, i'm not a huge fan of adding options to fix behavior. imo the uses case that inspired the change is a bug, but maybe the way i attempted to fix it was wrong and broke other things, and should be done the right way, not with an option that would further complicate code and confuse users.

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

@fent would you assist me in finding out what happens exactly, bearing with me if I ask stupid questions? When you speak of a “window”, what do you mean, exactly:

  1. a Vim window as defined in the Vim help, i.e. what is known colloquially as a split;
  2. or a Vim window from a window manager POV, i.e. a GUI or terminal muxer window?

from vim-stay.

fent avatar fent commented on May 8, 2024

When I speak of a window, I mean a vim spit window.

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

OK, thanks for that. Hmm, last time I looked, BufWinEnter did not trigger on simply entering a split. The Vim 8.1 help concurs (for what that is worth), stating that it fires:

when the buffer is loaded (after processing the modelines) or when a hidden buffer is displayed in a window (and is no longer hidden).

My point is that though stay creates a view whenever leaving a window (through WinLeave), it cannot by rights load one when you simply switch to an already open window (because BufWinEnter does not fire); I tested for that at the time, more than once, so either Vim’s event handling changed dramatically and without warning, or there is something in your usage scenario and / or configuration triggering an unwanted load event.

Could you give me a detailed, step by step scenario of how the issue is reproducibly triggered for you? Starting with how you start (Neo)Vim and including what exact version and patch level you are using on what OS. Please make a note on how exactly you execute each step (what Vim commands you use, or if you use custom mappings to do so, the mapping code).

Also, once you did that, could you please try to reproduce using a minimal configuration, i.e. a vimrc set up to just run stay and nothing else?

from vim-stay.

fent avatar fent commented on May 8, 2024

so either Vim’s event handling changed dramatically and without warning, or there is something in your usage scenario and / or configuration triggering an unwanted load event.

Could be that the commands I'm using to switch back to the buffer are causing BufWinEnter to fire, even if the buffer is already loaded, and shown in another split.

These following 3 methods I used to switch back all reproduce the issue

  • :e#
  • :b [name]
  • :e [name]

The docs for BufWinEnter do say that it's fired when a name is provided to the :split command, maybe this also applies to the commands I'm using. And maybe the only time this doesn't fire is if you're splitting the currently opened file.

Also, once you did that, could you please try to reproduce using a minimal configuration, i.e. a vimrc set up to just run stay and nothing else?

I'm able to reproduce it when I disable all other plugins except vim-stay :/. I also disabled all of mappings and autocmds.

Could you give me a detailed, step by step scenario of how the issue is reproducibly triggered for you? Starting with how you start (Neo)Vim and including what exact version and patch level you are using on what OS.

VIM - Vi IMproved 8.0 (2016 Sep 12, compiled May 17 2018 15:09:32)
macOS version
Included patches: 1-1850

Steps to reproduce

  • Open a file with vim vim file1.txt
  • Scroll halfway through file by pressing ctrl+D or searching for text I know is halfway
  • Create a split :split
  • Scroll to top of file to note different position, still on first split gg
  • Open a different file :e file2.txt
  • Switch back to first file :e# (or :b file1.txt or :e file1.txt)
  • Note that the position of this split when switching back matches the other split, instead of being at the top of file

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

Hm. So I was able to reproduce the behavior with neovim 0.3.4 using a minimal vimrc (blank, except for loading vim-stay). I'm not sure what the best course of solution here is, but I'll dig into the code here to see if I can come up with anything.

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

So, thinking about this more, I'm not sure that this isn't desired behavior. Let's think about it this way: when you split the open buffer into 2 windows, it's creating a view port into that file for each window. However, there's still only one buffer. When you then switch one of those two windows to another buffer (by opening another file with :e), you're destroying it's view port.

As far as I know, vim doesn't keep track of view ports (except for the ones open and visible), only buffers. After opening the second buffer, the first window is no longer viewing the first buffer. When you switch that window back to viewing the first buffer, vim-stay does its job and scrolls to the same place where the second window is. In other words: the most recently-scrolled-to place in that buffer (because the other window is still open and scrolled to that point).

from vim-stay.

fent avatar fent commented on May 8, 2024

So, thinking about this more, I'm not sure that this isn't desired behavior.

If I start vim without vim-stay, this behavior isn't reproduced. And I think it would be more expected from users that vim-stay persist state across windows, even multiple windows of the same buffer.

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

If I start vim without vim-stay, this behavior isn't reproduced.

Well, the whole point of stay is to add behaviour not present in Vim without it, so that is only natural.

And I think it would be more expected from users that vim-stay persist state across windows, even multiple windows of the same buffer.

Actually persisting different states for different windows is both impossible while using Vim view sessions (these map to the file loaded in a buffer, not to a window) and conceptually unsound (what window state do you want when you re-open a file in a fresh editing session; don’t say “the last” – what if there were more than one window open when you last quit?).

@zhimsel is right insofar as this is, technically speaking, expected behaviour, because the usage pattern above is not to switch to a window, but to re-edit a loaded buffer when wanting to switch. Vim recycles the existing window when one does so, so it feels equivalent, but it is not (see the :e help, which is quite clear about the fact that using it on an open file triggers a fresh edit). Real window switching using Ctrl-W commands or (heresy) the mouse should not trigger a re-edit.

This being said, I agree with @fent that what happens to them, technically correct or not, feels wrong, thus violating the software design principle of least surprise. An obvious out would be to get rid of theWinLeave event to save view state (as stated before, replacing BufWinEnter for view loading is not an option unless we want to strip the plug-in of most of its functionality). However, I am pretty sure I originally put it there for a reason, i.e. BufWinLeave not firing in all desirable situations.

Could you both try to exercise stay with the lines 85 and 86 of plugin/stay commented out, trying different split and quit situations (with none, one or more windows on the same buffer open at different positions, for instance) to see if the results are still satisfactory?

If this doesn’t pan out, the aternative solution I can think of ATM would be to check for the number of windows a buffer is shown in, and only save the view when that number is one. The problem with that is that we would need to shim win_findbuf() on older Vim versions, or up compatibility requirements … EDIT: turns out I already did that when creating the whole window ID shim autoload module.

from vim-stay.

fent avatar fent commented on May 8, 2024

Could you both try to exercise stay with the lines 85 and 86 of plugin/stay commented out, trying different split and quit situations (with none, one or more windows on the same buffer open at different positions, for instance) to see if the results are still satisfactory?

After removing this autocmd, I'm still able to reproduce a slightly different error. Now, the view that was previously saved on the buffer is restored when switching back to it.

So for example

  • I open text1.txt and vim-stay restores the cursor at the middle of the file
  • Split
  • Move to the end of the file
  • Open another file
  • Switch back to first file
  • The cursor is restored to the middle of the file

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

Well, I guess we all know why WinLeave was there in the first place now. I’ll go ahead and declare this line of thinking abortive.

I am currently tending towards agreeing with Zach and declaring these “errors” expected behaviour: stay is behaving both consistently with Vim’s (convoluted and not altogether intuitive) file handling model and in a technically correct way.

I still am with @fent insofar as that technically correct behaviour runs against superficial expectations, and I‘ll ponder possibilities to alleviate the problem, but I don’t think a poor fit between a certain usage pattern and the plug-in warrants gutting its feature set. Of course, that decision is ultimately @zhimsel’s, not mine …

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

@fent I don’t want to give the impression I am dismissing your concerns lightly, but your usage pattern for buffer activation really is orthogonal to the plug-in’s declared intent, i.e. reliably restoring the last view state whenever a buffer is displayed in a buffer: on startup in any combination of splits and tabs, on unhiding, on cycling through with :xdo commands. Unluckily, there is no way to differentiate between “this buffer has been loaded into a window and needs its view state reloaded” and “this buffer has been loaded into a window but should not have its view state restored” without knowing user intent.

One way to declare this intent would be to load your reference split into a preview window instead of a regular one, as stay ignores the former. This would at least provide a workaround to your problem until we can think of a better way…

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

I might have an idea how to handle this, thanks to an insomniac night. Because it is thanks to an insomniac night, I ’d like to run this by you both, @fent and @zhimsel.

It seems to me the issue of recognising when there is no need for a saved view state load can be reduced to 1. a buffer does not really enter a window, just technically, firing a misleading BufWinEnter, 2. the view state of that window consequently does not change.

How about we add a window view state heuristic where, if 1. the window contains the same buffer as before BufWinEnter fired and 2. other observable view state elements (essentially what winsaveview() returns, I guess) are unchanged after it fired, we skip view session loading? To my admittedly sleep deprived brain, this sounds like it should resolve the issue while maintaining all of the current feature set, and that without introducing major new corner cases (except maybe a scenario where a real reload is triggered on a buffer with the cursor positioned at the beginning of the file … that one will lose fold state through the reload, as heuristics will fail to detect the change).

Please mull this over and point out the failings in my reasoning; it sounds too good to be entirely true, and I don’t trust the part of my brain that is awake right now …

from vim-stay.

fent avatar fent commented on May 8, 2024

if 1. the window contains the same buffer as before BufWinEnter fired

How is this checked? "before" as in, before switching to a different buffer and then switching back?

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

How is this checked?

My current thinking is to do that by setting a window scoped dictionary variable (w:_stay) whenever we write a view session file storing the buffer name and the window state at this point. We then compare the current values to that before we load a view session.

In your scenario, what would happen would be that:

  1. You open file A in window 1. stay loads its view session.
  2. You open file A again in window 2, switching to it in the process. stay writes a view session for file A based on the state of window 1 and loads that in window 2. The status variable for window 1 is set, storing cursor position and the fact it shows file A.
  3. You change the view state of window 2.
  4. You switch back to window 1. stay repeats the above steps for window 2; your saved view session for file A now reflects the state of window 2. However, the window status variable for window 1 tells stay neither the buffer nor the cursor position have changed since we were last there. View session loading is skipped.

Any logical errors you can see?

from vim-stay.

kopischke avatar kopischke commented on May 8, 2024

Any logical errors you can see?

And by that I mean not just in the scenario I laid out above, but also for alternative usage patterns, e.g. switching via window commands, switching via closing windows, hiding / unhiding buffers, loading from arglist, :xdo commands, loading multiple copies of a file on Vim start etc.

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

Hm. I'm not opposed to the method @kopischke described above. That seems like a reasonable way of handling this behavior change without overtly affecting "normal" usage.

@fent I can't guarantee I'll be able to implement this any time soon (my work schedule is insane right now), so I'll happily review a PR if you wanted to write one. Otherwise, I'll do my best to write this up when I have time.

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

@fent is this still an issue for you? Sorry it took so long for me to get back around to this, but it's possible I'll have some time very soon to work on this, if it's still relevant.

from vim-stay.

fent avatar fent commented on May 8, 2024

hi @zhimsel , thanks for looking into this again. i am still able to reproduce the steps from this comment above, with the latest version of this plugin, and without making the changes mentioned in the comment.

meanwhile, i've been using the version from this PR and it doesn't have the issue. although i understand that the way it's fixed in the PR may not be the best way to fix it.

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

Got it, thanks. I'll hopefully have some time to hack on this in the next couple weeks.

from vim-stay.

zhimsel avatar zhimsel commented on May 8, 2024

@fent now that it's well past a "couple of weeks" later 😉 : I also have an alternative idea, which would be easier to implement, and solve your particular problem (and allow you to switch back upstream). We could create a feature-flag variable the user can set which would simply switch the autocommand events to how you proposed them in #45.

As long as there's a clear explanation of what the setting does (and why it may be necessary to use), I'd be happy to merge that.

I'm not saying we can't/shouldn't modify the plugin as @kopischke; I just know I won't have the time necessary to fully test and implement it.

If you're up for creating a PR, I'd be happy to review and merge it. If not, I can make the changes myself fairly soon.

from vim-stay.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.