15 GetOptions("s" => \$stand_alone);
18 require HTTP::Server::Simple::CGI;
20 package # hide me from PAUSE
21 Class::MOP::Browser::Server;
22 our @ISA = qw(HTTP::Server::Simple::CGI);
23 sub handle_request { ::process_template() }
25 Class::MOP::Browser::Server->new()->run();
34 sub process_template {
35 $DATA ||= join "" => <DATA>;
36 Template->new->process(
39 'get_all_metaclasses' => \&::get_all_metaclasses,
40 'get_metaclass_by_name' => \&::get_metaclass_by_name,
41 'deparse_method' => \&::deparse_method,
42 'deparse_item' => \&::deparse_item,
44 ) or warn Template->error;
48 sub get_all_metaclasses {
49 sort { $a->name cmp $b->name } Class::MOP::get_all_metaclass_instances()
52 sub get_metaclass_by_name {
53 Class::MOP::get_metaclass_by_name(@_);
58 my $deparse = B::Deparse->new("-d");
59 my $body = $deparse->coderef2text($method->body());
60 return "sub " . $method->name . ' ' . _clean_deparse_code($body);
65 return $item unless ref $item;
66 local $Data::Dumper::Deparse = 1;
67 local $Data::Dumper::Indent = 1;
68 my $dumped = Dumper $item;
69 $dumped =~ s/^\$VAR1\s=\s//;
71 return _clean_deparse_code($dumped);
74 sub _clean_deparse_code {
75 my @body = split /\n/ => $_[0];
80 next if /^\s+package/;
83 return (join "\n" => @cleaned);
88 ## This is the template file to be used
93 [% area = 'attributes' %]
94 [% IF q.param('area') %]
95 [% area = q.param('area') %]
100 <title>Class::MOP Browser</title>
101 <style type='text/css'>
107 td { font-size: 12px; }
108 b { font-size: 12px; }
111 font-family: courier;
116 border: 1px dotted green;
123 text-decoration: none;
127 text-decoration: underline;
131 background-color: #99BBFF;
132 border-right: 1px solid #336699;
133 border-bottom: 1px solid #336699;
134 border-top: 1px solid #BBDDFF;
135 border-left: 1px solid #BBDDFF;
139 background-color: #CCCCCC;
140 border-right: 1px solid #888888;
141 border-bottom: 1px solid #888888;
142 border-top: 1px solid #DDDDDD;
143 border-left: 1px solid #DDDDDD;
147 background-color: #FFDD99;
148 border-right: 2px solid #CC9933;
149 border-bottom: 2px solid #CC9933;
150 border-top: 2px solid #FFFFBB;
151 border-left: 2px solid #FFFFBB;
155 background-color: #33CC33;
156 border-right: 1px solid #009900;
157 border-bottom: 1px solid #009900;
162 background-color: #AAFFAA;
163 border-right: 1px solid #33FF33;
164 border-bottom: 1px solid #33FF33;
170 <h1>Class::MOP Browser</h1>
171 <table bgcolor='#CCCCCC' cellpadding='0' cellspacing='0' border='0' align='center' height='400'>
174 <td rowspan='2' width='200'><table cellspacing='0' cellpadding='5' border='0' width='100%'>
175 [% FOREACH metaclass IN get_all_metaclasses() %]
177 [% IF q.param('class') == metaclass.name %]
178 <td class='lightblue'><b>[% metaclass.name %]</b></td>
180 <td class='grey'><a href='?class=[% metaclass.name %]'>[% metaclass.name %]</a></td>
185 <td height='10' width='250'><table cellspacing='0' cellpadding='5' border='0' width='100%'>
187 [% FOREACH area_name IN [ 'attributes', 'methods', 'superclasses' ] %]
188 [% IF q.param('class') %]
189 [% IF area == area_name %]
190 <td class='manila'><b>[% area_name %]</b></td>
192 <td class='lightblue'><a href='?class=[% q.param('class') %]&area=[% area_name %]'>[% area_name %]</a></td>
195 <td class='lightblue' style="color: #336699;">[% area_name %]</td>
201 <td valign='top' rowspan='2' class='lightgreen' width='450'>
202 <table cellspacing='0' cellpadding='3' border='0'>
204 <td class='darkgreen' width='100'></td>
205 <td class='darkgreen' width='350'></td>
207 [% IF q.param('class') && area == 'attributes' && q.param('attr') %]
210 meta = get_metaclass_by_name(q.param('class'))
211 attr = meta.get_attribute(q.param('attr'))
214 [% FOREACH aspect IN [ 'name', 'init_arg', 'reader', 'writer', 'accessor', 'predicate', 'default' ]%]
215 [% item = attr.$aspect() %]
217 <td class='darkgreen' align='right' valign='top'>[% aspect %]</td>
218 <td class='lightgreen'>[% IF item == undef %]—[% ELSE %]<pre>[% deparse_item(item) %]</pre>[% END %]</td>
222 [% ELSIF q.param('class') && area == 'methods' && q.param('method') %]
225 meta = get_metaclass_by_name(q.param('class'))
226 method = meta.get_method(q.param('method'))
229 [% FOREACH aspect IN [ 'name', 'package_name', 'fully_qualified_name' ]%]
231 <td class='darkgreen' align='right' valign='top'>[% aspect %]</td>
232 <td class='lightgreen'>[% method.$aspect() %]</td>
236 <td class='darkgreen' align='right' valign='top'>body</td>
237 <td class='lightgreen'><pre>[% deparse_method(method) %]</pre></td>
246 [% IF q.param('class') && area %]
248 [% meta = get_metaclass_by_name(q.param('class')) %]
250 <td class='lightblue' valign='top'><div style='height: 100%; overflow: auto;'><table cellspacing='0' cellpadding='5' border='0' width='100%'>
252 [% IF area == 'methods' %]
253 [% FOREACH method IN meta.get_method_list.sort %]
255 [% IF q.param('method') == method %]
256 <td class='darkgreen'><b>[% method %]</b></td>
258 <td class='manila'><a href='?class=[% q.param('class') %]&area=[% q.param('area') %]&method=[% method %]'>[% method %]</a></td>
263 [% IF area == 'attributes' %]
264 [% FOREACH attr IN meta.get_attribute_list.sort %]
266 [% IF q.param('attr') == attr %]
267 <td class='darkgreen'><b>[% attr %]</b></td>
269 <td class='manila'><a href='?class=[% q.param('class') %]&area=[% q.param('area') %]&attr=[% attr %]'>[% attr %]</a></td>
274 [% IF area == 'superclasses' %]
275 [% FOREACH super IN meta.superclasses.sort %]
277 <td class='manila'><a href='?class=[% super %]'>[% super %]</a></td>