// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de // This code is made available under the terms of the Eclipse Public License, // version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html package net.sf.eclipsefp.haskell.ui.internal.editors.haskell.text; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.source.ICharacterPairMatcher; /** <p>The pair matcher implementation used for matching parentheses etc.</p> * * @author Leif Frenzel * @deprecated JP Moresmau August 29th, 2013. Why not use Eclipse's default implementation? */ @Deprecated public class HaskellCharacterPairMatcher implements ICharacterPairMatcher { private static final int FORWARD = +1; private static final int BACKWARDS = -1; private static final char PAIRS[] = { '{', '}', '(', ')', '[', ']' }; private int anchor; // interface methods of ICharacterPairMatcher ///////////////////////////////////////////// @Override public void clear() { anchor = 0; } @Override public void dispose() { //nothing to dispose } @Override public IRegion match(final IDocument document, final int theOffset) { Assert.isNotNull( document ); Assert.isLegal( theOffset >= 0 ); //special case, there is nothing to complete if cursor is on position zero if (0 == theOffset) { return null; } try { final int initialOffset = theOffset - 1; final char start = document.getChar(initialOffset); int direction = 0; if (isClosingCharacter(start)) { anchor = RIGHT; direction = BACKWARDS; } else if (isOpeningCharacter(start)) { anchor = LEFT; direction = FORWARD; } else { return null; } return matchPair(document, initialOffset, direction); } catch( BadLocationException ex ) { // ignore: probably there isn't a matching character yet } return null; } private IRegion matchPair(final IDocument document, final int initialOffset, final int searchDirection) throws BadLocationException { final Reader reader = new Reader(document, initialOffset, searchDirection); final char start = reader.readChar(); final char match = pairFor(start); int length = 1; int nestingLevel = 0; //advance the starting character while(!reader.eof()) { char c = reader.readChar(); ++length; if (c == match) { if (nestingLevel == 0) { return new Region(reader.getSmallestOffset(), length); } --nestingLevel; } else if (c == start){ ++nestingLevel; } } return null; } @Override public int getAnchor() { return anchor; } // helping methods ////////////////// private boolean isClosingCharacter( final char ch ) { for( int i = 1; i < PAIRS.length; i += 2 ) { if( ch == PAIRS[ i ] ) { return true; } } return false; } private boolean isOpeningCharacter( final char ch ) { for( int i = 0; i < PAIRS.length; i += 2 ) { if( ch == PAIRS[ i ] ) { return true; } } return false; } private char pairFor(final char c) { for(int i = 0; i < PAIRS.length; ++i ) { if (PAIRS[i] == c) { if (i % 2 == 0) { return PAIRS[i + 1]; } return PAIRS[i - 1]; } } return c; } private static class Reader { private final IDocument fSourceDoc; private final int fInitialOffset; private final int fIncrement; private int fLastOffset; public Reader(final IDocument document, final int initialOffset, final int increment) { fSourceDoc = document; fInitialOffset = initialOffset; fIncrement = increment; fLastOffset = fInitialOffset - fIncrement; } public int getSmallestOffset() { return Math.min(fInitialOffset, fLastOffset); } public char readChar() throws BadLocationException { fLastOffset += fIncrement; char result = fSourceDoc.getChar(fLastOffset); return result; } public boolean eof() { return (fIncrement < 0) ? fLastOffset < 0 : fLastOffset+fIncrement >= fSourceDoc.getLength(); } } }