summaryrefslogtreecommitdiff
path: root/lib/reline
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2020-08-28 02:09:34 +0900
committeraycabta <aycabta@gmail.com>2020-08-28 11:05:18 +0900
commit1f09c4362806e3ce8a7b15e0effc3abb7f53411d (patch)
tree725e6234de6094359251a267e8f05d0435c9ed92 /lib/reline
parentcdd7d41046f6c91dfa8a1f0612dc686b79f6e849 (diff)
[ruby/reline] Move width calculator methods to Reline::Unicode
https://github.com/ruby/reline/commit/f348ecd9f5
Diffstat (limited to 'lib/reline')
-rw-r--r--lib/reline/line_editor.rb68
-rw-r--r--lib/reline/unicode.rb68
2 files changed, 72 insertions, 64 deletions
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index c9d88edc85..b4d2b457c7 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -50,12 +50,6 @@ class Reline::LineEditor
CompletionJourneyData = Struct.new('CompletionJourneyData', :preposing, :postposing, :list, :pointer)
MenuInfo = Struct.new('MenuInfo', :target, :list)
- CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
- OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
- NON_PRINTING_START = "\1"
- NON_PRINTING_END = "\2"
- WIDTH_SCANNER = /\G(?:#{NON_PRINTING_START}|#{NON_PRINTING_END}|#{CSI_REGEXP}|#{OSC_REGEXP}|\X)/
-
def initialize(config, encoding)
@config = config
@completion_append_character = ''
@@ -234,40 +228,8 @@ class Reline::LineEditor
width.div(@screen_size.last) + 1
end
- private def split_by_width(prompt, str, max_width)
- lines = [String.new(encoding: @encoding)]
- height = 1
- width = 0
- rest = "#{prompt}#{str}".encode(Encoding::UTF_8)
- in_zero_width = false
- rest.scan(WIDTH_SCANNER) do |gc|
- case gc
- when NON_PRINTING_START
- in_zero_width = true
- when NON_PRINTING_END
- in_zero_width = false
- when CSI_REGEXP, OSC_REGEXP
- lines.last << gc
- else
- unless in_zero_width
- mbchar_width = Reline::Unicode.get_mbchar_width(gc)
- if (width += mbchar_width) > max_width
- width = mbchar_width
- lines << nil
- lines << String.new(encoding: @encoding)
- height += 1
- end
- end
- lines.last << gc
- end
- end
- # The cursor moves to next line in first
- if width == max_width
- lines << nil
- lines << String.new(encoding: @encoding)
- height += 1
- end
- [lines, height]
+ private def split_by_width(str, max_width)
+ Reline::Unicode.split_by_width(str, max_width, @encoding)
end
private def scroll_down(val)
@@ -511,7 +473,7 @@ class Reline::LineEditor
end
private def render_partial(prompt, prompt_width, line_to_render, with_control = true)
- visual_lines, height = split_by_width(prompt, line_to_render.nil? ? '' : line_to_render, @screen_size.last)
+ visual_lines, height = split_by_width(line_to_render.nil? ? prompt : prompt + line_to_render, @screen_size.last)
if with_control
if height > @highest_in_this
diff = height - @highest_in_this
@@ -1081,29 +1043,7 @@ class Reline::LineEditor
end
private def calculate_width(str, allow_escape_code = false)
- if allow_escape_code
- width = 0
- rest = str.encode(Encoding::UTF_8)
- in_zero_width = false
- rest.scan(WIDTH_SCANNER) do |gc|
- case gc
- when NON_PRINTING_START
- in_zero_width = true
- when NON_PRINTING_END
- in_zero_width = false
- when CSI_REGEXP, OSC_REGEXP
- else
- unless in_zero_width
- width += Reline::Unicode.get_mbchar_width(gc)
- end
- end
- end
- width
- else
- str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc|
- w + Reline::Unicode.get_mbchar_width(gc)
- }
- end
+ Reline::Unicode.calculate_width(str, allow_escape_code)
end
private def key_delete(key)
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
index 4b30f044f3..3b5ef6fb99 100644
--- a/lib/reline/unicode.rb
+++ b/lib/reline/unicode.rb
@@ -35,6 +35,12 @@ class Reline::Unicode
}
EscapedChars = EscapedPairs.keys.map(&:chr)
+ CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
+ OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
+ NON_PRINTING_START = "\1"
+ NON_PRINTING_END = "\2"
+ WIDTH_SCANNER = /\G(?:#{NON_PRINTING_START}|#{NON_PRINTING_END}|#{CSI_REGEXP}|#{OSC_REGEXP}|\X)/
+
def self.get_mbchar_byte_size_by_first_char(c)
# Checks UTF-8 character byte size
case c.ord
@@ -85,6 +91,68 @@ class Reline::Unicode
end
end
+ def self.calculate_width(str, allow_escape_code = false)
+ if allow_escape_code
+ width = 0
+ rest = str.encode(Encoding::UTF_8)
+ in_zero_width = false
+ rest.scan(WIDTH_SCANNER) do |gc|
+ case gc
+ when NON_PRINTING_START
+ in_zero_width = true
+ when NON_PRINTING_END
+ in_zero_width = false
+ when CSI_REGEXP, OSC_REGEXP
+ else
+ unless in_zero_width
+ width += get_mbchar_width(gc)
+ end
+ end
+ end
+ width
+ else
+ str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc|
+ w + get_mbchar_width(gc)
+ }
+ end
+ end
+
+ def self.split_by_width(str, max_width, encoding)
+ lines = [String.new(encoding: encoding)]
+ height = 1
+ width = 0
+ rest = str.encode(Encoding::UTF_8)
+ in_zero_width = false
+ rest.scan(WIDTH_SCANNER) do |gc|
+ case gc
+ when NON_PRINTING_START
+ in_zero_width = true
+ when NON_PRINTING_END
+ in_zero_width = false
+ when CSI_REGEXP, OSC_REGEXP
+ lines.last << gc
+ else
+ unless in_zero_width
+ mbchar_width = get_mbchar_width(gc)
+ if (width += mbchar_width) > max_width
+ width = mbchar_width
+ lines << nil
+ lines << String.new(encoding: encoding)
+ height += 1
+ end
+ end
+ lines.last << gc
+ end
+ end
+ # The cursor moves to next line in first
+ if width == max_width
+ lines << nil
+ lines << String.new(encoding: encoding)
+ height += 1
+ end
+ [lines, height]
+ end
+
def self.get_next_mbchar_size(line, byte_pointer)
grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first
grapheme ? grapheme.bytesize : 0