Skip to content

Commit

Permalink
Merge pull request #23378 from JuliaLang/rf/REPL-transpose-words
Browse files Browse the repository at this point in the history
REPL: transpose words with Alt-t
  • Loading branch information
StefanKarpinski committed Aug 22, 2017
2 parents f7d16c6 + 5838d5a commit 4739ca0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 29 deletions.
34 changes: 31 additions & 3 deletions base/repl/LineEdit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,9 @@ function edit_kill_line(s::MIState)
refresh_line(s)
end

edit_transpose(s) = edit_transpose(buffer(s)) && refresh_line(s)
function edit_transpose(buf::IOBuffer)
edit_transpose_chars(s) = edit_transpose_chars(buffer(s)) && refresh_line(s)

function edit_transpose_chars(buf::IOBuffer)
position(buf) == 0 && return false
eof(buf) && char_move_left(buf)
char_move_left(buf)
Expand All @@ -608,6 +609,32 @@ function edit_transpose(buf::IOBuffer)
return true
end

edit_transpose_words(s) = edit_transpose_words(buffer(s)) && refresh_line(s)

function edit_transpose_words(buf::IOBuffer, mode=:emacs)
mode in [:readline, :emacs] ||
throw(ArgumentError("`mode` must be `:readline` or `:emacs`"))
pos = position(buf)
if mode == :emacs
char_move_word_left(buf)
char_move_word_right(buf)
end
char_move_word_right(buf)
e2 = position(buf)
char_move_word_left(buf)
b2 = position(buf)
char_move_word_left(buf)
b1 = position(buf)
char_move_word_right(buf)
e1 = position(buf)
e1 >= b2 && (seek(buf, pos); return false)
word2 = splice!(buf.data, b2+1:e2, buf.data[b1+1:e1])
splice!(buf.data, b1+1:e1, word2)
seek(buf, e2)
true
end


edit_clear(buf::IOBuffer) = truncate(buf, 0)

function edit_clear(s::MIState)
Expand Down Expand Up @@ -1501,7 +1528,8 @@ AnyDict(
input = bracketed_paste(s)
edit_insert(s, input)
end,
"^T" => (s,o...)->edit_transpose(s)
"^T" => (s,o...)->edit_transpose_chars(s),
"\et" => (s,o...)->edit_transpose_words(s),
)

const history_keymap = AnyDict(
Expand Down
28 changes: 13 additions & 15 deletions base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,7 @@ julia> chr2ind(str, 2)
"""
function ind2chr(s::AbstractString, i::Integer)
s[i] # throws error if invalid
j = 1
k = start(s)
while true
c, l = next(s,k)
if i <= k
return j
end
j += 1
k = l
end
unsafe_ind2chr(s, i)
end

"""
Expand All @@ -303,18 +294,25 @@ julia> ind2chr(str, 3)
"""
function chr2ind(s::AbstractString, i::Integer)
i < start(s) && throw(BoundsError(s, i))
k = unsafe_chr2ind(s, i)
s[k] # throws error if invalid
k
end

function map_chr_ind(s::AbstractString, i::Integer, stop, ret)
j = 1
k = start(s)
while true
c, l = next(s,k)
if i == j
return k
end
i == stop((j, k)) && return ret((j, k)) # k could point after the last character
_, k = next(s, k)
j += 1
k = l
end
end

unsafe_ind2chr(s::AbstractString, i::Integer) = map_chr_ind(s, i, last, first)
unsafe_chr2ind(s::AbstractString, i::Integer) = map_chr_ind(s, i, first, last)


struct EachStringIndex{T<:AbstractString}
s::T
end
Expand Down
58 changes: 47 additions & 11 deletions test/lineedit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -308,41 +308,77 @@ let buf = IOBuffer()
@test String(buf.data[1:buf.size]) == "a"
end

## edit_transpose ##
## edit_transpose_chars ##
let buf = IOBuffer()
LineEdit.edit_insert(buf, "abcde")
seek(buf,0)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "abcde"
LineEdit.char_move_right(buf)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "bacde"
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "bcade"
seekend(buf)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "bcaed"
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "bcade"

seek(buf, 0)
LineEdit.edit_clear(buf)
LineEdit.edit_insert(buf, "αβγδε")
seek(buf,0)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "αβγδε"
LineEdit.char_move_right(buf)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βαγδε"
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαδε"
seekend(buf)
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαεδ"
LineEdit.edit_transpose(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαδε"
end

@testset "edit_word_transpose" begin
buf = IOBuffer()
mode = Ref{Symbol}()
function transpose!(i) # i: char indice
seek(buf, Base.unsafe_chr2ind(String(take!(copy(buf))), i+1)-1)
LineEdit.edit_transpose_words(buf, mode[])
str = String(take!(copy(buf)))
str, Base.unsafe_ind2chr(str, position(buf)+1)-1
end

mode[] = :readline
LineEdit.edit_insert(buf, "àbç def gh ")
@test transpose!(0) == ("àbç def gh ", 0)
@test transpose!(1) == ("àbç def gh ", 1)
@test transpose!(2) == ("àbç def gh ", 2)
@test transpose!(3) == ("def àbç gh ", 7)
@test transpose!(4) == ("àbç def gh ", 7)
@test transpose!(5) == ("def àbç gh ", 7)
@test transpose!(6) == ("àbç def gh ", 7)
@test transpose!(7) == ("àbç gh def ", 11)
@test transpose!(10) == ("àbç def gh ", 11)
@test transpose!(11) == ("àbç gh def", 12)
LineEdit.edit_insert(buf, " ")
@test transpose!(13) == ("àbç def gh", 13)

take!(buf)
mode[] = :emacs
LineEdit.edit_insert(buf, "àbç def gh ")
@test transpose!(0) == ("def àbç gh ", 7)
@test transpose!(4) == ("àbç def gh ", 7)
@test transpose!(5) == ("àbç gh def ", 11)
@test transpose!(10) == ("àbç def gh", 12)
LineEdit.edit_insert(buf, " ")
@test transpose!(13) == ("àbç gh def", 13)
end

let
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer())
s = LineEdit.init_state(term, ModalInterface([Prompt("test> ")]))
Expand Down

0 comments on commit 4739ca0

Please sign in to comment.