Module: Paint
- Defined in:
- lib/paint.rb,
lib/paint/util.rb,
lib/paint/version.rb,
lib/paint/constants.rb,
lib/paint/rgb_colors.rb
Constant Summary collapse
- VERSION =
"2.3.0"
- NOTHING =
Clears all colors
"\033[0m"
- TRUE_COLOR =
Number of possible colors in TRUE COLOR mode
0xFFFFFF
- ANSI_COLORS =
Basic colors (often, the color differs when using the bright effect) Final color will be 30 + value for foreground and 40 + value for background
{ :black => 0, :red => 1, :green => 2, :yellow => 3, :blue => 4, :magenta => 5, :cyan => 6, :white => 7, :gray => 7, :default => 9, }.freeze
- ANSI_COLORS_FOREGROUND =
{ :black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :magenta => 35, :cyan => 36, :white => 37, :gray => 37, :default => 39, }.freeze
- ANSI_COLORS_BACKGROUND =
{ :black => 40, :red => 41, :green => 42, :yellow => 43, :blue => 44, :magenta => 45, :cyan => 46, :white => 47, :gray => 47, :default => 49, }.freeze
- ANSI_EFFECTS =
Terminal effects - most of them are not supported ;) See en.wikipedia.org/wiki/ANSI_escape_code
{ :reset => 0, :nothing => 0, # usually supported :bright => 1, :bold => 1, # usually supported :faint => 2, :italic => 3, :underline => 4, # usually supported :blink => 5, :slow_blink => 5, :rapid_blink => 6, :inverse => 7, :swap => 7, # usually supported :conceal => 8, :hide => 9, :default_font => 10, :font0 => 10, :font1 => 11, :font2 => 12, :font3 => 13, :font4 => 14, :font5 => 15, :font6 => 16, :font7 => 17, :font8 => 18, :font9 => 19, :fraktur => 20, :bright_off => 21, :bold_off => 21, :double_underline => 21, :clean => 22, :italic_off => 23, :fraktur_off => 23, :underline_off => 24, :blink_off => 25, :inverse_off => 26, :positive => 26, :conceal_off => 27, :show => 27, :reveal => 27, :crossed_off => 29, :crossed_out_off => 29, :frame => 51, :encircle => 52, :overline => 53, :frame_off => 54, :encircle_off => 54, :overline_off => 55, }.freeze
- RGB_COLORS_ANSI =
A list of color names for standard ansi colors, needed for 16/8 color fallback mode See en.wikipedia.org/wiki/ANSI_escape_code#Colors
{ :black => [ 0, 0, 0], :red => [205, 0, 0], :green => [ 0, 205, 0], :yellow => [205, 205, 0], :blue => [ 0, 0, 238], :magenta => [205, 0, 205], :cyan => [ 0, 205, 205], :white => [229, 229, 229], :gray => [229, 229, 229], }.each { |k, v| v.freeze }.freeze
- RGB_COLORS_ANSI_BRIGHT =
A list of color names for standard bright ansi colors, needed for 16 color fallback mode See en.wikipedia.org/wiki/ANSI_escape_code#Colors
{ :black => [127, 127, 127], :red => [255, 0, 0], :green => [ 0, 255, 0], :yellow => [255, 255, 0], :blue => [ 92, 92, 255], :magenta => [255, 0, 255], :cyan => [ 0, 255, 255], :white => [255, 255, 255], :gray => [255, 255, 255], }.each { |k, v| v.freeze }.freeze
- RGB_COLORS_INDEX_FILENAME =
File.dirname(__FILE__) + "/../../data/rgb_colors.marshal.gz"
Class Attribute Summary collapse
-
.mode ⇒ Object
This variable influences the color code generation Currently supported values: * 0xFFFFFF - 24-bit (~16 million) colors, aka truecolor * 256 - 256 colors * 16 - only ansi colors and bright effect * 8 - only ansi colors * 0 - no colorization!.
Class Method Summary collapse
-
.%(paint_arguments, clear_color = NOTHING) ⇒ Object
Takes an array with string and color options and colorizes the string, extended version with nesting and substitution support.
-
.[](string, *options) ⇒ Object
Takes a string and color options and colorizes the string, fast version without nesting.
-
.color(*options) ⇒ Object
Transforms options into the desired color.
-
.detect_mode ⇒ Object
Determine supported colors Note: there’s no reliable test for 24-bit color support.
-
.effect(effect_name) ⇒ Object
Creates the specified effect by looking it up in Paint::ANSI_EFFECTS.
-
.random(background = false) ⇒ Object
Creates a random ANSI color.
-
.rgb(red, green, blue, background = false) ⇒ Object
If not true_color, creates a 256-compatible color from rgb values, otherwise, an exact 24-bit color.
-
.rgb_hex(string, background = false) ⇒ Object
Creates RGB color from a HTML-like color definition string.
-
.rgb_name(color_name, background = false) ⇒ Object
Creates a RGB from a name found in Paint::RGB_COLORS (based on rgb.txt).
-
.simple(color_name, background = false) ⇒ Object
Creates simple ansi color by looking it up on Paint::ANSI_COLORS.
-
.unpaint(string) ⇒ Object
Removes any color and effect strings.
-
.wrap(*ansi_codes) ⇒ Object
Adds ANSI sequence.
Class Attribute Details
.mode ⇒ Object
This variable influences the color code generation Currently supported values:
-
0xFFFFFF - 24-bit (~16 million) colors, aka truecolor
-
256 - 256 colors
-
16 - only ansi colors and bright effect
-
8 - only ansi colors
-
0 - no colorization!
112 113 114 |
# File 'lib/paint.rb', line 112 def mode @mode end |
Class Method Details
.%(paint_arguments, clear_color = NOTHING) ⇒ Object
Takes an array with string and color options and colorizes the string, extended version with nesting and substitution support
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/paint.rb', line 20 def %(paint_arguments, clear_color = NOTHING) string, * = paint_arguments return string.to_s if .empty? substitutions = .pop if [-1].is_a?(Hash) = [0] if .size == 1 && ![0].respond_to?(:to_ary) current_color = @cache[] # Substitutions & Nesting if substitutions substitutions.each{ |key, value| string = string.gsub( "%{#{key}}", value.is_a?(Array) ? self.%(value, clear_color + current_color) : value.to_s ) } end # Wrap string (if Paint.mode > 0) if @mode.zero? string.to_s else current_color + string.to_s + clear_color end end |
.[](string, *options) ⇒ Object
Takes a string and color options and colorizes the string, fast version without nesting
12 13 14 15 16 |
# File 'lib/paint.rb', line 12 def [](string, *) return string.to_s if @mode.zero? || .empty? = [0] if .size == 1 && ![0].respond_to?(:to_ary) @cache[] + string.to_s + NOTHING end |
.color(*options) ⇒ Object
Transforms options into the desired color. Used by @cache
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/paint.rb', line 48 def color(*) return '' if @mode.zero? || .empty? mix = [] color_seen = false colors = ANSI_COLORS_FOREGROUND .each{ |option| case option when Symbol if color = colors[option] mix << color color_seen = :set elsif ANSI_EFFECTS.key?(option) mix << effect(option) else raise ArgumentError, "Unknown color or effect: #{ option }" end when Array if option.size == 3 && option.all?{ |n| n.is_a? Numeric } mix << rgb(*[*option, color_seen]) color_seen = :set else raise ArgumentError, "Array argument must contain 3 numerals" end when ::String if option =~ /\A#?(?<hex_color>[[:xdigit:]]{3}{1,2})\z/ # 3 or 6 hex chars mix << rgb_hex($~[:hex_color], color_seen) color_seen = :set else mix << rgb_name(option, color_seen) color_seen = :set end when Numeric integer = option.to_i color_seen = :set if (30..49).include?(integer) mix << integer when nil color_seen = :set else raise ArgumentError, "Invalid argument: #{ option.inspect }" end if color_seen == :set colors = ANSI_COLORS_BACKGROUND color_seen = true end } wrap(*mix) end |
.detect_mode ⇒ Object
Determine supported colors Note: there’s no reliable test for 24-bit color support
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/paint.rb', line 178 def detect_mode if ENV['NO_COLOR'] # see https://no-color.org/ 0 elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # windows if ENV['ANSICON'] 16 elsif ENV['ConEmuANSI'] == 'ON' TRUE_COLOR else 0 end elsif ENV['TERM_PROGRAM'] == 'Apple_Terminal' 256 else case ENV['TERM'] when /^rxvt-(?:.*)-256color$/ 256 when /-color$/, /^rxvt/ 16 else # optimistic default TRUE_COLOR end end end |
.effect(effect_name) ⇒ Object
Creates the specified effect by looking it up in Paint::ANSI_EFFECTS
172 173 174 |
# File 'lib/paint.rb', line 172 def effect(effect_name) ANSI_EFFECTS[effect_name] end |
.random(background = false) ⇒ Object
Creates a random ANSI color
12 13 14 |
# File 'lib/paint/util.rb', line 12 def random(background = false) (background ? 40 : 30) + rand(8) end |
.rgb(red, green, blue, background = false) ⇒ Object
If not true_color, creates a 256-compatible color from rgb values, otherwise, an exact 24-bit color
140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/paint.rb', line 140 def rgb(red, green, blue, background = false) case @mode when 8 "#{background ? 4 : 3}#{rgb_to_ansi(red, green, blue, false)}" when 16 "#{background ? 4 : 3}#{rgb_to_ansi(red, green, blue, true)}" when 256 "#{background ? 48 : 38}#{rgb_to_256(red, green, blue)}" when TRUE_COLOR "#{background ? 48 : 38}#{rgb_true(red, green, blue)}" end end |
.rgb_hex(string, background = false) ⇒ Object
Creates RGB color from a HTML-like color definition string
154 155 156 157 158 159 160 161 162 |
# File 'lib/paint.rb', line 154 def rgb_hex(string, background = false) case string.size when 6 color_code = string.each_char.each_slice(2).map{ |hex_color| hex_color.join.to_i(16) } when 3 color_code = string.each_char.map{ |hex_color_half| (hex_color_half*2).to_i(16) } end rgb(*[*color_code, background]) end |
.rgb_name(color_name, background = false) ⇒ Object
Creates a RGB from a name found in Paint::RGB_COLORS (based on rgb.txt)
165 166 167 168 169 |
# File 'lib/paint.rb', line 165 def rgb_name(color_name, background = false) if color_code = RGB_COLORS[color_name] rgb(*[*color_code, background]) end end |
.simple(color_name, background = false) ⇒ Object
Creates simple ansi color by looking it up on Paint::ANSI_COLORS
134 135 136 |
# File 'lib/paint.rb', line 134 def simple(color_name, background = false) (background ? 40 : 30) + ANSI_COLORS[color_name] end |
.unpaint(string) ⇒ Object
Removes any color and effect strings
7 8 9 |
# File 'lib/paint/util.rb', line 7 def unpaint(string) string.gsub(/\e\[(?:[0-9];?)+m/, '') end |
.wrap(*ansi_codes) ⇒ Object
Adds ANSI sequence
129 130 131 |
# File 'lib/paint.rb', line 129 def wrap(*ansi_codes) "\033[" + ansi_codes*";" + "m" end |