vic 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/vic.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Vic
2
- VERSION = '0.0.6'
2
+ VERSION = '1.0.0'.freeze
3
3
  end
4
4
 
5
+ require 'ostruct'
6
+ require 'vic/color_scheme'
7
+ require 'vic/color_scheme_writer'
5
8
  require 'vic/color'
6
- require 'vic/color_error'
7
- require 'vic/colorscheme'
8
- require 'vic/colorscheme/highlight'
9
- require 'vic/colorscheme/highlight_set'
10
- require 'vic/colorscheme/highlight/argument'
11
- require 'vic/colorscheme/highlight/argument_set'
9
+ require 'vic/convert'
10
+ require 'vic/xterm_color'
11
+ require 'vic/highlight'
12
+ require 'vic/link'
data/lib/vic/color.rb CHANGED
@@ -1,87 +1,104 @@
1
1
  module Vic
2
- module Color extend self
3
- # System colors (0-15)
4
- SYSTEM_COLORS = [
5
- [0x00, 0x00, 0x00],
6
- [0x80, 0x00, 0x00],
7
- [0x00, 0x80, 0x00],
8
- [0x80, 0x80, 0x00],
9
- [0x00, 0x00, 0x80],
10
- [0x80, 0x00, 0x80],
11
- [0x00, 0x80, 0x80],
12
- [0xc0, 0xc0, 0xc0],
13
- [0x80, 0x80, 0x80],
14
- [0xff, 0x00, 0x00],
15
- [0x00, 0xff, 0x00],
16
- [0xff, 0xff, 0x00],
17
- [0x00, 0x00, 0xff],
18
- [0xff, 0x00, 0xff],
19
- [0x00, 0xff, 0xff],
20
- [0xff, 0xff, 0xff]
21
- ]
2
+ class Color
3
+ attr_accessor :value
22
4
 
23
- # RGB colors (16 - 231)
24
- RGB_COLORS = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff].repeated_permutation(3).to_a
25
-
26
- # Grayscale colors (232 - 255)
27
- GRAYSCALE_COLORS = (0x08..0xee).step(0x0a).to_a.map {|v| Array.new(3).fill(v) }
5
+ def initialize(value)
6
+ @value = value
7
+ end
28
8
 
29
- # All 256 colors of the rainbow. Organized from 0 to 255.
30
- COLORS_256 = SYSTEM_COLORS + RGB_COLORS + GRAYSCALE_COLORS
9
+ class ColorError < RuntimeError; end
31
10
 
32
- # Convert hexidecimal color to an Array of RGB values.
11
+ # Convert the color value to a hexadecimal color
12
+ #
13
+ # @return [Symbol,String]
14
+ # the color as either "NONE" or hexadecimal
33
15
  #
34
- # @param [String] hex the hexidecimal color
35
- # @return [Array] the RGB color conversion
36
- def hex_to_rgb(hex)
37
- hex.match(/#?(..)(..)(..)/)[1..4].to_a.map {|v| v.to_i(16) }
16
+ # @api public
17
+ def to_gui
18
+ return to_standard_hex if hexadecimal?
19
+ return Convert.xterm_to_hex(@value) if cterm?
20
+ return :NONE if none?
21
+
22
+ raise ColorError.new "can't convert \"#{ @value }\" to gui"
38
23
  end
39
24
 
40
- # Takes a hexidecimal color and returns is closest 256 color match.
25
+ # Convert the color value to a cterm compatible color
41
26
  #
42
- # Credit goes to Micheal Elliot for the algorithm which was originally written
43
- # in Python.
27
+ # @return [Fixnum]
28
+ # the color as either "NONE" or cterm color
44
29
  #
45
- # @see https://gist.github.com/719710
46
- # @param [String] hex the hexidecimal color
47
- # @return [FixNum] the closest 256 color match
48
- def hex_to_256(hex)
49
- parts = hex_to_rgb(hex)
30
+ # @api public
31
+ def to_cterm
32
+ return @value if cterm?
33
+ return Convert.hex_to_xterm(to_standard_hex) if hexadecimal?
34
+ return :NONE if none?
50
35
 
51
- # If the hex is a member of the 256 colors club, we'll just return it's 256
52
- # color value. No sense in doing extra work, right?
53
- return COLORS_256.index(parts) if COLORS_256.include?(parts)
36
+ raise ColorError.new "can't convert \"#{ @value }\" to cterm"
37
+ end
54
38
 
55
- increments = 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff
39
+ # Returns true if the color value is cterm compatible color and false if
40
+ # it's not
41
+ #
42
+ # @return [TrueClass,FalseClass]
43
+ # whether or not the color value is cterm compatible
44
+ #
45
+ # @api public
46
+ def cterm?
47
+ @value.kind_of?(Fixnum) and @value.between?(0, 255)
48
+ end
56
49
 
57
- # For each part we need to check if it's between any two of the increments.
58
- # If it is we'll determine the closest match, change it's value, break,
59
- # and move on to the next part.
60
- parts.map! do |part|
61
- closest = nil
62
- for i in (0..(increments.length - 1))
63
- lower = increments[i]
64
- upper = increments[i + 1]
65
- next unless (lower <= part) && (part <= upper)
66
- distance_from_lower = (lower - part).abs
67
- distance_from_upper = (upper - part).abs
68
- closest = distance_from_lower < distance_from_upper ? lower : upper
69
- break
70
- end
71
- closest
72
- end
50
+ # Returns true if the color value is a gui compatible color and false if
51
+ # it's not
52
+ #
53
+ # @return [TrueClass,FalseClass]
54
+ # whether or not the color value is gui compatible
55
+ #
56
+ # @api public
57
+ def gui?
58
+ hexadecimal?
59
+ end
73
60
 
74
- # Return the index of the color
75
- COLORS_256.index(parts)
61
+ # Returns true if the color value is a hexadecimal color and false if it's not
62
+ #
63
+ # @return [TrueClass,FalseClass]
64
+ # whether or not the color value is hexadecimal
65
+ #
66
+ # @api public
67
+ def hexadecimal?
68
+ # Both standard and shorthand (CSS) style hexadecimal color value.
69
+ not cterm? and /\A#?(?:[0-9a-f]{3}|[0-9a-f]{6})\z/io.match(@value.to_s)
76
70
  end
77
71
 
78
- # Checks if the subjec is a valid hexidecimal color.
72
+ # Returns true if the color value is either empty or set to "NONE"
73
+ #
74
+ # @return [TrueClass,FalseClass]
75
+ # whether or not the color value is empty or "NONE"
79
76
  #
80
- # @param [String] subject the string in question
81
- # @return [Match
82
- def is_hexadecimal?(subject)
83
- return false unless subject.respond_to? :match
84
- subject.match(/#?[\da-f]{6}/i) ? true : false
77
+ # @api public
78
+ def none?
79
+ @value.to_s.empty? or /\Anone\z/io.match(@value.to_s)
80
+ end
81
+
82
+ private
83
+
84
+ # Convert the color value to a standard hexadecimal value
85
+ #
86
+ # @example
87
+ # Color.new('333').send(:to_standard_hex) # => '#333333'
88
+ #
89
+ # @return [String]
90
+ # the color in standard hexadecimal format
91
+ #
92
+ # @api private
93
+ def to_standard_hex
94
+ color = @value.dup
95
+ color.insert(0, '#') unless color.start_with? '#'
96
+
97
+ # Convert shorthand hex to standard hex.
98
+ if color.size == 4
99
+ color.slice!(1, 3).chars { |char| color << char * 2 }
100
+ end
101
+ color
85
102
  end
86
- end
87
- end
103
+ end # class Color
104
+ end # module Vic
@@ -0,0 +1,303 @@
1
+ module Vic
2
+ class ColorScheme
3
+ attr_accessor :title
4
+
5
+ def initialize(title, &block)
6
+ @title = title
7
+ @highlights = []
8
+ @links = []
9
+ @info = OpenStruct.new
10
+
11
+ if block_given?
12
+ block.arity.zero? ? instance_eval(&block) : yield(self)
13
+ end
14
+ end
15
+
16
+ # Return the colorscheme information
17
+ #
18
+ # @return [Hash]
19
+ # the colorscheme information
20
+ #
21
+ # @api public
22
+ def info
23
+ @info.marshal_dump
24
+ end
25
+
26
+ # Set the colorscheme information
27
+ #
28
+ # @param [Hash] data
29
+ # the data to use
30
+ #
31
+ # @return [Hash]
32
+ # the colorscheme information
33
+ #
34
+ # @api public
35
+ def info=(data = {})
36
+ @info.marshal_load(data)
37
+ end
38
+
39
+ # Updates the colorscheme information
40
+ #
41
+ # @param [Hash] data
42
+ # the data to use
43
+ #
44
+ # @return [Hash]
45
+ # the colorscheme information
46
+ #
47
+ # @api public
48
+ def add_info(data = {})
49
+ self.info = @info.marshal_dump.merge(data)
50
+ end
51
+
52
+ # Return the background setting
53
+ #
54
+ # @return [NilClass,String,Symbol]
55
+ # the background setting
56
+ def background
57
+ @background
58
+ end
59
+
60
+ # Sets the background
61
+ #
62
+ # @param [String,Symbol] setting
63
+ # a background setting of either "light" or "dark"
64
+ #
65
+ # @return [String,Symbol]
66
+ # the background setting
67
+ #
68
+ # @api public
69
+ def background=(setting)
70
+ unless /\A(light|dark)\z/o.match(setting)
71
+ raise ArgumentError.new("expected 'light' or 'dark'")
72
+ end
73
+ @background = setting
74
+ end
75
+
76
+ # Sets the background automatically
77
+ #
78
+ # By default this will return "dark". If a highlight with the `group`
79
+ # "Normal" and a `guibg` setting has been added to the colorscheme, it will
80
+ # determine the setting to use. If the `guibg` is strictly less than
81
+ # "#808080" the background will be set to "dark" otherwise it will be set
82
+ # to "light".
83
+ #
84
+ # @return [String]
85
+ # the background setting
86
+ #
87
+ # @api public
88
+ def background!
89
+ normal = find_highlight(:Normal)
90
+ return @background = 'dark' unless normal && normal.guibg
91
+ @background = normal.guibg[1..-1].to_i(16) < 8421504 ? 'dark' : 'light'
92
+ end
93
+
94
+ # Return the colorscheme's highlights
95
+ #
96
+ # @return [Array]
97
+ # the colorscheme's highlights
98
+ #
99
+ # @api public
100
+ def highlights
101
+ @highlights.dup
102
+ end
103
+
104
+ # Add or update a highlight
105
+ #
106
+ # @example
107
+ # scheme.highlight(:Normal, fg: 'eee', bg: '333')
108
+ #
109
+ # @param [String,Symbol] group
110
+ # the group to highlight
111
+ #
112
+ # @param [Hash] attributes
113
+ # the attributes to set or update
114
+ #
115
+ # @return [Vic::Highlight]
116
+ # the highlight
117
+ #
118
+ # @api public
119
+ def highlight(group, attributes={})
120
+ if hilight = find_highlight(group)
121
+ hilight.update_attributes!(attributes)
122
+ else
123
+ hilight = Highlight.new(:"#{ language }#{ group }", attributes)
124
+ @highlights << hilight
125
+ end
126
+
127
+ hilight
128
+ end
129
+ alias_method :hi, :highlight
130
+
131
+ # Add or update a forced highlight
132
+ #
133
+ # @example
134
+ # scheme.highlight!(:Normal, fg: 'eee', bg: '333').force? # => true
135
+ #
136
+ # @param [Hash] attributes
137
+ # the attributes to set or update
138
+ #
139
+ # @return [Vic::Highlight]
140
+ # the highlight
141
+ #
142
+ # @api public
143
+ def highlight!(group, attributes={})
144
+ highlight(group, attributes.dup.tap { |hash| hash[:force] = true })
145
+ end
146
+ alias_method :hi!, :highlight!
147
+
148
+ # Return the colorscheme's links
149
+ #
150
+ # @return [Array]
151
+ # the colorscheme's links
152
+ #
153
+ # @api public
154
+ def links
155
+ @links.dup
156
+ end
157
+
158
+ # Add highlight links to the colorscheme
159
+ #
160
+ # @example
161
+ # scheme.link(:rubyInstanceVariable, :rubyClassVariable)
162
+ #
163
+ # @param [String,Symbol] from_groups
164
+ # a list of groups to link from
165
+ #
166
+ # @param [String,Symbol] to_groups
167
+ # the group to link to
168
+ #
169
+ # @return [Array]
170
+ # the added links
171
+ #
172
+ # @api public
173
+ def link(*from_groups, to_group)
174
+ from_groups.flatten.map do |from_group|
175
+ # Don't add anything we don't already have.
176
+ next if find_link(from_group, to_group)
177
+ link = Link.new(from_group, to_group)
178
+ link.tap { |l| @links << l }
179
+ end.compact
180
+ end
181
+
182
+ # Add forced highlight links to the colorscheme
183
+ #
184
+ # @example
185
+ # scheme.link!(:rubyInstanceVariable, :rubyClassVariable)
186
+ # link = scheme.links.find do |l|
187
+ # l.from_group == :rubyInstanceVariable and l.to_group = :rubyClassVariable
188
+ # end
189
+ # link.force? # => true
190
+ #
191
+ # @param [String,Symbol] from_groups
192
+ # a list of groups to link from
193
+ #
194
+ # @param [String,Symbol] to_groups
195
+ # the group to link to
196
+ #
197
+ # @return [Array]
198
+ # the added/updated links
199
+ #
200
+ # @api public
201
+ def link!(*from_groups, to_group)
202
+ # Use the default method first.
203
+ self.link(from_groups, to_group)
204
+
205
+ # Then update the links.
206
+ from_groups.flatten.map do |from_group|
207
+ link = find_link(from_group, to_group)
208
+ link.tap(&:force!)
209
+ end
210
+ end
211
+
212
+ # Set a language to prepend new highlight group names with
213
+ #
214
+ # @example
215
+ # scheme.language = :ruby
216
+ # scheme.hi(:InstanceVariable).group == :rubyInstanceVariable # => true
217
+ #
218
+ # @param [String,Symbol] name
219
+ # the language name
220
+ #
221
+ # @return [String,Symbol]
222
+ # the language name
223
+ #
224
+ # @api public
225
+ def language=(name)
226
+ @language = name
227
+ end
228
+
229
+ # Return the language
230
+ #
231
+ # If a name and a block is passed the language will be temporarily set to
232
+ # name inside the block.
233
+ #
234
+ # @example
235
+ # scheme.language :ruby do |s|
236
+ # s.hi(:InstanceVariable)
237
+ # s.hi(:ClassVariable)
238
+ # end
239
+ # scheme.highlights.any? { |h| h.group == :rubyClassVarible } # => true
240
+ #
241
+ # @param [String,Symbol] name
242
+ # the language to temporarily set if a block is given
243
+ #
244
+ # @yieldparam [Vic::Colorscheme]
245
+ # the colorscheme
246
+ #
247
+ # @return [String,Symbol]
248
+ # the language setting
249
+ #
250
+ # @api public
251
+ def language(name = nil, &block)
252
+ return @language unless name and block_given?
253
+
254
+ previous_language = self.language
255
+ @language = name
256
+ block.arity == 0 ? instance_eval(&block) : yield(self)
257
+ @language = previous_language
258
+ end
259
+
260
+ # Render the colorscheme
261
+ #
262
+ # @return [String]
263
+ # the colorscheme as a string
264
+ #
265
+ # @api public
266
+ def render
267
+ ColorSchemeWriter.write(self)
268
+ end
269
+
270
+ private
271
+
272
+ # Find a highlight
273
+ #
274
+ # @param [String,Symbol] group
275
+ # the highlight group to find
276
+ #
277
+ # @return [NilClass,Vic::Highlight]
278
+ # the found highlight
279
+ #
280
+ # @api private
281
+ def find_highlight(group)
282
+ highlights.find { |h| /\A#{ group }\z/.match(h.group) }
283
+ end
284
+
285
+ # Find a link
286
+ #
287
+ # @param [String,Symbol] from_group
288
+ # the link from_group
289
+ #
290
+ # @param [String,Symbol] to_group
291
+ # the link to_group
292
+ #
293
+ # @return [NilClass,Vic::Highlight]
294
+ # the found highlight
295
+ #
296
+ # @api private
297
+ def find_link(from_group, to_group)
298
+ @links.find do |l|
299
+ /\A#{ from_group }\z/.match(l.from_group) and /\A#{ to_group }\z/.match(l.to_group)
300
+ end
301
+ end
302
+ end # class ColorScheme
303
+ end # module Vic
@@ -0,0 +1,80 @@
1
+ module Vic
2
+ class ColorSchemeWriter
3
+ def initialize(colorscheme)
4
+ @colorscheme = colorscheme
5
+ end
6
+
7
+ def self.write(colorscheme)
8
+ new(colorscheme).write
9
+ end
10
+
11
+ def write
12
+ lines = [title, info, background, reset, name, highlights, links]
13
+ "%s\n%s\n\n%s\n\n%s\n%s\n\n%s\n%s" % lines
14
+ end
15
+
16
+ private
17
+
18
+ def title
19
+ %(" Title: #{ @colorscheme.title })
20
+ end
21
+
22
+ def info
23
+ return if @colorscheme.info.empty?
24
+ @colorscheme.info.map do |key, val|
25
+ %(" #{ key }: #{ val })
26
+ end.join("\n")
27
+ end
28
+
29
+ def background
30
+ "set background=#{ @colorscheme.background || @colorscheme.background! }"
31
+ end
32
+
33
+ def reset
34
+ <<-VIML.gsub(/^ {6}/, '')
35
+ hi clear
36
+
37
+ if exists("syntax_on")
38
+ syntax reset
39
+ endif
40
+ VIML
41
+ end
42
+
43
+ def name
44
+ %(let g:colors_name="#{ @colorscheme.title }")
45
+ end
46
+
47
+ def highlights
48
+ @colorscheme.highlights.map do |highlight|
49
+ attributes = Highlight.attributes.map do |attribute|
50
+ next unless value = highlight.send(attribute)
51
+
52
+ case value
53
+ when String, Symbol, Integer
54
+ " #{ attribute }=#{ value }"
55
+ when Array
56
+ " #{ attribute }=#{ value.map(&:to_s).map(&:strip).join(',') }"
57
+ end
58
+ end
59
+
60
+ next unless attributes.any?
61
+
62
+ if highlight.force?
63
+ "hi! #{ highlight.group }" << attributes.join
64
+ else
65
+ "hi #{ highlight.group }" << attributes.join
66
+ end
67
+ end.compact.join("\n")
68
+ end
69
+
70
+ def links
71
+ @colorscheme.links.map do |link|
72
+ if link.force?
73
+ "hi! default link #{ link.from_group } #{ link.to_group }"
74
+ else
75
+ "hi default link #{ link.from_group } #{ link.to_group }"
76
+ end
77
+ end.compact.join("\n")
78
+ end
79
+ end # class ColorSchemeWriter
80
+ end # module Vic
@@ -0,0 +1,33 @@
1
+ module Vic
2
+ module Convert
3
+ def self.hex_to_rgb(hex)
4
+ hex.match(/#?(..)(..)(..)/).captures.map { |v| v.to_i(16) }
5
+ end
6
+
7
+ def self.hex_to_xterm(hex)
8
+ rgb = hex_to_rgb(hex)
9
+
10
+ return XtermColor.table.index(rgb) if XtermColor.table.include?(rgb)
11
+
12
+ increments = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
13
+
14
+ rgb.map! do |part|
15
+ for i in (0...5)
16
+ lower, upper = increments[i], increments[i + 1]
17
+
18
+ next unless part.between?(lower, upper)
19
+
20
+ distance_from_lower = (lower - part).abs
21
+ distance_from_upper = (upper - part).abs
22
+ closest = distance_from_lower < distance_from_upper ? lower : upper
23
+ end
24
+ closest
25
+ end
26
+ XtermColor.table.index(rgb)
27
+ end
28
+
29
+ def self.xterm_to_hex(code)
30
+ '#' + XtermColor.table[code].map { |v| (v.to_s(16) * 2)[0...2] }.join
31
+ end
32
+ end # module Convert
33
+ end # module Vic
@@ -0,0 +1,230 @@
1
+ module Vic
2
+ class Highlight
3
+
4
+ attr_accessor :group
5
+
6
+ def initialize(group, attributes={})
7
+ @group = group
8
+ update_attributes!(attributes)
9
+ end
10
+
11
+ # Updates the highlights attributes
12
+ #
13
+ # @example
14
+ # h = Vic::Highlight.new('Normal', { guibg: '333' })
15
+ # h.guibg # => "#333333"
16
+ # h.update_attributes!({ guibg: '000' })
17
+ # h.guibg # => "#000000"
18
+ #
19
+ # @param [Hash] attributes
20
+ # the attributes to update
21
+ #
22
+ # @return [Vic::Highlight]
23
+ # the updated highlight
24
+ #
25
+ # @api public
26
+ def update_attributes!(attributes={})
27
+ attributes.each_pair do |key, val|
28
+ self.respond_to?(:"#{ key }=") && send(:"#{ key }=", val)
29
+ end
30
+
31
+ # Returning self seems like the right thing to do when a method changes
32
+ # more than one property of an object.
33
+ self
34
+ end
35
+
36
+ # Return the list of highlight attributes
37
+ #
38
+ # @return [Array]
39
+ # the list of highlight attributes
40
+ #
41
+ # @api semipublic
42
+ def self.attributes
43
+ [:term, :start, :stop, :cterm, :ctermbg, :ctermfg, :gui, :guibg, :guifg, :guisp, :font]
44
+ end
45
+
46
+ # Set the force
47
+ #
48
+ # @param [TrueClass,FalseClass] bool
49
+ # a value of true or false
50
+ #
51
+ # @return [TrueClass,FalseClass]
52
+ # the force setting
53
+ #
54
+ # @api public
55
+ def force=(bool)
56
+ @force = !!bool
57
+ end
58
+
59
+ # Return the force setting
60
+ #
61
+ # @return [TrueClass,FalseClass]
62
+ # the force setting
63
+ #
64
+ # @api public
65
+ def force?
66
+ @force
67
+ end
68
+
69
+ # Set the force setting to true
70
+ #
71
+ # @return [TrueClass]
72
+ # the force setting
73
+ #
74
+ # @api public
75
+ def force!
76
+ @force = true
77
+ end
78
+
79
+ # Set both ctermbg and guibg simultaneously
80
+ #
81
+ # @param [String] color
82
+ # the color to use
83
+ #
84
+ # @return [Vic::Highlight]
85
+ # the updated highlight
86
+ #
87
+ # @api public
88
+ def bg=(color)
89
+ color = Color.new(color)
90
+ @ctermbg, @guibg = color.to_cterm, color.to_gui
91
+ self
92
+ end
93
+
94
+ # Set both ctermfg and guifg simultaneously
95
+ #
96
+ # @param [String] color
97
+ # the color to use
98
+ #
99
+ # @return [Vic::Highlight]
100
+ # the updated highlight
101
+ #
102
+ # @api public
103
+ def fg=(color)
104
+ color = Color.new(color)
105
+ @ctermfg, @guifg = color.to_cterm, color.to_gui
106
+ self
107
+ end
108
+
109
+ # Set both cterm and gui simultaneously
110
+ #
111
+ # @param [Array] styles
112
+ # the styles to use
113
+ #
114
+ # @return [Vic::Highlight]
115
+ # the updated highlight
116
+ #
117
+ # @api public
118
+ def style=(styles)
119
+ @cterm, @gui = [select_styles(styles)] * 2
120
+ self
121
+ end
122
+
123
+ attr_accessor :term, :start, :stop
124
+
125
+ attr_reader :cterm, :ctermfg, :ctermbg
126
+
127
+ # Set the cterm value
128
+ #
129
+ # @param [Array,String,Symbol] styles
130
+ # the styles to use
131
+ #
132
+ # @return [Array,Symbol]
133
+ # the cterm value
134
+ #
135
+ # @api public
136
+ def cterm=(*styles)
137
+ @cterm = select_styles(styles)
138
+ end
139
+
140
+ # Set the ctermbg value
141
+ #
142
+ # @param [String,Symbol] color
143
+ # the color to use
144
+ #
145
+ # @return [String,Symbol]
146
+ # the ctermbg color
147
+ #
148
+ # @api public
149
+ def ctermbg=(color)
150
+ @ctermbg = Color.new(color).to_cterm
151
+ end
152
+
153
+ # Set the ctermfg value
154
+ #
155
+ # @param [String,Symbol] color
156
+ # the color to use
157
+ #
158
+ # @return [String,Symbol]
159
+ # the ctermfg color
160
+ #
161
+ # @api public
162
+ def ctermfg=(color)
163
+ @ctermfg = Color.new(color).to_cterm
164
+ end
165
+
166
+ attr_reader :gui, :guibg, :guifg
167
+ attr_accessor :guisp, :font
168
+
169
+ # Set the gui value
170
+ #
171
+ # @param [Array,String,Symbol] styles
172
+ # the styles to use
173
+ #
174
+ # @return [Array,Symbol]
175
+ # the gui value
176
+ #
177
+ # @api public
178
+ def gui=(*styles)
179
+ @gui = select_styles(styles)
180
+ end
181
+
182
+ # Set the guibg value
183
+ #
184
+ # @param [String,Symbol] color
185
+ # the color to use
186
+ #
187
+ # @return [String,Symbol]
188
+ # the guibg color
189
+ #
190
+ # @api public
191
+ def guibg=(color)
192
+ @guibg = Color.new(color).to_gui
193
+ end
194
+
195
+ # Set the guifg value
196
+ #
197
+ # @param [String,Symbol] color
198
+ # the color to use
199
+ #
200
+ # @return [String,Symbol]
201
+ # the guifg color
202
+ #
203
+ # @api public
204
+ def guifg=(color)
205
+ @guifg = Color.new(color).to_gui
206
+ end
207
+
208
+ private
209
+
210
+ # Valid font styles *excluding* none
211
+ FONT_STYLE = /bold|(under(line|curl))|((re|in)verse)|italic|standout/o
212
+
213
+ # Selcect valid styles from a list
214
+ #
215
+ # @param [Mixed] styles
216
+ # the list of styles
217
+ #
218
+ # @return [Array,Symbol]
219
+ # the list of valid styles or "NONE"
220
+ #
221
+ # @api private
222
+ def select_styles(*styles)
223
+ styles.tap(&:compact).flatten!
224
+ if styles.empty? or styles.length == 1 && /\Anone\z/io.match(styles[0])
225
+ return :NONE
226
+ end
227
+ styles.select { |s| FONT_STYLE.match(s) }
228
+ end
229
+ end # class Highlight
230
+ end # module Vic
data/lib/vic/link.rb ADDED
@@ -0,0 +1,44 @@
1
+ module Vic
2
+ class Link
3
+ attr_accessor :from_group, :to_group
4
+
5
+ def initialize(from_group, to_group = :NONE)
6
+ @from_group = from_group
7
+ @to_group = to_group
8
+ @force = false
9
+ end
10
+
11
+ # Set the force
12
+ #
13
+ # @param [TrueClass,FalseClass] bool
14
+ # a value of true or false
15
+ #
16
+ # @return [TrueClass,FalseClass]
17
+ # the force setting
18
+ #
19
+ # @api public
20
+ def force=(bool)
21
+ @force = !!bool
22
+ end
23
+
24
+ # Return the force setting
25
+ #
26
+ # @return [TrueClass,FalseClass]
27
+ # the force setting
28
+ #
29
+ # @api public
30
+ def force?
31
+ @force
32
+ end
33
+
34
+ # Set the force setting to true
35
+ #
36
+ # @return [TrueClass]
37
+ # the force setting
38
+ #
39
+ # @api public
40
+ def force!
41
+ @force = true
42
+ end
43
+ end # class Link
44
+ end # module Vic
@@ -0,0 +1,18 @@
1
+ module Vic
2
+ module XtermColor
3
+ SYSTEM = [[0x00, 0x00, 0x00], [0x80, 0x00, 0x00], [0x00, 0x80, 0x00],
4
+ [0x80, 0x80, 0x00], [0x00, 0x00, 0x80], [0x80, 0x00, 0x80],
5
+ [0x00, 0x80, 0x80], [0xc0, 0xc0, 0xc0], [0x80, 0x80, 0x80],
6
+ [0xff, 0x00, 0x00], [0x00, 0xff, 0x00], [0xff, 0xff, 0x00],
7
+ [0x00, 0x00, 0xff], [0xff, 0x00, 0xff], [0x00, 0xff, 0xff],
8
+ [0xff, 0xff, 0xff]]
9
+
10
+ RGB = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff].repeated_permutation(3).to_a
11
+
12
+ GREYSCALE = (0x08..0xee).step(0x0a).map { |v| [v] * 3 }
13
+
14
+ def self.table
15
+ SYSTEM + RGB + GREYSCALE
16
+ end
17
+ end # module XtermColor
18
+ end # module Vic
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-22 00:00:00.000000000Z
12
+ date: 2012-04-24 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: Create Vim colorschemes with Ruby
15
15
  email: cjholdbrooks@gmail.com
@@ -19,12 +19,12 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - lib/vic.rb
21
21
  - lib/vic/color.rb
22
- - lib/vic/color_error.rb
23
- - lib/vic/colorscheme.rb
24
- - lib/vic/colorscheme/highlight.rb
25
- - lib/vic/colorscheme/highlight_set.rb
26
- - lib/vic/colorscheme/highlight/argument.rb
27
- - lib/vic/colorscheme/highlight/argument_set.rb
22
+ - lib/vic/color_scheme.rb
23
+ - lib/vic/color_scheme_writer.rb
24
+ - lib/vic/convert.rb
25
+ - lib/vic/highlight.rb
26
+ - lib/vic/link.rb
27
+ - lib/vic/xterm_color.rb
28
28
  homepage: https://github.com/noprompt/vic
29
29
  licenses: []
30
30
  post_install_message:
@@ -1,7 +0,0 @@
1
- module Vic
2
- class ColorError < StandardError
3
- def initialize(message)
4
- super(message)
5
- end
6
- end
7
- end
@@ -1,141 +0,0 @@
1
- module Vic
2
- class Colorscheme
3
- attr_accessor :colors_name, :information
4
-
5
- # A new instance of Colorscheme. If a block is given with no arguments, the
6
- # the block will be evaluated in the context of the new colorscheme.
7
- # Otherwise the block will yield self.
8
- #
9
- # @param [String] colors_name the name of the colorscheme
10
- # @param [Proc] block the block to be evaluated
11
- # @return [Colorscheme]
12
- def initialize(colors_name, &block)
13
- @colors_name = colors_name
14
- if block_given?
15
- block.arity == 0 ? instance_eval(&block) : yield(self)
16
- end
17
- end
18
-
19
- # Returns/sets the information attribute
20
- #
21
- # @param [Hash] information the information, :author => 'Joel Holdbrooks'
22
- # @return [Hash]
23
- def information(inf={})
24
- (@information ||= {}).merge!(inf) if inf.respond_to? :merge
25
- end
26
- alias_method :info, :information
27
-
28
- # Returns the background color.
29
- #
30
- # @return [String] 'light' or 'dark'
31
- def background
32
- @background ||= background!
33
- end
34
-
35
- # Sets the background color.
36
- #
37
- # @param [String] a value of 'light' or 'dark'
38
- # @return [String] the background attribute
39
- def background=(light_or_dark)
40
- unless (light_or_dark =~ /^light$|^dark$/).nil?
41
- @background = light_or_dark
42
- end
43
- end
44
-
45
- # Sets the background color by attempting to determine it.
46
- #
47
- # @return[String] the background attribute
48
- def background!
49
- @background =
50
- if normal = highlights.find_by_group('Normal')
51
- return 'dark' unless color = normal.guibg
52
- color.partition('#').last.to_i(16) <= 8421504 ? 'dark' : 'light'
53
- else
54
- 'dark'
55
- end
56
- end
57
-
58
- # Returns the set of highlights for the colorscheme
59
- def highlight_set
60
- @highlight_set ||= HighlightSet.new
61
- end
62
- alias_method :highlights, :highlight_set
63
-
64
- # Creates a new highlight
65
- #
66
- # If inside of a language block the langauge name is automatcially prepended
67
- # to the group name of the new highlight.
68
- #
69
- # @see Vic::Highlight
70
- # @return [Vic::Highlight] the new highlight
71
- def highlight(group, args={})
72
- return if args.empty?
73
-
74
- if h = find_highlight(group)
75
- h.update_arguments! args
76
- else
77
- h = Highlight.new "#{language}#{group}", args
78
- highlight_set.add h
79
- end
80
- end
81
- alias_method :hi, :highlight
82
-
83
- def find_highlight(group)
84
- highlight_set.find_by_group(group)
85
- end
86
-
87
- # Sets the current language to name. Any new highlights created will have
88
- # the language name automatically prepended.
89
- #
90
- # @return [String] the new language name
91
- def language=(name)
92
- @language = name
93
- end
94
-
95
- # Returns the current language or temporarily sets the language to name if
96
- # a block is given. If a block is given with no arguments, it will be
97
- # evaluated in the context of the colorscheme, otherwise it will yield the
98
- # colorscheme.
99
- #
100
- # @param [String,Symbol] name the name of the language
101
- # @param [Proc] block the block to be evalauted
102
- # @return [String] the current language
103
- def language(name=nil, &block)
104
- if @language and not name
105
- return @language
106
- elsif name and block_given?
107
- previous_language = self.language
108
- self.language = name
109
- block.arity == 0 ? instance_eval(&block) : yield(self)
110
- self.language = previous_language
111
- end
112
- end
113
-
114
- # Returns the colorscheme header.
115
- #
116
- # @return [String] the colorscheme header
117
- def header
118
- <<-EOT.gsub(/^ {6}/, '')
119
- " Vim color file
120
- #{info.to_a.map do |pair|
121
- pair.join(": ").tap {|s| s[0] = '" ' + s[0].upcase }
122
- end.join("\n")}
123
- set background=#{background}
124
- hi clear
125
-
126
- if exists("syntax_on")
127
- syntax reset
128
- endif
129
-
130
- let g:colors_name="#{colors_name}"
131
- EOT
132
- end
133
-
134
- # Returns the colorscheme as a string
135
- #
136
- # @return [String] the colorscheme
137
- def write
138
- [header, highlights.map(&:write)].join("\n")
139
- end
140
- end
141
- end
@@ -1,97 +0,0 @@
1
- module Vic
2
- class Colorscheme::Highlight
3
-
4
- attr_accessor :group
5
-
6
- # Creates an instance of Vic::Colorscheme::Highlight. Uses
7
- # `update_arguments!` to set the arguments.
8
- #
9
- # @param [String] group the group name, 'Normal', 'Function', etc.
10
- # @param [Hash] args the arguments to set
11
- # @return [Vic::Colorscheme::Highlight] the new highlight
12
- def initialize(group, args={})
13
- # Convert to group name to symbol to ensure consistency
14
- @group = group.to_sym
15
- update_arguments!(args)
16
- end
17
-
18
- # Sets the methods term, term=, start, start=, etc. for settings arguments.
19
- self.class_eval do
20
- %w{term start stop cterm ctermfg ctermbg gui guifg guibg}.each do |m|
21
-
22
- # Getter method
23
- define_method(m) do
24
- arg = argument_set.find_by_key(m)
25
- return arg.val if arg
26
- end
27
-
28
- # Setter method
29
- define_method("#{m}=") do |val|
30
- arg = argument_set.find_by_key(m)
31
- if arg
32
- arg.val = val
33
- else
34
- arg = Argument.new(m, val)
35
- argument_set.add arg
36
- end
37
- end
38
- end
39
- end
40
-
41
- # Sets guifg and ctermfg simultaneously. `hex` is automatically converted to
42
- # the 256 color code for ctermfg.
43
- #
44
- # @param [String] hex a hexidecimal color
45
- def fg=(color)
46
- if color == 'NONE'
47
- self.ctermfg = color
48
- elsif Color.is_hexadecimal?(color)
49
- self.ctermfg = Color.hex_to_256(color)
50
- else
51
- raise ColorError.new "invalid hexadecimal color #{color}"
52
- end
53
-
54
- self.guifg = color
55
- end
56
-
57
- # Sets guibg and ctermbg simultaneously. `hex` is automatically converted to
58
- # the 256 color code for ctermbg.
59
- #
60
- # @param [String] hex a hexidecimal color
61
- def bg=(color)
62
- if color == 'NONE'
63
- self.ctermbg = color
64
- elsif Color.is_hexadecimal?(color)
65
- self.ctermbg = Color.hex_to_256(color)
66
- else
67
- raise ColorError.new "invalid hexadecimal color #{color}"
68
- end
69
-
70
- self.guibg = color
71
- end
72
-
73
- # Updates/sets the current highlight's arguments.
74
- #
75
- # @param [Hash] args the arguments to update/set, `:guibg => '#333333'`
76
- # @return [Vic::Colorscheme::Highlight::ArgumentSet] the updated argument set
77
- def update_arguments!(args={})
78
- args.each {|key, val| send("#{key}=", val)}
79
- arguments
80
- end
81
-
82
- # Returns the set of arguments for the given highlight
83
- #
84
- # @return [Vic::Colorscheme::Highlight::ArgumentSet] the argument set
85
- def argument_set
86
- @argument_set ||= ArgumentSet.new
87
- end
88
- alias_method :arguments, :argument_set
89
-
90
- # Writes the highlight contents.
91
- #
92
- # @return [String] the highlight as a string
93
- def write
94
- "hi #{group} #{arguments.sort_by_key.map(&:write).compact.join(' ')}"
95
- end
96
- end
97
- end
@@ -1,27 +0,0 @@
1
- module Vic
2
- class Colorscheme::Highlight::Argument
3
- VALID = %w{term start stop cterm ctermfg ctermbg gui guifg guibg guisp font}
4
-
5
- attr_accessor :key, :val
6
-
7
- def initialize(key, val)
8
- @key, @val = key, val
9
- end
10
-
11
- # The argument as a string
12
- #
13
- # @return [String,nil] the string if argument has been set
14
- def write
15
- return unless val
16
- "#{key}=#{val.respond_to?(:join) ? val.join(',') : val}"
17
- end
18
-
19
- # Checks if `key` is valid vim key for an argument
20
- #
21
- # @param [String,Symbol]
22
- # @return [true,false] the key is valid
23
- def self.is_valid?(key)
24
- VALID.include?(key.to_s)
25
- end
26
- end
27
- end
@@ -1,41 +0,0 @@
1
- module Vic
2
- class Colorscheme::Highlight::ArgumentSet
3
- include Enumerable
4
-
5
- def arguments
6
- @arguments ||= []
7
- end
8
-
9
- def each
10
- arguments.each {|a| yield a }
11
- end
12
-
13
- # Adds a new argument to the set
14
- #
15
- # @param [Colorscheme::Highlight::Argument] argument the argument to add
16
- # @return [Colorscheme::Highlight::ArgumentSet] the new set of arguments
17
- def add(argument)
18
- if argument.respond_to? :val
19
- arguments.push argument
20
- else
21
- # Raise an Exception
22
- raise TypeError.new("expted type Colorscheme::Highlight::Argument")
23
- end
24
- end
25
-
26
- # Finds an argument by a key.
27
- #
28
- # @param [String,Symbol] key the key to search for
29
- # @return [Colorscheme::Highlight::Argument,nil] the new argument
30
- def find_by_key(key)
31
- find {|a| a.key.to_s == key.to_s }
32
- end
33
-
34
- # Sorts the arguments by key name
35
- #
36
- # @return [Colorscheme::Highlight::ArgumentSet] the sorted set of arguments
37
- def sort_by_key
38
- sort {|a, b| a.key.to_s <=> b.key.to_s }
39
- end
40
- end
41
- end
@@ -1,34 +0,0 @@
1
- module Vic
2
- class Colorscheme::HighlightSet
3
- include Enumerable
4
-
5
- def highlights
6
- @highlights ||= []
7
- end
8
-
9
- def each
10
- highlights.each {|h| yield h }
11
- end
12
-
13
- # Adds a highlight to the set.
14
- #
15
- # @param [Colorscheme::Highlight] highlight the highlight to add
16
- # @return [Colorscheme::HighlightSet] the updated set of highlights
17
- def add(highlight)
18
- if highlight.respond_to? :gui
19
- highlights.push highlight
20
- else
21
- # Raise and Exception
22
- raise TypeError.new("expected type Colorscheme::Vic::Highlight")
23
- end
24
- end
25
-
26
- # Find a highlight by group name
27
- #
28
- # @param [String] group the group name
29
- # @return [Colorscheme::Highlight,nil] the highlight
30
- def find_by_group(group)
31
- find {|h| h.group == group.to_sym }
32
- end
33
- end
34
- end