123456789_123456789_123456789_123456789_123456789_

Class: RDoc::Parser::ChangeLog

Relationships & Source Files
Namespace Children
Modules:
Git
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Instance Chain:
Inherits: RDoc::Parser
Defined in: lib/rdoc/parser/changelog.rb

Overview

A ChangeLog file parser.

This parser converts a ChangeLog into an ::RDoc::Markup::Document. When viewed as HTML a ChangeLog page will have an entry for each day’s entries in the sidebar table of contents.

This parser is meant to parse the MRI ChangeLog, but can be used to parse any GNU style Change Log.

Class Attribute Summary

::RDoc::Parser - Inherited

.parsers

An Array of arrays that maps file extension (or name) regular expressions to parser classes that will parse matching filenames.

Class Method Summary

::RDoc::Parser - Inherited

.alias_extension

::RDoc::Alias an extension to another extension.

.binary?

Determines if the file is a “binary” file which basically means it has content that an ::RDoc::RDoc parser shouldn’t try to consume.

.can_parse

Return a parser that can handle a particular extension.

.can_parse_by_name

Returns a parser that can handle the extension for #file_name.

.check_modeline

Returns the file type from the modeline in #file_name

.for

Finds and instantiates the correct parser for the given #file_name and content.

.new

Creates a new ::RDoc::Parser storing top_level, #file_name, content, options and stats in instance variables.

.parse_files_matching

Record which file types this parser can understand.

.remove_modeline

Removes an emacs-style modeline from the first line of the document.

.use_markup

If there is a markup: parser_name comment at the front of the file, use it to determine the parser.

.zip?

Checks if file is a zip file in disguise.

Instance Attribute Summary

::RDoc::Parser - Inherited

#file_name

The name of the file being parsed.

Instance Method Summary

::RDoc::Parser - Inherited

#handle_tab_width

Normalizes tabs in body

Constructor Details

This class inherits a constructor from RDoc::Parser

Instance Method Details

#continue_entry_body(entry_body, continuation)

Attaches the continuation of the previous line to the entry_body.

Continued function listings are joined together as a single entry. Continued descriptions are joined to make a single paragraph.

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 26

def continue_entry_body entry_body, continuation
  return unless last = entry_body.last

  if last =~ /\)\s*\z/ and continuation =~ /\A\(/ then
    last.sub!(/\)\s*\z/, ',')
    continuation = continuation.sub(/\A\(/, '')
  end

  if last =~ /\s\z/ then
    last << continuation
  else
    last << ' ' + continuation
  end
end

#create_document(groups)

Creates an ::RDoc::Markup::Document given the groups of ChangeLog entries.

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 44

def create_document groups
  doc = RDoc::Markup::Document.new
  doc.omit_headings_below = 2
  doc.file = @top_level

  doc << RDoc::Markup::Heading.new(1, File.basename(@file_name))
  doc << RDoc::Markup::BlankLine.new

  groups.sort_by do |day,| day end.reverse_each do |day, entries|
    doc << RDoc::Markup::Heading.new(2, day.dup)
    doc << RDoc::Markup::BlankLine.new

    doc.concat create_entries entries
  end

  doc
end

#create_entries(entries)

Returns a list of ChangeLog entries an ::RDoc::Markup nodes for the given entries.

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 66

def create_entries entries
  out = []

  entries.each do |entry, items|
    out << RDoc::Markup::Heading.new(3, entry)
    out << RDoc::Markup::BlankLine.new

    out << create_items(items)
  end

  out
end

#create_items(items)

Returns an ::RDoc::Markup::List containing the given items in the ChangeLog

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 83

def create_items items
  list = RDoc::Markup::List.new :NOTE

  items.each do |item|
    item =~ /\A(.*?(?:\([^)]+\))?):\s*/

    title = $1
    body = $'

    paragraph = RDoc::Markup::Paragraph.new body
    list_item = RDoc::Markup::ListItem.new title, paragraph
    list << list_item
  end

  list
end

#group_entries(entries)

Groups entries by date.

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 103

def group_entries entries
  @time_cache ||= {}
  entries.group_by do |title, _|
    begin
      time = @time_cache[title]
      (time || parse_date(title)).strftime '%Y-%m-%d'
    rescue NoMethodError, ArgumentError
      time, = title.split '  ', 2
      parse_date(time).strftime '%Y-%m-%d'
    end
  end
end

#parse_date(date)

Parse date in ISO-8601, RFC-2822, or default of ChangeLog::Git

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 119

def parse_date(date)
  case date
  when /\A\s*(\d)-(\d)-(\d+)(?:[ T](\d):(\d):(\d+) *([-+]\d\d):?(\d\d))?\b/
    Time.new($1, $2, $3, $4, $5, $6, ("#{$7}:#{$8}" if $7))
  when /\A\s*\w{3}, (\d) (\w{3}) (\d+) (\d):(\d):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
    Time.new($3, $2, $1, $4, $5, $6, ("#{$7}:#{$8}" if $7))
  when /\A\s*\w{3} (\w{3}) (\d) (\d+) (\d):(\d):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
    Time.new($3, $1, $2, $4, $5, $6, ("#{$7}:#{$8}" if $7))
  when /\A\s*\w{3} (\w{3}) (\d) (\d):(\d):(\d+) (\d+)\b/
    Time.new($6, $1, $2, $3, $4, $5)
  else
    raise ArgumentError, "bad date: #{date}"
  end
end

#parse_entries

Parses the entries in the ChangeLog.

Returns an Array of each ChangeLog entry in order of parsing.

A ChangeLog entry is an Array containing the ChangeLog title (date and committer) and an Array of ChangeLog items (file and function changed with description).

An example result would be:

[ 'Tue Dec  4 08:33:46 2012  Eric Hodel  <drbrain@segment7.net>',
  [ 'README.EXT:  Converted to RDoc format',
    'README.EXT.ja:  ditto']]
[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 149

def parse_entries
  @time_cache ||= {}

  if /\A((?:.*\n){,3})commit\s/ =~ @content
    class << self; prepend Git; end
    parse_info($1)
    return parse_entries
  end

  entries = []
  entry_name = nil
  entry_body = []

  @content.each_line do |line|
    case line
    when /^\s*$/ then
      next
    when /^\w.*/ then
      entries << [entry_name, entry_body] if entry_name

      entry_name = $&

      begin
        time = parse_date entry_name
        @time_cache[entry_name] = time
      rescue ArgumentError
        entry_name = nil
      end

      entry_body = []
    when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..."
      entry_body << $2.dup
    when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..."
      entry = $2

      if entry_body.last =~ /:/ then
        entry_body << entry.dup
      else
        continue_entry_body entry_body, entry
      end
    when /^(\t| {8})?\s*(.*)/ then
      continue_entry_body entry_body, $2
    end
  end

  entries << [entry_name, entry_body] if entry_name

  entries.reject! do |(entry, _)|
    entry == nil
  end

  entries
end

#scan

Converts the ChangeLog into an ::RDoc::Markup::Document

[ GitHub ]

  
# File 'lib/rdoc/parser/changelog.rb', line 206

def scan
  @time_cache = {}

  entries = parse_entries
  grouped_entries = group_entries entries

  doc = create_document grouped_entries

  @top_level.comment = doc

  @top_level
end