lib/rouge/theme.rb in rouge-0.0.5 vs lib/rouge/theme.rb in rouge-0.0.6
- old
+ new
@@ -1,47 +1,111 @@
module Rouge
class Theme
+ class InheritableHash < Hash
+ def initialize(parent=nil)
+ @parent = parent
+ end
+
+ def [](k)
+ _sup = super
+ return _sup if own_keys.include?(k)
+
+ _sup || parent[k]
+ end
+
+ def parent
+ @parent ||= {}
+ end
+
+ def include?(k)
+ super or parent.include?(k)
+ end
+
+ def each(&b)
+ keys.each do |k|
+ b.call(k, self[k])
+ end
+ end
+
+ alias own_keys keys
+ def keys
+ keys = own_keys.concat(parent.keys)
+ keys.uniq!
+ keys
+ end
+ end
+
class Style < Hash
+ def initialize(theme, hsh={})
+ super()
+ @theme = theme
+ merge!(hsh)
+ end
+
def render(selector, &b)
return enum_for(:render, selector).to_a.join("\n") unless b
return if empty?
yield "#{selector} {"
- yield " color: #{self[:fg]};" if self[:fg]
- yield " background-color: #{self[:bg]};" if self[:bg]
+ yield " color: #{@theme.palette(self[:fg])};" if self[:fg]
+ yield " background-color: #{@theme.palette(self[:bg])};" if self[:bg]
yield " font-weight: bold;" if self[:bold]
yield " font-style: italic;" if self[:italic]
yield " text-decoration: underline;" if self[:underline]
(self[:rules] || []).each do |rule|
yield " #{rule};"
end
yield "}"
end
+
end
- class << self
- def styles
- @styles ||= {}
+ def styles
+ @styles ||= self.class.styles.dup
+ end
+
+ @palette = {}
+ def self.palette(arg={})
+ @palette ||= InheritableHash.new(superclass.palette)
+
+ if arg.is_a? Hash
+ @palette.merge! arg
+ @palette
+ else
+ case arg
+ when /#[0-9a-f]+/i
+ arg
+ else
+ @palette[arg] or raise "not in palette: #{arg.inspect}"
+ end
end
+ end
+ @styles = {}
+ def self.styles
+ @styles ||= InheritableHash.new(superclass.styles)
+ end
+
+ class << self
def style(*tokens)
- style = Style.new
- style.merge!(tokens.pop) if tokens.last.is_a? Hash
+ style = tokens.last.is_a?(Hash) ? tokens.pop : {}
+ style = Style.new(self, style)
+
tokens.each do |tok|
styles[tok.to_s] = style
end
end
def name(n=nil)
return @name if n.nil?
@name = n.to_s
- registry[@name] = self
+ Theme.registry[@name] = self
end
def find(n)
registry[n.to_s]
end
@@ -50,19 +114,40 @@
@registry ||= {}
end
end
end
+ module HasModes
+ def mode(arg=:absent)
+ return @mode if arg == :absent
+
+ @modes ||= {}
+ @modes[arg] ||= get_mode(arg)
+ end
+
+ def get_mode(mode)
+ return self if self.mode == mode
+
+ new_name = "#{self.name}.#{mode}"
+ Class.new(self) { name(new_name); mode!(mode) }
+ end
+
+ def mode!(arg)
+ @mode = arg
+ send("make_#{arg}!")
+ end
+ end
+
class CSSTheme < Theme
def initialize(opts={})
@scope = opts[:scope] || '.highlight'
end
def render(&b)
return enum_for(:render).to_a.join("\n") unless b
- self.class.styles.each do |tokname, style|
+ styles.each do |tokname, style|
style.render(css_selector(Token[tokname]), &b)
end
end
private
@@ -90,10 +175,10 @@
def inflate_token(tok, &b)
return enum_for(:inflate_token, tok) unless block_given?
yield tok
tok.sub_tokens.each_value do |st|
- next if self.class.styles.include? st.name
+ next if styles[st.name]
inflate_token(st, &b)
end
end
end