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