@@ -185,27 +185,28 @@ quitMessage = "See ya!"
186-- Haskeline completions
186-- Haskeline completions
188−data CompletionContext = Command String | FilePath | Module | Identifier | Fixed [String] | Multiple [CompletionContext]
188+data CompletionContext = Command String | FilePath String | Module | Identifier
189+ | Type | Fixed [String] | Multiple [CompletionContext]
189 deriving (Show)
190 deriving (Show)
192-- Decide what kind of completion we need based on input.
193-- Decide what kind of completion we need based on input.
193−completionContext :: String -> Maybe CompletionContext
194+completionContext :: String -> String -> Maybe CompletionContext
194−completionContext cmd@"" = Just $ Multiple [Command cmd, Identifier]
195+completionContext cmd@"" _ = Just $ Multiple [Command cmd, Identifier]
195−completionContext cmd@(':' : _ )
196+completionContext cmd@(':' : _ ) _
196 | cmd `elem` C.commands || cmd == ":" = Just $ Command cmd
197 | cmd `elem` C.commands || cmd == ":" = Just $ Command cmd
197−completionContext (':' : c : _) = case c of
198+completionContext (':' : c : _) word = case c of
198 'i' -> Just Module
199 'i' -> Just Module
199 'b' -> Just Module
200 'b' -> Just Module
200− 'm' -> Just FilePath
201+ 'm' -> Just $ FilePath word
201 'q' -> Nothing
202 'q' -> Nothing
202 'r' -> Nothing
203 'r' -> Nothing
203 '?' -> Nothing
204 '?' -> Nothing
204 's' -> Just $ Fixed ["import", "loaded"]
205 's' -> Just $ Fixed ["import", "loaded"]
205 't' -> Just Identifier
206 't' -> Just Identifier
206− 'k' -> Just Identifier
207+ 'k' -> Just Type
207 _ -> Nothing
208 _ -> Nothing
208−completionContext _ = Just Identifier
209+completionContext _ _ = Just Identifier
211-- Loads module, function, and file completions.
212-- Loads module, function, and file completions.
@@ -215,22 +216,23 @@ completion = completeWordWithPrev Nothing " \t\n\r" findCompletions
216 findCompletions :: String -> String -> StateT PSCiState IO [Completion]
217 findCompletions :: String -> String -> StateT PSCiState IO [Completion]
217 findCompletions prev word = do
218 findCompletions prev word = do
218− let ctx = completionContext $ (dropWhile isSpace (reverse prev)) ++ word
219+ let ctx = completionContext ((dropWhile isSpace (reverse prev)) ++ word) word
219 completions <- case ctx of
220 completions <- case ctx of
220 Nothing -> return []
221 Nothing -> return []
221 (Just c) -> (mapMaybe $ either (\cand -> if word `isPrefixOf` cand
222 (Just c) -> (mapMaybe $ either (\cand -> if word `isPrefixOf` cand
222 then Just $ simpleCompletion cand
223 then Just $ simpleCompletion cand
223 else Nothing) Just)
224 else Nothing) Just)
224− <$> getCompletion c word
225+ <$> getCompletion c
225 return $ sortBy sorter completions
226 return $ sortBy sorter completions
227− getCompletion :: CompletionContext -> String -> StateT PSCiState IO [Either String Completion]
228+ getCompletion :: CompletionContext -> StateT PSCiState IO [Either String Completion]
228− getCompletion (Command s) _ = return $ (map Left) $ nub $ filter (isPrefixOf s) C.commands
229+ getCompletion (Command s) = return $ (map Left) $ nub $ filter (isPrefixOf s) C.commands
229− getCompletion FilePath f = (map Right) <$> listFiles f
230+ getCompletion (FilePath f) = (map Right) <$> listFiles f
230− getCompletion Module _ = (map Left) <$> getModuleNames
231+ getCompletion Module = (map Left) <$> getModuleNames
231− getCompletion Identifier _ = (map Left) <$> getIdentNames
232+ getCompletion Identifier = (map Left) <$> ((++) <$> getIdentNames <*> getDctorNames)
233+ getCompletion Type = (map Left) <$> getTypeNames
232− getCompletion (Fixed list) _ = return $ (map Left) list
234+ getCompletion (Fixed list) = return $ (map Left) list
233− getCompletion (Multiple contexts) f = concat <$> mapM (flip getCompletion $ f) contexts
235+ getCompletion (Multiple contexts) = concat <$> mapM getCompletion contexts
235 getLoadedModules :: StateT PSCiState IO [P.Module]
237 getLoadedModules :: StateT PSCiState IO [P.Module]
236 getLoadedModules = map snd . psciLoadedModules <$> get
238 getLoadedModules = map snd . psciLoadedModules <$> get
@@ -238,30 +240,60 @@ completion = completeWordWithPrev Nothing " \t\n\r" findCompletions
238 getModuleNames :: StateT PSCiState IO [String]
240 getModuleNames :: StateT PSCiState IO [String]
239 getModuleNames = moduleNames <$> getLoadedModules
241 getModuleNames = moduleNames <$> getLoadedModules
243+ mapLoadedModulesAndQualify :: (Show a) => (P.Module -> [a]) -> StateT PSCiState IO [String]
244+ mapLoadedModulesAndQualify f = do
245+ ms <- getLoadedModules
246+ q <- sequence [qualifyIfNeeded m (f m) | m <- ms]
241 getIdentNames :: StateT PSCiState IO [String]
249 getIdentNames :: StateT PSCiState IO [String]
242− getIdentNames = identNames <$> getLoadedModules
250+ getIdentNames = mapLoadedModulesAndQualify identNames
252+ getDctorNames :: StateT PSCiState IO [String]
253+ getDctorNames = mapLoadedModulesAndQualify dctorNames
255+ getTypeNames :: StateT PSCiState IO [String]
256+ getTypeNames = mapLoadedModulesAndQualify typeDecls
258+ qualifyIfNeeded :: (Show a) => P.Module -> [a] -> StateT PSCiState IO [String]
259+ qualifyIfNeeded m decls = do
260+ let name = P.getModuleName m
261+ imported <- psciImportedModuleNames <$> get
262+ let qualified = map (P.Qualified $ Just name) decls
263+ if name `elem` imported then
264+ return $ map show $ qualified ++ (map (P.Qualified Nothing) decls)
266+ return $ map show qualified
268+ typeDecls :: P.Module -> [N.ProperName]
269+ typeDecls m = mapMaybe getTypeName $ filter P.isDataDecl (P.exportedDeclarations m)
270+ where getTypeName :: P.Declaration -> Maybe N.ProperName
271+ getTypeName (P.TypeSynonymDeclaration name _ _) = Just name
272+ getTypeName (P.DataDeclaration _ name _ _) = Just name
273+ getTypeName (P.PositionedDeclaration _ d) = getTypeName d
274+ getTypeName _ = Nothing
276+ identNames :: P.Module -> [N.Ident]
277+ identNames (P.Module _ ds exports) = nub [ ident | ident <- mapMaybe (getDeclName exports) ds ]
244− getDeclName :: Maybe [P.DeclarationRef] -> P.Declaration -> Maybe P.Ident
278+ where getDeclName :: Maybe [P.DeclarationRef] -> P.Declaration -> Maybe P.Ident
245− getDeclName exts (P.ValueDeclaration ident _ _ _) | isExported ident exts = Just ident
279+ getDeclName exts decl@(P.ValueDeclaration ident _ _ _) | P.isExported exts decl = Just ident
246− getDeclName exts (P.ExternDeclaration _ ident _ _) | isExported ident exts = Just ident
280+ getDeclName exts decl@(P.ExternDeclaration _ ident _ _) | P.isExported exts decl = Just ident
247− getDeclName exts (P.PositionedDeclaration _ d) = getDeclName exts d
281+ getDeclName exts (P.PositionedDeclaration _ d) = getDeclName exts d
248− getDeclName _ _ = Nothing
282+ getDeclName _ _ = Nothing
250− isExported :: N.Ident -> Maybe [P.DeclarationRef] -> Bool
284+ dctorNames :: P.Module -> [N.ProperName]
251− isExported ident = maybe True (any exports)
285+ dctorNames m = nub $ concat $ map (P.exportedDctors m) dnames
252− where
286+ where getDataDeclName :: P.Declaration -> Maybe N.ProperName
253− exports :: P.DeclarationRef -> Bool
287+ getDataDeclName (P.DataDeclaration _ name _ _) = Just name
254− exports (P.ValueRef ident') = ident == ident'
288+ getDataDeclName (P.PositionedDeclaration _ d) = getDataDeclName d
255− exports (P.PositionedDeclarationRef _ r) = exports r
289+ getDataDeclName _ = Nothing
256− exports _ = False
290+
257−
291+ dnames :: [N.ProperName]
258− identNames :: [P.Module] -> [String]
292+ dnames = (mapMaybe getDataDeclName onlyDataDecls)
259− identNames ms = nub [ show qual
293+
260− | P.Module moduleName ds exts <- ms
294+ onlyDataDecls :: [P.Declaration]
261− , ident <- mapMaybe (getDeclName exts) ds
295+ onlyDataDecls = (filter P.isDataDecl (P.exportedDeclarations m))
262− , qual <- [ P.Qualified Nothing ident
296+
263− , P.Qualified (Just moduleName) ident]
265 moduleNames :: [P.Module] -> [String]
297 moduleNames :: [P.Module] -> [String]
266 moduleNames ms = nub [show moduleName | P.Module moduleName _ _ <- ms]
298 moduleNames ms = nub [show moduleName | P.Module moduleName _ _ <- ms]
@@ -601,7 +633,6 @@ main = execParser opts >>= loop
601 infoModList = fullDesc <> headerInfo <> footerInfo
633 infoModList = fullDesc <> headerInfo <> footerInfo
602 headerInfo = header "psci - Interactive mode for PureScript"
634 headerInfo = header "psci - Interactive mode for PureScript"
603 footerInfo = footer $ "psci " ++ showVersion Paths.version
635 footerInfo = footer $ "psci " ++ showVersion Paths.version
605 version :: Parser (a -> a)
637 version :: Parser (a -> a)
606 version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> Opts.help "Show the version number" <> hidden
638 version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> Opts.help "Show the version number" <> hidden