lualine.nvim icon indicating copy to clipboard operation
lualine.nvim copied to clipboard

Feat: prevent lualine from overflowing the window width

Open hoob3rt opened this issue 4 years ago • 11 comments
trafficstars

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.

hoob3rt avatar May 10 '21 23:05 hoob3rt

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 .

shadmansaleh avatar May 10 '21 23:05 shadmansaleh

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.

hoob3rt avatar May 10 '21 23:05 hoob3rt

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.

wookayin avatar Nov 21 '21 01:11 wookayin

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

shadmansaleh avatar Nov 21 '21 01:11 shadmansaleh

@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.

wookayin avatar Nov 21 '21 01:11 wookayin

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 .

shadmansaleh avatar Nov 21 '21 02:11 shadmansaleh

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,
   }

wookayin avatar Nov 28 '21 02:11 wookayin

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

Alaz-Oz avatar Aug 30 '22 07:08 Alaz-Oz

No currently there aren't any.

shadmansaleh avatar Aug 31 '22 03:08 shadmansaleh

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?

rodhash avatar Nov 24 '23 15:11 rodhash