/*
* RegexpIndentRule.java
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2005 Slava Pestov
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.indent;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.text.Segment;
import org.gjt.sp.jedit.buffer.JEditBuffer;
import org.gjt.sp.jedit.syntax.Token;
import org.gjt.sp.jedit.syntax.TokenHandler;
import org.gjt.sp.jedit.syntax.TokenMarker;
/**
* @author Slava Pestov
* @version $Id: RegexpIndentRule.java 21831 2012-06-18 22:54:17Z ezust $
*/
public class RegexpIndentRule implements IndentRule
{
//{{{ RegexpIndentRule constructor
/**
* @param collapse If true, then if the next indent rule is
* an opening bracket, this rule will not increase indent.
*/
public RegexpIndentRule(String regexp, IndentAction prevPrev,
IndentAction prev, IndentAction thisLine, boolean collapse)
throws PatternSyntaxException
{
prevPrevAction = prevPrev;
prevAction = prev;
thisAction = thisLine;
this.regexp = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE );
this.collapse = collapse;
} //}}}
//{{{ apply() method
public void apply(JEditBuffer buffer, int thisLineIndex,
int prevLineIndex, int prevPrevLineIndex,
List<IndentAction> indentActions)
{
if(thisAction != null
&& lineMatches(buffer, thisLineIndex))
{
indentActions.add(thisAction);
}
if(prevAction != null
&& prevLineIndex != -1
&& lineMatches(buffer, prevLineIndex))
{
indentActions.add(prevAction);
if (collapse)
indentActions.add(IndentAction.PrevCollapse);
}
if(prevPrevAction != null
&& prevPrevLineIndex != -1
&& lineMatches(buffer, prevPrevLineIndex))
{
indentActions.add(prevPrevAction);
if (collapse)
indentActions.add(IndentAction.PrevPrevCollapse);
}
} //}}}
//{{{ toString() method
public String toString()
{
return getClass().getName() + '[' + regexp + ']';
} //}}}
private IndentAction prevPrevAction, prevAction, thisAction;
private Pattern regexp;
private boolean collapse;
//{{{ class TokenFilter
/**
* A filter which removes non syntactic characters in comments
* or literals which might confuse regexp matchings for indent.
*/
private static class TokenFilter implements TokenHandler
{
public StringBuilder result;
public TokenFilter(int originalLength)
{
result = new StringBuilder(originalLength);
}
public void handleToken(Segment seg
, byte id, int offset, int length
, TokenMarker.LineContext context)
{
// Avoid replacing an empty token into a non empty
// string.
if (length <= 0)
{
return;
}
switch (id)
{
case Token.COMMENT1:
case Token.COMMENT2:
case Token.COMMENT3:
case Token.COMMENT4:
// Replace any comments to a white space
// so that they are simply ignored.
result.append(' ');
break;
case Token.LITERAL1:
case Token.LITERAL2:
case Token.LITERAL3:
case Token.LITERAL4:
// Replace any literals to a '0' which means
// a simple integer literal in most programming
// languages.
result.append('0');
break;
default:
result.append(seg.array
, seg.offset + offset
, length);
break;
}
}
public void setLineContext(TokenMarker.LineContext lineContext)
{
}
} //}}}
//{{{ lineMatches() method
private boolean lineMatches(JEditBuffer buffer, int lineIndex)
{
TokenFilter filter
= new TokenFilter(buffer.getLineLength(lineIndex));
buffer.markTokens(lineIndex, filter);
return regexp.matcher(filter.result).matches();
} //}}}
}