/**
* 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.ruby;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.jface.text.rules.MultiLineRule;
import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.source.ISourceViewer;
import com.aptana.editor.common.AbstractThemeableEditor;
import com.aptana.editor.common.CommonEditorPlugin;
import com.aptana.editor.common.CommonUtil;
import com.aptana.editor.common.IPartitioningConfiguration;
import com.aptana.editor.common.ISourceViewerConfiguration;
import com.aptana.editor.common.scripting.IContentTypeTranslator;
import com.aptana.editor.common.scripting.QualifiedContentType;
import com.aptana.editor.common.text.SingleTokenScanner;
import com.aptana.editor.common.text.rules.CommentScanner;
import com.aptana.editor.common.text.rules.ISubPartitionScanner;
import com.aptana.editor.common.text.rules.PartitionerSwitchingIgnoreRule;
import com.aptana.editor.common.text.rules.SubPartitionScanner;
import com.aptana.editor.common.text.rules.ThemeingDamagerRepairer;
import com.aptana.editor.ruby.internal.contentassist.RubyCommentContentAssistProcessor;
import com.aptana.editor.ruby.internal.contentassist.RubyContentAssistProcessor;
import com.aptana.editor.ruby.internal.contentassist.RubyDoubleQuotedStringContentAssistProcessor;
import com.aptana.editor.ruby.internal.contentassist.RubyRegexpContentAssistProcessor;
import com.aptana.editor.ruby.internal.text.LineContinuationDamagerRepairer;
import com.aptana.ruby.core.IRubyConstants;
/**
* @author Max Stepanov
* @author Michael Xia
*/
public class RubySourceConfiguration implements IPartitioningConfiguration, ISourceViewerConfiguration
{
// FIXME Move out the translations strings as constants in IRubyConstants
public static final String PREFIX = "__rb_"; //$NON-NLS-1$
public static final String DEFAULT = "__rb" + IDocument.DEFAULT_CONTENT_TYPE; //$NON-NLS-1$
public static final String SINGLE_LINE_COMMENT = PREFIX + "singleline_comment"; //$NON-NLS-1$
public static final String MULTI_LINE_COMMENT = PREFIX + "multiline_comment"; //$NON-NLS-1$
public static final String REGULAR_EXPRESSION = PREFIX + "regular_expression"; //$NON-NLS-1$
public static final String COMMAND = PREFIX + "command"; //$NON-NLS-1$
public static final String STRING_SINGLE = PREFIX + "string_single"; //$NON-NLS-1$
public static final String STRING_DOUBLE = PREFIX + "string_double"; //$NON-NLS-1$
public static final String[] CONTENT_TYPES = new String[] { DEFAULT, SINGLE_LINE_COMMENT, MULTI_LINE_COMMENT,
REGULAR_EXPRESSION, COMMAND, STRING_SINGLE, STRING_DOUBLE };
private static final String[] SPELLING_CONTENT_TYPES = new String[] { SINGLE_LINE_COMMENT, MULTI_LINE_COMMENT,
STRING_SINGLE, STRING_DOUBLE };
private static final String[][] TOP_CONTENT_TYPES = new String[][] { { IRubyConstants.CONTENT_TYPE_RUBY } };
private final IPredicateRule[] partitioningRules = new IPredicateRule[] {
new PartitionerSwitchingIgnoreRule(new EndOfLineRule("#", getToken(SINGLE_LINE_COMMENT))), //$NON-NLS-1$
new PartitionerSwitchingIgnoreRule(new MultiLineRule(
"=begin", "=end", getToken(MULTI_LINE_COMMENT), (char) 0, true)), //$NON-NLS-1$ //$NON-NLS-2$
new SingleLineRule("/", "/", getToken(REGULAR_EXPRESSION), '\\'), //$NON-NLS-1$ //$NON-NLS-2$
new SingleLineRule("\"", "\"", getToken(STRING_DOUBLE), '\\'), //$NON-NLS-1$ //$NON-NLS-2$
new SingleLineRule("\'", "\'", getToken(STRING_SINGLE), '\\') }; //$NON-NLS-1$ //$NON-NLS-2$
private static RubySourceConfiguration instance;
static
{
IContentTypeTranslator c = CommonEditorPlugin.getDefault().getContentTypeTranslator();
c.addTranslation(new QualifiedContentType(IRubyConstants.CONTENT_TYPE_RUBY), new QualifiedContentType(
"source.ruby.rails")); //$NON-NLS-1$ // FIXME Should just be source.ruby! Rails bundle should contribute the more specific scope
c.addTranslation(new QualifiedContentType(STRING_SINGLE), new QualifiedContentType(
IRubyConstants.SINGLE_QUOTED_STRING_SCOPE));
c.addTranslation(new QualifiedContentType(STRING_DOUBLE), new QualifiedContentType(
IRubyConstants.DOUBLE_QUOTED_STRING_SCOPE));
c.addTranslation(new QualifiedContentType(SINGLE_LINE_COMMENT), new QualifiedContentType(
IRubyConstants.LINE_COMMENT_SCOPE));
c.addTranslation(new QualifiedContentType(MULTI_LINE_COMMENT), new QualifiedContentType(
IRubyConstants.BLOCK_COMMENT_SCOPE));
c.addTranslation(new QualifiedContentType(REGULAR_EXPRESSION), new QualifiedContentType(
"string.regexp.classic.ruby")); //$NON-NLS-1$
c.addTranslation(new QualifiedContentType(COMMAND), new QualifiedContentType("string.interpolated.ruby")); //$NON-NLS-1$
}
private RubySourceConfiguration()
{
}
public synchronized static RubySourceConfiguration getDefault()
{
if (instance == null)
{
instance = new RubySourceConfiguration();
}
return instance;
}
/*
* @see com.aptana.editor.common.IPartitioningConfiguration#getContentTypes()
*/
public String[] getContentTypes()
{
return CONTENT_TYPES;
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.ITopContentTypesProvider#getTopContentTypes()
*/
public String[][] getTopContentTypes()
{
return TOP_CONTENT_TYPES;
}
/* (non-Javadoc)
* @see com.aptana.editor.common.ISourceViewerConfiguration#getSpellingContentTypes()
*/
public String[] getSpellingContentTypes()
{
return SPELLING_CONTENT_TYPES;
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.IPartitioningConfiguration#getPartitioningRules()
*/
public IPredicateRule[] getPartitioningRules()
{
return partitioningRules;
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.IPartitioningConfiguration#createSubPartitionScanner()
*/
public ISubPartitionScanner createSubPartitionScanner()
{
return new SubPartitionScanner(partitioningRules, CONTENT_TYPES, getToken(DEFAULT));
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.IPartitioningConfiguration#getDocumentContentType(java.lang.String)
*/
public String getDocumentContentType(String contentType)
{
if (contentType.startsWith(PREFIX))
{
return IRubyConstants.CONTENT_TYPE_RUBY;
}
return null;
}
/*
* (non-Javadoc)
* @see
* com.aptana.editor.common.ISourceViewerConfiguration#setupPresentationReconciler(org.eclipse.jface.text.presentation
* .PresentationReconciler, org.eclipse.jface.text.source.ISourceViewer)
*/
public void setupPresentationReconciler(PresentationReconciler reconciler, ISourceViewer sourceViewer)
{
DefaultDamagerRepairer dr = new LineContinuationDamagerRepairer(getCodeScanner());
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setDamager(dr, DEFAULT);
reconciler.setRepairer(dr, DEFAULT);
dr = new ThemeingDamagerRepairer(getSingleLineCommentScanner());
reconciler.setDamager(dr, RubySourceConfiguration.SINGLE_LINE_COMMENT);
reconciler.setRepairer(dr, RubySourceConfiguration.SINGLE_LINE_COMMENT);
dr = new ThemeingDamagerRepairer(getMultiLineCommentScanner());
reconciler.setDamager(dr, RubySourceConfiguration.MULTI_LINE_COMMENT);
reconciler.setRepairer(dr, RubySourceConfiguration.MULTI_LINE_COMMENT);
dr = new ThemeingDamagerRepairer(getRegexpScanner());
reconciler.setDamager(dr, RubySourceConfiguration.REGULAR_EXPRESSION);
reconciler.setRepairer(dr, RubySourceConfiguration.REGULAR_EXPRESSION);
dr = new ThemeingDamagerRepairer(getCommandScanner());
reconciler.setDamager(dr, RubySourceConfiguration.COMMAND);
reconciler.setRepairer(dr, RubySourceConfiguration.COMMAND);
dr = new ThemeingDamagerRepairer(getSingleQuotedStringScanner());
reconciler.setDamager(dr, RubySourceConfiguration.STRING_SINGLE);
reconciler.setRepairer(dr, RubySourceConfiguration.STRING_SINGLE);
dr = new ThemeingDamagerRepairer(getDoubleQuotedStringScanner());
reconciler.setDamager(dr, RubySourceConfiguration.STRING_DOUBLE);
reconciler.setRepairer(dr, RubySourceConfiguration.STRING_DOUBLE);
}
/*
* (non-Javadoc)
* @see com.aptana.editor.common.ISourceViewerConfiguration#getContentAssistProcessor(com.aptana.editor.common.
* AbstractThemeableEditor, java.lang.String)
*/
public IContentAssistProcessor getContentAssistProcessor(AbstractThemeableEditor editor, String contentType)
{
if (DEFAULT.equals(contentType) || IDocument.DEFAULT_CONTENT_TYPE.equals(contentType))
{
return new RubyContentAssistProcessor(editor);
}
if (RubySourceConfiguration.STRING_DOUBLE.equals(contentType)
|| RubySourceConfiguration.COMMAND.equals(contentType)
||RubySourceConfiguration.STRING_SINGLE.equals(contentType))
{
return new RubyDoubleQuotedStringContentAssistProcessor(editor);
}
if (RubySourceConfiguration.REGULAR_EXPRESSION.equals(contentType))
{
return new RubyRegexpContentAssistProcessor(editor);
}
if (RubySourceConfiguration.MULTI_LINE_COMMENT.equals(contentType)
|| RubySourceConfiguration.SINGLE_LINE_COMMENT.equals(contentType))
{
return new RubyCommentContentAssistProcessor(editor);
}
// TODO Add special content assist processor for comments
return null;
}
private ITokenScanner getCodeScanner()
{
return new RubyCodeScanner();
}
private ITokenScanner getMultiLineCommentScanner()
{
return new CommentScanner(getToken(IRubyConstants.BLOCK_COMMENT_SCOPE));
}
private ITokenScanner getSingleLineCommentScanner()
{
return new CommentScanner(getToken(IRubyConstants.LINE_COMMENT_SCOPE));
}
private ITokenScanner getRegexpScanner()
{
return new RubyRegexpScanner();
}
private ITokenScanner getCommandScanner()
{
return new SingleTokenScanner(getToken("string.interpolated.ruby")); //$NON-NLS-1$
}
private ITokenScanner getSingleQuotedStringScanner()
{
return new SingleTokenScanner(getToken(IRubyConstants.SINGLE_QUOTED_STRING_SCOPE));
}
private ITokenScanner getDoubleQuotedStringScanner()
{
return new SingleTokenScanner(getToken(IRubyConstants.DOUBLE_QUOTED_STRING_SCOPE));
}
private static IToken getToken(String tokenName)
{
return CommonUtil.getToken(tokenName);
}
}