From eec37b63500402a1742f6280898535a3b9863719 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 22 Dec 2016 11:10:25 +0100 Subject: [PATCH 1/3] jump to numbered stackframe with hotkey CTRL+Q --- NEWS.md | 2 + base/REPL.jl | 20 +++++++ base/replutil.jl | 7 +++ doc/src/manual/interacting-with-julia.md | 66 ++++++++++++------------ 4 files changed, 63 insertions(+), 32 deletions(-) diff --git a/NEWS.md b/NEWS.md index 1e73f8b53a05a..6b15d745769bf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -83,6 +83,8 @@ Library improvements * The `chop` and `chomp` functions now return a `SubString` ([#18339]). + * Numbered stackframes printed in stacktraces can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q`. + * The REPL now supports something called *prompt pasting* ([#17599]). This activates when pasting text that starts with `julia> ` into the REPL. In that case, only expressions starting with `julia> ` are parsed, the rest are removed. diff --git a/base/REPL.jl b/base/REPL.jl index 6716c80fd0292..27ab0637e25ee 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -899,6 +899,26 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep firstline = false end end, + + # Open the editor at the location of a stackframe + # This is accessing a global variable that gets set in + # the show_backtrace function. + "^Q" => (s, o...) -> begin + linfos = Base.LAST_BACKTRACE_LINE_INFOS + str = String(take!(LineEdit.buffer(s))) + n = tryparse(Int, str) + isnull(n) && @goto writeback + n = get(n) + if n <= 0 || n > length(linfos) || startswith(linfos[n][1], "./REPL") + @goto writeback + end + Base.edit(linfos[n][1], linfos[n][2]) + Base.LineEdit.refresh_line(s) + return + @label writeback + write(Base.LineEdit.buffer(s), str) + return + end, ) prefix_prompt, prefix_keymap = LineEdit.setup_prefix_keymap(hp, julia_prompt) diff --git a/base/replutil.jl b/base/replutil.jl index 4f9c49687c899..9b8c71bc8f2c3 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -585,14 +585,21 @@ function show_trace_entry(io, frame, n; prefix = " in ") n > 1 && print(io, " (repeats ", n, " times)") end +# Contains file name and file number. Gets set when a backtrace +# is showed. Used by the REPL to make it possible to open +# the location of a stackframe in the edítor. +global LAST_BACKTRACE_LINE_INFOS = Tuple{String, Int}[] + function show_backtrace(io::IO, t::Vector) n_frames = 0 frame_counter = 0 + resize!(LAST_BACKTRACE_LINE_INFOS, 0) process_backtrace((a,b) -> n_frames += 1, t) n_frames != 0 && print(io, "\nStacktrace:") process_entry = (last_frame, n) -> begin frame_counter += 1 show_trace_entry(io, last_frame, n, prefix = string(" [", frame_counter, "] ")) + push!(LAST_BACKTRACE_LINE_INFOS, (string(last_frame.file), last_frame.line)) end process_backtrace(process_entry, t) end diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index 2704e9f3a688f..0e57866164a36 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -129,38 +129,40 @@ control-key, there are also meta-key bindings. These vary more by platform, but default to using alt- or option- held down with a key to send the meta-key (or can be configured to do so). -| Keybinding | Description | -|:------------------- |:---------------------------------------------------------------------------- | -| **Program control** |   | -| `^D` | Exit (when buffer is empty) | -| `^C` | Interrupt or cancel | -| `^L` | Clear console screen | -| Return/Enter, `^J` | New line, executing if it is complete | -| meta-Return/Enter | Insert new line without executing it | -| `?` or `;` | Enter help or shell mode (when at start of a line) | -| `^R`, `^S` | Incremental history search, described above | -| **Cursor movement** |   | -| Right arrow, `^F` | Move right one character | -| Left arrow, `^B` | Move left one character | -| Home, `^A` | Move to beginning of line | -| End, `^E` | Move to end of line | -| `^P` | Change to the previous or next history entry | -| `^N` | Change to the next history entry | -| Up arrow | Move up one line (or to the previous history entry) | -| Down arrow | Move down one line (or to the next history entry) | -| Page-up | Change to the previous history entry that matches the text before the cursor | -| Page-down | Change to the next history entry that matches the text before the cursor | -| `meta-F` | Move right one word | -| `meta-B` | Move left one word | -| **Editing** |   | -| Backspace, `^H` | Delete the previous character | -| Delete, `^D` | Forward delete one character (when buffer has text) | -| meta-Backspace | Delete the previous word | -| `meta-D` | Forward delete the next word | -| `^W` | Delete previous text up to the nearest whitespace | -| `^K` | "Kill" to end of line, placing the text in a buffer | -| `^Y` | "Yank" insert the text from the kill buffer | -| `^T` | Transpose the characters about the cursor | +| Keybinding | Description | +|:------------------- |:-------------------------------------------------------------------------------- | +| **Program control** |   | +| `^D` | Exit (when buffer is empty) | +| `^C` | Interrupt or cancel | +| `^L` | Clear console screen | +| Return/Enter, `^J` | New line, executing if it is complete | +| meta-Return/Enter | Insert new line without executing it | +| `?` or `;` | Enter help or shell mode (when at start of a line) | +| `^R`, `^S` | Incremental history search, described above | +| **Cursor movement** |   | +| Right arrow, `^F` | Move right one character | +| Left arrow, `^B` | Move left one character | +| Home, `^A` | Move to beginning of line | +| End, `^E` | Move to end of line | +| `^P` | Change to the previous or next history entry | +| `^N` | Change to the next history entry | +| Up arrow | Move up one line (or to the previous history entry) | +| Down arrow | Move down one line (or to the next history entry) | +| Page-up | Change to the previous history entry that matches the text before the cursor | +| Page-down | Change to the next history entry that matches the text before the cursor | +| `meta-F` | Move right one word | +| `meta-B` | Move left one word | +| **Editing** |   | +| Backspace, `^H` | Delete the previous character | +| Delete, `^D` | Forward delete one character (when buffer has text) | +| meta-Backspace | Delete the previous word | +| `meta-D` | Forward delete the next word | +| `^W` | Delete previous text up to the nearest whitespace | +| `^K` | "Kill" to end of line, placing the text in a buffer | +| `^Y` | "Yank" insert the text from the kill buffer | +| `^T` | Transpose the characters about the cursor | +| `^Q` | Write a number in REPL and press `^Q` to open editor at corresponding stackframe | + ### Customizing keybindings From 4dc48608bb0ba661ae3e6975812542f0da53538c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 30 Dec 2016 17:17:08 +0100 Subject: [PATCH 2/3] fix grammar [ci skip] --- base/replutil.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/replutil.jl b/base/replutil.jl index 9b8c71bc8f2c3..1c96c642a182c 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -586,7 +586,7 @@ function show_trace_entry(io, frame, n; prefix = " in ") end # Contains file name and file number. Gets set when a backtrace -# is showed. Used by the REPL to make it possible to open +# is shown. Used by the REPL to make it possible to open # the location of a stackframe in the edítor. global LAST_BACKTRACE_LINE_INFOS = Tuple{String, Int}[] From f35d80fdde891a63481a99a976972086653658a6 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 2 Jan 2017 19:48:04 +0100 Subject: [PATCH 3/3] add pr ref to NEWS [ci skip] --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 6b15d745769bf..5871a7478bb9d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -83,7 +83,7 @@ Library improvements * The `chop` and `chomp` functions now return a `SubString` ([#18339]). - * Numbered stackframes printed in stacktraces can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q`. + * Numbered stackframes printed in stacktraces can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#19680]). * The REPL now supports something called *prompt pasting* ([#17599]). This activates when pasting text that starts with `julia> ` into the REPL. @@ -804,3 +804,4 @@ Language tooling improvements [#19543]: https://github.com/JuliaLang/julia/issues/19543 [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 +[#19680]: https://github.com/JuliaLang/julia/issues/19680