PyConsole: correctly indent after execution of incomplete multi-line string.

This commit is contained in:
Dmitry Trofimov
2013-11-19 17:24:22 +01:00
parent d7a0fe63e4
commit c77f4b7e3e
3 changed files with 52 additions and 22 deletions
@@ -44,6 +44,7 @@ public class StringUtil extends StringUtilRt {
@NonNls private static final String VOWELS = "aeiouy";
@NonNls private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *");
@NonNls private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *");
@NonNls private static final Pattern EOL_SPLIT_DONT_TRIM_PATTERN = Pattern.compile("(\r|\n|\r\n)+");
public static final NotNullFunction<String, String> QUOTER = new NotNullFunction<String, String>() {
@Override
@@ -307,9 +308,14 @@ public class StringUtil extends StringUtilRt {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case '\n': buffer.append("\\n"); break;
case '\r': buffer.append("\\r"); break;
default: buffer.append(c);
case '\n':
buffer.append("\\n");
break;
case '\r':
buffer.append("\\r");
break;
default:
buffer.append(c);
}
}
return buffer.toString();
@@ -814,13 +820,17 @@ public class StringUtil extends StringUtilRt {
return true;
}
/** @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 14). */
/**
* @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 14).
*/
@SuppressWarnings("UnusedDeclaration")
public static boolean startsWithConcatenationOf(@NotNull String string, @NotNull String firstPrefix, @NotNull String secondPrefix) {
return startsWithConcatenation(string, firstPrefix, secondPrefix);
}
/** @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 14). */
/**
* @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 14).
*/
@SuppressWarnings("UnusedDeclaration")
public static boolean startsWithConcatenationOf(@NotNull String string,
@NotNull String firstPrefix,
@@ -947,11 +957,11 @@ public class StringUtil extends StringUtilRt {
@Contract("null -> true")
public static boolean isEmptyOrSpaces(@Nullable final String s) {
if(s == null || s.isEmpty()) {
if (s == null || s.isEmpty()) {
return true;
}
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) > ' ') {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > ' ') {
return false;
}
}
@@ -992,7 +1002,7 @@ public class StringUtil extends StringUtilRt {
@NotNull
public static String repeat(@NotNull String s, int count) {
assert count >=0 : count;
assert count >= 0 : count;
StringBuilder sb = new StringBuilder(s.length() * count);
for (int i = 0; i < count; i++) {
sb.append(s);
@@ -1214,7 +1224,9 @@ public class StringUtil extends StringUtilRt {
}
@NotNull
public static <T> String join(@NotNull Collection<? extends T> items, @NotNull Function<? super T, String> f, @NotNull @NonNls String separator) {
public static <T> String join(@NotNull Collection<? extends T> items,
@NotNull Function<? super T, String> f,
@NotNull @NonNls String separator) {
if (items.isEmpty()) return "";
return join((Iterable<? extends T>)items, f, separator);
}
@@ -1231,7 +1243,9 @@ public class StringUtil extends StringUtilRt {
}
@NotNull
public static <T> String join(@NotNull Iterable<? extends T> items, @NotNull Function<? super T, String> f, @NotNull @NonNls String separator) {
public static <T> String join(@NotNull Iterable<? extends T> items,
@NotNull Function<? super T, String> f,
@NotNull @NonNls String separator) {
final StringBuilder result = new StringBuilder();
for (T item : items) {
String string = f.fun(item);
@@ -1587,7 +1601,7 @@ public class StringUtil extends StringUtilRt {
* @param end end offset to use within the given char sequence (exclusive)
* @param c target symbol to check
* @return <code>true</code> if given symbol is contained at the target range of the given char sequence;
* <code>false</code> otherwise
* <code>false</code> otherwise
*/
public static boolean contains(@NotNull CharSequence s, int start, int end, char c) {
return indexOf(s, c, start, end) >= 0;
@@ -1640,6 +1654,7 @@ public class StringUtil extends StringUtilRt {
public static int indexOfAny(@NotNull final String s, @NotNull final String chars) {
return indexOfAny(s, chars, 0, s.length());
}
public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars) {
return indexOfAny(s, chars, 0, s.length());
}
@@ -1647,6 +1662,7 @@ public class StringUtil extends StringUtilRt {
public static int indexOfAny(@NotNull final String s, @NotNull final String chars, final int start, final int end) {
return indexOfAny((CharSequence)s, chars, start, end);
}
public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars, final int start, final int end) {
for (int i = start; i < end; i++) {
if (containsChar(chars, s.charAt(i))) return i;
@@ -1669,7 +1685,7 @@ public class StringUtil extends StringUtilRt {
* @param start start offset of the target text (inclusive)
* @param end end offset of the target text (exclusive)
* @return index of the last occurrence of the given symbol at the target sub-sequence of the given text if any;
* <code>-1</code> otherwise
* <code>-1</code> otherwise
*/
public static int lastIndexOf(@NotNull CharSequence s, char c, int start, int end) {
for (int i = end - 1; i >= start; i--) {
@@ -2191,6 +2207,11 @@ public class StringUtil extends StringUtilRt {
return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string);
}
@NotNull
public static String[] splitByLinesDontTrim(@NotNull String string) {
return EOL_SPLIT_DONT_TRIM_PATTERN.split(string);
}
@NotNull
public static List<Pair<String, Integer>> getWordsWithOffset(@NotNull String s) {
List<Pair<String, Integer>> res = ContainerUtil.newArrayList();
@@ -2351,7 +2372,7 @@ public class StringUtil extends StringUtilRt {
return false;
}
for (int i = 0; i < s1.length(); i++) {
if (!charsMatch(s1.charAt(i),s2.charAt(i), true)) {
if (!charsMatch(s1.charAt(i), s2.charAt(i), true)) {
return false;
}
}
@@ -2382,7 +2403,7 @@ public class StringUtil extends StringUtilRt {
}
public static boolean charsMatch(char c1, char c2, boolean ignoreCase) {
return compare(c1,c2,ignoreCase) == 0;
return compare(c1, c2, ignoreCase) == 0;
}
@NotNull
@@ -2416,7 +2437,10 @@ public class StringUtil extends StringUtilRt {
}
@NotNull
public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength, boolean useEllipsisSymbol) {
public static String shortenTextWithEllipsis(@NotNull final String text,
final int maxLength,
final int suffixLength,
boolean useEllipsisSymbol) {
final int textLength = text.length();
if (textLength > maxLength) {
String symbol = useEllipsisSymbol ? "\u2026" : "...";
@@ -2442,6 +2466,7 @@ public class StringUtil extends StringUtilRt {
public static boolean charsEqual(char a, char b, boolean ignoreCase) {
return ignoreCase ? charsEqualIgnoreCase(a, b) : a == b;
}
public static boolean charsEqualIgnoreCase(char a, char b) {
return StringUtilRt.charsEqualIgnoreCase(a, b);
}
@@ -45,7 +45,6 @@ import org.jetbrains.annotations.Nullable;
* @author traff
*/
public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandler implements ConsoleCommunicationListener {
private final LanguageConsoleView myConsoleView;
private String myInMultilineStringState = null;
@@ -97,7 +96,7 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
final LanguageConsoleImpl console = myConsoleView.getConsole();
final Editor currentEditor = console.getConsoleEditor();
sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false), null, console, currentEditor);
sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false), console, currentEditor);
}
private void processOneLine(String line) {
@@ -187,11 +186,10 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
}
sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), true), line, console, currentEditor);
sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), true), console, currentEditor);
}
private void sendLineToConsole(@NotNull final ConsoleCommunication.ConsoleCodeFragment code,
@Nullable final String line,
@NotNull final LanguageConsoleImpl console,
@NotNull final Editor currentEditor) {
if (myConsoleCommunication != null) {
@@ -212,7 +210,7 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
if (myCurrentIndentSize == 0) {
// compute current indentation
setCurrentIndentSize(
(line != null ? IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false) : 0) + getPythonIndent());
IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, lastLine(code.getText()), false) + getPythonIndent());
// In this case we can insert indent automatically
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -240,6 +238,11 @@ public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandle
}
}
private static String lastLine(@NotNull String text) {
String[] lines = StringUtil.splitByLinesDontTrim(text);
return lines[lines.length - 1];
}
private void ordinaryPrompt(LanguageConsoleImpl console, Editor currentEditor) {
if (!myConsoleCommunication.isExecuting()) {
if (!PyConsoleUtil.ORDINARY_PROMPT.equals(console.getPrompt())) {
@@ -152,7 +152,9 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
private void doExecute(String code) {
executeInConsole(PyConsoleIndentUtil.normalize(code, myExecuteActionHandler.getCurrentIndentSize()));
String codeFragment = PyConsoleIndentUtil.normalize(code, myExecuteActionHandler.getCurrentIndentSize());
codeFragment += "\n";
executeInConsole(codeFragment);
}
public void executeInConsole(final String code) {