1 {-# OPTIONS -#include "Linker.h" #-}
2 -----------------------------------------------------------------------------
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2005-2006
8 -----------------------------------------------------------------------------
9 module InteractiveUI ( interactiveUI, ghciWelcomeMsg ) where
11 #include "HsVersions.h"
19 import GHC ( Session, LoadHowMuch(..), Target(..), TargetId(..),
20 Type, Module, ModuleName, TyThing(..), Phase,
21 BreakIndex, SrcSpan, Resume, SingleStep )
27 import Outputable hiding (printForUser)
28 import Module -- for ModuleEnv
31 -- Other random utilities
33 import BasicTypes hiding (isTopLevel)
34 import Panic hiding (showException)
41 #ifndef mingw32_HOST_OS
42 import System.Posix hiding (getEnv)
44 import GHC.ConsoleHandler ( flushConsole )
45 import System.Win32 ( setConsoleCP, setConsoleOutputCP )
46 import qualified System.Win32
50 import Control.Concurrent ( yield ) -- Used in readline loop
51 import System.Console.Readline as Readline
56 import Control.Exception as Exception
57 -- import Control.Concurrent
59 import qualified Data.ByteString.Char8 as BS
63 import System.Environment
64 import System.Exit ( exitWith, ExitCode(..) )
65 import System.Directory
67 import System.IO.Error as IO
71 import Control.Monad as Monad
74 import Foreign.StablePtr ( newStablePtr )
75 import GHC.Exts ( unsafeCoerce# )
76 import GHC.IOBase ( IOErrorType(InvalidArgument) )
78 import Data.IORef ( IORef, readIORef, writeIORef )
80 import System.Posix.Internals ( setNonBlockingFD )
82 -----------------------------------------------------------------------------
84 ghciWelcomeMsg :: String
85 ghciWelcomeMsg = "GHCi, version " ++ cProjectVersion ++
86 ": http://www.haskell.org/ghc/ :? for help"
88 type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
91 GLOBAL_VAR(commands, builtin_commands, [Command])
93 builtin_commands :: [Command]
95 -- Hugs users are accustomed to :e, so make sure it doesn't overlap
96 ("?", keepGoing help, False, completeNone),
97 ("add", keepGoingPaths addModule, False, completeFilename),
98 ("abandon", keepGoing abandonCmd, False, completeNone),
99 ("break", keepGoing breakCmd, False, completeIdentifier),
100 ("back", keepGoing backCmd, False, completeNone),
101 ("browse", keepGoing browseCmd, False, completeModule),
102 ("cd", keepGoing changeDirectory, False, completeFilename),
103 ("check", keepGoing checkModule, False, completeHomeModule),
104 ("continue", keepGoing continueCmd, False, completeNone),
105 ("cmd", keepGoing cmdCmd, False, completeIdentifier),
106 ("ctags", keepGoing createCTagsFileCmd, False, completeFilename),
107 ("def", keepGoing defineMacro, False, completeIdentifier),
108 ("delete", keepGoing deleteCmd, False, completeNone),
109 ("e", keepGoing editFile, False, completeFilename),
110 ("edit", keepGoing editFile, False, completeFilename),
111 ("etags", keepGoing createETagsFileCmd, False, completeFilename),
112 ("force", keepGoing forceCmd, False, completeIdentifier),
113 ("forward", keepGoing forwardCmd, False, completeNone),
114 ("help", keepGoing help, False, completeNone),
115 ("history", keepGoing historyCmd, False, completeNone),
116 ("info", keepGoing info, False, completeIdentifier),
117 ("kind", keepGoing kindOfType, False, completeIdentifier),
118 ("load", keepGoingPaths loadModule_, False, completeHomeModuleOrFile),
119 ("list", keepGoing listCmd, False, completeNone),
120 ("module", keepGoing setContext, False, completeModule),
121 ("main", keepGoing runMain, False, completeIdentifier),
122 ("print", keepGoing printCmd, False, completeIdentifier),
123 ("quit", quit, False, completeNone),
124 ("reload", keepGoing reloadModule, False, completeNone),
125 ("set", keepGoing setCmd, True, completeSetOptions),
126 ("show", keepGoing showCmd, False, completeNone),
127 ("sprint", keepGoing sprintCmd, False, completeIdentifier),
128 ("step", keepGoing stepCmd, False, completeIdentifier),
129 ("type", keepGoing typeOfExpr, False, completeIdentifier),
130 ("trace", keepGoing traceCmd, False, completeIdentifier),
131 ("undef", keepGoing undefineMacro, False, completeMacro),
132 ("unset", keepGoing unsetOptions, True, completeSetOptions)
135 keepGoing :: (String -> GHCi ()) -> (String -> GHCi Bool)
136 keepGoing a str = a str >> return False
138 keepGoingPaths :: ([FilePath] -> GHCi ()) -> (String -> GHCi Bool)
139 keepGoingPaths a str = a (toArgs str) >> return False
141 shortHelpText = "use :? for help.\n"
144 " Commands available from the prompt:\n" ++
146 " <statement> evaluate/run <statement>\n" ++
147 " :add <filename> ... add module(s) to the current target set\n" ++
148 " :browse [*]<module> display the names defined by <module>\n" ++
149 " :cd <dir> change directory to <dir>\n" ++
150 " :cmd <expr> run the commands returned by <expr>::IO String\n" ++
151 " :ctags [<file>] create tags file for Vi (default: \"tags\")\n" ++
152 " :def <cmd> <expr> define a command :<cmd>\n" ++
153 " :edit <file> edit file\n" ++
154 " :edit edit last module\n" ++
155 " :etags [<file>] create tags file for Emacs (default: \"TAGS\")\n" ++
156 " :help, :? display this list of commands\n" ++
157 " :info [<name> ...] display information about the given names\n" ++
158 " :kind <type> show the kind of <type>\n" ++
159 " :load <filename> ... load module(s) and their dependents\n" ++
160 " :module [+/-] [*]<mod> ... set the context for expression evaluation\n" ++
161 " :main [<arguments> ...] run the main function with the given arguments\n" ++
162 " :quit exit GHCi\n" ++
163 " :reload reload the current module set\n" ++
164 " :type <expr> show the type of <expr>\n" ++
165 " :undef <cmd> undefine user-defined command :<cmd>\n" ++
166 " :!<command> run the shell command <command>\n" ++
168 " -- Commands for debugging:\n" ++
170 " :abandon at a breakpoint, abandon current computation\n" ++
171 " :back go back in the history (after :trace)\n" ++
172 " :break [<mod>] <l> [<col>] set a breakpoint at the specified location\n" ++
173 " :break <name> set a breakpoint on the specified function\n" ++
174 " :continue resume after a breakpoint\n" ++
175 " :delete <number> delete the specified breakpoint\n" ++
176 " :delete * delete all breakpoints\n" ++
177 " :force <expr> print <expr>, forcing unevaluated parts\n" ++
178 " :forward go forward in the history (after :back)\n" ++
179 " :history [<n>] show the last <n> items in the history (after :trace)\n" ++
180 " :print [<name> ...] prints a value without forcing its computation\n" ++
181 " :sprint [<name> ...] simplifed version of :print\n" ++
182 " :step single-step after stopping at a breakpoint\n"++
183 " :step <expr> single-step into <expr>\n"++
184 " :trace trace after stopping at a breakpoint\n"++
185 " :trace <expr> trace into <expr> (remembers breakpoints for :history)\n"++
188 " -- Commands for changing settings:\n" ++
190 " :set <option> ... set options\n" ++
191 " :set args <arg> ... set the arguments returned by System.getArgs\n" ++
192 " :set prog <progname> set the value returned by System.getProgName\n" ++
193 " :set prompt <prompt> set the prompt used in GHCi\n" ++
194 " :set editor <cmd> set the command used for :edit\n" ++
195 " :set stop <cmd> set the command to run when a breakpoint is hit\n" ++
196 " :unset <option> ... unset options\n" ++
198 " Options for ':set' and ':unset':\n" ++
200 " +r revert top-level expressions after each evaluation\n" ++
201 " +s print timing/memory stats after each evaluation\n" ++
202 " +t print type after evaluation\n" ++
203 " -<flags> most GHC command line flags can also be set here\n" ++
204 " (eg. -v2, -fglasgow-exts, etc.)\n" ++
206 " -- Commands for displaying information:\n" ++
208 " :show bindings show the current bindings made at the prompt\n" ++
209 " :show breaks show the active breakpoints\n" ++
210 " :show context show the breakpoint context\n" ++
211 " :show modules show the currently loaded modules\n" ++
212 " :show <setting> show anything that can be set with :set (e.g. args)\n" ++
219 win <- System.Win32.getWindowsDirectory
220 return (win `joinFileName` "notepad.exe")
225 interactiveUI :: Session -> [(FilePath, Maybe Phase)] -> Maybe String -> IO ()
226 interactiveUI session srcs maybe_expr = do
227 -- HACK! If we happen to get into an infinite loop (eg the user
228 -- types 'let x=x in x' at the prompt), then the thread will block
229 -- on a blackhole, and become unreachable during GC. The GC will
230 -- detect that it is unreachable and send it the NonTermination
231 -- exception. However, since the thread is unreachable, everything
232 -- it refers to might be finalized, including the standard Handles.
233 -- This sounds like a bug, but we don't have a good solution right
239 -- Initialise buffering for the *interpreted* I/O system
240 initInterpBuffering session
242 when (isNothing maybe_expr) $ do
243 -- Only for GHCi (not runghc and ghc -e):
245 -- Turn buffering off for the compiled program's stdout/stderr
247 -- Turn buffering off for GHCi's stdout
249 hSetBuffering stdout NoBuffering
250 -- We don't want the cmd line to buffer any input that might be
251 -- intended for the program, so unbuffer stdin.
252 hSetBuffering stdin NoBuffering
254 -- initial context is just the Prelude
255 prel_mod <- GHC.findModule session prel_name (Just basePackageId)
256 GHC.setContext session [] [prel_mod]
260 Readline.setAttemptedCompletionFunction (Just completeWord)
261 --Readline.parseAndBind "set show-all-if-ambiguous 1"
263 let symbols = "!#$%&*+/<=>?@\\^|-~"
264 specials = "(),;[]`{}"
266 word_break_chars = spaces ++ specials ++ symbols
268 Readline.setBasicWordBreakCharacters word_break_chars
269 Readline.setCompleterWordBreakCharacters word_break_chars
272 default_editor <- findEditor
274 startGHCi (runGHCi srcs maybe_expr)
275 GHCiState{ progname = "<interactive>",
279 editor = default_editor,
285 tickarrays = emptyModuleEnv,
290 Readline.resetTerminal Nothing
295 prel_name = GHC.mkModuleName "Prelude"
297 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe String -> GHCi ()
298 runGHCi paths maybe_expr = do
299 let read_dot_files = not opt_IgnoreDotGhci
301 when (read_dot_files) $ do
304 exists <- io (doesFileExist file)
306 dir_ok <- io (checkPerms ".")
307 file_ok <- io (checkPerms file)
308 when (dir_ok && file_ok) $ do
309 either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
312 Right hdl -> fileLoop hdl False
314 when (read_dot_files) $ do
315 -- Read in $HOME/.ghci
316 either_dir <- io (IO.try (getEnv "HOME"))
320 cwd <- io (getCurrentDirectory)
321 when (dir /= cwd) $ do
322 let file = dir ++ "/.ghci"
323 ok <- io (checkPerms file)
325 either_hdl <- io (IO.try (openFile file ReadMode))
328 Right hdl -> fileLoop hdl False
330 -- Perform a :load for files given on the GHCi command line
331 -- When in -e mode, if the load fails then we want to stop
332 -- immediately rather than going on to evaluate the expression.
333 when (not (null paths)) $ do
334 ok <- ghciHandle (\e -> do showException e; return Failed) $
336 when (isJust maybe_expr && failed ok) $
337 io (exitWith (ExitFailure 1))
339 -- if verbosity is greater than 0, or we are connected to a
340 -- terminal, display the prompt in the interactive loop.
341 is_tty <- io (hIsTerminalDevice stdin)
342 dflags <- getDynFlags
343 let show_prompt = verbosity dflags > 0 || is_tty
348 #if defined(mingw32_HOST_OS)
349 -- The win32 Console API mutates the first character of
350 -- type-ahead when reading from it in a non-buffered manner. Work
351 -- around this by flushing the input buffer of type-ahead characters,
352 -- but only if stdin is available.
353 flushed <- io (IO.try (GHC.ConsoleHandler.flushConsole stdin))
355 Left err | isDoesNotExistError err -> return ()
356 | otherwise -> io (ioError err)
357 Right () -> return ()
359 -- initialise the console if necessary
362 -- enter the interactive loop
363 interactiveLoop is_tty show_prompt
365 -- just evaluate the expression we were given
370 io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
373 interactiveLoop is_tty show_prompt =
374 -- Ignore ^C exceptions caught here
375 ghciHandleDyn (\e -> case e of
377 #if defined(mingw32_HOST_OS)
380 interactiveLoop is_tty show_prompt
381 _other -> return ()) $
383 ghciUnblock $ do -- unblock necessary if we recursed from the
384 -- exception handler above.
386 -- read commands from stdin
390 else fileLoop stdin show_prompt
392 fileLoop stdin show_prompt
396 -- NOTE: We only read .ghci files if they are owned by the current user,
397 -- and aren't world writable. Otherwise, we could be accidentally
398 -- running code planted by a malicious third party.
400 -- Furthermore, We only read ./.ghci if . is owned by the current user
401 -- and isn't writable by anyone else. I think this is sufficient: we
402 -- don't need to check .. and ../.. etc. because "." always refers to
403 -- the same directory while a process is running.
405 checkPerms :: String -> IO Bool
407 #ifdef mingw32_HOST_OS
410 Util.handle (\_ -> return False) $ do
411 st <- getFileStatus name
413 if fileOwner st /= me then do
414 putStrLn $ "WARNING: " ++ name ++ " is owned by someone else, IGNORING!"
417 let mode = fileMode st
418 if (groupWriteMode == (mode `intersectFileModes` groupWriteMode))
419 || (otherWriteMode == (mode `intersectFileModes` otherWriteMode))
421 putStrLn $ "*** WARNING: " ++ name ++
422 " is writable by someone else, IGNORING!"
427 fileLoop :: Handle -> Bool -> GHCi ()
428 fileLoop hdl show_prompt = do
429 when show_prompt $ do
432 l <- io (IO.try (hGetLine hdl))
434 Left e | isEOFError e -> return ()
435 | InvalidArgument <- etype -> return ()
436 | otherwise -> io (ioError e)
437 where etype = ioeGetErrorType e
438 -- treat InvalidArgument in the same way as EOF:
439 -- this can happen if the user closed stdin, or
440 -- perhaps did getContents which closes stdin at
443 case removeSpaces l of
444 "" -> fileLoop hdl show_prompt
445 l -> do quit <- runCommands l
446 if quit then return () else fileLoop hdl show_prompt
449 session <- getSession
450 (toplevs,exports) <- io (GHC.getContext session)
451 resumes <- io $ GHC.getResumeContext session
457 let ix = GHC.resumeHistoryIx r
459 then return (brackets (ppr (GHC.resumeSpan r)) <> space)
461 let hist = GHC.resumeHistory r !! (ix-1)
462 span <- io $ GHC.getHistorySpan session hist
463 return (brackets (ppr (negate ix) <> char ':'
464 <+> ppr span) <> space)
466 dots | r:rs <- resumes, not (null rs) = text "... "
470 hsep (map (\m -> char '*' <> ppr (GHC.moduleName m)) toplevs) <+>
471 hsep (map (ppr . GHC.moduleName) exports)
473 deflt_prompt = dots <> context_bit <> modules_bit
475 f ('%':'s':xs) = deflt_prompt <> f xs
476 f ('%':'%':xs) = char '%' <> f xs
477 f (x:xs) = char x <> f xs
481 return (showSDoc (f (prompt st)))
485 readlineLoop :: GHCi ()
487 session <- getSession
488 (mod,imports) <- io (GHC.getContext session)
490 saveSession -- for use by completion
492 mb_span <- getCurrentBreakSpan
494 l <- io (readline prompt `finally` setNonBlockingFD 0)
495 -- readline sometimes puts stdin into blocking mode,
496 -- so we need to put it back for the IO library
501 case removeSpaces l of
505 quit <- runCommands l
506 if quit then return () else readlineLoop
509 runCommands :: String -> GHCi Bool
511 q <- ghciHandle handler (doCommand cmd)
512 if q then return True else runNext
518 c:cs -> do setGHCiState st{ cmdqueue = cs }
521 doCommand (':' : cmd) = specialCommand cmd
522 doCommand stmt = do timeIt $ runStmt stmt GHC.RunToCompletion
525 enqueueCommands :: [String] -> GHCi ()
526 enqueueCommands cmds = do
528 setGHCiState st{ cmdqueue = cmds ++ cmdqueue st }
531 -- This version is for the GHC command-line option -e. The only difference
532 -- from runCommand is that it catches the ExitException exception and
533 -- exits, rather than printing out the exception.
534 runCommandEval c = ghciHandle handleEval (doCommand c)
536 handleEval (ExitException code) = io (exitWith code)
537 handleEval e = do handler e
538 io (exitWith (ExitFailure 1))
540 doCommand (':' : command) = specialCommand command
542 = do r <- runStmt stmt GHC.RunToCompletion
544 False -> io (exitWith (ExitFailure 1))
545 -- failure to run the command causes exit(1) for ghc -e.
548 runStmt :: String -> SingleStep -> GHCi Bool
550 | null (filter (not.isSpace) stmt) = return False
551 | ["import", mod] <- words stmt = keepGoing setContext ('+':mod)
553 = do st <- getGHCiState
554 session <- getSession
555 result <- io $ withProgName (progname st) $ withArgs (args st) $
556 GHC.runStmt session stmt step
560 afterRunStmt :: GHC.RunResult -> GHCi Bool
561 -- False <=> the statement failed to compile
562 afterRunStmt (GHC.RunException e) = throw e
563 afterRunStmt run_result = do
564 session <- getSession
566 GHC.RunOk names -> do
567 show_types <- isOptionSet ShowType
568 when show_types $ printTypeOfNames session names
569 GHC.RunBreak _ names mb_info -> do
570 resumes <- io $ GHC.getResumeContext session
571 printForUser $ ptext SLIT("Stopped at") <+>
572 ppr (GHC.resumeSpan (head resumes))
573 printTypeOfNames session names
574 maybe (return ()) runBreakCmd mb_info
575 -- run the command set with ":set stop <cmd>"
577 enqueueCommands [stop st]
582 io installSignalHandlers
583 b <- isOptionSet RevertCAFs
584 io (when b revertCAFs)
586 return (case run_result of GHC.RunOk _ -> True; _ -> False)
588 runBreakCmd :: GHC.BreakInfo -> GHCi ()
589 runBreakCmd info = do
590 let mod = GHC.breakInfo_module info
591 nm = GHC.breakInfo_number info
593 case [ loc | (i,loc) <- breaks st,
594 breakModule loc == mod, breakTick loc == nm ] of
596 loc:_ | null cmd -> return ()
597 | otherwise -> do enqueueCommands [cmd]; return ()
598 where cmd = onBreakCmd loc
600 printTypeOfNames :: Session -> [Name] -> GHCi ()
601 printTypeOfNames session names
602 = mapM_ (printTypeOfName session) $ sortBy compareNames names
604 compareNames :: Name -> Name -> Ordering
605 n1 `compareNames` n2 = compareWith n1 `compare` compareWith n2
606 where compareWith n = (getOccString n, getSrcSpan n)
608 printTypeOfName :: Session -> Name -> GHCi ()
609 printTypeOfName session n
610 = do maybe_tything <- io (GHC.lookupName session n)
611 case maybe_tything of
613 Just thing -> printTyThing thing
615 specialCommand :: String -> GHCi Bool
616 specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
617 specialCommand str = do
618 let (cmd,rest) = break isSpace str
619 maybe_cmd <- io (lookupCommand cmd)
621 Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
622 ++ shortHelpText) >> return False)
623 Just (_,f,_,_) -> f (dropWhile isSpace rest)
625 lookupCommand :: String -> IO (Maybe Command)
626 lookupCommand str = do
627 cmds <- readIORef commands
628 -- look for exact match first, then the first prefix match
629 case [ c | c <- cmds, str == cmdName c ] of
630 c:_ -> return (Just c)
631 [] -> case [ c | c@(s,_,_,_) <- cmds, str `isPrefixOf` s ] of
633 c:_ -> return (Just c)
636 getCurrentBreakSpan :: GHCi (Maybe SrcSpan)
637 getCurrentBreakSpan = do
638 session <- getSession
639 resumes <- io $ GHC.getResumeContext session
643 let ix = GHC.resumeHistoryIx r
645 then return (Just (GHC.resumeSpan r))
647 let hist = GHC.resumeHistory r !! (ix-1)
648 span <- io $ GHC.getHistorySpan session hist
651 -----------------------------------------------------------------------------
654 noArgs :: GHCi () -> String -> GHCi ()
656 noArgs m _ = io $ putStrLn "This command takes no arguments"
658 help :: String -> GHCi ()
659 help _ = io (putStr helpText)
661 info :: String -> GHCi ()
662 info "" = throwDyn (CmdLineError "syntax: ':i <thing-you-want-info-about>'")
663 info s = do { let names = words s
664 ; session <- getSession
665 ; dflags <- getDynFlags
666 ; let pefas = dopt Opt_PrintExplicitForalls dflags
667 ; mapM_ (infoThing pefas session) names }
669 infoThing pefas session str = io $ do
670 names <- GHC.parseName session str
671 let filtered = filterOutChildren names
672 mb_stuffs <- mapM (GHC.getInfo session) filtered
673 unqual <- GHC.getPrintUnqual session
674 putStrLn (showSDocForUser unqual $
675 vcat (intersperse (text "") $
676 [ pprInfo pefas stuff | Just stuff <- mb_stuffs ]))
678 -- Filter out names whose parent is also there Good
679 -- example is '[]', which is both a type and data
680 -- constructor in the same type
681 filterOutChildren :: [Name] -> [Name]
682 filterOutChildren names = filter (not . parent_is_there) names
683 where parent_is_there n
684 -- | Just p <- GHC.nameParent_maybe n = p `elem` names
688 pprInfo :: PrintExplicitForalls -> (TyThing, Fixity, [GHC.Instance]) -> SDoc
689 pprInfo pefas (thing, fixity, insts)
690 = pprTyThingInContextLoc pefas thing
691 $$ show_fixity fixity
692 $$ vcat (map GHC.pprInstance insts)
695 | fix == GHC.defaultFixity = empty
696 | otherwise = ppr fix <+> ppr (GHC.getName thing)
698 runMain :: String -> GHCi ()
700 let ss = concat $ intersperse "," (map (\ s -> ('"':s)++"\"") (toArgs args))
701 enqueueCommands ['[': ss ++ "] `System.Environment.withArgs` main"]
703 addModule :: [FilePath] -> GHCi ()
705 io (revertCAFs) -- always revert CAFs on load/add.
706 files <- mapM expandPath files
707 targets <- mapM (\m -> io (GHC.guessTarget m Nothing)) files
708 session <- getSession
709 io (mapM_ (GHC.addTarget session) targets)
710 ok <- io (GHC.load session LoadAllTargets)
713 changeDirectory :: String -> GHCi ()
714 changeDirectory dir = do
715 session <- getSession
716 graph <- io (GHC.getModuleGraph session)
717 when (not (null graph)) $
718 io $ putStr "Warning: changing directory causes all loaded modules to be unloaded,\nbecause the search path has changed.\n"
719 io (GHC.setTargets session [])
720 io (GHC.load session LoadAllTargets)
721 setContextAfterLoad session []
722 io (GHC.workingDirectoryChanged session)
723 dir <- expandPath dir
724 io (setCurrentDirectory dir)
726 editFile :: String -> GHCi ()
728 do file <- if null str then chooseEditFile else return str
732 $ throwDyn (CmdLineError "editor not set, use :set editor")
733 io $ system (cmd ++ ' ':file)
736 -- The user didn't specify a file so we pick one for them.
737 -- Our strategy is to pick the first module that failed to load,
738 -- or otherwise the first target.
740 -- XXX: Can we figure out what happened if the depndecy analysis fails
741 -- (e.g., because the porgrammeer mistyped the name of a module)?
742 -- XXX: Can we figure out the location of an error to pass to the editor?
743 -- XXX: if we could figure out the list of errors that occured during the
744 -- last load/reaload, then we could start the editor focused on the first
746 chooseEditFile :: GHCi String
748 do session <- getSession
749 let hasFailed x = io $ fmap not $ GHC.isLoaded session $ GHC.ms_mod_name x
751 graph <- io (GHC.getModuleGraph session)
752 failed_graph <- filterM hasFailed graph
753 let order g = flattenSCCs $ GHC.topSortModuleGraph True g Nothing
755 x : _ -> GHC.ml_hs_file (GHC.ms_location x)
758 case pick (order failed_graph) of
759 Just file -> return file
761 do targets <- io (GHC.getTargets session)
762 case msum (map fromTarget targets) of
763 Just file -> return file
764 Nothing -> throwDyn (CmdLineError "No files to edit.")
766 where fromTarget (GHC.Target (GHC.TargetFile f _) _) = Just f
767 fromTarget _ = Nothing -- when would we get a module target?
769 defineMacro :: String -> GHCi ()
771 let (macro_name, definition) = break isSpace s
772 cmds <- io (readIORef commands)
774 then throwDyn (CmdLineError "invalid macro name")
776 if (macro_name `elem` map cmdName cmds)
777 then throwDyn (CmdLineError
778 ("command '" ++ macro_name ++ "' is already defined"))
781 -- give the expression a type signature, so we can be sure we're getting
782 -- something of the right type.
783 let new_expr = '(' : definition ++ ") :: String -> IO String"
785 -- compile the expression
787 maybe_hv <- io (GHC.compileExpr cms new_expr)
790 Just hv -> io (writeIORef commands --
791 (cmds ++ [(macro_name, runMacro hv, False, completeNone)]))
793 runMacro :: GHC.HValue{-String -> IO String-} -> String -> GHCi Bool
795 str <- io ((unsafeCoerce# fun :: String -> IO String) s)
796 enqueueCommands (lines str)
799 undefineMacro :: String -> GHCi ()
800 undefineMacro macro_name = do
801 cmds <- io (readIORef commands)
802 if (macro_name `elem` map cmdName builtin_commands)
803 then throwDyn (CmdLineError
804 ("command '" ++ macro_name ++ "' cannot be undefined"))
806 if (macro_name `notElem` map cmdName cmds)
807 then throwDyn (CmdLineError
808 ("command '" ++ macro_name ++ "' not defined"))
810 io (writeIORef commands (filter ((/= macro_name) . cmdName) cmds))
812 cmdCmd :: String -> GHCi ()
814 let expr = '(' : str ++ ") :: IO String"
815 session <- getSession
816 maybe_hv <- io (GHC.compileExpr session expr)
820 cmds <- io $ (unsafeCoerce# hv :: IO String)
821 enqueueCommands (lines cmds)
824 loadModule :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
825 loadModule fs = timeIt (loadModule' fs)
827 loadModule_ :: [FilePath] -> GHCi ()
828 loadModule_ fs = do loadModule (zip fs (repeat Nothing)); return ()
830 loadModule' :: [(FilePath, Maybe Phase)] -> GHCi SuccessFlag
831 loadModule' files = do
832 session <- getSession
835 discardActiveBreakPoints
836 io (GHC.setTargets session [])
837 io (GHC.load session LoadAllTargets)
840 let (filenames, phases) = unzip files
841 exp_filenames <- mapM expandPath filenames
842 let files' = zip exp_filenames phases
843 targets <- io (mapM (uncurry GHC.guessTarget) files')
845 -- NOTE: we used to do the dependency anal first, so that if it
846 -- fails we didn't throw away the current set of modules. This would
847 -- require some re-working of the GHC interface, so we'll leave it
848 -- as a ToDo for now.
850 io (GHC.setTargets session targets)
851 doLoad session LoadAllTargets
853 checkModule :: String -> GHCi ()
855 let modl = GHC.mkModuleName m
856 session <- getSession
857 result <- io (GHC.checkModule session modl False)
859 Nothing -> io $ putStrLn "Nothing"
860 Just r -> io $ putStrLn (showSDoc (
861 case GHC.checkedModuleInfo r of
862 Just cm | Just scope <- GHC.modInfoTopLevelScope cm ->
864 (local,global) = partition ((== modl) . GHC.moduleName . GHC.nameModule) scope
866 (text "global names: " <+> ppr global) $$
867 (text "local names: " <+> ppr local)
869 afterLoad (successIf (isJust result)) session
871 reloadModule :: String -> GHCi ()
873 io (revertCAFs) -- always revert CAFs on reload.
874 discardActiveBreakPoints
875 session <- getSession
876 doLoad session $ if null m then LoadAllTargets
877 else LoadUpTo (GHC.mkModuleName m)
880 doLoad session howmuch = do
881 -- turn off breakpoints before we load: we can't turn them off later, because
882 -- the ModBreaks will have gone away.
883 discardActiveBreakPoints
884 ok <- io (GHC.load session howmuch)
888 afterLoad ok session = do
889 io (revertCAFs) -- always revert CAFs on load.
891 graph <- io (GHC.getModuleGraph session)
892 graph' <- filterM (io . GHC.isLoaded session . GHC.ms_mod_name) graph
893 setContextAfterLoad session graph'
894 modulesLoadedMsg ok (map GHC.ms_mod_name graph')
896 setContextAfterLoad session [] = do
897 prel_mod <- getPrelude
898 io (GHC.setContext session [] [prel_mod])
899 setContextAfterLoad session ms = do
900 -- load a target if one is available, otherwise load the topmost module.
901 targets <- io (GHC.getTargets session)
902 case [ m | Just m <- map (findTarget ms) targets ] of
904 let graph' = flattenSCCs (GHC.topSortModuleGraph True ms Nothing) in
905 load_this (last graph')
910 = case filter (`matches` t) ms of
914 summary `matches` Target (TargetModule m) _
915 = GHC.ms_mod_name summary == m
916 summary `matches` Target (TargetFile f _) _
917 | Just f' <- GHC.ml_hs_file (GHC.ms_location summary) = f == f'
918 summary `matches` target
921 load_this summary | m <- GHC.ms_mod summary = do
922 b <- io (GHC.moduleIsInterpreted session m)
923 if b then io (GHC.setContext session [m] [])
925 prel_mod <- getPrelude
926 io (GHC.setContext session [] [prel_mod,m])
929 modulesLoadedMsg :: SuccessFlag -> [ModuleName] -> GHCi ()
930 modulesLoadedMsg ok mods = do
931 dflags <- getDynFlags
932 when (verbosity dflags > 0) $ do
934 | null mods = text "none."
936 punctuate comma (map ppr mods)) <> text "."
939 io (putStrLn (showSDoc (text "Failed, modules loaded: " <> mod_commas)))
941 io (putStrLn (showSDoc (text "Ok, modules loaded: " <> mod_commas)))
944 typeOfExpr :: String -> GHCi ()
946 = do cms <- getSession
947 maybe_ty <- io (GHC.exprType cms str)
950 Just ty -> do ty' <- cleanType ty
951 printForUser $ text str <> text " :: " <> ppr ty'
953 kindOfType :: String -> GHCi ()
955 = do cms <- getSession
956 maybe_ty <- io (GHC.typeKind cms str)
959 Just ty -> printForUser $ text str <> text " :: " <> ppr ty
961 quit :: String -> GHCi Bool
964 shellEscape :: String -> GHCi Bool
965 shellEscape str = io (system str >> return False)
967 -----------------------------------------------------------------------------
968 -- Browsing a module's contents
970 browseCmd :: String -> GHCi ()
973 ['*':m] | looksLikeModuleName m -> browseModule m False
974 [m] | looksLikeModuleName m -> browseModule m True
975 _ -> throwDyn (CmdLineError "syntax: :browse <module>")
977 browseModule m exports_only = do
979 modl <- if exports_only then lookupModule m
980 else wantInterpretedModule m
982 -- Temporarily set the context to the module we're interested in,
983 -- just so we can get an appropriate PrintUnqualified
984 (as,bs) <- io (GHC.getContext s)
985 prel_mod <- getPrelude
986 io (if exports_only then GHC.setContext s [] [prel_mod,modl]
987 else GHC.setContext s [modl] [])
988 unqual <- io (GHC.getPrintUnqual s)
989 io (GHC.setContext s as bs)
991 mb_mod_info <- io $ GHC.getModuleInfo s modl
993 Nothing -> throwDyn (CmdLineError ("unknown module: " ++ m))
996 | exports_only = GHC.modInfoExports mod_info
997 | otherwise = fromMaybe [] (GHC.modInfoTopLevelScope mod_info)
999 filtered = filterOutChildren names
1001 things <- io $ mapM (GHC.lookupName s) filtered
1003 dflags <- getDynFlags
1004 let pefas = dopt Opt_PrintExplicitForalls dflags
1005 io (putStrLn (showSDocForUser unqual (
1006 vcat (map (pprTyThingInContext pefas) (catMaybes things))
1008 -- ToDo: modInfoInstances currently throws an exception for
1009 -- package modules. When it works, we can do this:
1010 -- $$ vcat (map GHC.pprInstance (GHC.modInfoInstances mod_info))
1012 -----------------------------------------------------------------------------
1013 -- Setting the module context
1016 | all sensible mods = fn mods
1017 | otherwise = throwDyn (CmdLineError "syntax: :module [+/-] [*]M1 ... [*]Mn")
1019 (fn, mods) = case str of
1020 '+':stuff -> (addToContext, words stuff)
1021 '-':stuff -> (removeFromContext, words stuff)
1022 stuff -> (newContext, words stuff)
1024 sensible ('*':m) = looksLikeModuleName m
1025 sensible m = looksLikeModuleName m
1027 separate :: Session -> [String] -> [Module] -> [Module]
1028 -> GHCi ([Module],[Module])
1029 separate session [] as bs = return (as,bs)
1030 separate session (('*':str):ms) as bs = do
1031 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1032 b <- io $ GHC.moduleIsInterpreted session m
1033 if b then separate session ms (m:as) bs
1034 else throwDyn (CmdLineError ("module '"
1035 ++ GHC.moduleNameString (GHC.moduleName m)
1036 ++ "' is not interpreted"))
1037 separate session (str:ms) as bs = do
1038 m <- io $ GHC.findModule session (GHC.mkModuleName str) Nothing
1039 separate session ms as (m:bs)
1041 newContext :: [String] -> GHCi ()
1042 newContext strs = do
1044 (as,bs) <- separate s strs [] []
1045 prel_mod <- getPrelude
1046 let bs' = if null as && prel_mod `notElem` bs then prel_mod:bs else bs
1047 io $ GHC.setContext s as bs'
1050 addToContext :: [String] -> GHCi ()
1051 addToContext strs = do
1053 (as,bs) <- io $ GHC.getContext s
1055 (new_as,new_bs) <- separate s strs [] []
1057 let as_to_add = new_as \\ (as ++ bs)
1058 bs_to_add = new_bs \\ (as ++ bs)
1060 io $ GHC.setContext s (as ++ as_to_add) (bs ++ bs_to_add)
1063 removeFromContext :: [String] -> GHCi ()
1064 removeFromContext strs = do
1066 (as,bs) <- io $ GHC.getContext s
1068 (as_to_remove,bs_to_remove) <- separate s strs [] []
1070 let as' = as \\ (as_to_remove ++ bs_to_remove)
1071 bs' = bs \\ (as_to_remove ++ bs_to_remove)
1073 io $ GHC.setContext s as' bs'
1075 ----------------------------------------------------------------------------
1078 -- set options in the interpreter. Syntax is exactly the same as the
1079 -- ghc command line, except that certain options aren't available (-C,
1082 -- This is pretty fragile: most options won't work as expected. ToDo:
1083 -- figure out which ones & disallow them.
1085 setCmd :: String -> GHCi ()
1087 = do st <- getGHCiState
1088 let opts = options st
1089 io $ putStrLn (showSDoc (
1090 text "options currently set: " <>
1093 else hsep (map (\o -> char '+' <> text (optToStr o)) opts)
1096 = case toArgs str of
1097 ("args":args) -> setArgs args
1098 ("prog":prog) -> setProg prog
1099 ("prompt":prompt) -> setPrompt (after 6)
1100 ("editor":cmd) -> setEditor (after 6)
1101 ("stop":cmd) -> setStop (after 4)
1102 wds -> setOptions wds
1103 where after n = dropWhile isSpace $ drop n $ dropWhile isSpace str
1107 setGHCiState st{ args = args }
1111 setGHCiState st{ progname = prog }
1113 io (hPutStrLn stderr "syntax: :set prog <progname>")
1117 setGHCiState st{ editor = cmd }
1119 setStop str@(c:_) | isDigit c
1120 = do let (nm_str,rest) = break (not.isDigit) str
1123 let old_breaks = breaks st
1124 if all ((/= nm) . fst) old_breaks
1125 then printForUser (text "Breakpoint" <+> ppr nm <+>
1126 text "does not exist")
1128 let new_breaks = map fn old_breaks
1129 fn (i,loc) | i == nm = (i,loc { onBreakCmd = dropWhile isSpace rest })
1130 | otherwise = (i,loc)
1131 setGHCiState st{ breaks = new_breaks }
1134 setGHCiState st{ stop = cmd }
1136 setPrompt value = do
1139 then io $ hPutStrLn stderr $ "syntax: :set prompt <prompt>, currently \"" ++ prompt st ++ "\""
1140 else setGHCiState st{ prompt = remQuotes value }
1142 remQuotes ('\"':xs) | not (null xs) && last xs == '\"' = init xs
1146 do -- first, deal with the GHCi opts (+s, +t, etc.)
1147 let (plus_opts, minus_opts) = partition isPlus wds
1148 mapM_ setOpt plus_opts
1149 -- then, dynamic flags
1150 newDynFlags minus_opts
1152 newDynFlags minus_opts = do
1153 dflags <- getDynFlags
1154 let pkg_flags = packageFlags dflags
1155 (dflags',leftovers) <- io $ GHC.parseDynamicFlags dflags minus_opts
1157 if (not (null leftovers))
1158 then throwDyn (CmdLineError ("unrecognised flags: " ++
1162 new_pkgs <- setDynFlags dflags'
1164 -- if the package flags changed, we should reset the context
1165 -- and link the new packages.
1166 dflags <- getDynFlags
1167 when (packageFlags dflags /= pkg_flags) $ do
1168 io $ hPutStrLn stderr "package flags have changed, ressetting and loading new packages..."
1169 session <- getSession
1170 io (GHC.setTargets session [])
1171 io (GHC.load session LoadAllTargets)
1172 io (linkPackages dflags new_pkgs)
1173 setContextAfterLoad session []
1177 unsetOptions :: String -> GHCi ()
1179 = do -- first, deal with the GHCi opts (+s, +t, etc.)
1180 let opts = words str
1181 (minus_opts, rest1) = partition isMinus opts
1182 (plus_opts, rest2) = partition isPlus rest1
1184 if (not (null rest2))
1185 then io (putStrLn ("unknown option: '" ++ head rest2 ++ "'"))
1188 mapM_ unsetOpt plus_opts
1190 let no_flag ('-':'f':rest) = return ("-fno-" ++ rest)
1191 no_flag f = throwDyn (ProgramError ("don't know how to reverse " ++ f))
1193 no_flags <- mapM no_flag minus_opts
1194 newDynFlags no_flags
1196 isMinus ('-':s) = True
1199 isPlus ('+':s) = True
1203 = case strToGHCiOpt str of
1204 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1205 Just o -> setOption o
1208 = case strToGHCiOpt str of
1209 Nothing -> io (putStrLn ("unknown option: '" ++ str ++ "'"))
1210 Just o -> unsetOption o
1212 strToGHCiOpt :: String -> (Maybe GHCiOption)
1213 strToGHCiOpt "s" = Just ShowTiming
1214 strToGHCiOpt "t" = Just ShowType
1215 strToGHCiOpt "r" = Just RevertCAFs
1216 strToGHCiOpt _ = Nothing
1218 optToStr :: GHCiOption -> String
1219 optToStr ShowTiming = "s"
1220 optToStr ShowType = "t"
1221 optToStr RevertCAFs = "r"
1223 -- ---------------------------------------------------------------------------
1229 ["args"] -> io $ putStrLn (show (args st))
1230 ["prog"] -> io $ putStrLn (show (progname st))
1231 ["prompt"] -> io $ putStrLn (show (prompt st))
1232 ["editor"] -> io $ putStrLn (show (editor st))
1233 ["stop"] -> io $ putStrLn (show (stop st))
1234 ["modules" ] -> showModules
1235 ["bindings"] -> showBindings
1236 ["linker"] -> io showLinkerState
1237 ["breaks"] -> showBkptTable
1238 ["context"] -> showContext
1239 _ -> throwDyn (CmdLineError "syntax: :show [args|prog|prompt|editor|stop|modules|bindings|breaks|context]")
1242 session <- getSession
1243 let show_one ms = do m <- io (GHC.showModule session ms)
1245 graph <- io (GHC.getModuleGraph session)
1246 mapM_ show_one graph
1250 unqual <- io (GHC.getPrintUnqual s)
1251 bindings <- io (GHC.getBindings s)
1252 mapM_ printTyThing $ sortBy compareTyThings bindings
1255 compareTyThings :: TyThing -> TyThing -> Ordering
1256 t1 `compareTyThings` t2 = getName t1 `compareNames` getName t2
1258 printTyThing :: TyThing -> GHCi ()
1259 printTyThing (AnId id) = do
1260 ty' <- cleanType (GHC.idType id)
1261 printForUser $ ppr id <> text " :: " <> ppr ty'
1262 printTyThing _ = return ()
1264 -- if -fglasgow-exts is on we show the foralls, otherwise we don't.
1265 cleanType :: Type -> GHCi Type
1267 dflags <- getDynFlags
1268 if dopt Opt_PrintExplicitForalls dflags
1270 else return $! GHC.dropForAlls ty
1272 showBkptTable :: GHCi ()
1275 printForUser $ prettyLocations (breaks st)
1277 showContext :: GHCi ()
1279 session <- getSession
1280 resumes <- io $ GHC.getResumeContext session
1281 printForUser $ vcat (map pp_resume (reverse resumes))
1284 ptext SLIT("--> ") <> text (GHC.resumeStmt resume)
1285 $$ nest 2 (ptext SLIT("Stopped at") <+> ppr (GHC.resumeSpan resume))
1288 -- -----------------------------------------------------------------------------
1291 completeNone :: String -> IO [String]
1292 completeNone w = return []
1295 completeWord :: String -> Int -> Int -> IO (Maybe (String, [String]))
1296 completeWord w start end = do
1297 line <- Readline.getLineBuffer
1299 ':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
1301 | Just c <- is_cmd line -> do
1302 maybe_cmd <- lookupCommand c
1303 let (n,w') = selectWord (words' 0 line)
1305 Nothing -> return Nothing
1306 Just (_,_,False,complete) -> wrapCompleter complete w
1307 Just (_,_,True,complete) -> let complete' w = do rets <- complete w
1308 return (map (drop n) rets)
1309 in wrapCompleter complete' w'
1311 --printf "complete %s, start = %d, end = %d\n" w start end
1312 wrapCompleter completeIdentifier w
1313 where words' _ [] = []
1314 words' n str = let (w,r) = break isSpace str
1315 (s,r') = span isSpace r
1316 in (n,w):words' (n+length w+length s) r'
1317 -- In a Haskell expression we want to parse 'a-b' as three words
1318 -- where a compiler flag (ie. -fno-monomorphism-restriction) should
1319 -- only be a single word.
1320 selectWord [] = (0,w)
1321 selectWord ((offset,x):xs)
1322 | offset+length x >= start = (start-offset,take (end-offset) x)
1323 | otherwise = selectWord xs
1326 | ((':':w) : _) <- words (dropWhile isSpace line) = Just w
1327 | otherwise = Nothing
1330 cmds <- readIORef commands
1331 return (filter (w `isPrefixOf`) (map (':':) (map cmdName cmds)))
1333 completeMacro w = do
1334 cmds <- readIORef commands
1335 let cmds' = [ cmd | cmd <- map cmdName cmds, cmd `elem` map cmdName builtin_commands ]
1336 return (filter (w `isPrefixOf`) cmds')
1338 completeIdentifier w = do
1340 rdrs <- GHC.getRdrNamesInScope s
1341 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) rdrs))
1343 completeModule w = do
1345 dflags <- GHC.getSessionDynFlags s
1346 let pkg_mods = allExposedModules dflags
1347 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) pkg_mods))
1349 completeHomeModule w = do
1351 g <- GHC.getModuleGraph s
1352 let home_mods = map GHC.ms_mod_name g
1353 return (filter (w `isPrefixOf`) (map (showSDoc.ppr) home_mods))
1355 completeSetOptions w = do
1356 return (filter (w `isPrefixOf`) options)
1357 where options = "args":"prog":allFlags
1359 completeFilename = Readline.filenameCompletionFunction
1361 completeHomeModuleOrFile = unionComplete completeHomeModule completeFilename
1363 unionComplete :: (String -> IO [String]) -> (String -> IO [String]) -> String -> IO [String]
1364 unionComplete f1 f2 w = do
1369 wrapCompleter :: (String -> IO [String]) -> String -> IO (Maybe (String,[String]))
1370 wrapCompleter fun w = do
1373 [] -> return Nothing
1374 [x] -> return (Just (x,[]))
1375 xs -> case getCommonPrefix xs of
1376 "" -> return (Just ("",xs))
1377 pref -> return (Just (pref,xs))
1379 getCommonPrefix :: [String] -> String
1380 getCommonPrefix [] = ""
1381 getCommonPrefix (s:ss) = foldl common s ss
1382 where common s "" = ""
1384 common (c:cs) (d:ds)
1385 | c == d = c : common cs ds
1388 allExposedModules :: DynFlags -> [ModuleName]
1389 allExposedModules dflags
1390 = map GHC.mkModuleName (concat (map exposedModules (filter exposed (eltsUFM pkg_db))))
1392 pkg_db = pkgIdMap (pkgState dflags)
1394 completeCmd = completeNone
1395 completeMacro = completeNone
1396 completeIdentifier = completeNone
1397 completeModule = completeNone
1398 completeHomeModule = completeNone
1399 completeSetOptions = completeNone
1400 completeFilename = completeNone
1401 completeHomeModuleOrFile=completeNone
1402 completeBkpt = completeNone
1405 -- ---------------------------------------------------------------------------
1406 -- User code exception handling
1408 -- This is the exception handler for exceptions generated by the
1409 -- user's code and exceptions coming from children sessions;
1410 -- it normally just prints out the exception. The
1411 -- handler must be recursive, in case showing the exception causes
1412 -- more exceptions to be raised.
1414 -- Bugfix: if the user closed stdout or stderr, the flushing will fail,
1415 -- raising another exception. We therefore don't put the recursive
1416 -- handler arond the flushing operation, so if stderr is closed
1417 -- GHCi will just die gracefully rather than going into an infinite loop.
1418 handler :: Exception -> GHCi Bool
1420 handler exception = do
1422 io installSignalHandlers
1423 ghciHandle handler (showException exception >> return False)
1425 showException (DynException dyn) =
1426 case fromDynamic dyn of
1427 Nothing -> io (putStrLn ("*** Exception: (unknown)"))
1428 Just Interrupted -> io (putStrLn "Interrupted.")
1429 Just (CmdLineError s) -> io (putStrLn s) -- omit the location for CmdLineError
1430 Just ph@PhaseFailed{} -> io (putStrLn (showGhcException ph "")) -- ditto
1431 Just other_ghc_ex -> io (print other_ghc_ex)
1433 showException other_exception
1434 = io (putStrLn ("*** Exception: " ++ show other_exception))
1436 -----------------------------------------------------------------------------
1437 -- recursive exception handlers
1439 -- Don't forget to unblock async exceptions in the handler, or if we're
1440 -- in an exception loop (eg. let a = error a in a) the ^C exception
1441 -- may never be delivered. Thanks to Marcin for pointing out the bug.
1443 ghciHandle :: (Exception -> GHCi a) -> GHCi a -> GHCi a
1444 ghciHandle h (GHCi m) = GHCi $ \s ->
1445 Exception.catch (m s)
1446 (\e -> unGHCi (ghciUnblock (h e)) s)
1448 ghciUnblock :: GHCi a -> GHCi a
1449 ghciUnblock (GHCi a) = GHCi $ \s -> Exception.unblock (a s)
1452 -- ----------------------------------------------------------------------------
1455 expandPath :: String -> GHCi String
1457 case dropWhile isSpace path of
1459 tilde <- io (getEnv "HOME") -- will fail if HOME not defined
1460 return (tilde ++ '/':d)
1464 wantInterpretedModule :: String -> GHCi Module
1465 wantInterpretedModule str = do
1466 session <- getSession
1467 modl <- lookupModule str
1468 is_interpreted <- io (GHC.moduleIsInterpreted session modl)
1469 when (not is_interpreted) $
1470 throwDyn (CmdLineError ("module '" ++ str ++ "' is not interpreted"))
1473 wantNameFromInterpretedModule noCanDo str and_then = do
1474 session <- getSession
1475 names <- io $ GHC.parseName session str
1479 let modl = GHC.nameModule n
1480 if not (GHC.isExternalName n)
1481 then noCanDo n $ ppr n <>
1482 text " is not defined in an interpreted module"
1484 is_interpreted <- io (GHC.moduleIsInterpreted session modl)
1485 if not is_interpreted
1486 then noCanDo n $ text "module " <> ppr modl <>
1487 text " is not interpreted"
1490 -- ----------------------------------------------------------------------------
1491 -- Windows console setup
1493 setUpConsole :: IO ()
1495 #ifdef mingw32_HOST_OS
1496 -- On Windows we need to set a known code page, otherwise the characters
1497 -- we read from the console will be be in some strange encoding, and
1498 -- similarly for characters we write to the console.
1500 -- At the moment, GHCi pretends all input is Latin-1. In the
1501 -- future we should support UTF-8, but for now we set the code pages
1504 -- It seems you have to set the font in the console window to
1505 -- a Unicode font in order for output to work properly,
1506 -- otherwise non-ASCII characters are mapped wrongly. sigh.
1507 -- (see MSDN for SetConsoleOutputCP()).
1509 setConsoleCP 28591 -- ISO Latin-1
1510 setConsoleOutputCP 28591 -- ISO Latin-1
1514 -- -----------------------------------------------------------------------------
1515 -- commands for debugger
1517 sprintCmd = pprintCommand False False
1518 printCmd = pprintCommand True False
1519 forceCmd = pprintCommand False True
1521 pprintCommand bind force str = do
1522 session <- getSession
1523 io $ pprintClosureCommand session bind force str
1525 stepCmd :: String -> GHCi ()
1526 stepCmd [] = doContinue GHC.SingleStep
1527 stepCmd expression = do runStmt expression GHC.SingleStep; return ()
1529 traceCmd :: String -> GHCi ()
1530 traceCmd [] = doContinue GHC.RunAndLogSteps
1531 traceCmd expression = do runStmt expression GHC.RunAndLogSteps; return ()
1533 continueCmd :: String -> GHCi ()
1534 continueCmd = noArgs $ doContinue GHC.RunToCompletion
1536 doContinue :: SingleStep -> GHCi ()
1537 doContinue step = do
1538 session <- getSession
1539 runResult <- io $ GHC.resume session step
1540 afterRunStmt runResult
1543 abandonCmd :: String -> GHCi ()
1544 abandonCmd = noArgs $ do
1546 b <- io $ GHC.abandon s -- the prompt will change to indicate the new context
1547 when (not b) $ io $ putStrLn "There is no computation running."
1550 deleteCmd :: String -> GHCi ()
1551 deleteCmd argLine = do
1552 deleteSwitch $ words argLine
1554 deleteSwitch :: [String] -> GHCi ()
1556 io $ putStrLn "The delete command requires at least one argument."
1557 -- delete all break points
1558 deleteSwitch ("*":_rest) = discardActiveBreakPoints
1559 deleteSwitch idents = do
1560 mapM_ deleteOneBreak idents
1562 deleteOneBreak :: String -> GHCi ()
1564 | all isDigit str = deleteBreak (read str)
1565 | otherwise = return ()
1567 historyCmd :: String -> GHCi ()
1569 | null arg = history 20
1570 | all isDigit arg = history (read arg)
1571 | otherwise = io $ putStrLn "Syntax: :history [num]"
1575 resumes <- io $ GHC.getResumeContext s
1577 [] -> io $ putStrLn "Not stopped at a breakpoint"
1579 let hist = GHC.resumeHistory r
1580 (took,rest) = splitAt num hist
1581 spans <- mapM (io . GHC.getHistorySpan s) took
1582 let nums = map (printf "-%-3d:") [(1::Int)..]
1583 printForUser (vcat (zipWith (<+>) (map text nums) (map ppr spans)))
1584 io $ putStrLn $ if null rest then "<end of history>" else "..."
1586 backCmd :: String -> GHCi ()
1587 backCmd = noArgs $ do
1589 (names, ix, span) <- io $ GHC.back s
1590 printForUser $ ptext SLIT("Logged breakpoint at") <+> ppr span
1591 printTypeOfNames s names
1592 -- run the command set with ":set stop <cmd>"
1594 enqueueCommands [stop st]
1596 forwardCmd :: String -> GHCi ()
1597 forwardCmd = noArgs $ do
1599 (names, ix, span) <- io $ GHC.forward s
1600 printForUser $ (if (ix == 0)
1601 then ptext SLIT("Stopped at")
1602 else ptext SLIT("Logged breakpoint at")) <+> ppr span
1603 printTypeOfNames s names
1604 -- run the command set with ":set stop <cmd>"
1606 enqueueCommands [stop st]
1608 -- handle the "break" command
1609 breakCmd :: String -> GHCi ()
1610 breakCmd argLine = do
1611 session <- getSession
1612 breakSwitch session $ words argLine
1614 breakSwitch :: Session -> [String] -> GHCi ()
1615 breakSwitch _session [] = do
1616 io $ putStrLn "The break command requires at least one argument."
1617 breakSwitch session args@(arg1:rest)
1618 | looksLikeModuleName arg1 = do
1619 mod <- wantInterpretedModule arg1
1620 breakByModule session mod rest
1621 | all isDigit arg1 = do
1622 (toplevel, _) <- io $ GHC.getContext session
1624 (mod : _) -> breakByModuleLine mod (read arg1) rest
1626 io $ putStrLn "Cannot find default module for breakpoint."
1627 io $ putStrLn "Perhaps no modules are loaded for debugging?"
1628 | otherwise = do -- try parsing it as an identifier
1629 wantNameFromInterpretedModule noCanDo arg1 $ \name -> do
1630 let loc = GHC.srcSpanStart (GHC.nameSrcSpan name)
1631 if GHC.isGoodSrcLoc loc
1632 then findBreakAndSet (GHC.nameModule name) $
1633 findBreakByCoord (Just (GHC.srcLocFile loc))
1634 (GHC.srcLocLine loc,
1636 else noCanDo name $ text "can't find its location: " <> ppr loc
1638 noCanDo n why = printForUser $
1639 text "cannot set breakpoint on " <> ppr n <> text ": " <> why
1641 breakByModule :: Session -> Module -> [String] -> GHCi ()
1642 breakByModule session mod args@(arg1:rest)
1643 | all isDigit arg1 = do -- looks like a line number
1644 breakByModuleLine mod (read arg1) rest
1645 breakByModule session mod _
1648 breakByModuleLine :: Module -> Int -> [String] -> GHCi ()
1649 breakByModuleLine mod line args
1650 | [] <- args = findBreakAndSet mod $ findBreakByLine line
1651 | [col] <- args, all isDigit col =
1652 findBreakAndSet mod $ findBreakByCoord Nothing (line, read col)
1653 | otherwise = breakSyntax
1655 breakSyntax = throwDyn (CmdLineError "Syntax: :break [<mod>] <line> [<column>]")
1657 findBreakAndSet :: Module -> (TickArray -> Maybe (Int, SrcSpan)) -> GHCi ()
1658 findBreakAndSet mod lookupTickTree = do
1659 tickArray <- getTickArray mod
1660 (breakArray, _) <- getModBreak mod
1661 case lookupTickTree tickArray of
1662 Nothing -> io $ putStrLn $ "No breakpoints found at that location."
1663 Just (tick, span) -> do
1664 success <- io $ setBreakFlag True breakArray tick
1665 session <- getSession
1669 recordBreak $ BreakLocation
1676 text "Breakpoint " <> ppr nm <>
1678 then text " was already set at " <> ppr span
1679 else text " activated at " <> ppr span
1681 printForUser $ text "Breakpoint could not be activated at"
1684 -- When a line number is specified, the current policy for choosing
1685 -- the best breakpoint is this:
1686 -- - the leftmost complete subexpression on the specified line, or
1687 -- - the leftmost subexpression starting on the specified line, or
1688 -- - the rightmost subexpression enclosing the specified line
1690 findBreakByLine :: Int -> TickArray -> Maybe (BreakIndex,SrcSpan)
1691 findBreakByLine line arr
1692 | not (inRange (bounds arr) line) = Nothing
1694 listToMaybe (sortBy leftmost_largest complete) `mplus`
1695 listToMaybe (sortBy leftmost_smallest incomplete) `mplus`
1696 listToMaybe (sortBy rightmost ticks)
1700 starts_here = [ tick | tick@(nm,span) <- ticks,
1701 GHC.srcSpanStartLine span == line ]
1703 (complete,incomplete) = partition ends_here starts_here
1704 where ends_here (nm,span) = GHC.srcSpanEndLine span == line
1706 findBreakByCoord :: Maybe FastString -> (Int,Int) -> TickArray
1707 -> Maybe (BreakIndex,SrcSpan)
1708 findBreakByCoord mb_file (line, col) arr
1709 | not (inRange (bounds arr) line) = Nothing
1711 listToMaybe (sortBy rightmost contains) `mplus`
1712 listToMaybe (sortBy leftmost_smallest after_here)
1716 -- the ticks that span this coordinate
1717 contains = [ tick | tick@(nm,span) <- ticks, span `spans` (line,col),
1718 is_correct_file span ]
1720 is_correct_file span
1721 | Just f <- mb_file = GHC.srcSpanFile span == f
1724 after_here = [ tick | tick@(nm,span) <- ticks,
1725 GHC.srcSpanStartLine span == line,
1726 GHC.srcSpanStartCol span >= col ]
1729 leftmost_smallest (_,a) (_,b) = a `compare` b
1730 leftmost_largest (_,a) (_,b) = (GHC.srcSpanStart a `compare` GHC.srcSpanStart b)
1732 (GHC.srcSpanEnd b `compare` GHC.srcSpanEnd a)
1733 rightmost (_,a) (_,b) = b `compare` a
1735 spans :: SrcSpan -> (Int,Int) -> Bool
1736 spans span (l,c) = GHC.srcSpanStart span <= loc && loc <= GHC.srcSpanEnd span
1737 where loc = GHC.mkSrcLoc (GHC.srcSpanFile span) l c
1739 -- for now, use ANSI bold on Unixy systems. On Windows, we add a line
1740 -- of carets under the active expression instead. The Windows console
1741 -- doesn't support ANSI escape sequences, and most Unix terminals
1742 -- (including xterm) do, so this is a reasonable guess until we have a
1743 -- proper termcap/terminfo library.
1744 #if !defined(mingw32_TARGET_OS)
1750 start_bold = BS.pack "\ESC[1m"
1751 end_bold = BS.pack "\ESC[0m"
1753 listCmd :: String -> GHCi ()
1755 mb_span <- getCurrentBreakSpan
1757 Nothing -> printForUser $ text "not stopped at a breakpoint; nothing to list"
1758 Just span | GHC.isGoodSrcSpan span -> io $ listAround span True
1759 | otherwise -> printForUser $ text "unable to list source for" <+> ppr span
1760 listCmd str = list2 (words str)
1762 list2 [arg] | all isDigit arg = do
1763 session <- getSession
1764 (toplevel, _) <- io $ GHC.getContext session
1766 [] -> io $ putStrLn "No module to list"
1767 (mod : _) -> listModuleLine mod (read arg)
1768 list2 [arg1,arg2] | looksLikeModuleName arg1, all isDigit arg2 = do
1769 mod <- wantInterpretedModule arg1
1770 listModuleLine mod (read arg2)
1772 wantNameFromInterpretedModule noCanDo arg $ \name -> do
1773 let loc = GHC.srcSpanStart (GHC.nameSrcSpan name)
1774 if GHC.isGoodSrcLoc loc
1776 tickArray <- getTickArray (GHC.nameModule name)
1777 let mb_span = findBreakByCoord (Just (GHC.srcLocFile loc))
1778 (GHC.srcLocLine loc, GHC.srcLocCol loc)
1781 Nothing -> io $ listAround (GHC.srcLocSpan loc) False
1782 Just (_,span) -> io $ listAround span False
1784 noCanDo name $ text "can't find its location: " <>
1787 noCanDo n why = printForUser $
1788 text "cannot list source code for " <> ppr n <> text ": " <> why
1790 io $ putStrLn "syntax: :list [<line> | <module> <line> | <identifier>]"
1792 listModuleLine :: Module -> Int -> GHCi ()
1793 listModuleLine modl line = do
1794 session <- getSession
1795 graph <- io (GHC.getModuleGraph session)
1796 let this = filter ((== modl) . GHC.ms_mod) graph
1798 [] -> panic "listModuleLine"
1800 let filename = fromJust (ml_hs_file (GHC.ms_location summ))
1801 loc = GHC.mkSrcLoc (mkFastString (filename)) line 0
1802 io $ listAround (GHC.srcLocSpan loc) False
1804 -- | list a section of a source file around a particular SrcSpan.
1805 -- If the highlight flag is True, also highlight the span using
1806 -- start_bold/end_bold.
1807 listAround span do_highlight = do
1808 contents <- BS.readFile (unpackFS file)
1810 lines = BS.split '\n' contents
1811 these_lines = take (line2 - line1 + 1 + pad_before + pad_after) $
1812 drop (line1 - 1 - pad_before) $ lines
1813 fst_line = max 1 (line1 - pad_before)
1814 line_nos = [ fst_line .. ]
1816 highlighted | do_highlight = zipWith highlight line_nos these_lines
1817 | otherwise = these_lines
1819 bs_line_nos = [ BS.pack (show l ++ " ") | l <- line_nos ]
1820 prefixed = zipWith BS.append bs_line_nos highlighted
1822 BS.putStrLn (BS.join (BS.pack "\n") prefixed)
1824 file = GHC.srcSpanFile span
1825 line1 = GHC.srcSpanStartLine span
1826 col1 = GHC.srcSpanStartCol span
1827 line2 = GHC.srcSpanEndLine span
1828 col2 = GHC.srcSpanEndCol span
1830 pad_before | line1 == 1 = 0
1834 highlight | do_bold = highlight_bold
1835 | otherwise = highlight_carets
1837 highlight_bold no line
1838 | no == line1 && no == line2
1839 = let (a,r) = BS.splitAt col1 line
1840 (b,c) = BS.splitAt (col2-col1) r
1842 BS.concat [a,start_bold,b,end_bold,c]
1844 = let (a,b) = BS.splitAt col1 line in
1845 BS.concat [a, start_bold, b]
1847 = let (a,b) = BS.splitAt col2 line in
1848 BS.concat [a, end_bold, b]
1851 highlight_carets no line
1852 | no == line1 && no == line2
1853 = BS.concat [line, nl, indent, BS.replicate col1 ' ',
1854 BS.replicate (col2-col1) '^']
1856 = BS.concat [line, nl, indent, BS.replicate col1 ' ',
1857 BS.replicate (BS.length line-col1) '^']
1859 = BS.concat [line, nl, indent, BS.replicate col2 '^']
1862 indent = BS.pack " "
1863 nl = BS.singleton '\n'
1865 -- --------------------------------------------------------------------------
1868 getTickArray :: Module -> GHCi TickArray
1869 getTickArray modl = do
1871 let arrmap = tickarrays st
1872 case lookupModuleEnv arrmap modl of
1873 Just arr -> return arr
1875 (breakArray, ticks) <- getModBreak modl
1876 let arr = mkTickArray (assocs ticks)
1877 setGHCiState st{tickarrays = extendModuleEnv arrmap modl arr}
1880 discardTickArrays :: GHCi ()
1881 discardTickArrays = do
1883 setGHCiState st{tickarrays = emptyModuleEnv}
1885 mkTickArray :: [(BreakIndex,SrcSpan)] -> TickArray
1887 = accumArray (flip (:)) [] (1, max_line)
1888 [ (line, (nm,span)) | (nm,span) <- ticks,
1889 line <- srcSpanLines span ]
1891 max_line = foldr max 0 (map GHC.srcSpanEndLine (map snd ticks))
1892 srcSpanLines span = [ GHC.srcSpanStartLine span ..
1893 GHC.srcSpanEndLine span ]
1895 lookupModule :: String -> GHCi Module
1896 lookupModule modName
1897 = do session <- getSession
1898 io (GHC.findModule session (GHC.mkModuleName modName) Nothing)
1900 -- don't reset the counter back to zero?
1901 discardActiveBreakPoints :: GHCi ()
1902 discardActiveBreakPoints = do
1904 mapM (turnOffBreak.snd) (breaks st)
1905 setGHCiState $ st { breaks = [] }
1907 deleteBreak :: Int -> GHCi ()
1908 deleteBreak identity = do
1910 let oldLocations = breaks st
1911 (this,rest) = partition (\loc -> fst loc == identity) oldLocations
1913 then printForUser (text "Breakpoint" <+> ppr identity <+>
1914 text "does not exist")
1916 mapM (turnOffBreak.snd) this
1917 setGHCiState $ st { breaks = rest }
1919 turnOffBreak loc = do
1920 (arr, _) <- getModBreak (breakModule loc)
1921 io $ setBreakFlag False arr (breakTick loc)
1923 getModBreak :: Module -> GHCi (GHC.BreakArray, Array Int SrcSpan)
1924 getModBreak mod = do
1925 session <- getSession
1926 Just mod_info <- io $ GHC.getModuleInfo session mod
1927 let modBreaks = GHC.modInfoModBreaks mod_info
1928 let array = GHC.modBreaks_flags modBreaks
1929 let ticks = GHC.modBreaks_locs modBreaks
1930 return (array, ticks)
1932 setBreakFlag :: Bool -> GHC.BreakArray -> Int -> IO Bool
1933 setBreakFlag toggle array index
1934 | toggle = GHC.setBreakOn array index
1935 | otherwise = GHC.setBreakOff array index