module Nix.Options.Parser where import Control.Arrow ( second ) import Data.Char ( isDigit ) import Data.Maybe ( fromMaybe ) import Data.Text ( Text ) import qualified Data.Text as Text import Data.Time import Nix.Options import Options.Applicative hiding ( ParserResult(..) ) decodeVerbosity :: Int -> Verbosity decodeVerbosity 0 = ErrorsOnly decodeVerbosity 1 = Informational decodeVerbosity 2 = Talkative decodeVerbosity 3 = Chatty decodeVerbosity 4 = DebugInfo decodeVerbosity _ = Vomit 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 :: UTCTime -> Parser Options nixOptions current = Options <$> (fromMaybe Informational <$> optional (option (do a <- str if all isDigit a then pure $ decodeVerbosity (read a) else fail "Argument to -v/--verbose must be a number" ) (short 'v' <> long "verbose" <> help "Verbose output") ) ) <*> switch ( long "trace" <> help "Enable tracing code (even more can be seen if built with --flags=tracing)" ) <*> switch (long "thunks" <> help "Enable reporting of thunk tracing as well as regular evaluation" ) <*> switch ( long "values" <> help "Enable reporting of value provenance in error messages" ) <*> switch ( long "scopes" <> help "Enable reporting of scopes in evaluation traces" ) <*> optional (strOption ( long "reduce" <> help "When done evaluating, output the evaluated part of the expression to FILE" ) ) <*> switch (long "reduce-sets" <> help "Reduce set members that aren't used; breaks if hasAttr is used" ) <*> switch (long "reduce-lists" <> help "Reduce list members that aren't used; breaks if elemAt is used" ) <*> 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 "find" <> help "If selected, find paths within attr trees") <*> optional (strOption ( long "find-file" <> help "Look up the given files in Nix's search path" ) ) <*> switch ( long "strict" <> help "When used with --eval, recursively evaluate list elements and attributes" ) <*> switch (long "eval" <> help "Whether to evaluate, or just pretty-print") <*> switch ( long "json" <> help "Print the resulting value as an JSON representation" ) <*> switch ( long "xml" <> help "Print the resulting value as an XML representation" ) <*> optional (strOption ( short 'A' <> long "attr" <> help "Select an attribute from the top-level Nix expression being evaluated" ) ) <*> many (strOption (short 'I' <> long "include" <> help "Add a path to the Nix expression search path" ) ) <*> 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 "repl" <> help "After performing any indicated actions, enter the REPL" ) <*> 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" ) ) <*> option (parseTimeOrError True defaultTimeLocale "%Y/%m/%d %H:%M:%S" <$> str) (long "now" <> value current <> help "Set current time for testing purposes" ) <*> many (strArgument (metavar "FILE" <> help "Path of file to parse")) nixOptionsInfo :: UTCTime -> ParserInfo Options nixOptionsInfo current = info (helper <*> nixOptions current) (fullDesc <> progDesc "" <> header "hnix")