Skip to content

Commit

Permalink
REPL: add tests for the kill ring
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Sep 3, 2017
1 parent 2d962c1 commit 8422d50
Showing 1 changed file with 112 additions and 84 deletions.
196 changes: 112 additions & 84 deletions test/lineedit.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
# 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

isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl"))
using TestHelpers

# no need to have animation in tests
LineEdit.REGION_ANIMATION_DURATION[] = 0.001

## helper functions

function new_state()
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer())
LineEdit.init_state(term, ModalInterface([Prompt("test> ")]))
end

charseek(buf, i) = seek(buf, Base.unsafe_chr2ind(content(buf), i+1)-1)
charpos(buf, pos=position(buf)) = Base.unsafe_ind2chr(content(buf), pos+1)-1

function transform!(f, s, i = -1) # i is char-based (not bytes) buffer position
buf = buffer(s)
i >= 0 && charseek(buf, i)
f(s)
content(buf), charpos(buf), charpos(buf, getmark(buf))
end


function run_test(d,buf)
global a_foo, b_foo, a_bar, b_bar
a_foo = b_foo = a_bar = b_bar = 0
Expand Down Expand Up @@ -277,25 +300,25 @@ seekend(buf)
@test LineEdit.edit_delete_prev_word(buf)
@test position(buf) == 5
@test buf.size == 5
@test String(buf.data[1:buf.size]) == "type "
@test content(buf) == "type "

buf = IOBuffer("4 +aaa+ x")
seek(buf,8)
@test LineEdit.edit_delete_prev_word(buf)
@test position(buf) == 3
@test buf.size == 4
@test String(buf.data[1:buf.size]) == "4 +x"
@test content(buf) == "4 +x"

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 String(buf.data[1:buf.size]) == "x = func(arg1,arg3)"
@test content(buf) == "x = func(arg1,arg3)"
@test LineEdit.edit_delete_prev_word(buf)
@test String(buf.data[1:buf.size]) == "x = func(arg3)"
@test content(buf) == "x = func(arg3)"
@test LineEdit.edit_delete_prev_word(buf)
@test String(buf.data[1:buf.size]) == "x = arg3)"
@test content(buf) == "x = arg3)"

# Unicode combining characters
let buf = IOBuffer()
Expand All @@ -305,53 +328,49 @@ let buf = IOBuffer()
LineEdit.edit_move_right(buf)
@test nb_available(buf) == 0
LineEdit.edit_backspace(buf)
@test String(buf.data[1:buf.size]) == "a"
@test content(buf) == "a"
end

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

seek(buf, 0)
LineEdit.edit_clear(buf)
LineEdit.edit_insert(buf, "αβγδε")
seek(buf,0)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "αβγδε"
@test content(buf) == "αβγδε"
LineEdit.char_move_right(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βαγδε"
@test content(buf) == "βαγδε"
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαδε"
@test content(buf) == "βγαδε"
seekend(buf)
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαεδ"
@test content(buf) == "βγαεδ"
LineEdit.edit_transpose_chars(buf)
@test String(buf.data[1:buf.size]) == "βγαδε"
@test content(buf) == "βγαδε"
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
transpose!(i) = transform!(buf -> LineEdit.edit_transpose_words(buf, mode[]),
buf, i)[1:2]

mode[] = :readline
LineEdit.edit_insert(buf, "àbç def gh ")
Expand Down Expand Up @@ -379,13 +398,11 @@ end
@test transpose!(13) == ("àbç gh def", 13)
end

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

LineEdit.edit_insert(s,"first line\nsecond line\nthird line")
@test String(buf.data[1:buf.size]) == "first line\nsecond line\nthird line"
@test content(buf) == "first line\nsecond line\nthird line"

## edit_move_line_start/end ##
seek(buf, 0)
Expand Down Expand Up @@ -414,11 +431,11 @@ let
s.key_repeats = 1 # Manually flag a repeated keypress
LineEdit.edit_kill_line(s)
s.key_repeats = 0
@test String(buf.data[1:buf.size]) == "second line\nthird line"
@test content(buf) == "second line\nthird line"
LineEdit.move_line_end(s)
LineEdit.edit_move_right(s)
LineEdit.edit_yank(s)
@test String(buf.data[1:buf.size]) == "second line\nfirst line\nthird line"
@test content(buf) == "second line\nfirst line\nthird line"
end

# Issue 7845
Expand All @@ -439,16 +456,16 @@ let
end

@testset "function prompt indentation" begin
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer(), false)
s = new_state()
term = Base.LineEdit.terminal(s)
# default prompt: PromptState.indent should not be set to a final fixed value
s = LineEdit.init_state(term, ModalInterface([Prompt("julia> ")]))
ps::LineEdit.PromptState = s.mode_state[s.current_mode]
@test ps.indent == -1
# the prompt is modified afterwards to a function
ps.p.prompt = let i = 0
() -> ["Julia is Fun! > ", "> "][mod1(i+=1, 2)] # lengths are 16 and 2
end
buf = LineEdit.buffer(ps)
buf = buffer(ps)
write(buf, "begin\n julia = :fun\nend")
outbuf = IOBuffer()
termbuf = Base.Terminals.TerminalBuffer(outbuf)
Expand All @@ -458,120 +475,107 @@ end
"\r\e[16C julia = :fun\n" *
"\r\e[16Cend\r\e[19C"
LineEdit.refresh_multi_line(termbuf, term, ps)
@test String(take!(copy(outbuf))) ==
@test String(take!(outbuf)) ==
"\r\e[0K\e[1A\r\e[0K\e[1A\r\e[0K\e[1m> \e[0m\r\e[2Cbegin\n" *
"\r\e[2C julia = :fun\n" *
"\r\e[2Cend\r\e[5C"
end

@testset "tab/backspace alignment feature" begin
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer())
s = LineEdit.init_state(term, ModalInterface([Prompt("test> ")]))
function bufferdata(s)
buf = LineEdit.buffer(s)
String(buf.data[1:buf.size])
end
s = new_state()
move_left(s, n) = for x = 1:n
LineEdit.edit_move_left(s)
end

bufpos(s::Base.LineEdit.MIState) = position(LineEdit.buffer(s))

LineEdit.edit_insert(s, "for x=1:10\n")
LineEdit.edit_tab(s)
@test bufferdata(s) == "for x=1:10\n "
@test content(s) == "for x=1:10\n "
LineEdit.edit_backspace(s, true, false)
@test bufferdata(s) == "for x=1:10\n"
@test content(s) == "for x=1:10\n"
LineEdit.edit_insert(s, " ")
@test bufpos(s) == 13
@test position(s) == 13
LineEdit.edit_tab(s)
@test bufferdata(s) == "for x=1:10\n "
@test content(s) == "for x=1:10\n "
LineEdit.edit_insert(s, " ")
LineEdit.edit_backspace(s, true, false)
@test bufferdata(s) == "for x=1:10\n "
@test content(s) == "for x=1:10\n "
LineEdit.edit_insert(s, "éé=3 ")
LineEdit.edit_tab(s)
@test bufferdata(s) == "for x=1:10\n éé=3 "
@test content(s) == "for x=1:10\n éé=3 "
LineEdit.edit_backspace(s, true, false)
@test bufferdata(s) == "for x=1:10\n éé=3"
@test content(s) == "for x=1:10\n éé=3"
LineEdit.edit_insert(s, "\n 1∉x ")
LineEdit.edit_tab(s)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
LineEdit.edit_backspace(s, false, false)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
LineEdit.edit_backspace(s, true, false)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
LineEdit.edit_move_word_left(s)
LineEdit.edit_tab(s)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
LineEdit.move_line_start(s)
@test bufpos(s) == 22
@test position(s) == 22
LineEdit.edit_tab(s, true)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test bufpos(s) == 30
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
@test position(s) == 30
LineEdit.edit_move_left(s)
@test bufpos(s) == 29
@test position(s) == 29
LineEdit.edit_backspace(s, true, true)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test bufpos(s) == 26
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
@test position(s) == 26
LineEdit.edit_tab(s, false) # same as edit_tab(s, true) here
@test bufpos(s) == 30
@test position(s) == 30
move_left(s, 6)
@test bufpos(s) == 24
@test position(s) == 24
LineEdit.edit_backspace(s, true, true)
@test bufferdata(s) == "for x=1:10\n éé=3\n 1∉x "
@test bufpos(s) == 22
@test content(s) == "for x=1:10\n éé=3\n 1∉x "
@test position(s) == 22
LineEdit.edit_kill_line(s)
LineEdit.edit_insert(s, ' '^10)
move_left(s, 7)
@test bufferdata(s) == "for x=1:10\n éé=3\n "
@test bufpos(s) == 25
@test content(s) == "for x=1:10\n éé=3\n "
@test position(s) == 25
LineEdit.edit_tab(s, true, false)
@test bufpos(s) == 32
@test position(s) == 32
move_left(s, 7)
LineEdit.edit_tab(s, true, true)
@test bufpos(s) == 26
@test bufferdata(s) == "for x=1:10\n éé=3\n "
@test position(s) == 26
@test content(s) == "for x=1:10\n éé=3\n "
# test again the same, when there is a next line
LineEdit.edit_insert(s, " \nend")
move_left(s, 11)
@test bufpos(s) == 25
@test position(s) == 25
LineEdit.edit_tab(s, true, false)
@test bufpos(s) == 32
@test position(s) == 32
move_left(s, 7)
LineEdit.edit_tab(s, true, true)
@test bufpos(s) == 26
@test bufferdata(s) == "for x=1:10\n éé=3\n \nend"
@test position(s) == 26
@test content(s) == "for x=1:10\n éé=3\n \nend"
end

@testset "newline alignment feature" begin
term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer())
s = LineEdit.init_state(term, ModalInterface([Prompt("test> ")]))
function bufferdata(s)
buf = LineEdit.buffer(s)
String(buf.data[1:buf.size])
end

s = new_state()
LineEdit.edit_insert(s, "for x=1:10\n é = 1")
LineEdit.edit_insert_newline(s)
@test bufferdata(s) == "for x=1:10\n é = 1\n "
@test content(s) == "for x=1:10\n é = 1\n "
LineEdit.edit_insert(s, " b = 2")
LineEdit.edit_insert_newline(s)
@test bufferdata(s) == "for x=1:10\n é = 1\n b = 2\n "
@test content(s) == "for x=1:10\n é = 1\n b = 2\n "
# after an empty line, should still insert the expected number of spaces
LineEdit.edit_insert_newline(s)
@test bufferdata(s) == "for x=1:10\n é = 1\n b = 2\n \n "
@test content(s) == "for x=1:10\n é = 1\n b = 2\n \n "
LineEdit.edit_insert_newline(s, 0)
@test bufferdata(s) == "for x=1:10\n é = 1\n b = 2\n \n \n"
@test content(s) == "for x=1:10\n é = 1\n b = 2\n \n \n"
LineEdit.edit_insert_newline(s, 2)
@test bufferdata(s) == "for x=1:10\n é = 1\n b = 2\n \n \n\n "
@test content(s) == "for x=1:10\n é = 1\n b = 2\n \n \n\n "
# test when point before first letter of the line
for i=6:10
LineEdit.edit_clear(s)
LineEdit.edit_insert(s, "begin\n x")
seek(LineEdit.buffer(s), i)
LineEdit.edit_insert_newline(s)
@test bufferdata(s) == "begin\n" * ' '^(i-6) * "\n x"
@test content(s) == "begin\n" * ' '^(i-6) * "\n x"
end
end

Expand All @@ -586,3 +590,27 @@ end
LineEdit.edit_lower_case(buf)
@test String(take!(copy(buf))) == "AA Bb cc"
end

@testset "kill ring" begin
s = new_state()
buf = buffer(s)
edit_insert(s, "ça ≡ nothing")
@test transform!(LineEdit.edit_copy_region, s) == ("ça ≡ nothing", 12, 0)
@test s.kill_ring[end] == "ça ≡ nothing"
@test transform!(LineEdit.edit_exchange_point_and_mark, s)[2:3] == (0, 12)
charseek(buf, 8); setmark(s)
charseek(buf, 1)
@test transform!(LineEdit.edit_kill_region, s) == ("çhing", 1, 1)
@test s.kill_ring[end] == "a ≡ not"
charseek(buf, 0)
@test transform!(LineEdit.edit_yank, s) == ("a ≡ notçhing", 7, 0)
# next action will fail, as yank-pop doesn't know a yank was just issued
@test transform!(LineEdit.edit_yank_pop, s) == ("a ≡ notçhing", 7, 0)
s.last_action = :edit_yank
# not this should work:
@test transform!(LineEdit.edit_yank_pop, s) == ("ça ≡ nothingçhing", 12, 0)
@test s.kill_idx == 1
LineEdit.edit_kill_line(s)
@test s.kill_ring[end] == "çhing"
@test s.kill_idx == 3
end

0 comments on commit 8422d50

Please sign in to comment.