packages feed

headroom-0.4.3.0: src/Headroom/Command/Readers.hs

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}

{-|
Module      : Headroom.Command.Readers
Description : Custom readers for /optparse-applicative/ library
Copyright   : (c) 2019-2022 Vaclav Svejcar
License     : BSD-3-Clause
Maintainer  : vaclav.svejcar@gmail.com
Stability   : experimental
Portability : POSIX

This module contains custom readers required by the /optparse-applicative/
library to parse data types such as 'LicenseType' or 'FileType'.
-}

module Headroom.Command.Readers
  ( licenseReader
  , licenseTypeReader
  , regexReader
  , templateRefReader
  , parseLicense
  )
where

import           Data.Either.Combinators             ( maybeToRight )
import           Headroom.Config.Types               ( LicenseType )
import           Headroom.Data.EnumExtra             ( EnumExtra(..) )
import           Headroom.Data.Regex                 ( Regex(..)
                                                     , compile
                                                     )
import           Headroom.FileType.Types             ( FileType(..) )
import           Headroom.Template.TemplateRef       ( TemplateRef(..)
                                                     , mkTemplateRef
                                                     )
import           Options.Applicative
import           RIO
import qualified RIO.Text                           as T
import qualified RIO.Text.Partial                   as TP


-- | Reader for tuple of 'LicenseType' and 'FileType'.
licenseReader :: ReadM (LicenseType, FileType)
licenseReader = eitherReader parseLicense'
 where
  parseLicense' raw = maybeToRight errMsg (parseLicense $ T.pack raw)
  errMsg = T.unpack $ mconcat
    [ "invalid license/file type, must be in format 'licenseType:fileType' "
    , "(e.g. bsd3:haskell)"
    , "\nAvailable license types: "
    , T.toLower (allValuesToText @LicenseType)
    , "\nAvailable file types: "
    , T.toLower (allValuesToText @FileType)
    ]


-- | Reader for 'LicenseType'.
licenseTypeReader :: ReadM LicenseType
licenseTypeReader = eitherReader parseLicenseType
 where
  parseLicenseType raw = maybeToRight errMsg (textToEnum $ T.pack raw)
  errMsg = T.unpack $ mconcat
    [ "invalid license type, available options: "
    , T.toLower (allValuesToText @LicenseType)
    ]


-- | Reader for 'Regex'.
regexReader :: ReadM Regex
regexReader =
  let parse input = mapLeft displayException (compile . T.pack $ input)
  in  eitherReader parse


-- | Reader for 'TemplateRef'.
templateRefReader :: ReadM TemplateRef
templateRefReader =
  let parse input = mapLeft displayException (mkTemplateRef . T.pack $ input)
  in  eitherReader parse


-- | Parses 'LicenseType' and 'FileType' from the input string,
-- formatted as @licenseType:fileType@.
--
-- >>> parseLicense "bsd3:haskell"
-- Just (BSD3,Haskell)
parseLicense :: Text -> Maybe (LicenseType, FileType)
parseLicense raw
  | [lt, ft] <- TP.splitOn ":" raw = (,) <$> textToEnum lt <*> textToEnum ft
  | otherwise                      = Nothing