Class: RDoc::Markup::ToAnsi

Inherits:
ToRdoc show all
Defined in:
lib/rdoc/markup/to_ansi.rb

Overview

Outputs RDoc markup with vibrant ANSI color!

Constant Summary collapse

ANSI_STYLE_CODES_ON =

Maps attributes to ANSI sequences

{
  BOLD: 1,
  TT: 7,
  EM: 4,
  STRIKE: 9
}
ANSI_STYLE_CODES_OFF =
{
  BOLD: 22,
  TT: 27,
  EM: 24,
  STRIKE: 29
}

Constants inherited from ToRdoc

RDoc::Markup::ToRdoc::DEFAULT_HEADINGS

Instance Attribute Summary

Attributes inherited from ToRdoc

#indent, #list_index, #list_type, #list_width, #prefix, #res, #width

Instance Method Summary collapse

Methods inherited from ToRdoc

#accept_blank_line, #accept_block_quote, #accept_heading, #accept_indented_paragraph, #accept_list_end, #accept_list_start, #accept_paragraph, #accept_raw, #accept_rule, #accept_table, #accept_verbatim, #attributes, #emit_inline, #end_accepting, #handle_BOLD, #handle_BOLD_WORD, #handle_EM, #handle_EM_WORD, #handle_HARD_BREAK, #handle_PLAIN_TEXT, #handle_REGEXP_HANDLING_TEXT, #handle_STRIKE, #handle_TIDYLINK, #handle_TT, #handle_regexp_SUPPRESSED_CROSSREF, #off, #on, #use_prefix, #wrap

Methods inherited from Formatter

#accept_document, #add_regexp_handling_RDOCLINK, #annotate, #apply_regexp_handling, #convert, #convert_string, gen_relative_url, #handle_BOLD, #handle_BOLD_WORD, #handle_EM, #handle_EM_WORD, #handle_HARD_BREAK, #handle_PLAIN_TEXT, #handle_REGEXP_HANDLING_TEXT, #handle_STRIKE, #handle_TEXT, #handle_TIDYLINK, #handle_TT, #ignore, #parse_url, #traverse_inline_nodes, #tt?

Constructor Details

#initialize(markup = nil) ⇒ ToAnsi

Creates a new ToAnsi visitor that is ready to output vibrant ANSI color!



10
11
12
13
14
15
16
17
# File 'lib/rdoc/markup/to_ansi.rb', line 10

def initialize(markup = nil)
  super

  @headings.clear
  @headings[1] = ["\e[1;32m", "\e[m"] # bold
  @headings[2] = ["\e[4;32m", "\e[m"] # underline
  @headings[3] = ["\e[32m",   "\e[m"] # just green
end

Instance Method Details

#accept_list_item_end(list_item) ⇒ Object

Overrides indent width to ensure output lines up correctly.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rdoc/markup/to_ansi.rb', line 78

def accept_list_item_end(list_item)
  width = case @list_type.last
          when :BULLET then
            2
          when :NOTE, :LABEL then
            if @prefix then
              @res << @prefix.strip
              @prefix = nil
            end

            @res << "\n" unless res.length == 1
            2
          else
            bullet = @list_index.last.to_s
            @list_index[-1] = @list_index.last.succ
            bullet.length + 2
          end

  @indent -= width
end

#accept_list_item_start(list_item) ⇒ Object

Adds coloring to note and label list items



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rdoc/markup/to_ansi.rb', line 102

def accept_list_item_start(list_item)
  bullet = case @list_type.last
           when :BULLET then
             '*'
           when :NOTE, :LABEL then
             labels = Array(list_item.label).map do |label|
               attributes(label).strip
             end.join "\n"

             labels << ":\n" unless labels.empty?

             labels
           else
             @list_index.last.to_s + '.'
           end

  case @list_type.last
  when :NOTE, :LABEL then
    @indent += 2
    @prefix = bullet + (' ' * @indent)
  else
    @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)

    width = bullet.gsub(/\e\[[\d;]*m/, '').length + 1

    @indent += width
  end
end

#add_text(text) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/rdoc/markup/to_ansi.rb', line 59

def add_text(text)
  attrs = @attributes.keys
  if @applied_attributes != attrs
    apply_attributes(attrs)
  end
  emit_inline(text)
end

#apply_attributes(attributes) ⇒ Object

Apply the given attributes by emitting ANSI sequences. Emitting attribute changes are deferred until new text is added and applied in batch. This method computes the necessary ANSI codes to transition from the current set of applied attributes to the new set of attributes.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rdoc/markup/to_ansi.rb', line 41

def apply_attributes(attributes)
  before = @applied_attributes
  after = attributes.sort
  return if before == after

  if after.empty?
    emit_inline("\e[m")
  elsif !before.empty? && before.size > (before & after).size + 1
    codes = after.map {|attr| ANSI_STYLE_CODES_ON[attr] }.compact
    emit_inline("\e[#{[0, *codes].join(';')}m")
  else
    off_codes = (before - after).map {|attr| ANSI_STYLE_CODES_OFF[attr] }.compact
    on_codes = (after - before).map {|attr| ANSI_STYLE_CODES_ON[attr] }.compact
    emit_inline("\e[#{(off_codes + on_codes).join(';')}m")
  end
  @applied_attributes = attributes
end

#calculate_text_width(text) ⇒ Object



131
132
133
# File 'lib/rdoc/markup/to_ansi.rb', line 131

def calculate_text_width(text)
  text.gsub(/\e\[[\d;]*m/, '').size
end

#handle_inline(text) ⇒ Object



67
68
69
70
71
72
73
# File 'lib/rdoc/markup/to_ansi.rb', line 67

def handle_inline(text)
  @applied_attributes = []
  res = super
  res << "\e[m" unless @applied_attributes.empty?
  @applied_attributes = []
  res
end

#start_acceptingObject

Starts accepting with a reset screen



138
139
140
141
142
# File 'lib/rdoc/markup/to_ansi.rb', line 138

def start_accepting
  super

  @res = ["\e[0m"]
end