# This application is free software; you can redistribute it and/or # modify it under the terms of the Ruby license defined in the # COPYING file. # # Copyright (C) 2005 Martin DeMello. All rights reserved. # # This class is mostly copy & paste from ri_formatter.rb. # except that it always returns a string and does not print anything. class FoxTextFormatter # define all possible styles STYLE_NORMAL = :STYLE_NORMAL STYLE_BOLD = :STYLE_BOLD STYLE_CLASS = :STYLE_CLASS STYLE_H1 = :STYLE_H1 STYLE_H2 = :STYLE_H2 STYLE_H3 = :STYLE_H3 STYLE_TELETYPE = :STYLE_TELETYPE STYLE_CODE = :STYLE_CODE STYLE_EMPHASIS = :STYLE_EMPHASIS attr_reader :indent attr_accessor :width # whenever text should be printed/added/shown, proc is called with the text as the argument. def initialize(width, indent, &proc) @width = width @indent = indent @proc = proc end ###################################################################### def draw_line(label=nil) len = @width len -= (label.size+1) if label len = [0, len].max @proc.call("-"*len) if label @proc.call(" ") @proc.call(label, STYLE_CLASS) end @proc.call("\n") end def display_params(method) params = method.params if params[0] == ?( if method.is_singleton params = method.full_name + params else params = method.name + params end end params.split(/\n/).each do |param| @proc.call(param+"\n", STYLE_BOLD) end end def wrap(txt, prefix=@indent, linelen=@width) return if !txt || txt.empty? @proc.call(prefix, STYLE_EMPHASIS) conv_markup(txt, prefix, linelen) =begin textLen = linelen - prefix.length patt = Regexp.new("^(.{0,#{textLen}})[ \n]") next_prefix = prefix.tr("^ ", " ") res = [] while work.length > textLen if work =~ patt res << $1 work.slice!(0, $&.length) else res << work.slice!(0, textLen) end end res << work if work.length.nonzero? @proc.call(prefix + res.join("\n" + next_prefix) + "\n") =end end ###################################################################### def blankline @proc.call("\n") end ###################################################################### # called when we want to ensure a nbew 'wrap' starts on a newline # Only needed for HtmlFormatter, because the rest do their # own line breaking def break_to_newline end ###################################################################### def bold_print(txt) @proc.call(txt, STYLE_BOLD) end ###################################################################### def raw_print_line(txt) @proc.call(txt) end ###################################################################### # convert HTML entities back to ASCII def conv_html(txt) txt. gsub(/>/, '>'). gsub(/</, '<'). gsub(/"/, '"'). gsub(/&/, '&') end # convert markup into display form def conv_markup(txt, prefix, linelen) # this code assumes that tags are not used inside tags pos = 0 old_pos = 0 style = STYLE_NORMAL current_indent = prefix.size while pos = txt.index(%r{(|||||||)}, old_pos) new_part = txt[old_pos...pos] @proc.call(new_part, style) # get tag name old_pos = txt.index(">", pos) + 1 style = case txt[(pos+1)...(old_pos-1)] when "tt" STYLE_TELETYPE when "code" STYLE_CODE when "b" STYLE_BOLD when "em" STYLE_EMPHASIS else # closing or unknown tags STYLE_NORMAL end end @proc.call(txt[old_pos...txt.size], style) @proc.call("\n") end ###################################################################### def display_list(list) case list.type when SM::ListBase::BULLET prefixer = proc { |ignored| @indent + "* " } when SM::ListBase::NUMBER, SM::ListBase::UPPERALPHA, SM::ListBase::LOWERALPHA start = case list.type when SM::ListBase::NUMBER then 1 when SM::ListBase::UPPERALPHA then 'A' when SM::ListBase::LOWERALPHA then 'a' end prefixer = proc do |ignored| res = @indent + "#{start}.".ljust(4) start = start.succ res end when SM::ListBase::LABELED prefixer = proc do |li| li.label end when SM::ListBase::NOTE longest = 0 list.contents.each do |item| if item.kind_of?(SM::Flow::LI) && item.label.length > longest longest = item.label.length end end prefixer = proc do |li| @indent + li.label.ljust(longest+1) end else fail "unknown list type" end list.contents.each do |item| if item.kind_of? SM::Flow::LI prefix = prefixer.call(item) display_flow_item(item, prefix) else display_flow_item(item) end end end ###################################################################### def display_flow_item(item, prefix=@indent) case item when SM::Flow::P, SM::Flow::LI wrap(conv_html(item.body), prefix) blankline when SM::Flow::LIST display_list(item) when SM::Flow::VERB display_verbatim_flow_item(item, @indent) when SM::Flow::H # bug #2634: it looks like in 1.8.3 a H element is sometimes # passed as a string instead of an array so check that case if item.text.kind_of? Array h_text = item.text.join else h_text = item.text end display_heading(conv_html(h_text), item.level, @indent) when SM::Flow::RULE draw_line when String wrap(conv_html(item), prefix) else fail "Unknown flow element: #{item.class}" end end ###################################################################### def display_verbatim_flow_item(item, prefix=@indent) item.body.split(/\n/).each do |line| @proc.call(@indent) @proc.call(conv_html(line)) @proc.call("\n") end blankline end ###################################################################### def display_heading(text, level, indent) case level when 1 @proc.call(text, STYLE_H1) @proc.call("\n") when 2 @proc.call(text, STYLE_H2) @proc.call("\n") else @proc.call(indent) @proc.call(text, STYLE_H3) @proc.call("\n") end end def display_flow(flow) flow.each do |f| display_flow_item(f) end end end