1-- | Support for command-line completion at the REPL and in the prover
2module Idris.Completion (replCompletion, proverCompletion) where
4import Core.Evaluate (ctxtAlist)
6import Core.CoreParser (opChars)
8import Idris.AbsSyntaxTree
11import Control.Monad.State.Strict
16import System.Console.Haskeline
22commands = concatMap fst3 help
24-- | A specification of the arguments that tactics can take
25data TacticArg = NameTArg -- ^ Names: n1, n2, n3, ... n
29-- | A list of available tactics and their argument requirements
30tacticArgs :: [(String, Maybe TacticArg)]
31tacticArgs = [ ("intro", Nothing)
33 , ("refine", Just ExprTArg)
34 , ("rewrite", Just ExprTArg)
35 , ("let", Nothing) -- FIXME syntax for let
36 , ("focus", Just ExprTArg)
37 , ("exact", Just ExprTArg)
38 , ("applyTactic", Just ExprTArg)
39 , ("reflect", Just ExprTArg)
40 , ("fill", Just ExprTArg)
41 , ("try", Just AltsTArg)
42 ] ++ map (\x -> (x, Nothing)) [
43 "intro", "intros", "compute", "trivial", "solve", "attack",
44 "state", "term", "undo", "qed", "abandon", ":q"
46tactics = map fst tacticArgs
48-- | Convert a name into a string usable for completion. Filters out names
49-- that users probably don't want to see.
50nameString :: Name -> Maybe String
51nameString (UN ('@':_)) = Nothing
52nameString (UN ('#':_)) = Nothing
53nameString (UN n) = Just n
54nameString (NS n _) = nameString n
57-- FIXME: Respect module imports
58-- | Get the user-visible names from the current interpreter state.
59names :: Idris [String]
62 return $ nub $ mapMaybe (nameString . fst) $ ctxtAlist ctxt
64metavars :: Idris [String]
66 return . map (show . nsroot) $ idris_metavars i \\ primDefs
69modules :: Idris [String]
71 return $ map show $ imported i
75completeWith :: [String] -> String -> [Completion]
76completeWith ns n = if uniqueExists
77 then [simpleCompletion n]
78 else map simpleCompletion prefixMatches
79 where prefixMatches = filter (isPrefixOf n) ns
80 uniqueExists = [n] == prefixMatches
82completeName :: [String] -> String -> Idris [Completion]
83completeName extra n = do ns <- names
84 return $ completeWith (extra ++ ns) n
86completeExpr :: [String] -> CompletionFunc Idris
87completeExpr extra = completeWord Nothing (" \t(){}:" ++ opChars) (completeName extra)
89completeMetaVar :: CompletionFunc Idris
90completeMetaVar = completeWord Nothing (" \t(){}:" ++ opChars) completeM
91 where completeM m = do mvs <- metavars
92 return $ completeWith mvs m
94completeOption :: CompletionFunc Idris
95completeOption = completeWord Nothing " \t" completeOpt
96 where completeOpt = return . (completeWith ["errorcontext", "showimplicits"])
98isWhitespace :: Char -> Bool
99isWhitespace = (flip elem) " \t\n"
101lookupInHelp :: String -> Maybe CmdArg
102lookupInHelp cmd = lookupInHelp' cmd help
103 where lookupInHelp' cmd ((cmds, arg, _):xs) | elem cmd cmds = Just arg
104 | otherwise = lookupInHelp' cmd xs
105 lookupInHelp' cmd [] = Nothing
107-- | Get the completion function for a particular command
108completeCmd :: String -> CompletionFunc Idris
109completeCmd cmd (prev, next) = fromMaybe completeCmdName $ fmap completeArg $ lookupInHelp cmd
110 where completeArg FileArg = completeFilename (prev, next)
111 completeArg NameArg = completeExpr [] (prev, next) -- FIXME only complete one name
112 completeArg OptionArg = completeOption (prev, next)
113 completeArg ModuleArg = noCompletion (prev, next) -- FIXME do later
114 completeArg ExprArg = completeExpr [] (prev, next)
115 completeArg MetaVarArg = completeMetaVar (prev, next) -- FIXME only complete one name
116 completeArg NoArg = noCompletion (prev, next)
117 completeCmdName = return $ ("", completeWith commands cmd)
119-- | Complete REPL commands and defined identifiers
120replCompletion :: CompletionFunc Idris
121replCompletion (prev, next) = case firstWord of
122 ':':cmdName -> completeCmd (':':cmdName) (prev, next)
123 _ -> completeExpr [] (prev, next)
124 where firstWord = fst $ break isWhitespace $ dropWhile isWhitespace $ reverse prev
127completeTactic :: [String] -> String -> CompletionFunc Idris
128completeTactic as tac (prev, next) = fromMaybe completeTacName $ fmap completeArg $ lookup tac tacticArgs
129 where completeTacName = return $ ("", completeWith tactics tac)
130 completeArg Nothing = noCompletion (prev, next)
131 completeArg (Just NameTArg) = noCompletion (prev, next) -- this is for binding new names!
132 completeArg (Just ExprTArg) = completeExpr as (prev, next)
133 completeArg (Just AltsTArg) = noCompletion (prev, next) -- TODO
135-- | Complete tactics and their arguments
136proverCompletion :: [String] -- ^ The names of current local assumptions
137 -> CompletionFunc Idris
138proverCompletion assumptions (prev, next) = completeTactic assumptions firstWord (prev, next)
139 where firstWord = fst $ break isWhitespace $ dropWhile isWhitespace $ reverse prev
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