This commit is contained in:
jdf
2010-04-09 02:23:26 +00:00
parent edef85ba0b
commit 3b3b23d433
3 changed files with 140 additions and 111 deletions
+133
View File
@@ -0,0 +1,133 @@
package processing.app.syntax;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jonathan Feinberg <jdf@pobox.com>
*
*/
public class Brackets {
private volatile List<Integer> offsets = null;
public void invalidate() {
offsets = null;
}
public int findMatchingBracket(final String text, final int pos) {
if (offsets == null)
parse(text);
// find this bracket
int p;
for (p = 0; p < offsets.size(); p++)
if (offsets.get(p) == pos)
break;
if (p == offsets.size()) {
return -1;
}
final int direction;
final char alpha = text.charAt(offsets.get(p));
final char beta;
switch (alpha) {
case '(':
beta = ')';
direction = 1;
break;
case ')':
beta = '(';
direction = -1;
break;
case '[':
beta = ']';
direction = 1;
break;
case ']':
beta = '[';
direction = -1;
break;
case '{':
beta = '}';
direction = 1;
break;
case '}':
beta = '{';
direction = -1;
break;
default:
System.err.println("Unexpected char " + alpha + " at position " + p);
return -1;
}
int depth = 1;
for (p += direction; p >= 0 && p < offsets.size(); p += direction) {
final int offset = offsets.get(p);
final char c = text.charAt(offset);
if (c == alpha)
depth++;
else if (c == beta)
depth--;
if (depth == 0)
return offset;
}
return -1;
}
int pos;
private void parse(final String text) {
offsets = new ArrayList<Integer>();
final int len = text.length();
for (pos = 0; pos < len; pos++) {
final char c = text.charAt(pos);
if (c == '/' && (pos < len - 1)) {
final char d = text.charAt(++pos);
if (d == '/') {
readComment(text);
} else if (d == '*') {
readMLComment(text);
}
} else if (c == '"' || c == '\'') {
readString(text, c);
} else if (c == '{' || c == '[' || c == '(' || c == '}' || c == ']'
|| c == ')') {
offsets.add(pos);
}
}
}
private void readString(final String text, final char q) {
final int len = text.length();
for (pos++; pos < len; pos++) {
final char c = text.charAt(pos);
if (c == q) {
return;
}
if (c == '\\') {
pos++;
}
}
}
private void readComment(final String text) {
final int len = text.length();
for (pos++; pos < len; pos++)
if (text.charAt(pos) == '\n') {
pos++;
return;
}
}
private void readMLComment(final String text) {
final int len = text.length();
for (pos++; pos < len; pos++) {
final char c = text.charAt(pos);
if (c == '*' && (pos < len - 1)) {
pos++;
final char d = text.charAt(pos);
if (d == '/') {
return;
}
}
}
}
}
@@ -129,6 +129,8 @@ public class JEditTextArea extends JComponent
}
});
}
private Brackets bracketHelper = new Brackets();
/**
* Inline Input Method Support for Japanese.
@@ -1714,8 +1716,8 @@ public class JEditTextArea extends JComponent
try
{
int offset = TextUtilities.findMatchingBracket(
document,newCaretPosition - 1);
int offset = bracketHelper.findMatchingBracket(document.getText(0,
document.getLength()), newCaretPosition - 1);
if(offset != -1)
{
bracketLine = getLineOfOffset(offset);
@@ -1733,6 +1735,8 @@ public class JEditTextArea extends JComponent
protected void documentChanged(DocumentEvent evt)
{
bracketHelper.invalidate();
DocumentEvent.ElementChange ch =
evt.getChange(document.getDefaultRootElement());
@@ -2112,7 +2116,7 @@ public class JEditTextArea extends JComponent
return;
try {
int bracket = TextUtilities.findMatchingBracket(document,
int bracket = bracketHelper.findMatchingBracket(document.getText(0, document.getLength()),
Math.max(0,dot - 1));
if (bracket != -1) {
int mark = getMarkPosition();
@@ -9,7 +9,6 @@
package processing.app.syntax;
import javax.swing.text.*;
/**
* Class with several utility functions used by the text area component.
@@ -18,113 +17,6 @@ import javax.swing.text.*;
*/
public class TextUtilities
{
/**
* Returns the offset of the bracket matching the one at the
* specified offset of the document, or -1 if the bracket is
* unmatched (or if the character is not a bracket).
* @param doc The document
* @param offset The offset
* @exception BadLocationException If an out-of-bounds access
* was attempted on the document text
*/
public static int findMatchingBracket(Document doc, int offset)
throws BadLocationException
{
if(doc.getLength() == 0)
return -1;
char c = doc.getText(offset,1).charAt(0);
char cprime; // c` - corresponding character
boolean direction; // true = back, false = forward
switch(c)
{
case '(': cprime = ')'; direction = false; break;
case ')': cprime = '('; direction = true; break;
case '[': cprime = ']'; direction = false; break;
case ']': cprime = '['; direction = true; break;
case '{': cprime = '}'; direction = false; break;
case '}': cprime = '{'; direction = true; break;
default: return -1;
}
int count;
// How to merge these two cases is left as an exercise
// for the reader.
// Go back or forward
if(direction)
{
// Count is 1 initially because we have already
// `found' one closing bracket
count = 1;
// Get text[0,offset-1];
String text = doc.getText(0,offset);
// Scan backwards
for(int i = offset - 1; i >= 0; i--)
{
// If text[i] == c, we have found another
// closing bracket, therefore we will need
// two opening brackets to complete the
// match.
char x = text.charAt(i);
if(x == c)
count++;
// If text[i] == cprime, we have found a
// opening bracket, so we return i if
// --count == 0
else if(x == cprime)
{
if(--count == 0)
return i;
}
}
}
else
{
// Count is 1 initially because we have already
// `found' one opening bracket
count = 1;
// So we don't have to + 1 in every loop
offset++;
// Number of characters to check
int len = doc.getLength() - offset;
// Get text[offset+1,len];
String text = doc.getText(offset,len);
// Scan forwards
for(int i = 0; i < len; i++)
{
// If text[i] == c, we have found another
// opening bracket, therefore we will need
// two closing brackets to complete the
// match.
char x = text.charAt(i);
if(x == c)
count++;
// If text[i] == cprime, we have found an
// closing bracket, so we return i if
// --count == 0
else if(x == cprime)
{
if(--count == 0)
return i + offset;
}
}
}
// Nothing found
return -1;
}
/**
* Locates the start of the word at the specified position.
* @param line The text