From 96df58fb29930c44e6912a7fc36bb3951cbc4efb Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Wed, 11 Apr 2018 20:53:38 -0700 Subject: [PATCH] Split off command-line options processing into a new Nix.Options module --- hnix.cabal | 8 ++++- main/Main.hs | 88 ++-------------------------------------------- package.yaml | 5 ++- src/Nix/Options.hs | 82 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 89 deletions(-) create mode 100644 src/Nix/Options.hs diff --git a/hnix.cabal b/hnix.cabal index 7051767..a9cf893 100644 --- a/hnix.cabal +++ b/hnix.cabal @@ -2,7 +2,7 @@ -- -- see: https://github.com/sol/hpack -- --- hash: 00ae617f664cd9dc67f4a6551a0e3c0eee19899f21b44c6dda24e17618a8fb5d +-- hash: 2c49222c1eda4bbca80475f682dd4cfaccf99ed3d4143ee2ad25f91171f21898 name: hnix version: 0.5.0 @@ -41,6 +41,7 @@ library Nix.Expr.Types.Annotated Nix.Lint Nix.Normal + Nix.Options Nix.Parser Nix.Parser.Library Nix.Parser.Operators @@ -78,6 +79,7 @@ library , megaparsec , monadlist , mtl + , optparse-applicative , process , regex-tdfa , regex-tdfa-text @@ -140,6 +142,7 @@ test-suite hnix-tests Glob , ansi-wl-pprint , base >=4.9 && <5 + , bytestring , compact , containers , data-fix @@ -150,6 +153,7 @@ test-suite hnix-tests , hnix , interpolate , mtl + , optparse-applicative , process , serialise , split @@ -175,6 +179,7 @@ benchmark hnix-benchmarks build-depends: ansi-wl-pprint , base >=4.9 && <5 + , bytestring , compact , containers , criterion @@ -184,6 +189,7 @@ benchmark hnix-benchmarks , filepath , hnix , mtl + , optparse-applicative , serialise , template-haskell , text diff --git a/main/Main.hs b/main/Main.hs index a5fbda9..b423150 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -1,7 +1,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} -- {-# LANGUAGE QuasiQuotes #-} -{-# LANGUAGE TypeApplications #-} module Main where @@ -12,16 +11,14 @@ import Control.Monad import Control.Monad.ST import Data.Fix import qualified Data.HashMap.Lazy as M -import Data.Text (Text) -import qualified Data.Text as Text import qualified Data.Text.IO as Text import qualified Nix import Nix.Cache -import Nix.Eval -import Nix.Exec (Lazy, runLazyM, callFunc) +import Nix.Exec (Lazy, runLazyM) import Nix.Expr import Nix.Lint import Nix.Normal +import Nix.Options import Nix.Parser import Nix.Pretty import Nix.Stack (NixException(..)) @@ -32,80 +29,9 @@ import System.IO import System.FilePath import Text.PrettyPrint.ANSI.Leijen hiding ((<$>)) -data Options = Options - { verbose :: Bool - , debug :: Bool - , evaluate :: Bool - , check :: Bool - , readFrom :: Maybe FilePath - , cache :: Bool - , parse :: Bool - , parseOnly :: Bool - , ignoreErrors :: Bool - , expression :: Maybe Text - , arg :: [(Text, Text)] - , argstr :: [(Text, Text)] - , fromFile :: Maybe FilePath - , filePaths :: [FilePath] - } - -argPair :: Mod OptionFields (Text, Text) -> Parser (Text, Text) -argPair = option $ str >>= \s -> - case Text.findIndex (== '=') s of - Nothing -> errorWithoutStackTrace - "Format of --arg/--argstr in hnix is: name=expr" - Just i -> return $ second Text.tail $ Text.splitAt i s - -mainOptions :: Parser Options -mainOptions = Options - <$> switch - ( short 'v' - <> long "verbose" - <> help "Verbose output") - <*> switch - ( short 'd' - <> long "debug" - <> help "Debug output") - <*> switch - ( long "eval" - <> help "Whether to evaluate, or just pretty-print") - <*> switch - ( long "check" - <> help "Whether to check for syntax errors after parsing") - <*> optional (strOption - ( long "read" - <> help "Read in an expression tree from a binary cache")) - <*> switch - ( long "cache" - <> help "Write out the parsed expression tree to a binary cache") - <*> switch - ( long "parse" - <> help "Whether to parse the file (also the default right now)") - <*> switch - ( long "parse-only" - <> help "Whether to parse only, no pretty printing or checking") - <*> switch - ( long "ignore-errors" - <> help "Continue parsing files, even if there are errors") - <*> optional (strOption - ( short 'E' - <> long "expr" - <> help "Expression to parse or evaluate")) - <*> many (argPair - ( long "arg" - <> help "Argument to pass to an evaluated lambda")) - <*> many (argPair - ( long "argstr" - <> help "Argument string to pass to an evaluated lambda")) - <*> optional (strOption - ( short 'f' - <> long "file" - <> help "Parse all of the files given in FILE; - means stdin")) - <*> many (strArgument (metavar "FILE" <> help "Path of file to parse")) - main :: IO () main = do - opts <- execParser optsDef + opts <- execParser nixOptionsInfo case readFrom opts of Just path -> do let file = addExtension (dropExtension path) "nix" @@ -127,12 +53,7 @@ main = do paths -> mapM_ (processFile opts) paths where - optsDef :: ParserInfo Options - optsDef = info (helper <*> mainOptions) - (fullDesc <> progDesc "" <> header "hnix") - processFile opts path = do - -- putStrLn "Parsing file..." eres <- parseNixFileLoc path handleResult opts (Just path) eres @@ -148,9 +69,6 @@ main = do NixEvalException msg -> errorWithoutStackTrace msg process opts mpath expr = do - -- expr <- Exc.evaluate $ force expr - -- putStrLn "Parsing file...done" - when (check opts) $ putStrLn $ runST $ Nix.runLintM . renderSymbolic =<< Nix.lint expr diff --git a/package.yaml b/package.yaml index 07e547e..a065f56 100644 --- a/package.yaml +++ b/package.yaml @@ -16,6 +16,7 @@ extra-source-files: dependencies: - base >= 4.9 && < 5 - ansi-wl-pprint + - bytestring - compact - containers - data-fix @@ -23,6 +24,7 @@ dependencies: - exceptions - filepath - mtl + - optparse-applicative - serialise - template-haskell - text @@ -42,7 +44,6 @@ library: - array >= 0.4 && < 0.6 - base16-bytestring - binary - - bytestring - cryptohash - deriving-compat >= 0.3 && < 0.5 - directory @@ -66,8 +67,6 @@ executables: main: Main.hs dependencies: - hnix - - bytestring - - optparse-applicative tests: hnix-tests: diff --git a/src/Nix/Options.hs b/src/Nix/Options.hs new file mode 100644 index 0000000..5f8d345 --- /dev/null +++ b/src/Nix/Options.hs @@ -0,0 +1,82 @@ +module Nix.Options where + +import Control.Arrow (second) +import Data.Text (Text) +import qualified Data.Text as Text +import Options.Applicative hiding (ParserResult(..)) +import Text.PrettyPrint.ANSI.Leijen hiding ((<$>)) + +data Options = Options + { verbose :: Bool + , debug :: Bool + , evaluate :: Bool + , check :: Bool + , readFrom :: Maybe FilePath + , cache :: Bool + , parse :: Bool + , parseOnly :: Bool + , ignoreErrors :: Bool + , expression :: Maybe Text + , arg :: [(Text, Text)] + , argstr :: [(Text, Text)] + , fromFile :: Maybe FilePath + , filePaths :: [FilePath] + } + +argPair :: Mod OptionFields (Text, Text) -> Parser (Text, Text) +argPair = option $ str >>= \s -> + case Text.findIndex (== '=') s of + Nothing -> errorWithoutStackTrace + "Format of --arg/--argstr in hnix is: name=expr" + Just i -> return $ second Text.tail $ Text.splitAt i s + +nixOptions :: Parser Options +nixOptions = Options + <$> switch + ( short 'v' + <> long "verbose" + <> help "Verbose output") + <*> switch + ( short 'd' + <> long "debug" + <> help "Debug output") + <*> switch + ( long "eval" + <> help "Whether to evaluate, or just pretty-print") + <*> switch + ( long "check" + <> help "Whether to check for syntax errors after parsing") + <*> optional (strOption + ( long "read" + <> help "Read in an expression tree from a binary cache")) + <*> switch + ( long "cache" + <> help "Write out the parsed expression tree to a binary cache") + <*> switch + ( long "parse" + <> help "Whether to parse the file (also the default right now)") + <*> switch + ( long "parse-only" + <> help "Whether to parse only, no pretty printing or checking") + <*> switch + ( long "ignore-errors" + <> help "Continue parsing files, even if there are errors") + <*> optional (strOption + ( short 'E' + <> long "expr" + <> help "Expression to parse or evaluate")) + <*> many (argPair + ( long "arg" + <> help "Argument to pass to an evaluated lambda")) + <*> many (argPair + ( long "argstr" + <> help "Argument string to pass to an evaluated lambda")) + <*> optional (strOption + ( short 'f' + <> long "file" + <> help "Parse all of the files given in FILE; - means stdin")) + <*> many (strArgument (metavar "FILE" <> help "Path of file to parse")) + +nixOptionsInfo :: ParserInfo Options +nixOptionsInfo = info (helper <*> nixOptions) + (fullDesc <> progDesc "" <> header "hnix")