Ian Lynagh <igloo@earth.li>**
20071124231857
It used to be a synonym for ":r" in 6.6.1, but this wasn't documented or
known about by the developers. In 6.8.1 it was accidentally broken.
This patch brings it back, but as "repeat the last command", similar to
pressing enter in gdb. This is almost as good for people who want it to
reload, and means that it can also be used to repeat commands like :step.
-----------------------------------------------------------------------------
-- GHCi monad
-----------------------------------------------------------------------------
-- GHCi monad
+type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
+
data GHCiState = GHCiState
{
progname :: String,
data GHCiState = GHCiState
{
progname :: String,
-- tickarrays caches the TickArray for loaded modules,
-- so that we don't rebuild it each time the user sets
-- a breakpoint.
-- tickarrays caches the TickArray for loaded modules,
-- so that we don't rebuild it each time the user sets
-- a breakpoint.
+ -- ":" at the GHCi prompt repeats the last command, so we
+ -- remember is here:
+ last_command :: Maybe Command,
cmdqueue :: [String],
remembered_ctx :: Maybe ([Module],[Module])
-- modules we want to add to the context, but can't
cmdqueue :: [String],
remembered_ctx :: Maybe ([Module],[Module])
-- modules we want to add to the context, but can't
ghciWelcomeMsg = "GHCi, version " ++ cProjectVersion ++
": http://www.haskell.org/ghc/ :? for help"
ghciWelcomeMsg = "GHCi, version " ++ cProjectVersion ++
": http://www.haskell.org/ghc/ :? for help"
-type Command = (String, String -> GHCi Bool, Bool, String -> IO [String])
-
cmdName :: Command -> String
cmdName (n,_,_,_) = n
cmdName :: Command -> String
cmdName (n,_,_,_) = n
" Commands available from the prompt:\n" ++
"\n" ++
" <statement> evaluate/run <statement>\n" ++
" Commands available from the prompt:\n" ++
"\n" ++
" <statement> evaluate/run <statement>\n" ++
+ " : repeat last command\n" ++
" :{\\n ..lines.. \\n:}\\n multiline command\n" ++
" :add <filename> ... add module(s) to the current target set\n" ++
" :browse[!] [[*]<mod>] display the names defined by module <mod>\n" ++
" :{\\n ..lines.. \\n:}\\n multiline command\n" ++
" :add <filename> ... add module(s) to the current target set\n" ++
" :browse[!] [[*]<mod>] display the names defined by module <mod>\n" ++
break_ctr = 0,
breaks = [],
tickarrays = emptyModuleEnv,
break_ctr = 0,
breaks = [],
tickarrays = emptyModuleEnv,
+ last_command = Nothing,
cmdqueue = [],
remembered_ctx = Nothing
}
cmdqueue = [],
remembered_ctx = Nothing
}
Just thing -> printTyThing thing
Just thing -> printTyThing thing
+data MaybeCommand = GotCommand Command | BadCommand | NoLastCommand
specialCommand :: String -> GHCi Bool
specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
specialCommand str = do
let (cmd,rest) = break isSpace str
specialCommand :: String -> GHCi Bool
specialCommand ('!':str) = shellEscape (dropWhile isSpace str)
specialCommand str = do
let (cmd,rest) = break isSpace str
- maybe_cmd <- io (lookupCommand cmd)
+ maybe_cmd <- lookupCommand cmd
- Nothing -> io (hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
- ++ shortHelpText) >> return False)
- Just (_,f,_,_) -> f (dropWhile isSpace rest)
-
-lookupCommand :: String -> IO (Maybe Command)
+ GotCommand (_,f,_,_) -> f (dropWhile isSpace rest)
+ BadCommand ->
+ do io $ hPutStr stdout ("unknown command ':" ++ cmd ++ "'\n"
+ ++ shortHelpText)
+ return False
+ NoLastCommand ->
+ do io $ hPutStr stdout ("there is no last command to perform\n"
+ ++ shortHelpText)
+ return False
+
+lookupCommand :: String -> GHCi (MaybeCommand)
+lookupCommand "" = do
+ st <- getGHCiState
+ case last_command st of
+ Just c -> return $ GotCommand c
+ Nothing -> return NoLastCommand
+ mc <- io $ lookupCommand' str
+ st <- getGHCiState
+ setGHCiState st{ last_command = mc }
+ return $ case mc of
+ Just c -> GotCommand c
+ Nothing -> BadCommand
+
+lookupCommand' :: String -> IO (Maybe Command)
+lookupCommand' str = do
macros <- readIORef macros_ref
let cmds = builtin_commands ++ macros
-- look for exact match first, then the first prefix match
macros <- readIORef macros_ref
let cmds = builtin_commands ++ macros
-- look for exact match first, then the first prefix match
- case [ c | c <- cmds, str == cmdName c ] of
- c:_ -> return (Just c)
- [] -> case [ c | c@(s,_,_,_) <- cmds, str `isPrefixOf` s ] of
- [] -> return Nothing
- c:_ -> return (Just c)
-
+ return $ case [ c | c <- cmds, str == cmdName c ] of
+ c:_ -> Just c
+ [] -> case [ c | c@(s,_,_,_) <- cmds, str `isPrefixOf` s ] of
+ [] -> Nothing
+ c:_ -> Just c
getCurrentBreakSpan :: GHCi (Maybe SrcSpan)
getCurrentBreakSpan = do
getCurrentBreakSpan :: GHCi (Maybe SrcSpan)
getCurrentBreakSpan = do
':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
_other
| ((':':c) : _) <- line_words -> do
':':_ | all isSpace (take (start-1) line) -> wrapCompleter completeCmd w
_other
| ((':':c) : _) <- line_words -> do
- maybe_cmd <- lookupCommand c
+ maybe_cmd <- lookupCommand' c
let (n,w') = selectWord (words' 0 line)
case maybe_cmd of
Nothing -> return Nothing
let (n,w') = selectWord (words' 0 line)
case maybe_cmd of
Nothing -> return Nothing
</varlistentry>
<varlistentry>
</varlistentry>
<varlistentry>
+ <term>
+ <literal>:</literal>
+ <indexterm><primary><literal>:</literal></primary></indexterm>
+ </term>
+ <listitem>
+ <para>Repeat the previous command.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+
<term>
<literal>:history [<replaceable>num</replaceable>]</literal>
<indexterm><primary><literal>:history</literal></primary></indexterm>
<term>
<literal>:history [<replaceable>num</replaceable>]</literal>
<indexterm><primary><literal>:history</literal></primary></indexterm>