2 * Copyright winterwell Mathematics Ltd.
\r
3 * @author Daniel Winterstein
\r
6 package winterwell.markdown.editors;
\r
8 import org.eclipse.core.runtime.Assert;
\r
9 import org.eclipse.jface.text.rules.ICharacterScanner;
\r
10 import org.eclipse.jface.text.rules.IRule;
\r
11 import org.eclipse.jface.text.rules.IToken;
\r
12 import org.eclipse.jface.text.rules.MultiLineRule;
\r
13 import org.eclipse.jface.text.rules.Token;
\r
18 * @author Daniel Winterstein
\r
20 public class EmphasisRule implements IRule {
\r
21 private static char[][] fDelimiters = null;
\r
22 private char[] fSequence;
\r
23 protected IToken fToken;
\r
26 public EmphasisRule(String marker, IToken token) {
\r
27 assert marker.equals("*") || marker.equals("_") || marker.equals("**")
\r
28 || marker.equals("***") || marker.equals("`") || marker.equals("``");
\r
29 Assert.isNotNull(token);
\r
30 fSequence = marker.toCharArray();
\r
34 // Copied from org.eclipse.jface.text.rules.PatternRule
\r
35 protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {
\r
36 for (int i = 1; i < sequence.length; i++) {
\r
37 int c = scanner.read();
\r
38 if (c == ICharacterScanner.EOF && eofAllowed) {
\r
40 } else if (c != sequence[i]) {
\r
41 // Non-matching character detected, rewind the scanner back to
\r
43 // Do not unread the first character.
\r
44 for (int j = i; j > 0; j--)
\r
53 * @see IRule#evaluate(ICharacterScanner)
\r
57 public IToken evaluate(ICharacterScanner scanner) {
\r
58 // Should be connected only on the right side
\r
60 boolean sawSpaceBefore = Character.isWhitespace(scanner.read());
\r
61 if (!sawSpaceBefore && scanner.getColumn() != 0) {
\r
62 return Token.UNDEFINED;
\r
65 int c = scanner.read();
\r
66 // Should be connected only on right side
\r
67 if (c != fSequence[0] || !sequenceDetected(scanner, fSequence, false)) {
\r
69 return Token.UNDEFINED;
\r
71 int readCount = fSequence.length;
\r
72 if (fDelimiters == null) {
\r
73 fDelimiters = scanner.getLegalLineDelimiters();
\r
75 // Start sequence detected
\r
76 int delimiterFound = 0;
\r
77 // Is it a list item marker, or just a floating *?
\r
78 if (sawSpaceBefore) {
\r
79 boolean after = Character.isWhitespace(scanner.read());
\r
85 while (delimiterFound < 2
\r
86 && (c = scanner.read()) != ICharacterScanner.EOF) {
\r
89 if (!sawSpaceBefore && c == fSequence[0]
\r
90 && sequenceDetected(scanner, fSequence, false)) {
\r
95 for (i = 0; i < fDelimiters.length; i++) {
\r
96 if (c == fDelimiters[i][0]
\r
97 && sequenceDetected(scanner, fDelimiters[i], true)) {
\r
102 if (i == fDelimiters.length)
\r
103 delimiterFound = 0;
\r
104 sawSpaceBefore = Character.isWhitespace(c);
\r
106 // Reached ICharacterScanner.EOF
\r
107 for (; readCount > 0; readCount--)
\r
109 return Token.UNDEFINED;
\r