-
Notifications
You must be signed in to change notification settings - Fork 55
[Feature] Smart component truncation #96
Comments
The way I would approach truncation would require a slight refactor and breaking changes for the provider key. In order for the truncation to be useful, it will have to be a core feature, so you can't really opt out. Firstly, we would have to store the state of the statusline. The main elements we would require for truncation would be the remaining length of the section (assuming that sections are equal in length), the current window size and the truncation priority. The priority system will be important as it will allow us to know what components need to be truncated, therefore, it should have its own key for components where the user can change the priority of component. If the component doesn't have a priority set, it will just be left to right (index 1..N). Now, in order for the truncation to be useful, I propose three states: normal, short and hidden. This would require a seperate provider for the short version, if the user omits the short provider, the provider will just get hidden. Therefore, feline will first compare the current window length and the remaining section length and use that to either show the full provider, the short provider or just hide it entirely. I think this method is better than the max_length method because that is quite naive since it just splits the string if it is greater than N characters. Also, I don't think you have to worry about the fact that neovim doesn't have a |
Maybe we could instead add a |
Another way would be to allow provider to be a table instead of just a string. The table could work be like this: {
str = 'insert string here'
short_str = 'insert short string here'
icon = 'insert icon here'
} But then the issue with that is then we'd have two places where the user could place icon values, the component (which takes higher precedence) and the provider itself. But we need both of them since providers need to be able to return default icons to use and components need to be able to override them. Alternatively we could also have the functions return 3 values, but that'd require reordering to put the |
Here my ideas on truncation behaviour that are somewhat similar to @ram02z's:
I'm unsure how challenging this would be to implement though, so perhaps it's too difficult. |
I'd say I agree with it for the most part. As for (1) though, pretty sure that would be controlled by the provider itself if we are to implement truncation. As for (2), how do you suggest for that to be implemented @Melkster? |
I'm thinking that perhaps the Alternatively, an optional |
Yeah,
Overloading the provider field is also reasonable, however, not having a set limit of providers per component can result in ambigious behaviour. |
But wouldn't that mean that for built-in providers, we'd have to have 2 functions for each? That'd increase redundancy wouldn't it? Not to mention that the user might want different configuration options for the two providers. For example, for the |
That could be an advantage for choosing to overload the provider field.
You bring up a good example. I think for this feature to work builtin providers will need a refactor regarding their special component values. Instead, the component values will have to be specified directly from the provider i.e. {
provider = {
"file_info",
colored_icon = false,
type = "full-path",
},
} Now this approach would require a refactor for the respective providers. We would need to check if the provider is a table or a string. If it is a table, we expect component values. If it is a string, we fallback to the provider's default configuration. Following this approach, the user could also define a |
I don't get what you mean by that.
What about icons then, would they be a provider value or a component value? |
Also, what if every component gets truncated and the statusline still isn't small enough to fit within the window? Do we just let Neovim deal with that like it currently does? |
I was refering to one of @Melkster's ideas. He suggested overloading the provider function. His full response:
Icons would remain as a component value. I think having a different icon for normal and short providers doesn't make much sense since the short provider's usecase is just to provide a shorter alternative to the normal provider. |
We shouldn't really factor in window sizes that are too small to have a statusline since they won't be realistic. If the statusline is too small to fit anything and everything is truncated, then we can only assume the window is too small to fit anything anyway. |
So, is that all? If so, I can probably start work on implementing it |
Yeah, maybe start on refactoring the special component values for builtin providers first before starting to work on the truncation feature. |
@ram02z so, another issue, some providers (eg: |
Vi mode has very basic implementation, however, it is probably used in every config, so I don't think it should be deprecated.
Couldn't you just pass the |
That's true, however, it's worth noting that Feline isn't at version 1.0 yet, as long as the deprecation period is long enough, it shouldn't cause any problems. Besides, all the user would have to do is the change the provider string from 'vi_mode' to their preferred icon. We could also turn the
Passing just the icon just seems like a wrong design choice imo, I'd say either pass the entire component table or none of it. |
Oh, I just thought of a way. It would be possible to make the |
Can |
Don't think so, no. Besides, |
This is why I suggested giving each component a priority and a truncation direction (i.e. left or right side). When this situation occurs, Feline can start removing the lowest priority component until all remaining ones fit. Now the last component to be removed can get truncated based on its truncation direction and the remaining part of it could be rendered in the statusline as well. |
By the way, there's one last issue we need to tackle, how do we find the length of a component? Simply using the string's length won't work since not all of it is displayed on the statusline and some of it is parsed by Neovim |
Using the return value of the provider should work, since none of the builtin providers return any statusline modifiers and we don't expect users to return statusline modifiers in their custom providers either. The logic will have to come after this line: feline.nvim/lua/feline/generator.lua Line 206 in 5d152e2
|
But then, things like icons and separators could still cause the statusline text to be larger than the window |
Damn, I forgot that icons and seperators return statusline modifiers. Unforunately there isn't a function like
local function component_len(str, ...)
local len = #str
local next = next
local spl
for _, arg in ipairs {...} do
if type(arg) == "string" and arg ~= "" then
spl = vim.split(arg, "#")
if next(spl) then
spl = spl[#spl]
len = len + #spl
end
end
end
return len
end You could call the function before |
Alternatively, we could make |
I just realized that |
Couldn't you just pass |
Since removing the dependence for the |
Again, I'm against passing just the icon. What if we eventually need the highlight, do we add yet another argument for it? What if we need the separators? You can see that that could be a big problem. Either we have no dependence on the component or just take the whole component |
Well for the meantime there are no builtin providers that utilise component values other than the icon and special component values. If you do eventually need the highlight or another component value, you can go back to using the component table. Honestly, I am not too fussed about passing the full component table. |
Wouldn't it be better to just do it right away then instead of having yet another breaking change in the future changing what arguments the provider takes? |
Yeah you could definitely do it right away, but it won't be a breaking change, since changing the arguments for the builtin providers won't affect the user. |
Changing the arguments for builtin providers changes them for all providers since all providers are treated the same way, so it would in fact be a breaking change |
Aren't custom providers and builtin providers are handled seperately? You could just change the arguments for builtin providers without affecting custom providers. feline.nvim/lua/feline/generator.lua Lines 221 to 225 in 0f3afe2
|
They are, but I'm against handling them separately. I think all providers should allow the same level of customizability. Especially since providers can be added using |
If they are going to be handled the same, then special component values being moved to the provider wouldn't make sense for custom providers because they have no special component values. |
I mean, theoretically speaking, a custom provider can be the same function that's used in two different places (eg: the active and inactive statusline) but with different options |
So, two major issues:
Honestly, things are looking dim for the truncation feature request now, it's just way too much effort at this point. |
I wouldn't call that an issue for feline. It could be different depending on the terminal emulator you use.
I didn't expect truncation to have an easy implementation, which is why I suggested that it be implemented as a core feature. If you decide not to complete it, it would be very useful to submit your current work as a draft PR, so I (or someone interested) can pick up from where you left off. |
It is an issue for Feline because the character still only takes 1 character width of space in the window, but since it uses multiple bytes (or at least that's why I think it happens) it counts as multiple characters in the string. Couple that with the fact that the glyphs are used literally everywhere in Feline, and I'd say that's a pretty big problem, honestly.
I could do that, yes. But the issue is not that the implementation is hard. The issue is that the implementation is going to be flawed (doesn't work with Vim statusline modifiers or with multibyte characters) and it'll greatly increase the complexity of the codebase which can make the code borderline unreadable for anyone who's willing to contribute |
I am sorry, but I think I am missing the issue. If a double width glyph counts as 2 characters, wouldn't that mean that feline would calculate the length correctly? If it takes one visible cell width then it is because of your terminal emulator. |
Sorry, it's not double width, wrong wording on my part. I meant multibyte not double-width. |
|
How would I go about adding truncation directions for specific components like what @Melkster wants? Like, what's the Vim statusline syntax for truncating a specific section of the statusline from a specific direction. Because as far as I can see, |
There is also |
Well, I don't think feline should cut strings, rather leave that to the user when setting a short provider. This behaviour is inspired by the formatting used for blocks in i3status-rust. |
That function doesn't seem to exist on my version of Neovim.
Makes sense |
I don't want to sound impolite, really I love this plugin and I think it is the best at its job. provider = function(winid, component)
if vim.fn.winwidth(winid) >= 100 then return 'looooong'
else return 'short'
end
end |
This is basically what I do in my own config. The main advantage with the approach I described above it will (hopefully) take into account the remaining length in each section and the priority of each component to "intelligently" decide when to show, truncate or hide components. |
I'm willing to give this another shot. But first, we'd have to plan how truncation actually works. How do we decide when to truncate, which components to truncate, and where to truncate the components, and how do we allow the provider to affect the truncation? We need to plan out a good blueprint for truncation before we can implement it, so I'd like the input of as many people as possible.
@ram02z you seemed to have ideas for truncation as well, I'd be interested in hearing them out again. @Melkster how would you want truncation to work?
The text was updated successfully, but these errors were encountered: