diff options
author | Paul Pazderski | 2020-01-07 22:35:24 +0000 |
---|---|---|
committer | Paul Pazderski | 2020-01-22 08:19:10 +0000 |
commit | 89a1b717855675c6f4a4d2f55062292dbb7eaf1f (patch) | |
tree | 167710f1aef7224fee3f0361e36395056b384098 | |
parent | 2f6e2318fa4db3f21adcb458245b8ec7398d8d96 (diff) | |
download | eclipse.platform.debug-89a1b717855675c6f4a4d2f55062292dbb7eaf1f.tar.gz eclipse.platform.debug-89a1b717855675c6f4a4d2f55062292dbb7eaf1f.tar.xz eclipse.platform.debug-89a1b717855675c6f4a4d2f55062292dbb7eaf1f.zip |
Bug 553282 - [console] Handle \f and \v in console outputY20200130-0045Y20200127-1055Y20200126-2245I20200201-1800I20200131-1800I20200130-1800I20200129-1800I20200129-0935I20200129-0100I20200128-1805I20200127-1800I20200126-1800I20200126-0250I20200125-1805I20200124-1800I20200123-1800I20200123-0525I20200123-0430I20200122-1805
Change-Id: I8c86ad1116aa12c59ec4cbfbf2662e484c55c1c4
Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de>
3 files changed, 96 insertions, 14 deletions
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTestUtil.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTestUtil.java index 865561f82..831f810b7 100644 --- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTestUtil.java +++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTestUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 Paul Pazderski and others. + * Copyright (c) 2019, 2020 Paul Pazderski and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -109,7 +109,7 @@ public final class IOConsoleTestUtil { */ public IOConsoleTestUtil clear() throws Exception { console.clearConsole(); - waitForScheduledJobs(); + flush(); TestCase.assertEquals("Console is not cleared.", 0, doc.getLength()); return this; } @@ -121,6 +121,7 @@ public final class IOConsoleTestUtil { * @param s content to write in output stream * @return this {@link IOConsoleTestUtil} to chain methods * @see #write(String) + * @see #flush() */ @SuppressWarnings("resource") public IOConsoleTestUtil writeFast(final String s) throws IOException { @@ -164,6 +165,7 @@ public final class IOConsoleTestUtil { * @param out use this output stream instead of default one * @return this {@link IOConsoleTestUtil} to chain methods * @see #write(String, IOConsoleOutputStream) + * @see #flush() */ public IOConsoleTestUtil writeFast(final String s, IOConsoleOutputStream out) throws IOException { out.write(s); @@ -181,7 +183,7 @@ public final class IOConsoleTestUtil { */ public IOConsoleTestUtil write(final String s, IOConsoleOutputStream out) throws Exception { writeFast(s, out); - waitForScheduledJobs(); + flush(); return this; } @@ -543,7 +545,7 @@ public final class IOConsoleTestUtil { verifyContentByOffset(expectedContent, line.getOffset()); TestCase.assertEquals("Line " + l + " has wrong length.", expectedContent.length(), line.getLength()); } catch (BadLocationException e) { - TestCase.fail("Expected line not found in console document. Bad location!"); + TestCase.fail("Expected line " + lineNum + " not found in console document. Bad location!"); } return this; } @@ -562,7 +564,7 @@ public final class IOConsoleTestUtil { final int len = Math.min(doc.getLength() - o, expectedContent.length()); TestCase.assertEquals("Expected string not found in console document.", expectedContent, doc.get(o, len)); } catch (BadLocationException ex) { - TestCase.fail("Expected string not found in console document. Bad location!"); + TestCase.fail("Expected string '" + expectedContent + "' not found in console document. Bad location!"); } return this; } @@ -704,6 +706,18 @@ public final class IOConsoleTestUtil { } /** + * Ensure all pending write operations are fully applied on the console view + * before returning. + * + * @return this {@link IOConsoleTestUtil} to chain methods + */ + public IOConsoleTestUtil flush() { + // overall this method is just a better name for waitForScheduledJobs + waitForScheduledJobs(); + return this; + } + + /** * Close the default output stream if it was used. */ public void closeOutputStream() { @@ -747,7 +761,9 @@ public final class IOConsoleTestUtil { /** * If <code>true</code> the util will work as if console is not in fixed * width mode. E.g. {@link #moveCaretToLineStart()} will move caret to - * document line start not to widget line start. + * document line start not to widget line start or + * {@link #verifyContentByLine(String, int)} would check the line as seen + * without fixed width. * * @see #ignoreFixedConsole */ @@ -756,11 +772,12 @@ public final class IOConsoleTestUtil { } /** - * Enable compatibility mode. If set to <code>true</code> written for + * Enable compatibility mode. If set to <code>true</code> tests written for * console without fixed width should work with any fixed width. Commands * like {@link #moveCaretToLineStart()} are modified to not move to begin of * widget line (maybe wrapped line) but to start it would have without fixed - * width. + * width or {@link #verifyContentByLine(String, int)} would check the line + * as seen without fixed width. * * @see #ignoreFixedConsole */ diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java index bd18bd8ba..5ec28c675 100644 --- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java +++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java @@ -195,7 +195,7 @@ public class IOConsoleTests extends AbstractDebugTest { c.writeAndVerify("Hello World!"); c.getDocument().replace(0, c.getContentLength(), ""); - c.waitForScheduledJobs(); + c.flush(); c.verifyContent("").verifyPartitions(); c.writeAndVerify("New console content."); @@ -558,6 +558,49 @@ public class IOConsoleTests extends AbstractDebugTest { } /** + * Test handling of <code>\f</code>. + */ + public void testFormFeedControlCharacter() throws Exception { + final IOConsoleTestUtil c = getTestUtil("Test \\f"); + c.getConsole().setHandleControlCharacters(true); + try (IOConsoleOutputStream err = c.getConsole().newOutputStream()) { + c.write("\f"); + assertEquals("Wrong number of lines.", 2, c.getDocument().getNumberOfLines()); + c.verifyContentByLine("", 0).verifyContentByLine("", 1); + c.writeAndVerify("output").writeFast("\f").write("more"); + c.verifyContentByLine("output", 1); + c.verifyContentByLine(" more", 2); + c.clear(); + c.writeFast("\f\f").writeFast("\f", err).write("\fend").verifyPartitions(2); + assertEquals("Wrong number of lines.", 5, c.getDocument().getNumberOfLines()); + c.verifyContentByLine("end", 4); + c.clear(); + c.write("1st\f2nd\f3rd").verifyPartitions(); + c.verifyContentByLine("1st", 0); + c.verifyContentByLine(" 2nd", 1); + c.verifyContentByLine(" 3rd", 2); + + // test form feed mixed with backspaces + c.clear(); + c.write("first\f\b\bsecond"); + c.verifyContentByLine("first", 0); + c.verifyContentByLine(" second", 1); + c.clear(); + c.writeFast("><\b").writeFast("\f", err).write("abc").verifyPartitions(2); + c.verifyContentByLine("><", 0); + c.verifyContentByLine(" abc", 1); + + // test with input partitions. At the moment input is + // considered for the indentation + c.clear(); + c.writeAndVerify("foo").insertTyping("input").writeFast("bar").write("\f.", err).verifyPartitions(2); + c.verifyContentByLine("fooinputbar", 0); + c.verifyContentByLine(" .", 1); + } + closeConsole(c); + } + + /** * Test larger number of partitions with pseudo random console content. */ public void testManyPartitions() throws IOException { diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java index dd7859b6c..d6a73d3d2 100644 --- a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java +++ b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java @@ -17,6 +17,7 @@ * Bug 550621: Implementation of IConsoleDocumentPartitionerExtension * Bug 76936: Support interpretation of \b and \r in console output * Bug 365770: Race condition in console clearing + * Bug 553282: Support interpretation of \f and \v in console output *******************************************************************************/ package org.eclipse.ui.internal.console; @@ -97,12 +98,12 @@ public class IOConsolePartitioner * Pattern used to find supported ASCII control characters <b>except</b> * carriage return. */ - private static final String CONTROL_CHARACTERS_PATTERN_STR = "(?:\b+)"; //$NON-NLS-1$ + private static final String CONTROL_CHARACTERS_PATTERN_STR = "(?:\b+|\u000b+|\f+)"; //$NON-NLS-1$ /** * Pattern used to find supported ASCII control characters <b>including</b> * carriage return. */ - private static final String CONTROL_CHARACTERS_WITH_CR_PATTERN_STR = "(?:\b+|\r+(?!\n))"; //$NON-NLS-1$ + private static final String CONTROL_CHARACTERS_WITH_CR_PATTERN_STR = "(?:\b+|\u000b+|\f+|\r+(?!\n))"; //$NON-NLS-1$ /** The connected {@link IDocument} this partitioner manages. */ private IDocument document; @@ -879,11 +880,11 @@ public class IOConsolePartitioner final String controlCharacterMatch = controlCharacterMatcher.group(); final char controlCharacter = controlCharacterMatch.charAt(0); + final int outputLineStartOffset = findOutputLineStartOffset(outputOffset); switch (controlCharacter) { case '\b': // move virtual output cursor one step back for each \b // but stop at current line start and skip any input partitions - final int outputLineStartOffset = findOutputLineStartOffset(outputOffset); int backStepCount = controlCharacterMatch.length(); if (partitions.size() == 0) { outputOffset = 0; @@ -914,13 +915,34 @@ public class IOConsolePartitioner atOutputPartition = getPartitionByIndex(atOutputPartitionIndex); } outputOffset = Math.max(outputOffset, outputLineStartOffset); + nextWriteOffset = outputOffset; break; case '\r': // move virtual output cursor to start of output line - outputOffset = findOutputLineStartOffset(outputOffset); + outputOffset = outputLineStartOffset; atOutputPartitionIndex = -1; atOutputPartition = null; + nextWriteOffset = outputOffset; + break; + + case '\f': + case '\u000b': // \v + // Vertical tab does not override existing content. It will introduce a newline + // (at the end of current line even if output offset is inside the line) and + // indent the new line dependent on current output offset. + int indention = outputOffset - outputLineStartOffset; + final int vtabCount = controlCharacterMatch.length(); + final StringBuilder vtab = new StringBuilder(indention + vtabCount); + for (int i = 0; i < vtabCount; i++) { + vtab.append(System.lineSeparator()); + } + for (int i = 0; i < indention; i++) { + vtab.append(' '); + } + outputOffset = document.getLength(); + nextWriteOffset = outputOffset; + partititonContent(pending.stream, vtab, 0, vtab.length()); break; default: @@ -929,12 +951,12 @@ public class IOConsolePartitioner + Integer.toHexString(controlCharacter)); break; } - nextWriteOffset = outputOffset; textOffset = controlCharacterMatcher.end(); } } } applyOutputToDocument(content.toString(), nextWriteOffset, replaceLength); + content = null; } /** |