public class MarkOccurrencesHighlighter implements CaretListener {

  private static final AttributeSet defaultColors =
      AttributesUtilities.createImmutable(StyleConstants.Background, new Color(236, 235, 163));

  private final OffsetsBag bag;

  private JTextComponent comp;
  private final WeakReference<Document> weakDoc;

  private final RequestProcessor rp;
  private static final int REFRESH_DELAY = 100;
  private RequestProcessor.Task lastRefreshTask;

  public MarkOccurrencesHighlighter(Document doc) {
    rp = new RequestProcessor(MarkOccurrencesHighlighter.class);
    bag = new OffsetsBag(doc);
    weakDoc = new WeakReference<Document>((Document) doc);
    DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get());
    if (dobj != null) {
      EditorCookie pane = dobj.getLookup().lookup(EditorCookie.class);
      JEditorPane[] panes = pane.getOpenedPanes();
      if (panes != null && panes.length > 0) {
        comp = panes[0];
        comp.addCaretListener(this);
      }
    }
  }

  @Override
  public void caretUpdate(CaretEvent e) {
    bag.clear();
    setupAutoRefresh();
  }

  public void setupAutoRefresh() {
    if (lastRefreshTask == null) {
      lastRefreshTask =
          rp.create(
              new Runnable() {
                @Override
                public void run() {
                  String selection = comp.getSelectedText();
                  if (selection != null) {
                    Pattern p = Pattern.compile(selection);
                    Matcher m = p.matcher(comp.getText());
                    while (m.find() == true) {
                      int startOffset = m.start();
                      int endOffset = m.end();
                      bag.addHighlight(startOffset, endOffset, defaultColors);
                    }
                  }
                }
              });
    }
    lastRefreshTask.schedule(REFRESH_DELAY);
  }

  public OffsetsBag getHighlightsBag() {
    return bag;
  }
}
/** @author SessonaD */
public class OccurrencesHighlighter implements CaretListener {

  private static final AttributeSet defaultColors =
      AttributesUtilities.createImmutable(StyleConstants.Background, new Color(236, 235, 163));
  private final OffsetsBag bag;
  private JTextComponent comp;
  private final WeakReference<Document> weakDoc;
  private final RequestProcessor rp;
  private static final int DELAY = 100;
  private RequestProcessor.Task refreshTask;
  static List<String> keywords = GherkinCompletionNames.getKeywordsFormatching();

  public OccurrencesHighlighter(Document doc) {
    rp = new RequestProcessor(OccurrencesHighlighter.class);
    bag = new OffsetsBag(doc);
    weakDoc = new WeakReference<Document>((Document) doc);
    DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get());
    if (dobj != null) {
      EditorCookie pane = dobj.getLookup().lookup(EditorCookie.class);
      JEditorPane[] panes = pane.getOpenedPanes();
      if (panes != null && panes.length > 0) {
        comp = panes[0];
        comp.addCaretListener(this);
      }
    }
  }

  @Override
  public void caretUpdate(CaretEvent e) {
    bag.clear();
    setupAutoRefresh();
  }

  public void setupAutoRefresh() {
    if (refreshTask == null) {
      refreshTask =
          rp.create(
              new Runnable() {
                @Override
                public void run() {
                  String selection = comp.getSelectedText();
                  if (selection != null && !isKeyword(selection)) {
                    Pattern p = Pattern.compile(selection);
                    Matcher m = p.matcher(comp.getText());
                    // for some reason the matcher skips the \n chars
                    // so i am finding them all and subtracting them
                    // from the resulting start and end offset.
                    while (m.find() == true) {
                      int startOffset = m.start();
                      int numberOfLineFeed =
                          comp.getText().substring(0, startOffset).split("\n").length - 1;
                      startOffset = startOffset - numberOfLineFeed;
                      int endOffset = m.end() - numberOfLineFeed;
                      bag.addHighlight(startOffset, endOffset, defaultColors);
                    }
                  }
                }
              });
      refreshTask.setPriority(Thread.MIN_PRIORITY);
    }
    refreshTask.schedule(DELAY);
  }

  public boolean isKeyword(String selection) {
    return keywords.contains(selection);
  }

  public OffsetsBag getHighlightsBag() {
    return bag;
  }
}