Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REPL: fix yank-twice activates region #33814

Merged
merged 1 commit into from
Nov 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions stdlib/REPL/src/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ options(s::PromptState) =
end

function setmark(s::MIState, guess_region_active::Bool=true)
was_active = is_region_active(s)
guess_region_active && activate_region(s, s.key_repeats > 0 ? :mark : :off)
refresh = set_action!(s, :setmark)
s.current_action === :setmark && s.key_repeats > 0 && activate_region(s, :mark)
mark(buffer(s))
was_active && refresh_line(s)
refresh && refresh_line(s)
nothing
end

Expand Down Expand Up @@ -239,30 +239,35 @@ function preserve_active(command::Symbol)
command [:edit_indent, :edit_transpose_lines_down!, :edit_transpose_lines_up!]
end

# returns whether the "active region" status changed visibly,
# i.e. whether there should be a visual refresh
function set_action!(s::MIState, command::Symbol)
# if a command is already running, don't update the current_action field,
# as the caller is used as a helper function
s.current_action === :unknown || return
s.current_action === :unknown || return false

active = region_active(s)

## record current action
s.current_action = command

## handle activeness of the region
is_shift_move(cmd) = startswith(String(cmd), "shift_")
if is_shift_move(command)
if region_active(s) !== :shift
setmark(s, false)
if startswith(String(command), "shift_") # shift-move command
if active !== :shift
setmark(s) # s.current_action must already have been set
activate_region(s, :shift)
# NOTE: if the region was already active from a non-shift
# move (e.g. ^Space^Space), the region is visibly changed
return active !== :off # active status is reset
end
elseif !(preserve_active(command) ||
command_group(command) === :movement && region_active(s) === :mark)
# if we move after a shift-move, the region is de-activated
# (e.g. like emacs behavior)
deactivate_region(s)
return active !== :off
end

## record current action
s.current_action = command
nothing
false
end

set_action!(s, command::Symbol) = nothing
Expand Down
18 changes: 18 additions & 0 deletions stdlib/REPL/test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1059,3 +1059,21 @@ fake_repl() do stdin_write, stdout_read, repl
wait(repltask)
@test istaskdone(repltask)
end

fake_repl() do stdin_write, stdout_read, repl
repltask = @async begin
REPL.run_repl(repl)
end
write(stdin_write, "anything\x15\x19\x19") # ^u^y^y : kill line backwards + 2 yanks
s1 = readuntil(stdout_read, "anything") # typed
s2 = readuntil(stdout_read, "anything") # yanked (first ^y)
s3 = readuntil(stdout_read, "anything") # previous yanked refreshed (from second ^y)
s4 = readuntil(stdout_read, "anything", keep=true) # last yanked
# necessary to read at least some part of the buffer,
# for the "region_active" to have time to be updated

@test LineEdit.state(repl.mistate).region_active == :off
@test s4 == "anything" # no control characters between the last two occurences of "anything"
write(stdin_write, "\x15\x04")
Base.wait(repltask)
end