Skip to content

Commit

Permalink
REPL: transpose multiple lines at once when highlighted
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Dec 8, 2017
1 parent e3768b1 commit d787423
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
24 changes: 13 additions & 11 deletions base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ command_group(command::Function) = command_group(Base.function_name(command))

# return true if command should keep active a region
function preserve_active(command::Symbol)
command == :edit_indent
command [:edit_indent, :edit_transpose_lines_down!, :edit_transpose_lines_up!]
end

function set_action!(s::MIState, command::Symbol)
Expand Down Expand Up @@ -953,37 +953,39 @@ function edit_transpose_words(buf::IOBuffer, mode=:emacs)
end


# swap current line with line above
function edit_transpose_lines_up!(buf::IOBuffer)
b2 = beginofline(buf)
# swap all lines intersecting the region with line above
function edit_transpose_lines_up!(buf::IOBuffer, reg::Region)
b2 = beginofline(buf, first(reg))
b2 == 0 && return false
b1 = beginofline(buf, b2-1)
# we do in this order so that the buffer's position is maintained in current line
line1 = edit_splice!(buf, b1 => b2) # delete whole previous line
line1 = '\n'*line1[1:end-1] # don't include the final '\n'
pos = position(buf) # save pos in case it's at the end of line
b = endofline(buf)
b = endofline(buf, last(reg) - b2 + b1) # b2-b1 is the size of the removed line1
edit_splice!(buf, b => b, line1)
seek(buf, pos)
true
end

# swap current line with line below
function edit_transpose_lines_down!(buf::IOBuffer)
e1 = endofline(buf)
# swap all lines intersecting the region with line below
function edit_transpose_lines_down!(buf::IOBuffer, reg::Region)
e1 = endofline(buf, last(reg))
e1 == buf.size && return false
e2 = endofline(buf, e1+1)
line2 = edit_splice!(buf, e1 => e2) # delete whole next line
line2 = line2[2:end]*'\n' # don't include leading '\n'
b = beginofline(buf)
b = beginofline(buf, first(reg))
edit_splice!(buf, b => b, line2)
true
end

# return the region if active, or the current position as a Region otherwise
region_if_active(s)::Region = is_region_active(s) ? region(s) : position(s)=>position(s)

function edit_transpose_lines_up!(s::MIState)
set_action!(s, :edit_transpose_lines_up!)
if edit_transpose_lines_up!(buffer(s))
if edit_transpose_lines_up!(buffer(s), region_if_active(s))
refresh_line(s)
else
# beeping would be too noisy here
Expand All @@ -993,7 +995,7 @@ end

function edit_transpose_lines_down!(s::MIState)
set_action!(s, :edit_transpose_lines_down!)
if edit_transpose_lines_down!(buffer(s))
if edit_transpose_lines_down!(buffer(s), region_if_active(s))
refresh_line(s)
else
:ignore
Expand Down
30 changes: 22 additions & 8 deletions test/lineedit.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Base.LineEdit
using Base.LineEdit: edit_insert, buffer, content, setmark, getmark
using Base.LineEdit: edit_insert, buffer, content, setmark, getmark, region

isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl"))
using Main.TestHelpers
Expand Down Expand Up @@ -802,19 +802,33 @@ end
end

@testset "edit_transpose_lines_{up,down}!" begin
transpose_lines_up!(buf) = LineEdit.edit_transpose_lines_up!(buf, position(buf)=>position(buf))
transpose_lines_up_reg!(buf) = LineEdit.edit_transpose_lines_up!(buf, region(buf))
transpose_lines_down!(buf) = LineEdit.edit_transpose_lines_down!(buf, position(buf)=>position(buf))
transpose_lines_down_reg!(buf) = LineEdit.edit_transpose_lines_down!(buf, region(buf))

local buf
buf = IOBuffer()

write(buf, "l1\nl2\nl3")
seek(buf, 0)
@test LineEdit.edit_transpose_lines_up!(buf) == false
@test transform!(LineEdit.edit_transpose_lines_up!, buf) == ("l1\nl2\nl3", 0, 0)
@test transform!(LineEdit.edit_transpose_lines_down!, buf) == ("l2\nl1\nl3", 3, 0)
@test LineEdit.edit_transpose_lines_down!(buf) == true
@test transpose_lines_up!(buf) == false
@test transform!(transpose_lines_up!, buf) == ("l1\nl2\nl3", 0, 0)
@test transform!(transpose_lines_down!, buf) == ("l2\nl1\nl3", 3, 0)
@test transpose_lines_down!(buf) == true
@test String(take!(copy(buf))) == "l2\nl3\nl1"
@test LineEdit.edit_transpose_lines_down!(buf) == false
@test transpose_lines_down!(buf) == false
@test String(take!(copy(buf))) == "l2\nl3\nl1" # no change
LineEdit.edit_move_right(buf)
@test transform!(LineEdit.edit_transpose_lines_up!, buf) == ("l2\nl1\nl3", 4, 0)
@test transform!(transpose_lines_up!, buf) == ("l2\nl1\nl3", 4, 0)
LineEdit.edit_move_right(buf)
@test transform!(LineEdit.edit_transpose_lines_up!, buf) == ("l1\nl2\nl3", 2, 0)
@test transform!(transpose_lines_up!, buf) == ("l1\nl2\nl3", 2, 0)

# multiline
@test transpose_lines_up_reg!(buf) == false
@test transform!(transpose_lines_down_reg!, buf) == ("l2\nl1\nl3", 5, 0)
Base.LineEdit.edit_exchange_point_and_mark(buf)
seek(buf, 1)
@test transpose_lines_up_reg!(buf) == false
@test transform!(transpose_lines_down_reg!, buf) == ("l3\nl2\nl1", 4, 8)
end

0 comments on commit d787423

Please sign in to comment.