Closed LordMZTE closed 1 year ago
Related: #756 (But very different, this actually sounds pretty feasible and i'm not opposed)
I don't really understand what you are gaining by doing configuration in source or for creating a custom binary as in your example. If you're going that far you might as well just keep a personal fork and do whatever you want there?
I don't really understand what you are gaining by doing configuration in source or for creating a custom binary as in your example. If you're going that far you might as well just keep a personal fork and do whatever you want there?
I think this approach would make it more convenient. In a personal fork, you'd have to rip out the whole config part of i3status-rust first. With a library crate, this would be made much easier and we could easily integrate it, as the binary crate could just call the same API as a cutom binary would, but based on the config file.
Here's some reasons I think someone might prefer configuring in rust:
I imagine it might be useful for some custom blocks that are hard and/or not efficient to implement as a script and which cannot be merged upstream for some reason. Maintaining a fork is not that easy.
Good point! Maintaining a fork just for a personal config would be a lot of work for keeping up to date with upstream. You might have to deal with merge conflicts, whereas in the case of a library crate it would just be a matter of adjusting the version in Cargo.toml
, and maybe accounting for API changes.
As an experiment, I'll try splitting swaystatus
(#430) into two crates - one with all the types, bloks and logic, and the second which will parse the config and run the bar. Will see how it'll go.
I can start working on this if that's alright!
I can start working on this if that's alright!
Sure, I'll let you know when I get to the point when at least one block can run, so you can port other blocks if you will.
I meant on i3status-rust, not swaystatus :D
Anyways, you are always free to try this on your fork xD
It looks like the best way to go about this would be to split up the codebase into 2 crates. We could for example call them libi3status-rust and i3status-rust. This would be necessary to only have the dependencies on toml and clap on the binary crate, as (to my knowledge) it is not possible to have a dependency only for the binary part of a bin+lib crate.
Also, it would allow a seperate examples directory for both, and make it more obvious what actually belongs to the binary and what does to the library.
If we're gonna do this, I'd have to know how to go about restructuring the project. It would require moving some files around.
Phew, looks like implementing this requires some crazy amounts of refactoring to split into 2 crates :P
I think another benefit is being able to enable or disable blocks based on certain conditions, or change the formatting of a block. An example is having a desktop and a laptop and showing the battery block on the laptop only without having two config files. Another is showing swap info only if the setup has swap.
@johnf9896 this is already possible for the battery block using the allow_missing
and hide_missing
options. Not so for swap.
But how do you intend to use this feature for that usecase? Isn't maintaining two separate source configs just as difficult/annoying as maintaining two config files?
this is already possible for the battery block using the allow_missing and hide_missing options.
Yeah, I found out about them after writing the comment. They weren't available back when I added i3status-rust.
But how do you intend to use this feature for that usecase? Isn't maintaining two separate source configs just as difficult/annoying as maintaining two config files?
I wouldn't keep two source configs. I would have one with an if to check if there is swap and set clickable = true/false
I am already doing that for the battery, using scriptfs + Ruby ERB
My i3status.toml.erb
contains
<% if system("ls /sys/class/power_supply/*/capacity >/dev/null 2>&1") %>
[[block]]
block = "battery"
driver = "upower"
device = "DisplayDevice"
format = "{percentage}%"
<% end %>
The point is controlling the config using arbitrary conditions, not just for showing or hiding blocks as #1326 would allow. I am already solving that by using scriptfs + Ruby to generate the config file but having it in Rust would allow the other benefits stated above.
That's a neat solution, I admit, but IMO usecases like these should be covered within the block's logic (like battery
does now) rather than in source config. People shouldn't have to recompile to enable such behavior, esp. if they may be installing from a binary package manager
Yes, I agree. The more that can be done through a regular config file the better. I would leave the source config for cases that are very particular because you can't integrate every single one into the program
How about using lua for configuration (nvim way)?
That's a cool idea, but I'd still prefer source configs, as I suggested. That would offer even more flexibility than lua would, without any performance penalty.
In case it's used only for configuration, the startup might take a little longer, however, looking at neovim, this shouldn't be noticeable. Performance shouldn't be an issue even if lua will be used for custom blocks, at least it should be much better compared to external scripts.
And to be honest, I don't think rust fits well into the "source as a config" category. It takes more than two minutes to recompile this project on my machine after a small change of the defaults (Intel i5-5200U, rustc 1.58.0-nightly, release mode). How many times should I start a config-less version to get those two minutes back :laughing: ?
And in addition, wouldn't it be nice to give almost the power of source config to binary package users?
Still, both approaches can coexist.
This is now possible:
If there is interest in making the API more convenient, it can be discussed in new issues.
I'm currently looking to switch from a homemade bar to i3status-rust, but I think that I'd prefer configuring i3status-rs in rust, as opposed to toml.
This would (assuming we add a good API) also make it easy to implement custom blocks. The way I'm seeing this work, is to create a
lib.rs
file in i3status-rs, and have all the modules that wouldn't be used only in the current, toml-based version be declared inlib.rs
, in order to have them be available in the library crate. This crate could then also be pushed to crates.io.The user would then create a binary crate, and add the i3status-rust library to
Cargo.toml
. The main function could look something like this:Of course this is just a rough idea of how the API could look.
There seems to be a project that already works like this called i3monkit, but it seems to be unmaintained, and doesn't have nearly as many blocks as i3status-rust, and also doesn't seem to support styling as fancy as i3status-rust does or callbacks.
I would love to contribute to i3status-rust, but I've currently not used it or looked at the code, so it might take me some time to get used to it. 😅