ardekantur (owner)

Revisions

gist: 95979 Download_button fork
public
Public Clone URL: git://gist.github.com/95979.git
Embed All Files: show embed
amorfus.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
require 'rubygems'
require 'fileutils'
require 'nokogiri'
 
DIRECTORY_HEADER_LEVEL = 3
 
def asciidoc_header size, name
  '=' * size + " #{name}\n\n"
end
 
class DocumentedClass
 
  attr_accessor :name, :children, :description
  
  def initialize name, description, header_level = DIRECTORY_HEADER_LEVEL + 1
    @name = name
    @description = description
    @children = {}
    @hl = header_level
  end
  
  def add_child identifier, description
    @children[identifier] = description unless identifier == ""
  end
  
  def to_s
    @name.to_sym
  end
  
  def to_asciidoc with_headers = true
    doc = ""
    doc += asciidoc_header(@hl, @name) + @description + "\n\n" if with_headers
    const = @children.delete(:Constructor)
    doc += asciidoc_header(@hl + 1, :Constructor) + const + "\n\n" if const
    const = @children.delete(:Destructor)
    doc += asciidoc_header(@hl + 1, :Destructor) + const + "\n\n" if const
    @children.each { |name, desc| doc += asciidoc_header(@hl + 1, name) + desc + "\n\n" }
    return doc
  end
    
end
 
class CommentDocParser
  
  attr_accessor :trunk_dir, :comments, :classes
  
  def initialize section, section_name, trunk_dir = '.'
    @trunk_dir = trunk_dir
    @section = section
    @section_name = section_name
    @classes = []
    `mkdir -p dia/#{@section}`
    `mkdir -p images/#{@section}`
  end
  
  def cleaned_comment comment
    comment.gsub!(/\/\*+/, '')
    comment.gsub!(/^[ \t]*\*/, '')
    comment.gsub!(/\n/, '')
    comment.gsub!(/@param\s+(\w+)/, 'The parameter `\1` is')
    comment.gsub!(/@return/, 'This function returns')
    comment.strip!
  end
  
  def cleaned_identifier identifier
    return :Destructor if identifier.strip =~ /^~/
    return :Constructor if identifier.strip =~ /^\w+\(/
    result = identifier
    result.gsub!(/^(.*?)\s*\*? (\w+)(.*)/, '\2')
    result.strip!
    return identifier if result == ""
    return result.to_sym
  end
  
  def to_asciidoc
    doc = ""
    doc += asciidoc_header(DIRECTORY_HEADER_LEVEL, @section_name)
    @classes.each do |klass|
      if @got_image_for[klass.name]
        # We need to knock other objects out of the dia diagram
        xml = Nokogiri::XML(open("dia/#{@section}/#{klass.name}.dia"))
        unless xml.xpath('//dia:object').count == 1
          new_xml = <<-XML
<?xml version="1.0"?>
<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
 
XML
          new_xml += xml.xpath('//dia:diagramdata').to_s
          new_xml += ' <dia:layer name="Background" visible="true">'
          new_xml += "\n "
          right_index = xml.xpath('//dia:object/dia:attribute[@name="name"]/dia:string').inner_text.split('#').delete_if { |a| a == "" }.index(klass.name.to_s)
          if right_index
            puts "Completely rewriting dia file for #{klass.name} to only include Dia object at index #{right_index}"
            new_xml += xml.xpath('//dia:object')[right_index].to_s
            new_xml += " </dia:layer>\n</dia:diagram>"
            f = File.new("dia/#{@section}/#{klass.name}.dia", "w")
            f.write new_xml
            f.close
          else
            doc += klass.to_asciidoc
            next
          end
        end
        `dia -t png -e images/#{@section}/#{klass.name}.png dia/#{@section}/#{klass.name}.dia`
        doc += asciidoc_header(DIRECTORY_HEADER_LEVEL + 1, klass.name)
        doc += "image::images/#{@section}/#{klass.name}.png[scaledwidth=\"75%\"]\n\n"
        doc += klass.description + "\n\n"
        doc += klass.to_asciidoc false
      else
        doc += klass.to_asciidoc
      end
    end
    return doc
  end
  
  def parse
    @comments = {}
    @got_image_for = {}
    files = Dir["#{@trunk_dir}/clementine/#{@section}/**/*.cxx"] | Dir["#{@trunk_dir}/clementine/#{@section}/**/*.h"]
 
    beginning_comment = /^[ \t]*\/\*/
    ending_comment = /^[ \t]*\*\//
 
    files.each do |file|
      found_comment_block = false
      found_identifier = false
      comment_block = ""
      handle = File.new(file)
      begin
        while line = handle.readline
          if line =~ beginning_comment
            found_comment_block = true
          end
          if line =~ ending_comment
            found_comment_block = false
            found_identifier = true
          end
          if found_comment_block
            comment_block += line if found_comment_block
          end
          if found_identifier
            @comments[file] ||= {}
            identifier = handle.readline.strip
            if identifier =~ /^[ \t]*(class|struct)/
              identifier = identifier.gsub(/^[ \t]*(class|struct)[ ]+/, '').to_sym
              @classes << DocumentedClass.new(identifier, cleaned_comment(comment_block))
              `autodia.pl -l c++ -i #{file} -o dia/#{@section}/#{identifier.to_s}.dia`
              @got_image_for[identifier] = ($? == 0) ? true : false
            end
            if @classes.last
              if identifier != @classes.last.name
                @classes.last.add_child(cleaned_identifier(identifier), cleaned_comment(comment_block))
              end
            else
              if cleaned_identifier(identifier) != ""
                @comments[file][cleaned_identifier(identifier)] = cleaned_comment(comment_block)
              end
            end
            comment_block = ""
            found_identifier = false
          end
        end
      rescue EOFError
        next
      end
    end
  end
  
end