-
Notifications
You must be signed in to change notification settings - Fork 55
Conversation
After doing some benchmarks I can see that it makes the statusline generation time around 15% higher than before |
I wonder what happens when a window is resized causing a component in an inactive window to require truncation or allowing a component in an inactive window to not be truncated. There's no |
You are right, this is a limitation of neovim since there is no I quickly tried the file_info example you added to the README and the switching between the normal provider and short provider works well, but it doesn't seem to hide the short provider if it is still too big (took a quick look at the changes and I don't think it was implemented). I don't think it's that big of a deal though, since the user could use the enabled key for that. I currently don't have much time to thoroughly test and review this properly, however, I will do as soon as I can. |
Question, should it start removing components only after all components with |
Not necessarily, we should only care about the length and priority of the providers. Same reason why I think it is up to the user to ensure that the short provider is actually shorter than the normal provider. I think that components that don't have a short provider should be hidden when truncated in order of priority and when they do have a short provider, feline should first attempt to fallback to the short provider, but if the short provider's length still surpasses the section limit, it should be hidden. Perhaps, hiding the components should be an opt-in feature though by introducing a key to feline's setup or maybe to each component; whatever you think is better. I am suggesting that it should be opt-in because some users may not want their component's hidden unless they explicitly define that behaviour themselves. |
I'm going to add an |
Actually, thinking more about it, I think it'd just be better if components aren't hidden at all, best to leave that to the user |
fea12d3
to
4173f99
Compare
I agree with that as well, which I suggested it should be opt-in behaviour (disabled by default). It might as well get implemented since it will make use of feline's priority system, so it would be redundant if the user tried to replicate that behaviour in their own config. |
In theory, setting But if we do make it an opt-in feature either way, I wonder if it'd be better to have one setting for the entire statusline through |
If the implementation isn't complicated, per component customisation is preferred imo. |
So I finally added the feature to hide components entirely. Again, this seems to be working fine. But even though it's a cool feature and all, I can't say I'm a fan of the performance degrade this feature brings, not to mention the increased complexity of the code. |
After doing some benchmarks again though it seems that the performance downgrade is not as bad as I had first seen, which is relieving. The code could still use some simplifying though, except I don't really have much of an idea on how to approach that |
Simplified the code a little bit, not sure how readable it is now though. @ram02z when you have time I'd like to know if you have trouble understanding the code |
8aa26e9
to
41c3989
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Once neovim releases a WinResized
autocommand most of the truncation logic in generate_statusline
can be moved to a function triggered by it. I think you should definitely CC the feline users that expressed interest in the truncation to also test this branch, but from what I have tested so far, it seems to working as intended.
lua/feline/generator.lua
Outdated
elseif component.truncate_hide then | ||
statusline_length = statusline_length - parsed_component.len | ||
parsed_sections[indices[1]][indices[2]] = {str = '', len = 0} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elseif component.truncate_hide then | |
statusline_length = statusline_length - parsed_component.len | |
parsed_sections[indices[1]][indices[2]] = {str = '', len = 0} |
This isn't needed since the check happens after anyways. Also causes an issue when you have a component with no short provider, high priority and truncate_hide set to true. It will still get hidden even though it has a priority higher than a component with a short provider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That isn't supposed to happen because components are always hidden in order of priority. Also the check that happens afterwards hides all components with truncate_hide
set to true, even if they have a short provider, which should only happen if all other components are using their short_provider
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, for one there is no point of checking the truncate_hide
value for components without a short_provider because they would have been hidden by the code I suggested to be removed anyway. Anyway, you should be able to reproduce the bug with this config. Just keep making the active smaller and you will see that the higher priority component is still hidden first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, for one there is no point of checking the
truncate_hide
value for components without a short_provider because they would have been hidden by the code I suggested to be removed anyway. Anyway, you should be able to reproduce the bug with this config. Just keep making the active smaller and you will see that the higher priority component is still hidden first.
Ah, I see what you mean now. That behavior was intended actually, but thinking more about it, it makes more sense to remove it
The code itself is not difficult to understand and the comments are useful too. The only issue I think may that debugging truncation issues may be difficult due to how tables like |
Actually, I don't think so, since it needs to modify the generated statusline string directly. |
Any suggestions to fix that? |
True, but that autocommand at the bare minmum will allow for truncation to be visible for inactive windows.
Honestly, not sure because the |
Yeah, that's an issue. If only Lua allowed taking variable references... |
ff7fa32
to
561b6ce
Compare
This doesn't seem to work anymore after I rebased it against the develop branch, not sure why |
This seems to be caused by #120 |
Removing the |
Honestly, at this point I'd suggest removing the |
I don't personally have a problem when |
It's not |
1b632c7
to
dd7261b
Compare
Since this seems to be working fine I'm going to merge this now. Make a new issue if this causes any problems |
@ram02z it seems that truncation doesn't work correctly still because in Vim's statusline, in order to have a literal |
I might have to end up removing truncation. It still seems to have a lot of flaws (such as the one mentioned above), and it's not really very reliable, plus it seems to have a massive performance hit as well and it's kind of impossible to make it zero-cost. |
I've opened an issue in the Neovim repo that'd make the process much easier: neovim/neovim#15849 But until that's implemented, I'm strongly in favor of removing truncation. No truncation is better than half-assed truncation imo. |
I'm going to remove truncation for now until either the feature gets implemented in Neovim or until I can find a more performant and reliable way to get the statusline length |
You can use Even if neovim implements expanding stl expressions it'll still be costly . As it can't really be lighter then what neovim currently does while drawing statusline. |
Oh? I'm not sure how to do that though
But at least then it'll be more accurate |
It'll be something like this local ffi = require('ffi')
local M = {}
ffi.cdef [[
typedef unsigned char char_u;
typedef struct window_S win_T;
extern win_T *curwin;
typedef struct {} stl_hlrec_t;
typedef struct {} StlClickDefinition;
typedef struct {} StlClickRecord;
int build_stl_str_hl(
win_T *wp,
char_u *out,
size_t outlen,
char_u *fmt,
int use_sandbox,
char_u fillchar,
int maxwidth,
stl_hlrec_t **hltab,
StlClickRecord **tabtab
);
]]
function M.expand_stl_expr(stl_fmt)
local stlbuf = ffi.new('char_u [?]', 256)
local fmt = ffi.cast('char_u *', stl_fmt)
ffi.C.build_stl_str_hl(
ffi.C.curwin,
stlbuf,
256,
fmt,
0,
ffi.cast('char_u', 0x20),
vim.fn.winwidth(0),
nil,
nil
)
return ffi.string(stlbuf)
end
return M Note: Untested code . |
Oh wow, this actually seems to work pretty well. Thanks a lot for this! |
Closes #96
Seems to be working fine. Though I'd like @ram02z to review the code (and try to make it simpler if possible). I'd also like it to be well-tested before merge.