class Discoball::Highlighter

Public Class Methods

new(patterns, color_mode = :individual, match_mode = :all) click to toggle source

Patterns is an array of patterns to match. There are two options that can be changed:

* color_mode
  -:individual - each unique string matching one of the patterns will be a different color.
  -:group_colors - the matches corresponding to each pattern will be the same color.
  -:one_color - all matches will be a single color.
* match_mode
  -:all - all lines are returned
  -:match_any - lines matching any pattern are returned
  -:match_all - only lines matching every pattern are returned
# File lib/discoball.rb, line 20
def initialize(patterns, color_mode = :individual, match_mode = :all)
  @patterns = patterns
  @color_mode = color_mode
  @match_mode = match_mode
  @color_stack = String.colors.reject { |color| UNUSABLE_COLORS.any? { |unusable| color =~ unusable } }
  @color_assignments = {}
  if color_mode == :group_colors
    @patterns.each { |pattern| @color_assignments[pattern] = pop_rotate }
  end
end

Public Instance Methods

filter(line) click to toggle source
# File lib/discoball.rb, line 31
def filter(line)
  match_found = {}
  @patterns.each { |pattern| match_found[pattern] = false }

  case @color_mode
  when :one_color
    matches = @patterns.reduce([]) { |memo, pattern| # No Array#flat_map in Ruby 1.8 :\
      m = line.scan(pattern).map { |match| match.is_a?(Array) ? match.first : match }
      match_found[pattern] = true unless m.empty?
      memo += m
    }.uniq
    matches.each { |match| highlight!(line, match, SINGLE_COLOR) }
  when :group_colors
    @patterns.each do |pattern|
      matches = line.scan(pattern).map { |match| match.is_a?(Array) ? match.first : match }.uniq
      match_found[pattern] = true unless matches.empty?
      matches.each { |match| highlight!(line, match, @color_assignments[pattern]) }
    end
  when :individual
    matches = @patterns.reduce([]) { |memo, pattern|
      m = line.scan(pattern).map { |match| match.is_a?(Array) ? match.first : match }
      match_found[pattern] = true unless m.empty?
      memo += m
    }.uniq
    matches.each do |match|
      unless @color_assignments.include? match
        @color_assignments[match] = pop_rotate
      end
      matches.each { |match| highlight!(line, match, @color_assignments[match]) }
    end
  end

  case @match_mode
  when :match_any
    match_found.any? { |pattern, found| found } ? line : nil
  when :match_all
    match_found.all? { |pattern, found| found } ? line : nil
  else
    line
  end
end

Private Instance Methods

highlight!(line, match, color) click to toggle source
# File lib/discoball.rb, line 75
def highlight!(line, match, color)
  line.gsub!(match, match.colorize(color).underline)
end
pop_rotate() click to toggle source

Get the next color and put it at the back

# File lib/discoball.rb, line 80
def pop_rotate
  color = @color_stack.pop
  @color_stack.unshift color
  color
end