packages feed

fortran-src-extras-0.1.0: src/Language/Fortran/Extras/RunOptions.hs

{-# LANGUAGE FlexibleInstances #-}

-- | This module is responsible for handling CLI options
module Language.Fortran.Extras.RunOptions
  ( FortranSrcRunOptions(..)
  , getFortranSrcRunOptions
  , unwrapFortranSrcOptions
  , RunOptions(..)
  , getRunOptions
  )
where

import qualified Data.ByteString.Char8         as B
import           Data.Char                      ( toLower )
import           Data.List                      ( isInfixOf )
import           Data.Semigroup                 ( (<>) )
import           Language.Fortran.Version       ( FortranVersion(..)
                                                , selectFortranVersion
                                                )
import           Options.Applicative

import           Language.Fortran.Util.Files
                                                ( flexReadFile )

-- | Holds fortran-src specific CLI options.
-- This includes the version of the parser, included files and the path
-- of the source
data FortranSrcRunOptions = FortranSrcRunOptions
    { version  :: !FortranVersion
    , includes :: ![String]
    , path     :: !String
    } deriving Show

-- | Provided version, includes and path strings, this functon maps them to
-- 'FortranSrcRunOptions'
--
-- Note that this will throw an exception on an unrecognized version string.
toFortranSrcOptions :: String -> [String] -> String -> FortranSrcRunOptions
toFortranSrcOptions verStr =
    let (Just ver) = selectFortranVersion verStr
     in FortranSrcRunOptions ver

-- | Definition of parser for 'FortranSrcRunOptions'
fortranSrcRunOptionsParser :: Parser FortranSrcRunOptions
fortranSrcRunOptionsParser =
  toFortranSrcOptions
    <$> strOption
          (  short 'v'
          <> long "fortranVersion"
          <> metavar "VERSION"
          <> help
               "Fortran version to use, format: Fortran[66/77/77l/77e/90/95/03/08]"
          )
    <*> many
          (strOption
            (short 'I' <> long "include" <> metavar "DIRECTORY" <> help
              "Directory to include files from"
            )
          )
    <*> argument str (metavar "PATH")

-- | Given description and header, decorate fortran-src options parser with
-- info details
fortranSrcRunOptionsInfo :: String -> String -> ParserInfo FortranSrcRunOptions
fortranSrcRunOptionsInfo programDescription headerDescription = info
  (helper <*> fortranSrcRunOptionsParser)
  (fullDesc <> progDesc programDescription <> header headerDescription)

-- | Given description and header, execute fortran-src options parser
-- and get the 'FortranSrcRunOptions'
getFortranSrcRunOptions :: String -> String -> IO FortranSrcRunOptions
getFortranSrcRunOptions programDescription headerDescription =
  execParser $ fortranSrcRunOptionsInfo programDescription headerDescription

-- | Obtain path, contents, include dirs and 'FortranVersion'
-- from 'FortranSrcRunOptions'
unwrapFortranSrcOptions
  :: FortranSrcRunOptions -> IO (String, B.ByteString, [String], FortranVersion)
unwrapFortranSrcOptions options = do
  let p = path options
  c <- flexReadFile p
  let i = includes options
      v = version options
  return (p, c, i, v)

-- | Holds 'FortranSrcRunOptions' and additional tool specific CLI options
data RunOptions a = RunOptions
    { fortranSrcOpts :: FortranSrcRunOptions
    , toolOpts :: a
    } deriving Show

-- | Given decription, header and tool options parser, decorate options
-- with info details
runOptionsInfo :: String -> String -> Parser a -> ParserInfo (RunOptions a)
runOptionsInfo programDescription headerDescription toolOptsParser = info
  (helper <*> liftA2 RunOptions fortranSrcRunOptionsParser toolOptsParser)
  (fullDesc <> progDesc programDescription <> header headerDescription)

-- | Given description, header and tool options parser, execute options parser
-- and get the 'RunOptions'
getRunOptions :: String -> String -> Parser a -> IO (RunOptions a)
getRunOptions programDescription headerDescription toolOptsParser =
  execParser
    $ runOptionsInfo programDescription headerDescription toolOptsParser