Skip to content

Instantly share code, notes, and snippets.

@daphee
Last active September 6, 2015 16:06
Show Gist options
  • Save daphee/90f4276fa5c0826167af to your computer and use it in GitHub Desktop.
Save daphee/90f4276fa5c0826167af to your computer and use it in GitHub Desktop.
require "colorize"
# I think a pure regex solution isn't possible unfortunately
# This regex is still reall handy becomes you can
# go from escape code group to escape code and get the text in between
FORMAT_GROUPS_REG = /(?:\e\[(?:(?:[0-9]{1,3});)*(?:[0-9]{1,3})m)+([^\e]+)/
# Procues something like #<MatchData "\e[33;1m\e[99mT" 1:"T">
# This now exctracts the styles from the groups of escape codes
# This is a number either followed by a 'm' or a ';'
FORMAT_REG = /([0-9]{1,3})[;m]/
# To figure out if e.g. the number 33 'overwrites' a current active number of '93'
# We have to know wether both are of the same type (fg, bg or text style)
FG_COLORS = [] of Int32
{% for name in Colorize::Object::COLORS %}
FG_COLORS << Colorize::Object::FORE_{{name.upcase.id}}.to_i
{% end %}
BG_COLORS = [] of Int32
{% for name in Colorize::Object::COLORS %}
BG_COLORS << Colorize::Object::BACK_{{name.upcase.id}}.to_i
{% end %}
TEXT_STYLES = [1, 4]
def optimize input
output = ""
current_format = {
:fg => -1,
:bg => -1,
:style => -1
}
s = "Splitted:\n"
input.scan(FORMAT_GROUPS_REG).each do |match|
if match
text = match[1] || ""
styles = match[0].scan(FORMAT_REG).map {|match| match[1].to_s.to_i}
s += "\t'#{text}' #{styles}" # debug only
this_format = {} of Symbol => Int32
styles.each do |style|
# This could be done in a less readable way
# By iterating over an array [:fg, :bg, :style]
if FG_COLORS.includes? style
this_format[:fg] = style
elsif BG_COLORS.includes? style
this_format[:bg] = style
elsif TEXT_STYLES.includes? style
this_format[:style] = style
elsif style == 0
# Just set every value to 0
# This could be done in a less readable way by
# Including 0 in the fg_color, BG_COLORS, TEXT_STYLES array.
this_format[:fg] = this_format[:bg] = this_format[:style] = 0
else
raise Exception.new "Don't know what to do with style code '#{style}'"
end
end
s += " => #{this_format.values}"
s_helper = [] of Colorize::Object(Int32)
changed_styles = [] of Int32
this_format.each_with_index do |format_type, value|
# If has changed, update current_format and save to write to output string later
if current_format[format_type] != value
current_format[format_type] = value
changed_styles << value
s_helper << value.colorize.green
else
s_helper << value.colorize.red
end
end
# \e[0m is translated to :fg, :bg, :style => 0
# And we don't want multiple zeroes
changed_styles.uniq!
s += " => #{s_helper}\n"
# Write changed style to output string
output += "\e[#{changed_styles.join(";")}m" if changed_styles.length > 0
output += text
end
end
puts s,""
puts "Input: #{input.inspect}\n"
puts "Output: #{output.inspect}\n"
puts "Input: #{input}\e[0m\n"
puts "Output: #{output}\e[0m\n"
output
end
input = "\e[33;1m\e[95mT\e[33;1me\e[33;4ms\e[33mt \e[4mTest \e[0m\e[34mTest \e[33m Test"
optimize(input)
puts
optimize("\e[44m \e[44m \e[44m \e[44m \e[44m \e[44m \e[44m \e[44m \e[44m \e[44m \e[44m ")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment