package com.aptana.ide.editors.haml.internal;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import com.aptana.ide.core.builder.BuildContext;
import com.aptana.ide.core.builder.BuildParticipant;
import com.aptana.ide.editor.css.CSSColors;
import com.aptana.ide.editor.css.IIndexConstants;
import com.aptana.ide.index.core.Index;
import com.aptana.ide.index.core.IndexManager;
public class HAMLandSassIndexer extends BuildParticipant
{
private Index fIndex;
private Set<Index> indices;
private static final Pattern SASS_COLOR_PATTERN = Pattern.compile("#([a-f0-9A-F]{6}|[a-f0-9A-F]{3})");
private static final Pattern SASS_CLASS_PATTERN = Pattern.compile("\\s*(\\.[\\w\\-]+)\\s+");
private static final Pattern SASS_ID_PATTERN = Pattern.compile("\\s*(#[\\w\\-]+)\\s+");
private static final Pattern HAML_CLASS_PATTERN = Pattern.compile("[\\w\\s]*(\\.[\\w\\-]+)");
private static final Pattern HAML_ID_PATTERN = SASS_ID_PATTERN;
public HAMLandSassIndexer()
{
indices = new HashSet<Index>();
}
@Override
public void buildStarting(List<BuildContext> contexts, boolean isBatch, IProgressMonitor monitor)
{
indices.clear();
}
@Override
public void build(BuildContext context, IProgressMonitor monitor)
{
String extension = context.getFile().getFileExtension();
if (extension != null && extension.equalsIgnoreCase("sass"))
{
indexSASS(context);
}
else if (extension != null && extension.equalsIgnoreCase("haml"))
{
indexHAML(context);
}
}
@Override
public void buildFinishing(IProgressMonitor monitor)
{
// Save the indexes now (so it gets saved to disk!)
saveModifiedIndices();
indices.clear();
}
private void saveModifiedIndices()
{
for (Index index : indices)
{
try
{
if (index != null)
index.save();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void indexHAML(BuildContext context)
{
String src = context.getContents();
// Index classes
Matcher m = HAML_CLASS_PATTERN.matcher(src);
while (m.find())
{
String match = m.group(1);
if (isMeasurement(match))
continue;
addIndex(context, IIndexConstants.CSS_CLASS, match.substring(1));
}
// Index IDs
m = HAML_ID_PATTERN.matcher(src);
while (m.find())
{
String match = m.group(1);
if (isColor(match))
continue;
addIndex(context, IIndexConstants.CSS_IDENTIFIER, match.substring(1));
}
}
private boolean isColor(String value)
{
if (value == null || value.trim().length() == 0)
return false;
if (CSSColors.namedColorExists(value))
return true;
if (value.startsWith("#") && (value.length() == 4 || value.length() == 7))
{
return SASS_COLOR_PATTERN.matcher(value).find();
}
return false;
}
private void addIndex(BuildContext context, String category, String word)
{
Index index = getIndex(context);
indices.add(index);
index.addEntry(category, word, context.getFile().getProjectRelativePath().toPortableString());
}
private void indexSASS(BuildContext context)
{
String src = context.getContents();
// Index colors
Matcher m = SASS_COLOR_PATTERN.matcher(src);
while (m.find())
{
String match = m.group();
if (!isColor(match))
continue;
addIndex(context, IIndexConstants.CSS_COLOR, CSSColors.to6CharHexWithLeadingHash(match));
}
// Index classes
m = SASS_CLASS_PATTERN.matcher(src);
while (m.find())
{
String match = m.group(1);
if (isMeasurement(match))
continue;
addIndex(context, IIndexConstants.CSS_CLASS, match.substring(1));
}
// Index IDs
m = SASS_ID_PATTERN.matcher(src);
while (m.find())
{
String match = m.group(1);
if (isColor(match))
continue;
addIndex(context, IIndexConstants.CSS_IDENTIFIER, match.substring(1));
}
}
private boolean isMeasurement(String match)
{
return match.length() >= 4 && Character.isDigit(match.charAt(1)) && match.endsWith("em");
}
private Index getIndex(BuildContext context)
{
if (fIndex == null)
{
IProject project = context.getFile().getProject();
fIndex = IndexManager.getInstance().getIndex(project.getFullPath().toPortableString());
}
return fIndex;
}
@Override
public void cleanStarting(IProject project)
{
Index index = IndexManager.getInstance().getIndex(project.getFullPath().toPortableString());
index.removeCategories(IIndexConstants.CSS_CLASS, IIndexConstants.CSS_IDENTIFIER);
}
@Override
public boolean isActive(IProject project)
{
return true;
}
}