Commit b03f074f authored by Ben Gamari's avatar Ben Gamari 🐢 Committed by Austin Seipp

ghci: Allow :back and :forward to take counts

These behave like the count arguments of the gdb `up` and `down`
commands, allowing the user to quickly jump around in history.

Reviewed By: austin

Differential Revision: https://phabricator.haskell.org/D853
parent 578d2bad
...@@ -564,11 +564,11 @@ resumeExec canLogSpan step ...@@ -564,11 +564,11 @@ resumeExec canLogSpan step
handleRunStatus step expr bindings final_ids handleRunStatus step expr bindings final_ids
breakMVar statusMVar status hist' breakMVar statusMVar status hist'
back :: GhcMonad m => m ([Name], Int, SrcSpan) back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
back = moveHist (+1) back n = moveHist (+n)
forward :: GhcMonad m => m ([Name], Int, SrcSpan) forward :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
forward = moveHist (subtract 1) forward n = moveHist (subtract n)
moveHist :: GhcMonad m => (Int -> Int) -> m ([Name], Int, SrcSpan) moveHist :: GhcMonad m => (Int -> Int) -> m ([Name], Int, SrcSpan)
moveHist fn = do moveHist fn = do
......
...@@ -96,6 +96,11 @@ ...@@ -96,6 +96,11 @@
<literal>Main</literal> with an explicit module header but <literal>Main</literal> with an explicit module header but
without <literal>main</literal> is now an error (#7765). without <literal>main</literal> is now an error (#7765).
</para> </para>
<para>
The <literal>:back</literal> and <literal>:forward</literal>
commands now take an optional count allowing the user to move forward or
backward in history several steps at a time.
</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</sect3> </sect3>
......
...@@ -2096,12 +2096,14 @@ $ ghci -lm ...@@ -2096,12 +2096,14 @@ $ ghci -lm
<varlistentry> <varlistentry>
<term> <term>
<literal>:back</literal> <literal>:back <optional><replaceable>n</replaceable></optional></literal>
<indexterm><primary><literal>:back</literal></primary></indexterm> <indexterm><primary><literal>:back</literal></primary></indexterm>
</term> </term>
<listitem> <listitem>
<para>Travel back one step in the history. See <xref <para>Travel back <replaceable>n</replaceable> steps in the
linkend="tracing" />. See also: history. <replaceable>n</replaceable> is one if omitted.
See <xref linkend="tracing" /> for more about GHCi's debugging
facilities. See also:
<literal>:trace</literal>, <literal>:history</literal>, <literal>:trace</literal>, <literal>:history</literal>,
<literal>:forward</literal>.</para> <literal>:forward</literal>.</para>
</listitem> </listitem>
...@@ -2474,12 +2476,14 @@ Prelude> :. cmds.ghci ...@@ -2474,12 +2476,14 @@ Prelude> :. cmds.ghci
<varlistentry> <varlistentry>
<term> <term>
<literal>:forward</literal> <literal>:forward <optional><replaceable>n</replaceable></optional></literal>
<indexterm><primary><literal>:forward</literal></primary></indexterm> <indexterm><primary><literal>:forward</literal></primary></indexterm>
</term> </term>
<listitem> <listitem>
<para>Move forward in the history. See <xref <para>Move forward <replaceable>n</replaceable> steps in the
linkend="tracing" />. See also: history. <replaceable>n</replaceable> is one if omitted.
See <xref linkend="tracing" /> for more about GHCi's debugging
facilities. See also:
<literal>:trace</literal>, <literal>:history</literal>, <literal>:trace</literal>, <literal>:history</literal>,
<literal>:back</literal>.</para> <literal>:back</literal>.</para>
</listitem> </listitem>
......
...@@ -268,14 +268,14 @@ defFullHelpText = ...@@ -268,14 +268,14 @@ defFullHelpText =
" -- Commands for debugging:\n" ++ " -- Commands for debugging:\n" ++
"\n" ++ "\n" ++
" :abandon at a breakpoint, abandon current computation\n" ++ " :abandon at a breakpoint, abandon current computation\n" ++
" :back go back in the history (after :trace)\n" ++ " :back [<n>] go back in the history N steps (after :trace)\n" ++
" :break [<mod>] <l> [<col>] set a breakpoint at the specified location\n" ++ " :break [<mod>] <l> [<col>] set a breakpoint at the specified location\n" ++
" :break <name> set a breakpoint on the specified function\n" ++ " :break <name> set a breakpoint on the specified function\n" ++
" :continue resume after a breakpoint\n" ++ " :continue resume after a breakpoint\n" ++
" :delete <number> delete the specified breakpoint\n" ++ " :delete <number> delete the specified breakpoint\n" ++
" :delete * delete all breakpoints\n" ++ " :delete * delete all breakpoints\n" ++
" :force <expr> print <expr>, forcing unevaluated parts\n" ++ " :force <expr> print <expr>, forcing unevaluated parts\n" ++
" :forward go forward in the history (after :back)\n" ++ " :forward [<n>] go forward in the history N step s(after :back)\n" ++
" :history [<n>] after :trace, show the execution history\n" ++ " :history [<n>] after :trace, show the execution history\n" ++
" :list show the source code around current breakpoint\n" ++ " :list show the source code around current breakpoint\n" ++
" :list <identifier> show the source code for <identifier>\n" ++ " :list <identifier> show the source code for <identifier>\n" ++
...@@ -2747,24 +2747,34 @@ bold c | do_bold = text start_bold <> c <> text end_bold ...@@ -2747,24 +2747,34 @@ bold c | do_bold = text start_bold <> c <> text end_bold
| otherwise = c | otherwise = c
backCmd :: String -> GHCi () backCmd :: String -> GHCi ()
backCmd = noArgs $ withSandboxOnly ":back" $ do backCmd arg
(names, _, pan) <- GHC.back | null arg = back 1
printForUser $ ptext (sLit "Logged breakpoint at") <+> ppr pan | all isDigit arg = back (read arg)
printTypeOfNames names | otherwise = liftIO $ putStrLn "Syntax: :back [num]"
-- run the command set with ":set stop <cmd>" where
st <- getGHCiState back num = withSandboxOnly ":back" $ do
enqueueCommands [stop st] (names, _, pan) <- GHC.back num
printForUser $ ptext (sLit "Logged breakpoint at") <+> ppr pan
printTypeOfNames names
-- run the command set with ":set stop <cmd>"
st <- getGHCiState
enqueueCommands [stop st]
forwardCmd :: String -> GHCi () forwardCmd :: String -> GHCi ()
forwardCmd = noArgs $ withSandboxOnly ":forward" $ do forwardCmd arg
(names, ix, pan) <- GHC.forward | null arg = forward 1
printForUser $ (if (ix == 0) | all isDigit arg = forward (read arg)
then ptext (sLit "Stopped at") | otherwise = liftIO $ putStrLn "Syntax: :back [num]"
else ptext (sLit "Logged breakpoint at")) <+> ppr pan where
printTypeOfNames names forward num = withSandboxOnly ":forward" $ do
-- run the command set with ":set stop <cmd>" (names, ix, pan) <- GHC.forward num
st <- getGHCiState printForUser $ (if (ix == 0)
enqueueCommands [stop st] then ptext (sLit "Stopped at")
else ptext (sLit "Logged breakpoint at")) <+> ppr pan
printTypeOfNames names
-- run the command set with ":set stop <cmd>"
st <- getGHCiState
enqueueCommands [stop st]
-- handle the "break" command -- handle the "break" command
breakCmd :: String -> GHCi () breakCmd :: String -> GHCi ()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment