class RDoc::Parser::ChangeLog

一个 ChangeLog 文件解析器。

此解析器将 ChangeLog 转换为 RDoc::Markup::Document。当以 HTML 格式查看时,ChangeLog 页面将在侧边栏目录中为每天的条目设置一个条目。

此解析器旨在解析 MRI ChangeLog,但也可用于解析任何 GNU 风格的 Change Log

公共实例方法

continue_entry_body(entry_body, continuation) 点击以切换源

将上一行的 continuation 附加到 entry_body

连续的函数列表被连接在一起作为一个条目。连续的描述被连接在一起形成一个段落。

# File 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) 点击以切换源

给定 ChangeLog 条目的 groups,创建一个 RDoc::Markup::Document

# File 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) 点击以切换源

返回给定 entriesChangeLog 条目的列表,其中包含 RDoc::Markup 节点。

# File 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) 点击以切换源

返回一个 RDoc::Markup::List,其中包含 ChangeLog 中的给定 items

# File 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) 点击以切换源

按日期对 entries 进行分组。

# File 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) 点击以切换源

解析 ISO-8601、RFC-2822 或 Git 的默认日期。

# File 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() 点击以切换源

解析 ChangeLog 中的条目。

按照解析顺序返回每个 ChangeLog 条目的数组。

ChangeLog 条目是一个数组,其中包含 ChangeLog 标题(日期和提交者)以及一个 ChangeLog 项目数组(已更改的文件和函数以及描述)。

一个示例结果如下

[ 'Tue Dec  4 08:33:46 2012  Eric Hodel  <[email protected]>',
  [ 'README.EXT:  Converted to RDoc format',
    'README.EXT.ja:  ditto']]
# File 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() 点击以切换源

ChangeLog 转换为 RDoc::Markup::Document

# File 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