| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.jetbrains.python.console; |
| |
| import com.google.common.base.Strings; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Lists; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.util.ArrayUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| /** |
| * @author traff |
| */ |
| public class PyConsoleIndentUtil { |
| private static final int TAB_INDENT = 4; |
| |
| private static final Map<String, String> pythonBrackets = ImmutableMap.of( |
| "(", ")", |
| "[", "]", |
| "{", "}" |
| ); |
| |
| private PyConsoleIndentUtil() { |
| } |
| |
| public static String normalize(@NotNull String codeFragment) { |
| return normalize(codeFragment, 0); |
| } |
| |
| public static String normalize(@NotNull String codeFragment, int addIndent) { |
| Scanner s = new Scanner(codeFragment); |
| |
| List<String> lines = Lists.newArrayList(); |
| List<Integer> indents = Lists.newArrayList(); |
| while (s.hasNextLine()) { |
| String line = s.nextLine(); |
| int indent = 0; |
| for (char c : line.toCharArray()) { |
| if (c == ' ') { |
| indent++; |
| } |
| else if (c == '\t') { |
| indent += TAB_INDENT; |
| } |
| else { |
| break; |
| } |
| } |
| if (!StringUtil.isEmpty(line)) { |
| lines.add(line.trim()); |
| indents.add(indent); |
| } |
| } |
| |
| int[] indentArray = ArrayUtil.toIntArray(indents); |
| |
| shiftLeftAll(indentArray, lines); |
| |
| for (int i = 0; i < indentArray.length; i++) { |
| indentArray[i] += addIndent; |
| } |
| |
| return padOutput(lines, indentArray); |
| } |
| |
| private static void shiftLeftAll(int[] indentArray, List<String> lines) { |
| if (indentArray.length == 0) { |
| return; |
| } |
| |
| int minpos = arrayMinPosition(indentArray, indentArray.length); |
| if (minpos == 0) { |
| int minIndent = indentArray[minpos]; |
| shiftTailLeftOnLevel(indentArray, minIndent); |
| return; |
| } |
| |
| int prevMinPosition = indentArray.length; |
| while (minpos != 0) { |
| shiftTailLeftOnLevel(indentArray, minpos, prevMinPosition, indentArray[minpos]); |
| prevMinPosition = minpos; |
| minpos = arrayMinPosition(indentArray, minpos); |
| } |
| |
| int minIndent = indentArray[minpos]; |
| for (int i = 0; indentArray[i] != 0; i++) { |
| indentArray[i] -= minIndent; |
| } |
| } |
| |
| private static void shiftTailLeftOnLevel(int[] indentArray, int level) { |
| shiftTailLeftOnLevel(indentArray, 0, indentArray.length, level); |
| } |
| |
| private static void shiftTailLeftOnLevel(int[] indentArray, int upper, int bottom, int level) { |
| for (int i = upper; i < bottom; i++) { |
| if (indentArray[i] < level) { |
| throw new IllegalStateException("Current indentation is less then subtracted level."); |
| } |
| indentArray[i] -= level; |
| } |
| } |
| |
| private static int arrayMinPosition(int[] indentArray, int border) { |
| if (border < 1) { |
| return -1; |
| } |
| |
| int minPosition = 0; |
| for (int i = 0; i < border; i++) { |
| if (indentArray[minPosition] > indentArray[i]) { |
| minPosition = i; |
| } |
| } |
| return minPosition; |
| } |
| |
| private static String padOutput(List<String> lines, int[] indentArray) { |
| int i = 0; |
| StringBuilder result = new StringBuilder(); |
| for (String line : lines) { |
| if (!StringUtil.isEmpty(line)) { |
| line = Strings.padStart(line, indentArray[i] + line.length(), ' '); |
| } |
| i++; |
| result.append(line); |
| if (i < lines.size()) { |
| result.append("\n"); |
| } |
| } |
| |
| return result.toString(); |
| } |
| |
| public static boolean shouldIndent(@NotNull String line) { |
| line = stripComments(line); |
| return line.endsWith(":"); |
| } |
| |
| private static String stripComments(String line) { |
| if (line.contains("#")) { |
| line = line.substring(0, line.indexOf("#")); //strip comments |
| line = line.trim(); |
| } |
| return line; |
| } |
| } |