@Override public void enterMode(final ModeSwitchHint... hints) throws CommandExecutionException { boolean fixSelection = false; boolean keepSelection = false; boolean recallSelection = false; ExecuteCommandHint onEnterCommand = null; for (final ModeSwitchHint hint : hints) { if (hint == FIX_SELECTION_HINT) { keepSelection = true; fixSelection = true; } if (hint == KEEP_SELECTION_HINT) { keepSelection = true; } if (hint == RECALL_SELECTION_HINT) { recallSelection = true; } if (hint instanceof ExecuteCommandHint) { onEnterCommand = (ExecuteCommandHint) hint; } } if (recallSelection) { Selection previousSel = editorAdaptor.getLastActiveSelection(); CursorService cursorService = editorAdaptor.getCursorService(); Position from = cursorService.getMark(CursorService.INTERNAL_LAST_SELECT_FROM_MARK); Position to = cursorService.getMark(CursorService.INTERNAL_LAST_SELECT_TO_MARK); if (previousSel == null) { VrapperLog.info("Previous selection was null, selection not recalled."); } else { Selection updatedSel = updateSelection(editorAdaptor, previousSel, from, to); // Makes sure to set the sticky column. editorAdaptor.setPosition(updatedSel.getTo(), StickyColumnPolicy.ON_CHANGE); editorAdaptor.setSelection(updatedSel); } } else if (!keepSelection) { editorAdaptor.setSelection(null); } Selection currentSelection = editorAdaptor.getSelection(); if (fixSelection && currentSelection != null) { editorAdaptor.setSelection(fixSelection(currentSelection)); } super.enterMode(hints); if (onEnterCommand != null) { try { super.executeCommand(onEnterCommand.getCommand()); } catch (final CommandExecutionException e) { editorAdaptor.getUserInterfaceService().setErrorMessage(e.getMessage()); } } fixCaret(); }
/** * Vim doesn't start a delimited range on a newline or end a range on an empty line (try 'vi{' * while within a function for proof). */ public static Position fixLeftDelimiter(TextContent model, CursorService cursor, Position delim) { // check if the character after delimiter is a newline if (isNewLine(model.getText(delim.getModelOffset() + 1, 1))) { // start after newline LineInformation line = model.getLineInformationOfOffset(delim.getModelOffset()); LineInformation nextLine = model.getLineInformation(line.getNumber() + 1); delim = cursor.newPositionForModelOffset(nextLine.getBeginOffset()); } else { delim = delim.addModelOffset(1); } return delim; }
public static Position fixRightDelimiter( TextContent model, CursorService cursor, Position delim) { int delimIndex = delim.getModelOffset(); LineInformation line = model.getLineInformationOfOffset(delimIndex); int lineStart = line.getBeginOffset(); if (delimIndex > lineStart) { // is everything before the delimiter just whitespace? String text = model.getText(lineStart, delimIndex - lineStart); if (VimUtils.isBlank(text)) { // end on previous line LineInformation previousLine = model.getLineInformation(line.getNumber() - 1); delimIndex = previousLine.getEndOffset(); delim = cursor.newPositionForModelOffset(delimIndex); } } return delim; }
/** * Adds a (possibly negative) offset to a Position, then checks that the position didn't run into * newline sequence or is past the last character. Windows endlines (CR LF) are notorious as they * will make Eclipse puke. * * <p>This function will also account for the end of the text and the start of the text. * * @param adaptor {@link EditorAdaptor} * @param original {@link Position} starting position * @param delta {@link delta} how many characters to move. A CR LF newline will always count for * two, whereas a CR newline only counts for one. The only special case is when the given * delta makes us move into a CR LF sequence, in that case this function will move +/- 1 * character. * @param allowPastLastChar whether the newly returned position can be past the last character. * All motions want to pass <tt>true</tt> so that a selection includes the last character, * while low-level positioning logic can pass <tt>false</tt> to keep the cursor on the last * character. If the line is empty, the first position of the line is returned. */ public static Position safeAddModelOffset( EditorAdaptor adaptor, Position original, int delta, boolean allowPastLastChar) { CursorService cursorService = adaptor.getCursorService(); int originalPos = original.getModelOffset(); return cursorService.shiftPositionForModelOffset(originalPos, delta, allowPastLastChar); }