packages feed

horizon-gen-nix-0.2: src/Horizon/Gen/Nix/Options.hs

{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TemplateHaskell       #-}
module Horizon.Gen.Nix.Options
  ( horizonGenNixOpts
  , horizonGenNixOptsInfo
  , InputFile (..)
  , HorizonCommand (..)
  , HorizonOptions (..)
  , MakePackageSetOptions (..)
  , OverlayOptions (..)
  , defaultMakePackageSetOptions
  , defaultPackagesDirectory
  , defaultPackageSetFile
  , defaultOverlayFile
  , defaultOverlayOptions
  ,   ) where

import           Data.Either.Combinators                 (mapLeft)
import           Data.Kind                               (Type)
import           Horizon.Gen.Nix.Types.OverlayFile       (OverlayFile (MkOverlayFile))
import           Horizon.Gen.Nix.Types.PackagesDirectory (PackagesDirectory (MkPackagesDirectory))
import           Horizon.Gen.Nix.Types.PackageSetFile    (PackageSetFile (MkPackageSetFile))
import           Options.Applicative                     (Parser, ParserInfo,
                                                          ReadM, command,
                                                          eitherReader, help,
                                                          helper, info, long,
                                                          metavar, option,
                                                          progDesc, subparser,
                                                          value)
import           Path                                    (File, Path, Rel,
                                                          mkRelDir, mkRelFile,
                                                          parseRelDir,
                                                          parseRelFile)
import           Path.Dhall                              ()


parsePackagesDirectory :: ReadM PackagesDirectory
parsePackagesDirectory = eitherReader $ mapLeft show . fmap MkPackagesDirectory . parseRelDir

defaultPackagesDirectory :: PackagesDirectory
defaultPackagesDirectory = MkPackagesDirectory $(mkRelDir "pkgs")

packagesDirectoryOption :: Parser PackagesDirectory
packagesDirectoryOption =
  option parsePackagesDirectory
    (  long "packages-dir"
    <> metavar "PACKAGES_DIR"
    <> value defaultPackagesDirectory
    <> help "The directory to put haskell packages."
    )


parsePackageSetFile :: ReadM PackageSetFile
parsePackageSetFile = eitherReader $ mapLeft show . fmap MkPackageSetFile . parseRelFile

defaultPackageSetFile :: PackageSetFile
defaultPackageSetFile = MkPackageSetFile $(mkRelFile "initial-packages.nix")

packageSetFileOption :: Parser PackageSetFile
packageSetFileOption =
  option parsePackageSetFile
    (  long "packageset-file"
    <> metavar "PACKAGESET_FILE"
    <> value defaultPackageSetFile
    <> help "The name of the package set file"
    )


parseOverlayFile :: ReadM OverlayFile
parseOverlayFile = eitherReader $ mapLeft show . fmap MkOverlayFile . parseRelFile

defaultOverlayFile :: OverlayFile
defaultOverlayFile = MkOverlayFile $(mkRelFile "overlay.nix")

overlayFileOption :: Parser OverlayFile
overlayFileOption =
  option parseOverlayFile
    (  long "overlay-file"
    <> metavar "OVERLAY_FILE"
    <> value defaultOverlayFile
    <> help "The name of the overlay file."
    )

type InputFile :: Type
newtype InputFile where
  MkInputFile :: { fromInputFile :: Path Rel File }
              -> InputFile
  deriving stock (Eq, Show)

parseInputFile :: ReadM InputFile
parseInputFile = eitherReader $ mapLeft show . fmap MkInputFile . parseRelFile

defaultInputFile :: InputFile
defaultInputFile = MkInputFile $(mkRelFile "horizon.dhall")

inputFileOption :: Parser InputFile
inputFileOption =
  option parseInputFile
    (  long "input-file"
    <> metavar "INPUT_FILE"
    <> value defaultInputFile
    <> help "The name of the input file."
    )


type MakePackageSetOptions :: Type
data MakePackageSetOptions where
  MkMakePackageSetOptions :: { optPackageSetFile :: PackageSetFile }
                          -> MakePackageSetOptions
  deriving stock (Eq, Show)

makePackageSetOptions :: Parser MakePackageSetOptions
makePackageSetOptions =
      MkMakePackageSetOptions
  <$> packageSetFileOption

defaultMakePackageSetOptions :: MakePackageSetOptions
defaultMakePackageSetOptions = MkMakePackageSetOptions defaultPackageSetFile


type OverlayOptions :: Type
data OverlayOptions where
  MkOverlayOptions :: { optOverlayFile :: OverlayFile}
                   -> OverlayOptions
  deriving stock (Eq, Show)

overlayOptions :: Parser OverlayOptions
overlayOptions =
      MkOverlayOptions
  <$> overlayFileOption

defaultOverlayOptions :: OverlayOptions
defaultOverlayOptions = MkOverlayOptions defaultOverlayFile


type HorizonCommand :: Type
data HorizonCommand where
  MakePackageSetCommand :: MakePackageSetOptions -> HorizonCommand
  OverlayCommand :: OverlayOptions -> HorizonCommand
  deriving stock (Eq, Show)

type HorizonOptions :: Type
data HorizonOptions where
  MkHorizonOptions :: { optInputFile :: InputFile
                      , optPackagesDirectory :: PackagesDirectory
                      , optHorizonCommand :: HorizonCommand} -> HorizonOptions
  deriving stock (Eq, Show)

makePackageSetCommand :: Parser HorizonCommand
makePackageSetCommand = fmap MakePackageSetCommand makePackageSetOptions

overlayCommand :: Parser HorizonCommand
overlayCommand = fmap OverlayCommand overlayOptions

horizonCommandOpts :: Parser HorizonCommand
horizonCommandOpts = subparser
  ( command "make-package-set" (info (helper <*> makePackageSetCommand) ( progDesc "Run in MakePackageSet Mode" ))
 <> command "overlay" (info (helper <*> overlayCommand) ( progDesc "Run in Overlay Mode" ))
  )

horizonGenNixOpts :: Parser HorizonOptions
horizonGenNixOpts =
      MkHorizonOptions
  <$> inputFileOption
  <*> packagesDirectoryOption
  <*> horizonCommandOpts

horizonGenNixOptsInfo :: ParserInfo HorizonOptions
horizonGenNixOptsInfo = info (helper <*> horizonGenNixOpts) mempty