1 21 22 package org.armedbear.j; 23 24 public final class PythonIndenter 25 { 26 private static final PythonMode mode = PythonMode.getMode(); 27 28 private final Line line; 29 private final Buffer buffer; 30 private final int indentSize; 31 32 public PythonIndenter(Line line, Buffer buffer) 33 { 34 this.line = line; 35 this.buffer = buffer; 36 indentSize = buffer.getIndentSize(); 37 } 38 39 public int getCorrectIndentation() 40 { 41 final Line model = findModel(line); 42 if (model == null) 43 return 0; 44 final int modelIndent = buffer.getIndentation(model); 45 switch (model.getText().trim().charAt(0)) { 48 case '#': 49 case '\'': 50 case '"': 51 return modelIndent; 52 default: 53 break; 54 } 55 final String modelText = trimSyntacticWhitespace(model.getText()); 56 if (modelText.length() == 0) 57 return 0; char c = modelText.charAt(modelText.length()-1); 60 if (c == '{' || c == '(' || c == '[') 61 return modelIndent + indentSize; 62 final String modelFirst = getFirstIdentifier(modelText); 63 if (c == ':') { 64 final String [] indentAfter = { 65 "class", "def", "if", "else", "elif", 66 "for", "while", "try", "except", "finally" 67 }; 68 if (Utilities.isOneOf(modelFirst, indentAfter)) 69 return modelIndent + indentSize; 70 } 71 final String lineText = trimSyntacticWhitespace(line.getText()); 72 final String lineFirst = getFirstIdentifier(lineText); 73 if (lineFirst.equals("class")) 74 return 0; 75 if (lineFirst.equals("def")) 76 return indentDef(); 77 final String [] unindentAfter = {"break", "continue", "return", "pass"}; 79 if (Utilities.isOneOf(modelFirst, unindentAfter)) 80 return Math.max(0, modelIndent - indentSize); 81 final String [] unindent = {"else", "elif", "except", "finally"}; 84 if (Utilities.isOneOf(lineFirst, unindent)) 85 return Math.max(0, modelIndent - indentSize); 86 return modelIndent; 87 } 88 89 private int indentDef() 92 { 93 for (Line model = line.previous(); model != null; model = model.previous()) { 94 String modelFirst = getFirstIdentifier(model); 95 if (modelFirst.equals("def")) 96 return buffer.getIndentation(model); 97 if (modelFirst.equals("class")) 98 return buffer.getIndentation(model) + buffer.getIndentSize(); 99 } 100 return 0; 101 } 102 103 private static Line findModel(Line line) 105 { 106 for (Line model = line.previous(); model != null; model = model.previous()) { 107 if (!model.isBlank()) 108 return model; 109 } 110 return null; 111 } 112 113 private static String trimSyntacticWhitespace(String s) 116 { 117 PythonSyntaxIterator it = new PythonSyntaxIterator(null); 118 return new String (it.hideSyntacticWhitespace(s)).trim(); 119 } 120 121 private static String getFirstIdentifier(Line line) 123 { 124 return getFirstIdentifier(trimSyntacticWhitespace(line.getText())); 125 } 126 127 private static String getFirstIdentifier(String s) 129 { 130 FastStringBuffer sb = new FastStringBuffer(); 131 final int length = s.length(); 132 int i = 0; 133 while (i < length && !mode.isIdentifierStart(s.charAt(i))) 134 ++i; 135 char c; 136 while (i < length && mode.isIdentifierPart(c = s.charAt(i))) { 137 sb.append(c); 138 ++i; 139 } 140 return sb.toString(); 141 } 142 } 143 | Popular Tags |