Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#48] Add configurations, read from the file #59

Merged
merged 5 commits into from
May 25, 2018
Merged

Conversation

vrom911
Copy link
Member

@vrom911 vrom911 commented May 23, 2018

Things to do

  • Handle [GhcVer] from the custom configurations
  • Add new instructions to the README explaining how configs should work

@vrom911 vrom911 added feature idea config TOML configurations labels May 23, 2018
@vrom911 vrom911 self-assigned this May 23, 2018
@vrom911 vrom911 requested a review from chshersh May 23, 2018 10:53
@@ -1,6 +1,7 @@
module Summoner
( module Summoner.Ansi
, module Summoner.CLI
, module Summoner.Config
, module Summoner.Default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I right that Default module will be removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should be

-- Generate the project.
generateProject projectName targets
runWithOptions (InitOpts projectName cliConfig maybeFile) = do
file <- case maybeFile of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really need universum for such things (so we can use whenNothing here) 😏

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm agree with adding it after so many stupid imports..

generateProject projectName targets
runWithOptions (InitOpts projectName cliConfig maybeFile) = do
file <- case maybeFile of
Nothing -> getHomeDirectory >>= pure . (++ "/summoner.toml")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to use (</>) operator instead of (++) to make it work on Windows as well.

Also, m >>= pure . f is f <$> m.

Right conf -> pure $ defaultConfig <> conf
else pure defaultConfig
-- get the final config
let globalConfig = case finalise (config <> cliConfig) of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, to me it looks slightly more cleaner when you write all configs in one place, like this:

let unionConfig = defaultConfig <> fileConfig <> cliConfig
finalConfig <- ...

putStrLn "Using default config.."
pure defaultConfig
Right conf -> pure $ defaultConfig <> conf
else pure defaultConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to make unionConfig you can just return pure mempty here.

fromDecision d = snd $ head $ filter ((== d) . fst) decisionMaybe

toDecision :: Maybe Bool -> Decision
toDecision m = fst $ head $ filter ((== m) . snd) decisionMaybe
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lookup +swap here as well 👍

<*> pure cBench
<*> fin "ghcVersions" cGhcVer
where
fin name = maybe (Left $ "Missing field: " <> name) Right . getLast
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this is an interesting piece of code. Applicative instance for Either works in that way that it fails on first error and returns only single error to user. But it would be much more convenient to tell all absent fields at once. This actually already exist in Haskell world. There's data type called Validation. It's like Either (just different constructor names). But it has slightly more interesting applicative instance. It accumulates all errors. So we can copy-paste Validation to us and this instance and just use it here instead of Either to output multiple errors to user regarding absent fields!


-- | Read configuration from the given file and return it in data type.
loadFileConfig :: MonadIO m => FilePath -> m (Either Toml.EncodeException PartialConfig)
loadFileConfig filePath = liftIO $ TIO.readFile filePath >>= pure . Toml.encode configT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just use throwIO here instead of returning Either. If there's error in configuration we don't want to skip this file, we want to throw exception. This also will simplify code a bit in main.

@@ -198,3 +133,23 @@ generateProject projectName Targets{..} = do
"git" ["add", "."]
"git" ["commit", "-m", "Create the project"]
"git" ["push", "-u", "origin", "master"]

categoryText :: Text
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool idea to move this under where.
You get the joke?) under where is like underwear 😂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣

@@ -1,12 +1,22 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE InstanceSigs #-}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think DeriveGeneric and InstanceSigs should be put into default extensions safely.

data LoadTomlException = LoadTomlException FilePath String

instance Show LoadTomlException where
show (LoadTomlException filePath msg) = "Couldnt parse file " ++ filePath ++ ": " ++ show msg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, sorry for that... I will add Exception instance to EncodeException. But I think I can't write this code better. Because for now EncodeException contains file name only in case of parse error, not encoding error.

README.md Outdated
`false` if you don't. If not specified it would be asked during each run of the `summoner`.
* `lib` – `true` if you want to create `src` folder by default,
`false` if you don't. If not specified it would be asked during each run of the `summoner`.
* `exe` – `true` if you want to create `app` folder by default,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's good to add here that app folder will contain dummy Main.hs file and executable target will be added to .cabal file. Same for test flag.

generateProject projectName targets
runWithOptions (InitOpts projectName cliConfig maybeFile) = do
file <- case maybeFile of
Nothing -> (</> "summoner.toml") <$> getHomeDirectory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can put "summoner.toml" into Default module. As well as IO function which returns full path to this file.

fileConfig <-
if isFile
then loadFileConfig file
else pure mempty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking a little bit more on this, I came to decision that logic here should be slightly complicated to increase UX.

  1. If file exist, print information message (probably we can use Blue for information?) that this file configuration will be used.
  2. If this is a default file ~/summoner.toml and it doesn't exist then print info message that no configuration file was specified (or will be used).
  3. If this is not a default configuration file (i.e. specified by --file) then we should abort immediately because I think that if you specify file manually through CLI you expect this file to exist. But if you have typo in file name, it's better to see error that such file doesn't exist and fix CLI command instead of silently continue to work.

then do
infoMessage $ "Configurations from " <> T.pack file <> " will be used."
loadFileConfig file
else if isDefault
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space here..

Success c -> c
finalConfig <- case finalise unionConfig of
Failure msgs -> do
for_ msgs $ \msg -> errorMessage msg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can eta-reduce lambda here

loadFileConfig file
else if isDefault
then do
warningMessage "Default config file is missing."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can add path defaultTomlFile path to this message just in case. So stupid people won't complain in a way like It says to me that default config file is missing but I don't know where default config file should be.

queryManyRepeatOnFail parser question = do
T.putStrLn question
queryManyRepeatOnFail :: forall a . (Text -> Maybe a) -> IO [a]
queryManyRepeatOnFail parser = do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need do here and you can put promptLoop on the same line as queryManyRepeatOnFail

@vrom911 vrom911 force-pushed the vrom911/48-toml branch from f356caf to aebce9b Compare May 25, 2018 08:11
@chshersh chshersh merged commit a0e1507 into master May 25, 2018
@chshersh chshersh deleted the vrom911/48-toml branch May 25, 2018 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
config TOML configurations feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants