Skip to content
This repository was archived by the owner on Dec 16, 2022. It is now read-only.

Commit ed9570e

Browse files
committed
Introduce splice_buffer! abstraction for IOBuffer
Behaves just like `splice!` for arrays, except that it accepts 0-indexed positions and keeps the cursor position stable with the text. Minor behavior change to kill_line -- when killing just a newline, that goes into the buffer.
1 parent 4fc2a15 commit ed9570e

File tree

1 file changed

+29
-49
lines changed

1 file changed

+29
-49
lines changed

base/LineEdit.jl

+29-49
Original file line numberDiff line numberDiff line change
@@ -412,23 +412,22 @@ function edit_move_down(s)
412412
changed
413413
end
414414

415-
function memmove(dst::IOBuffer, idst::Int, src::IOBuffer, isrc::Int, num::Int)
416-
num == 0 && return
417-
@assert 0 < num
418-
@assert 0 < idst <= length(dst.data) - num + 1
419-
@assert 0 < isrc <= length(src.data) - num + 1
420-
pdst = pointer(dst.data, idst)
421-
psrc = pointer(src.data, isrc)
422-
ccall(:memmove, Void, (Ptr{Void},Ptr{Void},Csize_t), pdst, psrc, num)
415+
# splice! for IOBuffer: convert from 0-indexed positions, update the size,
416+
# and keep the cursor position stable with the text
417+
function splice_buffer!{T<:Integer}(buf::IOBuffer, r::UnitRange{T}, ins::String = "")
418+
pos = position(buf)
419+
if !isempty(r) && pos in r
420+
seek(buf, first(r))
421+
elseif pos > last(r)
422+
seek(buf, pos - length(r))
423+
end
424+
splice!(buf.data, r .+ 1, ins.data) # position(), etc, are 0-indexed
425+
buf.size = buf.size + sizeof(ins) - length(r)
426+
seek(buf, position(buf) + sizeof(ins))
423427
end
424428

425429
function edit_replace(s, from, to, str)
426-
room = length(str.data) - (to - from)
427-
ensureroom(s.input_buffer, s.input_buffer.size + room)
428-
memmove(s.input_buffer, to+room+1, s.input_buffer, to+1, s.input_buffer.size-to)
429-
s.input_buffer.size += room
430-
seek(s.input_buffer, from)
431-
write(s.input_buffer, str)
430+
splice_buffer!(buffer(s), from:to-1, str)
432431
end
433432

434433
function edit_insert(s::PromptState, c)
@@ -443,17 +442,11 @@ function edit_insert(s::PromptState, c)
443442
end
444443
end
445444

446-
# TODO: Don't use memmove
447445
function edit_insert(buf::IOBuffer, c)
448446
if eof(buf)
449447
write(buf, c)
450448
else
451-
s = string(c)
452-
ensureroom(buf, buf.size-position(buf)+sizeof(s))
453-
oldpos = position(buf)
454-
memmove(buf, position(buf)+1+sizeof(s), buf, position(buf)+1, buf.size-position(buf))
455-
buf.size += sizeof(s)
456-
write(buf, c)
449+
splice_buffer!(buf, position(buf):position(buf)-1, string(c))
457450
end
458451
end
459452

@@ -468,8 +461,7 @@ function edit_backspace(buf::IOBuffer)
468461
if position(buf) > 0 && buf.size > 0
469462
oldpos = position(buf)
470463
char_move_left(buf)
471-
memmove(buf, position(buf)+1, buf, oldpos+1, buf.size-oldpos)
472-
buf.size -= oldpos-position(buf)
464+
splice_buffer!(buf, position(buf):oldpos-1)
473465
return true
474466
else
475467
return false
@@ -478,26 +470,19 @@ end
478470

479471
edit_delete(s) = edit_delete(buffer(s)) ? refresh_line(s) : beep(LineEdit.terminal(s))
480472
function edit_delete(buf::IOBuffer)
481-
# (buf.size == 0 || eof(buf)) && return false
482-
if buf.size > 0 && position(buf) < buf.size
483-
oldpos = position(buf)
484-
char_move_right(buf)
485-
memmove(buf, oldpos+1, buf, position(buf)+1, buf.size-position(buf))
486-
buf.size -= position(buf) - oldpos
487-
seek(buf, oldpos)
488-
return true
489-
else
490-
return false
491-
end
473+
eof(buf) && return false
474+
oldpos = position(buf)
475+
char_move_right(buf)
476+
splice_buffer!(buf, oldpos:position(buf)-1)
477+
true
492478
end
493479

494480
function edit_werase(buf::IOBuffer)
495481
pos1 = position(buf)
496482
char_move_word_left(buf,isspace)
497483
pos0 = position(buf)
498484
pos0 < pos1 || return false
499-
memmove(buf, pos0+1, buf, pos1+1, buf.size-pos1)
500-
buf.size -= pos1 - pos0
485+
splice_buffer!(buf, pos0:pos1-1)
501486
true
502487
end
503488
function edit_werase(s)
@@ -509,8 +494,7 @@ function edit_delete_prev_word(buf::IOBuffer)
509494
char_move_word_left(buf)
510495
pos0 = position(buf)
511496
pos0 < pos1 || return false
512-
memmove(buf, pos0+1, buf, pos1+1, buf.size-pos1)
513-
buf.size -= pos1 - pos0
497+
splice_buffer!(buf, pos0:pos1-1)
514498
true
515499
end
516500
function edit_delete_prev_word(s)
@@ -522,9 +506,7 @@ function edit_delete_next_word(buf::IOBuffer)
522506
char_move_word_right(buf)
523507
pos1 = position(buf)
524508
pos0 < pos1 || return false
525-
seek(buf,pos0)
526-
memmove(buf, pos0+1, buf, pos1+1, buf.size-pos1)
527-
buf.size -= pos1 - pos0
509+
splice_buffer!(buf, pos0:pos1-1)
528510
true
529511
end
530512
function edit_delete_next_word(s)
@@ -537,16 +519,14 @@ function edit_yank(s::MIState)
537519
end
538520

539521
function edit_kill_line(s::MIState)
540-
pos = position(buffer(s))
541-
s.kill_buffer = readline(buffer(s))
542-
rest = readall(buffer(s))
543-
truncate(buffer(s), pos)
544-
if !isempty(s.kill_buffer) && s.kill_buffer[end] == '\n'
522+
buf = buffer(s)
523+
pos = position(buf)
524+
s.kill_buffer = readline(buf)
525+
if length(s.kill_buffer) > 1 && s.kill_buffer[end] == '\n'
545526
s.kill_buffer = s.kill_buffer[1:end-1]
546-
isempty(s.kill_buffer) || print(buffer(s), '\n')
527+
char_move_left(buf)
547528
end
548-
print(buffer(s), rest)
549-
seek(buffer(s), pos)
529+
splice_buffer!(buf, pos:position(buf)-1)
550530
refresh_line(s)
551531
end
552532

0 commit comments

Comments
 (0)