Skip to content

Replace hardcoded defaults. Remove parser boilerplate. (#27)#44

Merged
georgefst merged 1 commit intofourmolu:masterfrom
kukimik:options_default_values
Oct 13, 2020
Merged

Replace hardcoded defaults. Remove parser boilerplate. (#27)#44
georgefst merged 1 commit intofourmolu:masterfrom
kukimik:options_default_values

Conversation

@kukimik
Copy link
Contributor

@kukimik kukimik commented Oct 6, 2020

Closes #27.

This solves the problem described in #27. At the same time I wanted to reduce the number of places where the strings encoding option values were hardcoded, which resulted in rewriting/replacing parseHaddockStyle, parseCommaStyle and parseBool and modifying the way that the help texts are built.

I also decided to make the error messages a bit more user friendly by providing the user with the list of possible values of an option (because it was nearly free with the new approach).

Some comments:

  1. I don't understand why booleans are case-insensitive and other options are case-sensitive. Do we really want it this way?
  2. The values can still be represented in different ways on the command line and in the config file. I think it would be nice if we had a single source of truth, guaranteeing that these representations are uniform. However, I'm not sure what is the best approach to this problem. But anyway, I think this is out of scope for this issue/PR.

@georgefst
Copy link
Collaborator

This looks really good! Unfortunately I don't quite have time to look at the code in-depth right now, but I should be able to review properly by the weekend.

I don't understand why booleans are case-insensitive and other options are case-sensitive. Do we really want it this way?

That's an error really. We probably want universal case-insensitivity, although in practice just accepting all-lowercase would be fine since this is what the examples use.

The values can still be represented in different ways on the command line and in the config file. I think it would be nice if we had a single source of truth, guaranteeing that these representations are uniform. However, I'm not sure what is the best approach to this problem. But anyway, I think this is out of scope for this issue/PR.

Yeah, I'm interested in a general solution to this, and I think it could be quite neatly encapsulated in a library. See my comment on Reddit, which was largely inspired by Fourmolu. It seems that nothing complete currently exists for Haskell. I've been meaning to research what solutions are available in other languages.

@kukimik
Copy link
Contributor Author

kukimik commented Oct 7, 2020

We probably want universal case-insensitivity, although in practice just accepting all-lowercase would be fine since this is what the examples use.

I opt for requiring all-lowercase, to keep it compatible with Ormolu (and save a few lines of code). But I can do it either way, just let me know.


When reviewing please take a look at parseMode in Main.hs. I left it untouched, as it comes from Ormolu and I wanted to save some merging work if they ever decide to change it. But perhaps it's better to make it uniform with other parsers.


Yeah, I'm interested in a general solution to this, and I think it could be quite neatly encapsulated in a library. See my comment on Reddit, which was largely inspired by Fourmolu. It seems that nothing complete currently exists for Haskell. I've been meaning to research what solutions are available in other languages.

Sounds interesting.

@kukimik kukimik force-pushed the options_default_values branch 2 times, most recently from 9d30323 to 4cc442e Compare October 8, 2020 19:08
@georgefst
Copy link
Collaborator

I opt for requiring all-lowercase, to keep it compatible with Ormolu (and save a few lines of code).

Yep, those are good enough reasons.

When reviewing please take a look at parseMode in Main.hs. I left it untouched, as it comes from Ormolu and I wanted to save some merging work if they ever decide to change it. But perhaps it's better to make it uniform with other parsers.

I'd go for uniformity here. It's a trivial enough function that I'm not too concerned about merge conflicts. Would there be any visible change in behaviour?

Sounds interesting.

Yeah, unfortunately, I'm really not looking for another library to maintain right now. Some of the code you've written here would actually be a good starting point, since it's really pretty independent of Fourmolu.

@kukimik kukimik force-pushed the options_default_values branch from 4cc442e to faf6d1b Compare October 13, 2020 13:16
@kukimik
Copy link
Contributor Author

kukimik commented Oct 13, 2020

I opt for requiring all-lowercase, to keep it compatible with Ormolu (and save a few lines of code).

Yep, those are good enough reasons.

Ok, I did it this way.

When reviewing please take a look at parseMode in Main.hs. I left it untouched, as it comes from Ormolu and I wanted to save some merging work if they ever decide to change it. But perhaps it's better to make it uniform with other parsers.

I'd go for uniformity here. It's a trivial enough function that I'm not too concerned about merge conflicts. Would there be any visible change in behaviour?

I replaced the parser.

Yes, there is a change in the error message ("unknown value:" instead of "unknown mode:" and an extra line with allowed values).


I also did a naming change (standardParse -> parseBoundedEnum), modified the comments and fixed a bug I made in error message formatting. Probably I should have made a separete commit instead of force pushing. Sorry for that.


Sounds interesting.

Yeah, unfortunately, I'm really not looking for another library to maintain right now. Some of the code you've written here would actually be a good starting point, since it's really pretty independent of Fourmolu.

I've thought about it for a moment (not a very long one 😉 ) and I don't know how to apply these ideas when we don't know what is the type that contains the preferences (i.e. when PrinterOpts f is replaced by an arbitrary type) and at the same time keep it easy to use.

About the solutions in other languages: are you aware of some libraries that handle this?

@georgefst
Copy link
Collaborator

I've thought about it for a moment (not a very long one wink ) and I don't know how to apply these ideas when we don't know what is the type that contains the preferences (i.e. when PrinterOpts f is replaced by an arbitrary type) and at the same time keep it easy to use.

Hmm, good point. I suppose we want to be able to work with any record type that has the correct kind ((Type -> Type) -> Type), with all fields being of the form f a, where a is an instance of the equivalent of ToCLIArgument. This is probably a bit much for GHC.Generics. We could use Template Haskell to generate some pieces.

About the solutions in other languages: are you aware of some libraries that handle this?

I don't know any, but I feel like there must be something out there. I can't imagine we're the first to think about generalising this.

@kukimik
Copy link
Contributor Author

kukimik commented Oct 13, 2020

I did a quick research and found some libraries in:

Didn't have time to read any of these, though.

This looks like an useful tool, and the problem seems rather accessible. If a project was started, I'd be eager to help. However, with my current Haskell skills, I don't think I'm ready to design a solution.

@georgefst georgefst merged commit 1f16118 into fourmolu:master Oct 13, 2020
@georgefst
Copy link
Collaborator

Nice. that list is very handy!

I'll let you know if I do make a start on this. Unfortunately, the likely need for TemplateHaskell to get something nice takes it out of the realms of "something I might be able to knock together on a Sunday afternoon".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make sure defaults don't slip out of sync

2 participants