mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Support OSC and treat \1 \2 correctly
This commit is contained in:
parent
70166b3ca3
commit
9a68aba79f
1 changed files with 53 additions and 12 deletions
|
@ -82,7 +82,9 @@ class Reline::LineEditor
|
||||||
MenuInfo = Struct.new('MenuInfo', :target, :list)
|
MenuInfo = Struct.new('MenuInfo', :target, :list)
|
||||||
|
|
||||||
CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
|
CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
|
||||||
NON_PRINTING_ESCAPES = "\1\2"
|
OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
|
||||||
|
NON_PRINTING_START = "\1"
|
||||||
|
NON_PRINTING_END = "\2"
|
||||||
|
|
||||||
def initialize(config)
|
def initialize(config)
|
||||||
@config = config
|
@config = config
|
||||||
|
@ -180,19 +182,31 @@ class Reline::LineEditor
|
||||||
lines = [String.new(encoding: @encoding)]
|
lines = [String.new(encoding: @encoding)]
|
||||||
height = 1
|
height = 1
|
||||||
width = 0
|
width = 0
|
||||||
prompt = prompt.tr(NON_PRINTING_ESCAPES, '')
|
|
||||||
str = str.tr(NON_PRINTING_ESCAPES, '')
|
|
||||||
rest = "#{prompt}#{str}".encode(Encoding::UTF_8)
|
rest = "#{prompt}#{str}".encode(Encoding::UTF_8)
|
||||||
|
in_zero_width = false
|
||||||
loop do
|
loop do
|
||||||
break if rest.empty?
|
break if rest.empty?
|
||||||
if rest =~ /\A#{CSI_REGEXP}/
|
if rest.start_with?(NON_PRINTING_START)
|
||||||
|
rest.delete_prefix!(NON_PRINTING_START)
|
||||||
|
in_zero_width = true
|
||||||
|
elsif rest.start_with?(NON_PRINTING_END)
|
||||||
|
rest.delete_prefix!(NON_PRINTING_END)
|
||||||
|
in_zero_width = false
|
||||||
|
elsif rest.start_with?(CSI_REGEXP)
|
||||||
|
lines.last << $&
|
||||||
|
rest = $'
|
||||||
|
elsif rest.start_with?(OSC_REGEXP)
|
||||||
lines.last << $&
|
lines.last << $&
|
||||||
rest = $'
|
rest = $'
|
||||||
else
|
else
|
||||||
gcs = rest.grapheme_clusters
|
gcs = rest.grapheme_clusters
|
||||||
gc = gcs.first
|
gc = gcs.first
|
||||||
rest = gcs[1..-1].join
|
rest = gcs[1..-1].join
|
||||||
|
if in_zero_width
|
||||||
|
mbchar_width = 0
|
||||||
|
else
|
||||||
mbchar_width = Reline::Unicode.get_mbchar_width(gc)
|
mbchar_width = Reline::Unicode.get_mbchar_width(gc)
|
||||||
|
end
|
||||||
width += mbchar_width
|
width += mbchar_width
|
||||||
if width > max_width
|
if width > max_width
|
||||||
width = mbchar_width
|
width = mbchar_width
|
||||||
|
@ -825,15 +839,42 @@ class Reline::LineEditor
|
||||||
new_str
|
new_str
|
||||||
end
|
end
|
||||||
|
|
||||||
private def calculate_width(str, allow_csi = false)
|
private def calculate_width(str, allow_escape_code = false)
|
||||||
if allow_csi
|
if allow_escape_code
|
||||||
str = str.gsub(CSI_REGEXP, '')
|
width = 0
|
||||||
str = str.tr(NON_PRINTING_ESCAPES, '')
|
rest = str.encode(Encoding::UTF_8)
|
||||||
|
in_zero_width = false
|
||||||
|
loop do
|
||||||
|
break if rest.empty?
|
||||||
|
if rest.start_with?(NON_PRINTING_START)
|
||||||
|
rest.delete_prefix!(NON_PRINTING_START)
|
||||||
|
in_zero_width = true
|
||||||
|
elsif rest.start_with?(NON_PRINTING_END)
|
||||||
|
rest.delete_prefix!(NON_PRINTING_END)
|
||||||
|
in_zero_width = false
|
||||||
|
elsif rest.start_with?(CSI_REGEXP)
|
||||||
|
rest = $'
|
||||||
|
elsif rest.start_with?(OSC_REGEXP)
|
||||||
|
rest = $'
|
||||||
|
else
|
||||||
|
gcs = rest.grapheme_clusters
|
||||||
|
gc = gcs.first
|
||||||
|
rest = gcs[1..-1].join
|
||||||
|
if in_zero_width
|
||||||
|
mbchar_width = 0
|
||||||
|
else
|
||||||
|
mbchar_width = Reline::Unicode.get_mbchar_width(gc)
|
||||||
end
|
end
|
||||||
|
width += mbchar_width
|
||||||
|
end
|
||||||
|
end
|
||||||
|
width
|
||||||
|
else
|
||||||
str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |width, gc|
|
str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |width, gc|
|
||||||
width + Reline::Unicode.get_mbchar_width(gc)
|
width + Reline::Unicode.get_mbchar_width(gc)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private def key_delete(key)
|
private def key_delete(key)
|
||||||
if @config.editing_mode_is?(:vi_insert, :emacs)
|
if @config.editing_mode_is?(:vi_insert, :emacs)
|
||||||
|
|
Loading…
Reference in a new issue