/**
* Copyright (c) 2009, 2010 Mark Feber, MulgaSoft
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package com.mulgasoft.emacsplus.commands;
import java.text.BreakIterator;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.TextConsoleViewer;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* Implements: forward-sexp. Move forward one s-expression
*
* @author Mark Feber - initial API and implementation
*/
public abstract class SexpBaseForwardHandler extends SexpHandler implements IConsoleDispatch {
@Override
protected int getDirection() {
return FORWARD;
}
/**
* @see com.mulgasoft.emacsplus.commands.EmacsPlusNoEditHandler#transform(ITextEditor, IDocument, ITextSelection, ExecutionEvent)
*/
protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection, ExecutionEvent event)
throws BadLocationException {
ITextSelection selection = null;
try {
ITextSelection nSelection = currentSelection;
if (checkMark(editor, currentSelection.getOffset(),currentSelection.getLength())) {
// when expanding mark, always start from the cursor
nSelection = new TextSelection(document, getCursorOffset(editor,currentSelection), 0);
}
selection = getNextSexp(document, nSelection);
} catch (BadLocationException e) {}
if (selection == null) {
selection = currentSelection;
if (isUnbalanced()) {
unbalanced(editor, true);
throw new BadLocationException();
}
}
return endTransform(editor,selection.getOffset() + selection.getLength(),currentSelection,selection);
}
/**
* @see com.mulgasoft.emacsplus.commands.IConsoleDispatch#consoleDispatch(org.eclipse.ui.console.TextConsoleViewer, org.eclipse.ui.console.IConsoleView, org.eclipse.core.commands.ExecutionEvent)
*/
public Object consoleDispatch(TextConsoleViewer viewer, IConsoleView activePart, ExecutionEvent event) {
IDocument document = viewer.getDocument();
ITextSelection currentSelection = (ITextSelection)viewer.getSelectionProvider().getSelection();
ITextSelection selection = new TextSelection(document, viewer.getTextWidget().getCaretOffset(), 0);
try {
selection = getNextSexp(document, selection);
if (selection == null) {
selection = currentSelection;
unbalanced(activePart,true);
return null;
} else {
return endTransform(viewer, selection.getOffset() + selection.getLength(), currentSelection, selection);
}
} catch (BadLocationException e) {
}
return null;
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#getNextPosition(org.eclipse.jface.text.IDocument, java.text.BreakIterator, int)
*/
@Override
protected int getNextPosition(IDocument document, BreakIterator iter, int pos) {
int result = iter.following(pos);
if (result != BreakIterator.DONE) {
result = checkDot(document, pos, result);
result = checkUnder(document, result);
}
return result;
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#getNextPosition(org.eclipse.jface.text.IDocument, java.text.BreakIterator)
*/
@Override
protected int getNextPosition(IDocument document, BreakIterator iter) {
int pos = iter.current();
int result = iter.next();
if (result != BreakIterator.DONE) {
result = checkDot(document,pos,result);
result = checkUnder(document,result);
}
return result;
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#isBracket(char)
*/
@Override
protected boolean isBracket(char c){
return isBracket(c,OPEN);
}
protected boolean isUnbalanced(char c, int updown) {
boolean result = false;
if (GNU_SEXP && updown != DOWN) {
result = isBracket(c,CLOSE);
}
setUnbalanced(result);
return result;
}
@Override
protected int getBracketPosition(IDocument document, int pos) {
int result = -1;
IRegion reg = getBracketMatch(document, pos);
if (reg != null){
result = reg.getOffset() + reg.getLength();
}
return result;
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#getTransSexp(org.eclipse.jface.text.IDocument, int, boolean)
*/
@Override
ITextSelection getTransSexp(IDocument document, int pos, boolean wordp)
throws BadLocationException {
ITextSelection result = null;
SexpHandler backsexp = new SexpBackwardHandler();
result = getNextSexp(document, new TextSelection(document,pos,0), wordp);
if (result != null) {
// get full sexp in case currentSelection is in the middle of it
ITextSelection full = new TextSelection(document, result.getOffset() + result.getLength(), 0);
full = backsexp.getNextSexp(document, full, wordp);
// make sure full starts before result
if (full != null && full.getOffset() < result.getOffset()) {
result = full;
}
result = new TextSelection(document, result.getOffset(), result.getText().trim().length());
String text;
while ((text = result.getText()).length() == 1 && !Character.isJavaIdentifierPart(text.charAt(0))) {
result = getNextSexp(document, new TextSelection(document, result.getOffset() + 1, 0), wordp);
result = backsexp.getNextSexp(document, new TextSelection(document, result.getOffset()
+ result.getLength(), 0), wordp);
result = new TextSelection(document, result.getOffset(), result.getText().trim().length());
text = result.getText();
}
// transpose around . if it is a break character
if (isDot() && text.charAt(0) == '.') {
result = new TextSelection(document, result.getOffset()+1, result.getLength()-1);
}
}
return result;
}
}