packages feed

scripths-0.5.2.0: src/ScriptHs/CLI/Types.hs

module ScriptHs.CLI.Types (
    Args (..),
    emptyArgs,
    parseArgs,
) where

import Data.List (isPrefixOf)
import ScriptHs.Markdown

-- | Parsed command-line options.
data Args = Args
    { argScript :: Maybe FilePath
    , argOutput :: Maybe FilePath
    , argPackages :: [FilePath]
    , argNoLocalProject :: Bool
    , argInPlace :: Bool
    , argHelp :: Bool
    , argVersion :: Bool
    , argCodeStyle :: CodeStyle
    , argOutputStyle :: OutputStyle
    }

emptyArgs :: Args
emptyArgs =
    Args
        { argScript = Nothing
        , argOutput = Nothing
        , argPackages = []
        , argNoLocalProject = False
        , argInPlace = False
        , argHelp = False
        , argVersion = False
        , argCodeStyle = DisplayCode
        , argOutputStyle = OutputQuoted
        }

{- | Parse args: @[-o FILE | --output=FILE] [-i | --in-place] [--package DIR |
-p DIR | --package=DIR]... [--no-local-project] [-h | --help] <script>@. The
script is the sole non-flag argument.
-}
parseArgs :: [String] -> Either String Args
parseArgs = go emptyArgs
  where
    go a [] = Right a
    go a ("-o" : f : rest) = go a{argOutput = Just f} rest
    go _ ["-o"] = Left "-o requires a filename"
    go a (tok : rest)
        | tok == "-p" || tok == "--package" = case rest of
            (d : rest') -> go a{argPackages = argPackages a ++ [d]} rest'
            [] -> Left (tok ++ " requires a directory")
        | Just f <- stripFlag "--output=" tok = go a{argOutput = Just f} rest
        | Just d <- stripFlag "--package=" tok =
            go a{argPackages = argPackages a ++ [d]} rest
        | tok == "--no-local-project" = go a{argNoLocalProject = True} rest
        | tok == "-i" || tok == "--in-place" = go a{argInPlace = True} rest
        | tok == "-h" || tok == "--help" = go a{argHelp = True} rest
        | tok == "-v" || tok == "--version" = go a{argVersion = True} rest
        | tok == "--code-style" = case rest of
            (d : rest') -> case parseCodeStyle d of
                Just codeStyle -> go a{argCodeStyle = codeStyle} rest'
                Nothing -> Left ("Could not parse code style: " ++ tok)
            [] -> Left (tok ++ " requires a code style")
        | tok == "--output-style" = case rest of
            (d : rest') -> case parseOutputStyle d of
                Just codeStyle -> go a{argOutputStyle = codeStyle} rest'
                Nothing -> Left ("Could not parse output style: " ++ tok)
            [] -> Left (tok ++ " requires a output style")
        | "-" `isPrefixOf` tok = Left ("unknown flag: " ++ tok)
        | otherwise = case argScript a of
            Nothing -> go a{argScript = Just tok} rest
            Just _ -> Left ("unexpected extra argument: " ++ tok)
    stripFlag p s = if p `isPrefixOf` s then Just (drop (length p) s) else Nothing