You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

89 lines
2.1 KiB

class Wrapper
def self.wrap(text, prefix = ' > ', length = 80)
text = carriage_return_filler(text.chomp(''), length)
pure = ''
ansi_code = {}
while (md = text.match(/\e\[\d+;?\d*m/))
pos = md.begin(0) + pure.length
pure += md.pre_match
text = md.post_match
append_in_hash(ansi_code, pos, md.match(0))
end
pure += text
offset = 0
ansi_extra = {}
rows = pure.length / length
last_code = nil
rows.times do |i|
pos = (i + 1) * length
last_code = last_ansi_by_range(ansi_code, last_code, offset, pos)
if last_code
append_in_hash(ansi_extra, pos, "\e[0m\n#{prefix}#{last_code}")
elsif pos < pure.length
append_in_hash(ansi_extra, pos, "\n#{prefix}")
end
offset = pos + 1
end
ansi_extra.each_pair do |k, v|
append_in_hash(ansi_code, k, v.first)
end
ansi_code = ansi_code.sort
final = pure
offset = 0
ansi_code.each do |k, v|
insert_text = v.join
final = final.insert(k + offset, insert_text)
offset += insert_text.length
end
final
end
private
def self.carriage_return_filler(text, length)
lines = text.split("\n")
return text if lines.count < 2
last_ansi = nil
final = lines.map do |line|
fill_count = length - line.length
current = line
result = last_ansi ? "#{last_ansi}#{line}" : line
last_ansi = nil if last_ansi == "\e[0m"
while (md = current.match(/\e\[\d+;?\d*m/))
last_ansi = md.to_s
fill_count += last_ansi.length
current = md.post_match
end
result = "#{result}\e[0m" if last_ansi
next result if fill_count < 1
"#{result}#{' ' * fill_count}"
end.join
last_ansi ? "#{final}\e[0m" : final
end
def self.last_ansi_by_range(ansi_code, last_code, offset, pos)
pos.downto(offset) do |i|
next unless ansi_code.has_key?(i)
result = ansi_code[i].last
result = nil if result == "\e[0m"
return result
end
last_code
end
def self.append_in_hash(hash, key, value)
if hash.has_key?(key)
hash[key] << value
else
hash[key] = [value]
end
end
end