KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > RubyIndenter


1 /*
2  * RubyIndenter.java
3  *
4  * Copyright (C) 2002 Jens Luedicke <jens@irs-net.com>
5  * based on PythonIndenter.java
6  * $Id: RubyIndenter.java,v 1.1.1.1 2002/09/24 16:08:22 piso Exp $
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.armedbear.j;
24
25 public final class RubyIndenter
26 {
27     private static final RubyMode mode = RubyMode.getMode();
28
29     private final Line line;
30     private final Buffer buffer;
31     private final int indentSize;
32
33     public RubyIndenter(Line line, Buffer buffer)
34     {
35         this.line = line;
36         this.buffer = buffer;
37         indentSize = buffer.getIndentSize();
38     }
39
40     public int getCorrectIndentation()
41     {
42         final String JavaDoc lineFirst = getFirstIdentifier(line);
43         if (lineFirst.equals("def"))
44             return indentDef();
45         if (lineFirst.equals("when"))
46             return indentWhen();
47         if (lineFirst.equals("end"))
48             return indentEnd();
49         final Line model = findModel(line);
50         if (model == null)
51             return 0;
52         final int modelIndent = buffer.getIndentation(model);
53         final String JavaDoc lineText = trimSyntacticWhitespace(line.getText());
54         if (lineText.startsWith("}"))
55             return Math.max(modelIndent - indentSize, 0);
56         final String JavaDoc modelText = trimSyntacticWhitespace(model.getText());
57         if (modelText.endsWith("do") || modelText.endsWith("|")) {
58             // e.g. "do |foo|"
59
return modelIndent + indentSize;
60         }
61         final String JavaDoc modelFirst = getFirstIdentifier(modelText);
62         final String JavaDoc[] indentAfter = {
63             "begin", "class", "def", "if", "else", "elsif",
64             "for", "module", "unless", "when", "while"
65         };
66         if (Utilities.isOneOf(modelFirst, indentAfter))
67             return modelIndent + indentSize;
68         // Unindent if the current line starts with "else" or "elsif".
69
final String JavaDoc[] unindent = {"else", "elsif"};
70         if (Utilities.isOneOf(lineFirst, unindent))
71             return Math.max(0, modelIndent - indentSize);
72         return modelIndent;
73     }
74
75     // Scan backwards for line starting with "def" or "class" and indent
76
// accordingly.
77
private int indentDef()
78     {
79         for (Line model = line.previous(); model != null; model = model.previous()) {
80             String JavaDoc modelFirst = getFirstIdentifier(model);
81             if (modelFirst.equals("def"))
82                 return buffer.getIndentation(model);
83             if (modelFirst.equals("class"))
84                 return buffer.getIndentation(model) + buffer.getIndentSize();
85         }
86         return 0;
87     }
88
89     // Scan backwards for line starting with "when" or "case" and indent
90
// accordingly. This doesn't work correctly with nested case statements!
91
private int indentWhen()
92     {
93         for (Line model = line.previous(); model != null; model = model.previous()) {
94             String JavaDoc modelFirst = getFirstIdentifier(model);
95             if (modelFirst.equals("when") || modelFirst.equals("case"))
96                 return buffer.getIndentation(model);
97         }
98         return 0;
99     }
100
101     private int indentEnd()
102     {
103         for (Line model = line.previous(); model != null; model = model.previous()) {
104             if (model.isBlank() || model.trim().startsWith("#"))
105                 continue;
106             String JavaDoc modelFirst = getFirstIdentifier(model);
107             if (modelFirst.equals("def"))
108                 return buffer.getIndentation(model);
109             return Math.max(buffer.getIndentation(model) - indentSize, 0);
110         }
111         return 0;
112     }
113
114     // Return last non-blank line before this one.
115
private static Line findModel(Line line)
116     {
117         for (Line model = line.previous(); model != null; model = model.previous()) {
118             if (!model.isBlank() && !model.trim().startsWith("#"))
119                 return model;
120         }
121         return null;
122     }
123
124     // Replace syntactic whitespace (quotes and comments) with actual space
125
// characters and return trimmed string.
126
private static String JavaDoc trimSyntacticWhitespace(String JavaDoc s)
127     {
128         RubySyntaxIterator it = new RubySyntaxIterator(null);
129         return new String JavaDoc(it.hideSyntacticWhitespace(s)).trim();
130     }
131
132     // Never returns null.
133
private static String JavaDoc getFirstIdentifier(Line line)
134     {
135         return getFirstIdentifier(trimSyntacticWhitespace(line.getText()));
136     }
137
138     // Never returns null.
139
private static String JavaDoc getFirstIdentifier(String JavaDoc s)
140     {
141         FastStringBuffer sb = new FastStringBuffer();
142         final int length = s.length();
143         int i = 0;
144         while (i < length && Character.isWhitespace(s.charAt(i)))
145             ++i;
146         char c;
147         while (i < length && !Character.isWhitespace(c = s.charAt(i))) {
148             sb.append(c);
149             ++i;
150         }
151         return sb.toString();
152     }
153 }
154
Popular Tags