on 2a68244 help sign in
Idris-dev/src/Idris/CmdOptions.hs
281 lines 15 kB history raw
1{-# LANGUAGE CPP #-}
2{-|
3Module : Idris.CmdOptions
4Description : A parser for the CmdOptions for the Idris executable.
5License : BSD3
6Maintainer : The Idris Community.
7-}
8{-# LANGUAGE Arrows #-}
9module Idris.CmdOptions
10 (
11 module Idris.CmdOptions
12 , opt
13 , getClient, getPkg, getPkgCheck, getPkgClean, getPkgMkDoc
14 , getPkgREPL, getPkgTest, getPort, getIBCSubDir
15 ) where
17import Idris.AbsSyntax (getClient, getIBCSubDir, getPkg, getPkgCheck,
18 getPkgClean, getPkgMkDoc, getPkgREPL, getPkgTest,
19 getPort, opt)
20import Idris.AbsSyntaxTree
21import Idris.Info (getIdrisVersion)
22-- import Idris.REPL
23import IRTS.CodegenCommon
25import Control.Monad.Trans (lift)
26import Control.Monad.Trans.Except (throwE)
27import Control.Monad.Trans.Reader (ask)
28import Data.Char
29import Data.Maybe
30#if MIN_VERSION_optparse_applicative(0,13,0)
31import Data.Monoid ((<>))
32#endif
33import Options.Applicative
34import Options.Applicative.Arrows
35import Options.Applicative.Types (ReadM(..))
36import Safe (lastMay)
37import Text.ParserCombinators.ReadP hiding (many, option)
38import qualified Text.PrettyPrint.ANSI.Leijen as PP
40runArgParser :: IO [Opt]
41runArgParser = do opts <- execParser $ info parser
42 (fullDesc
43 <> headerDoc (Just idrisHeader)
44 <> progDescDoc (Just idrisProgDesc)
45 <> footerDoc (Just idrisFooter)
46 )
47 return $ preProcOpts opts
48 where
49 idrisHeader = PP.hsep [PP.text "Idris version", PP.text getIdrisVersion, PP.text ", (C) The Idris Community 2016"]
50 idrisProgDesc = PP.vsep [PP.empty,
51 PP.text "Idris is a general purpose pure functional programming language with dependent",
52 PP.text "types. Dependent types allow types to be predicated on values, meaning that",
53 PP.text "some aspects of a program's behaviour can be specified precisely in the type.",
54 PP.text "It is compiled, with eager evaluation. Its features are influenced by Haskell",
55 PP.text "and ML.",
56 PP.empty,
57 PP.vsep $ map (PP.indent 4 . PP.text) [
58 "+ Full dependent types with dependent pattern matching",
59 "+ Simple case expressions, where-clauses, with-rule",
60 "+ Pattern matching let- and lambda-bindings",
61 "+ Overloading via Interfaces (Type class-like), Monad comprehensions",
62 "+ do-notation, idiom brackets",
63 "+ Syntactic conveniences for lists, tuples, dependent pairs",
64 "+ Totality checking",
65 "+ Coinductive types",
66 "+ Indentation significant syntax, Extensible syntax",
67 "+ Tactic based theorem proving (influenced by Coq)",
68 "+ Cumulative universes",
69 "+ Simple Foreign Function Interface",
70 "+ Hugs style interactive environment"
71 ]]
72 idrisFooter = PP.vsep [PP.text "It is important to note that Idris is first and foremost a research tool",
73 PP.text "and project. Thus the tooling provided and resulting programs created",
74 PP.text "should not necessarily be seen as production ready nor for industrial use.",
75 PP.empty,
76 PP.text "More details over Idris can be found online here:",
77 PP.empty,
78 PP.indent 4 (PP.text "http://www.idris-lang.org/")]
80pureArgParser :: [String] -> [Opt]
81pureArgParser args = case getParseResult $ execParserPure (prefs idm) (info parser idm) args of
82 Just opts -> preProcOpts opts
83 Nothing -> []
85parser :: Parser [Opt]
86parser = runA $ proc () -> do
87 flags <- asA parseFlags -< ()
88 files <- asA (many $ argument (fmap Filename str) (metavar "FILES")) -< ()
89 A parseVersion >>> A helper -< (flags ++ files)
91parseFlags :: Parser [Opt]
92parseFlags = many $
93 flag' NoBanner (long "nobanner" <> help "Suppress the banner")
94 <|> flag' Quiet (short 'q' <> long "quiet" <> help "Quiet verbosity")
96 -- IDE Mode Specific Flags
97 <|> flag' Idemode (long "ide-mode" <> help "Run the Idris REPL with machine-readable syntax")
98 <|> flag' IdemodeSocket (long "ide-mode-socket" <> help "Choose a socket for IDE mode to listen on")
100 <|> (Client <$> strOption (long "client"))
102 -- Logging Flags
103 <|> (OLogging <$> option auto (long "log" <> metavar "LEVEL" <> help "Debugging log level"))
104 <|> (OLogCats <$> option (str >>= parseLogCats)
105 (long "logging-categories"
106 <> metavar "CATS"
107 <> help "Colon separated logging categories. Use --listlogcats to see list."))
109 -- Turn off things
110 <|> flag' NoBasePkgs (long "nobasepkgs" <> help "Do not use the given base package")
111 <|> flag' NoPrelude (long "noprelude" <> help "Do not use the given prelude")
112 <|> flag' NoBuiltins (long "nobuiltins" <> help "Do not use the builtin functions")
114 <|> flag' NoREPL (long "check" <> help "Typecheck only, don't start the REPL")
116 <|> (Output <$> strOption (short 'o' <> long "output" <> metavar "FILE" <> help "Specify output file"))
118 -- <|> flag' TypeCase (long "typecase")
119 <|> flag' Interface (long "interface" <> help "Generate interface files from ExportLists")
120 <|> flag' TypeInType (long "typeintype" <> help "Turn off Universe checking")
121 <|> flag' DefaultTotal (long "total" <> help "Require functions to be total by default")
122 <|> flag' DefaultPartial (long "partial")
123 <|> flag' WarnPartial (long "warnpartial" <> help "Warn about undeclared partial functions")
124 <|> flag' WarnReach (long "warnreach" <> help "Warn about reachable but inaccessible arguments")
125 <|> flag' NoCoverage (long "nocoverage")
126 <|> flag' ErrContext (long "errorcontext")
128 -- Show things
129 <|> flag' ShowAll (long "info" <> help "Display information about installation.")
130 <|> flag' ShowLoggingCats (long "listlogcats" <> help "Display logging categories")
131 <|> flag' ShowLibs (long "link" <> help "Display link flags")
132 <|> flag' ShowPkgs (long "listlibs" <> help "Display installed libraries")
133 <|> flag' ShowLibDir (long "libdir" <> help "Display library directory")
134 <|> flag' ShowDocDir (long "docdir" <> help "Display idrisdoc install directory")
135 <|> flag' ShowIncs (long "include" <> help "Display the includes flags")
137 <|> flag' (Verbose 3) (long "V2" <> help "Loudest verbosity")
138 <|> flag' (Verbose 2) (long "V1" <> help "Louder verbosity")
139 <|> flag' (Verbose 1) (short 'V' <> long "V0" <>long "verbose" <> help "Loud verbosity")
141 <|> (IBCSubDir <$> strOption (long "ibcsubdir" <> metavar "FILE" <> help "Write IBC files into sub directory"))
142 <|> (ImportDir <$> strOption (short 'i' <> long "idrispath" <> help "Add directory to the list of import paths"))
143 <|> (SourceDir <$> strOption (long "sourcepath" <> help "Add directory to the list of source search paths"))
145 <|> flag' WarnOnly (long "warn")
147 <|> (Pkg <$> strOption (short 'p' <> long "package" <> help "Add package as a dependency"))
148 <|> (Port <$> option portReader (long "port" <> metavar "PORT" <> help "REPL TCP port - pass \"none\" to not bind any port"))
150 -- Package commands
151 <|> (PkgBuild <$> strOption (long "build" <> metavar "IPKG" <> help "Build package"))
152 <|> (PkgInstall <$> strOption (long "install" <> metavar "IPKG" <> help "Install package"))
153 <|> (PkgREPL <$> strOption (long "repl" <> metavar "IPKG" <> help "Launch REPL, only for executables"))
154 <|> (PkgClean <$> strOption (long "clean" <> metavar "IPKG" <> help "Clean package"))
155 <|> (PkgDocBuild <$> strOption (long "mkdoc" <> metavar "IPKG" <> help "Generate IdrisDoc for package"))
156 <|> (PkgDocInstall <$> strOption (long "installdoc" <> metavar "IPKG" <> help "Install IdrisDoc for package"))
157 <|> (PkgCheck <$> strOption (long "checkpkg" <> metavar "IPKG" <> help "Check package only"))
158 <|> (PkgTest <$> strOption (long "testpkg" <> metavar "IPKG" <> help "Run tests for package"))
160 -- Misc options
161 <|> (BCAsm <$> strOption (long "bytecode"))
163 <|> flag' (OutputTy Raw) (short 'S' <> long "codegenonly" <> help "Do no further compilation of code generator output")
164 <|> flag' (OutputTy Object) (short 'c' <> long "compileonly" <> help "Compile to object files rather than an executable")
166 <|> (DumpDefun <$> strOption (long "dumpdefuns"))
167 <|> (DumpCases <$> strOption (long "dumpcases"))
169 <|> (UseCodegen . parseCodegen) <$> strOption (long "codegen"
170 <> metavar "TARGET"
171 <> help "Select code generator: C, Javascript, Node and bytecode are bundled with Idris")
173 <|> ((UseCodegen . Via JSONFormat) <$> strOption (long "portable-codegen"
174 <> metavar "TARGET"
175 <> help "Pass the name of the code generator. This option is for codegens that take JSON formatted IR."))
177 <|> (CodegenArgs <$> strOption (long "cg-opt"
178 <> metavar "ARG"
179 <> help "Arguments to pass to code generator"))
181 <|> (EvalExpr <$> strOption (long "eval" <> short 'e' <> metavar "EXPR" <> help "Evaluate an expression without loading the REPL"))
183 <|> flag' (InterpretScript "Main.main") (long "execute" <> help "Execute as idris")
184 <|> (InterpretScript <$> strOption (long "exec" <> metavar "EXPR" <> help "Execute as idris"))
186 <|> ((Extension . getExt) <$> strOption (long "extension"
187 <> short 'X'
188 <> metavar "EXT"
189 <> help "Turn on language extension (TypeProviders or ErrorReflection)"))
191 -- Optimisation Levels
192 <|> flag' (OptLevel 3) (long "O3")
193 <|> flag' (OptLevel 2) (long "O2")
194 <|> flag' (OptLevel 1) (long "O1")
195 <|> flag' (OptLevel 0) (long "O0")
197 <|> flag' (AddOpt PETransform) (long "partial-eval")
198 <|> flag' (RemoveOpt PETransform) (long "no-partial-eval" <> help "Switch off partial evaluation, mainly for debugging purposes")
200 <|> (OptLevel <$> option auto (short 'O' <> long "level"))
202 <|> (TargetTriple <$> strOption (long "target" <> metavar "TRIPLE" <> help "If supported the codegen will target the named triple."))
203 <|> (TargetCPU <$> strOption (long "cpu" <> metavar "CPU" <> help "If supported the codegen will target the named CPU e.g. corei7 or cortex-m3"))
205 -- Colour Options
206 <|> flag' (ColourREPL True) (long "colour" <> long "color" <> help "Force coloured output")
207 <|> flag' (ColourREPL False) (long "nocolour" <> long "nocolor" <> help "Disable coloured output")
209 <|> (UseConsoleWidth <$> option (str >>= parseConsoleWidth) (long "consolewidth" <> metavar "WIDTH" <> help "Select console width: auto, infinite, nat"))
211 <|> flag' DumpHighlights (long "highlight" <> help "Emit source code highlighting")
213 <|> flag' NoElimDeprecationWarnings (long "no-elim-deprecation-warnings" <> help "Disable deprecation warnings for %elim")
214 <|> flag' NoOldTacticDeprecationWarnings (long "no-tactic-deprecation-warnings" <> help "Disable deprecation warnings for the old tactic sublanguage")
216 where
217 getExt :: String -> LanguageExt
218 getExt s = fromMaybe (error ("Unknown extension " ++ s)) (maybeRead s)
219 maybeRead :: String -> Maybe LanguageExt
220 maybeRead = fmap fst . listToMaybe . reads
221 portReader :: ReadM REPLPort
222 portReader =
223 ((ListenPort . fromIntegral) <$> auto) <|>
224 (ReadM $ do opt <- ask
225 if map toLower opt == "none"
226 then return $ DontListen
227 else lift $ throwE $ ErrorMsg $
228 "got " <> opt <> " expected port number or \"none\"")
230parseVersion :: Parser (a -> a)
231parseVersion = infoOption getIdrisVersion (short 'v' <> long "version" <> help "Print version information")
233preProcOpts :: [Opt] -> [Opt]
234preProcOpts (NoBuiltins : xs) = NoBuiltins : NoPrelude : preProcOpts xs
235preProcOpts (Output s : xs) = Output s : NoREPL : preProcOpts xs
236preProcOpts (BCAsm s : xs) = BCAsm s : NoREPL : preProcOpts xs
237preProcOpts (x:xs) = x : preProcOpts xs
238preProcOpts [] = []
240parseCodegen :: String -> Codegen
241parseCodegen "bytecode" = Bytecode
242parseCodegen cg = Via IBCFormat (map toLower cg)
244parseLogCats :: Monad m => String -> m [LogCat]
245parseLogCats s =
246 case lastMay (readP_to_S doParse s) of
247 Just (xs, _) -> return xs
248 _ -> fail "Incorrect categories specified"
249 where
250 doParse :: ReadP [LogCat]
251 doParse = do
252 cs <- sepBy1 parseLogCat (char ':')
253 eof
254 return (concat cs)
256 parseLogCat :: ReadP [LogCat]
257 parseLogCat = (string (strLogCat IParse) *> return parserCats)
258 <|> (string (strLogCat IElab) *> return elabCats)
259 <|> (string (strLogCat ICodeGen) *> return codegenCats)
260 <|> (string (strLogCat ICoverage) *> return [ICoverage])
261 <|> (string (strLogCat IIBC) *> return [IIBC])
262 <|> (string (strLogCat IErasure) *> return [IErasure])
263 <|> parseLogCatBad
265 parseLogCatBad :: ReadP [LogCat]
266 parseLogCatBad = do
267 s <- look
268 fail $ "Category: " ++ s ++ " is not recognised."
270parseConsoleWidth :: Monad m => String -> m ConsoleWidth
271parseConsoleWidth "auto" = return AutomaticWidth
272parseConsoleWidth "infinite" = return InfinitelyWide
273parseConsoleWidth s =
274 case lastMay (readP_to_S integerReader s) of
275 Just (r, _) -> return $ ColsWide r
276 _ -> fail $ "Cannot parse: " ++ s
278integerReader :: ReadP Int
279integerReader = do
280 digits <- many1 $ satisfy isDigit
281 return $ read digits