1 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 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 lineText = trimSyntacticWhitespace(line.getText()); 54 if (lineText.startsWith("}")) 55 return Math.max(modelIndent - indentSize, 0); 56 final String modelText = trimSyntacticWhitespace(model.getText()); 57 if (modelText.endsWith("do") || modelText.endsWith("|")) { 58 return modelIndent + indentSize; 60 } 61 final String modelFirst = getFirstIdentifier(modelText); 62 final String [] 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 final String [] unindent = {"else", "elsif"}; 70 if (Utilities.isOneOf(lineFirst, unindent)) 71 return Math.max(0, modelIndent - indentSize); 72 return modelIndent; 73 } 74 75 private int indentDef() 78 { 79 for (Line model = line.previous(); model != null; model = model.previous()) { 80 String 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 private int indentWhen() 92 { 93 for (Line model = line.previous(); model != null; model = model.previous()) { 94 String 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 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 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 private static String trimSyntacticWhitespace(String s) 127 { 128 RubySyntaxIterator it = new RubySyntaxIterator(null); 129 return new String (it.hideSyntacticWhitespace(s)).trim(); 130 } 131 132 private static String getFirstIdentifier(Line line) 134 { 135 return getFirstIdentifier(trimSyntacticWhitespace(line.getText())); 136 } 137 138 private static String getFirstIdentifier(String 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 |