@Override public void customizeDocumentCommand(IDocument d, DocumentCommand c) { try { if ("-".equals(c.text) && c.offset >= 3 && d.get(c.offset - 3, 3).equals("<!-")) { c.text = "- -->"; c.shiftsCaret = false; c.caretOffset = c.offset + 2; c.doit = false; return; } if ("[".equals(c.text) && c.offset >= 2 && d.get(c.offset - 2, 2).equals("<!")) { c.text = "[CDATA[]]>"; c.shiftsCaret = false; c.caretOffset = c.offset + 7; c.doit = false; return; } if ("l".equals(c.text) && c.offset >= 4 && d.get(c.offset - 4, 4).equals("<?xm")) { c.text = "l version = \"1.0\" encoding = \"" + charset + "\"?>"; return; } } catch (BadLocationException e) { HTMLPlugin.logException(e); } super.customizeDocumentCommand(d, c); }
@Override public void customizeDocumentCommand(IDocument d, DocumentCommand c) { try { // if("%".equals(c.text) && c.offset > 0){ // if(d.getChar(c.offset - 1) == '<'){ // c.text = "% %>"; // c.shiftsCaret = false; // c.caretOffset = c.offset + 1; // c.doit = false; // return; // } // } if ("{".equals(c.text) && c.offset > 0) { if (d.getChar(c.offset - 1) == '$') { c.text = "{}"; c.shiftsCaret = false; c.caretOffset = c.offset + 1; c.doit = false; return; } } if ("-".equals(c.text) && c.offset >= 3 && d.get(c.offset - 3, 3).equals("<%-")) { c.text = "- --%>"; c.shiftsCaret = false; c.caretOffset = c.offset + 2; c.doit = false; return; } } catch (BadLocationException e) { HTMLPlugin.logException(e); } super.customizeDocumentCommand(d, c); }
private void fixIndentOfCurrentLine() throws BadLocationException { int start = getStartOfCurrentLine(); int end = getEndOfCurrentLine(); int endOfWs = firstEndOfWhitespace(start, end); // we want this to happen in three cases: // 1. the user types a tab in the whitespace // at the start of the line // 2. the user types { or ( at the start of // the line // 3. Correct Indentation is calling us // test for Correct Indentation action boolean correctingIndentation = command.offset == start && !command.shiftsCaret; boolean opening = command.text.equals("{") || command.text.equals("("); if (command.offset < endOfWs || // we want strictly < since we don't want to prevent the caret advancing when a space is // typed command.offset == endOfWs && endOfWs == end && opening || // this can cause the caret to jump *backwards* when a { or ( is typed! correctingIndentation) { int endOfPrev = getEndOfPreviousLine(); int startOfPrev = getStartOfPreviousLine(); char startOfCurrentLineChar = opening ? command.text.charAt(0) : // the typed character is now the first character in the line getNextNonHiddenCharacterInLine(start); char endOfLastLineChar = getPreviousNonHiddenCharacterInLine(endOfPrev); StringBuilder buf = new StringBuilder(); appendIndent( start, end, startOfPrev, endOfPrev, startOfCurrentLineChar, endOfLastLineChar, false, buf); int len = endOfWs - start; String text = buf.toString(); if (text.length() != len || !document.get(start, len).equals(text)) { if (opening) { text += command.text; } command.text = text; command.offset = start; command.length = len; } else if (!opening) { command.caretOffset = start + len; command.shiftsCaret = false; command.text = null; } } }
public void customizeDocumentCommand() { // Note that Correct Indentation sends us a tab // character at the start of each line of selected // text. This is amazingly sucky because it's very // difficult to distinguish Correct Indentation from // an actual typed tab. // Note also that typed tabs are replaced with spaces // before this method is called if the spacesfortabs // setting is enabled. if (command.text != null) { // command.length>0 means we are replacing or deleting text if (command.length == 0) { if (command.text.isEmpty()) { // workaround for a really annoying bug where we // get sent "" instead of "\t" or " " by IMP // reconstruct what we would have been sent // without the bug if (getIndentWithSpaces()) { int overhang = getPrefix().length() % getIndentSpaces(); command.text = getDefaultIndent().substring(overhang); } else { command.text = "\t"; } smartIndentOnKeypress(); } else if (isLineEnding(command.text)) { // a typed newline (might have length 1 or 2, // depending on the platform) smartIndentAfterNewline(); } else if (command.text.length() == 1 || // when spacesfortabs is enabled, we get // sent spaces instead of a tab - the right // number of spaces to take us to the next // tab stop getIndentWithSpaces() && isIndent(getPrefix())) { // anything that might represent a single // keypress or a Correct Indentation smartIndentOnKeypress(); } } if (command.text != null && command.text.length() == 1 && command.length == 0) { closeOpening(); } } }
private void smartIndentAfterClosingBracket(IDocument d, DocumentCommand c) { if (c.offset == -1 || d.getLength() == 0) return; try { int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset); int line = d.getLineOfOffset(p); int start = d.getLineOffset(line); int whiteend = findEndOfWhiteSpace(d, start, c.offset); JavaHeuristicScanner scanner = new JavaHeuristicScanner(d); JavaIndenter indenter = new JavaIndenter(d, scanner, fProject); // shift only when line does not contain any text up to the closing bracket if (whiteend == c.offset) { // evaluate the line with the opening bracket that matches out closing bracket int reference = indenter.findReferencePosition(c.offset, false, true, false, false); int indLine = d.getLineOfOffset(reference); if (indLine != -1 && indLine != line) { // take the indent of the found line StringBuffer replaceText = new StringBuffer(getIndentOfLine(d, indLine)); // add the rest of the current line including the just added close bracket replaceText.append(d.get(whiteend, c.offset - whiteend)); replaceText.append(c.text); // modify document command c.length += c.offset - start; c.offset = start; c.text = replaceText.toString(); } } } catch (BadLocationException e) { JavaPlugin.log(e); } }
protected void copyIndentation(final IDocument d, final DocumentCommand c) { // CODE KOPIERT AUS SUPER-KLASSE DA DORT PRIVATE // == DefaultIndentLineAutoEditStrategy.autoIndentAfterNewLine(IDocument d, DocumentCommand c) if (c.offset == -1 || d.getLength() == 0) return; try { // find start of line int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset); IRegion info = d.getLineInformationOfOffset(p); int start = info.getOffset(); // find white spaces int end = findEndOfWhiteSpace(d, start, c.offset); StringBuffer buf = new StringBuffer(c.text); if (end > start) { // append to input buf.append(d.get(start, end - start)); } c.text = buf.toString(); } catch (BadLocationException excp) { // stop work } }
@Test public void testBacketHandling() { IDocument document = new Document(); document.set(input.replace(CURSOR, "")); DocumentCommand command = new DocumentCommandStub(); command.text = textToInsert; // insert text at cursor position command.offset = input.indexOf(CURSOR); // position cursor at correct position in input text command.caretOffset = input.indexOf(CURSOR); command.shiftsCaret = true; stategy.customizeDocumentCommand(document, command); System.out.println("text = '" + command.text + "'"); String expectedDocumentAfter = expected.replace(CURSOR, ""); System.out.println("Cursor before " + command.caretOffset); executeCommand(document, command); System.out.println("Cursor after " + command.caretOffset); String documentAfter = document.get(); System.out.println("Document after: '" + documentAfter + "'"); assertEquals(expectedDocumentAfter, documentAfter); int expectedCursorOffset = expected.indexOf(CURSOR); assertEquals("Cursor at unexpected position", expectedCursorOffset, command.caretOffset); }
public void customizeDocumentCommand(IDocument d, DocumentCommand c) { if (c.length == 0 && c.text != null && TextUtilities.endsWith(d.getLegalLineDelimiters(), c.text) != -1) { autoIndentAfterNewLine(d, c); } else if (c.text.equals("\t")) { c.text = INDENT_STRING; } }
@Test public void indentShouldNotBeAdded_whenPreviousLineDoesNotStartFromIndent() { document.set("xyz"); command.offset = 3; command.text = "\n"; strategy.customizeDocumentCommand(document, command); assertThat(command.text).isEqualTo("\n"); }
@Test public void indentFromPreviousLineShouldBeAdded() { document.set(" abc"); command.offset = 7; command.text = "\n"; strategy.customizeDocumentCommand(document, command); assertThat(command.text).isEqualTo("\n "); }
@Test public void commandShouldNotBeChanged_whenItIsNotLineBreak() { document.set("x"); command.offset = 1; command.text = "q"; strategy.customizeDocumentCommand(document, command); assertThat(command.text).isEqualTo("q"); }
private void indentNewLine() throws BadLocationException { int stringIndent = getStringOrCommentIndent(command.offset); int start = getStartOfCurrentLine(); if (stringIndent >= 0) { // we're in a string or multiline comment StringBuilder sb = new StringBuilder(); for (int i = 0; i < stringIndent; i++) { char ws = document.getChar(start + i) == '\t' ? '\t' : ' '; sb.append(ws); } command.text = command.text + sb.toString() + getRelativeIndent(command.offset); } else { char endOfLastLineChar = getPreviousNonHiddenCharacterInLine(command.offset); char startOfNewLineChar = getNextNonHiddenCharacterInNewline(command.offset); StringBuilder buf = new StringBuilder(command.text); IPreferenceStore store = getPreferences(); boolean closeBrace = store == null || store.getBoolean(CLOSE_BRACES); int end = getEndOfCurrentLine(); appendIndent( command.offset, end, start, command.offset, startOfNewLineChar, endOfLastLineChar, closeBrace, buf); if (buf.length() > 2) { char ch = buf.charAt(buf.length() - 1); if (ch == '}' || ch == ')') { String hanging = document.get( command.offset, end - command.offset); // stuff after the { on the current line buf.insert(command.caretOffset - command.offset, hanging); command.length = hanging.length(); } } command.text = buf.toString(); } closeUnterminatedMultlineComment(); }
private void autoEditAfterNewLine(IDocument document, DocumentCommand command) { if (command.offset == -1 || document.getLength() == 0) { return; } try { int p = command.offset == document.getLength() ? command.offset - 1 : command.offset; IRegion info = document.getLineInformationOfOffset(p); int start = info.getOffset(); StringBuffer buf = new StringBuffer(command.text); int end = findEndOfWhiteSpaceAfter(document, start, command.offset); String lineSpaces = (end > start) ? document.get(start, end - start) : ""; buf.append(lineSpaces); if (isAfterOpenBrace(document, command.offset - 1, start)) { buf.append( IndenterUtil.createWhiteSpace(1, 0, TextUtilities.getDefaultLineDelimiter(document))); if (isBeforeCloseBrace(document, command.offset, info.getOffset() + info.getLength())) { command.shiftsCaret = false; command.caretOffset = command.offset + buf.length(); buf.append(command.text); buf.append(lineSpaces); } command.text = buf.toString(); } else { int indent = computeIndentCount(document, command.offset); if (isBeforeCloseBrace(document, command.offset, info.getOffset() + info.getLength())) { indent--; } command.text += IndenterUtil.createWhiteSpace( indent, 0, TextUtilities.getDefaultLineDelimiter(document)); } } catch (BadLocationException e) { KotlinLogger.logAndThrow(e); } }
protected void indentAfterNewLine(final IDocument d, final DocumentCommand c) throws BadLocationException { final int offset = c.offset; String txt = null; editor.reconcileNow(); final IErlElement element = editor.getElementAt(offset, false); final IErlMember member = (IErlMember) element; if (member != null) { final int start = member.getSourceRange().getOffset(); if (offset >= start) { txt = d.get(start, offset - start); } } if (txt == null) { txt = ""; } final int lineN = d.getLineOfOffset(offset); final int lineOffset = d.getLineOffset(lineN); final int lineLength = d.getLineLength(lineN); final String oldLine = d.get(offset, lineLength + lineOffset - offset); try { final IRpcSite b = BackendCore.getBackendManager().getIdeBackend().getRpcSite(); final int tabw = getTabWidthFromPreferences(); final Map<String, String> prefs = new TreeMap<String, String>(); IndentationPreferencePage.addKeysAndPrefs(prefs); SmartTypingPreferencePage.addAutoNLKeysAndPrefs(prefs); final boolean useTabs = getUseTabsFromPreferences(); final IndentResult res = ErlideIndent.indentLine(b, oldLine, txt, c.text, tabw, useTabs, prefs); if (res.isAddNewLine()) { c.text += "\n"; } c.text += res.getText(); c.length += res.getRemoveNext(); } catch (final Exception e) { ErlLogger.warn(e); } }
private void AtlStringIndentAfterNewLine(IDocument document, DocumentCommand command) throws BadLocationException { ITypedRegion partition = TextUtilities.getPartition(document, fPartitioning, command.offset, true); int offset = partition.getOffset(); int length = partition.getLength(); if (command.offset == offset + length && document.getChar(offset + length - 1) == '\'') return; String indentation = getLineIndentation(document, command.offset); String delimiter = TextUtilities.getDefaultLineDelimiter(document); IRegion line = document.getLineInformationOfOffset(offset); String string = document.get(line.getOffset(), offset - line.getOffset()); if (string.trim().length() != 0) indentation += String.valueOf("\t\t"); IPreferenceStore preferenceStore = AtlUIPlugin.getDefault().getPreferenceStore(); if (isLineDelimiter(document, command.text)) command.text = "\' +" + command.text + indentation + "\'"; else if (command.text.length() > 1 && preferenceStore.getBoolean(AtlPreferenceConstants.TYPING_ESCAPE_STRINGS)) command.text = getModifiedText(command.text, indentation, delimiter); }
private void closeUnterminatedMultlineComment() { if (isInUnterminatedMultilineComment(command.offset, document)) { command.shiftsCaret = false; String text = command.text; command.caretOffset = command.offset + text.length(); command.text = text + text + // uncomment to get a bigger indent // (text.indexOf(' ')>=0 ? // text.replaceFirst(" ", "") : text) + "*/"; } }
/** * Indent the new line the same way as the current line. * * @param doc the document to indent in * @param command the document command to customize * @throws BadLocationException if the offsets are invalid */ private void copyPreviousLineIndentation(IDocument doc, DocumentCommand command) throws BadLocationException { if (command.offset == -1 || doc.getLength() == 0) { return; } int lineStart = findLineStart(doc, command.offset); int textStart = findTextStart(doc, lineStart, command.offset); StringBuilder sb = new StringBuilder(command.text); if (textStart > lineStart) { sb.append(doc.get(lineStart, textStart - lineStart)); } command.text = sb.toString(); }
private void handleSmartTrigger(IDocument document, char trigger, int referenceOffset) throws BadLocationException { DocumentCommand cmd = new DocumentCommand() {}; cmd.offset = referenceOffset; cmd.length = 0; cmd.text = Character.toString(trigger); cmd.doit = true; cmd.shiftsCaret = true; cmd.caretOffset = getReplacementOffset() + getCursorPosition(); SmartSemicolonAutoEditStrategy strategy = new SmartSemicolonAutoEditStrategy(DartPartitions.DART_PARTITIONING); strategy.customizeDocumentCommand(document, cmd); replace(document, cmd.offset, cmd.length, cmd.text); setCursorPosition(cmd.caretOffset - getReplacementOffset() + cmd.text.length()); }
private void autoEditBeforeCloseBrace(IDocument document, DocumentCommand command) { if (isNewLineBefore(document, command.offset)) { try { int spaceLength = command.offset - findEndOfWhiteSpaceBefore(document, command.offset - 1, 0) - 1; command.text = IndenterUtil.createWhiteSpace( computeIndentCount(document, command.offset) - 1, 0, TextUtilities.getDefaultLineDelimiter(document)) + CLOSING_BRACE_STRING; command.offset -= spaceLength; document.replace(command.offset, spaceLength, ""); } catch (BadLocationException e) { KotlinLogger.logAndThrow(e); } } }
/** * Set the indent of a bracket based on the command provided in the supplied document. * * @param document - the document being parsed * @param command - the command being performed */ protected void smartInsertAfterBracket(final IDocument document, final DocumentCommand command) { if (command.offset == -1 || document.getLength() == 0) { return; } try { int p = (command.offset == document.getLength() ? command.offset - 1 : command.offset); int line = document.getLineOfOffset(p); int start = document.getLineOffset(line); int whiteend = findEndOfWhiteSpace(document, start, command.offset); // shift only when line does not contain any text up to // the closing // bracket if (whiteend == command.offset) { // evaluate the line with the opening bracket // that matches out // closing bracket int indLine = findMatchingOpenBracket(document, command.offset); if (indLine != -1 && indLine != line) { // take the indent of the found line StringBuffer replaceText = new StringBuffer(getIndentOfLine(document, indLine, command)); // add the rest of the current line // including the just added // close bracket // replaceText.append(document.get(whiteend, // command.offset // - whiteend)); replaceText.append(command.text); // modify document command command.length = command.offset - start; command.offset = start; command.text = replaceText.toString(); } } } catch (BadLocationException e) { ErrorReporter.logExceptionStackTrace(e); } }
/** * Adds two spaces to the indentation of the previous line. * * @param d the document to work on * @param c the command to deal with */ private void autoIndentAfterNewLine(IDocument d, DocumentCommand c) { if (c.offset == -1 || d.getLength() == 0) return; try { String lastPartitionType = null; if (d instanceof IDocumentExtension3) { IDocumentExtension3 id3 = (IDocumentExtension3) d; lastPartitionType = id3.getDocumentPartitioner(SassEditor.SASS_PARTITIONING).getContentType(c.offset - 1); } // find start of line int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset); IRegion info = d.getLineInformationOfOffset(p); int start = info.getOffset(); // find white spaces int end = findEndOfWhiteSpace(d, start, c.offset); // indent if we just finished an element StringBuffer buf = new StringBuffer(c.text); if (lastPartitionType != null && (lastPartitionType.equalsIgnoreCase(SassPartitionScanner.SASS_CLASS) || lastPartitionType.equalsIgnoreCase(SassPartitionScanner.SASS_ID))) { buf.append(" "); } if (end > start) { // append to input buf.append(d.get(start, end - start)); } c.text = buf.toString(); } catch (BadLocationException excp) { // stop work } }
private void fixIndentOfStringOrCommentContinuation() throws BadLocationException { int endOfWs = firstEndOfWhitespace(command.offset, getEndOfCurrentLine()); if (endOfWs < 0) return; CommonToken tokenContainingOffset = getTokenStrictlyContainingOffset(command.offset); CommonToken token = getStartOfStringToken(tokenContainingOffset); int pos = command.offset - getStartOfCurrentLine(); int tokenIndent = token.getCharPositionInLine(); if (pos > tokenIndent) return; StringBuilder indent = new StringBuilder(); int startOfTokenLine = document.getLineOffset(token.getLine() - 1); String prefix = document.get(startOfTokenLine + pos, tokenIndent - pos); for (int i = 0; i < prefix.length(); i++) { char ch = prefix.charAt(i); indent.append(ch == '\t' ? '\t' : ' '); } indent.append(getExtraIndent(token)); indent.append(getRelativeIndent(command.offset)); if (indent.length() > 0) { command.length = endOfWs - command.offset; command.text = indent.toString(); } }
@Override public void customizeDocumentCommand(final IDocument d, final DocumentCommand c) { if (TextUtilities.endsWith(d.getLegalLineDelimiters(), c.text) != -1) { // Start autoindentation after a cabal section (e.g., global, executable, library) try { IRegion r = d.getLineInformation(d.getLineOfOffset(c.offset)); String s = d.get(r.getOffset(), r.getLength()).toLowerCase(); for (String section : CabalSyntax.sections.keySet()) { if (s.equals(section) || s.startsWith(section + " ")) { // $NON-NLS-1$ char[] ch = new char[getTabWidth()]; Arrays.fill(ch, ' '); c.text = c.text + new String(ch); } } } catch (BadLocationException ble) { // ignore } } else { // Superclass takes care of autoindentation super.customizeDocumentCommand(d, c); } }
private void smartIndentAfterOpeningBracket(IDocument d, DocumentCommand c) { if (c.offset < 1 || d.getLength() == 0) return; JavaHeuristicScanner scanner = new JavaHeuristicScanner(d); int p = (c.offset == d.getLength() ? c.offset - 1 : c.offset); try { // current line int line = d.getLineOfOffset(p); int lineOffset = d.getLineOffset(line); // make sure we don't have any leading comments etc. if (d.get(lineOffset, p - lineOffset).trim().length() != 0) return; // line of last Java code int pos = scanner.findNonWhitespaceBackward(p, JavaHeuristicScanner.UNBOUND); if (pos == -1) return; int lastLine = d.getLineOfOffset(pos); // only shift if the last java line is further up and is a braceless block candidate if (lastLine < line) { JavaIndenter indenter = new JavaIndenter(d, scanner, fProject); StringBuffer indent = indenter.computeIndentation(p, true); String toDelete = d.get(lineOffset, c.offset - lineOffset); if (indent != null && !indent.toString().equals(toDelete)) { c.text = indent.append(c.text).toString(); c.length += c.offset - lineOffset; c.offset = lineOffset; } } } catch (BadLocationException e) { JavaPlugin.log(e); } }
private void smartPaste(IDocument document, DocumentCommand command) { int newOffset = command.offset; int newLength = command.length; String newText = command.text; try { JavaHeuristicScanner scanner = new JavaHeuristicScanner(document); JavaIndenter indenter = new JavaIndenter(document, scanner, fProject); int offset = newOffset; // reference position to get the indent from int refOffset = indenter.findReferencePosition(offset); if (refOffset == JavaHeuristicScanner.NOT_FOUND) return; int peerOffset = getPeerPosition(document, command); peerOffset = indenter.findReferencePosition(peerOffset); if (peerOffset != JavaHeuristicScanner.NOT_FOUND) refOffset = Math.min(refOffset, peerOffset); // eat any WS before the insertion to the beginning of the line int firstLine = 1; // don't format the first line per default, as it has other content before it IRegion line = document.getLineInformationOfOffset(offset); String notSelected = document.get(line.getOffset(), offset - line.getOffset()); if (notSelected.trim().length() == 0) { newLength += notSelected.length(); newOffset = line.getOffset(); firstLine = 0; } // prefix: the part we need for formatting but won't paste IRegion refLine = document.getLineInformationOfOffset(refOffset); String prefix = document.get(refLine.getOffset(), newOffset - refLine.getOffset()); // handle the indentation computation inside a temporary document Document temp = new Document(prefix + newText); DocumentRewriteSession session = temp.startRewriteSession(DocumentRewriteSessionType.STRICTLY_SEQUENTIAL); scanner = new JavaHeuristicScanner(temp); indenter = new JavaIndenter(temp, scanner, fProject); installJavaStuff(temp); // indent the first and second line // compute the relative indentation difference from the second line // (as the first might be partially selected) and use the value to // indent all other lines. boolean isIndentDetected = false; StringBuffer addition = new StringBuffer(); int insertLength = 0; int firstLineInsertLength = 0; int firstLineIndent = 0; int first = document.computeNumberOfLines(prefix) + firstLine; // don't format first line int lines = temp.getNumberOfLines(); int tabLength = getVisualTabLengthPreference(); boolean changed = false; for (int l = first; l < lines; l++) { // we don't change the number of lines while adding indents IRegion r = temp.getLineInformation(l); int lineOffset = r.getOffset(); int lineLength = r.getLength(); if (lineLength == 0) // don't modify empty lines continue; if (!isIndentDetected) { // indent the first pasted line String current = getCurrentIndent(temp, l); StringBuffer correct = indenter.computeIndentation(lineOffset); if (correct == null) return; // bail out insertLength = subtractIndent(correct, current, addition, tabLength); if (l == first) { firstLineInsertLength = insertLength; firstLineIndent = current.length(); } if (l != first && temp.get(lineOffset, lineLength).trim().length() != 0) { isIndentDetected = true; if (firstLineIndent >= current.length()) insertLength = firstLineInsertLength; if (insertLength == 0) { // no adjustment needed, bail out if (firstLine == 0) { // but we still need to adjust the first line command.offset = newOffset; command.length = newLength; if (changed) break; // still need to get the leading indent of the first line } return; } } else { changed = insertLength != 0; } } // relatively indent all pasted lines if (insertLength > 0) addIndent(temp, l, addition, tabLength); else if (insertLength < 0) cutIndent(temp, l, -insertLength, tabLength); } removeJavaStuff(temp); temp.stopRewriteSession(session); newText = temp.get(prefix.length(), temp.getLength() - prefix.length()); command.offset = newOffset; command.length = newLength; command.text = newText; } catch (BadLocationException e) { JavaPlugin.log(e); } }
public void customizeDocumentCommand(IDocument document, DocumentCommand c) { if (!isSmartInsertMode()) { return; } if (!(document instanceof IStructuredDocument)) { // This shouldn't happen unless this strategy is used on an invalid document return; } IStructuredDocument doc = (IStructuredDocument) document; // Handle newlines/indentation if (c.length == 0 && c.text != null && TextUtilities.endsWith(doc.getLegalLineDelimiters(), c.text) != -1) { IModelManager modelManager = StructuredModelManager.getModelManager(); IStructuredModel model = modelManager.getModelForRead(doc); if (model != null) { try { final int offset = c.offset; int lineStart = findLineStart(doc, offset); int textStart = findTextStart(doc, lineStart, offset); IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(textStart); if (region != null && region.getType().equals(XML_TAG_NAME)) { Pair<Integer, Integer> balance = getBalance(doc, textStart, offset); int tagBalance = balance.getFirst(); int bracketBalance = balance.getSecond(); String lineIndent = ""; // $NON-NLS-1$ if (textStart > lineStart) { lineIndent = doc.get(lineStart, textStart - lineStart); } // We only care if tag or bracket balance is greater than 0; // we never *dedent* on negative balances boolean addIndent = false; if (bracketBalance < 0) { // Handle // <foo // ></foo>^ // and // <foo // />^ ITextRegion left = getRegionAt(doc, offset, true /*biasLeft*/); if (left != null && (left.getType().equals(XML_TAG_CLOSE) || left.getType().equals(XML_EMPTY_TAG_CLOSE))) { // Find the corresponding open tag... // The org.eclipse.wst.xml.ui.gotoMatchingTag frequently // doesn't work, it just says "No matching brace found" // (or I would use that here). int targetBalance = 0; ITextRegion right = getRegionAt(doc, offset, false /*biasLeft*/); if (right != null && right.getType().equals(XML_END_TAG_OPEN)) { targetBalance = -1; } int openTag = AndroidXmlCharacterMatcher.findTagBackwards(doc, offset, targetBalance); if (openTag != -1) { // Look up the indentation of the given line lineIndent = AndroidXmlEditor.getIndentAtOffset(doc, openTag); } } } else if (tagBalance > 0 || bracketBalance > 0) { // Add indentation addIndent = true; } StringBuilder sb = new StringBuilder(c.text); sb.append(lineIndent); String oneIndentUnit = XmlFormatPreferences.create().getOneIndentUnit(); if (addIndent) { sb.append(oneIndentUnit); } // Handle // <foo>^</foo> // turning into // <foo> // ^ // </foo> ITextRegion left = getRegionAt(doc, offset, true /*biasLeft*/); ITextRegion right = getRegionAt(doc, offset, false /*biasLeft*/); if (left != null && right != null && left.getType().equals(XML_TAG_CLOSE) && right.getType().equals(XML_END_TAG_OPEN)) { // Move end tag if (tagBalance > 0 && bracketBalance < 0) { sb.append(oneIndentUnit); } c.caretOffset = offset + sb.length(); c.shiftsCaret = false; sb.append(TextUtilities.getDefaultLineDelimiter(doc)); sb.append(lineIndent); } c.text = sb.toString(); } else if (region != null && region.getType().equals(XML_CONTENT)) { // Indenting in text content. If you're in the middle of editing // text, just copy the current line indentation. // However, if you're editing in leading whitespace (e.g. you press // newline on a blank line following say an element) then figure // out the indentation as if the newline had been pressed at the // end of the element, and insert that amount of indentation. // In this case we need to also make sure to subtract any existing // whitespace on the current line such that if we have // // <foo> // ^ <bar/> // </foo> // // you end up with // // <foo> // // ^<bar/> // </foo> // String text = region.getText(); int regionStart = region.getStartOffset(); int delta = offset - regionStart; boolean inWhitespacePrefix = true; for (int i = 0, n = Math.min(delta, text.length()); i < n; i++) { char ch = text.charAt(i); if (!Character.isWhitespace(ch)) { inWhitespacePrefix = false; break; } } if (inWhitespacePrefix) { IStructuredDocumentRegion previous = region.getPrevious(); if (previous != null && previous.getType() == XML_TAG_NAME) { ITextRegionList subRegions = previous.getRegions(); ITextRegion last = subRegions.get(subRegions.size() - 1); if (last.getType() == XML_TAG_CLOSE || last.getType() == XML_EMPTY_TAG_CLOSE) { int begin = AndroidXmlCharacterMatcher.findTagBackwards( doc, previous.getStartOffset() + last.getStart(), 0); int prevLineStart = findLineStart(doc, begin); int prevTextStart = findTextStart(doc, prevLineStart, begin); String lineIndent = ""; // $NON-NLS-1$ if (prevTextStart > prevLineStart) { lineIndent = doc.get(prevLineStart, prevTextStart - prevLineStart); } StringBuilder sb = new StringBuilder(c.text); sb.append(lineIndent); String oneIndentUnit = XmlFormatPreferences.create().getOneIndentUnit(); // See if there is whitespace on the insert line that // we should also remove for (int i = delta, n = text.length(); i < n; i++) { char ch = text.charAt(i); if (ch == ' ') { c.length++; } else { break; } } boolean onClosingTagLine = false; if (text.indexOf('\n', delta) == -1) { IStructuredDocumentRegion next = region.getNext(); if (next != null && next.getType() == XML_TAG_NAME) { String nextType = next.getRegions().get(0).getType(); if (nextType == XML_END_TAG_OPEN) { onClosingTagLine = true; } } } boolean addIndent = (last.getType() == XML_TAG_CLOSE) && !onClosingTagLine; if (addIndent) { sb.append(oneIndentUnit); } c.text = sb.toString(); return; } } } copyPreviousLineIndentation(doc, c); } else { copyPreviousLineIndentation(doc, c); } } catch (BadLocationException e) { AdtPlugin.log(e, null); } finally { model.releaseFromRead(); } } } }
private void smartIndentUponE(IDocument d, DocumentCommand c) { if (c.offset < 4 || d.getLength() == 0) return; try { String content = d.get(c.offset - 3, 3); if (content.equals("els")) { // $NON-NLS-1$ JavaHeuristicScanner scanner = new JavaHeuristicScanner(d); int p = c.offset - 3; // current line int line = d.getLineOfOffset(p); int lineOffset = d.getLineOffset(line); // make sure we don't have any leading comments etc. if (d.get(lineOffset, p - lineOffset).trim().length() != 0) return; // line of last Java code int pos = scanner.findNonWhitespaceBackward(p - 1, JavaHeuristicScanner.UNBOUND); if (pos == -1) return; int lastLine = d.getLineOfOffset(pos); // only shift if the last java line is further up and is a braceless block candidate if (lastLine < line) { JavaIndenter indenter = new JavaIndenter(d, scanner, fProject); int ref = indenter.findReferencePosition(p, true, false, false, false); if (ref == JavaHeuristicScanner.NOT_FOUND) return; int refLine = d.getLineOfOffset(ref); String indent = getIndentOfLine(d, refLine); if (indent != null) { c.text = indent.toString() + "else"; // $NON-NLS-1$ c.length += c.offset - lineOffset; c.offset = lineOffset; } } return; } if (content.equals("cas")) { // $NON-NLS-1$ JavaHeuristicScanner scanner = new JavaHeuristicScanner(d); int p = c.offset - 3; // current line int line = d.getLineOfOffset(p); int lineOffset = d.getLineOffset(line); // make sure we don't have any leading comments etc. if (d.get(lineOffset, p - lineOffset).trim().length() != 0) return; // line of last Java code int pos = scanner.findNonWhitespaceBackward(p - 1, JavaHeuristicScanner.UNBOUND); if (pos == -1) return; int lastLine = d.getLineOfOffset(pos); // only shift if the last java line is further up and is a braceless block candidate if (lastLine < line) { JavaIndenter indenter = new JavaIndenter(d, scanner, fProject); int ref = indenter.findReferencePosition(p, false, false, false, true); if (ref == JavaHeuristicScanner.NOT_FOUND) return; int refLine = d.getLineOfOffset(ref); int nextToken = scanner.nextToken(ref, JavaHeuristicScanner.UNBOUND); String indent; if (nextToken == Symbols.TokenCASE || nextToken == Symbols.TokenDEFAULT) indent = getIndentOfLine(d, refLine); else // at the brace of the switch indent = indenter.computeIndentation(p).toString(); if (indent != null) { c.text = indent.toString() + "case"; // $NON-NLS-1$ c.length += c.offset - lineOffset; c.offset = lineOffset; } } return; } } catch (BadLocationException e) { JavaPlugin.log(e); } }
private void closeOpening() { if (isCommented(command.offset)) { return; } boolean quoted = isQuoted(command.offset); String current = command.text; try { // don't close fences after a backslash escape // TODO: improve this, check the surrounding // token type! if (command.offset > 0 && document.getChar(command.offset - 1) == '\\') { return; } // don't close fences before an identifier, // literal or opening paren if (!quoted && // there are special rules for < below !current.equals("<")) { int curr = command.offset; while (curr < document.getLength()) { char ch = document.getChar(curr++); if (isLetter(ch) || isDigit(ch) || ch == '(') { return; } if (ch == '"' && !"\"".equals(current) && !"`".equals(current)) { return; } if (ch == '\'' && !"\'".equals(current)) { return; } if (ch != ' ') { break; } } } } catch (BadLocationException e) { } String opening = null; String closing = null; boolean found = false; IPreferenceStore store = getPreferences(); for (String[] type : FENCES) { if (type[0].equals(current) || type[1].equals(current)) { if (store == null || store.getBoolean(type[2])) { opening = type[0]; closing = type[1]; found = true; break; } } } if (found) { if (current.equals(closing)) { // typed character is a closing fence try { // skip one ahead if next char is already a closing fence if (skipClosingFence(closing) && closeOpeningFence(opening, closing)) { command.text = null; command.shiftsCaret = false; command.caretOffset = command.offset + 1; return; } } catch (BadLocationException e) { } } boolean isInterpolation = isGraveAccentCharacterInStringLiteral(command.offset, opening); boolean isDocLink = isOpeningBracketInAnnotationStringLiteral(command.offset, opening); if (current.equals(opening) && (isInterpolation || isDocLink || !quoted)) { // typed character is an opening fence if (isInterpolation || isDocLink || closeOpeningFence(opening, closing)) { // add a closing fence command.shiftsCaret = false; command.caretOffset = command.offset + 1; if (isInterpolation) { try { if (command.offset > 1 && document.get(command.offset - 1, 1).equals("`") && !document.get(command.offset - 2, 1).equals("`")) { command.text += "``"; } } catch (BadLocationException e) { } } else if (isDocLink) { try { if (command.offset > 1 && document.get(command.offset - 1, 1).equals("[") && !document.get(command.offset - 2, 1).equals("]")) { command.text += "]]"; } } catch (BadLocationException e) { } } else if (opening.equals("\"")) { try { if (command.offset <= 1 || !document.get(command.offset - 1, 1).equals("\"")) { command.text += closing; } else if (command.offset > 1 && document.get(command.offset - 2, 2).equals("\"\"") && !(command.offset > 2 && document.get(command.offset - 3, 1).equals("\""))) { command.text += "\"\"\""; } } catch (BadLocationException e) { } } else { command.text += closing; } } } } }
/** * Copies the indentation of the previous line. * * @param d the document to work on * @param c the command to deal with */ protected void autoIndentAfterNewLine(IDocument d, DocumentCommand c) { c.text += getAutoIndentAfterNewLine(d, c); }
private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) { JavaHeuristicScanner scanner = new JavaHeuristicScanner(d); JavaIndenter indenter = new JavaIndenter(d, scanner, fProject); StringBuffer indent = indenter.computeIndentation(c.offset); if (indent == null) indent = new StringBuffer(); int docLength = d.getLength(); if (c.offset == -1 || docLength == 0) return; try { int p = (c.offset == docLength ? c.offset - 1 : c.offset); int line = d.getLineOfOffset(p); StringBuffer buf = new StringBuffer(c.text + indent); IRegion reg = d.getLineInformation(line); int lineEnd = reg.getOffset() + reg.getLength(); int contentStart = findEndOfWhiteSpace(d, c.offset, lineEnd); c.length = Math.max(contentStart - c.offset, 0); int start = reg.getOffset(); ITypedRegion region = TextUtilities.getPartition(d, fPartitioning, start, true); if (IJavaPartitions.JAVA_DOC.equals(region.getType())) start = d.getLineInformationOfOffset(region.getOffset()).getOffset(); // insert closing brace on new line after an unclosed opening brace if (getBracketCount(d, start, c.offset, true) > 0 && closeBrace() && !isClosed(d, c.offset, c.length)) { c.caretOffset = c.offset + buf.length(); c.shiftsCaret = false; // copy old content of line behind insertion point to new line // unless we think we are inserting an anonymous type definition if (c.offset == 0 || computeAnonymousPosition(d, c.offset - 1, fPartitioning, lineEnd) == -1) { if (lineEnd - contentStart > 0) { c.length = lineEnd - c.offset; buf.append(d.get(contentStart, lineEnd - contentStart).toCharArray()); } } buf.append(TextUtilities.getDefaultLineDelimiter(d)); StringBuffer reference = null; int nonWS = findEndOfWhiteSpace(d, start, lineEnd); if (nonWS < c.offset && d.getChar(nonWS) == '{') reference = new StringBuffer(d.get(start, nonWS - start)); else reference = indenter.getReferenceIndentation(c.offset); if (reference != null) buf.append(reference); buf.append('}'); } // insert extra line upon new line between two braces else if (c.offset > start && contentStart < lineEnd && d.getChar(contentStart) == '}') { int firstCharPos = scanner.findNonWhitespaceBackward(c.offset - 1, start); if (firstCharPos != JavaHeuristicScanner.NOT_FOUND && d.getChar(firstCharPos) == '{') { c.caretOffset = c.offset + buf.length(); c.shiftsCaret = false; StringBuffer reference = null; int nonWS = findEndOfWhiteSpace(d, start, lineEnd); if (nonWS < c.offset && d.getChar(nonWS) == '{') reference = new StringBuffer(d.get(start, nonWS - start)); else reference = indenter.getReferenceIndentation(c.offset); buf.append(TextUtilities.getDefaultLineDelimiter(d)); if (reference != null) buf.append(reference); } } c.text = buf.toString(); } catch (BadLocationException e) { JavaPlugin.log(e); } }