DeepIndentRule.java :  » Swing-Library » jEdit-4.3.1 » org » gjt » sp » jedit » indent » Java Open Source

Java Open Source » Swing Library » jEdit 4.3.1 
jEdit 4.3.1 » org » gjt » sp » jedit » indent » DeepIndentRule.java
/*
 * DeepIndentRule.java
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 2006 Matthieu Casanova
 *
 * 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 org.gjt.sp.jedit.TextUtilities;
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;

import java.util.List;
import java.util.Stack;
import javax.swing.text.Segment;

/**
 * Deep indent rule.
 *
 * @author Matthieu Casanova
 * @version $Id: DeepIndentRule.java 13045 2008-07-11 06:48:37Z vanza $
 */
public class DeepIndentRule implements IndentRule
{
  private final char openChar;
  private final char closeChar;

  public DeepIndentRule(char openChar, char closeChar)
  {
    this.openChar = openChar;
    this.closeChar = closeChar;
  }

  //{{{ apply() method
  public void apply(JEditBuffer buffer, int thisLineIndex,
        int prevLineIndex, int prevPrevLineIndex,
        List<IndentAction> indentActions)
  {
    if (prevLineIndex == -1)
      return;

    int lineIndex = prevLineIndex;
    int oldLineIndex = lineIndex;
    CharSequence lineText = buffer.getLineSegment(lineIndex);
    int searchPos = -1;
    while (true)
    {
      if (lineIndex != oldLineIndex)
      {
        lineText = buffer.getLineSegment(lineIndex);
        oldLineIndex = lineIndex;
      }
      Parens parens = new Parens(buffer, lineIndex, searchPos);

      // No unmatched parens on prev line.
      if (parens.openOffset == -1 && parens.closeOffset == -1)
      {
        // Try prev-prev line if present.
        if (prevPrevLineIndex != -1) {
          searchPos = -1;
          lineIndex = prevPrevLineIndex;
          prevPrevLineIndex = -1;
          continue;
        }
        return;
      }

      // There's an unmatched open parenthesis - we want to
      // align according to its position.
      if (parens.closeOffset == -1)
      {
        // recalculate column (when using tabs instead of spaces)
        int indent = parens.openOffset + getIndent(lineText, buffer.getTabSize()) - lineText.length();
        indentActions.clear();
        indentActions.add(new IndentAction.AlignParameter(indent));
        return;
      }

      // There's an unmatched closed parenthesis - find the
      // matching parenthesis and start looking from there again.
      int openParenOffset = TextUtilities.findMatchingBracket(buffer, lineIndex, parens.closeOffset);
      if (openParenOffset >= 0)
      {
        // Avoid falling back to the prev-prev line in this case.
        prevPrevLineIndex = -1;
        lineIndex = buffer.getLineOfOffset(openParenOffset);
        searchPos = openParenOffset - buffer.getLineStartOffset(lineIndex) - 1;
        if (searchPos < 0)
          break;
      }
      else
        break;
    }
  } //}}}


  /**
   * Returns the length of the string as if it were indented with
   * spaces instead of tabs.
   */
  private int getIndent(CharSequence line, int tabSize)
  {
    int cnt = 0;
    for (int i = 0;  i < line.length(); i++)
    {
      if (line.charAt(i) == '\t')
      {
        cnt += tabSize;
      }
      else
      {
        if (!Character.isWhitespace(line.charAt(i)))
        {
          cnt += (line.length() - i);
          break;
        }
        cnt++;
      }
    }
    return cnt;
  }


  /**
   * A token filter that looks for the position of the open and
   * close characters in the line being parsed. Characters inside
   * literals and comments are ignored.
   */
  private class Parens implements TokenHandler
  {
    int openOffset;
    int closeOffset;

    private int searchPos;
    private Stack<Integer> open;
    private Stack<Integer> close;

    Parens(JEditBuffer b, int line, int pos)
    {
      this.searchPos = pos;
      this.open = new Stack<Integer>();
      this.close = new Stack<Integer>();
      b.markTokens(line, this);
      openOffset = (open.isEmpty()) ? -1 : open.pop();
      closeOffset = (close.isEmpty()) ? -1 : close.pop();
    }

    public void handleToken(Segment seg,
          byte id,
          int offset,
          int length,
          TokenMarker.LineContext context)
    {
      if (length <= 0 ||
          (searchPos != -1 && searchPos < offset))
      {
        return;
      }

      if (searchPos != -1 && offset + length > searchPos)
      {
        length = searchPos - offset + 1;
      }

      switch (id)
      {
      case Token.COMMENT1:
      case Token.COMMENT2:
      case Token.COMMENT3:
      case Token.COMMENT4:
      case Token.LITERAL1:
      case Token.LITERAL2:
      case Token.LITERAL3:
      case Token.LITERAL4:
        /* Ignore comments and literals. */
        break;
      default:
        for (int i = offset; i < offset + length; i++)
        {
          if (seg.array[seg.offset + i] == openChar)
          {
            if (open.isEmpty() && !close.isEmpty())
              close.pop();
            else
              open.push(i);
          }
          else if (seg.array[seg.offset + i] == closeChar)
          {
            if (close.isEmpty() && !open.isEmpty())
              open.pop();
            else
              close.push(i);
          }
        }
        break;
      }
    }

    public void setLineContext(TokenMarker.LineContext lineContext)
    {
      /* Do nothing. */
    }

    @Override
    public String toString()
    {
      return "Parens(" + openOffset + ',' + closeOffset + ')';
    }
  } //}}}

}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.