purebred-mua / purebred

A terminal based mail user agent based on notmuch
GNU Affero General Public License v3.0
139 stars 19 forks source link

load config from file #510

Open teto opened 1 year ago

teto commented 1 year ago

Is your feature request related to a problem? Please describe. I suppose there is already an existing ticket about this but couldn't find it. I am really interested in this project, mail is an area where haskell or rust could shine. I wanna use "alot" but I would prefer contributing to this project instead. My main problem with it is that I dont want to recompile a program just to change the config which is why I never tried Xmonad and went with i3/sway) and I think it prevents adoption outside the haskell circle. Right now I can't use purebred out of the box because of this line:

      , _cvSendMailCmd = sendmail "/usr/sbin/sendmail"

I am on nixos so such a path wont exist. What if I want to change this path ?

Describe the solution you'd like Load config at runtime.

Describe alternatives you've considered I think a better default might be just "sendmail" so that I can put it in PATH and purebred would work even on nixos without recompilation.

In general I wonder what the devs position are on this topic ?

teto commented 1 year ago

NB: I've just edited the Config.hs and reran nix run and looked like it recompiled a bunch of stuff. I was expecting the config to be a separate module, I haven't looked at the build system but maybe there are ways to speed up the nix build by splitting libraries ?

romanofski commented 1 year ago

@teto hm.. I haven't looked at nix for a few months (apart from the day to day stuff) so thanks for the pointer to nix run. I'll give it a look. I configure my purebred instance like so: https://github.com/romanofski/nix/blob/master/nixpkgs/programs/purebred.nix

I think we built the application on the concept of building the main program based on the configuration. I would think @frasertweedale is probably not moving from that stand point.

Out of curiosity tho... if I think about mutt for example: I'd have to restart the application for the changes to take affect. For XMonad, when you restart the WM, it basically recompiles the binary from the config and restarts. Basically what I'm getting at, I think for the user there isn't really that much difference whether I recompile the config turning into the main application and restart the application which then parses the config. I guess applying config values during runtime might be a different cattle of fish. Is that what you were after?

teto commented 1 year ago

if I think about mutt for example: I'd have to restart the application for the changes to take affect. For XMonad, when you restart the WM, it basically recompiles the binary from the config and restarts

and there are the issues:

  1. compilation basically takes a lot more time than editing a .ini + restarting the program,
  2. compliation requires a whole toolchain and in haskell's case it is far from trivial with every ghc version breaking stuff. and when you do a small error, you might get a huge error thrown at you that if you dont do haskell will= likely make you run away
frasertweedale commented 1 year ago

Hi @teto. One of the huge advantages of the current configuration approach is that it allows the configuration to use native data types, including things that are difficult to express in a config language, such as functions. It also makes plugin integration much less complex than the other approaches I know about.

Yes, one big disadvantage is that you need the toolchain. It's a downside, I agree. For me, the upsides outweigh the downsides by a big margin. But I'm the sort of person who carries a Haskell toolchain everywhere I go, so the marginal cost for me is small. I acknowledge the plight of folks actually inconvenienced by the toolchain requirement. Because this is a hobby project, I personally am not motivated to solve the problem. But I am open to others tackling an alternative config approach. My main expectations would be:

teto commented 1 year ago

One of the huge advantages of the current configuration approach is that it allows the configuration to use native data types, including things that are difficult to express in a config language, such as functions. It also makes plugin integration much less complex than the other approaches I know about.

All of my software is configured via files and I dont feel limited. In case I am or if one needs a function, he can provide a plugin (which purebred seems to have an architecture for already ?). I've had a look at src/Purebred/Config.hs and I haven't seen functions that could impede the change (IMO).
As for native data types, parsing the config file would get you a native datatype. Aeson does that just fine for json, you can even derive the instances via generic.

Minimise the size/number of new dependencies

-dyre +config library :D I actually dont know the haskell ecosystem around that, I can ask on matrix. There seems to be https://hackage.haskell.org/package/conferer . I am not especially a fan of aeson but the library works damn well and it wouldn't be "much work" to swap the systems.

Because this is a hobby project, I personally am not motivated to solve the problem.

Now that is interesting. purebred has the interface I like the best close with alot. I believe haskell to be better suited to deal with the complexity of mail. I wouldn't mind contributing (lightly) to purebred, also despite being a hobby project it seems quite mature and also you've been working on it for quite some time already so I am not that worried ?! Is purebred your main MUA ? what happens if you decide to give up development ? do you think @romanofski (or any other contributor) would keep the flame burning :) ?

The existing solution using dyre remains an option, and that the two solutions do not mix. Either the new config system is used, or dyre is used

Agreed.

A POC with aeson should be tractable. Not everything has to be converted it could be incremental since UserConfiguration is already split in nice subtypes.

toml: https://github.com/kowainik/tomland ini: https://hackage.haskell.org/package/ini or https://hackage.haskell.org/package/config-ini

frasertweedale commented 1 year ago

-dyre +config library :D I actually dont know the haskell ecosystem around that, I can ask on matrix. There seems to be https://hackage.haskell.org/package/conferer . I am not especially a fan of aeson but the library works damn well and it wouldn't be "much work" to swap the systems.

Because this is a hobby project, I personally am not motivated to solve the problem.

Now that is interesting. purebred has the interface I like the best close with alot. I believe haskell to be better suited to deal with the complexity of mail. I wouldn't mind contributing (lightly) to purebred, also despite being a hobby project it seems quite mature and also you've been working on it for quite some time already so I am not that worried ?! Is purebred your main MUA ? what happens if you decide to give up development ? do you think @romanofski (or any other contributor) would keep the flame burning :) ?

Purebred is not my main MUA but I use it in anger probably several times a week (mainly for the power of notmuch search). I believe @romanofski is using it as MUA, or closer to that point than I am at least. I would like to get there. I don't think purebred will be abandoned, but development is slow as @romanofski and I chip away as capacity permits. Maybe an alternative approach to config will attract more users and contributors?

A POC with aeson should be tractable. Not everything has to be converted it could be incremental since UserConfiguration is already split in nice subtypes.

toml: https://github.com/kowainik/tomland ini: https://hackage.haskell.org/package/ini or https://hackage.haskell.org/package/config-ini

I don't love JSON as a config format. If we're going to do it, I think there are more ergonomic options. But if that's what the implementer chooses I will not oppose it.

aeson is not currently a dependency, but most of its transitive dependencies (including large ones like attoparsec) are already in the purebred dependency path. That's acceptable to me.

config-ini is already a dependency of purebred, via brick. So if INI is the way to go, I'd prefer config-ini over ini.

Other formats (TOML, YAML) seem OK to me too, but I'm not familiar with the libraries. I know https://dhall-lang.org/ is another option popular in the Haskell/FP scene.

With conferer, we would still have to choose exactly which format(s) to support and compile in the dependencies. I don't see much benefit.

romanofski commented 1 year ago

Yeah I use it as my daily driver and the config is currently the least of my problems. There still is a lot of UX missing even tho it's usable as bare bones as it is.