summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2019-06-04 06:39:02 +0900
committeraycabta <aycabta@gmail.com>2019-06-04 07:23:36 +0900
commit4b7213a85a6700657b825f8f127ce83a3070bf1d (patch)
treea67ac0525591eefb8a467ee2cf5a731ddcfa2dc2 /lib
parentc9b74f9fd95113df903fc34cc1d6ec3fb3160c85 (diff)
Implement transpose-words
Diffstat (limited to 'lib')
-rw-r--r--lib/reline/key_actor/emacs.rb2
-rw-r--r--lib/reline/line_editor.rb13
-rw-r--r--lib/reline/unicode.rb101
3 files changed, 115 insertions, 1 deletions
diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb
index 7354c9279e..134f424a2c 100644
--- a/lib/reline/key_actor/emacs.rb
+++ b/lib/reline/key_actor/emacs.rb
@@ -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
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 784b8dd7c4..b1769d958a 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -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)
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
index 5523d4fa31..4b30f044f3 100644
--- a/lib/reline/unicode.rb
+++ b/lib/reline/unicode.rb
@@ -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