1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Implement transpose-words

This commit is contained in:
aycabta 2019-06-04 06:39:02 +09:00
parent c9b74f9fd9
commit 4b7213a85a
4 changed files with 157 additions and 1 deletions

View file

@ -489,7 +489,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
# 243 M-s
:ed_unassigned,
# 244 M-t
:ed_unassigned,
:ed_transpose_words,
# 245 M-u
:em_upper_case,
# 246 M-v

View file

@ -1406,6 +1406,19 @@ class Reline::LineEditor
end
end
private def ed_transpose_words(key)
left_word_start, middle_start, right_word_start, after_start = Reline::Unicode.ed_transpose_words(@line, @byte_pointer)
before = @line.byteslice(0, left_word_start)
left_word = @line.byteslice(left_word_start, middle_start - left_word_start)
middle = @line.byteslice(middle_start, right_word_start - middle_start)
right_word = @line.byteslice(right_word_start, after_start - right_word_start)
after = @line.byteslice(after_start, @line.bytesize - after_start)
@line = before + right_word + middle + left_word + after
from_head_to_left_word = before + right_word + middle + left_word
@byte_pointer = from_head_to_left_word.bytesize
@cursor = calculate_width(from_head_to_left_word)
end
private def em_capitol_case(key)
if @line.bytesize > @byte_pointer
byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(@line, @byte_pointer)

View file

@ -188,6 +188,107 @@ class Reline::Unicode
[byte_size, width]
end
def self.ed_transpose_words(line, byte_pointer)
right_word_start = nil
size = get_next_mbchar_size(line, byte_pointer)
mbchar = line.byteslice(byte_pointer, size)
if size.zero?
# ' aaa bbb [cursor]'
byte_size = 0
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
byte_size -= size
end
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size -= size
end
right_word_start = byte_pointer + byte_size
byte_size = 0
while line.bytesize > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size += size
end
after_start = byte_pointer + byte_size
elsif mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
# ' aaa bb[cursor]b'
byte_size = 0
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size -= size
end
right_word_start = byte_pointer + byte_size
byte_size = 0
while line.bytesize > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size += size
end
after_start = byte_pointer + byte_size
else
byte_size = 0
while (line.bytesize - 1) > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
byte_size += size
end
if (byte_pointer + byte_size) == (line.bytesize - 1)
# ' aaa bbb [cursor] '
after_start = line.bytesize
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
byte_size -= size
end
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size -= size
end
right_word_start = byte_pointer + byte_size
else
# ' aaa [cursor] bbb '
right_word_start = byte_pointer + byte_size
while line.bytesize > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size += size
end
after_start = byte_pointer + byte_size
end
end
byte_size = right_word_start - byte_pointer
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
byte_size -= size
end
middle_start = byte_pointer + byte_size
byte_size = middle_start - byte_pointer
while 0 < (byte_pointer + byte_size)
size = get_prev_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size - size, size)
break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
byte_size -= size
end
left_word_start = byte_pointer + byte_size
[left_word_start, middle_start, right_word_start, after_start]
end
def self.vi_big_forward_word(line, byte_pointer)
width = 0
byte_size = 0

View file

@ -819,6 +819,48 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_line("\u3099あさ")
end
def test_ed_transpose_words
input_keys('abc def')
assert_line('abc def')
assert_byte_pointer_size('abc def')
assert_cursor(7)
assert_cursor_max(7)
input_keys("\M-t", false)
assert_line('def abc')
assert_byte_pointer_size('def abc')
assert_cursor(7)
assert_cursor_max(7)
input_keys("\C-a\C-k", false)
input_keys(' abc def ')
input_keys("\C-b" * 4, false)
assert_line(' abc def ')
assert_byte_pointer_size(' abc de')
assert_cursor(8)
assert_cursor_max(12)
input_keys("\M-t", false)
assert_line(' def abc ')
assert_byte_pointer_size(' def abc')
assert_cursor(9)
assert_cursor_max(12)
input_keys("\C-a\C-k", false)
input_keys(' abc def ')
input_keys("\C-b" * 6, false)
assert_line(' abc def ')
assert_byte_pointer_size(' abc ')
assert_cursor(6)
assert_cursor_max(12)
input_keys("\M-t", false)
assert_line(' def abc ')
assert_byte_pointer_size(' def abc')
assert_cursor(9)
assert_cursor_max(12)
input_keys("\M-t", false)
assert_line(' abc def')
assert_byte_pointer_size(' abc def')
assert_cursor(12)
assert_cursor_max(12)
end
def test_ed_digit
input_keys('0123')
assert_byte_pointer_size('0123')