Text::Format provides the ability to nicely format fixed-width text with knowledge of the writeable space (number of columns), margins, and indentation settings.
Copyright © 2002 - 2005 by Austin Ziegler
1.0.0
Perl Text::Format, Copyright © 1998 Gábor Egressy
Ruby’s, Perl Artistic, or GPL version 2 (or later)
Compares the formatting rules, excepting hyphenator, of two Text::Format objects. Generated results (e.g., split_words) are not compared.
# File lib/text/format.rb, line 188 def ==(o) (@text == o.text) and (@columns == o.columns) and (@left_margin == o.left_margin) and (@right_margin == o.right_margin) and (@hard_margins == o.hard_margins) and (@split_rules == o.split_rules) and (@first_indent == o.first_indent) and (@body_indent == o.body_indent) and (@tag_text == o.tag_text) and (@tabstop == o.tabstop) and (@format_style == o.format_style) and (@extra_space == o.extra_space) and (@tag_paragraph == o.tag_paragraph) and (@nobreak == o.nobreak) and (@terminal_punctuation == o.terminal_punctuation) and (@terminal_quotes == o.terminal_quotes) and (@abbreviations == o.abbreviations) and (@nobreak_regex == o.nobreak_regex) end
Centers the text, preserving empty lines and tabs.
# File lib/text/format.rb, line 728 def center(to_center = nil) to_center = @text if to_center.nil? to_center = [to_center].flatten tabs = 0 width = @columns - @left_margin - @right_margin centered = [] to_center.each do |tc| s = tc.strip tabs = s.count(TAB) tabs = 0 if tabs.nil? ct = ((width - s.size - (tabs * @tabstop) + tabs) / 2) ct = (width - @left_margin - @right_margin) - ct centered << "#{s.rjust(ct)}\n" end centered.join('') end
Replaces all tab characters in the text with tabstop spaces.
# File lib/text/format.rb, line 747 def expand(to_expand = nil) to_expand = @text if to_expand.nil? tmp = ' ' * @tabstop changer = lambda do |text| res = text.split(NEWLINE_RE) res.collect! { |ln| ln.gsub!(/\t/, tmp) } res.join(NEWLINE) end if to_expand.kind_of?(Array) to_expand.collect { |te| changer[te] } else changer[to_expand] end end
Formats text into a nice paragraph format. The text is separated into words and then reassembled a word at a time using the settings of this Format object.
If text is nil, then the value of text will be worked on.
# File lib/text/format.rb, line 550 def format_one_paragraph(text = nil) text ||= @text text = text[0] if text.kind_of?(Array) # Convert the provided paragraph to a list of words. words = text.split(SPACES_RE).reverse.reject { |ww| ww.nil? or ww.empty? } text = [] # Find the maximum line width and the initial indent string. # TODO 20050114 - allow the left and right margins to be specified as # strings. If they are strings, then we need to use the sizes of the # strings. Also: allow the indent string to be set manually and # indicate whether the indent string will have a following space. max_line_width = @columns - @first_indent - @left_margin - @right_margin indent_str = ' ' * @first_indent first_line = true if words.empty? line = [] line_size = 0 extra_space = false else line = [ words.pop ] line_size = line[-1].size extra_space = __add_extra_space?(line[-1]) end while next_word = words.pop next_word.strip! unless next_word.nil? new_line_size = (next_word.size + line_size) + 1 if extra_space if (line[-1] !~ __sentence_end_re) extra_space = false end end # Increase the width of the new line if there's a sentence # terminator and we are applying extra_space. new_line_size += 1 if extra_space # Will the word fit onto the current line? If so, simply append it # to the end of the line. if new_line_size <= max_line_width if line.empty? line << next_word else if extra_space line << " #{next_word}" else line << " #{next_word}" end end else # Forcibly wrap the line if nonbreaking spaces are turned on and # there is a condition where words must be wrapped. If we have # returned more than one word, readjust the word list. line, next_word = __wrap_line(line, next_word) if @nobreak if next_word.kind_of?(Array) if next_word.size > 1 words.push(*(next_word.reverse)) next_word = words.pop else next_word = next_word[0] end next_word.strip! unless next_word.nil? end # Check to see if the line needs to be hyphenated. If a word has a # hyphen in it (e.g., "fixed-width"), then we can ALWAYS wrap at # that hyphenation, even if #hard_margins is not turned on. More # elaborate forms of hyphenation will only be performed if # #hard_margins is turned on. If we have returned more than one # word, readjust the word list. line, new_line_size, next_word = __hyphenate(line, line_size, next_word, max_line_width) if next_word.kind_of?(Array) if next_word.size > 1 words.push(*(next_word.reverse)) next_word = words.pop else next_word = next_word[0] end next_word.strip! unless next_word.nil? end text << __make_line(line, indent_str, max_line_width, next_word.nil?) unless line.nil? if first_line first_line = false max_line_width = @columns - @body_indent - @left_margin - @right_margin indent_str = ' ' * @body_indent end if next_word.nil? line = [] new_line_size = 0 else line = [ next_word ] new_line_size = next_word.size end end line_size = new_line_size extra_space = __add_extra_space?(next_word) unless next_word.nil? end loop do break if line.nil? or line.empty? line, line_size, ww = __hyphenate(line, line_size, ww, max_line_width)#if @hard_margins text << __make_line(line, indent_str, max_line_width, ww.nil?) line = ww ww = nil end if (@tag_paragraph and (not text.empty?)) if @tag_cur.nil? or @tag_cur.empty? @tag_cur = @tag_text[0] end fchar = /(\S)/.match(text[0])[1] white = text[0].index(fchar) unless @tag_cur.nil? if ((white - @left_margin - 1) > @tag_cur.size) then white = @tag_cur.size + @left_margin text[0].gsub!(/^ {#{white}}/, "#{' ' * @left_margin}#{@tag_cur}") else text.unshift("#{' ' * @left_margin}#{@tag_cur}\n") end end end text.join('') end
The formatting object itself can be used as a hyphenator, where the default implementation of hyphenate_to implements the conditions necessary to properly produce SPLIT_CONTINUATION.
# File lib/text/format.rb, line 531 def hyphenate_to(word, size) if (size - 2) < 0 [nil, word] else [word[0 .. (size - 2)] + "\\", word[(size - 1) .. -1]] end end
Indicates that the format style is full justification.
false
# File lib/text/format.rb, line 524 def justify? @format_style == JUSTIFY end
Indicates that the format style is left alignment.
true
# File lib/text/format.rb, line 500 def left_align? @format_style == LEFT_ALIGN end
Considers each element of text (provided or internal) as a paragraph. If first_indent is the same as body_indent, then paragraphs will be separated by a single empty line in the result; otherwise, the paragraphs will follow immediately after each other. Uses format to do the heavy lifting.
If to_wrap responds to split, then it will be split into an
array of elements by calling split with the value of split_on.
The default value of split_on is $/, or the default record separator,
repeated twice (e.g., /nn/).
# File lib/text/format.rb, line 699 def paragraphs(to_wrap = nil, split_on = /(#{$/}){2}/) to_wrap = @text if to_wrap.nil? if to_wrap.respond_to?(:split) to_wrap = to_wrap.split(split_on) else to_wrap = [to_wrap].flatten end if ((@first_indent == @body_indent) or @tag_paragraph) then p_end = NEWLINE else p_end = '' end cnt = 0 ret = [] to_wrap.each do |tw| @tag_cur = @tag_text[cnt] if @tag_paragraph @tag_cur = '' if @tag_cur.nil? line = format(tw) ret << "#{line}#{p_end}" if (not line.nil?) and (line.size > 0) cnt += 1 end ret[-1].chomp! unless ret.empty? ret.join('') end
Indicates that the format style is right alignment.
false
# File lib/text/format.rb, line 508 def right_align? @format_style == RIGHT_ALIGN end
Indicates that the format style is right fill.
false
# File lib/text/format.rb, line 516 def right_fill? @format_style == RIGHT_FILL end
Splits the provided word so that it is in two parts, word[0 .. (size
- 1)] and word[size .. -1].
# File lib/text/format.rb, line 541 def split_word_to(word, size) [word[0 .. (size - 1)], word[size .. -1]] end
Replaces all occurrences of tabstop consecutive spaces with a tab character.
# File lib/text/format.rb, line 766 def unexpand(to_unexpand = nil) to_unexpand = @text if to_unexpand.nil? tmp = / {#{@tabstop}}/ changer = lambda do |text| res = text.split(NEWLINE_RE) res.collect! { |ln| ln.gsub!(tmp, TAB) } res.join(NEWLINE) end if to_unexpand.kind_of?(Array) to_unexpand.collect { |tu| changer[tu] } else changer[to_unexpand] end end
Create a Text::Format object. Accepts an optional
hash of construction options (this will be changed to named paramters in
Ruby 2.0). After the initial object is constructed (with either the
provided or default values), the object will be yielded (as
self) to an optional block for further construction and
operation.
# File lib/text/format.rb, line 1016 def initialize(options = {}) #:yields self: @text = options[:text] || [] @columns = options[:columns] || 72 @tabstop = options[:tabstop] || 8 @first_indent = options[:first_indent] || 4 @body_indent = options[:body_indent] || 0 @format_style = options[:format_style] || LEFT_ALIGN @left_margin = options[:left_margin] || 0 @right_margin = options[:right_margin] || 0 @extra_space = options[:extra_space] || false @tag_paragraph = options[:tag_paragraph] || false @tag_text = options[:tag_text] || [] @abbreviations = options[:abbreviations] || [] @terminal_punctuation = options[:terminal_punctuation] || "" @terminal_quotes = options[:terminal_quotes] || "" @nobreak = options[:nobreak] || false @nobreak_regex = options[:nobreak_regex] || {} @hard_margins = options[:hard_margins] || false @split_rules = options[:split_rules] || SPLIT_FIXED @hyphenator = options[:hyphenator] || self @hyphenator_arity = @hyphenator.method(:hyphenate_to).arity @tag_cur = "" @split_words = [] yield self if block_given? end