Package com.redcareditor.mate

Source Code of com.redcareditor.mate.Scope

package com.redcareditor.mate;

import java.util.List;
import java.util.ArrayList;

import com.redcareditor.mate.document.MateDocument;
import com.redcareditor.mate.document.MateTextLocation;
import com.redcareditor.mate.document.swt.SwtMateTextLocation;
import com.redcareditor.mate.document.MateTextRange;
import com.redcareditor.onig.Match;
import com.redcareditor.onig.Rx;
import com.redcareditor.theme.ThemeSetting;

public class Scope implements Comparable<Scope>{
  private MateText mateText;
 
  private MateDocument document;
 
  private MateTextRange range;
  private MateTextRange innerRange;
 
  public String name;
  public Pattern pattern;
 
  public boolean isOpen;
  public boolean isCapture;
  public boolean isCloseCapture;
 
  public Match openMatch;
  public Match closeMatch;
 
  public Rx closingRegex;
  public String beginMatchString;
  public String endMatchString;
 
  public Scope parent;
  public ArrayList<Scope> children;
 
  public String bgColour;
  public String fgColour;
 
  StringBuilder prettyString;
  int indent;
 
  public ThemeSetting themeSetting;
 
  public Scope(MateText mt, String name) {
    this.mateText = mt;
    this.name = name;
    this.children = new ArrayList<Scope>();
    this.document = mt.getMateDocument();
   
    this.range = document.getTextRange();
    this.innerRange = document.getTextRange();
  }
 
  public void setMateText(MateText mateText) {
    this.mateText = mateText;
    this.document = mateText.getMateDocument();
    this.range.setDocument(this.document);
    if (this.innerRange != null) {
      this.innerRange.setDocument(this.document);
    }
   
    for (Scope child : children)
      child.setMateText(mateText);
  }
 
  static public Scope findContainingScopeOld(ArrayList<Scope> scopes, MateTextLocation location) {
    for (Scope child : scopes) {
      if (child.contains(location)) {
        return child;
      }
    }
    return null;
  }
 
  static int indexOfEarliestAfter(ArrayList<Scope> scopes, int offset) {
    if (offset == 0) {
      if (scopes.size() > 0)
        return 0;
      else
        return -1;
    }
    int ix = indexOfLatestBefore(scopes, offset - 1);
    int c = ix + 1;
    if (c == scopes.size())
      return -1;
    return c;
  }
 
  static int indexOfLatestBefore(ArrayList<Scope> scopes, int offset) {
    int high = scopes.size(), low = -1, probe, probeStart;
    if (high == 0)
      return -1;
    int bestProbe = 0;
    int bestStart = ((SwtMateTextLocation) scopes.get(0).getStart()).offset;
    if (bestStart > offset)
      return -1;
    Scope scope;
    while (high - low > 1) {
      probe = (low + high) >>> 1;
      scope = scopes.get(probe);
      probeStart = ((SwtMateTextLocation) scope.getStart()).offset;
      //System.out.printf("low: %d high: %d diff: %d probe: %d value: %d\n", low, high, high - low, probe, probeStart);
      if (probeStart <= offset) {
        low = probe;
        bestStart = probeStart;
        bestProbe = probe;
      }
      else {
        high = probe;
      }
    }
    if (bestStart <= offset)
      return bestProbe;
    else
      return -1;
  }
 
  static public Scope findContainingScopeNew(ArrayList<Scope> scopes, int offset) {
    //System.out.printf("findContainingScopeNew(offset: %d)\n", offset);
    int ix = indexOfLatestBefore(scopes, offset);
    if (ix == -1)
      return null;
    Scope scope = scopes.get(ix);
    int scopeStart = ((SwtMateTextLocation) scope.getStart()).offset;
    if (scopeStart <= offset) {
      int scopeEnd = ((SwtMateTextLocation) scope.getEnd()).offset;
      if (scopeEnd > offset) {
        return scope;
      }
    }
    return null;
  }

  public Scope scopeAt(int line, int lineOffset) {
    MateTextLocation location = document.getTextLocation(line, lineOffset);
    Scope r = null;   
    if (getStart().compareTo(location) <= 0 || parent == null) {
      if (isOpen || getEnd().compareTo(location) >= 0) {
        Scope containingChildNew = Scope.findContainingScopeNew(children, ((SwtMateTextLocation) location).offset);
        //Scope containingChildOld = Scope.findContainingScopeOld(children, location);
        //if (containingChildNew != containingChildOld) {
        //  System.out.printf("scopeAt(%d, %d)\n", line, lineOffset);
        //  System.out.printf("containingChild differs %s -> %s\n",
        //    (containingChildOld == null ? "none" : containingChildOld.name),
        //    (containingChildNew == null ? "none" : containingChildNew.name)
        //  );
        //  System.out.printf(pretty(2));
        //}
        if (containingChildNew != null)
          r = containingChildNew.scopeAt(line, lineOffset);
        else
          r = this;
      }
    }
    return r;
  }
 
  public void clearFrom(int offset) {
    //System.out.printf("clearFrom(%d) children: %d\n", offset, children.size());
    int ix = indexOfLatestBefore(children, offset);
    //System.out.printf("  ix: %d\n", ix);
    if (ix == -1)
      return;
    Scope scope = children.get(ix);
    int scopeStart = scope.getStart().getOffset();
    //System.out.printf("  scopeStart: %d\n", scopeStart);
    if (scopeStart < offset) {
      ix = ix + 1;
      int scopeEnd = scope.getEnd().getOffset();
      if (scopeEnd > offset)
        scope.clearFrom(offset);
    }
    if (ix <= children.size() - 1) {
      //System.out.printf("  range: %d - %d\n", ix, children.size());
      ((List<Scope>) children).subList(ix, children.size()).clear();
    }
    if (getEnd().getOffset() > offset) {
      removeEnd();
      isOpen = true;
    }
  }
 
  public int compareTo(Scope o) {
    if(getStart().compareTo(o.getStart()) == 0){
      return getEnd().compareTo(o.getEnd());
    }
    return getStart().compareTo(o.getStart());
  }

  public Scope containingDoubleScope(int lineIx) {
    Scope scope = this;
    while ((scope.pattern instanceof SinglePattern ||
            scope.isCapture ||
            (scope.getStart().getLine() == lineIx && scope.getStart().getLineOffset() == 0)) &&
           scope.parent != null) {
      scope = scope.parent;
    }
    return scope;
  }
 
  public boolean surfaceIdenticalTo(Scope other) {
    if (surfaceIdenticalToModuloEnding(other) &&
        getEnd().equals(other.getEnd()) &&
        getInnerEnd().equals(other.getInnerEnd()) &&
        beginMatchString.equals(other.beginMatchString)) {
      return true;
    }
    return false;
  }

  public boolean surfaceIdenticalToModuloEnding(Scope other) {
      //System.out.printf("name: %s; other.name: %s\n", name, other.name);
      //if (getStart() == null) {
      //  System.out.printf("getStart() is null");
      //}
    if (
         ( (name == null && other.name == null) || (name != null && name.equals(other.name)) ) &&
        pattern == other.pattern &&
        getStart().equals(other.getStart()) &&
        getInnerStart().equals(other.getInnerStart()) &&
        beginMatchString.equals(other.beginMatchString)) {
      return true;
    }
    return false;
  }

  public ArrayList<Scope> scopesOnLine(int lineIx) {
    ArrayList<Scope> scopes = new ArrayList<Scope>();
    if (getStart().getLine() <= lineIx && getEnd().getLine() >= lineIx)
      scopes.add(this);
    childScopesOnLine(lineIx, scopes);
    return scopes;
  }
 
  public void childScopesOnLine(int lineIx, ArrayList<Scope> scopes) {
    for (Scope child : children) {
      if (child.getStart().getLine() <= lineIx && child.getEnd().getLine() >= lineIx) {
        scopes.add(child);
        child.childScopesOnLine(lineIx, scopes);
      }
    }
  }
 
  public ArrayList<Scope> scopesBetween(int startOffset, int endOffset) {
    ArrayList<Scope> scopes = new ArrayList<Scope>();
    if (getStart().getOffset() < endOffset && getEnd().getOffset() >= startOffset)
      scopes.add(this);
    childScopesBetween(startOffset, endOffset, scopes);
    return scopes;
  }
 
  public void childScopesBetween(int startOffset, int endOffset, ArrayList<Scope> scopes) {
    for (Scope child : children) {
      if (child.getStart().getOffset() < endOffset && child.getEnd().getOffset() >= startOffset) {
        scopes.add(child);
        child.childScopesBetween(startOffset, endOffset, scopes);
      }
    }
  }
 
  public boolean overlapsWith(Scope other) {
    // sd1    +---
    // sd2  +---
    if (getStart().compareTo(other.getStart()) >= 0) {
      if (getStart().compareTo(other.getEnd()) < 0) {
        return true;
      }
      return false;
    }

    // sd1 +---
    // sd2   +---
    if (getEnd().compareTo(other.getStart()) > 0) {
      return true;
    }
    return false;
  }

  public void addChild(Scope newChild) {
    if (children.size() == 0){
      children.add(newChild);
      return;
    }
   
    int newChildStartOffset = newChild.getStart().getOffset();

    if (children.get(0).getStart().getOffset() > newChildStartOffset){
      children.add(0, newChild);
      return;
    }

    int insertIx = 0;
    int ix = 1;
    Scope lastChild = children.get(children.size() - 1);
   
    if (lastChild.getStart().getOffset() <= newChildStartOffset) {
      insertIx = children.size();
    }
    else {
      for (Scope child : children) {
        if (child.getStart().getOffset() <= newChildStartOffset) {
          insertIx = ix;
        }
        ix++;
      }
    }
    children.add(insertIx, newChild);
  }
 
  public void removeChild(Scope child) {
    children.remove(child);
  }
 
  public Scope firstChildAfter(MateTextLocation location) {
    if (children.size() == 0)
      return null;
     
    int offset = location.getOffset();
    int ix = indexOfEarliestAfter(children, offset);
    Scope r = null;
    if (ix == -1) {
      return null;
    }
    else {
      return children.get(ix);
    }
  }
 
  public void printScopeRanges(String title, ArrayList<Scope> scopes) {
    System.out.printf("%s: ", title);
    for (Scope s : scopes) {
      System.out.printf("%d-%d, ", s.getStart().getOffset(), s.getEnd().getOffset());
    }
    System.out.printf("\n");
  }
 
  public ArrayList<Scope> deleteAnyBetweenNotIn(int startOffset, int endOffset, ArrayList<Scope> scopes) {
    //System.out.printf("deleteAnyBetweenNotIn(%d, %d)\n", startOffset, endOffset);
    //printScopeRanges("  children", children);
    //printScopeRanges("  safe", scopes);
    ArrayList<Scope> removedScopes = new ArrayList<Scope>();
    int ix, childStart;
   
    int ixEnd   = indexOfLatestBefore(children, endOffset);
    if (ixEnd == -1)
      return removedScopes;
    int ixStart = indexOfEarliestAfter(children, startOffset);
    if (ixStart == -1)
      ix = 0;
    else
      ix = ixStart;
    //System.out.printf("  start: %d, end: %d\n", ixStart, ixEnd);
    while (ix <= ixEnd) {
      Scope child = children.get(ix);
      childStart = child.getStart().getOffset();
      //System.out.printf("    checking: %d-%d\n", child.getStart().getOffset(), child.getEnd().getOffset());
      if (childStart >= startOffset && childStart < endOffset && !scopes.contains(child)) {
        removedScopes.add(child);
      }
      ix++;
    }
    children.removeAll(removedScopes);
    //printScopeRanges("  removedScopes", removedScopes);
    return removedScopes;
  }
 
  public void setStartPos(int line, int lineOffset, boolean hasLeftGravity) {
    MateTextLocation start = document.getTextLocation(line, lineOffset);
    this.range.setStart(start);
    document.addTextLocation("scopes", start);
  }

  public void setInnerStartPos(int line, int lineOffset, boolean hasLeftGravity) {
    MateTextLocation innerStart = document.getTextLocation(line, lineOffset);
    this.innerRange.setStart(innerStart);
    document.addTextLocation("scopes", innerStart);
  }

  public void setInnerEndPos(int line, int lineOffset, boolean c) {
    MateTextLocation innerEnd = document.getTextLocation(line, lineOffset);
    this.innerRange.setEnd(innerEnd);
    document.addTextLocation("scopes", innerEnd);
  }

  public void setEndPos(int line, int lineOffset, boolean c) {
    MateTextLocation end = document.getTextLocation(line, lineOffset);
    this.range.setEnd(end);
    document.addTextLocation("scopes", end);
  }
 
  public void removeEnd() {
    this.range.clearEnd();
    this.innerRange.clearEnd();
  }
 
  public int getLength(){
    return range.getLength();
  }
 
  public MateTextLocation getStart() {
    return range.getStart();
  }
 
  public MateTextLocation getEnd(){
    return range.getEnd();
  }

  public MateTextLocation getInnerStart(){
    return innerRange.getStart();
  }
   
  public MateTextLocation getInnerEnd(){
    return innerRange.getEnd();
  }
   
  public boolean contains(MateTextLocation location){
    return range.conatains(location);
  }

  public String hierarchyNames(boolean inner) {
    String selfName;
    // stdout.printf("'%s'.hierarchy_names(%s)\n", name, inner ? "true" : "false");
    if (pattern instanceof DoublePattern &&
        ((DoublePattern) pattern).contentName != null &&
        inner) {
      selfName = name + " " + ((DoublePattern) pattern).contentName;
    }
    else {
      selfName = name;
    }
    if (parent != null) {
      boolean next_inner;
      if (isCapture)
        next_inner = false;
      else
        next_inner = true;
      return parent.hierarchyNames(next_inner) + " " + selfName;
    }
    else {
      return selfName;
    }
  }

  public String pretty(int indent) {
    prettyString = new StringBuilder("");
    this.indent = indent;
    for (int i = 0; i < indent; i++)
      prettyString.append("  ");
    if (this.isCapture)
      prettyString.append("c");
    else
      prettyString.append("+");
   
    if (this.name != null)
      prettyString.append(" " + this.name);
    else
      prettyString.append(" " + "[noname]");
   
    if (this.pattern instanceof DoublePattern &&
        this.isCapture == false &&
        ((DoublePattern) this.pattern).contentName != null)
      prettyString.append(" " + ((DoublePattern) this.pattern).contentName);
    prettyString.append(" (");
    prettyString.append(String.format(
        "%d,%d",
        getStart().getLine(),
        getStart().getLineOffset()));
//    prettyString.append(getStart().getOffset());
    prettyString.append(")-(");
    prettyString.append(String.format(
        "%d,%d",
        getEnd().getLine(),
        getEnd().getLineOffset()));
//    prettyString.append(getEnd().getOffset());
    prettyString.append(")");
    prettyString.append((isOpen ? " open" : " closed"));
    prettyString.append("\n");

    this.indent += 1;
    for (Scope child : this.children) {
      prettyString.append(child.pretty(this.indent));
    }
   
    return prettyString.toString();
  }
 

  public String nearestBackgroundColour() {
    if (parent != null) {
      return parent.nearestBackgroundColour1();
    }
    return null;
  }

  public String nearestBackgroundColour1() {
    if (bgColour != null)
      return bgColour;
    if (parent != null) {
      return parent.nearestBackgroundColour1();
    }
    return null;
  }

  public String nearestForegroundColour() {
    if (parent != null) {
      return parent.nearestForegroundColour1();
    }
    return null;
  }

  public String nearestForegroundColour1() {
    if (fgColour != null)
      return fgColour;
    if (parent != null) {
      return parent.nearestForegroundColour1();
    }
    return null;
  }
 
  public int countDescendants() {
    int i = children.size();
    for (Scope child : children) {
      i += child.countDescendants();
    }
    return i;
  }
}


TOP

Related Classes of com.redcareditor.mate.Scope

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.