/**
* 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 org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
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: down-list
*
* Move forward down one level of brackets. With arg, do this that many times.
*
* @author Mark Feber - initial API and implementation
*/
public class DownListHandler extends SexpForwardHandler implements IConsoleDispatch {
/**
* @see com.mulgasoft.emacsplus.commands.SexpBaseForwardHandler#transform(ITextEditor, IDocument, ITextSelection, ExecutionEvent)
*/
@Override
protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection, ExecutionEvent event)
throws BadLocationException {
ITextSelection selection = null;
selection = downList(document, currentSelection);
if (selection == null) {
unbalanced(editor,true);
// trapped by generalized beep() exit
throw new BadLocationException();
}
return endTransform(editor,selection.getOffset() + selection.getLength(), currentSelection, selection);
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpBaseForwardHandler#consoleDispatch(TextConsoleViewer, IConsoleView, ExecutionEvent)
*/
public Object consoleDispatch(final TextConsoleViewer viewer, final IConsoleView activePart, ExecutionEvent event) {
IDocument doc = viewer.getDocument();
ITextSelection currentSelection = (ITextSelection) viewer.getSelectionProvider().getSelection();
ITextSelection selection = downList(doc, currentSelection);
if (selection == null) {
unbalanced(activePart,false);
} else {
endTransform(viewer,selection.getOffset() + selection.getLength(), currentSelection, selection);
}
return null;
}
/**
* Proceed down into next list
*
* @param document
* @param currentSelection
*
* @return selection positioned after next list opening or null if unbalanced
*/
private ITextSelection downList(IDocument document, ITextSelection currentSelection) {
ITextSelection selection = currentSelection;
try {
int newOffset = selection.getOffset() + selection.getLength();
do {
int oldOff = newOffset;
selection = new TextSelection(document,newOffset,0);
selection = getNextSexp(document, selection, false, DOWN);
if (selection != null) {
newOffset = selection.getOffset() + selection.getLength();
if (oldOff == newOffset) {
// if no movement, then unbalanced
selection = null;
}
}
}
while (selection != null && !isDownList(document,selection));
} catch (BadLocationException e) {
// mark as unbalanced; transform will re-throw
selection = null;
}
return selection;
}
/**
* Test for sexp open character
*
* @param document
* @param selection
* @return true if we're at a sexp open character
* @throws BadLocationException
*/
private boolean isDownList(IDocument document, ITextSelection selection) throws BadLocationException {
return isOpen(document.getChar(selection.getOffset()+selection.getLength()-1));
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpBaseForwardHandler#isBracket(char)
*
* Match both open and close, so we can test for sexp end when moving forward
*/
protected boolean isBracket(char c) {
for (int i = 0; i < getSexpBrackets().length; i++) {
if (c == getSexpBrackets()[i]) {
return true;
}
}
return false;
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#endTransform(org.eclipse.ui.texteditor.ITextEditor, int, org.eclipse.jface.text.ITextSelection, org.eclipse.jface.text.ITextSelection)
*/
@Override
protected int endTransform(ITextEditor editor, int offset,
ITextSelection origSelection, ITextSelection selection) {
if (isMarkEnabled(editor,origSelection)) {
return selectTransform(editor,offset,origSelection,selection);
} else {
return noSelectTransform(editor,offset,selection,true);
}
}
/**
* @see com.mulgasoft.emacsplus.commands.SexpHandler#endTransform(org.eclipse.ui.console.TextConsoleViewer, int, org.eclipse.jface.text.ITextSelection, org.eclipse.jface.text.ITextSelection)
*/
@Override
protected int endTransform(TextConsoleViewer viewer, int offset,
ITextSelection origSelection, ITextSelection selection) {
if (isMarkEnabled(viewer, origSelection)) {
return selectTransform(viewer, offset, origSelection, selection);
} else {
return noSelectTransform(viewer, offset, selection, true);
}
}
}