nanozuki / tabby.nvim

A declarative, highly configurable, and neovim style tabline plugin. Use your nvim tabs as a workspace multiplexer!
MIT License
607 stars 21 forks source link

feat: foreach enhancements #154

Closed capsey closed 2 months ago

capsey commented 2 months ago

General improvements to tabs.foreach() and wins.foreach() functions.

props

You can pass an object with additional properties after the render function to add them to the resulting TabbyNode, like hl or margin. Useful to add spaces between tabs since margin isn't inherited by child nodes.

length and index arguments

In addition to TabbyTab/TabbyWin object passed to the render function it will also pass current tab/win's index and total number of tabs/wins. Useful to check if current tab or win is first or last to add proper separators.

not overriding user defined click events

Before adding default click handle to switch to clicked tab, wrap_tab_node function in tabs.foreach() will now check if returned node has already defined its own handle to prevent overriding it.

nanozuki commented 2 months ago

Well done! I think the index and count are useful.

But, can you explain how the "params" works in line.tabs().foreach({callback}, {params}) by example?

capsey commented 2 months ago

TabbyNode has two properties - hl for specifying highlight group and margin for specifying margin text added between each child node. When I was trying to make my theme I noticed that you can't specify them for nodes returned by foreach() functions without saving them into local variable and modifying it, which is cumbersome and makes nodes out of order in the config.

For example, in my config I wanted to have a 1 space separation between tabs. Without this feature you would have to either do:

line = function(line)
  local tabs = line.tabs().foreach(function(tab)
    return { tab.name() }
  end)
  tabs.margin = ' '

  return {
    -- ...
    tabs
    -- ...
  }
end,

or (which will add extra space at the end):

line = function(line)
  return {
    -- ...
    line.tabs().foreach(function(tab)
      return { tab.name(), ' ' }
    end)
    -- ...
  }
end,

And with this feature you can just do this:

line = function(line)
  return {
    -- ...
    line.tabs().foreach(function(tab)
      return { tab.name() }
    end, { margin = ' ' })
    -- ...
  }
end,

Which will add margin to the node returned by foreach. This also might be useful in case more node properties are added in the future.

nanozuki commented 2 months ago

You can do like this, I think there are not too much difference:

line = function(line)
  return {
    -- ...
    {
        line.tabs().foreach(function(tab)
          return { tab.name() }
        end),
        margin = ' ',
    },
    -- ...
  }
end,
capsey commented 2 months ago

This doesn't work, margin applies only to the node it is on and doesn't propagate to the children, and since foreach returns one node with tabs as children, what you shown doesn't add margin between the tabs, but instead to elements before and after foreach, which in this case is nothing.

image

capsey commented 2 months ago

Here I added some elements before and after foreach to demonstrate:

image

nanozuki commented 2 months ago

I'm too busy these days, sorry for late. I got that. You're right, thanks for explaining!