romgrk / barbar.nvim

The neovim tabline plugin.
2.2k stars 81 forks source link

feat: `scroll_lock_pinned` #401

Closed Iron-E closed 1 year ago

Iron-E commented 1 year ago

Allows users to lock elements in the tabline as visible.

require'barbar'.setup {
  scroll_lock_pinned = true,
}

If I can get it working, I will use #408 instead as it will be more compatible with #175.


Todo:


Closes #393

Iron-E commented 1 year ago

@otavioschwanck this is probably serviceable if you're looking to use this feature right now.

I'm going to keep working on an alternate implementation (noted in the PR body) which may replace this one if I can get it working. Until then, this implementation can likely fit your use case

romgrk commented 1 year ago

Do you mind describing the behavior you're intending to implement here? And the different cases, e.g. what happens where there are multiple pinned buffers.

Iron-E commented 1 year ago

Essentially, if a type of buffer is scroll_locked, when scrolling would cause the a buffer of that type to go off-screen, it will stay on-screen at the edge.

Example:

The behavior on this branch is:

The behavior on my feat/393-alt branch (which is still WIP):

The feat/393-alt branch will be more compatible with #175 because this branch can never show things at the end.

romgrk commented 1 year ago

Can you remind me what's the difference between a pinned and non-pinned buffer?

I've been thinking about these, and I feel like I'd want these to be like my browser pinned tabs instead of our current implementation: image

Wdyt about that? It could also simplify the implementation here, we could have a static section at the start of the barbar that would be a container for the pinned buffers.

Iron-E commented 1 year ago

Can you remind me what's the difference between a pinned and non-pinned buffer?

Sure thing— pinned buffers have two primary properties:

  1. They stay on the left of the bufferline (and when #175 hits, potentially also the right)
  2. They persist between sessions

Wdyt about that? It could also simplify the implementation here, we could have a static section at the start of the barbar that would be a container for the pinned buffers.

That's basically what feat/393-alt does. It's a little complicated in practice, because we have to:

  1. Calculate the "theoretical" layout of the bufferline, as if nothing was pinned/scroll_locked (i.e. Layout.calculate)
  2. Iterate through the bufnrs param to generate_tabline to:
    1. set the scroll (iff the refocus param to generate_tabline is not false), since all the following calculations depend on it
    2. find the pinned/scroll_locked buffers which will be hidden by the current scroll
  3. Re-calculate the layout of the bufferline, knowing now exactly how many buffers will be scroll_locked/pinned
  4. Finally, iterate through the bufnrs using the correct layout

Surprisingly, my WIP implementation is ~25% faster than master (since I save all the calculations done in the first loop, and I can determine which items can be skipped altogether because they will not be visible due to the current scroll). I might as well throw it up as a PR draft since it only has a few bugs left to squash

Iron-E commented 1 year ago

See #408 for the alt implementation I was mentioning. I'm still fussing with it, but I'll get it working eventually. I'll leave this open until I'm sure it's working.

romgrk commented 1 year ago

Ok, ima say I'm a bit wary of #408. I don't like offering too many options, my goal with barbar is to provide great defaults that don't have to be modified (except for the styling, where opinions are more diverse).

What do you think about the following:

This should be good enough for the large majority of users, and ensures we don't add unnecessary complexity to barbar. Simplicity is an important feature.

Iron-E commented 1 year ago

What do you think about the following:

  • We implement pinned buffers like in browsers, with only the icon shown.
  • We store pinned buffers in a separate list, let's say state.buffers_pinned
  • Layout is easy, because:
  • Pinned buffers have a fixed width
  • Unpinned buffers fill the middle area dynamically like they do right now
  • Scroll locking would be implicit: pinned buffers always take the same width on the left of the bar

I'd be fine with that. I can refactor #408 to make that simplified, and potentially even implement #175 at the same time if state.buffers_pinned = {left = {}, right = {}}.

We might want to just set padding_width to 1 for pinned buffers, since only showing an icon would hide the buffer_index (breaking #379), diagnostics, etc. As of #386 you can do this to almost simulate your screenshot:

require'barbar'.setup {
  icons = {
    pinned = {
      buffer_index = false,
      buffer_number = false,
      button = false,
    },
  },
}

We could add another option to hide the filename, and that would get the behavior you're looking for for pinned buffers.

One question: should it be an option to keep the pinned buffers on screen, or should that be forced?

romgrk commented 1 year ago

Not sure if I'd implement #175 ourselves, there is a single request for it with no reactions, and the requester didn't have enough interest to open a PR for it. I think we should just keep it simple and have state.buffers_pinned: integer[], and they'd always be left. And I think #175 would merely be having all of them right; not some left and some right.

romgrk commented 1 year ago

For the options, the default would be that pinned buffers show the icon. We could provide the option to switch the icon for the index or buffer number if requested.

For the initial implementation, we could only have pinned buffers fixed on screen.

I have some time to work on barbar, but if you want to do the implementation I can let you go at it.

Iron-E commented 1 year ago

I have some time to work on barbar, but if you want to do the implementation I can let you go at it.

The #408 branch had some perf improvements that I think I can preserve for the implementation. Glad you're back for a bit, by the way!

romgrk commented 1 year ago

Alright, I'll let you work on #408 then. I think we can close this one, right? I'll try to take a look at #405.

Iron-E commented 1 year ago

Yep, we can close this.