1 -----------------------------------------------------------------------------
2 -- $Id: InteractiveUI.hs,v 1.2 2000/11/16 11:39:37 simonmar Exp $
4 -- GHC Interactive User Interface
6 -- (c) The GHC Team 2000
8 -----------------------------------------------------------------------------
10 module InteractiveUI (interactiveUI) where
30 -----------------------------------------------------------------------------
33 \ _____ __ __ ____ _________________________________________________\n\
34 \(| || || (| |) GHC Interactive, version 5.00 \n\
35 \|| __ ||___|| || () For Haskell 98. \n\
36 \|| |) ||---|| || || http://www.haskell.org/ghc \n\
37 \|| || || || || (| Bug reports to: glasgow-haskell-bugs@haskell.org \n\
38 \(|___|| || || (|__|) \\\\______________________________________________________\n"
40 commands :: [(String, String -> GHCi ())]
42 ("cd", changeDirectory),
46 ("reload", reloadModule),
53 shortHelpText = "use :? for help.\n"
56 \ <expr> evaluate <expr>\n\
57 \ :cd <dir> change directory to <dir>\n\
58 \ :help display this list of commands\n\
59 \ :? display this list of commands\n\
60 \ :load <filename> load a module (and it dependents)\n\
61 \ :reload reload the current program\n\
62 \ :set <opetion> ... set options\n\
63 \ :type <expr> show the type of <expr>\n\
65 \ :!<command> run the shell command <command>\n\
68 interactiveUI :: CmState -> IO ()
70 hPutStrLn stdout ghciWelcomeMsg
72 hSetBuffering stdout NoBuffering
74 -- link in the available packages
75 pkgs <- getPackageInfo
76 linkPackages (reverse pkgs)
81 _ <- (unGHCi uiLoop) GHCiState{ current_module = mkModuleName "Prelude",
90 l <- io (readline (moduleNameUserString (current_module st) ++ ">"))
92 l <- io (hGetLine stdin)
104 runCommand c = myCatch (doCommand c)
105 (\e -> io (hPutStr stdout ("Error: " ++ show e)))
107 doCommand (':' : command) = specialCommand command
109 io (hPutStrLn stdout ("Run expression: " ++ expr))
112 specialCommand str = do
113 let (cmd,rest) = break isSpace str
114 case [ (s,f) | (s,f) <- commands, prefixMatch cmd s ] of
115 [] -> io $ hPutStr stdout ("uknown command `:" ++ cmd ++ "'\n"
118 cs -> io $ hPutStrLn stdout ("prefix " ++ cmd ++
119 " matches multiple commands (" ++
120 foldr1 (\a b -> a ++ ',':b) (map fst cs) ++ ")")
122 noArgs c = io (hPutStrLn stdout ("command `:" ++ c ++ "' takes no arguments"))
124 -----------------------------------------------------------------------------
127 -- ToDo: don't forget to catch errors
129 help :: String -> GHCi ()
130 help _ = io (putStr helpText)
132 changeDirectory :: String -> GHCi ()
133 changeDirectory = io . setCurrentDirectory
135 loadModule :: String -> GHCi ()
137 state <- getGHCiState
138 (new_cmstate, mod) <- io (cmLoadModule (cmstate state) ({-ToDo!!-}mkModuleName path))
139 setGHCiState state{cmstate=new_cmstate, target=Just path}
141 reloadModule :: String -> GHCi ()
143 state <- getGHCiState
145 Nothing -> io (putStr "no current target\n")
146 Just path -> do (new_cmstate, mod) <- io (cmLoadModule (cmstate state) (mkModuleName path))
147 setGHCiState state{cmstate=new_cmstate}
148 reloadModule _ = noArgs ":reload"
150 setOptions :: String -> GHCi ()
151 setOptions = panic "setOptions"
153 typeOfExpr :: String -> GHCi ()
154 typeOfExpr = panic "typeOfExpr"
156 quit :: String -> GHCi ()
159 shellEscape :: String -> GHCi ()
160 shellEscape str = io (system str >> return ())
162 -----------------------------------------------------------------------------
165 data GHCiState = GHCiState
167 current_module :: ModuleName,
168 target :: Maybe FilePath,
172 newtype GHCi a = GHCi { unGHCi :: GHCiState -> IO (GHCiState, a) }
174 instance Monad GHCi where
175 (GHCi m) >>= k = GHCi $ \s -> m s >>= \(s,a) -> unGHCi (k a) s
176 return a = GHCi $ \s -> return (s,a)
178 getGHCiState = GHCi $ \s -> return (s,s)
179 setGHCiState s = GHCi $ \_ -> return (s,())
181 io m = GHCi $ \s -> m >>= \a -> return (s,a)
183 myCatch (GHCi m) h = GHCi $ \s -> Exception.catch (m s) (\e -> unGHCi (h e) s)
185 -----------------------------------------------------------------------------
188 linkPackages :: [Package] -> IO ()
189 linkPackages pkgs = mapM_ linkPackage pkgs
191 linkPackage :: Package -> IO ()
192 -- ignore rts and gmp for now (ToDo; better?)
193 linkPackage pkg | name pkg `elem` ["rts", "gmp"] = return ()
195 putStr ("Loading package " ++ name pkg ++ " ... ")
196 let dirs = library_dirs pkg
197 let objs = map (++".o") (hs_libraries pkg ++ extra_libraries pkg)
198 mapM (linkOneObj dirs) objs
199 putStr "resolving ... "
203 linkOneObj dirs obj = do
204 filename <- findFile dirs obj
207 findFile [] obj = throwDyn (OtherError ("can't find " ++ obj))
208 findFile (d:ds) obj = do
209 let path = d ++ '/':obj
210 b <- doesFileExist path
211 if b then return path else findFile ds obj