Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: specify icons per buffer activity/state #386

Merged
merged 24 commits into from
Mar 29, 2023
Merged

feat: specify icons per buffer activity/state #386

merged 24 commits into from
Mar 29, 2023

Conversation

Iron-E
Copy link
Collaborator

@Iron-E Iron-E commented Mar 17, 2023

This PR allows customization of the bufferline.icons setting per activity / state, like so:

require'bufferline'.setup {
  icons = {
    -- Configure the base icons on the bufferline.
    buffer_index = false,
    buffer_number = false,
    close = '',
    diagnostics = {…}, -- moved here from the `diagnostics` option
    filetype = {
      -- Sets the icon's highlight group.
      -- If false, will use nvim-web-devicons colors
      custom_colors = false,

      -- Requires `nvim-web-devicons` if `true`
      enabled = true,
    },
    inactive = {separator = {left = ''}},
    separator = {left = ''},

    -- Configure the icons on the bufferline when modified or pinned.
    -- Supports all the base icon options.
    modified = {button = ''},
    pinned = {button = ''},

    -- Configure the icons on the bufferline based on the visibility of a buffer.
    -- Supports all the base icon options, plus `modified` and `pinned`.
    alternate = {filetype = {enabled = false}},
    current = {buffer_index = true},
    inactive = {button = '×'},
    visible = {modified = {buffer_number = false}},
  },
}

When multiple options match (e.g. icons.separator, icons.modified.separator, and icons.alternate.separator), precedence works as follows:

  1. icons.(alternate|current|inactive|visible).(modified|pinned).foo, if the buffer is modified or pinned
  2. icons.(modified|pinned).foo, if the buffer is modified or pinned
  3. icons.(alternate|current|inactive|visible).foo
  4. icons.foo

Users who specify their icons/icon_separator_active/etc options the old way are prompted with a deprecation notice, but no action is necessary. The old options are automatically translated to the new format, and this will continue until a theoretical v2.0.0 releases.


This seemed like the best compromise between letting a user provide a function (my initial proposal) and adhering to the simplicity of user configuration (romgrk's preference).


Closes #46.
Closes #243.
Closes #379.

@Iron-E Iron-E added the request New feature or request label Mar 17, 2023
@Iron-E Iron-E self-assigned this Mar 17, 2023
@Iron-E Iron-E force-pushed the feat/379 branch 10 times, most recently from 29b3ac2 to 0d498bd Compare March 19, 2023 23:21
Prevents us having to check and see if `vim.deprecate` is available
(since that is 0.8 functionality, and we only require `0.7`)
@Iron-E Iron-E force-pushed the feat/379 branch 7 times, most recently from 15a9340 to d363239 Compare March 20, 2023 05:36
@otavioschwanck
Copy link
Contributor

Extremely WIP.

This PR allows customization of the bufferline.icons setting per activity / state, like so:

--- @class bufferline.options.icons.buffer
--- @field buffer_number? boolean iff `true`, show the `bufnr` for the associated buffer.
--- @field buffer_index? boolean iff `true`, show the index of the associated buffer with respect to the ordering of the buffers in the tabline.
--- @field file_icon? boolean iff `true`, show the `devicons` for the associated buffer's `filetype`.

--- @class bufferline.options.icons.state: bufferline.options.icons.buffer
--- @field modified? bufferline.options.icons.buffer the icons used for an modified buffer
--- @field pinned? bufferline.options.icons.buffer the icons used for a pinned buffer

--- @class bufferline.options.icons
--- @field alternate? bufferline.options.icons.state the icons used for an alternate buffer
--- @field current? bufferline.options.icons.state the icons for the current buffer
--- @field default? bufferline.options.icons.state the icons used when no other filter matches
--- @field inactive? bufferline.options.icons.state the icons for inactive buffers
--- @field visible? bufferline.options.icons.state the icons for visible buffers

When multiple definitions match, they most specific definition applies on top of its defaults. For example:

require'bufferline'.setup {
  icons = {
    default = {buffer_number = true, pinned = {buffer_index = true}},
    visible = {file_icon = true, modified = {file_icon = false}},
  },
}
  • A visible buffer will show its file icon.
  • A visible, pinned buffer will show its file icon and buffer index.
  • A visible, modified buffer will show no icons (since visible.modified.file_icon overrides visible.file_icon).
  • A visible, modified, and pinned buffer will show only the buffer index.
  • A non-visible, pinned buffer will show its buffer index and buffer number.
  • A non-visible, non-pinned buffer will show its buffer number.

There is automatic translation done for users who specify their options in the "old" way, i.e.:

--- @alias bufferline.options.icons.preset boolean|"both"|"buffer_number_with_icon"|"buffer_numbers"|"numbers"

--- @type {[bufferline.options.icons.preset]: bufferline.options.icons}
local PRESETS = {
  [false] = {},
  [true] = {default = {file_icon = true}},
  both = {default = {buffer_index = true, file_icon = true}},
  buffer_number_with_icon = {default = {buffer_number = true, file_icon = true}},
  buffer_numbers = {default = {buffer_number = true}},
  numbers = {default = {buffer_index = true}},
}

This seemed like the best compromise between letting a user provide a function (my initial proposal) and adhering to the simplicity of user configuration (romgrk's preference).

Closes #379.

Very nice, a nice think to have maybe is the pinned tabs be always visible (for a next task)

@Iron-E Iron-E force-pushed the feat/379 branch 6 times, most recently from dee5155 to db61a29 Compare March 20, 2023 22:26
@Iron-E Iron-E marked this pull request as ready for review March 20, 2023 22:35
@Iron-E
Copy link
Collaborator Author

Iron-E commented Mar 20, 2023

@otavioschwanck feel free to try this PR now, I've been using it for about a day and haven't gotten any errors (but that usually means they're hiding, so an extra tester would be helpful!). I believe your desired configuration would be:

require'bufferline'.setup {
  icons = {
    pinned = {
      buffer_index = true,
    },
  },
}

Feel free to make another issue for keeping pinned tabs visible.

@otavioschwanck
Copy link
Contributor

Some issues:

If we set the deprecated options, barbar throw an error and close itself.

i think the close = 'icon' is a strange option.

i had to do that:

        icons = {
          pinned = { buffer_index = true, close = '󰐃' },
        },

Maybe something like: left, icon or button, idk,

@Iron-E
Copy link
Collaborator Author

Iron-E commented Mar 29, 2023

Thanks for sacrificing some time out of your busy schedule! I appreciate it. This is a lot of code; I wanted to get your OK on the high-level concepts even if you didn't have time to go line-by-line.

I'll test it one more time before merging.

The `options` module now caches `g:bufferline`. The cache is updated
when either of the following happens:

* `bufferline.setup` is called
* A key in `g:bufferline` is `:let`-ed in Vimscript

Anyone doing `vim.g.bufferline.foo = bar` _in Lua_ should be doing
`.setup` by this point.
Prevents clobbering existing settings. Also a performance improvement.
`render.update` now automatically calls `redrawtabline` when necessary
This falls in line with other `vim` methods (e.g. `vim.list_slice`) and
our own `utils.list_slice_from_end`
Having a lot of buffers open degrates the performance of the
`render.update` call linearly. This commit ensures that no calculations
are done in `render` before entering and after exiting the viewport.
We were making a lot of repeat API calls in the `utils.hl` module, so I
added a cache for when `utils.hl` is called
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request New feature or request
Projects
None yet
4 participants