2module Idris.REPLParser (parseCmd, help, allHelp) where
4import System.FilePath ((</>))
5import System.Console.ANSI (Color(..))
11import qualified Idris.Parser as P
13import Control.Applicative
14import Control.Monad.State.Strict
16import Text.Parser.Combinators
17import Text.Parser.Char(anyChar,oneOf)
18import Text.Trifecta(Result, parseString)
19import Text.Trifecta.Delta
23import Data.List.Split(splitOn)
24import Data.Char(isSpace, toLower)
25import qualified Data.ByteString.UTF8 as UTF8
27parseCmd :: IState -> String -> String -> Result (Either String Command)
28parseCmd i inputname = P.runparser pCmd i inputname . dropWhile isSpace
30type CommandTable = [ ( [String], CmdArg, String
31 , String -> P.IdrisParser (Either String Command) ) ]
33help :: [([String], CmdArg, String)]
34help = (["<expr>"], NoArg, "Evaluate an expression") :
35 [ (map (':' :) names, args, text) | (names, args, text, _) <- parserCommandsForHelp ]
37allHelp :: [([String], CmdArg, String)]
38allHelp = [ (map (':' :) names, args, text)
39 | (names, args, text, _) <- parserCommandsForHelp ++ parserCommands ]
41parserCommandsForHelp :: CommandTable
42parserCommandsForHelp =
43 [ exprArgCmd ["t", "type"] Check "Check the type of an expression"
44 , nameArgCmd ["miss", "missing"] Missing "Show missing clauses"
45 , (["doc"], NameArg, "Show internal documentation", cmd_doc)
46 , (["mkdoc"], NamespaceArg, "Generate IdrisDoc for namespace(s) and dependencies"
47 , genArg "namespace" (many anyChar) MakeDoc)
48 , (["apropos"], SeqArgs (OptionalArg PkgArgs) NameArg, " Search names, types, and documentation"
50 , (["s", "search"], SeqArgs (OptionalArg PkgArgs) ExprArg
51 , " Search for values by type", cmd_search)
52 , nameArgCmd ["wc", "whocalls"] WhoCalls "List the callers of some name"
53 , nameArgCmd ["cw", "callswho"] CallsWho "List the callees of some name"
54 , nameArgCmd ["total"] TotCheck "Check the totality of a name"
55 , noArgCmd ["r", "reload"] Reload "Reload current file"
56 , (["l", "load"], FileArg, "Load a new file"
57 , strArg (\f -> Load f Nothing))
58 , (["cd"], FileArg, "Change working directory"
59 , strArg ChangeDirectory)
60 , (["module"], ModuleArg, "Import an extra module", moduleArg ModImport) -- NOTE: dragons
61 , noArgCmd ["e", "edit"] Edit "Edit current file using $EDITOR or $VISUAL"
62 , noArgCmd ["m", "metavars"] Metavars "Show remaining proof obligations (metavariables)"
63 , (["p", "prove"], MetaVarArg, "Prove a metavariable"
65 , (["a", "addproof"], NameArg, "Add proof to source file", cmd_addproof)
66 , (["rmproof"], NameArg, "Remove proof from proof stack"
68 , (["showproof"], NameArg, "Show proof"
70 , noArgCmd ["proofs"] Proofs "Show available proofs"
71 , exprArgCmd ["x"] ExecVal "Execute IO actions resulting from an expression using the interpreter"
72 , (["c", "compile"], FileArg, "Compile to an executable [codegen] <filename>", cmd_compile)
73 , noArgCmd ["exec", "execute"] Execute "Compile to an executable and run"
74 , (["dynamic"], FileArg, "Dynamically load a C library (similar to %dynamic)", cmd_dynamic)
75 , (["dynamic"], NoArg, "List dynamically loaded C libraries", cmd_dynamic)
76 , noArgCmd ["?", "h", "help"] Help "Display this help text"
77 , optArgCmd ["set"] SetOpt "Set an option (errorcontext, showimplicits)"
78 , optArgCmd ["unset"] UnsetOpt "Unset an option"
79 , (["color", "colour"], ColourArg
80 , "Turn REPL colours on or off; set a specific colour"
82 , (["consolewidth"], ConsoleWidthArg, "Set the width of the console", cmd_consolewidth)
83 , noArgCmd ["q", "quit"] Quit "Exit the Idris system"
84 , noArgCmd ["w", "warranty"] Warranty "Displays warranty information"
85 , (["let"], ManyArgs DeclArg
86 , "Evaluate a declaration, such as a function definition, instance implementation, or fixity declaration"
88 , (["unlet", "undefine"], ManyArgs NameArg
89 , "Remove the listed repl definitions, or all repl definitions if no names given"
91 , nameArgCmd ["printdef"] PrintDef "Show the definition of a function"
92 , (["pp", "pprint"], (SeqArgs OptionArg (SeqArgs NumberArg NameArg))
93 , "Pretty prints an Idris function in either LaTeX or HTML and for a specified width."
98 [ noArgCmd ["u", "universes"] Universes "Display universe constraints"
99 , noArgCmd ["errorhandlers"] ListErrorHandlers "List registered error handlers"
101 , nameArgCmd ["d", "def"] Defn "Display a name's internal definitions"
102 , nameArgCmd ["transinfo"] TransformInfo "Show relevant transformation rules for a name"
103 , nameArgCmd ["di", "dbginfo"] DebugInfo "Show debugging information for a name"
105 , exprArgCmd ["patt"] Pattelab "(Debugging) Elaborate pattern expression"
106 , exprArgCmd ["spec"] Spec "?"
107 , exprArgCmd ["hnf"] HNF "?"
108 , exprArgCmd ["inline"] TestInline "?"
109 , proofArgCmd ["cs", "casesplit"] CaseSplitAt
110 ":cs <line> <name> splits the pattern variable on the line"
111 , proofArgCmd ["apc", "addproofclause"] AddProofClauseFrom
112 ":apc <line> <name> adds a pattern-matching proof clause to name on line"
113 , proofArgCmd ["ac", "addclause"] AddClauseFrom
114 ":ac <line> <name> adds a clause for the definition of the name on the line"
115 , proofArgCmd ["am", "addmissing"] AddMissing
116 ":am <line> <name> adds all missing pattern matches for the name on the line"
117 , proofArgCmd ["mw", "makewith"] MakeWith
118 ":mw <line> <name> adds a with clause for the definition of the name on the line"
119 , proofArgCmd ["ml", "makelemma"] MakeLemma "?"
120 , (["log"], NumberArg, "Set logging verbosity level", cmd_log)
121 , (["lto", "loadto"], SeqArgs NumberArg FileArg
122 , "Load file up to line number", cmd_loadto)
123 , (["ps", "proofsearch"], NoArg
124 , ":ps <line> <name> <names> does proof search for name on line, with names as hints"
126 , (["ref", "refine"], NoArg
127 , ":ref <line> <name> <name'> attempts to partially solve name on line, with name' as hint, introducing metavariables for arguments that aren't inferrable"
129 , (["debugunify"], SeqArgs ExprArg ExprArg
130 , "(Debugging) Try to unify two expressions", const $ do
131 l <- P.simpleExpr defaultSyntax
132 r <- P.simpleExpr defaultSyntax
134 return (Right (DebugUnify l r))
138noArgCmd names command doc =
139 (names, NoArg, doc, noArgs command)
140nameArgCmd names command doc =
141 (names, NameArg, doc, fnNameArg command)
142exprArgCmd names command doc =
143 (names, ExprArg, doc, exprArg command)
144metavarArgCmd names command doc =
145 (names, MetaVarArg, doc, fnNameArg command)
146optArgCmd names command doc =
147 (names, OptionArg, doc, optArg command)
148proofArgCmd names command doc =
149 (names, NoArg, doc, proofArg command)
151pCmd :: P.IdrisParser (Either String Command)
152pCmd = choice [ do c <- cmd names; parser c
153 | (names, _, _, parser) <- parserCommandsForHelp ++ parserCommands ]
157 where nop = do eof; return (Right NOP)
158 eval = exprArg Eval ""
162 let cmd' = takeWhile (/=' ') cmd
163 return (Left $ "Unrecognized command: " ++ cmd')
165cmd :: [String] -> P.IdrisParser String
170 where docmd [] = fail "Could not parse command"
171 docmd (x:xs) = try (P.reserved x >> return x) <|> docmd xs
173 sorted_xs = sortBy (\x y -> compare (length y) (length x)) xs
176noArgs :: Command -> String -> P.IdrisParser (Either String Command)
182 let failure = return (Left $ ":" ++ name ++ " takes no arguments")
184 emptyArgs <|> failure
186exprArg :: (PTerm -> Command) -> String -> P.IdrisParser (Either String Command)
190 return $ Left ("Usage is :" ++ name ++ " <expression>")
193 t <- P.fullExpr defaultSyntax
194 return $ Right (cmd t)
195 try noArg <|> properArg
199genArg :: String -> P.IdrisParser a -> (a -> Command)
200 -> String -> P.IdrisParser (Either String Command)
201genArg argName argParser cmd name = do
202 let emptyArgs = do eof; failure
203 oneArg = do arg <- argParser
205 return (Right (cmd arg))
206 try emptyArgs <|> oneArg <|> failure
208 failure = return $ Left ("Usage is :" ++ name ++ " <" ++ argName ++ ">")
210nameArg, fnNameArg :: (Name -> Command) -> String -> P.IdrisParser (Either String Command)
211nameArg = genArg "name" P.name
212fnNameArg = genArg "functionname" P.fnName
214strArg :: (String -> Command) -> String -> P.IdrisParser (Either String Command)
215strArg = genArg "string" (many anyChar)
217moduleArg :: (FilePath -> Command) -> String -> P.IdrisParser (Either String Command)
218moduleArg = genArg "module" (fmap toPath P.identifier)
220 toPath n = foldl1' (</>) $ splitOn "." n
222optArg :: (Opt -> Command) -> String -> P.IdrisParser (Either String Command)
226 return $ Left ("Usage is :" ++ name ++ " <option>")
232 return (Right (cmd o))
234 let failure = return $ Left "Unrecognized setting"
236 try emptyArgs <|> oneArg <|> failure
239 pOption :: P.IdrisParser Opt
240 pOption = do discard (P.symbol "errorcontext"); return ErrContext
241 <|> do discard (P.symbol "showimplicits"); return ShowImpl
242 <|> do discard (P.symbol "originalerrors"); return ShowOrigErr
243 <|> do discard (P.symbol "autosolve"); return AutoSolve
244 <|> do discard (P.symbol "nobanner") ; return NoBanner
245 <|> do discard (P.symbol "warnreach"); return WarnReach
247proofArg :: (Bool -> Int -> Name -> Command) -> String -> P.IdrisParser (Either String Command)
248proofArg cmd name = do
249 upd <- option False $ do
254 return (Right (cmd upd (fromInteger l) n))
256cmd_doc :: String -> P.IdrisParser (Either String Command)
261 return $ Right (DocStr (Right c) FullDocs)
263 let fnName = fnNameArg (\n -> DocStr (Left n) FullDocs) name
265 try constant <|> fnName
267cmd_consolewidth :: String -> P.IdrisParser (Either String Command)
268cmd_consolewidth name = do
270 return (Right (SetConsoleWidth w))
273 pConsoleWidth :: P.IdrisParser ConsoleWidth
274 pConsoleWidth = do discard (P.symbol "auto"); return AutomaticWidth
275 <|> do discard (P.symbol "infinite"); return InfinitelyWide
276 <|> do n <- fmap fromInteger P.natural; return (ColsWide n)
278cmd_dynamic :: String -> P.IdrisParser (Either String Command)
280 let emptyArgs = noArgs ListDynamic name
282 let oneArg = do l <- many anyChar
283 return $ Right (DynamicLink l)
285 let failure = return $ Left $ "Usage is :" ++ name ++ " [<library>]"
287 try emptyArgs <|> try oneArg <|> failure
289cmd_pprint :: String -> P.IdrisParser (Either String Command)
293 n <- fmap fromInteger P.natural
295 t <- P.fullExpr defaultSyntax
296 return (Right (PPrint fmt n t))
299 ppFormat :: P.IdrisParser OutputFmt
300 ppFormat = (discard (P.symbol "html") >> return HTMLOutput)
301 <|> (discard (P.symbol "latex") >> return LaTeXOutput)
305cmd_compile :: String -> P.IdrisParser (Either String Command)
307 let defaultCodegen = Via "c"
309 let codegenOption :: P.IdrisParser Codegen
311 let bytecodeCodegen = discard (P.symbol "bytecode") *> return Bytecode
312 viaCodegen = do x <- P.identifier
313 return (Via (map toLower x))
314 bytecodeCodegen <|> viaCodegen
320 return $ Right (Compile defaultCodegen f)
324 codegen <- codegenOption
327 return $ Right (Compile codegen f)
329 let failure = return $ Left $ "Usage is :" ++ name ++ " [<codegen>] <filename>"
330 try hasTwoArgs <|> try hasOneArg <|> failure
332cmd_addproof :: String -> P.IdrisParser (Either String Command)
333cmd_addproof name = do
334 n <- option Nothing $ do
338 return (Right (AddProof n))
340cmd_log :: String -> P.IdrisParser (Either String Command)
344 return (Right (LogLvl (fromIntegral i)))
346cmd_let :: String -> P.IdrisParser (Either String Command)
348 defn <- concat <$> many (P.decl defaultSyntax)
349 return (Right (NewDefn defn))
351cmd_unlet :: String -> P.IdrisParser (Either String Command)
352cmd_unlet name = (Right . Undefine) `fmap` many P.name
354cmd_loadto :: String -> P.IdrisParser (Either String Command)
358 return (Right (Load f (Just (fromInteger toline))))
360cmd_colour :: String -> P.IdrisParser (Either String Command)
361cmd_colour name = fmap Right pSetColourCmd
364 colours :: [(String, Maybe Color)]
365 colours = [ ("black", Just Black)
367 , ("green", Just Green)
368 , ("yellow", Just Yellow)
369 , ("blue", Just Blue)
370 , ("magenta", Just Magenta)
371 , ("cyan", Just Cyan)
372 , ("white", Just White)
373 , ("default", Nothing)
376 pSetColourCmd :: P.IdrisParser Command
377 pSetColourCmd = (do c <- pColourType
378 let defaultColour = IdrisColour Nothing True False False False
379 opts <- sepBy pColourMod (P.whiteSpace)
380 let colour = foldr ($) defaultColour $ reverse opts
381 return $ SetColour c colour)
382 <|> try (P.symbol "on" >> return ColourOn)
383 <|> try (P.symbol "off" >> return ColourOff)
385 pColour :: P.IdrisParser (Maybe Color)
386 pColour = doColour colours
387 where doColour [] = fail "Unknown colour"
388 doColour ((s, c):cs) = (try (P.symbol s) >> return c) <|> doColour cs
390 pColourMod :: P.IdrisParser (IdrisColour -> IdrisColour)
391 pColourMod = try (P.symbol "vivid" >> return doVivid)
392 <|> try (P.symbol "dull" >> return doDull)
393 <|> try (P.symbol "underline" >> return doUnderline)
394 <|> try (P.symbol "nounderline" >> return doNoUnderline)
395 <|> try (P.symbol "bold" >> return doBold)
396 <|> try (P.symbol "nobold" >> return doNoBold)
397 <|> try (P.symbol "italic" >> return doItalic)
398 <|> try (P.symbol "noitalic" >> return doNoItalic)
399 <|> try (pColour >>= return . doSetColour)
400 where doVivid i = i { vivid = True }
401 doDull i = i { vivid = False }
402 doUnderline i = i { underline = True }
403 doNoUnderline i = i { underline = False }
404 doBold i = i { bold = True }
405 doNoBold i = i { bold = False }
406 doItalic i = i { italic = True }
407 doNoItalic i = i { italic = False }
408 doSetColour c i = i { colour = c }
410 -- | Generate the colour type names using the default Show instance.
411 colourTypes :: [(String, ColourType)]
412 colourTypes = map (\x -> ((map toLower . reverse . drop 6 . reverse . show) x, x)) $
413 enumFromTo minBound maxBound
415 pColourType :: P.IdrisParser ColourType
416 pColourType = doColourType colourTypes
417 where doColourType [] = fail $ "Unknown colour category. Options: " ++
418 (concat . intersperse ", " . map fst) colourTypes
419 doColourType ((s,ct):cts) = (try (P.symbol s) >> return ct) <|> doColourType cts
421idChar = oneOf (['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ ['_'])
423cmd_apropos :: String -> P.IdrisParser (Either String Command)
424cmd_apropos = packageBasedCmd (some idChar) Apropos
426packageBasedCmd :: P.IdrisParser a -> ([String] -> a -> Command)
427 -> String -> P.IdrisParser (Either String Command)
428packageBasedCmd valParser cmd name = do
429 pkgs <- option [] . try $ do
431 pks <- sepBy (some idChar) (P.lchar ',')
435 return (Right (cmd pkgs val))
437cmd_search :: String -> P.IdrisParser (Either String Command)
438cmd_search = packageBasedCmd
439 (P.typeExpr (defaultSyntax { implicitAllowed = True })) Search
441cmd_proofsearch :: String -> P.IdrisParser (Either String Command)
442cmd_proofsearch name = do
443 upd <- option False (do P.lchar '!'; return True)
444 l <- P.natural; n <- P.name;
445 hints <- many P.fnName
446 return (Right (DoProofSearch upd True (fromInteger l) n hints))
448cmd_refine :: String -> P.IdrisParser (Either String Command)
450 upd <- option False (do P.lchar '!'; return True)
451 l <- P.natural; n <- P.name;
453 return (Right (DoProofSearch upd False (fromInteger l) n [hint]))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list