private void moveSelectionNow(boolean up) { int start = _gsEditor.getEditor().getSelectionStart(); int end = _gsEditor.getEditor().getSelectionEnd(); String script = _gsEditor.getEditor().getText(); // If the caret is positioned at the first point in a new line, treat it as if it is on the // previous line only if (start != end && end > 0 && script.charAt(end - 1) == '\n') { end = end - 1; } // Handle raw whitespace moves int rawStart = TextComponentUtil.getLineStart(script, start); int rawEnd = TextComponentUtil.getLineEnd(script, end); String line = script.substring(rawStart, rawEnd); if (GosuStringUtil.isWhitespace(line) || line.trim().startsWith("//")) { if (up) { if (rawStart == 0) { return; } int lineStartBefore = TextComponentUtil.getLineStart(script, rawStart - 1); GosuRefactorUtil.MoveInstruction moveInstruction = new GosuRefactorUtil.MoveInstruction(false, false, lineStartBefore); handleMoveInstruction(script, moveInstruction, rawStart, rawEnd, up); return; } else { if (rawEnd >= script.length()) { return; } int lineStartBefore = rawEnd + 1; GosuRefactorUtil.MoveInstruction moveInstruction = new GosuRefactorUtil.MoveInstruction(false, false, lineStartBefore); handleMoveInstruction(script, moveInstruction, rawStart, rawEnd, up); return; } } int peStart = TextComponentUtil.findNonWhitespacePositionAfter(script, rawStart); int peEnd = TextComponentUtil.findNonWhitespacePositionBefore(script, rawEnd); peStart = Math.min(peStart, script.length() - 1); peEnd = Math.min(peEnd, script.length() - 1); // Find the first statement at the selection start IParseTree firstStatement = GosuRefactorUtil.findFirstStatementAtLine( TextComponentUtil.getLineAtPosition(_gsEditor.getEditor(), peStart), peStart, _gsEditor.getParser().getLocations()); // Find the last statement at the selection end IParseTree lastStatement = GosuRefactorUtil.findLastStatementAtLine( TextComponentUtil.getLineAtPosition(_gsEditor.getEditor(), peEnd), peEnd, _gsEditor.getParser().getLocations()); // Find the spanning range of those two statements IParseTree[] boundingPair = GosuRefactorUtil.findSpanningLogicalRange(firstStatement, lastStatement); // If a bounding pair exists, do the move if (boundingPair != null) { int clipStart = Math.min(rawStart, TextComponentUtil.getLineStart(script, boundingPair[0].getOffset())); int clipEnd = Math.max(rawEnd, TextComponentUtil.getLineEnd(script, boundingPair[1].getExtent())); // if this is not a class element (that is, we are in an impl), handle moving into a white // space line if (!GosuRefactorUtil.isClassElement(boundingPair[0])) { int lineStart = up ? TextComponentUtil.getWhiteSpaceOrCommentLineStartBefore(script, clipStart) : TextComponentUtil.getWhiteSpaceOrCommentLineStartAfter(script, clipEnd); if (lineStart != -1) { GosuRefactorUtil.MoveInstruction moveInstruction = new GosuRefactorUtil.MoveInstruction(false, false, lineStart); handleMoveInstruction(script, moveInstruction, clipStart, clipEnd, up); return; } } // Not handling an into whitespace move, so do a syntax aware move GosuRefactorUtil.MoveInstruction moveInstruction = up ? GosuRefactorUtil.getMoveUpInstruction(boundingPair[0]) : GosuRefactorUtil.getMoveDownInstruction(boundingPair[1]); if (moveInstruction != null) { if (GosuRefactorUtil.isClassElement(boundingPair[1])) { IParseTree nextSibling = boundingPair[1].getNextSibling(); if (nextSibling != null) { clipEnd = TextComponentUtil.getLineStart(script, nextSibling.getOffset()) - 1; if (!up) { moveInstruction.position = TextComponentUtil.getDeepestWhiteSpaceLineStartAfter( script, moveInstruction.position); } } } handleMoveInstruction(script, moveInstruction, clipStart, clipEnd, up); } } }
private void handleMoveInstruction( String script, GosuRefactorUtil.MoveInstruction moveInstruction, int startClip, int endClip, boolean up) { // Do nothing if we are moving down beyond the last position in the script if (endClip == script.length() - 1 && !up) { return; } if (endClip < script.length()) { endClip = endClip + 1; } String movedCodeAsString = script.substring(startClip, endClip); if (!movedCodeAsString.endsWith("\n")) { movedCodeAsString += "\n"; } int offset = moveInstruction.position; if (up) { offset = TextComponentUtil.getLineStart(script, offset); } else { offset = TextComponentUtil.getLineEnd(script, offset) + 1 - movedCodeAsString.length(); } StringBuilder movedCode = new StringBuilder(); int caretPosition = _gsEditor.getEditor().getCaretPosition(); int selectionStart = _gsEditor.getEditor().getSelectionStart(); int selectionEnd = _gsEditor.getEditor().getSelectionEnd(); int currentPosition = startClip; if (moveInstruction.indent) { String[] strings = movedCodeAsString.split("\n"); for (String str : strings) { if (caretPosition > currentPosition) { caretPosition += 2; } if (selectionStart > currentPosition) { selectionStart += 2; } if (selectionEnd > currentPosition) { selectionEnd += 2; } movedCode.append(" "); movedCode.append(str); movedCode.append("\n"); currentPosition += str.length() + 1; } } else if (moveInstruction.outdent && movedCodeAsString.startsWith(" ")) { String[] strings = movedCodeAsString.split("\n"); for (String str : strings) { if (str.startsWith(" ")) { if (caretPosition > currentPosition) { caretPosition -= 2; } if (selectionStart > currentPosition) { selectionStart -= 2; } if (selectionEnd > currentPosition) { selectionEnd -= 2; } str = str.substring(2, str.length()); } movedCode.append(str); movedCode.append("\n"); currentPosition += str.length() + 1; } } else { movedCode.append(movedCodeAsString); } CompoundEdit undoAtom = _gsEditor.getUndoManager().getUndoAtom(); if (undoAtom != null && undoAtom.getPresentationName().equals("Script Change")) { _gsEditor.getUndoManager().endUndoAtom(); } _gsEditor.getUndoManager().beginUndoAtom("moveLine"); try { _gsEditor.getEditor().getDocument().remove(startClip, endClip - startClip); _gsEditor.getEditor().getDocument().insertString(offset, movedCode.toString(), null); _gsEditor.getEditor().setSelectionStart(selectionStart - (startClip - offset)); _gsEditor.getEditor().setSelectionEnd(selectionEnd - (startClip - offset)); _gsEditor.getEditor().getCaret().moveDot(caretPosition - (startClip - offset)); } catch (BadLocationException e) { throw new RuntimeException(e); } finally { _gsEditor.getUndoManager().endUndoAtom(); } }