pry-theme 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.travis.yml +8 -1
- data/CHANGELOG.md +40 -0
- data/Gemfile +1 -1
- data/README.md +26 -48
- data/Rakefile +10 -1
- data/VERSION +1 -0
- data/lib/pry-theme/basic_editor.rb +116 -0
- data/lib/pry-theme/color.rb +431 -0
- data/lib/pry-theme/color_table.rb +39 -0
- data/lib/pry-theme/colors/color16.rb +35 -0
- data/lib/pry-theme/colors/color256.rb +30 -0
- data/lib/pry-theme/colors/color8.rb +31 -0
- data/lib/pry-theme/commands.rb +237 -275
- data/lib/pry-theme/declaration.rb +120 -0
- data/lib/pry-theme/definition.rb +111 -0
- data/lib/pry-theme/formattable.rb +26 -0
- data/lib/pry-theme/hex.rb +76 -0
- data/lib/pry-theme/preview.rb +74 -0
- data/lib/pry-theme/rgb.rb +238 -13
- data/lib/pry-theme/term.rb +66 -0
- data/lib/pry-theme/theme.rb +116 -26
- data/lib/pry-theme/theme_list.rb +52 -0
- data/lib/pry-theme/when_started_hook.rb +25 -27
- data/lib/pry-theme.rb +84 -158
- data/pry-theme.gemspec +14 -18
- data/spec/color_table.rb +53 -0
- data/spec/colors/color16_spec.rb +255 -0
- data/spec/colors/color256_spec.rb +323 -0
- data/spec/colors/color8_spec.rb +254 -0
- data/spec/commands_spec.rb +203 -0
- data/spec/helper.rb +16 -0
- data/spec/hex_spec.rb +52 -0
- data/spec/rgb_spec.rb +81 -0
- data/spec/term_spec.rb +23 -0
- data/spec/theme_spec.rb +486 -0
- data/themes/github.prytheme.rb +49 -0
- data/themes/monokai.prytheme.rb +48 -0
- data/themes/pry-classic-16.prytheme.rb +48 -0
- data/themes/pry-classic-256.prytheme.rb +48 -0
- data/themes/pry-classic-8.prytheme.rb +48 -0
- data/themes/pry-cold.prytheme.rb +49 -0
- data/themes/pry-love-16.prytheme.rb +48 -0
- data/themes/pry-love-8.prytheme.rb +48 -0
- data/themes/pry-modern-16.prytheme.rb +48 -0
- data/themes/pry-modern-256.prytheme.rb +48 -0
- data/themes/pry-modern-8.prytheme.rb +48 -0
- data/themes/pry-monochrome.prytheme.rb +32 -0
- data/themes/pry-siberia-16.prytheme.rb +48 -0
- data/themes/pry-siberia-8.prytheme.rb +48 -0
- data/themes/pry-tepid-16.prytheme.rb +48 -0
- data/themes/pry-tepid-8.prytheme.rb +48 -0
- data/themes/pry-zealand-16.prytheme.rb +48 -0
- data/themes/pry-zealand-8.prytheme.rb +49 -0
- data/themes/railscasts.prytheme.rb +50 -0
- data/themes/solarized.prytheme.rb +48 -0
- data/themes/tomorrow.prytheme.rb +48 -0
- data/themes/twilight.prytheme.rb +48 -0
- data/themes/vim-default.prytheme.rb +50 -0
- data/themes/vim-detailed.prytheme.rb +50 -0
- data/themes/zenburn.prytheme.rb +48 -0
- metadata +56 -41
- data/lib/pry-theme/color_converter.rb +0 -55
- data/lib/pry-theme/helper.rb +0 -87
- data/lib/pry-theme/palette.rb +0 -85
- data/lib/pry-theme/term_notation.rb +0 -17
- data/lib/pry-theme/version.rb +0 -3
- data/test/fixtures/pry-classic.prytheme +0 -38
- data/test/helper.rb +0 -56
- data/test/test_color_converter.rb +0 -38
- data/test/test_commands.rb +0 -55
- data/test/test_helper.rb +0 -45
- data/test/test_palette.rb +0 -11
- data/themes/github.prytheme +0 -43
- data/themes/monokai.prytheme +0 -42
- data/themes/pry-classic.prytheme +0 -43
- data/themes/pry-cold.prytheme +0 -43
- data/themes/pry-modern.prytheme +0 -42
- data/themes/railscasts.prytheme +0 -44
- data/themes/saturday.prytheme +0 -42
- data/themes/solarized.prytheme +0 -43
- data/themes/tomorrow.prytheme +0 -43
- data/themes/twilight.prytheme +0 -42
- data/themes/vim-default.prytheme +0 -42
- data/themes/vim-detailed.prytheme +0 -42
- data/themes/zenburn.prytheme +0 -43
@@ -0,0 +1,120 @@
|
|
1
|
+
module PryTheme
|
2
|
+
class Color
|
3
|
+
|
4
|
+
# @since 0.2.0
|
5
|
+
# @api private
|
6
|
+
class Declaration
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def translate(decl, color_model)
|
10
|
+
decl = Declaration.new(decl, color_model)
|
11
|
+
decl.parse
|
12
|
+
decl.to_color
|
13
|
+
end
|
14
|
+
alias_method :t, :translate
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(color_decl, color_model)
|
18
|
+
validate_effects(color_decl, color_model)
|
19
|
+
|
20
|
+
@color_decl = color_decl
|
21
|
+
@color_model = color_model
|
22
|
+
@color_class = PryTheme.const_get(:"Color#{ color_model }")
|
23
|
+
@effects = {}
|
24
|
+
@parsed = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse
|
28
|
+
if @parsed
|
29
|
+
return
|
30
|
+
else
|
31
|
+
case @color_decl.size
|
32
|
+
when 3 then build_from_two_layers
|
33
|
+
when 2 then build_from_two_args
|
34
|
+
when 1 then build_from_arg
|
35
|
+
end
|
36
|
+
@parsed = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_color
|
41
|
+
[:readable, :hex, :rgb, :term].each do |type|
|
42
|
+
begin
|
43
|
+
return @color_class.new({
|
44
|
+
:from => type,
|
45
|
+
:foreground => @fg,
|
46
|
+
:background => @bg
|
47
|
+
}.merge!(@effects))
|
48
|
+
rescue ArgumentError, TypeError
|
49
|
+
next
|
50
|
+
end
|
51
|
+
end
|
52
|
+
raise PryTheme::ThemeError,
|
53
|
+
%|malformed color declaration (#{ [@fg, @bg].compact.join(', ') })|
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def validate_effects(color_decl, color_model)
|
59
|
+
incorrect_color_model = (color_model != 256)
|
60
|
+
incorrect_declaration = (color_decl.any? do |decl|
|
61
|
+
decl.is_a?(Array) && decl.all? { |elem| elem.is_a?(Symbol) }
|
62
|
+
end)
|
63
|
+
|
64
|
+
if incorrect_color_model && incorrect_declaration
|
65
|
+
raise PryTheme::ThemeError,
|
66
|
+
'effects are available only for 256-color themes'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_effects
|
71
|
+
if @color_decl.any?
|
72
|
+
@effects = @color_decl.shift.inject({}) { |h, k| h[k] = true; h }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def build_from_two_layers
|
77
|
+
@fg, @bg = 2.times.map { @color_decl.shift }
|
78
|
+
build_effects
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_from_two_args
|
82
|
+
if decl_has_bg_key?
|
83
|
+
@bg = @color_decl.first[:bg]
|
84
|
+
@color_decl.shift
|
85
|
+
else
|
86
|
+
@fg = @color_decl.shift
|
87
|
+
if @color_decl.last.is_a?(Array)
|
88
|
+
@bg = @color_decl.shift if decl_contains_rgb?
|
89
|
+
else
|
90
|
+
@bg = @color_decl.shift
|
91
|
+
end
|
92
|
+
end
|
93
|
+
build_effects
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_from_arg
|
97
|
+
f = @color_decl.first
|
98
|
+
if decl_has_bg_key?
|
99
|
+
@bg = f[:bg]
|
100
|
+
@color_decl.shift
|
101
|
+
elsif f.is_a?(String) || f.is_a?(Fixnum)
|
102
|
+
@fg = @color_decl.shift
|
103
|
+
else
|
104
|
+
build_effects
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def decl_has_bg_key?
|
109
|
+
f = @color_decl.first
|
110
|
+
f.is_a?(Hash) && f.has_key?(:bg)
|
111
|
+
end
|
112
|
+
|
113
|
+
def decl_contains_rgb?
|
114
|
+
l = @color_decl.last
|
115
|
+
l.size == 3 && l.all? { |decl| decl.is_a?(Fixnum) }
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module PryTheme
|
2
|
+
class Theme
|
3
|
+
|
4
|
+
# @since 0.2.0
|
5
|
+
# @api private
|
6
|
+
module DynamicMethod
|
7
|
+
def def_dynamic_methods(*dynamic_methods)
|
8
|
+
dynamic_methods.each { |attr|
|
9
|
+
define_method(attr) do |*args|
|
10
|
+
name = :"@#{ attr }"
|
11
|
+
if args.first
|
12
|
+
decl =
|
13
|
+
Color::Declaration.t(args, instance_variable_get(:@color_model))
|
14
|
+
instance_variable_set(name, decl)
|
15
|
+
end
|
16
|
+
instance_variable_get(name)
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @since 0.2.0
|
23
|
+
# @api private
|
24
|
+
module DefaultAttrs
|
25
|
+
def set_default_attrs(attrs)
|
26
|
+
default_color = PryTheme.const_get(:"Color#{ @color_model }").new
|
27
|
+
attrs.each do |attr|
|
28
|
+
instance_variable_set(:"@#{ attr }", default_color.dup)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_nested_attrs
|
33
|
+
regexp { set_default_attrs(Definition::Regexp::ATTRS) }
|
34
|
+
shell { set_default_attrs(Definition::Shell::ATTRS) }
|
35
|
+
string { set_default_attrs(Definition::String::ATTRS) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def method_missing(meth, *args, &block)
|
39
|
+
raise PryTheme::ThemeError, %|unknown option "#{ meth }"|
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @since 0.2.0
|
44
|
+
# @api private
|
45
|
+
# @todo: possibly, try to avoid duplication.
|
46
|
+
class Definition
|
47
|
+
extend DynamicMethod
|
48
|
+
include DefaultAttrs
|
49
|
+
|
50
|
+
ATTRS = [
|
51
|
+
:class_, :class_variable, :comment, :constant, :error, :float,
|
52
|
+
:global_variable, :inline_delimiter, :instance_variable, :integer,
|
53
|
+
:keyword, :method, :predefined_constant, :symbol
|
54
|
+
]
|
55
|
+
|
56
|
+
def_dynamic_methods *ATTRS
|
57
|
+
|
58
|
+
def initialize(color_model, &block)
|
59
|
+
@color_model = color_model
|
60
|
+
set_default_attrs(ATTRS) and set_nested_attrs
|
61
|
+
instance_eval(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def regexp(&block)
|
65
|
+
@regexp = Definition::Regexp.new(@color_model, &block) if block_given?
|
66
|
+
@regexp
|
67
|
+
end
|
68
|
+
|
69
|
+
def shell(&block)
|
70
|
+
@shell = Definition::Shell.new(@color_model, &block) if block_given?
|
71
|
+
@shell
|
72
|
+
end
|
73
|
+
|
74
|
+
def string(&block)
|
75
|
+
@string = Definition::String.new(@color_model, &block) if block_given?
|
76
|
+
@string
|
77
|
+
end
|
78
|
+
|
79
|
+
class Compound
|
80
|
+
extend DynamicMethod
|
81
|
+
include DefaultAttrs
|
82
|
+
|
83
|
+
ATTRS = [:self_, :char, :content, :delimiter, :escape]
|
84
|
+
|
85
|
+
def_dynamic_methods *ATTRS
|
86
|
+
|
87
|
+
def initialize(color_model, &block)
|
88
|
+
@color_model = color_model
|
89
|
+
set_default_attrs(ATTRS)
|
90
|
+
instance_eval(&block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Regexp < Compound
|
95
|
+
ATTRS = [:modifier]
|
96
|
+
|
97
|
+
def_dynamic_methods *ATTRS
|
98
|
+
|
99
|
+
def initialize(color_model, &block)
|
100
|
+
@color_model = color_model
|
101
|
+
set_default_attrs(ATTRS)
|
102
|
+
super
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
Shell = Class.new(Compound)
|
107
|
+
String = Class.new(Compound)
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PryTheme
|
2
|
+
module Formattable
|
3
|
+
|
4
|
+
FORMATTING = {
|
5
|
+
:bold => 1,
|
6
|
+
:italic => 3,
|
7
|
+
:underline => 4
|
8
|
+
}
|
9
|
+
|
10
|
+
def bold
|
11
|
+
options[:bold] && FORMATTING[:bold]
|
12
|
+
end
|
13
|
+
def bold?; !!bold; end
|
14
|
+
|
15
|
+
def italic
|
16
|
+
options[:italic] && FORMATTING[:italic]
|
17
|
+
end
|
18
|
+
def italic?; !!italic; end
|
19
|
+
|
20
|
+
def underline
|
21
|
+
options[:underline] && FORMATTING[:underline]
|
22
|
+
end
|
23
|
+
def underline?; !!underline; end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module PryTheme
|
2
|
+
# @since 0.2.0
|
3
|
+
# @api private
|
4
|
+
#
|
5
|
+
# Represents a HEX colour. It's possible to convert a HEX instance into {TERM}
|
6
|
+
# or {RGB} colours. However, this conversion is half-duplex (see {RGB}). This
|
7
|
+
# class validates its input (you won't see malformed or nonexistent HEX
|
8
|
+
# colours).
|
9
|
+
#
|
10
|
+
# @note Conversion to {TERM} relies on {RGB#to_term}, as a {HEX} instance
|
11
|
+
# converts itself to {RGB} first, and only then to {TERM}.
|
12
|
+
# @example Conversion to RGB
|
13
|
+
# HEX.new('#ffffff').to_rgb #=> (RGB: 255, 255, 255)
|
14
|
+
# @example Conversion to TERM
|
15
|
+
# HEX.new('#ffffff').to_term(16) #=> (TERM-16: 15)
|
16
|
+
#
|
17
|
+
# # Approximation.
|
18
|
+
# HEX.new('#fc33ea').to_term #=> (TERM-256: 207)
|
19
|
+
class HEX
|
20
|
+
|
21
|
+
# Represents a single HEX "digit".
|
22
|
+
BYTE = /[A-F\d]{2}/i
|
23
|
+
|
24
|
+
# A hex String must be prefixed with an octothorp. Use any letter case.
|
25
|
+
PATTERN = /\A#(#{ BYTE }){3}\z/i
|
26
|
+
|
27
|
+
# @param [String] value must be a valid hex number
|
28
|
+
def initialize(value)
|
29
|
+
validate_value(value)
|
30
|
+
@value = value
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String]
|
34
|
+
def inspect
|
35
|
+
"(HEX: #{ @value })"
|
36
|
+
end
|
37
|
+
|
38
|
+
# @example
|
39
|
+
# HEX.new('#33aabb').to_s #=> "#33aabb"
|
40
|
+
# @return [String]
|
41
|
+
def to_s
|
42
|
+
@value
|
43
|
+
end
|
44
|
+
|
45
|
+
# Converts `self` into {RGB}.
|
46
|
+
# @return [RGB]
|
47
|
+
def to_rgb
|
48
|
+
RGB.new(@value[1..-1].scan(BYTE).map! { |b| b.to_i(16) })
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts `self` into {TERM}.
|
52
|
+
# @return [RGB]
|
53
|
+
def to_term(color_model = 256)
|
54
|
+
to_rgb.to_term(color_model)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Validates whether +value+ is a valid hex colour value.
|
60
|
+
#
|
61
|
+
# @param [String] value
|
62
|
+
# @raise [TypeError] if +value+ isn't String
|
63
|
+
# @raise [ArgumentError] if +value+ is malformed
|
64
|
+
# @return [void]
|
65
|
+
def validate_value(value)
|
66
|
+
unless value.is_a?(String)
|
67
|
+
raise TypeError, "can't convert #{ value.class } into PryTheme::HEX"
|
68
|
+
end
|
69
|
+
if value !~ PryTheme::HEX::PATTERN
|
70
|
+
raise ArgumentError, %|invalid value for PryTheme::HEX#new(): "#{ value }"|
|
71
|
+
end
|
72
|
+
true
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module PryTheme
|
2
|
+
class Preview
|
3
|
+
|
4
|
+
def initialize(theme)
|
5
|
+
@theme = theme
|
6
|
+
end
|
7
|
+
|
8
|
+
def short
|
9
|
+
cur_theme = ThemeList.current_theme
|
10
|
+
@theme.activate
|
11
|
+
[header, description, '--', short_snippet].join("\n")
|
12
|
+
ensure
|
13
|
+
@theme.disable
|
14
|
+
cur_theme.activate
|
15
|
+
end
|
16
|
+
|
17
|
+
def long
|
18
|
+
long_snippet
|
19
|
+
end
|
20
|
+
|
21
|
+
def description
|
22
|
+
@theme.description
|
23
|
+
end
|
24
|
+
|
25
|
+
def header
|
26
|
+
Pry::Helpers::Text.bold("#{ @theme.name } / #{ @theme.color_model }")
|
27
|
+
end
|
28
|
+
|
29
|
+
def banner(msg)
|
30
|
+
safe_width = 80
|
31
|
+
delimiter = ('-' * safe_width)
|
32
|
+
[delimiter,
|
33
|
+
Pry::Helpers::Text.bold(msg.center(safe_width)),
|
34
|
+
delimiter
|
35
|
+
].join("\n") + "\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def short_snippet
|
41
|
+
code = Pry::Helpers::CommandHelpers.unindent(<<-'CODE')
|
42
|
+
1: class Theme
|
43
|
+
2: def method
|
44
|
+
3: @ivar, @@cvar, lvar = 10_000, 400.00, "string"
|
45
|
+
4: end
|
46
|
+
5: end
|
47
|
+
CODE
|
48
|
+
Pry::Helpers::BaseHelpers.colorize_code(code)
|
49
|
+
end
|
50
|
+
|
51
|
+
def long_snippet
|
52
|
+
code = Pry::Helpers::CommandHelpers.unindent(<<-CODE)
|
53
|
+
# "#{ @theme.name }" theme.
|
54
|
+
class PryTheme::ThisIsAClass
|
55
|
+
def this_is_a_method
|
56
|
+
THIS_IS_A_CONSTANT = :this_is_a_symbol
|
57
|
+
this_is_a_local_var = "\#{this} \#@is a string.\\n"
|
58
|
+
this_is_a_float = 10_000.00
|
59
|
+
this_is_an_integer = 10_000
|
60
|
+
|
61
|
+
# TRUE and FALSE are predefined constants.
|
62
|
+
$this_is_a_global_variable = TRUE or FALSE
|
63
|
+
|
64
|
+
@this_is_an_instance_variable = `echo '\#@hi \#{system} call\\n'`
|
65
|
+
@@this_is_a_class_variable = @@@\\\\$ # An error.
|
66
|
+
|
67
|
+
/[0-9]{1,3}this \#{is} a regexp\\w+/xi
|
68
|
+
end
|
69
|
+
end
|
70
|
+
CODE
|
71
|
+
Pry::Helpers::BaseHelpers.colorize_code(code)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/pry-theme/rgb.rb
CHANGED
@@ -1,23 +1,248 @@
|
|
1
1
|
module PryTheme
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
# @since 0.2.0
|
3
|
+
# @api private
|
4
|
+
#
|
5
|
+
# Represents an RGB colour. It's possible to convert an RGB instance into
|
6
|
+
# {HEX} or {TERM} colours. However, this conversion is half-duplex. If an RGB
|
7
|
+
# instance gets converted to {TERM} format, there is a high chance that it
|
8
|
+
# will be approximated to fit in range of colour model (colour model can be
|
9
|
+
# set via an argument of the conversion method). This class validates its
|
10
|
+
# input (you won't see malformed of nonexistent RGB colours).
|
11
|
+
#
|
12
|
+
# @example Conversion to HEX
|
13
|
+
# RGB.new([0, 0, 0]).to_hex #=> (HEX: #000000)
|
14
|
+
# @example Conversion to TERM
|
15
|
+
# RGB.new([0, 0, 0]).to_term(8) #=> (TERM-8: 0)
|
16
|
+
#
|
17
|
+
# # Approximation.
|
18
|
+
# RGB.new([254, 244, 231]).to_term(8) #=> (TERM-8: 7)
|
19
|
+
class RGB
|
20
|
+
|
21
|
+
# 8 colours. For the standard GNU/Linux terminal emulator.
|
22
|
+
LINUX = [
|
23
|
+
[ 0, 0, 0], [128, 0, 0], [ 0, 128, 0],
|
24
|
+
[128, 128, 0], [ 0, 0, 128], [128, 0, 128],
|
25
|
+
[ 0, 128, 128], [192, 192, 192]
|
26
|
+
]
|
27
|
+
|
28
|
+
# 16 colours. For cmd.exe on Windows and other miserable terminals.
|
29
|
+
SYSTEM = LINUX + [
|
30
|
+
[128, 128, 128], [255, 0, 0], [ 0, 255, 0], [255, 255, 0],
|
31
|
+
[ 0, 0, 255], [255, 0, 255], [ 0, 255, 255], [255, 255, 255]
|
11
32
|
]
|
12
33
|
|
34
|
+
# The next 216 colours. For men.
|
13
35
|
COLORS = [
|
14
|
-
[0,
|
36
|
+
[ 0, 0, 0], [ 0, 0, 95], [ 0, 0, 135], [ 0, 0, 175],
|
37
|
+
[ 0, 0, 215], [ 0, 0, 255], [ 0, 95, 0], [ 0, 95, 95],
|
38
|
+
[ 0, 95, 135], [ 0, 95, 175], [ 0, 95, 215], [ 0, 95, 255],
|
39
|
+
[ 0, 135, 0], [ 0, 135, 95], [ 0, 135, 135], [ 0, 135, 175],
|
40
|
+
[ 0, 135, 215], [ 0, 135, 255], [ 0, 175, 0], [ 0, 175, 95],
|
41
|
+
[ 0, 175, 135], [ 0, 175, 175], [ 0, 175, 215], [ 0, 175, 255],
|
42
|
+
[ 0, 215, 0], [ 0, 215, 95], [ 0, 215, 135], [ 0, 215, 175],
|
43
|
+
[ 0, 215, 215], [ 0, 215, 255], [ 0, 255, 0], [ 0, 255, 95],
|
44
|
+
[ 0, 255, 135], [ 0, 255, 175], [ 0, 255, 215], [ 0, 255, 255],
|
45
|
+
[ 95, 0, 0], [ 95, 0, 95], [ 95, 0, 135], [ 95, 0, 175],
|
46
|
+
[ 95, 0, 215], [ 95, 0, 255], [ 95, 95, 0], [ 95, 95, 95],
|
47
|
+
[ 95, 95, 135], [ 95, 95, 175], [ 95, 95, 215], [ 95, 95, 255],
|
48
|
+
[ 95, 135, 0], [ 95, 135, 95], [ 95, 135, 135], [ 95, 135, 175],
|
49
|
+
[ 95, 135, 215], [ 95, 135, 255], [ 95, 175, 0], [ 95, 175, 95],
|
50
|
+
[ 95, 175, 135], [ 95, 175, 175], [ 95, 175, 215], [ 95, 175, 255],
|
51
|
+
[ 95, 215, 0], [ 95, 215, 95], [ 95, 215, 135], [ 95, 215, 175],
|
52
|
+
[ 95, 215, 215], [ 95, 215, 255], [ 95, 255, 0], [ 95, 255, 95],
|
53
|
+
[ 95, 255, 135], [ 95, 255, 175], [ 95, 255, 215], [ 95, 255, 255],
|
54
|
+
[135, 0, 0], [135, 0, 95], [135, 0, 135], [135, 0, 175],
|
55
|
+
[135, 0, 215], [135, 0, 255], [135, 95, 0], [135, 95, 95],
|
56
|
+
[135, 95, 135], [135, 95, 175], [135, 95, 215], [135, 95, 255],
|
57
|
+
[135, 135, 0], [135, 135, 95], [135, 135, 135], [135, 135, 175],
|
58
|
+
[135, 135, 215], [135, 135, 255], [135, 175, 0], [135, 175, 95],
|
59
|
+
[135, 175, 135], [135, 175, 175], [135, 175, 215], [135, 175, 255],
|
60
|
+
[135, 215, 0], [135, 215, 95], [135, 215, 135], [135, 215, 175],
|
61
|
+
[135, 215, 215], [135, 215, 255], [135, 255, 0], [135, 255, 95],
|
62
|
+
[135, 255, 135], [135, 255, 175], [135, 255, 215], [135, 255, 255],
|
63
|
+
[175, 0, 0], [175, 0, 95], [175, 0, 135], [175, 0, 175],
|
64
|
+
[175, 0, 215], [175, 0, 255], [175, 95, 0], [175, 95, 95],
|
65
|
+
[175, 95, 135], [175, 95, 175], [175, 95, 215], [175, 95, 255],
|
66
|
+
[175, 135, 0], [175, 135, 95], [175, 135, 135], [175, 135, 175],
|
67
|
+
[175, 135, 215], [175, 135, 255], [175, 175, 0], [175, 175, 95],
|
68
|
+
[175, 175, 135], [175, 175, 175], [175, 175, 215], [175, 175, 255],
|
69
|
+
[175, 215, 0], [175, 215, 95], [175, 215, 135], [175, 215, 175],
|
70
|
+
[175, 215, 215], [175, 215, 255], [175, 255, 0], [175, 255, 95],
|
71
|
+
[175, 255, 135], [175, 255, 175], [175, 255, 215], [175, 255, 255],
|
72
|
+
[215, 0, 0], [215, 0, 95], [215, 0, 135], [215, 0, 175],
|
73
|
+
[215, 0, 215], [215, 0, 255], [215, 95, 0], [215, 95, 95],
|
74
|
+
[215, 95, 135], [215, 95, 175], [215, 95, 215], [215, 95, 255],
|
75
|
+
[215, 135, 0], [215, 135, 95], [215, 135, 135], [215, 135, 175],
|
76
|
+
[215, 135, 215], [215, 135, 255], [215, 175, 0], [215, 175, 95],
|
77
|
+
[215, 175, 135], [215, 175, 175], [215, 175, 175], [215, 175, 215],
|
78
|
+
[215, 175, 255], [215, 215, 0], [215, 215, 95], [215, 215, 135],
|
79
|
+
[215, 215, 175], [215, 215, 215], [215, 215, 255], [215, 255, 0],
|
80
|
+
[215, 255, 95], [215, 255, 135], [215, 255, 175], [215, 255, 215],
|
81
|
+
[215, 255, 255], [255, 0, 0], [255, 0, 95], [255, 0, 135],
|
82
|
+
[255, 0, 175], [255, 0, 215], [255, 0, 255], [255, 95, 0],
|
83
|
+
[255, 95, 95], [255, 95, 135], [255, 95, 175], [255, 95, 215],
|
84
|
+
[255, 95, 255], [255, 135, 0], [255, 135, 95], [255, 135, 135],
|
85
|
+
[255, 135, 175], [255, 135, 215], [255, 135, 255], [255, 175, 0],
|
86
|
+
[255, 175, 95], [255, 175, 135], [255, 175, 175], [255, 175, 215],
|
87
|
+
[255, 175, 255], [255, 215, 0], [255, 215, 95], [255, 215, 135],
|
88
|
+
[255, 215, 175], [255, 215, 215], [255, 215, 255], [255, 255, 0],
|
89
|
+
[255, 255, 95], [255, 255, 135], [255, 255, 175], [255, 255, 215]
|
15
90
|
]
|
16
91
|
|
17
|
-
|
92
|
+
# The next 16 colours. For zen.
|
93
|
+
GREYSCALE = (0x08..0xEE).step(0x0A).map { |v| [v] * 3 }
|
94
|
+
|
95
|
+
# Combine everything into a full featured 256 colour RGB model.
|
96
|
+
TABLE = SYSTEM + COLORS + GREYSCALE
|
97
|
+
|
98
|
+
# The key points that are used to calculate the nearest match of an RGB.
|
99
|
+
BYTEPOINTS_256 = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
|
100
|
+
|
101
|
+
# @param [Array<Integer>, String] value a String will be converted to Array
|
102
|
+
# @raise [TypeError] if the +value+ is neither Array or String
|
103
|
+
def initialize(value)
|
104
|
+
@value =
|
105
|
+
case value
|
106
|
+
when Array
|
107
|
+
validate_array(value)
|
108
|
+
value
|
109
|
+
when String
|
110
|
+
validate_array(value = value.scan(/\d+/).map!(&:to_i))
|
111
|
+
value
|
112
|
+
else
|
113
|
+
raise TypeError, "can't convert #{ value.class } into PryTheme::RGB"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [String]
|
118
|
+
def inspect
|
119
|
+
"(RGB: #{ to_s })"
|
120
|
+
end
|
121
|
+
|
122
|
+
# Converts the RGB to a terminal colour equivalent.
|
123
|
+
#
|
124
|
+
# @note Accepts the following numbers: 256, 16, 8.
|
125
|
+
# @param [Integer] color_model
|
126
|
+
# @raise [ArgumentError] if +color_model+ parameter is incorrect
|
127
|
+
# @return [TERM] a TERM representation of the RGB
|
128
|
+
def to_term(color_model = 256)
|
129
|
+
term = case color_model
|
130
|
+
when 256 then PryTheme::RGB::TABLE.index(@value)
|
131
|
+
when 16 then PryTheme::RGB::SYSTEM.index(@value)
|
132
|
+
when 8 then PryTheme::RGB::LINUX.index(@value)
|
133
|
+
else raise ArgumentError,
|
134
|
+
"invalid value for PryTheme::HEX#to_term(): #{ @value }"
|
135
|
+
end
|
136
|
+
term = find_among_term_colors(term, color_model) if term.nil?
|
137
|
+
PryTheme::TERM.new(term, color_model)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Converts the RGB to a HEX colour equivalent.
|
141
|
+
# @return [HEX] a HEX representation of the RGB
|
142
|
+
def to_hex
|
143
|
+
PryTheme::HEX.new("#%02x%02x%02x" % @value)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @example
|
147
|
+
# RGB.new([0, 12, 255]).to_s #=> "0, 12, 255"
|
148
|
+
# @return [String]
|
149
|
+
def to_s
|
150
|
+
@value.join(', ')
|
151
|
+
end
|
152
|
+
|
153
|
+
# @example
|
154
|
+
# RGB.new([0, 12, 255]).to_s #=> [0, 12, 255]
|
155
|
+
# @return [Array<Integer>]
|
156
|
+
def to_a
|
157
|
+
@value
|
158
|
+
end
|
159
|
+
|
160
|
+
# @example
|
161
|
+
# RGB.new([0, 0, 0]).to_css #=> 'rgb(0, 0, 0)'
|
162
|
+
# @return [String]
|
163
|
+
def to_css
|
164
|
+
"rgb(#{ to_s })"
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# Checks whether the +ary+ has correct number of elements and these elements
|
170
|
+
# are valid RGB numbers.
|
171
|
+
#
|
172
|
+
# @param [Array<Integer>] ary
|
173
|
+
# @raise [ArgumentError] if the +ary+ is invalid
|
174
|
+
# @return [void]
|
175
|
+
def validate_array(ary)
|
176
|
+
correct_size = ary.size.equal?(3)
|
177
|
+
correct_vals = ary.all?{ |val| val.is_a?(Fixnum) && val.between?(0, 255) }
|
178
|
+
return true if correct_size && correct_vals
|
179
|
+
raise ArgumentError,
|
180
|
+
%|invalid value for PryTheme::RGB#validate_array(): "#{ ary }"|
|
181
|
+
end
|
182
|
+
|
183
|
+
# Approximates the given +byte+ to a terminal colour value within range of
|
184
|
+
# 256 colours.
|
185
|
+
#
|
186
|
+
# @param [Integer] byte a number between 0 and 255
|
187
|
+
# @return [Integer] approximated number
|
188
|
+
def nearest_term_256(byte)
|
189
|
+
for i in 0..4
|
190
|
+
lower, upper = BYTEPOINTS_256[i], BYTEPOINTS_256[i + 1]
|
191
|
+
next unless byte.between?(lower, upper)
|
192
|
+
|
193
|
+
distance_from_lower = (lower - byte).abs
|
194
|
+
distance_from_upper = (upper - byte).abs
|
195
|
+
closest = distance_from_lower < distance_from_upper ? lower : upper
|
196
|
+
end
|
197
|
+
closest
|
198
|
+
end
|
199
|
+
|
200
|
+
# The same as {#nearest_term_256}, but returns a number beteen 0 and 15.
|
201
|
+
#
|
202
|
+
# @note Oh, come on. At least it works!
|
203
|
+
# @todo use more realistic algorithm.
|
204
|
+
def nearest_term_16(byte)
|
205
|
+
byte / 16
|
206
|
+
end
|
207
|
+
|
208
|
+
# The same as {#nearest_term_256}, but returns a number beteen 0 and 7.
|
209
|
+
#
|
210
|
+
# @note Oh, come on. At least it works!
|
211
|
+
# @todo use more realistic algorithm.
|
212
|
+
def nearest_term_8(byte)
|
213
|
+
byte / 32
|
214
|
+
end
|
215
|
+
|
216
|
+
# Finds an approximated +term+ colour among the colour numbers within the
|
217
|
+
# given +color_model+.
|
218
|
+
#
|
219
|
+
# @param [Integer] term a colour to be approximated
|
220
|
+
# @param [Integer] color_model possible values {#to_term}
|
221
|
+
# @return [Integer] approximated number, which fits in range of color_model
|
222
|
+
def find_among_term_colors(term, color_model)
|
223
|
+
rgb = @value.map { |byte| nearest_term_256(byte) }
|
224
|
+
term = PryTheme::RGB::TABLE.index(rgb)
|
225
|
+
approximate(term, color_model)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Approximates +term+ in correspondence with +color_model+
|
229
|
+
#
|
230
|
+
# @see #nearest_term_16
|
231
|
+
# @see #nearest_term_8
|
232
|
+
# @param [Integer] term a colour to be approximated
|
233
|
+
# @param [Integer] color_model possible values {#to_term}
|
234
|
+
# @return [Integer] approximated number, which fits in range of color_model
|
235
|
+
def approximate(term, color_model)
|
236
|
+
needs_approximation = (term > color_model - 1)
|
18
237
|
|
19
|
-
|
20
|
-
|
238
|
+
if needs_approximation
|
239
|
+
case color_model
|
240
|
+
when 16 then nearest_term_16(term)
|
241
|
+
when 8 then nearest_term_8(term)
|
242
|
+
end
|
243
|
+
else
|
244
|
+
term
|
245
|
+
end
|
21
246
|
end
|
22
247
|
|
23
248
|
end
|