Comments (51)
I don't want to sound impolite, really I love this plugin and I think it is the best at its job.
Could you please explain to me the advantage of this feature when one can do:
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.
from feline.nvim.
Yeah, maybe start on refactoring the special component values for builtin providers first before starting to work on the truncation feature.
from feline.nvim.
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
expand
for evaluating the statusline, however, we can assume that bothparse_icon
andparse_sep
return a string that has a highlight prepended.
%#StatusComponent_FF79C6_21222C_NONE# +
is an example of the string returned byparse_icon
. We could usevim.split
to split the string at#
and get the last string, which would be+
in our example. I think once the provider, icon and seperators have been evaluated we pass them indivually to a function that splits each of them like above and returns the combined length of the strings.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 endYou could call the function before
parse_component
's return statement i.e.component_len(str, left_sep_str, right_sep_str, icon)
Alternatively, we could make parse_icon
and parse_sep_list
return their length without the highlight to avoid all that extra pre-processing
from feline.nvim.
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 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.
from feline.nvim.
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 WinResized
autocommand since the statusline is smart enough to update when the window is resized (you can try this out by using the enabled
key to query the window size)
from feline.nvim.
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
WinResized
autocommand since the statusline is smart enough to update when the window is resized (you can try this out by using theenabled
key to query the window size)
Maybe we could instead add a short_provider
component value that takes in another function, but then that'd mean we'd have to create short versions of the built-in providers which can be annoying. Maybe make the providers take an is_short
boolean value optionally and act on it? But then we wouldn't have a way to know if the provider actually uses that value or not and whether to hide it if it doesn't. So what way do you think the the short provider should be provided?
from feline.nvim.
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 short_str
as the second return value and icon
as the third. But I guess both of these would be breaking changes anyway
from feline.nvim.
Here my ideas on truncation behaviour that are somewhat similar to @ram02z's:
- The ability to specify what side to truncate (i.e. whether to cut off the right or the left part of the component).
- The ability to specify one ore more "shorter versions" of a component. For instance, I personally like to have the current working path in my statusline, and I have specified in the provider that it should use
pathshorten()
on the path when the window is narrow. - The ability for feline to start truncating when the components no longer fit in the statusline rather than when the window width falls below a certain threshold. Also, if one could provide a truncation priority value to each component, feline could start truncating components from lowest to highest priority until all components fit in the statusline, and then stop truncating the remaining (highest priority) components. That way one could potentially have a mix of "short version" and "full version" components. If only one version of a provider is specified feline would truncate by cutting off the lowest priority components from the side specified by the truncation side from (1).
I'm unsure how challenging this would be to implement though, so perhaps it's too difficult.
from feline.nvim.
Here my ideas on truncation behaviour that are somewhat similar to @ram02z's:
The ability to specify what side to truncate (i.e. whether to cut off the right or the left part of the component).
The ability to specify one ore more "shorter versions" of a component. For instance, I personally like to have the current working path in my statusline, and I have specified in the provider that it should use
pathshorten()
on the path when the window is narrow.The ability for feline to start truncating when the components no longer fit in the statusline rather than when the window width falls below a certain threshold. Also, if one could provide a truncation priority value to each component, feline could start truncating components from lowest to highest priority until all components fit in the statusline, and then stop truncating the remaining (highest priority) components. That way one could potentially have a mix of "short version" and "full version" components. If only one version of a provider is specified feline would truncate by cutting off the lowest priority components from the side specified by the truncation side from (1).
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?
from feline.nvim.
As for (2), how do you suggest for that to be implemented @Melkster?
I'm thinking that perhaps the provider
field could be overloaded to also take a list of providers with decrementing length where the first element is the longest version and the last element is the shortest.
Alternatively, an optional short_provider
field like you mentioned in an earlier comment.
from feline.nvim.
Maybe we could instead add a
short_provider
component value that takes in another function, but then that'd mean we'd have to create short versions of the built-in providers which can be annoying. Maybe make the providers take anis_short
boolean value optionally and act on it? But then we wouldn't have a way to know if the provider actually uses that value or not and whether to hide it if it doesn't. So what way do you think the the short provider should be provided?
Yeah, short_provider
would be a seperate optional field that when omitted means that the provider is hidden when there is no space left on the bar.
I'm thinking that perhaps the provider field could be overloaded to also take a list of providers with decrementing length where the first element is the longest version and the last element is the shortest.
Overloading the provider field is also reasonable, however, not having a set limit of providers per component can result in ambigious behaviour.
from feline.nvim.
Yeah,
short_provider
would be a seperate optional field that when omitted means that the provider is hidden when there is no space left on the bar.
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 file_info
provider, they might want to set the file name type to full-path
while for the short provider they might want short-path
, how would we handle that?
from feline.nvim.
But wouldn't that mean that for built-in providers, we'd have to have 2 functions for each?
That could be an advantage for choosing to overload the provider field.
Not to mention that the user might want different configuration options for the two providers. For example, for the file_info provider, they might want to set the file name type to full-path while for the short provider they might want short-path, how would we handle that?
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 short_provider
value that has the type short-path
instead.
from feline.nvim.
But wouldn't that mean that for built-in providers, we'd have to have 2 functions for each?
That could be an advantage for choosing to overload the provider field.
I don't get what you mean by that.
Not to mention that the user might want different configuration options for the two providers. For example, for the file_info provider, they might want to set the file name type to full-path while for the short provider they might want short-path, how would we handle that?
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
short_provider
value that has the typeshort-path
instead.
What about icons then, would they be a provider value or a component value?
from feline.nvim.
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?
from feline.nvim.
That could be an advantage for choosing to overload the provider field.
I don't get what you mean by that.
I was refering to one of @Melkster's ideas. He suggested overloading the provider function.
His full response:
"I'm thinking that perhaps the provider field could be overloaded to also take a list of providers with decrementing length where the first element is the longest version and the last element is the shortest."
What about icons then, would they be a provider value or a component value?
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.
from feline.nvim.
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?
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.
from feline.nvim.
So, is that all? If so, I can probably start work on implementing it
from feline.nvim.
@ram02z so, another issue, some providers (eg: vi_mode
) still reference component.icon
in their provider, if we only send the provider
table values to the provider function (which I personally think should be the case), we'd somehow need to have a deal with that. One way is to remove the vi_mode
provider entirely since it just shows an icon anyway. Another way is to send both the provider table and the component table to the provider function, which I personally believe is too much
from feline.nvim.
One way is to remove the
vi_mode
provider entirely since it just shows an icon anyway.
Vi mode has very basic implementation, however, it is probably used in every config, so I don't think it should be deprecated.
Another way is to send both the provider table and the component table to the provider function, which I personally believe is too much
Couldn't you just pass the component.icon
in addition to the provider table values?
from feline.nvim.
One way is to remove the
vi_mode
provider entirely since it just shows an icon anyway.Vi mode has very basic implementation, however, it is probably used in every config, so I don't think it should be deprecated.
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 get_vim_mode()
utility function in the vi_mode provider file to a vi_mode_name
provider for those that don't use icons.
Another way is to send both the provider table and the component table to the provider function, which I personally believe is too much
Couldn't you just pass the
component.icon
in addition to the provider table values?
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.
from feline.nvim.
Oh, I just thought of a way. It would be possible to make the vi_mode
provider just return an icon with highlight instead of the provider text. The issue with that is that currently the icon is not shown if the provider is empty. Maybe an always_visible
option for icons?
from feline.nvim.
Can vim.api.nvim_get_mode()
return nil?
from feline.nvim.
Can
vim.api.nvim_get_mode()
return nil?
Don't think so, no. Besides, get_vim_mode()
in the vi_mode
does provider doesn't just use nvim_get_mode, it actually shows an alias for the mode
from feline.nvim.
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?
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.
from feline.nvim.
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
from feline.nvim.
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
from feline.nvim.
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
from feline.nvim.
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 expand
for evaluating the statusline, however, we can assume that both parse_icon
and parse_sep
return a string that has a highlight prepended.
%#StatusComponent_FF79C6_21222C_NONE# +
is an example of the string returned by parse_icon
. We could use vim.split
to split the string at #
and get the last string, which would be +
in our example. I think once the provider, icon and seperators have been evaluated we pass them indivually to a function that splits each of them like above and returns the combined length of the strings.
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 parse_component
's return statement i.e. component_len(str, left_sep_str, right_sep_str, icon)
from feline.nvim.
I just realized that file_info
still requires component.icon
so even if we do refactor vi_mode
that still leaves us with an issue
from feline.nvim.
I just realized that
file_info
still requirescomponent.icon
so even if we do refactorvi_mode
that still leaves us with an issue
Couldn't you just pass component.icon
to the builtin providers?
from feline.nvim.
I just realized that
file_info
still requirescomponent.icon
so even if we do refactorvi_mode
that still leaves us with an issue
Since removing the dependence for the component
table is out of the question, I propose that we allow provider to take 3 arguments instead, opts
for the provider options, component
for the component values and winid
. And yes, while that would be a massive breaking change for custom providers, not many people really use custom providers plus since all of this will be released in Version 0.2 anyway, I think people will have time to change their configurations.
from feline.nvim.
I just realized that
file_info
still requirescomponent.icon
so even if we do refactorvi_mode
that still leaves us with an issueCouldn't you just pass
component.icon
to the builtin providers?
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
from feline.nvim.
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.
from feline.nvim.
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?
from feline.nvim.
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.
from feline.nvim.
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
from feline.nvim.
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
from feline.nvim.
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 add_provider
from feline.nvim.
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
add_provider
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.
from feline.nvim.
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
add_provider
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
from feline.nvim.
So, two major issues:
-
When a wide character is used (such as some of the icon glyphs that are used in many providers) in a string and its length is accessed, the wide character counts as 2 characters instead of 1, which messed up truncation.
-
Truncation seems to add an unbelievably high amount of complexity to the code. Like I knew it'd make the code more complex but I didn't imagine it'd be to that extent.
Honestly, things are looking dim for the truncation feature request now, it's just way too much effort at this point.
from feline.nvim.
- When a wide character is used (such as some of the icon glyphs that are used in many providers) in a string and its length is accessed, the wide character counts as 2 characters instead of 1, which messed up truncation.
I wouldn't call that an issue for feline. It could be different depending on the terminal emulator you use.
- Truncation seems to add an unbelievably high amount of complexity to the code. Like I knew it'd make the code more complex but I didn't imagine it'd be to that extent.
Honestly, things are looking dim for the truncation feature request now, it's just way too much effort at this point.
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.
from feline.nvim.
- When a wide character is used (such as some of the icon glyphs that are used in many providers) in a string and its length is accessed, the wide character counts as 2 characters instead of 1, which messed up truncation.
I wouldn't call that an issue for feline. It could be different depending on the terminal emulator you use.
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 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.
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
from feline.nvim.
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 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.
from feline.nvim.
vim.fn.strdisplaywidth
seems to solve this issue
from feline.nvim.
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, %<
can only be used once in the statusline string
from feline.nvim.
vim.fn.strdisplaywidth
seems to solve this issue
There is also vim.api.nvim_strwidth
from feline.nvim.
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,
%<
can only be used once in the statusline string
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.
See https://github.com/greshake/i3status-rust/blob/master/doc/blocks.md#formatting for more information.
from feline.nvim.
vim.fn.strdisplaywidth
seems to solve this issueThere is also
vim.api.nvim_str_width
That function doesn't seem to exist on my version of Neovim.
EDIT: Nvm, it's called nvim_strwidth
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,
%<
can only be used once in the statusline stringWell, 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.
See https://github.com/greshake/i3status-rust/blob/master/doc/blocks.md#formatting for more information.
Makes sense
from feline.nvim.
I don't want to sound impolite, really I love this plugin and I think it is the best at its job.
Could you please explain to me the advantage of this feature when one can do:
provider = function(winid, component)
if vim.fn.winwidth(winid) >= 100 then return 'looooong'
else return 'short'
end
end
from feline.nvim.
Related Issues (20)
- Question: Background color of statusline does not change. HOT 2
- [Feature] HOT 2
- How do I configure feline as "default with no icons" HOT 2
- Changing single option without needing to add whole config HOT 2
- [Feature] Change the path seperator for the file_info provider HOT 2
- Unimplemented theme support HOT 5
- E542: Unbalanced groups HOT 8
- [Bug] adding 'neo-tree' to force-inactive table has no effect HOT 4
- Add my feline config link to your README.
- statusline config
- [Feature] An option for a small clock in the status bar HOT 1
- [Bug] cmdheight=0 not working HOT 12
- [Bug] Winbar disappears from inactive pane HOT 2
- [Bug] E5108: Error executing lua ... E539: Illegal character < > | Strings Ending With %% HOT 4
- [Bug] Actually disable winbar when using `disable` option HOT 3
- Error after install HOT 4
- [Feature] Feature request: component stack HOT 10
- [Bug] Starting Error
- [Bug] Global function `module` gets overwritten by feline HOT 2
- [Feature] Use a function to selectively update highlights
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from feline.nvim.