nvim-lualine / lualine.nvim

A blazing fast and easy to configure neovim statusline plugin written in pure lua.
MIT License
5.75k stars 457 forks source link

Feat: prevent lualine from overflowing the window width #225

Open hoob3rt opened 3 years ago

hoob3rt commented 3 years ago

Requested feature

Add a global(or local) config.shorten option which will handle automatic shortening for all? default components.

Motivation

As @shadmansaleh mentioned in #224 this can be done for each component with the format option. However this requires configuration bloat (imo) so I think we should provide sane shortening defaults to try preventing lualine from overflowing the window width.

shadmansaleh commented 3 years ago

You know I once actually tried making a global option that limits size of a component and it's longer then that it's scroll right to left overtime displaying the whole thing :D . Unfortunatly multibyte chars are a pain to deal . But we could probably make it work .

hoob3rt commented 3 years ago

Unfortunatly multibyte chars are a pain to deal .

Thankfully we have control over when to shorten so we might be able to apply it before icons ( I suppose that's what you have in mind when mentioning 'mulibyte chars'

But we could probably make it work .

I will try to provide a draft this week then.

wookayin commented 2 years ago

I think we can first start having a shortening feature (like airline#util#shorten) without multi-byte characters into much consideration. Most users will still be fine with this. Once this is done, extending it to be aware of multi-byte characters wouldn't be very difficult.

shadmansaleh commented 2 years ago

What does airline#util#shorten do ? Is it expossed to users ? It feels like a internal helper function.

wookayin commented 2 years ago

@shadmansaleh Yes airline#util#shorten(text, winwidth, minwidth) is more like an internal function, but which nvim-lualine will also likely to implement a similar thing as. It gives a truncated string including ... if the current window width is less than winwidth, but having at least (either the first or the last)minwidth characters. (NOTE: The meaning of minwidth is different than in the following)

In addition to this (shorten/truncate with dots), airline controls whether some component is visible or not depending on the current window width:

" Here is how you would define a part that is visible only if the window width greater than a minimum width.
call airline#parts#define_minwidth('some_component', 50)

Similarily, for lualine we could have some configuration options, for example,

{
    'mode',
    ...
    min_width = ...;       -- If the current window's width is less then this threshold, hide the component
    shortening_target = ...;         -- Similar to that for 'filename', but more generally for all components
}

We can have either one of these, or probably both, to prevent lualine from overflowing in width.

shadmansaleh commented 2 years ago

These can already be achieved with fmt 2nd one can be done with cond .

For example: https://github.com/nvim-lualine/lualine.nvim/wiki/Component-snippets#truncating-components-in-smaller-window

--- @param trunc_width number trunctates component when screen width is less then trunc_width
--- @param trunc_len number truncates component to trunc_len number of chars
--- @param hide_width number hides component when window width is smaller then hide_width
--- @param no_ellipsis boolean whether to disable adding '...' at end after truncation
--- return function that can format the component accordingly
local function trunc(trunc_width, trunc_len, hide_width, no_ellipsis)
  return function(str)
    local win_width = vim.fn.winwidth(0)
    if hide_width and win_width < hide_width then return ''
    elseif trunc_width and trunc_len and win_width < trunc_width and #str > trunc_len then
       return str:sub(1, trunc_len) .. (no_ellipsis and '' or '...')
    end
    return str
  end
end

require'lualine'.setup {
  lualine_a = {
    {'mode', fmt=trunc(80, 4, nil, true)},
    {'filename', fmt=trunc(90, 30, 50)},
    {function() return require'lsp-status'.status() end, fmt=truc(120, 20, 60)}
  }
}

The issue is this method won't work for vim-stl-components and probably be broken with unicode characters.

All though @hoob3rt was saying fmt way causes config bloat, I personally don't agree . As shown above trunc function can handle these more flexibly in just 9 lines .

wookayin commented 2 years ago

Thanks for sharing the snippet for how to truncate long components. I wish this were a built-in feature where a reasonable default behavior of truncating, but heavy users can start from those configs for more flexibility and customization.

~In addition, what about conditional visibility? Is it something that should be implemented with fmt where a function simply returns an empty string?~

UPDATE: Nevermind, I found this.

   { ...,
     fmt = ..,
     cond = conditions.hide_in_width,
   }
Alaz-Oz commented 1 year ago

A function which could tell if the lualine if overflowing?? Is that function available?

shadmansaleh commented 1 year ago

No currently there aren't any.

rodhash commented 7 months ago

These can already be achieved with fmt 2nd one can be done with cond .

For example: https://github.com/nvim-lualine/lualine.nvim/wiki/Component-snippets#truncating-components-in-smaller-window

--- @param trunc_width number trunctates component when screen width is less then trunc_width
--- @param trunc_len number truncates component to trunc_len number of chars
--- @param hide_width number hides component when window width is smaller then hide_width
--- @param no_ellipsis boolean whether to disable adding '...' at end after truncation
--- return function that can format the component accordingly
local function trunc(trunc_width, trunc_len, hide_width, no_ellipsis)
  return function(str)
    local win_width = vim.fn.winwidth(0)
    if hide_width and win_width < hide_width then return ''
    elseif trunc_width and trunc_len and win_width < trunc_width and #str > trunc_len then
       return str:sub(1, trunc_len) .. (no_ellipsis and '' or '...')
    end
    return str
  end
end

require'lualine'.setup {
  lualine_a = {
    {'mode', fmt=trunc(80, 4, nil, true)},
    {'filename', fmt=trunc(90, 30, 50)},
    {function() return require'lsp-status'.status() end, fmt=truc(120, 20, 60)}
  }
}

The issue is this method won't work for vim-stl-components and probably be broken with unicode characters.

All though @hoob3rt was saying fmt way causes config bloat, I personally don't agree . As shown above trunc function can handle these more flexibly in just 9 lines .

I really like this function, the only thing is.. when I'm splitting some file (:vsp) the lualine also gets truncated and in this situation I'd rather have full lualine shown..

is this possible? truncating only when the terminal itself gets resized?

rofrol commented 2 hours ago

It should be vim.o.columns instead of vim.fn.winwidth(0). Otherwise when I open neo-tree.nvim, it gets winwidth from neo-tree window.

Can someone fix this on wiki page?