How should I handle 'stickybuf' fallback behavior?

103 views
Skip to first unread message

Colin Kennedy

unread,
Dec 27, 2023, 1:42:43 PM12/27/23
to vim...@vim.org

Hi everyone,

I hope this is the right place to ask a question to Vim maintainers. My question is about this post: https://github.com/vim/vim/issues/6445

The summary of the post above is “I would like a ‘local to window’ option that pins a buffer to that window”. It’s a great idea however implementing it requires changes to commands in Vim. I was hoping to ask a couple questions. One about Quickfix and a related question about :argdo, :bufdo, :cdo, etc.

Quickfix + :cnext related commands

For example, if you have a window layout like this:

+--------------------+
|                    |
|        code        |  'nostickybuf'
|                    |
+--------------------+
|                    |
|      terminal      |  'stickybuf'
|                    |
+--------------------+
|      quickfix      |
+--------------------+

Where the terminal buffer’s window has stickybuf' enabled and 'switchbuf' includes 'uselast', I changed :cnext and other commands to prefer the last 'nostickybuf' window. But what should happen in that case when there is only one 'stickybuf' window + quickfix window, like this?

+--------------------+
|                    |
|        code        |  'stickybuf'
|                    |
+--------------------+
|      quickfix      |
+--------------------+

Here’s some ways I could see a command like :cnext running -

  1. Error saying something like “cannot switch buffer because of ‘stickybuf’”
  2. Succeed to change to the next quickfix entry, just don’t change the window’s buffer to show it
  3. Something else. Not sure what!

What do you think of this case?

:foodo-related commands (:argdo, :bufdo, :cdo, :windo, etc)

Normally running these “do” commands will change a window to view whatever buffer you’re currently acting upon. Like the quickfix commands, I have it set to prefer a window that is 'nostickybuf'. But what should happen if there is no fallback, 'nostickybuf' window to choose? Should the “do” command error? Or should it continue to “do” but not change the window’s buffer to show each entry?

I could imagine not changing would cause commands like :bufdo s/foo/bar/c to become more complex because you wouldn’t be able to confirm the replacement in advance. Which led me to think maybe checking for a valid window first before the “do” command runs makes more sense and fail early if there’s no window to choose. What do you think?

The quickfix and “:foodo”-related commands are some of the more complicated cases but once we know what the best behavior in those cases are, I’m sure the rest will be easy.

Thank you!
Colin

shane.qian

unread,
Dec 28, 2023, 1:37:53 AM12/28/23
to vim...@googlegroups.com, vim...@vim.org
> I hope this is the right place to ask a question to Vim maintainers. My
> question is about this post: https://github.com/vim/vim/issues/6445

not sure if it was right place, but i replied it in your ticket.
or anyway, please refer 'https://github.com/vim/vim/issues/8122'

i was struggle or try to suggest a similar idea about 'sticky window',
but later i felt it maybe not a vim style, and realized 'preview window' can help it in most cases.

--
shane.xb.qian

Colin Kennedy

unread,
Dec 28, 2023, 2:21:29 AM12/28/23
to vim_dev
Hi Shane,

I replied to you over at #6445. As for the two tickets linked, #8122 is very different in terms of the issue described and a proposed solution. It's hard to compare them. A preview window is able to help in the limited case that #8122 describes but #6445 describes a desire to give windows a specific purpose. Vim already has terminal buffers, pop-ups, netrw folder views, etc but there's no great way to describe a specialty window that's meant to be transient, like a preview window, vs a special window/buffer that you want to keep around for long periods of time and don't want Vim pulling focus away by accident. The proposed solution from #6445 in my opinion answers this need very effectively.

> I changed :cnext and other commands to prefer the last 'nostickybuf' window.

To clarify this point, I didn't change any of these commands directly. I simply changed the behavior of "find/save the previous window" to ignore windows that have 'stickybuf' applied. All other commands / logic is the same and 'switchbuf' remains unchanged. I was really pleasantly surprised at how well that works!

Hope this makes things more clear :)
Colin

Christian Brabandt

unread,
Dec 28, 2023, 5:47:46 PM12/28/23
to vim...@googlegroups.com

On Mi, 27 Dez 2023, Colin Kennedy wrote:

> Hi everyone,
>
> I hope this is the right place to ask a question to Vim maintainers. My question is about this post: https://github.com/vim/vim/issues/6445

You found the right place :)
>
> The summary of the post above is “I would like a ‘local to window’ option that pins a buffer to that window”. It’s a great idea however implementing it requires changes to commands in Vim. I was hoping to ask a couple questions. One about
> Quickfix and a related question about :argdo, :bufdo, :cdo, etc.
>
> Quickfix + :cnext related commands
>
> For example, if you have a window layout like this:
>
> +--------------------+
> | |
> | code | 'nostickybuf'
> | |
> +--------------------+
> | |
> | terminal | 'stickybuf'
> | |
> +--------------------+
> | quickfix |
> +--------------------+
>
> Where the terminal buffer’s window has stickybuf' enabled and 'switchbuf' includes 'uselast', I changed :cnext and other commands to prefer the last 'nostickybuf' window. But what should happen in that case when there is only one
> 'stickybuf' window + quickfix window, like this?
>
> +--------------------+
> | |
> | code | 'stickybuf'
> | |
> +--------------------+
> | quickfix |
> +--------------------+
>
> Here’s some ways I could see a command like :cnext running -
>
> 1. Error saying something like “cannot switch buffer because of ‘stickybuf’”
> 2. Succeed to change to the next quickfix entry, just don’t change the window’s buffer to show it
> 3. Something else. Not sure what!

I don't understand option 2. How would it succeed, if you do not change
the windows buffer?

If you think of 'stickybuf' as making the window containing the buffer
immutable, I would think we should open a new window then. Thinking
about it, it seems similar to how help files are handled
e.g. what would happen if your code window would have been a help window
instead. This also sounds like you may want to reuse the 'buftype'
option and add stickybuf as a new special value for it?


> What do you think of this case?
>
> :foodo-related commands (:argdo, :bufdo, :cdo, :windo, etc)
>
> Normally running these “do” commands will change a window to view whatever buffer you’re currently acting upon. Like the quickfix commands, I have it set to prefer a window that is 'nostickybuf'. But what should happen if there is no
> fallback, 'nostickybuf' window to choose? Should the “do” command error? Or should it continue to “do” but not change the window’s buffer to show each entry?
>
> I could imagine not changing would cause commands like :bufdo s/foo/bar/c to become more complex because you wouldn’t be able to confirm the replacement in advance. Which led me to think maybe checking for a valid window first before the
> “do” command runs makes more sense and fail early if there’s no window to choose. What do you think?
>
> The quickfix and “:foodo”-related commands are some of the more complicated cases but once we know what the best behavior in those cases are, I’m sure the rest will be easy.

Same here, if 'stickybuf' option is set, can we open a new window
instead?

Thanks,
Christian
--
Strangelove Reproduction:
Having children to make up for the fact that one no longer
believes in the future.
-- Douglas Coupland, "Generation X: Tales for an Accelerated
Culture"

Colin Kennedy

unread,
Dec 28, 2023, 9:01:37 PM12/28/23
to vim_dev

Hi Christian,

Where the terminal buffer’s window has stickybuf’ enabled and ‘switchbuf’ includes ‘uselast’, I changed :cnext and other commands to prefer the last ‘nostickybuf’ window. … I don’t understand option 2. How would it succeed, if you do not change the windows buffer?

Admittedly that #2 was not well thought out. I was too closely relating :cnext-and-family commands to :foodo-and-family commands. I’m happy to do #3 as you’ve suggested :)

If you think of ‘stickybuf’ as making the window containing the buffer immutable, I would think we should open a new window then. Thinking about it, it seems similar to how help files are handled

Sure, we can do that. I’ll open a new window according to 'switchbuf' like :cnext and others already do.

This also sounds like you may want to reuse the ‘buftype’ option and add stickybuf as a new special value for it?

Originally I had 'stickybuf' as a “local to buffer” option like 'buftype' but setting 'stickybuf' on the buffer frequently caused hiccups during testing. For example, if 'stickybuf' buffers are not hidden, there’s a chance someone could open the 'stickybuf' buffer by accident and then think “whoops! I didn’t mean to go to this buffer, I’d better back out!” and try to call :edit # or something only for it to fail because the user is in a 'stickybuf' buffer. (I later added forceit[!] to those commands, but that’s besides the point). It was a frequent annoyance for me, during testing. 'stickybuf' as a “local to window” option was much more natural in my opinion because then the only concern left to solve is “when we split a 'stickybuf' window, should the new window also be 'stickybuf'?”. Currently I’m leaning towards “no” because if you’re making a split, you’re probably about to switch away from the buffer. Maybe that’s a bad assumption, please let me know.

Regarding buffer vs window attribute, I figured if someone wants 'stickybuf' to be buffer-like, they could still achieve the same effect even if 'stickybuf' is a window option by using a buffer autocmd.

Same here, if ‘stickybuf’ option is set, can we open a new window instead?

Do you mean

“if only windows with 'stickybuf' remain, rather than erroring, can we open a new window instead?”

or

“if 'stickybuf' option is set, can we always open a new window instead”

Either way works for me. Though I’d prefer it as a last resort, personally. Would you also want this new window opened according to 'switchbuf'? Currently I don’t know whether :argdo, :bufdo, :cdo consider 'switchbuf'. The :help doesn’t mention it, that I could find.

Last question for now - if we keep 'stickybuf' as a “local to window” option, should we add a ! to :windo? From :help :bufdo, I noticed a line that says “When the current file can’t be |abandon|ed and the [!] is not present, the command fails.”. Since :windo has no !, I was wondering if 'stickybuf' would be a good opportunity to give :windo parity with the other :foodo[!] commands.

Thanks,
Colin

Message has been deleted

Colin Kennedy

unread,
Jan 17, 2024, 2:25:15 AM1/17/24
to vim_dev

Hello!

I had to take a break from this for a while but I’m back at it. Since then, I’ve encountered some scenarios that I wanted to double-check with you all.

Previously, we talked about creating a new split window if :foodo is called and all of the current windows are 'stickybuf'. I’ve added that behavior for :argdo, :bufdo, :cdo, and others.

Now for my questions, below:

  1. What about :ldo? Location lists are tied to one window, I believe. So if you create a window, then a location list, then set that window to 'stickybuf', and then call :ldo to try do an operation on multiple buffers, I don’t think we could split the window in that case, right? Because the location list is tied to a window, the newly-split window would be unrelated. What happens in this case - should the user get an error unless [!] force-it is included?
  2. Same question as #1 but for :lnext and other commands related to location lists. I’m not sure if it makes sense to split the window if calling :lnext would visit another buffer. We can do that for :cnext and its family of commands but I’m not sure about :lnext. Should I give the user an error message unless [!] force-it is added, instead? What should happen in :lnext‘s case?
  3. If I call :windo should it also fail only any encountered window is 'stickybuf'? I was thinking we could add [!] to mean “force-it on all windows, including 'stickybuf' windows”. Currently there’s no :windo! so it seemed like a good reason to add [!] to :windo.

If you could weigh in on what the expected behavior should be, that’d be really helpful.

Thank you!
Colin

Christian Brabandt

unread,
Jan 17, 2024, 2:29:33 PM1/17/24
to vim...@googlegroups.com

On Di, 16 Jan 2024, Colin Kennedy wrote:

> Hello!
>
> I had to take a break from this for a while but I'm back at it. Since
> then, I've encountered some scenarios that I wanted to double-check
> with you all.
>
> Previously, we talked about creating a new split window if `:foodo` is
> called and all of the current windows are `'stickybuf'`. I've added
> that behavior for `:argdo`, `:bufdo`, `:cdo`, and others.
>
> Now for my questions, below:
>
> 1. What about `:ldo`? Location lists are tied to one window, I
> believe. So if you create a window, then a location list, then set
> that window to `'stickybuf'`, and then call `:ldo` to try do an
> operation on multiple buffers, I don't think we could split the window
> in that case, right? Because the location list is tied to a window,
> the newly-split window would be unrelated. What happens in this case -
> should the user get an error unless `[!]` force-it is included?

Yes, location lists are window-specific. I would think an error unless
'!' is given is reasonable behaviour.

> 1b. Same question but for `:lnext` and other commands related to
> location lists. I'm not sure if it makes sense to split the window if
> calling `:lnext` would visit another buffer. We can do that for
> `:cnext` and its family of commands but I'm not sure about `:lnext`.
> Should I give the user an error message unless `[!]` forceit is added,
> instead?

Yes, also reasonable.

> What should happen in `:lnext`'s case?

Did you not just talk about :lnext?

> 2. If I call `:windo` should it also fail only any encountered window
> is `'stickybuf'`? I was thinking we could add `[!]` to mean "force-it
> on all windows, including `'stickybuf'` windows". Currently there's no
> `:windo!` so it seemed like a good reason to add `[!]` to `:windo`.

I don't think so. If you do :windo :set nu, why should this fail for
sticky buffers? I don't think :windo should fail in general, but we
should rather leave this to the individual commands. E.g. when trying to
load a new buffer in the window, this command should fail (and then
cause :windo fail as well).

> If you could weigh in on what the expected behavior should be, that'd
> be really helpful.
>
> Thank you! Colin


Thanks for working on it. I hope a few people can try it out once you
have the patch ready.


Thanks,
Christian
--
Contains a substantial amount of non-tobacco ingredients.

Colin Kennedy

unread,
Jan 21, 2024, 5:03:27 AM1/21/24
to vim_dev

Hello again,

Some good news and bad news.

Good news - I have a branch working and it even passing GitHub’s CI, which is comforting!
Bad news - I still have many questions ranging from simple things such as

“What should the error code be for when we need to display a message?”
I picked E922 since it is currently unused but I don’t know if there’s a standard to the error codes that I’m stepping over

to more complex decisions such as

  • The :drop command has no [!] so 'stickybuf' completely disables it. Are we okay with adding [!] so it has a fallback?
  • Several mappings are disabled during 'stickybuf'. Do we want to change :normal! the-disabled-mapping to force the mapping on 'stickybuf' windows? :normal! already has an existing, different meaning.
  • Should X group of commands that follow a specific 'stickybuf' behavior merge into group Y other-commands-behavior?

And other decision-making related questions like that. Would you rather we keep communications to here while each point is sorted out or would you want to see a GitHub draft PR sooner and I can place remaining questions there? I’m happy to do either.

Thanks,
Colin

Christian Brabandt

unread,
Jan 22, 2024, 3:12:51 PM1/22/24
to vim...@googlegroups.com

On So, 21 Jan 2024, Colin Kennedy wrote:

> Hello again,
>
> Some good news and bad news.
>
> Good news - I have a branch working and it even passing GitHub’s CI, which is comforting!
> Bad news - I still have many questions ranging from simple things such as
>
> “What should the error code be for when we need to display a message?”
> I picked E922 since it is currently unused but I don’t know if there’s a standard to the error codes that I’m stepping over

Good news. I think picking a free error code is fine. Just add a
reference in the help file at :h E922 which should probably sit at the
description of the stickybuf option.

> • The :drop command has no [!] so 'stickybuf' completely disables
> it. Are we okay with adding [!] so it has a fallback?

Why do we need this? If the current buffer is a 'stickybuf' buffer, why
can't we open a new window with the :drop command?

> • Several mappings are disabled during 'stickybuf'. Do we want to
> change :normal! the-disabled-mapping to force the mapping on
> 'stickybuf' windows? :normal! already has an existing, different
> meaning.

What mappings? By default there shouldn't be any mappings, so why do you
need them to be disabled? If you are talking about certain functionality
such as :b for switching a buffer, I think that should simply just cause
an error and abort for the sticky buffer.

Regarding the current :norm! meaning:
:norm! executes commands without applying mappings, such that if you do
:nmap k j
you can still use :norm! k to mean go upwards.

> • Should X group of commands that follow a specific 'stickybuf'
> behavior merge into group Y other-commands-behavior?

I don't understand this question.

> And other decision-making related questions like that. Would you
> rather we keep communications to here while each point is sorted out
> or would you want to see a GitHub draft PR sooner and I can place
> remaining questions there? I’m happy to do either.

Yes, please go ahead and create a PR. So we can easily test it and you
can get better feedback.

Thanks,
Christian
--
Physician: One upon whom we set our hopes when ill and our dogs when well.
-- Ambrose Bierce

Colin Kennedy

unread,
Jan 22, 2024, 11:23:58 PM1/22/24
to vim_dev
Hi Christian,

Sorry for the miscommunication there, the previous bullet points were rhetorical so I didn't elaborate on them as much as I normally would. From our chats, it sounds like, in general, you would prefer "(find or) split a window" where my current branch tends to do "fail X unless X[!]" instead. That's trivial to fix though so we can pivot as needed.

Let's get a PR up. This will make much more sense when viewed in context, I think.


Thank you!
Colin
Reply all
Reply to author
Forward
0 new messages