KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ruby > RDocFormatter


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.ruby;
20
21 import org.netbeans.modules.ruby.lexer.RubyCommentTokenId;
22 import org.netbeans.api.lexer.Token;
23 import org.netbeans.api.lexer.TokenHierarchy;
24 import org.netbeans.api.lexer.TokenSequence;
25
26
27 /**
28  * Digest rdoc-formatter strings and format them as html,
29  * A bit hacky at the moment, but it tries to understand most
30  * of the conventions described here:
31  * http://rdoc.sourceforge.net/doc/index.html
32  * and produce reasonably similar HTML. It also relies on
33  * the RubyCommentLexer.
34  *
35  * @todo Handle definition-style labelled blocks (I only do tabular ones at this point)
36  * where you have double brackets: [[foo]]
37  *
38  * @author Tor Norbye
39  */

40 class RDocFormatter {
41     private boolean inVerbatim;
42     private boolean inBulletedList;
43     private boolean inLabelledList;
44     private boolean inNumberedList;
45
46     /** State during rdoc generation: in suppressed comments (#--) section */
47     private boolean noComment;
48     private StringBuilder JavaDoc sb = new StringBuilder JavaDoc(500);
49
50     /** Creates a new instance of RDocFormatter */
51     public RDocFormatter() {
52     }
53
54     public void appendLine(String JavaDoc text) {
55         if (text.equals("#--")) { // NOI18N
56
noComment = true;
57
58             return;
59         } else if (text.equals("#++")) { // NOI18N
60
noComment = false;
61
62             return;
63         }
64
65         if (noComment) {
66             return;
67         }
68
69         if (text.startsWith("# ")) {
70             text = text.substring(2);
71         } else if (text.equals("#")) { // empty comment line
72
text = "";
73         }
74
75         process(text);
76     }
77
78     private void process(String JavaDoc text) {
79         // Use the lexer! The following is naive since it will
80
// do something about URLs, multiplication (*), etc.
81
if (text.length() == 0) {
82             finishSection();
83
84             return;
85         }
86
87         if (text.startsWith("* ") || text.startsWith("- ")) {
88             if (!inBulletedList) {
89                 sb.append("<ul>\n"); // NOI18N
90
inBulletedList = true;
91             }
92
93             sb.append("<li>"); // NOI18N
94
appendTokenized(text.substring(text.indexOf(' ') + 1));
95
96             return;
97         } else if (text.matches("^[0-9]+\\. .*")) {
98             if (!inNumberedList) {
99                 sb.append("<ol>\n"); // NOI18N
100
inNumberedList = true;
101             }
102
103             sb.append("<li>"); // NOI18N
104
appendTokenized(text.substring(text.indexOf(' ') + 1));
105
106             return;
107         } else if (text.matches("^\\[[A-Za-z+_*]+\\] .+")) { // NOI18N
108
// Labelled list: [+foo+] whatever
109

110             if (!inLabelledList) {
111                 sb.append("<table>\n"); // NOI18N
112
inLabelledList = true;
113             } else {
114                 sb.append("</td></tr>\n"); // NOI18N
115
}
116
117             sb.append("<tr><td valign=\"top\">"); // NOI18N
118

119             int index = text.indexOf("] ");
120             appendTokenized(text.substring(1, index)); // label between []'s
121
sb.append("</td><td>");
122             appendTokenized(text.substring(index + 2));
123
124             return;
125         } else if (text.matches("^[A-Za-z+_*]+:: .*")) { // NOI18N
126
// Labelled list: foo::
127

128             if (!inLabelledList) {
129                 sb.append("<table>\n"); // NOI18N
130
inLabelledList = true;
131             } else {
132                 sb.append("</td></tr>\n"); // NOI18N
133
}
134
135             sb.append("<tr><td valign=\"top\">"); // NOI18N
136

137             int index = text.indexOf(":: ");
138             appendTokenized(text.substring(0, index)); // label
139
sb.append("</td><td>");
140             appendTokenized(text.substring(index + 3));
141
142             return;
143         } else if (!inBulletedList && !inNumberedList && !inLabelledList && text.startsWith(" ")) { // Indented text in list is in same paragraph
144

145             if (!inVerbatim) {
146                 sb.append("<pre>\n"); // NOI18N
147
inVerbatim = true;
148             }
149
150             appendTokenized(text);
151
152             return;
153         } else if (text.startsWith("=")) { // NOI18N
154
// Generate a heading
155
// Count ='s
156

157             int i = 0;
158
159             for (; i < text.length(); i++) {
160                 if (text.charAt(i) != '=') {
161                     break;
162                 }
163             }
164
165             if (i <= 6) {
166                 sb.append("<h");
167                 sb.append(Integer.toString(i));
168                 sb.append(">");
169                 sb.append(text.substring(i));
170                 sb.append("</h");
171                 sb.append(Integer.toString(i));
172                 sb.append(">\n");
173
174                 return;
175             }
176
177             // Normal line with lots of ='s
178
appendTokenized(text);
179
180             return;
181         } else if (text.startsWith("#---")) { // NOI18N
182
// Generate a separator
183
// See if the line contains only -'s
184

185             int i = 1;
186             int n = text.length();
187
188             for (; i < n; i++) {
189                 if (text.charAt(i) != '-') {
190                     break;
191                 }
192             }
193
194             if (i == n) {
195                 sb.append("<hr>\n"); // NOI18N
196

197                 return;
198             }
199
200             appendTokenized(text);
201
202             return;
203         } else {
204             if (text.startsWith("####")) {
205                 // Generate a separator
206
// See if the line contains only #'s
207
int i = 1;
208                 int n = text.length();
209
210                 for (; i < n; i++) {
211                     if (text.charAt(i) != '#') {
212                         break;
213                     }
214                 }
215                 if (i == n) {
216                     sb.append("<hr>\n");
217                     return;
218                 }
219             } else if (inVerbatim) {
220                 finishSection();
221             }
222             appendTokenized(text);
223             return;
224         }
225     }
226
227     private void appendTokenized(String JavaDoc text) {
228         TokenHierarchy hi = TokenHierarchy.create(text, RubyCommentTokenId.language());
229
230         TokenSequence ts = hi.tokenSequence();
231
232         // If necessary move ts to the requested offset
233
int offset = 0;
234         ts.move(offset);
235         if (ts.moveNext()) {
236             do {
237                 Token t = ts.token();
238
239                 if ((t.id() == RubyCommentTokenId.COMMENT_TEXT) ||
240                         (t.id() == RubyCommentTokenId.COMMENT_TODO)) {
241                     sb.append(t.text());
242                 } else if (t.id() == RubyCommentTokenId.COMMENT_HTMLTAG) {
243                     String JavaDoc s = t.text().toString();
244                     char c = s.charAt(0);
245
246                     if (c == '+') {
247                         sb.append("<tt>");
248                         sb.append(s.substring(1, s.length() - 1));
249                         sb.append("</tt>");
250                     } else {
251                         sb.append(s);
252                     }
253                 } else if (t.id() == RubyCommentTokenId.COMMENT_LINK) {
254                     String JavaDoc s = t.text().toString();
255                     sb.append("<a HREF=\"");
256                     sb.append(s);
257                     sb.append("\">");
258
259                     if (s.startsWith("#")) {
260                         s = s.substring(1); // Chop off leading #
261
// Method reference
262
// TODO - generate special URL for local methods here?
263
}
264
265                     sb.append(s);
266                     sb.append("</a>");
267                 } else if (t.id() == RubyCommentTokenId.COMMENT_ITALIC) {
268                     sb.append("<i>");
269                     String JavaDoc s = t.text().toString();
270                     char c = s.charAt(0);
271
272                     if (c == '_') {
273                         sb.append(s.substring(1, s.length() - 1));
274                     } else {
275                         sb.append(t.text());
276                     }
277                     sb.append("</i>");
278                 } else if (t.id() == RubyCommentTokenId.COMMENT_BOLD) {
279                     sb.append("<b>");
280                     String JavaDoc s = t.text().toString();
281                     char c = s.charAt(0);
282
283                     if (c == '*') {
284                         sb.append(s.substring(1, s.length() - 1));
285                     } else {
286                         sb.append(t.text());
287                     }
288                     sb.append("</b>");
289                 } else if (t.id() == RubyCommentTokenId.COMMENT_RDOC) {
290                     // Do nothing - swallow these so they don't show up in the html
291
}
292             } while (ts.moveNext());
293         }
294
295         if (inVerbatim) {
296             sb.append("<br>");
297         } else {
298             sb.append(" "); // Ensure adjacent lines are separated by space.
299
}
300     }
301
302     private void finishSection() {
303         if (inVerbatim) {
304             sb.append("</pre>\n");
305             inVerbatim = false;
306         }
307
308         if (inBulletedList) {
309             sb.append("</ul>\n");
310             inBulletedList = false;
311         }
312
313         if (inNumberedList) {
314             sb.append("</ol>\n");
315             inBulletedList = false;
316         }
317
318         if (inLabelledList) {
319             sb.append("</td></tr>\n</table>");
320             inLabelledList = false;
321         }
322     }
323
324     public String JavaDoc toHtml() {
325         finishSection();
326
327         return sb.toString();
328     }
329 }
330
Popular Tags