1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2005-2006
8 -----------------------------------------------------------------------------
10 module InteractiveUI ( interactiveUI, ghciWelcomeMsg ) where
12 #include "HsVersions.h"
20 import GHC ( Session, LoadHowMuch(..), Target(..), TargetId(..),
21 Module, ModuleName, TyThing(..), Phase,
22 BreakIndex, SrcSpan, Resume, SingleStep, Id )
32 import HscTypes ( implicitTyThings )
33 import qualified RdrName ( getGRE_NameQualifier_maybes ) -- should this come via GHC?
34 import Outputable hiding (printForUser)
35 import Module -- for ModuleEnv
39 -- Other random utilities
41 import BasicTypes hiding (isTopLevel)
42 import Panic hiding (showException)
48 import Maybes ( orElse )
51 #ifndef mingw32_HOST_OS
52 import System.Posix hiding (getEnv)
54 import GHC.ConsoleHandler ( flushConsole )
55 import System.Win32 ( setConsoleCP, setConsoleOutputCP )
56 import qualified System.Win32
60 import Control.Concurrent ( yield ) -- Used in readline loop
61 import System.Console.Readline as Readline
66 import Control.Exception as Exception
67 -- import Control.Concurrent
69 import qualified Data.ByteString.Char8 as BS
73 import System.Environment
74 import System.Exit ( exitWith, ExitCode(..) )
75 import System.Directory
77 import System.IO.Error as IO
78 import System.IO.Unsafe
82 import Control.Monad as Monad
85 import Foreign.StablePtr ( newStablePtr )
86 import GHC.Exts ( unsafeCoerce# )
87 import GHC.IOBase ( IOErrorType(InvalidArgument) )
89 import Data.IORef ( IORef, readIORef, writeIORef )
92 import System.Posix.Internals ( setNonBlockingFD )
95 -----------------------------------------------------------------------------
97 ghciWelcomeMsg :: String
98 ghciWelcomeMsg = "GHCi, version " ++ cProjectVersion ++
99 ": http://www.haskell.org/ghc/ :? for help"
101 type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
103 cmdName :: Command -> String
104 cmdName (n,_,_,_) = n
106 macros_ref :: IORef [Command]
107 GLOBAL_VAR(macros_ref, [], [Command])
109 builtin_commands :: [Command]
111 -- Hugs users are accustomed to :e, so make sure it doesn't overlap
112 ("?", keepGoing help, False, completeNone),
113 ("add", keepGoingPaths addModule, False, completeFilename),
114 ("abandon", keepGoing abandonCmd, False, completeNone),
115 ("break", keepGoing breakCmd, False, completeIdentifier),
116 ("back", keepGoing backCmd, False, completeNone),
117 ("browse", keepGoing (browseCmd False), False, completeModule),
118 ("browse!", keepGoing (browseCmd True), False, completeModule),
119 ("cd", keepGoing changeDirectory, False, completeFilename),
120 ("check", keepGoing checkModule, False, completeHomeModule),
121 ("continue", keepGoing continueCmd, False, completeNone),
122 ("cmd", keepGoing cmdCmd, False, completeIdentifier),
123 ("ctags", keepGoing createCTagsFileCmd, False, completeFilename),
124 ("def", keepGoing (defineMacro False), False, completeIdentifier),
125 ("def!", keepGoing (defineMacro True), False, completeIdentifier),
126 ("delete", keepGoing deleteCmd, False, completeNone),
127 ("e", keepGoing editFile, False, completeFilename),
128 ("edit", keepGoing editFile, False, completeFilename),
129 ("etags", keepGoing createETagsFileCmd, False, completeFilename),
130 ("force", keepGoing forceCmd, False, completeIdentifier),
131 ("forward", keepGoing forwardCmd, False, completeNone),
132 ("help", keepGoing help, False, completeNone),
133 ("history", keepGoing historyCmd, False, completeNone),
134 ("info", keepGoing info, False, completeIdentifier),
135 ("kind", keepGoing kindOfType, False, completeIdentifier),
136 ("load", keepGoingPaths loadModule_, False, completeHomeModuleOrFile),
137 ("list", keepGoing listCmd, False, completeNone),
138 ("module", keepGoing setContext, False, completeModule),
139 ("main", keepGoing runMain, False, completeIdentifier),
140 ("print", keepGoing printCmd, False, completeIdentifier),
141 ("quit", quit, False, completeNone),
142 ("reload", keepGoing reloadModule, False, completeNone),
143 ("set", keepGoing setCmd, True, completeSetOptions),
144 ("show", keepGoing showCmd, False, completeNone),
145 ("sprint", keepGoing sprintCmd, False, completeIdentifier),
146 ("step", keepGoing stepCmd, False, completeIdentifier),
147 ("steplocal", keepGoing stepLocalCmd, False, completeIdentifier),
148 ("stepmodule",keepGoing stepModuleCmd, False, completeIdentifier),
149 ("type", keepGoing typeOfExpr, False, completeIdentifier),
150 ("trace", keepGoing traceCmd, False, completeIdentifier),
151 ("undef", keepGoing undefineMacro, False, completeMacro),
152 ("unset", keepGoing unsetOptions, True, completeSetOptions)
155 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
156 keepGoing a str = a str >> return False
158 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
159 keepGoingPaths a str = a (toArgs str) >> return False
161 shortHelpText :: String
162 shortHelpText = "use :? for help.\n"
166 " Commands available from the prompt:\n" ++
168 " <statement> evaluate/run <statement>\n" ++
169 " :{\\n ..lines.. \\n:}\\n multiline command\n" ++
170 " :add <filename> ... add module(s) to the current target set\n" ++
171 " :browse[!] [-s] [[*]<mod>] display the names defined by module <mod>\n" ++
172 " (!: more details; -s: sort; *: all top-level names)\n" ++
173 " :cd <dir> change directory to <dir>\n" ++
174 " :cmd <expr> run the commands returned by <expr>::IO String\n" ++
175 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
176 " :def <cmd> <expr> define a command :<cmd>\n" ++
177 " :edit <file> edit file\n" ++
178 " :edit edit last module\n" ++
179 " :etags [<file>] create tags file for Emacs (default: \"TAGS\")\n" ++
180 " :help, :? display this list of commands\n" ++
181 " :info [<name> ...] display information about the given names\n" ++
182 " :kind <type> show the kind of <type>\n" ++
183 " :load <filename> ... load module(s) and their dependents\n" ++
184 " :main [<arguments> ...] run the main function with the given arguments\n" ++
185 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
186 " :quit exit GHCi\n" ++
187 " :reload reload the current module set\n" ++
188 " :type <expr> show the type of <expr>\n" ++
189 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
190 " :!<command> run the shell command <command>\n" ++
192 " -- Commands for debugging:\n" ++
194 " :abandon at a breakpoint, abandon current computation\n" ++
195 " :back go back in the history (after :trace)\n" ++
196 " :break [<mod>] <l> [<col>] set a breakpoint at the specified location\n" ++
197 " :break <name> set a breakpoint on the specified function\n" ++
198 " :continue resume after a breakpoint\n" ++
199 " :delete <number> delete the specified breakpoint\n" ++
200 " :delete * delete all breakpoints\n" ++
201 " :force <expr> print <expr>, forcing unevaluated parts\n" ++
202 " :forward go forward in the history (after :back)\n" ++
203 " :history [<n>] show the last <n> items in the history (after :trace)\n" ++
204 " :print [<name> ...] prints a value without forcing its computation\n" ++
205 " :sprint [<name> ...] simplifed version of :print\n" ++
206 " :step single-step after stopping at a breakpoint\n"++
207 " :step <expr> single-step into <expr>\n"++
208 " :steplocal single-step restricted to the current top level decl.\n"++
209 " :stepmodule single-step restricted to the current module\n"++
210 " :trace trace after stopping at a breakpoint\n"++
211 " :trace <expr> trace into <expr> (remembers breakpoints for :history)\n"++
214 " -- Commands for changing settings:\n" ++
216 " :set <option> ... set options\n" ++
217 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
218 " :set prog <progname> set the value returned by System.getProgName\n" ++
219 " :set prompt <prompt> set the prompt used in GHCi\n" ++
220 " :set editor <cmd> set the command used for :edit\n" ++
221 " :set stop <cmd> set the command to run when a breakpoint is hit\n" ++
222 " :unset <option> ... unset options\n" ++
224 " Options for ':set' and ':unset':\n" ++
226 " +r revert top-level expressions after each evaluation\n" ++
227 " +s print timing/memory stats after each evaluation\n" ++
228 " +t print type after evaluation\n" ++
229 " -<flags> most GHC command line flags can also be set here\n" ++
230 " (eg. -v2, -fglasgow-exts, etc.)\n" ++
231 " for GHCi-specific flags, see User's Guide,\n"++
232 " Flag reference, Interactive-mode options\n" ++
234 " -- Commands for displaying information:\n" ++
236 " :show bindings show the current bindings made at the prompt\n" ++
237 " :show breaks show the active breakpoints\n" ++
238 " :show context show the breakpoint context\n" ++
239 " :show modules show the currently loaded modules\n" ++
240 " :show packages show the currently active package flags\n" ++
241 " :show languages show the currently active language flags\n" ++
242 " :show <setting> show anything that can be set with :set (e.g. args)\n" ++
245 findEditor :: IO String
250 win <- System.Win32.getWindowsDirectory
251 return (win `joinFileName` "notepad.exe")
256 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
257 interactiveUI session srcs maybe_expr = do
258 -- HACK! If we happen to get into an infinite loop (eg the user
259 -- types 'let x=x in x' at the prompt), then the thread will block
260 -- on a blackhole, and become unreachable during GC. The GC will
261 -- detect that it is unreachable and send it the NonTermination
262 -- exception. However, since the thread is unreachable, everything
263 -- it refers to might be finalized, including the standard Handles.
264 -- This sounds like a bug, but we don't have a good solution right
270 -- Initialise buffering for the *interpreted* I/O system
271 initInterpBuffering session
273 when (isNothing maybe_expr) $ do
274 -- Only for GHCi (not runghc and ghc -e):
276 -- Turn buffering off for the compiled program's stdout/stderr
278 -- Turn buffering off for GHCi's stdout
280 hSetBuffering stdout NoBuffering
281 -- We don't want the cmd line to buffer any input that might be
282 -- intended for the program, so unbuffer stdin.
283 hSetBuffering stdin NoBuffering
285 -- initial context is just the Prelude
286 prel_mod <- GHC.findModule session (GHC.mkModuleName "Prelude")
288 GHC.setContext session [] [prel_mod]
292 Readline.setAttemptedCompletionFunction (Just completeWord)
293 --Readline.parseAndBind "set show-all-if-ambiguous 1"
295 let symbols = "!#$%&*+/<=>?@\\^|-~"
296 specials = "(),;[]`{}"
298 word_break_chars = spaces ++ specials ++ symbols
300 Readline.setBasicWordBreakCharacters word_break_chars
301 Readline.setCompleterWordBreakCharacters word_break_chars
304 default_editor <- findEditor
306 startGHCi (runGHCi srcs maybe_expr)
307 GHCiState{ progname = "<interactive>",
311 editor = default_editor,
317 tickarrays = emptyModuleEnv,
322 Readline.resetTerminal Nothing
327 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
328 runGHCi paths maybe_expr = do
329 let read_dot_files = not opt_IgnoreDotGhci
331 when (read_dot_files) $ do
334 exists <- io (doesFileExist file)
336 dir_ok <- io (checkPerms ".")
337 file_ok <- io (checkPerms file)
338 when (dir_ok && file_ok) $ do
339 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
342 Right hdl -> runCommands (fileLoop hdl False)
344 when (read_dot_files) $ do
345 -- Read in $HOME/.ghci
346 either_dir <- io (IO.try getHomeDirectory)
350 cwd <- io (getCurrentDirectory)
351 when (dir /= cwd) $ do
352 let file = dir ++ "/.ghci"
353 ok <- io (checkPerms file)
355 either_hdl <- io (IO.try (openFile file ReadMode))
358 Right hdl -> runCommands (fileLoop hdl False)
360 -- Perform a :load for files given on the GHCi command line
361 -- When in -e mode, if the load fails then we want to stop
362 -- immediately rather than going on to evaluate the expression.
363 when (not (null paths)) $ do
364 ok <- ghciHandle (\e -> do showException e; return Failed) $
366 when (isJust maybe_expr && failed ok) $
367 io (exitWith (ExitFailure 1))
369 -- if verbosity is greater than 0, or we are connected to a
370 -- terminal, display the prompt in the interactive loop.
371 is_tty <- io (hIsTerminalDevice stdin)
372 dflags <- getDynFlags
373 let show_prompt = verbosity dflags > 0 || is_tty
378 #if defined(mingw32_HOST_OS)
379 -- The win32 Console API mutates the first character of
380 -- type-ahead when reading from it in a non-buffered manner. Work
381 -- around this by flushing the input buffer of type-ahead characters,
382 -- but only if stdin is available.
383 flushed <- io (IO.try (GHC.ConsoleHandler.flushConsole stdin))
385 Left err | isDoesNotExistError err -> return ()
386 | otherwise -> io (ioError err)
387 Right () -> return ()
389 -- initialise the console if necessary
392 -- enter the interactive loop
393 interactiveLoop is_tty show_prompt
395 -- just evaluate the expression we were given
400 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
403 interactiveLoop :: Bool -> Bool -> GHCi ()
404 interactiveLoop is_tty show_prompt =
405 -- Ignore ^C exceptions caught here
406 ghciHandleDyn (\e -> case e of
408 #if defined(mingw32_HOST_OS)
411 interactiveLoop is_tty show_prompt
412 _other -> return ()) $
414 ghciUnblock $ do -- unblock necessary if we recursed from the
415 -- exception handler above.
417 -- read commands from stdin
420 then runCommands readlineLoop
421 else runCommands (fileLoop stdin show_prompt)
423 runCommands (fileLoop stdin show_prompt)
427 -- NOTE: We only read .ghci files if they are owned by the current user,
428 -- and aren't world writable. Otherwise, we could be accidentally
429 -- running code planted by a malicious third party.
431 -- Furthermore, We only read ./.ghci if . is owned by the current user
432 -- and isn't writable by anyone else. I think this is sufficient: we
433 -- don't need to check .. and ../.. etc. because "." always refers to
434 -- the same directory while a process is running.
436 checkPerms :: String -> IO Bool
437 #ifdef mingw32_HOST_OS
442 Util.handle (\_ -> return False) $ do
443 st <- getFileStatus name
445 if fileOwner st /= me then do
446 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
449 let mode = fileMode st
450 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
451 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
453 putStrLn $ "*** WARNING: " ++ name ++
454 " is writable by someone else, IGNORING!"
459 fileLoop :: Handle -> Bool -> GHCi (Maybe String)
460 fileLoop hdl show_prompt = do
461 when show_prompt $ do
464 l <- io (IO.try (hGetLine hdl))
466 Left e | isEOFError e -> return Nothing
467 | InvalidArgument <- etype -> return Nothing
468 | otherwise -> io (ioError e)
469 where etype = ioeGetErrorType e
470 -- treat InvalidArgument in the same way as EOF:
471 -- this can happen if the user closed stdin, or
472 -- perhaps did getContents which closes stdin at
474 Right l -> return (Just l)
476 mkPrompt :: GHCi String
478 session <- getSession
479 (toplevs,exports) <- io (GHC.getContext session)
480 resumes <- io $ GHC.getResumeContext session
486 let ix = GHC.resumeHistoryIx r
488 then return (brackets (ppr (GHC.resumeSpan r)) <> space)
490 let hist = GHC.resumeHistory r !! (ix-1)
491 span <- io$ GHC.getHistorySpan session hist
492 return (brackets (ppr (negate ix) <> char ':'
493 <+> ppr span) <> space)
495 dots | _:rs <- resumes, not (null rs) = text "... "
499 hsep (map (\m -> char '*' <> ppr (GHC.moduleName m)) toplevs) <+>
500 hsep (map (ppr . GHC.moduleName) exports)
502 deflt_prompt = dots <> context_bit <> modules_bit
504 f ('%':'s':xs) = deflt_prompt <> f xs
505 f ('%':'%':xs) = char '%' <> f xs
506 f (x:xs) = char x <> f xs
510 return (showSDoc (f (prompt st)))
514 readlineLoop :: GHCi (Maybe String)
517 saveSession -- for use by completion
519 l <- io (readline prompt `finally` setNonBlockingFD 0)
520 -- readline sometimes puts stdin into blocking mode,
521 -- so we need to put it back for the IO library
524 Nothing -> return Nothing
530 queryQueue :: GHCi (Maybe String)
535 c:cs -> do setGHCiState st{ cmdqueue = cs }
538 runCommands :: GHCi (Maybe String) -> GHCi ()
539 runCommands getCmd = do
540 mb_cmd <- noSpace queryQueue
541 mb_cmd <- maybe (noSpace getCmd) (return . Just) mb_cmd
545 b <- ghciHandle handler (doCommand c)
546 if b then return () else runCommands getCmd
548 noSpace q = q >>= maybe (return Nothing)
549 (\c->case removeSpaces c of
551 ":{" -> multiLineCmd q
552 c -> return (Just c) )
556 setGHCiState st{ prompt = "%s| " }
557 mb_cmd <- collectCommand q ""
558 getGHCiState >>= \st->setGHCiState st{ prompt = p }
560 -- we can't use removeSpaces for the sublines here, so
561 -- multiline commands are somewhat more brittle against
562 -- fileformat errors (such as \r in dos input on unix),
563 -- we get rid of any extra spaces for the ":}" test;
564 -- we also avoid silent failure if ":}" is not found;
565 -- and since there is no (?) valid occurrence of \r (as
566 -- opposed to its String representation, "\r") inside a
567 -- ghci command, we replace any such with ' ' (argh:-(
568 collectCommand q c = q >>=
569 maybe (io (ioError collectError))
570 (\l->if removeSpaces l == ":}"
571 then return (Just $ removeSpaces c)
572 else collectCommand q (c++map normSpace l))
573 where normSpace '\r' = ' '
575 -- QUESTION: is userError the one to use here?
576 collectError = userError "unterminated multiline command :{ .. :}"
577 doCommand (':' : cmd) = specialCommand cmd
578 doCommand stmt = do timeIt $ runStmt stmt GHC.RunToCompletion
581 enqueueCommands :: [String] -> GHCi ()
582 enqueueCommands cmds = do
584 setGHCiState st{ cmdqueue = cmds ++ cmdqueue st }
587 -- This version is for the GHC command-line option -e. The only difference
588 -- from runCommand is that it catches the ExitException exception and
589 -- exits, rather than printing out the exception.
590 runCommandEval :: String -> GHCi Bool
591 runCommandEval c = ghciHandle handleEval (doCommand c)
593 handleEval (ExitException code) = io (exitWith code)
594 handleEval e = do handler e
595 io (exitWith (ExitFailure 1))
597 doCommand (':' : command) = specialCommand command
599 = do r <- runStmt stmt GHC.RunToCompletion
601 False -> io (exitWith (ExitFailure 1))
602 -- failure to run the command causes exit(1) for ghc -e.
605 runStmt :: String -> SingleStep -> GHCi Bool
607 | null (filter (not.isSpace) stmt) = return False
608 | ["import", mod] <- words stmt = keepGoing setContext ('+':mod)
610 = do st <- getGHCiState
611 session <- getSession
612 result <- io $ withProgName (progname st) $ withArgs (args st) $
613 GHC.runStmt session stmt step
614 afterRunStmt (const True) result
617 --afterRunStmt :: GHC.RunResult -> GHCi Bool
618 -- False <=> the statement failed to compile
619 afterRunStmt :: (SrcSpan -> Bool) -> GHC.RunResult -> GHCi Bool
620 afterRunStmt _ (GHC.RunException e) = throw e
621 afterRunStmt step_here run_result = do
622 session <- getSession
623 resumes <- io $ GHC.getResumeContext session
625 GHC.RunOk names -> do
626 show_types <- isOptionSet ShowType
627 when show_types $ printTypeOfNames session names
628 GHC.RunBreak _ names mb_info
629 | isNothing mb_info ||
630 step_here (GHC.resumeSpan $ head resumes) -> do
631 printForUser $ ptext SLIT("Stopped at") <+>
632 ppr (GHC.resumeSpan $ head resumes)
633 -- printTypeOfNames session names
634 let namesSorted = sortBy compareNames names
635 tythings <- catMaybes `liftM`
636 io (mapM (GHC.lookupName session) namesSorted)
638 printTypeAndContents session [id | AnId id <- tythings]
639 maybe (return ()) runBreakCmd mb_info
640 -- run the command set with ":set stop <cmd>"
642 enqueueCommands [stop st]
644 | otherwise -> io(GHC.resume session GHC.SingleStep) >>=
645 afterRunStmt step_here >> return ()
649 io installSignalHandlers
650 b <- isOptionSet RevertCAFs
651 io (when b revertCAFs)
653 return (case run_result of GHC.RunOk _ -> True; _ -> False)
655 runBreakCmd :: GHC.BreakInfo -> GHCi ()
656 runBreakCmd info = do
657 let mod = GHC.breakInfo_module info
658 nm = GHC.breakInfo_number info
660 case [ loc | (_,loc) <- breaks st,
661 breakModule loc == mod, breakTick loc == nm ] of
663 loc:_ | null cmd -> return ()
664 | otherwise -> do enqueueCommands [cmd]; return ()
665 where cmd = onBreakCmd loc
667 printTypeOfNames :: Session -> [Name] -> GHCi ()
668 printTypeOfNames session names
669 = mapM_ (printTypeOfName session) $ sortBy compareNames names
671 compareNames :: Name -> Name -> Ordering
672 n1 `compareNames` n2 = compareWith n1 `compare` compareWith n2
673 where compareWith n = (getOccString n, getSrcSpan n)
675 printTypeOfName :: Session -> Name -> GHCi ()
676 printTypeOfName session n
677 = do maybe_tything <- io (GHC.lookupName session n)
678 case maybe_tything of
680 Just thing -> printTyThing thing
682 printTypeAndContents :: Session -> [Id] -> GHCi ()
683 printTypeAndContents session ids = do
684 dflags <- getDynFlags
685 let pefas = dopt Opt_PrintExplicitForalls dflags
686 pcontents = dopt Opt_PrintBindContents dflags
690 terms <- mapM (io . GHC.obtainTermB session depthBound False) ids
691 docs_terms <- mapM (io . showTerm session) terms
692 printForUser $ vcat $ zipWith (\ty cts -> ty <+> equals <+> cts)
693 (map (pprTyThing pefas . AnId) ids)
695 else printForUser $ vcat $ map (pprTyThing pefas . AnId) ids
698 specialCommand :: String -> GHCi Bool
699 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
700 specialCommand str = do
701 let (cmd,rest) = break isSpace str
702 maybe_cmd <- io (lookupCommand cmd)
704 Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
705 ++ shortHelpText) >> return False)
706 Just (_,f,_,_) -> f (dropWhile isSpace rest)
708 lookupCommand :: String -> IO (Maybe Command)
709 lookupCommand str = do
710 macros <- readIORef macros_ref
711 let cmds = builtin_commands ++ macros
712 -- look for exact match first, then the first prefix match
713 case [ c | c <- cmds, str == cmdName c ] of
714 c:_ -> return (Just c)
715 [] -> case [ c | c@(s,_,_,_) <- cmds, str `isPrefixOf` s ] of
717 c:_ -> return (Just c)
720 getCurrentBreakSpan :: GHCi (Maybe SrcSpan)
721 getCurrentBreakSpan = do
722 session <- getSession
723 resumes <- io $ GHC.getResumeContext session
727 let ix = GHC.resumeHistoryIx r
729 then return (Just (GHC.resumeSpan r))
731 let hist = GHC.resumeHistory r !! (ix-1)
732 span <- io $ GHC.getHistorySpan session hist
735 getCurrentBreakModule :: GHCi (Maybe Module)
736 getCurrentBreakModule = do
737 session <- getSession
738 resumes <- io $ GHC.getResumeContext session
742 let ix = GHC.resumeHistoryIx r
744 then return (GHC.breakInfo_module `liftM` GHC.resumeBreakInfo r)
746 let hist = GHC.resumeHistory r !! (ix-1)
747 return $ Just $ GHC.getHistoryModule hist
749 -----------------------------------------------------------------------------
752 noArgs :: GHCi () -> String -> GHCi ()
754 noArgs _ _ = io $ putStrLn "This command takes no arguments"
756 help :: String -> GHCi ()
757 help _ = io (putStr helpText)
759 info :: String -> GHCi ()
760 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
761 info s = do { let names = words s
762 ; session <- getSession
763 ; dflags <- getDynFlags
764 ; let pefas = dopt Opt_PrintExplicitForalls dflags
765 ; mapM_ (infoThing pefas session) names }
767 infoThing pefas session str = io $ do
768 names <- GHC.parseName session str
769 mb_stuffs <- mapM (GHC.getInfo session) names
770 let filtered = filterOutChildren (\(t,_f,_i) -> t) (catMaybes mb_stuffs)
771 unqual <- GHC.getPrintUnqual session
772 putStrLn (showSDocForUser unqual $
773 vcat (intersperse (text "") $
774 map (pprInfo pefas) filtered))
776 -- Filter out names whose parent is also there Good
777 -- example is '[]', which is both a type and data
778 -- constructor in the same type
779 filterOutChildren :: (a -> TyThing) -> [a] -> [a]
780 filterOutChildren get_thing xs
781 = [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)]
783 implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)]
785 pprInfo :: PrintExplicitForalls -> (TyThing, Fixity, [GHC.Instance]) -> SDoc
786 pprInfo pefas (thing, fixity, insts)
787 = pprTyThingInContextLoc pefas thing
788 $$ show_fixity fixity
789 $$ vcat (map GHC.pprInstance insts)
792 | fix == GHC.defaultFixity = empty
793 | otherwise = ppr fix <+> ppr (GHC.getName thing)
795 runMain :: String -> GHCi ()
797 let ss = concat $ intersperse "," (map (\ s -> ('"':s)++"\"") (toArgs args))
798 enqueueCommands ['[': ss ++ "] `System.Environment.withArgs` main"]
800 addModule :: [FilePath] -> GHCi ()
802 io (revertCAFs) -- always revert CAFs on load/add.
803 files <- mapM expandPath files
804 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
805 session <- getSession
806 io (mapM_ (GHC.addTarget session) targets)
807 ok <- io (GHC.load session LoadAllTargets)
808 afterLoad ok session Nothing
810 changeDirectory :: String -> GHCi ()
811 changeDirectory dir = do
812 session <- getSession
813 graph <- io (GHC.getModuleGraph session)
814 when (not (null graph)) $
815 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
816 io (GHC.setTargets session [])
817 io (GHC.load session LoadAllTargets)
818 setContextAfterLoad session []
819 io (GHC.workingDirectoryChanged session)
820 dir <- expandPath dir
821 io (setCurrentDirectory dir)
823 editFile :: String -> GHCi ()
825 do file <- if null str then chooseEditFile else return str
829 $ throwDyn (CmdLineError "editor not set, use :set editor")
830 io $ system (cmd ++ ' ':file)
833 -- The user didn't specify a file so we pick one for them.
834 -- Our strategy is to pick the first module that failed to load,
835 -- or otherwise the first target.
837 -- XXX: Can we figure out what happened if the depndecy analysis fails
838 -- (e.g., because the porgrammeer mistyped the name of a module)?
839 -- XXX: Can we figure out the location of an error to pass to the editor?
840 -- XXX: if we could figure out the list of errors that occured during the
841 -- last load/reaload, then we could start the editor focused on the first
843 chooseEditFile :: GHCi String
845 do session <- getSession
846 let hasFailed x = io $ fmap not $ GHC.isLoaded session $ GHC.ms_mod_name x
848 graph <- io (GHC.getModuleGraph session)
849 failed_graph <- filterM hasFailed graph
850 let order g = flattenSCCs $ GHC.topSortModuleGraph True g Nothing
852 x : _ -> GHC.ml_hs_file (GHC.ms_location x)
855 case pick (order failed_graph) of
856 Just file -> return file
858 do targets <- io (GHC.getTargets session)
859 case msum (map fromTarget targets) of
860 Just file -> return file
861 Nothing -> throwDyn (CmdLineError "No files to edit.")
863 where fromTarget (GHC.Target (GHC.TargetFile f _) _) = Just f
864 fromTarget _ = Nothing -- when would we get a module target?
866 defineMacro :: Bool{-overwrite-} -> String -> GHCi ()
867 defineMacro overwrite s = do
868 let (macro_name, definition) = break isSpace s
869 macros <- io (readIORef macros_ref)
870 let defined = map cmdName macros
873 then io $ putStrLn "no macros defined"
874 else io $ putStr ("the following macros are defined:\n" ++
877 if (not overwrite && macro_name `elem` defined)
878 then throwDyn (CmdLineError
879 ("macro '" ++ macro_name ++ "' is already defined"))
882 let filtered = [ cmd | cmd <- macros, cmdName cmd /= macro_name ]
884 -- give the expression a type signature, so we can be sure we're getting
885 -- something of the right type.
886 let new_expr = '(' : definition ++ ") :: String -> IO String"
888 -- compile the expression
890 maybe_hv <- io (GHC.compileExpr cms new_expr)
893 Just hv -> io (writeIORef macros_ref --
894 (filtered ++ [(macro_name, runMacro hv, False, completeNone)]))
896 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi Bool
898 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
899 enqueueCommands (lines str)
902 undefineMacro :: String -> GHCi ()
903 undefineMacro str = mapM_ undef (words str)
904 where undef macro_name = do
905 cmds <- io (readIORef macros_ref)
906 if (macro_name `notElem` map cmdName cmds)
907 then throwDyn (CmdLineError
908 ("macro '" ++ macro_name ++ "' is not defined"))
910 io (writeIORef macros_ref (filter ((/= macro_name) . cmdName) cmds))
912 cmdCmd :: String -> GHCi ()
914 let expr = '(' : str ++ ") :: IO String"
915 session <- getSession
916 maybe_hv <- io (GHC.compileExpr session expr)
920 cmds <- io $ (unsafeCoerce# hv :: IO String)
921 enqueueCommands (lines cmds)
924 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
925 loadModule fs = timeIt (loadModule' fs)
927 loadModule_ :: [FilePath] -> GHCi ()
928 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
930 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
931 loadModule' files = do
932 session <- getSession
935 discardActiveBreakPoints
936 io (GHC.setTargets session [])
937 io (GHC.load session LoadAllTargets)
940 let (filenames, phases) = unzip files
941 exp_filenames <- mapM expandPath filenames
942 let files' = zip exp_filenames phases
943 targets <- io (mapM (uncurry GHC.guessTarget) files')
945 -- NOTE: we used to do the dependency anal first, so that if it
946 -- fails we didn't throw away the current set of modules. This would
947 -- require some re-working of the GHC interface, so we'll leave it
948 -- as a ToDo for now.
950 io (GHC.setTargets session targets)
951 doLoad session False LoadAllTargets
953 checkModule :: String -> GHCi ()
955 let modl = GHC.mkModuleName m
956 session <- getSession
957 result <- io (GHC.checkModule session modl False)
959 Nothing -> io $ putStrLn "Nothing"
960 Just r -> io $ putStrLn (showSDoc (
961 case GHC.checkedModuleInfo r of
962 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
964 (local,global) = partition ((== modl) . GHC.moduleName . GHC.nameModule) scope
966 (text "global names: " <+> ppr global) $$
967 (text "local names: " <+> ppr local)
969 afterLoad (successIf (isJust result)) session Nothing
971 reloadModule :: String -> GHCi ()
973 session <- getSession
974 doLoad session True $ if null m then LoadAllTargets
975 else LoadUpTo (GHC.mkModuleName m)
978 doLoad :: Session -> Bool -> LoadHowMuch -> GHCi SuccessFlag
979 doLoad session retain_context howmuch = do
980 -- turn off breakpoints before we load: we can't turn them off later, because
981 -- the ModBreaks will have gone away.
982 discardActiveBreakPoints
983 context <- io $ GHC.getContext session
984 ok <- io (GHC.load session howmuch)
985 afterLoad ok session (if retain_context then Just context else Nothing)
988 afterLoad :: SuccessFlag -> Session -> Maybe ([Module],[Module]) -> GHCi ()
989 afterLoad ok session maybe_context = do
990 io (revertCAFs) -- always revert CAFs on load.
992 loaded_mods <- getLoadedModules session
994 -- try to retain the old module context for :reload. This might
995 -- not be possible, for example if some modules have gone away, so
996 -- we attempt to set the same context, backing off to the default
997 -- context if that fails.
998 case maybe_context of
999 Nothing -> setContextAfterLoad session loaded_mods
1001 r <- io $ Exception.try (GHC.setContext session as bs)
1003 Left _err -> setContextAfterLoad session loaded_mods
1004 Right _ -> return ()
1006 modulesLoadedMsg ok (map GHC.ms_mod_name loaded_mods)
1008 setContextAfterLoad :: Session -> [GHC.ModSummary] -> GHCi ()
1009 setContextAfterLoad session [] = do
1010 prel_mod <- getPrelude
1011 io (GHC.setContext session [] [prel_mod])
1012 setContextAfterLoad session ms = do
1013 -- load a target if one is available, otherwise load the topmost module.
1014 targets <- io (GHC.getTargets session)
1015 case [ m | Just m <- map (findTarget ms) targets ] of
1017 let graph' = flattenSCCs (GHC.topSortModuleGraph True ms Nothing) in
1018 load_this (last graph')
1023 = case filter (`matches` t) ms of
1027 summary `matches` Target (TargetModule m) _
1028 = GHC.ms_mod_name summary == m
1029 summary `matches` Target (TargetFile f _) _
1030 | Just f' <- GHC.ml_hs_file (GHC.ms_location summary) = f == f'
1034 load_this summary | m <- GHC.ms_mod summary = do
1035 b <- io (GHC.moduleIsInterpreted session m)
1036 if b then io (GHC.setContext session [m] [])
1038 prel_mod <- getPrelude
1039 io (GHC.setContext session [] [prel_mod,m])
1042 modulesLoadedMsg :: SuccessFlag -> [ModuleName] -> GHCi ()
1043 modulesLoadedMsg ok mods = do
1044 dflags <- getDynFlags
1045 when (verbosity dflags > 0) $ do
1047 | null mods = text "none."
1048 | otherwise = hsep (
1049 punctuate comma (map ppr mods)) <> text "."
1052 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
1054 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
1057 typeOfExpr :: String -> GHCi ()
1059 = do cms <- getSession
1060 maybe_ty <- io (GHC.exprType cms str)
1062 Nothing -> return ()
1063 Just ty -> do dflags <- getDynFlags
1064 let pefas = dopt Opt_PrintExplicitForalls dflags
1065 printForUser $ text str <+> dcolon
1066 <+> pprTypeForUser pefas ty
1068 kindOfType :: String -> GHCi ()
1070 = do cms <- getSession
1071 maybe_ty <- io (GHC.typeKind cms str)
1073 Nothing -> return ()
1074 Just ty -> printForUser $ text str <+> dcolon <+> ppr ty
1076 quit :: String -> GHCi Bool
1077 quit _ = return True
1079 shellEscape :: String -> GHCi Bool
1080 shellEscape str = io (system str >> return False)
1082 -----------------------------------------------------------------------------
1083 -- Browsing a module's contents
1085 browseCmd :: Bool -> String -> GHCi ()
1088 ['*':s] | looksLikeModuleName s -> do
1089 m <- wantInterpretedModule s
1090 browseModule bang m False
1091 [s] | looksLikeModuleName s -> do
1093 browseModule bang m True
1096 (as,bs) <- io $ GHC.getContext s
1097 -- Guess which module the user wants to browse. Pick
1098 -- modules that are interpreted first. The most
1099 -- recently-added module occurs last, it seems.
1101 (as@(_:_), _) -> browseModule bang (last as) True
1102 ([], bs@(_:_)) -> browseModule bang (last bs) True
1103 ([], []) -> throwDyn (CmdLineError ":browse: no current module")
1104 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
1106 -- without bang, show items in context of their parents and omit children
1107 -- with bang, show class methods and data constructors separately, and
1108 -- indicate import modules, to aid qualifying unqualified names
1109 -- with sorted, sort items alphabetically
1110 browseModule :: Bool -> Module -> Bool -> GHCi ()
1111 browseModule bang modl exports_only = do
1113 -- Temporarily set the context to the module we're interested in,
1114 -- just so we can get an appropriate PrintUnqualified
1115 (as,bs) <- io (GHC.getContext s)
1116 prel_mod <- getPrelude
1117 io (if exports_only then GHC.setContext s [] [prel_mod,modl]
1118 else GHC.setContext s [modl] [])
1119 unqual <- io (GHC.getPrintUnqual s)
1120 io (GHC.setContext s as bs)
1122 mb_mod_info <- io $ GHC.getModuleInfo s modl
1124 Nothing -> throwDyn (CmdLineError ("unknown module: " ++
1125 GHC.moduleNameString (GHC.moduleName modl)))
1127 dflags <- getDynFlags
1129 | exports_only = GHC.modInfoExports mod_info
1130 | otherwise = GHC.modInfoTopLevelScope mod_info
1133 -- sort alphabetically name, but putting
1134 -- locally-defined identifiers first.
1135 -- We would like to improve this; see #1799.
1136 sorted_names = loc_sort local ++ occ_sort external
1138 (local,external) = partition ((==modl) . nameModule) names
1139 occ_sort = sortBy (compare `on` nameOccName)
1140 -- try to sort by src location. If the first name in
1141 -- our list has a good source location, then they all should.
1143 | n:_ <- names, isGoodSrcSpan (nameSrcSpan n)
1144 = sortBy (compare `on` nameSrcSpan) names
1148 mb_things <- io $ mapM (GHC.lookupName s) sorted_names
1149 let filtered_things = filterOutChildren (\t -> t) (catMaybes mb_things)
1151 rdr_env <- io $ GHC.getGRE s
1153 let pefas = dopt Opt_PrintExplicitForalls dflags
1154 things | bang = catMaybes mb_things
1155 | otherwise = filtered_things
1156 pretty | bang = pprTyThing
1157 | otherwise = pprTyThingInContext
1159 labels [] = text "-- not currently imported"
1160 labels l = text $ intercalate "\n" $ map qualifier l
1161 qualifier = maybe "-- defined locally"
1162 (("-- imported from "++) . intercalate ", "
1163 . map GHC.moduleNameString)
1164 importInfo = RdrName.getGRE_NameQualifier_maybes rdr_env
1165 modNames = map (importInfo . GHC.getName) things
1167 -- annotate groups of imports with their import modules
1168 -- the default ordering is somewhat arbitrary, so we group
1169 -- by header and sort groups; the names themselves should
1170 -- really come in order of source appearance.. (trac #1799)
1171 annotate mts = concatMap (\(m,ts)->labels m:ts)
1172 $ sortBy cmpQualifiers $ group mts
1173 where cmpQualifiers =
1174 compare `on` (map (fmap (map moduleNameFS)) . fst)
1176 group mts@((m,_):_) = (m,map snd g) : group ng
1177 where (g,ng) = partition ((==m).fst) mts
1179 let prettyThings = map (pretty pefas) things
1180 prettyThings' | bang = annotate $ zip modNames prettyThings
1181 | otherwise = prettyThings
1182 io (putStrLn $ showSDocForUser unqual (vcat prettyThings'))
1183 -- ToDo: modInfoInstances currently throws an exception for
1184 -- package modules. When it works, we can do this:
1185 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
1187 -----------------------------------------------------------------------------
1188 -- Setting the module context
1190 setContext :: String -> GHCi ()
1192 | all sensible mods = fn mods
1193 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
1195 (fn, mods) = case str of
1196 '+':stuff -> (addToContext, words stuff)
1197 '-':stuff -> (removeFromContext, words stuff)
1198 stuff -> (newContext, words stuff)
1200 sensible ('*':m) = looksLikeModuleName m
1201 sensible m = looksLikeModuleName m
1203 separate :: Session -> [String] -> [Module] -> [Module]
1204 -> GHCi ([Module],[Module])
1205 separate _ [] as bs = return (as,bs)
1206 separate session (('*':str):ms) as bs = do
1207 m <- wantInterpretedModule str
1208 separate session ms (m:as) bs
1209 separate session (str:ms) as bs = do
1210 m <- lookupModule str
1211 separate session ms as (m:bs)
1213 newContext :: [String] -> GHCi ()
1214 newContext strs = do
1216 (as,bs) <- separate s strs [] []
1217 prel_mod <- getPrelude
1218 let bs' = if null as && prel_mod `notElem` bs then prel_mod:bs else bs
1219 io $ GHC.setContext s as bs'
1222 addToContext :: [String] -> GHCi ()
1223 addToContext strs = do
1225 (as,bs) <- io $ GHC.getContext s
1227 (new_as,new_bs) <- separate s strs [] []
1229 let as_to_add = new_as \\ (as ++ bs)
1230 bs_to_add = new_bs \\ (as ++ bs)
1232 io $ GHC.setContext s (as ++ as_to_add) (bs ++ bs_to_add)
1235 removeFromContext :: [String] -> GHCi ()
1236 removeFromContext strs = do
1238 (as,bs) <- io $ GHC.getContext s
1240 (as_to_remove,bs_to_remove) <- separate s strs [] []
1242 let as' = as \\ (as_to_remove ++ bs_to_remove)
1243 bs' = bs \\ (as_to_remove ++ bs_to_remove)
1245 io $ GHC.setContext s as' bs'
1247 ----------------------------------------------------------------------------
1250 -- set options in the interpreter. Syntax is exactly the same as the
1251 -- ghc command line, except that certain options aren't available (-C,
1254 -- This is pretty fragile: most options won't work as expected. ToDo:
1255 -- figure out which ones & disallow them.
1257 setCmd :: String -> GHCi ()
1259 = do st <- getGHCiState
1260 let opts = options st
1261 io $ putStrLn (showSDoc (
1262 text "options currently set: " <>
1265 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
1267 dflags <- getDynFlags
1268 io $ putStrLn (showSDoc (
1269 vcat (text "GHCi-specific dynamic flag settings:"
1270 :map (flagSetting dflags) ghciFlags)
1272 io $ putStrLn (showSDoc (
1273 vcat (text "other dynamic, non-language, flag settings:"
1274 :map (flagSetting dflags) nonLanguageDynFlags)
1276 where flagSetting dflags (str,f)
1277 | dopt f dflags = text " " <> text "-f" <> text str
1278 | otherwise = text " " <> text "-fno-" <> text str
1279 (ghciFlags,others) = partition (\(_,f)->f `elem` flags)
1281 nonLanguageDynFlags = filter (\(_,f)->not $ f `elem` map snd xFlags)
1283 flags = [Opt_PrintExplicitForalls
1284 ,Opt_PrintBindResult
1285 ,Opt_BreakOnException
1287 ,Opt_PrintEvldWithShow
1290 = case toArgs str of
1291 ("args":args) -> setArgs args
1292 ("prog":prog) -> setProg prog
1293 ("prompt":_) -> setPrompt (after 6)
1294 ("editor":_) -> setEditor (after 6)
1295 ("stop":_) -> setStop (after 4)
1296 wds -> setOptions wds
1297 where after n = dropWhile isSpace $ drop n $ dropWhile isSpace str
1299 setArgs, setProg, setOptions :: [String] -> GHCi ()
1300 setEditor, setStop, setPrompt :: String -> GHCi ()
1304 setGHCiState st{ args = args }
1308 setGHCiState st{ progname = prog }
1310 io (hPutStrLn stderr "syntax: :set prog <progname>")
1314 setGHCiState st{ editor = cmd }
1316 setStop str@(c:_) | isDigit c
1317 = do let (nm_str,rest) = break (not.isDigit) str
1320 let old_breaks = breaks st
1321 if all ((/= nm) . fst) old_breaks
1322 then printForUser (text "Breakpoint" <+> ppr nm <+>
1323 text "does not exist")
1325 let new_breaks = map fn old_breaks
1326 fn (i,loc) | i == nm = (i,loc { onBreakCmd = dropWhile isSpace rest })
1327 | otherwise = (i,loc)
1328 setGHCiState st{ breaks = new_breaks }
1331 setGHCiState st{ stop = cmd }
1333 setPrompt value = do
1336 then io $ hPutStrLn stderr $ "syntax: :set prompt <prompt>, currently \"" ++ prompt st ++ "\""
1337 else setGHCiState st{ prompt = remQuotes value }
1339 remQuotes ('\"':xs) | not (null xs) && last xs == '\"' = init xs
1343 do -- first, deal with the GHCi opts (+s, +t, etc.)
1344 let (plus_opts, minus_opts) = partitionWith isPlus wds
1345 mapM_ setOpt plus_opts
1346 -- then, dynamic flags
1347 newDynFlags minus_opts
1349 newDynFlags :: [String] -> GHCi ()
1350 newDynFlags minus_opts = do
1351 dflags <- getDynFlags
1352 let pkg_flags = packageFlags dflags
1353 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1355 if (not (null leftovers))
1356 then throwDyn (CmdLineError ("unrecognised flags: " ++
1360 new_pkgs <- setDynFlags dflags'
1362 -- if the package flags changed, we should reset the context
1363 -- and link the new packages.
1364 dflags <- getDynFlags
1365 when (packageFlags dflags /= pkg_flags) $ do
1366 io $ hPutStrLn stderr "package flags have changed, ressetting and loading new packages..."
1367 session <- getSession
1368 io (GHC.setTargets session [])
1369 io (GHC.load session LoadAllTargets)
1370 io (linkPackages dflags new_pkgs)
1371 setContextAfterLoad session []
1375 unsetOptions :: String -> GHCi ()
1377 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1378 let opts = words str
1379 (minus_opts, rest1) = partition isMinus opts
1380 (plus_opts, rest2) = partitionWith isPlus rest1
1382 if (not (null rest2))
1383 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1386 mapM_ unsetOpt plus_opts
1388 let no_flag ('-':'f':rest) = return ("-fno-" ++ rest)
1389 no_flag f = throwDyn (ProgramError ("don't know how to reverse " ++ f))
1391 no_flags <- mapM no_flag minus_opts
1392 newDynFlags no_flags
1394 isMinus :: String -> Bool
1395 isMinus ('-':_) = True
1398 isPlus :: String -> Either String String
1399 isPlus ('+':opt) = Left opt
1400 isPlus other = Right other
1402 setOpt, unsetOpt :: String -> GHCi ()
1405 = case strToGHCiOpt str of
1406 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1407 Just o -> setOption o
1410 = case strToGHCiOpt str of
1411 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1412 Just o -> unsetOption o
1414 strToGHCiOpt :: String -> (Maybe GHCiOption)
1415 strToGHCiOpt "s" = Just ShowTiming
1416 strToGHCiOpt "t" = Just ShowType
1417 strToGHCiOpt "r" = Just RevertCAFs
1418 strToGHCiOpt _ = Nothing
1420 optToStr :: GHCiOption -> String
1421 optToStr ShowTiming = "s"
1422 optToStr ShowType = "t"
1423 optToStr RevertCAFs = "r"
1425 -- ---------------------------------------------------------------------------
1428 showCmd :: String -> GHCi ()
1432 ["args"] -> io $ putStrLn (show (args st))
1433 ["prog"] -> io $ putStrLn (show (progname st))
1434 ["prompt"] -> io $ putStrLn (show (prompt st))
1435 ["editor"] -> io $ putStrLn (show (editor st))
1436 ["stop"] -> io $ putStrLn (show (stop st))
1437 ["modules" ] -> showModules
1438 ["bindings"] -> showBindings
1439 ["linker"] -> io showLinkerState
1440 ["breaks"] -> showBkptTable
1441 ["context"] -> showContext
1442 ["packages"] -> showPackages
1443 ["languages"] -> showLanguages
1444 _ -> throwDyn (CmdLineError "syntax: :show [args|prog|prompt|editor|stop|modules|bindings|breaks|context]")
1446 showModules :: GHCi ()
1448 session <- getSession
1449 loaded_mods <- getLoadedModules session
1450 -- we want *loaded* modules only, see #1734
1451 let show_one ms = do m <- io (GHC.showModule session ms); io (putStrLn m)
1452 mapM_ show_one loaded_mods
1454 getLoadedModules :: GHC.Session -> GHCi [GHC.ModSummary]
1455 getLoadedModules session = do
1456 graph <- io (GHC.getModuleGraph session)
1457 filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph
1459 showBindings :: GHCi ()
1462 bindings <- io (GHC.getBindings s)
1463 printTypeAndContents s [ id | AnId id <- sortBy compareTyThings bindings]
1465 compareTyThings :: TyThing -> TyThing -> Ordering
1466 t1 `compareTyThings` t2 = getName t1 `compareNames` getName t2
1468 printTyThing :: TyThing -> GHCi ()
1469 printTyThing tyth = do dflags <- getDynFlags
1470 let pefas = dopt Opt_PrintExplicitForalls dflags
1471 printForUser (pprTyThing pefas tyth)
1473 showBkptTable :: GHCi ()
1476 printForUser $ prettyLocations (breaks st)
1478 showContext :: GHCi ()
1480 session <- getSession
1481 resumes <- io $ GHC.getResumeContext session
1482 printForUser $ vcat (map pp_resume (reverse resumes))
1485 ptext SLIT("--> ") <> text (GHC.resumeStmt resume)
1486 $$ nest 2 (ptext SLIT("Stopped at") <+> ppr (GHC.resumeSpan resume))
1488 showPackages :: GHCi ()
1490 pkg_flags <- fmap packageFlags getDynFlags
1491 io $ putStrLn $ showSDoc $ vcat $
1492 text ("active package flags:"++if null pkg_flags then " none" else "")
1493 : map showFlag pkg_flags
1494 pkg_ids <- fmap (preloadPackages . pkgState) getDynFlags
1495 io $ putStrLn $ showSDoc $ vcat $
1496 text "packages currently loaded:"
1497 : map (nest 2 . text . packageIdString) pkg_ids
1498 where showFlag (ExposePackage p) = text $ " -package " ++ p
1499 showFlag (HidePackage p) = text $ " -hide-package " ++ p
1500 showFlag (IgnorePackage p) = text $ " -ignore-package " ++ p
1502 showLanguages :: GHCi ()
1504 dflags <- getDynFlags
1505 io $ putStrLn $ showSDoc $ vcat $
1506 text "active language flags:" :
1507 [text (" -X" ++ str) | (str,f) <- DynFlags.xFlags, dopt f dflags]
1509 -- -----------------------------------------------------------------------------
1512 completeNone :: String -> IO [String]
1513 completeNone _w = return []
1515 completeMacro, completeIdentifier, completeModule,
1516 completeHomeModule, completeSetOptions, completeFilename,
1517 completeHomeModuleOrFile
1518 :: String -> IO [String]
1521 completeWord :: String -> Int -> Int -> IO (Maybe (String, [String]))
1522 completeWord w start end = do
1523 line <- Readline.getLineBuffer
1524 let line_words = words (dropWhile isSpace line)
1526 ':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
1528 | ((':':c) : _) <- line_words -> do
1529 maybe_cmd <- lookupCommand c
1530 let (n,w') = selectWord (words' 0 line)
1532 Nothing -> return Nothing
1533 Just (_,_,False,complete) -> wrapCompleter complete w
1534 Just (_,_,True,complete) -> let complete' w = do rets <- complete w
1535 return (map (drop n) rets)
1536 in wrapCompleter complete' w'
1537 | ("import" : _) <- line_words ->
1538 wrapCompleter completeModule w
1540 --printf "complete %s, start = %d, end = %d\n" w start end
1541 wrapCompleter completeIdentifier w
1542 where words' _ [] = []
1543 words' n str = let (w,r) = break isSpace str
1544 (s,r') = span isSpace r
1545 in (n,w):words' (n+length w+length s) r'
1546 -- In a Haskell expression we want to parse 'a-b' as three words
1547 -- where a compiler flag (ie. -fno-monomorphism-restriction) should
1548 -- only be a single word.
1549 selectWord [] = (0,w)
1550 selectWord ((offset,x):xs)
1551 | offset+length x >= start = (start-offset,take (end-offset) x)
1552 | otherwise = selectWord xs
1554 completeCmd :: String -> IO [String]
1556 cmds <- readIORef macros_ref
1557 return (filter (w `isPrefixOf`) (map (':':)
1558 (map cmdName (builtin_commands ++ cmds))))
1560 completeMacro w = do
1561 cmds <- readIORef macros_ref
1562 return (filter (w `isPrefixOf`) (map cmdName cmds))
1564 completeIdentifier w = do
1566 rdrs <- GHC.getRdrNamesInScope s
1567 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) rdrs))
1569 completeModule w = do
1571 dflags <- GHC.getSessionDynFlags s
1572 let pkg_mods = allExposedModules dflags
1573 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) pkg_mods))
1575 completeHomeModule w = do
1577 g <- GHC.getModuleGraph s
1578 let home_mods = map GHC.ms_mod_name g
1579 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) home_mods))
1581 completeSetOptions w = do
1582 return (filter (w `isPrefixOf`) options)
1583 where options = "args":"prog":allFlags
1585 completeFilename = Readline.filenameCompletionFunction
1587 completeHomeModuleOrFile = unionComplete completeHomeModule completeFilename
1589 unionComplete :: (String -> IO [String]) -> (String -> IO [String]) -> String -> IO [String]
1590 unionComplete f1 f2 w = do
1595 wrapCompleter :: (String -> IO [String]) -> String -> IO (Maybe (String,[String]))
1596 wrapCompleter fun w = do
1599 [] -> return Nothing
1600 [x] -> return (Just (x,[]))
1601 xs -> case getCommonPrefix xs of
1602 "" -> return (Just ("",xs))
1603 pref -> return (Just (pref,xs))
1605 getCommonPrefix :: [String] -> String
1606 getCommonPrefix [] = ""
1607 getCommonPrefix (s:ss) = foldl common s ss
1608 where common _s "" = ""
1610 common (c:cs) (d:ds)
1611 | c == d = c : common cs ds
1614 allExposedModules :: DynFlags -> [ModuleName]
1615 allExposedModules dflags
1616 = concat (map exposedModules (filter exposed (eltsUFM pkg_db)))
1618 pkg_db = pkgIdMap (pkgState dflags)
1620 completeMacro = completeNone
1621 completeIdentifier = completeNone
1622 completeModule = completeNone
1623 completeHomeModule = completeNone
1624 completeSetOptions = completeNone
1625 completeFilename = completeNone
1626 completeHomeModuleOrFile=completeNone
1629 -- ---------------------------------------------------------------------------
1630 -- User code exception handling
1632 -- This is the exception handler for exceptions generated by the
1633 -- user's code and exceptions coming from children sessions;
1634 -- it normally just prints out the exception. The
1635 -- handler must be recursive, in case showing the exception causes
1636 -- more exceptions to be raised.
1638 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
1639 -- raising another exception. We therefore don't put the recursive
1640 -- handler arond the flushing operation, so if stderr is closed
1641 -- GHCi will just die gracefully rather than going into an infinite loop.
1642 handler :: Exception -> GHCi Bool
1644 handler exception = do
1646 io installSignalHandlers
1647 ghciHandle handler (showException exception >> return False)
1649 showException :: Exception -> GHCi ()
1650 showException (DynException dyn) =
1651 case fromDynamic dyn of
1652 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
1653 Just Interrupted -> io (putStrLn "Interrupted.")
1654 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
1655 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
1656 Just other_ghc_ex -> io (print other_ghc_ex)
1658 showException other_exception
1659 = io (putStrLn ("*** Exception: " ++ show other_exception))
1661 -----------------------------------------------------------------------------
1662 -- recursive exception handlers
1664 -- Don't forget to unblock async exceptions in the handler, or if we're
1665 -- in an exception loop (eg. let a = error a in a) the ^C exception
1666 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1668 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1669 ghciHandle h (GHCi m) = GHCi $ \s ->
1670 Exception.catch (m s)
1671 (\e -> unGHCi (ghciUnblock (h e)) s)
1673 ghciUnblock :: GHCi a -> GHCi a
1674 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1677 -- ----------------------------------------------------------------------------
1680 expandPath :: String -> GHCi String
1682 case dropWhile isSpace path of
1684 tilde <- io getHomeDirectory -- will fail if HOME not defined
1685 return (tilde ++ '/':d)
1689 wantInterpretedModule :: String -> GHCi Module
1690 wantInterpretedModule str = do
1691 session <- getSession
1692 modl <- lookupModule str
1693 is_interpreted <- io (GHC.moduleIsInterpreted session modl)
1694 when (not is_interpreted) $
1695 throwDyn (CmdLineError ("module '" ++ str ++ "' is not interpreted"))
1698 wantNameFromInterpretedModule :: (Name -> SDoc -> GHCi ()) -> String
1699 -> (Name -> GHCi ())
1701 wantNameFromInterpretedModule noCanDo str and_then = do
1702 session <- getSession
1703 names <- io $ GHC.parseName session str
1707 let modl = GHC.nameModule n
1708 if not (GHC.isExternalName n)
1709 then noCanDo n $ ppr n <>
1710 text " is not defined in an interpreted module"
1712 is_interpreted <- io (GHC.moduleIsInterpreted session modl)
1713 if not is_interpreted
1714 then noCanDo n $ text "module " <> ppr modl <>
1715 text " is not interpreted"
1718 -- ----------------------------------------------------------------------------
1719 -- Windows console setup
1721 setUpConsole :: IO ()
1723 #ifdef mingw32_HOST_OS
1724 -- On Windows we need to set a known code page, otherwise the characters
1725 -- we read from the console will be be in some strange encoding, and
1726 -- similarly for characters we write to the console.
1728 -- At the moment, GHCi pretends all input is Latin-1. In the
1729 -- future we should support UTF-8, but for now we set the code
1730 -- pages to Latin-1. Doing it this way does lead to problems,
1731 -- however: see bug #1649.
1733 -- It seems you have to set the font in the console window to
1734 -- a Unicode font in order for output to work properly,
1735 -- otherwise non-ASCII characters are mapped wrongly. sigh.
1736 -- (see MSDN for SetConsoleOutputCP()).
1738 -- This call has been known to hang on some machines, see bug #1483
1740 setConsoleCP 28591 -- ISO Latin-1
1741 setConsoleOutputCP 28591 -- ISO Latin-1
1745 -- -----------------------------------------------------------------------------
1746 -- commands for debugger
1748 sprintCmd, printCmd, forceCmd :: String -> GHCi ()
1749 sprintCmd = pprintCommand False False
1750 printCmd = pprintCommand True False
1751 forceCmd = pprintCommand False True
1753 pprintCommand :: Bool -> Bool -> String -> GHCi ()
1754 pprintCommand bind force str = do
1755 session <- getSession
1756 io $ pprintClosureCommand session bind force str
1758 stepCmd :: String -> GHCi ()
1759 stepCmd [] = doContinue (const True) GHC.SingleStep
1760 stepCmd expression = do runStmt expression GHC.SingleStep; return ()
1762 stepLocalCmd :: String -> GHCi ()
1763 stepLocalCmd [] = do
1764 mb_span <- getCurrentBreakSpan
1766 Nothing -> stepCmd []
1768 Just mod <- getCurrentBreakModule
1769 current_toplevel_decl <- enclosingTickSpan mod loc
1770 doContinue (`isSubspanOf` current_toplevel_decl) GHC.SingleStep
1772 stepLocalCmd expression = stepCmd expression
1774 stepModuleCmd :: String -> GHCi ()
1775 stepModuleCmd [] = do
1776 mb_span <- getCurrentBreakSpan
1778 Nothing -> stepCmd []
1780 Just span <- getCurrentBreakSpan
1781 let f some_span = optSrcSpanFileName span == optSrcSpanFileName some_span
1782 doContinue f GHC.SingleStep
1784 stepModuleCmd expression = stepCmd expression
1786 -- | Returns the span of the largest tick containing the srcspan given
1787 enclosingTickSpan :: Module -> SrcSpan -> GHCi SrcSpan
1788 enclosingTickSpan mod src = do
1789 ticks <- getTickArray mod
1790 let line = srcSpanStartLine src
1791 ASSERT (inRange (bounds ticks) line) do
1792 let enclosing_spans = [ span | (_,span) <- ticks ! line
1793 , srcSpanEnd span >= srcSpanEnd src]
1794 return . head . sortBy leftmost_largest $ enclosing_spans
1796 traceCmd :: String -> GHCi ()
1797 traceCmd [] = doContinue (const True) GHC.RunAndLogSteps
1798 traceCmd expression = do runStmt expression GHC.RunAndLogSteps; return ()
1800 continueCmd :: String -> GHCi ()
1801 continueCmd = noArgs $ doContinue (const True) GHC.RunToCompletion
1803 -- doContinue :: SingleStep -> GHCi ()
1804 doContinue :: (SrcSpan -> Bool) -> SingleStep -> GHCi ()
1805 doContinue pred step = do
1806 session <- getSession
1807 runResult <- io $ GHC.resume session step
1808 afterRunStmt pred runResult
1811 abandonCmd :: String -> GHCi ()
1812 abandonCmd = noArgs $ do
1814 b <- io $ GHC.abandon s -- the prompt will change to indicate the new context
1815 when (not b) $ io $ putStrLn "There is no computation running."
1818 deleteCmd :: String -> GHCi ()
1819 deleteCmd argLine = do
1820 deleteSwitch $ words argLine
1822 deleteSwitch :: [String] -> GHCi ()
1824 io $ putStrLn "The delete command requires at least one argument."
1825 -- delete all break points
1826 deleteSwitch ("*":_rest) = discardActiveBreakPoints
1827 deleteSwitch idents = do
1828 mapM_ deleteOneBreak idents
1830 deleteOneBreak :: String -> GHCi ()
1832 | all isDigit str = deleteBreak (read str)
1833 | otherwise = return ()
1835 historyCmd :: String -> GHCi ()
1837 | null arg = history 20
1838 | all isDigit arg = history (read arg)
1839 | otherwise = io $ putStrLn "Syntax: :history [num]"
1843 resumes <- io $ GHC.getResumeContext s
1845 [] -> io $ putStrLn "Not stopped at a breakpoint"
1847 let hist = GHC.resumeHistory r
1848 (took,rest) = splitAt num hist
1849 spans <- mapM (io . GHC.getHistorySpan s) took
1850 let nums = map (printf "-%-3d:") [(1::Int)..]
1851 let names = map GHC.historyEnclosingDecl took
1852 printForUser (vcat(zipWith3
1853 (\x y z -> x <+> y <+> z)
1855 (map (bold . ppr) names)
1856 (map (parens . ppr) spans)))
1857 io $ putStrLn $ if null rest then "<end of history>" else "..."
1859 bold :: SDoc -> SDoc
1860 bold c | do_bold = text start_bold <> c <> text end_bold
1863 backCmd :: String -> GHCi ()
1864 backCmd = noArgs $ do
1866 (names, _, span) <- io $ GHC.back s
1867 printForUser $ ptext SLIT("Logged breakpoint at") <+> ppr span
1868 printTypeOfNames s names
1869 -- run the command set with ":set stop <cmd>"
1871 enqueueCommands [stop st]
1873 forwardCmd :: String -> GHCi ()
1874 forwardCmd = noArgs $ do
1876 (names, ix, span) <- io $ GHC.forward s
1877 printForUser $ (if (ix == 0)
1878 then ptext SLIT("Stopped at")
1879 else ptext SLIT("Logged breakpoint at")) <+> ppr span
1880 printTypeOfNames s names
1881 -- run the command set with ":set stop <cmd>"
1883 enqueueCommands [stop st]
1885 -- handle the "break" command
1886 breakCmd :: String -> GHCi ()
1887 breakCmd argLine = do
1888 session <- getSession
1889 breakSwitch session $ words argLine
1891 breakSwitch :: Session -> [String] -> GHCi ()
1892 breakSwitch _session [] = do
1893 io $ putStrLn "The break command requires at least one argument."
1894 breakSwitch session (arg1:rest)
1895 | looksLikeModuleName arg1 = do
1896 mod <- wantInterpretedModule arg1
1897 breakByModule mod rest
1898 | all isDigit arg1 = do
1899 (toplevel, _) <- io $ GHC.getContext session
1901 (mod : _) -> breakByModuleLine mod (read arg1) rest
1903 io $ putStrLn "Cannot find default module for breakpoint."
1904 io $ putStrLn "Perhaps no modules are loaded for debugging?"
1905 | otherwise = do -- try parsing it as an identifier
1906 wantNameFromInterpretedModule noCanDo arg1 $ \name -> do
1907 let loc = GHC.srcSpanStart (GHC.nameSrcSpan name)
1908 if GHC.isGoodSrcLoc loc
1909 then findBreakAndSet (GHC.nameModule name) $
1910 findBreakByCoord (Just (GHC.srcLocFile loc))
1911 (GHC.srcLocLine loc,
1913 else noCanDo name $ text "can't find its location: " <> ppr loc
1915 noCanDo n why = printForUser $
1916 text "cannot set breakpoint on " <> ppr n <> text ": " <> why
1918 breakByModule :: Module -> [String] -> GHCi ()
1919 breakByModule mod (arg1:rest)
1920 | all isDigit arg1 = do -- looks like a line number
1921 breakByModuleLine mod (read arg1) rest
1925 breakByModuleLine :: Module -> Int -> [String] -> GHCi ()
1926 breakByModuleLine mod line args
1927 | [] <- args = findBreakAndSet mod $ findBreakByLine line
1928 | [col] <- args, all isDigit col =
1929 findBreakAndSet mod $ findBreakByCoord Nothing (line, read col)
1930 | otherwise = breakSyntax
1933 breakSyntax = throwDyn (CmdLineError "Syntax: :break [<mod>] <line> [<column>]")
1935 findBreakAndSet :: Module -> (TickArray -> Maybe (Int, SrcSpan)) -> GHCi ()
1936 findBreakAndSet mod lookupTickTree = do
1937 tickArray <- getTickArray mod
1938 (breakArray, _) <- getModBreak mod
1939 case lookupTickTree tickArray of
1940 Nothing -> io $ putStrLn $ "No breakpoints found at that location."
1941 Just (tick, span) -> do
1942 success <- io $ setBreakFlag True breakArray tick
1946 recordBreak $ BreakLocation
1953 text "Breakpoint " <> ppr nm <>
1955 then text " was already set at " <> ppr span
1956 else text " activated at " <> ppr span
1958 printForUser $ text "Breakpoint could not be activated at"
1961 -- When a line number is specified, the current policy for choosing
1962 -- the best breakpoint is this:
1963 -- - the leftmost complete subexpression on the specified line, or
1964 -- - the leftmost subexpression starting on the specified line, or
1965 -- - the rightmost subexpression enclosing the specified line
1967 findBreakByLine :: Int -> TickArray -> Maybe (BreakIndex,SrcSpan)
1968 findBreakByLine line arr
1969 | not (inRange (bounds arr) line) = Nothing
1971 listToMaybe (sortBy (leftmost_largest `on` snd) complete) `mplus`
1972 listToMaybe (sortBy (leftmost_smallest `on` snd) incomplete) `mplus`
1973 listToMaybe (sortBy (rightmost `on` snd) ticks)
1977 starts_here = [ tick | tick@(_,span) <- ticks,
1978 GHC.srcSpanStartLine span == line ]
1980 (complete,incomplete) = partition ends_here starts_here
1981 where ends_here (_,span) = GHC.srcSpanEndLine span == line
1983 findBreakByCoord :: Maybe FastString -> (Int,Int) -> TickArray
1984 -> Maybe (BreakIndex,SrcSpan)
1985 findBreakByCoord mb_file (line, col) arr
1986 | not (inRange (bounds arr) line) = Nothing
1988 listToMaybe (sortBy (rightmost `on` snd) contains ++
1989 sortBy (leftmost_smallest `on` snd) after_here)
1993 -- the ticks that span this coordinate
1994 contains = [ tick | tick@(_,span) <- ticks, span `spans` (line,col),
1995 is_correct_file span ]
1997 is_correct_file span
1998 | Just f <- mb_file = GHC.srcSpanFile span == f
2001 after_here = [ tick | tick@(_,span) <- ticks,
2002 GHC.srcSpanStartLine span == line,
2003 GHC.srcSpanStartCol span >= col ]
2005 -- For now, use ANSI bold on terminals that we know support it.
2006 -- Otherwise, we add a line of carets under the active expression instead.
2007 -- In particular, on Windows and when running the testsuite (which sets
2008 -- TERM to vt100 for other reasons) we get carets.
2009 -- We really ought to use a proper termcap/terminfo library.
2011 do_bold = (`isPrefixOf` unsafePerformIO mTerm) `any` ["xterm", "linux"]
2012 where mTerm = System.Environment.getEnv "TERM"
2013 `Exception.catch` \_ -> return "TERM not set"
2015 start_bold :: String
2016 start_bold = "\ESC[1m"
2018 end_bold = "\ESC[0m"
2020 listCmd :: String -> GHCi ()
2022 mb_span <- getCurrentBreakSpan
2024 Nothing -> printForUser $ text "not stopped at a breakpoint; nothing to list"
2025 Just span | GHC.isGoodSrcSpan span -> io $ listAround span True
2026 | otherwise -> printForUser $ text "unable to list source for" <+> ppr span
2027 listCmd str = list2 (words str)
2029 list2 :: [String] -> GHCi ()
2030 list2 [arg] | all isDigit arg = do
2031 session <- getSession
2032 (toplevel, _) <- io $ GHC.getContext session
2034 [] -> io $ putStrLn "No module to list"
2035 (mod : _) -> listModuleLine mod (read arg)
2036 list2 [arg1,arg2] | looksLikeModuleName arg1, all isDigit arg2 = do
2037 mod <- wantInterpretedModule arg1
2038 listModuleLine mod (read arg2)
2040 wantNameFromInterpretedModule noCanDo arg $ \name -> do
2041 let loc = GHC.srcSpanStart (GHC.nameSrcSpan name)
2042 if GHC.isGoodSrcLoc loc
2044 tickArray <- getTickArray (GHC.nameModule name)
2045 let mb_span = findBreakByCoord (Just (GHC.srcLocFile loc))
2046 (GHC.srcLocLine loc, GHC.srcLocCol loc)
2049 Nothing -> io $ listAround (GHC.srcLocSpan loc) False
2050 Just (_,span) -> io $ listAround span False
2052 noCanDo name $ text "can't find its location: " <>
2055 noCanDo n why = printForUser $
2056 text "cannot list source code for " <> ppr n <> text ": " <> why
2058 io $ putStrLn "syntax: :list [<line> | <module> <line> | <identifier>]"
2060 listModuleLine :: Module -> Int -> GHCi ()
2061 listModuleLine modl line = do
2062 session <- getSession
2063 graph <- io (GHC.getModuleGraph session)
2064 let this = filter ((== modl) . GHC.ms_mod) graph
2066 [] -> panic "listModuleLine"
2068 let filename = fromJust (ml_hs_file (GHC.ms_location summ))
2069 loc = GHC.mkSrcLoc (mkFastString (filename)) line 0
2070 io $ listAround (GHC.srcLocSpan loc) False
2072 -- | list a section of a source file around a particular SrcSpan.
2073 -- If the highlight flag is True, also highlight the span using
2074 -- start_bold/end_bold.
2075 listAround :: SrcSpan -> Bool -> IO ()
2076 listAround span do_highlight = do
2077 contents <- BS.readFile (unpackFS file)
2079 lines = BS.split '\n' contents
2080 these_lines = take (line2 - line1 + 1 + pad_before + pad_after) $
2081 drop (line1 - 1 - pad_before) $ lines
2082 fst_line = max 1 (line1 - pad_before)
2083 line_nos = [ fst_line .. ]
2085 highlighted | do_highlight = zipWith highlight line_nos these_lines
2086 | otherwise = [\p -> BS.concat[p,l] | l <- these_lines]
2088 bs_line_nos = [ BS.pack (show l ++ " ") | l <- line_nos ]
2089 prefixed = zipWith ($) highlighted bs_line_nos
2091 BS.putStrLn (BS.intercalate (BS.pack "\n") prefixed)
2093 file = GHC.srcSpanFile span
2094 line1 = GHC.srcSpanStartLine span
2095 col1 = GHC.srcSpanStartCol span
2096 line2 = GHC.srcSpanEndLine span
2097 col2 = GHC.srcSpanEndCol span
2099 pad_before | line1 == 1 = 0
2103 highlight | do_bold = highlight_bold
2104 | otherwise = highlight_carets
2106 highlight_bold no line prefix
2107 | no == line1 && no == line2
2108 = let (a,r) = BS.splitAt col1 line
2109 (b,c) = BS.splitAt (col2-col1) r
2111 BS.concat [prefix, a,BS.pack start_bold,b,BS.pack end_bold,c]
2113 = let (a,b) = BS.splitAt col1 line in
2114 BS.concat [prefix, a, BS.pack start_bold, b]
2116 = let (a,b) = BS.splitAt col2 line in
2117 BS.concat [prefix, a, BS.pack end_bold, b]
2118 | otherwise = BS.concat [prefix, line]
2120 highlight_carets no line prefix
2121 | no == line1 && no == line2
2122 = BS.concat [prefix, line, nl, indent, BS.replicate col1 ' ',
2123 BS.replicate (col2-col1) '^']
2125 = BS.concat [indent, BS.replicate (col1 - 2) ' ', BS.pack "vv", nl,
2128 = BS.concat [prefix, line, nl, indent, BS.replicate col2 ' ',
2130 | otherwise = BS.concat [prefix, line]
2132 indent = BS.pack (" " ++ replicate (length (show no)) ' ')
2133 nl = BS.singleton '\n'
2135 -- --------------------------------------------------------------------------
2138 getTickArray :: Module -> GHCi TickArray
2139 getTickArray modl = do
2141 let arrmap = tickarrays st
2142 case lookupModuleEnv arrmap modl of
2143 Just arr -> return arr
2145 (_breakArray, ticks) <- getModBreak modl
2146 let arr = mkTickArray (assocs ticks)
2147 setGHCiState st{tickarrays = extendModuleEnv arrmap modl arr}
2150 discardTickArrays :: GHCi ()
2151 discardTickArrays = do
2153 setGHCiState st{tickarrays = emptyModuleEnv}
2155 mkTickArray :: [(BreakIndex,SrcSpan)] -> TickArray
2157 = accumArray (flip (:)) [] (1, max_line)
2158 [ (line, (nm,span)) | (nm,span) <- ticks,
2159 line <- srcSpanLines span ]
2161 max_line = foldr max 0 (map GHC.srcSpanEndLine (map snd ticks))
2162 srcSpanLines span = [ GHC.srcSpanStartLine span ..
2163 GHC.srcSpanEndLine span ]
2165 lookupModule :: String -> GHCi Module
2166 lookupModule modName
2167 = do session <- getSession
2168 io (GHC.findModule session (GHC.mkModuleName modName) Nothing)
2170 -- don't reset the counter back to zero?
2171 discardActiveBreakPoints :: GHCi ()
2172 discardActiveBreakPoints = do
2174 mapM (turnOffBreak.snd) (breaks st)
2175 setGHCiState $ st { breaks = [] }
2177 deleteBreak :: Int -> GHCi ()
2178 deleteBreak identity = do
2180 let oldLocations = breaks st
2181 (this,rest) = partition (\loc -> fst loc == identity) oldLocations
2183 then printForUser (text "Breakpoint" <+> ppr identity <+>
2184 text "does not exist")
2186 mapM (turnOffBreak.snd) this
2187 setGHCiState $ st { breaks = rest }
2189 turnOffBreak :: BreakLocation -> GHCi Bool
2190 turnOffBreak loc = do
2191 (arr, _) <- getModBreak (breakModule loc)
2192 io $ setBreakFlag False arr (breakTick loc)
2194 getModBreak :: Module -> GHCi (GHC.BreakArray, Array Int SrcSpan)
2195 getModBreak mod = do
2196 session <- getSession
2197 Just mod_info <- io $ GHC.getModuleInfo session mod
2198 let modBreaks = GHC.modInfoModBreaks mod_info
2199 let array = GHC.modBreaks_flags modBreaks
2200 let ticks = GHC.modBreaks_locs modBreaks
2201 return (array, ticks)
2203 setBreakFlag :: Bool -> GHC.BreakArray -> Int -> IO Bool
2204 setBreakFlag toggle array index
2205 | toggle = GHC.setBreakOn array index
2206 | otherwise = GHC.setBreakOff array index