diff --git a/base/repl/LineEdit.jl b/base/repl/LineEdit.jl index 95a05868bce22..ebf27b7a7bad9 100644 --- a/base/repl/LineEdit.jl +++ b/base/repl/LineEdit.jl @@ -621,45 +621,54 @@ function edit_werase(buf::IOBuffer) pos1 = position(buf) char_move_word_left(buf, isspace) pos0 = position(buf) - pos0 < pos1 || return false edit_splice!(buf, pos0 => pos1) - true end function edit_werase(s::MIState) push_undo(s) - edit_werase(buffer(s)) ? refresh_line(s) : pop_undo(s) - :edit_werase + if push_kill!(s, edit_werase(buffer(s)), rev=true) + refresh_line(s) + :edit_werase + else + pop_undo(s) + :ignore + end end function edit_delete_prev_word(buf::IOBuffer) pos1 = position(buf) char_move_word_left(buf) pos0 = position(buf) - pos0 < pos1 || return false edit_splice!(buf, pos0 => pos1) - true end function edit_delete_prev_word(s::MIState) push_undo(s) - edit_delete_prev_word(buffer(s)) ? refresh_line(s) : pop_undo(s) - :edit_delete_prev_word + if push_kill!(s, edit_delete_prev_word(buffer(s)), rev=true) + refresh_line(s) + :edit_delete_prev_word + else + pop_undo(s) + :ignore + end end function edit_delete_next_word(buf::IOBuffer) pos0 = position(buf) char_move_word_right(buf) pos1 = position(buf) - pos0 < pos1 || return false edit_splice!(buf, pos0 => pos1) - true end function edit_delete_next_word(s) push_undo(s) - edit_delete_next_word(buffer(s)) ? refresh_line(s) : pop_undo(s) - :edit_delete_next_word + if push_kill!(s, edit_delete_next_word(buffer(s))) + refresh_line(s) + :edit_delete_next_word + else + pop_undo(s) + :ignore + end end function edit_yank(s::MIState) @@ -687,10 +696,12 @@ function edit_yank_pop(s::MIState, require_previous_yank=true) end end -function push_kill!(s::MIState, killed::String, concat=false) +function push_kill!(s::MIState, killed::String, concat = s.key_repeats > 0; rev=false) isempty(killed) && return false - if concat - s.kill_ring[end] *= killed + if concat && !isempty(s.kill_ring) + s.kill_ring[end] = rev ? + killed * s.kill_ring[end] : # keep expected order for backward deletion + s.kill_ring[end] * killed else push!(s.kill_ring, killed) length(s.kill_ring) > KILL_RING_MAX[] && shift!(s.kill_ring) @@ -708,7 +719,7 @@ function edit_kill_line(s::MIState) killbuf = killbuf[1:end-1] char_move_left(buf) end - push_kill!(s, killbuf, s.key_repeats > 0) || return :ignore + push_kill!(s, killbuf) || return :ignore edit_splice!(buf, pos => position(buf)) refresh_line(s) :edit_kill_line @@ -716,7 +727,7 @@ end function edit_copy_region(s::MIState) buf = buffer(s) - push_kill!(s, content(buf, region(buf))) || return :ignore + push_kill!(s, content(buf, region(buf)), false) || return :ignore if REGION_ANIMATION_DURATION[] > 0.0 edit_exchange_point_and_mark(s) sleep(REGION_ANIMATION_DURATION[]) @@ -727,7 +738,7 @@ end function edit_kill_region(s::MIState) push_undo(s) - if push_kill!(s, edit_splice!(s)) + if push_kill!(s, edit_splice!(s), false) refresh_line(s) :edit_kill_region else @@ -807,6 +818,7 @@ edit_clear(buf::IOBuffer) = truncate(buf, 0) function edit_clear(s::MIState) push_undo(s) + push_kill!(s, content(s), false) || return :ignore edit_clear(buffer(s)) refresh_line(s) :edit_clear diff --git a/test/lineedit.jl b/test/lineedit.jl index e6b50cb14e402..db08ac64c2bc4 100644 --- a/test/lineedit.jl +++ b/test/lineedit.jl @@ -300,14 +300,14 @@ seek(buf,0) buf = IOBuffer("type X\n ") seekend(buf) -@test LineEdit.edit_delete_prev_word(buf) +@test !isempty(LineEdit.edit_delete_prev_word(buf)) @test position(buf) == 5 @test buf.size == 5 @test content(buf) == "type " buf = IOBuffer("4 +aaa+ x") seek(buf,8) -@test LineEdit.edit_delete_prev_word(buf) +@test !isempty(LineEdit.edit_delete_prev_word(buf)) @test position(buf) == 3 @test buf.size == 4 @test content(buf) == "4 +x" @@ -316,11 +316,11 @@ buf = IOBuffer("x = func(arg1,arg2 , arg3)") seekend(buf) LineEdit.char_move_word_left(buf) @test position(buf) == 21 -@test LineEdit.edit_delete_prev_word(buf) +@test !isempty(LineEdit.edit_delete_prev_word(buf)) @test content(buf) == "x = func(arg1,arg3)" -@test LineEdit.edit_delete_prev_word(buf) +@test !isempty(LineEdit.edit_delete_prev_word(buf)) @test content(buf) == "x = func(arg3)" -@test LineEdit.edit_delete_prev_word(buf) +@test !isempty(LineEdit.edit_delete_prev_word(buf)) @test content(buf) == "x = arg3)" # Unicode combining characters @@ -617,6 +617,29 @@ end LineEdit.edit_kill_line(s) @test s.kill_ring[end] == "çhing" @test s.kill_idx == 3 + # repetition (concatenation of killed strings + edit_insert(s, "A B C") + LineEdit.edit_delete_prev_word(s) + s.key_repeats = 1 + LineEdit.edit_delete_prev_word(s) + s.key_repeats = 0 + @test s.kill_ring[end] == "B C" + LineEdit.edit_yank(s) + LineEdit.edit_werase(s) + @test s.kill_ring[end] == "C" + s.key_repeats = 1 + LineEdit.edit_werase(s) + s.key_repeats = 0 + @test s.kill_ring[end] == "B C" + LineEdit.edit_yank(s) + LineEdit.edit_move_word_left(s) + LineEdit.edit_move_word_left(s) + LineEdit.edit_delete_next_word(s) + @test s.kill_ring[end] == "B" + s.key_repeats = 1 + LineEdit.edit_delete_next_word(s) + s.key_repeats = 0 + @test s.kill_ring[end] == "B C" end @testset "undo" begin