Skip to content

Commit

Permalink
REPL: allow editing current input in editor (via Meta-e)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet authored and KristofferC committed May 9, 2022
1 parent d3fdde9 commit b16afaf
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 9 deletions.
56 changes: 56 additions & 0 deletions stdlib/REPL/src/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import ..Terminals: raw!, width, height, cmove, getX,
import Base: ensureroom, show, AnyDict, position
using Base: something

using InteractiveUtils: InteractiveUtils

abstract type TextInterface end # see interface immediately below
abstract type ModeState end # see interface below
abstract type HistoryProvider end
Expand Down Expand Up @@ -1295,6 +1297,59 @@ _edit_indent(buf::IOBuffer, b::Int, num::Int) =
num >= 0 ? edit_splice!(buf, b => b, ' '^num, rigid_mark=false) :
edit_splice!(buf, b => (b - num))

function mode_idx(hist #=::REPLHistoryProvider =#, mode::TextInterface)
c = :julia
for (k,v) in hist.mode_mapping
isequal(v, mode) && (c = k)
end
return c
end

function guess_current_mode_name(s)
try
mode_idx(s.current_mode.hist, s.current_mode)
catch
nothing
end
end

# edit current input in editor
function edit_input(s)
mode_name = guess_current_mode_name(s)
filename = tempname()
if mode_name == :julia
filename *= ".jl"
elseif mode_name == :shell
filename *= ".sh"
end
buf = buffer(s)
data = buf.data
pos = position(buf)
size0 = buf.size
resize!(data, buf.size) # to not write garbage into filename
line = 1 + count(==(_newline), view(data, 1:pos))
ct0 = open(filename, "w") do io
write(io, data)
ctime(io)
end
InteractiveUtils.edit(filename, line)
n, ct = open(filename) do io
readbytes!(io, empty!(buf.data), typemax(Int)),
ctime(io)
end
rm(filename)
@assert n == length(buf.data)
buf.size = n
buf.ptr = n+1
if ct0 != ct # something was changed, run the input
commit_line(s)
:done
else # no change, the edit session probably unsuccessful
@assert n == size0
seek(buf, pos) # restore state from before edit
refresh_line(s)
end
end

history_prev(::EmptyHistoryProvider) = ("", false)
history_next(::EmptyHistoryProvider) = ("", false)
Expand Down Expand Up @@ -2337,6 +2392,7 @@ AnyDict(
"\eu" => (s::MIState,o...)->edit_upper_case(s),
"\el" => (s::MIState,o...)->edit_lower_case(s),
"\ec" => (s::MIState,o...)->edit_title_case(s),
"\ee" => (s::MIState,o...) -> edit_input(s),
)

const history_keymap = AnyDict(
Expand Down
11 changes: 2 additions & 9 deletions stdlib/REPL/src/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ import ..LineEdit:
terminal,
MIState,
PromptState,
TextInterface
TextInterface,
mode_idx

include("REPLCompletions.jl")
using .REPLCompletions
Expand Down Expand Up @@ -601,14 +602,6 @@ function hist_from_file(hp::REPLHistoryProvider, path::String)
return hp
end

function mode_idx(hist::REPLHistoryProvider, mode::TextInterface)
c = :julia
for (k,v) in hist.mode_mapping
isequal(v, mode) && (c = k)
end
return c
end

function add_history(hist::REPLHistoryProvider, s::PromptState)
str = rstrip(String(take!(copy(s.input_buffer))))
isempty(strip(str)) && return
Expand Down

0 comments on commit b16afaf

Please sign in to comment.