/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.haml.internal;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
import com.aptana.editor.common.IPartitionScannerSwitchStrategy;
import com.aptana.editor.common.IPartitionScannerSwitchStrategy.ISequenceBypassHandler;
import com.aptana.editor.common.PartitionScannerSwitchStrategy;
import com.aptana.editor.common.TextUtils;
import com.aptana.editor.common.text.rules.CompositeSubPartitionScanner;
import com.aptana.editor.common.text.rules.ISubPartitionScanner;
import com.aptana.editor.common.text.rules.SubPartitionScanner;
import com.aptana.editor.haml.HAMLSourceConfiguration;
import com.aptana.editor.ruby.RubySourceConfiguration;
/**
* @author Max Stepanov
*/
public class HAMLSubPartitionScanner extends CompositeSubPartitionScanner
{
private static final int TYPE_RUBY_EVALUATION = 1;
private static final int TYPE_RUBY_ATTRIBUTES = 2;
private static final String[] RUBY_EVALUATION_SWITCH_SEQUENCES = new String[] { "\r\n", "\n", "\r" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // $codepro.audit.disable platformSpecificLineSeparator
private static final String[] RUBY_ATTRIBUTES_SWITCH_SEQUENCES = new String[] { "}" }; //$NON-NLS-1$
private static final char COMMA = ',';
private static final char VERTICAL = '|';
private static final ISequenceBypassHandler RUBY_BYPASS_HANDLER = new ISequenceBypassHandler()
{
public boolean bypassSequence(ICharacterScanner characterScanner, char[] sequenceFound)
{
if (characterScanner.getColumn() > 0)
{
characterScanner.unread();
int c = characterScanner.read();
if (COMMA == c)
{
return true;
}
else if (VERTICAL == c)
{
char[][] newLineSequences = TextUtils.rsort(characterScanner.getLegalLineDelimiters());
int index = 0;
try
{
// skip found sequence
for (; index < sequenceFound.length; ++index)
{
characterScanner.read();
}
// search for newline, remember previous character to compare with vertical
int previous = 0;
while ((c = characterScanner.read()) != ICharacterScanner.EOF)
{
++index;
for (char[] sequence : newLineSequences)
{
if (c == sequence[0] && TextUtils.sequenceDetected(characterScanner, sequence, false))
{
return VERTICAL == previous;
}
}
previous = c;
}
}
finally
{
for (int j = index; j > 0; --j)
{
characterScanner.unread();
}
}
}
}
return false;
}
};
/**
*
*/
public HAMLSubPartitionScanner()
{
super(new ISubPartitionScanner[] {
new SubPartitionScanner(HAMLSourceConfiguration.getDefault().getPartitioningRules(),
HAMLSourceConfiguration.CONTENT_TYPES, new Token(HAMLSourceConfiguration.DEFAULT)),
RubySourceConfiguration.getDefault().createSubPartitionScanner(),
RubyAttributesSourceConfiguration.getDefault().createSubPartitionScanner() },
new IPartitionScannerSwitchStrategy[] {
new PartitionScannerSwitchStrategy(RUBY_EVALUATION_SWITCH_SEQUENCES, RUBY_BYPASS_HANDLER),
new PartitionScannerSwitchStrategy(RUBY_ATTRIBUTES_SWITCH_SEQUENCES) });
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.CompositeSubPartitionScanner#setLastToken(org.eclipse.jface.text.rules.IToken)
*/
@Override
public void setLastToken(IToken token)
{
super.setLastToken(token);
if (token == null)
{
return;
}
if (!(token.getData() instanceof String))
{
current = TYPE_DEFAULT;
return;
}
String contentType = (String) token.getData();
if (HAMLSourceConfiguration.RUBY_EVALUATION.equals(contentType))
{
current = TYPE_RUBY_EVALUATION;
super.setLastToken(null);
}
else if (HAMLSourceConfiguration.RUBY_ATTRIBUTES.equals(contentType))
{
current = TYPE_RUBY_ATTRIBUTES;
super.setLastToken(null);
}
else if (HAMLSourceConfiguration.DEFAULT.equals(contentType)
|| IDocument.DEFAULT_CONTENT_TYPE.equals(contentType))
{
current = TYPE_DEFAULT;
}
else
{
for (int i = 0; i < subPartitionScanners.length; ++i)
{
if (subPartitionScanners[i].hasContentType(contentType))
{
current = i;
break;
}
}
}
}
}